From 5d64dbe6769448e0f33080e9ac957a70a0973a13 Mon Sep 17 00:00:00 2001 From: ppillot Date: Fri, 24 May 2024 15:37:19 -0400 Subject: [PATCH] 2.3.0 --- dist/declarations/buffer/arrow-buffer.d.ts | 12 ++++----- dist/declarations/buffer/buffer.d.ts | 20 +++++++------- .../buffer/doublesided-buffer.d.ts | 12 ++++----- dist/declarations/buffer/point-buffer.d.ts | 2 +- dist/declarations/buffer/tubemesh-buffer.d.ts | 24 ++--------------- .../datasource/pdbe-datasource.d.ts | 11 ++++++++ dist/declarations/ngl.d.ts | 2 +- dist/declarations/parser/cif-parser.d.ts | 4 ++- .../declarations/parser/structure-parser.d.ts | 2 ++ dist/declarations/shader/shader-utils.d.ts | 2 +- dist/declarations/stage/stage.d.ts | 13 +++++----- dist/declarations/store/atom-store.d.ts | 2 +- dist/declarations/store/chemcomp-map.d.ts | 26 +++++++++++++++++++ dist/declarations/structure/structure.d.ts | 5 +++- dist/declarations/surface/surface.d.ts | 4 +-- dist/declarations/surface/volume.d.ts | 4 +-- dist/declarations/viewer/viewer.d.ts | 8 +++--- dist/ngl.esm.js | 4 +-- dist/ngl.esm.js.map | 2 +- dist/ngl.js | 10 +++---- dist/ngl.js.map | 2 +- dist/ngl.umd.js | 4 +-- dist/ngl.umd.js.map | 2 +- package-lock.json | 4 +-- package.json | 2 +- 25 files changed, 104 insertions(+), 79 deletions(-) create mode 100644 dist/declarations/datasource/pdbe-datasource.d.ts create mode 100644 dist/declarations/store/chemcomp-map.d.ts diff --git a/dist/declarations/buffer/arrow-buffer.d.ts b/dist/declarations/buffer/arrow-buffer.d.ts index b6e1d14c7..5d63cfb93 100644 --- a/dist/declarations/buffer/arrow-buffer.d.ts +++ b/dist/declarations/buffer/arrow-buffer.d.ts @@ -92,9 +92,9 @@ declare class ArrowBuffer { cylinderRadius: Float32Array; geometry: GeometryGroup; picking?: Picker; - group: Group; - wireframeGroup: Group; - pickingGroup: Group; + group: Group; + wireframeGroup: Group; + pickingGroup: Group; visible: boolean; /** * @param {Object} data - buffer data @@ -113,9 +113,9 @@ declare class ArrowBuffer { cylinder: Partial; cone: Partial; }; - getMesh(): Group; - getWireframeMesh(): Group; - getPickingMesh(): Group; + getMesh(): Group; + getWireframeMesh(): Group; + getPickingMesh(): Group; setAttributes(data?: Partial): void; /** * Set buffer parameters diff --git a/dist/declarations/buffer/buffer.d.ts b/dist/declarations/buffer/buffer.d.ts index 0a562acd2..65b585689 100644 --- a/dist/declarations/buffer/buffer.d.ts +++ b/dist/declarations/buffer/buffer.d.ts @@ -4,7 +4,7 @@ * @private */ import { Vector3, Matrix4, BufferGeometry, Uniform, Group, LineSegments, Points, Mesh, ShaderMaterial } from 'three'; -import { GenericColor, NumberArray } from '../types'; +import { GenericColor, TypedArray } from '../types'; import { ShaderDefines } from '../shader/shader-utils'; import { Picker } from '../utils/picker'; export declare type BufferSide = 'front' | 'back' | 'double'; @@ -12,7 +12,7 @@ export declare type BufferTypes = 'picking' | 'background'; export declare type BufferMaterials = 'material' | 'wireframeMaterial' | 'pickingMaterial'; export interface _BufferAttribute { type: 'f' | 'v2' | 'v3' | 'c'; - value?: NumberArray; + value?: TypedArray; } export declare type Uniforms = { [k: string]: Uniform | { @@ -201,12 +201,12 @@ declare class Buffer { uniforms: Uniforms; pickingUniforms: Uniforms; private _positionDataSize; - geometry: BufferGeometry; + geometry: BufferGeometry; indexVersion: number; wireframeIndexVersion: number; - group: Group; - wireframeGroup: Group; - pickingGroup: Group; + group: Group; + wireframeGroup: Group; + pickingGroup: Group; vertexShader: string; fragmentShader: string; isImpostor: boolean; @@ -245,10 +245,10 @@ declare class Buffer { makeWireframeIndex(): void; updateWireframeIndex(): void; getRenderOrder(): number; - _getMesh(materialName: BufferMaterials): LineSegments | Points | Mesh; - getMesh(): LineSegments | Points | Mesh; - getWireframeMesh(): LineSegments; - getPickingMesh(): LineSegments | Points | Mesh; + _getMesh(materialName: BufferMaterials): LineSegments, ShaderMaterial> | Points, ShaderMaterial> | Mesh, ShaderMaterial, import("three").Object3DEventMap>; + getMesh(): LineSegments, ShaderMaterial> | Points, ShaderMaterial> | Mesh, ShaderMaterial, import("three").Object3DEventMap>; + getWireframeMesh(): LineSegments, ShaderMaterial>; + getPickingMesh(): LineSegments, ShaderMaterial> | Points, ShaderMaterial> | Mesh, ShaderMaterial, import("three").Object3DEventMap>; getShader(name: string, type?: BufferTypes): string; getVertexShader(type?: BufferTypes): string; getFragmentShader(type?: BufferTypes): string; diff --git a/dist/declarations/buffer/doublesided-buffer.d.ts b/dist/declarations/buffer/doublesided-buffer.d.ts index 9b62d02e8..32b206b46 100644 --- a/dist/declarations/buffer/doublesided-buffer.d.ts +++ b/dist/declarations/buffer/doublesided-buffer.d.ts @@ -28,9 +28,9 @@ declare class DoubleSidedBuffer { wireframe: boolean; geometry: BufferGeometry; picking?: Picker; - group: Group; - wireframeGroup: Group; - pickingGroup: Group; + group: Group; + wireframeGroup: Group; + pickingGroup: Group; frontMeshes: (Mesh | LineSegments)[]; backMeshes: (Mesh | LineSegments)[]; buffer: Buffer; @@ -71,9 +71,9 @@ declare class DoubleSidedBuffer { diffuse: import("../types").GenericColor; interiorColor: import("../types").GenericColor; }; - getMesh(picking: boolean): Group; - getWireframeMesh(): LineSegments; - getPickingMesh(): Group; + getMesh(picking: boolean): Group; + getWireframeMesh(): LineSegments, import("three").ShaderMaterial>; + getPickingMesh(): Group; setAttributes(data: any): void; setParameters(data: any): void; setVisibility(value: boolean): void; diff --git a/dist/declarations/buffer/point-buffer.d.ts b/dist/declarations/buffer/point-buffer.d.ts index d760961a2..c9ca120c8 100644 --- a/dist/declarations/buffer/point-buffer.d.ts +++ b/dist/declarations/buffer/point-buffer.d.ts @@ -66,7 +66,7 @@ declare class PointBuffer extends Buffer { }; sortParticles: {}; alphaTest: { - updateShader: boolean; + uniform: boolean; }; useTexture: { updateShader: boolean; diff --git a/dist/declarations/buffer/tubemesh-buffer.d.ts b/dist/declarations/buffer/tubemesh-buffer.d.ts index 48e8fb654..fb9f5ca6a 100644 --- a/dist/declarations/buffer/tubemesh-buffer.d.ts +++ b/dist/declarations/buffer/tubemesh-buffer.d.ts @@ -22,17 +22,7 @@ export declare const TubeMeshBufferDefaultParameters: { depthWrite: boolean; clipNear: number; clipRadius: number; - clipCenter: Vector3; /** - * @param {Object} data - attribute object - * @param {Float32Array} data.position - positions - * @param {Float32Array} data.normal - normals - * @param {Float32Array} data.binormal - binormals - * @param {Float32Array} data.tangent - tangents - * @param {Float32Array} data.color - colors - * @param {Float32Array} data.size - sizes - * @param {Picker} data.picking - picking ids - * @param {BufferParameters} params - parameter object - */ + clipCenter: Vector3; flatShaded: boolean; wireframe: boolean; roughness: number; @@ -68,17 +58,7 @@ declare class TubeMeshBuffer extends MeshBuffer { depthWrite: boolean; clipNear: number; clipRadius: number; - clipCenter: Vector3; /** - * @param {Object} data - attribute object - * @param {Float32Array} data.position - positions - * @param {Float32Array} data.normal - normals - * @param {Float32Array} data.binormal - binormals - * @param {Float32Array} data.tangent - tangents - * @param {Float32Array} data.color - colors - * @param {Float32Array} data.size - sizes - * @param {Picker} data.picking - picking ids - * @param {BufferParameters} params - parameter object - */ + clipCenter: Vector3; flatShaded: boolean; wireframe: boolean; roughness: number; diff --git a/dist/declarations/datasource/pdbe-datasource.d.ts b/dist/declarations/datasource/pdbe-datasource.d.ts new file mode 100644 index 000000000..128e797e5 --- /dev/null +++ b/dist/declarations/datasource/pdbe-datasource.d.ts @@ -0,0 +1,11 @@ +/** + * @file PDB Europe Datasource + * @author Paul Pillot + * @private + */ +import Datasource from './datasource'; +declare class PDBeDatasource extends Datasource { + getUrl(src: string): string; + getExt(src: string): string; +} +export default PDBeDatasource; diff --git a/dist/declarations/ngl.d.ts b/dist/declarations/ngl.d.ts index e798cf53b..28d1d3541 100644 --- a/dist/declarations/ngl.d.ts +++ b/dist/declarations/ngl.d.ts @@ -126,7 +126,6 @@ import './parser/mrc-parser'; import './parser/xplor-parser'; import './parser/kin-parser'; import './parser/obj-parser'; -import './parser/ply-parser'; import './parser/csv-parser'; import './parser/json-parser'; import './parser/msgpack-parser'; @@ -142,6 +141,7 @@ import MolecularSurface from './surface/molecular-surface'; import Volume from './surface/volume'; import './utils/gzip-decompressor'; import './datasource/rcsb-datasource'; +import './datasource/pdbe-datasource'; import './datasource/pubchem-datasource'; import './datasource/passthrough-datasource'; import './datasource/alphafold-datasource'; diff --git a/dist/declarations/parser/cif-parser.d.ts b/dist/declarations/parser/cif-parser.d.ts index ffcca96bd..ed4a58b5c 100644 --- a/dist/declarations/parser/cif-parser.d.ts +++ b/dist/declarations/parser/cif-parser.d.ts @@ -1,11 +1,13 @@ /** * @file Cif Parser * @author Alexander Rose + * @author Paul Pillot * @private */ import StructureParser from './structure-parser'; declare class CifParser extends StructureParser { get type(): string; - _parse(): void; + get isBinary(): boolean; + _parse(): Promise; } export default CifParser; diff --git a/dist/declarations/parser/structure-parser.d.ts b/dist/declarations/parser/structure-parser.d.ts index 4444484a7..af85cc42b 100644 --- a/dist/declarations/parser/structure-parser.d.ts +++ b/dist/declarations/parser/structure-parser.d.ts @@ -4,6 +4,7 @@ * @private */ import Parser, { ParserParameters } from './parser'; +import Structure from '../structure/structure'; import StructureBuilder from '../structure/structure-builder'; import Streamer from '../streamer/streamer'; export interface StructureParserParameters extends ParserParameters { @@ -12,6 +13,7 @@ export interface StructureParserParameters extends ParserParameters { cAlphaOnly: boolean; } declare class StructureParser extends Parser { + structure: Structure; structureBuilder: StructureBuilder; constructor(streamer: Streamer, params?: Partial); get type(): string; diff --git a/dist/declarations/shader/shader-utils.d.ts b/dist/declarations/shader/shader-utils.d.ts index 7756689a5..ab8785de4 100644 --- a/dist/declarations/shader/shader-utils.d.ts +++ b/dist/declarations/shader/shader-utils.d.ts @@ -12,7 +12,7 @@ import './chunk/opaque_back_fragment.glsl'; import './chunk/radiusclip_vertex.glsl'; import './chunk/radiusclip_fragment.glsl'; import './chunk/unpack_color.glsl'; -export declare type ShaderDefine = ('NEAR_CLIP' | 'RADIUS_CLIP' | 'PICKING' | 'NOLIGHT' | 'FLAT_SHADED' | 'OPAQUE_BACK' | 'DIFFUSE_INTERIOR' | 'USE_INTERIOR_COLOR' | 'USE_SIZEATTENUATION' | 'USE_MAP' | 'ALPHATEST' | 'SDF' | 'FIXED_SIZE' | 'CUBIC_INTERPOLATION' | 'BSPLINE_FILTER' | 'CATMULROM_FILTER' | 'MITCHELL_FILTER'); +export declare type ShaderDefine = ('NEAR_CLIP' | 'RADIUS_CLIP' | 'PICKING' | 'NOLIGHT' | 'FLAT_SHADED' | 'OPAQUE_BACK' | 'DIFFUSE_INTERIOR' | 'USE_INTERIOR_COLOR' | 'USE_SIZEATTENUATION' | 'USE_MAP' | 'USE_ALPHATEST' | 'SDF' | 'FIXED_SIZE' | 'CUBIC_INTERPOLATION' | 'BSPLINE_FILTER' | 'CATMULROM_FILTER' | 'MITCHELL_FILTER'); export declare type ShaderDefines = { [k in ShaderDefine]?: number | string; }; diff --git a/dist/declarations/stage/stage.d.ts b/dist/declarations/stage/stage.d.ts index 8eec33e5d..b4e7f9731 100644 --- a/dist/declarations/stage/stage.d.ts +++ b/dist/declarations/stage/stage.d.ts @@ -31,6 +31,7 @@ import Structure from '../structure/structure'; import Surface from '../surface/surface'; import Volume from '../surface/volume'; import Shape from '../geometry/shape'; +import { GenericColor } from '../types'; declare global { interface Document { mozFullScreen: boolean; @@ -90,7 +91,7 @@ export declare const StageDefaultParameters: { quality: RenderQualityType; workerDefault: boolean; sampleLevel: number; - backgroundColor: string | number; + backgroundColor: GenericColor; rotateSpeed: number; zoomSpeed: number; panSpeed: number; @@ -104,9 +105,9 @@ export declare const StageDefaultParameters: { cameraFov: number; cameraEyeSep: number; cameraType: "perspective" | "orthographic" | "stereo"; - lightColor: string | number; + lightColor: GenericColor; lightIntensity: number; - ambientColor: string | number; + ambientColor: GenericColor; ambientIntensity: number; hoverTimeout: number; tooltip: boolean; @@ -166,7 +167,7 @@ declare class Stage { quality: RenderQualityType; workerDefault: boolean; sampleLevel: number; - backgroundColor: string | number; + backgroundColor: GenericColor; rotateSpeed: number; zoomSpeed: number; panSpeed: number; @@ -180,9 +181,9 @@ declare class Stage { cameraFov: number; cameraEyeSep: number; cameraType: "perspective" | "orthographic" | "stereo"; - lightColor: string | number; + lightColor: GenericColor; lightIntensity: number; - ambientColor: string | number; + ambientColor: GenericColor; ambientIntensity: number; hoverTimeout: number; tooltip: boolean; diff --git a/dist/declarations/store/atom-store.d.ts b/dist/declarations/store/atom-store.d.ts index 8852efa1f..0445e8625 100644 --- a/dist/declarations/store/atom-store.d.ts +++ b/dist/declarations/store/atom-store.d.ts @@ -18,7 +18,7 @@ export default class AtomStore extends Store { altloc: Uint8Array; occupancy: Float32Array; partialCharge?: Float32Array; - formalCharge?: Uint8Array; + formalCharge?: Int8Array; get _defaultFields(): StoreField[]; setAltloc(i: number, str: string): void; getAltloc(i: number): string; diff --git a/dist/declarations/store/chemcomp-map.d.ts b/dist/declarations/store/chemcomp-map.d.ts new file mode 100644 index 000000000..056a68260 --- /dev/null +++ b/dist/declarations/store/chemcomp-map.d.ts @@ -0,0 +1,26 @@ +/** + * @file ChemComp Map + * @author Paul Pillot + * @private + */ +import Structure from "../structure/structure"; +import { ResidueBonds } from "../structure/structure-utils"; +interface ChemCompBonds { + atom1: string[]; + atom2: string[]; + bondOrders: number[]; +} +declare class ChemCompMap { + readonly structure: Structure; + dict: { + [resname: string]: { + chemCompType: string; + bonds?: ChemCompBonds; + }; + }; + constructor(structure: Structure); + add(resname: string, chemCompType: string, bonds?: ChemCompBonds): void; + addBond(resname: string, atom1: string, atom2: string, bondOrder: number): void; + getBonds(resname: string, atomList: number[]): ResidueBonds | undefined; +} +export default ChemCompMap; diff --git a/dist/declarations/structure/structure.d.ts b/dist/declarations/structure/structure.d.ts index d46cc4e86..55010ead8 100644 --- a/dist/declarations/structure/structure.d.ts +++ b/dist/declarations/structure/structure.d.ts @@ -5,6 +5,7 @@ */ import { Vector3, Box3 } from 'three'; import { Signal } from 'signals'; +import { CifBlock } from 'molstar/lib/mol-io/reader/cif'; import BitArray from '../utils/bitarray'; import PrincipalAxes from '../math/principal-axes'; import SpatialHash from '../geometry/spatial-hash'; @@ -31,6 +32,7 @@ import AtomProxy from '../proxy/atom-proxy'; import ResidueProxy from '../proxy/residue-proxy'; import ChainProxy from '../proxy/chain-proxy'; import ModelProxy from '../proxy/model-proxy'; +import ChemCompMap from '../store/chemcomp-map'; interface Structure { signals: StructureSignals; name: string; @@ -65,6 +67,7 @@ interface Structure { modelStore: ModelStore; atomMap: AtomMap; residueMap: ResidueMap; + chemCompMap?: ChemCompMap; bondHash?: BondHash; spatialHash?: SpatialHash; atomSet?: BitArray; @@ -91,7 +94,7 @@ export declare type StructureHeader = { experimentalMethods?: string[]; }; export declare type StructureExtraData = { - cif?: object; + cif?: CifBlock; sdf?: object[]; }; export declare type StructureSignals = { diff --git a/dist/declarations/surface/surface.d.ts b/dist/declarations/surface/surface.d.ts index 0500647f2..146a72687 100644 --- a/dist/declarations/surface/surface.d.ts +++ b/dist/declarations/surface/surface.d.ts @@ -3,7 +3,7 @@ * @author Alexander Rose * @private */ -import { Vector3, Box3, Geometry, BufferGeometry, Group } from 'three'; +import { Vector3, Box3, BufferGeometry, Group } from 'three'; import { AtomPicker, SurfacePicker } from '../utils/picker'; import { ColormakerParameters } from '../color/colormaker'; import { Structure, Volume } from '../ngl'; @@ -63,7 +63,7 @@ declare class Surface { * @return {undefined} */ set(position: Float32Array, index: Uint32Array | Uint16Array | undefined, normal: Float32Array | undefined, color: Float32Array | undefined, atomindex: Int32Array | undefined, contour?: boolean): void; - fromGeometry(geometry: Geometry | BufferGeometry | Group): void; + fromGeometry(geometry: BufferGeometry | Group): void; getPosition(): Float32Array; getColor(params: ColormakerParameters & { scheme: string; diff --git a/dist/declarations/surface/volume.d.ts b/dist/declarations/surface/volume.d.ts index f3fded8c3..043903a51 100644 --- a/dist/declarations/surface/volume.d.ts +++ b/dist/declarations/surface/volume.d.ts @@ -38,7 +38,7 @@ declare class Volume { data: Float32Array; worker: Worker; workerPool: WorkerPool; - _position: Float32Array; + _position: Float32Array | undefined; _min: number | undefined; _max: number | undefined; _mean: number | undefined; @@ -92,7 +92,7 @@ declare class Volume { */ setAtomindex(atomindex?: Int32Array): void; getBox(center: Vector3, size: number, target: Box3): Box3; - _getBox(center: Vector3 | undefined, size: number): number[][] | undefined; + _getBox(center: Vector3 | undefined, size: number): import("three").Vector3Tuple[] | undefined; _makeSurface(sd: any, isolevel: number, smooth: number): Surface; getSurface(isolevel: number, smooth: number, center: Vector3, size: number, contour: boolean, wrap?: boolean): Surface; getSurfaceWorker(isolevel: number, smooth: number, center: Vector3, size: number, contour: boolean, wrap: boolean, callback: (s: Surface) => void): void; diff --git a/dist/declarations/viewer/viewer.d.ts b/dist/declarations/viewer/viewer.d.ts index cb3127a51..2190caa95 100644 --- a/dist/declarations/viewer/viewer.d.ts +++ b/dist/declarations/viewer/viewer.d.ts @@ -4,7 +4,7 @@ * @private */ import { Signal } from 'signals'; -import { PerspectiveCamera, OrthographicCamera, Box3, Matrix4, Color, WebGLRenderer, WebGLRenderTarget, Scene, Group, TextureEncoding } from 'three'; +import { PerspectiveCamera, OrthographicCamera, Box3, Matrix4, Color, WebGLRenderer, WebGLRenderTarget, Scene, Group, ColorSpace } from 'three'; import '../shader/BasicLine.vert'; import '../shader/BasicLine.frag'; import '../shader/Quad.vert'; @@ -37,7 +37,7 @@ export interface ViewerParameters { ambientColor: Color; ambientIntensity: number; sampleLevel: number; - rendererEncoding: TextureEncoding; + outputColorSpace: ColorSpace; } export interface BufferInstance { matrix: Matrix4; @@ -68,7 +68,7 @@ export default class Viewer { width: number; height: number; scene: Scene; - private spotLight; + private directionalLight; private ambientLight; rotationGroup: Group; translationGroup: Group; @@ -133,7 +133,7 @@ export default class Viewer { * In all cases, the output is always sRGB; this just affects how colors are computed internally. * Call this just after creating the viewer, before loading any models. */ - setColorWorkflow(encoding: ColorWorkflow): void; + setColorWorkflow(colorspace: ColorSpace): void; setCamera(type: CameraType, fov?: number, eyeSep?: number): void; setClip(near: number, far: number, dist: number, clipMode?: string, clipScale?: string): void; setSize(width: number, height: number): void; diff --git a/dist/ngl.esm.js b/dist/ngl.esm.js index 324e391ae..070223c5a 100644 --- a/dist/ngl.esm.js +++ b/dist/ngl.esm.js @@ -1,4 +1,4 @@ -import{Vector2 as t,Vector3 as e,Matrix4 as i,Quaternion as r,Color as s,ShaderChunk as n,Points as o,Box3 as a,LinearEncoding as c,PerspectiveCamera as l,OrthographicCamera as h,StereoCamera as d,Scene as u,Group as m,Fog as p,SpotLight as f,AmbientLight as g,WebGLRenderer as y,WebGLRenderTarget as b,NearestFilter as x,RGBAFormat as v,UnsignedByteType as w,LinearFilter as A,Uniform as _,ShaderMaterial as S,AdditiveBlending as C,Mesh as P,PlaneGeometry as I,BufferGeometry as k,BufferAttribute as M,LineSegments as T,sRGBEncoding as B,FloatType as D,Geometry as $,Matrix3 as O,UniformsUtils as R,UniformsLib as E,NoBlending as F,FrontSide as L,BackSide as N,DoubleSide as z,IcosahedronBufferGeometry as V,DataTexture as G,NormalBlending as U,Euler as j,CanvasTexture as H,CylinderBufferGeometry as W,ConeBufferGeometry as q,BoxBufferGeometry as X,OctahedronBufferGeometry as Y,TetrahedronBufferGeometry as K,TorusBufferGeometry as Z,Face3 as Q}from"three";export{Box3,Color,Euler,Matrix3,Matrix4,Plane,Quaternion,Vector2,Vector3}from"three";import*as J from"chroma-js";import*as tt from"signals";import{Signal as et}from"signals";export{Signal}from"signals";import{sprintf as it}from"sprintf-js";function rt(t){if("undefined"==typeof window)return;const e=new RegExp(`${t}=([^&#=]*)`).exec(window.location.search);return e?decodeURIComponent(e[1]):void 0}function st(t,e){return void 0!==t?t:e}function nt(t,e){const i=Object.assign({},t);for(const r in e){void 0===t[r]&&(i[r]=e[r])}return i}function ot(t,e){for(const i in e){const r=e[i];void 0!==r&&(t[i]=r)}return t}function at(t,e){e=st(e,[]);for(let i=0;ie?(o&&(clearTimeout(o),o=null),a=l,n=t.apply(r,s),o||(r=s=null)):o||!1===i.trailing||(o=setTimeout(c,h)),n}}function mt(t,e){return te?1:0}function pt(t,e,i=mt){let r=0,s=t.length-1;for(;r<=s;){const n=r+s>>1,o=i(e,t[n]);if(o>0)r=n+1;else{if(!(o<0))return n;s=n-1}}return-r-1}function ft(t,e,i){const r=function(t,e){let i=t.length-1;if(t[i]>1;t[s]>=e?i=s-1:r=s+1}return i+1}(t,e),s=function(t,e){if(t[0]>e)return-1;let i=0,r=t.length-1;for(;i<=r;){const s=i+r>>1;t[s]>e?r=s-1:i=s+1}return i-1}(t,i);return-1===r||-1===s||r>s?0:s-r+1}function gt(t){return t.sort().filter((function(t,e,i){return 0===e||t!==i[e-1]}))}function yt(t){const e=28672;if(t.length>e){const i=[];for(let r=0;r65535?Uint32Array:Uint16Array)(t)}function vt(t){return t.buffer&&t.buffer instanceof ArrayBuffer?t.buffer:t}function wt(t,e){return void 0===t?t=new e:Array.isArray(t)&&(t=(new e).fromArray(t)),t}function At(t){return wt(t,e)}function _t(t){return wt(t,i)}function St(t){return wt(t,r)}function Ct(t){return e=t,i=Float32Array,e instanceof i?e:new i(e);var e,i}function Pt(t){return st(t,"").toString().toLowerCase()}class It{constructor(t){this.name=t,this._dict={}}add(t,e){this._dict[Pt(t)]=e}get(t){return this._dict[Pt(t)]}get names(){return Object.keys(this._dict)}}function kt(t){return.01745*t}const Mt="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),Tt=new Array(36);function Bt(){let t,e=0;for(let i=0;i<36;i++)8===i||13===i||18===i||23===i?Tt[i]="-":14===i?Tt[i]="4":(e<=2&&(e=33554432+16777216*Math.random()|0),t=15&e,e>>=4,Tt[i]=Mt[19===i?3&t|8:t]);return Tt.join("")}function Dt(t,e,i){return Math.max(e,Math.min(i,t))}function $t(t,e,i){return t+(e-t)*i}function Ot(t,e,i,r,s,n){const o=(i-t)*n,a=(r-e)*n,c=s*s;return(2*e-2*i+o+a)*(s*c)+(-3*e+3*i-2*o-a)*c+o*s+e}function Rt(t,e,i){var r;return r=function(t,e,i){return(t-e)/(i-e)}(i,t,e),(i=Dt(r,0,1))*i*(3-2*i)}var Et="sRGB";const Ft={scale:"uniform",mode:"hcl",domain:[0,1],value:16777215,reverse:!1},Lt=new s;function Nt(t,e,i){const r=i.value;return i.value=function(t,e){let i=r.bind(this,t,e)();return"linear"==Et?(Lt.set(i),Lt.convertSRGBToLinear(),Lt.getHex()):i},i}class zt{constructor(t={}){this.parameters=nt(t,Ft),"string"==typeof this.parameters.value&&(this.parameters.value=Lt.set(this.parameters.value).getHex()),this.parameters.structure&&(this.atomProxy=this.parameters.structure.getAtomProxy())}getScale(t={}){const e=nt(t,this.parameters);return"rainbow"===e.scale?e.scale=["red","orange","yellow","green","blue"]:"rwb"===e.scale&&(e.scale=["red","white","blue"]),e.reverse&&(e.domain=e.domain.slice().reverse()),J.scale(e.scale).mode(e.mode).domain(e.domain).out("num")}colorToArray(t,e=[],i=0){return e[i]=(t>>16&255)/255,e[i+1]=(t>>8&255)/255,e[i+2]=(255&t)/255,e}atomColorToArray(t,e,i){return this.colorToArray(this.atomColor?this.atomColor(t):0,e,i)}bondColor(t,e){return this.atomProxy&&this.atomColor?(this.atomProxy.index=e?t.atomIndex1:t.atomIndex2,this.atomColor(this.atomProxy)):0}bondColorToArray(t,e,i,r){return this.colorToArray(this.bondColor(t,e),i,r)}volumeColorToArray(t,e,i){return this.colorToArray(this.volumeColor?this.volumeColor(t):0,e,i)}positionColorToArray(t,e,i){return this.colorToArray(this.positionColor?this.positionColor(t):0,e,i)}}var Vt;!function(t){t[t.PROTEIN=1]="PROTEIN",t[t.NUCLEIC=2]="NUCLEIC",t[t.RNA=3]="RNA",t[t.DNA=4]="DNA",t[t.POLYMER=5]="POLYMER",t[t.WATER=6]="WATER",t[t.HELIX=7]="HELIX",t[t.SHEET=8]="SHEET",t[t.TURN=9]="TURN",t[t.BACKBONE=10]="BACKBONE",t[t.SIDECHAIN=11]="SIDECHAIN",t[t.ALL=12]="ALL",t[t.HETERO=13]="HETERO",t[t.ION=14]="ION",t[t.SACCHARIDE=15]="SACCHARIDE",t[t.SUGAR=15]="SUGAR",t[t.BONDED=16]="BONDED",t[t.RING=17]="RING",t[t.AROMATICRING=18]="AROMATICRING",t[t.METAL=19]="METAL",t[t.POLARH=20]="POLARH",t[t.NONE=21]="NONE"}(Vt||(Vt={}));const Gt=["*","","ALL"],Ut=["NONE"],jt=[Vt.BACKBONE,Vt.SIDECHAIN,Vt.BONDED,Vt.RING,Vt.AROMATICRING,Vt.METAL,Vt.POLARH],Ht=[Vt.POLYMER,Vt.WATER],Wt=["ALA","GLY","SER"],qt=["CYS","SER","THR"],Xt=["ALA","ILE","LEU","MET","PHE","PRO","TRP","VAL"],Yt=["PHE","TRP","TYR","HIS"],Kt=["ASN","GLN"],Zt=["ASP","GLU"],Qt=["ARG","HIS","LYS"],Jt=["ARG","ASP","GLU","HIS","LYS"],te=["ASN","ARG","ASP","CYS","GLY","GLN","GLU","HIS","LYS","SER","THR","TYR"],ee=["ALA","ILE","LEU","MET","PHE","PRO","TRP","VAL"],ie=["HIS","PHE","PRO","TRP","TYR"],re=["ALA","GLY","ILE","LEU","VAL"];function se(t,e){if(void 0===e.atomname&&void 0===e.element&&void 0===e.altloc&&void 0===e.atomindex&&void 0===e.keyword&&void 0===e.inscode&&void 0===e.resname&&void 0===e.sstruc&&void 0===e.resno&&void 0===e.chainname&&void 0===e.model)return-1;if(void 0!==e.keyword){if(e.keyword===Vt.BACKBONE&&!t.isBackbone())return!1;if(e.keyword===Vt.SIDECHAIN&&!t.isSidechain())return!1;if(e.keyword===Vt.BONDED&&!t.isBonded())return!1;if(e.keyword===Vt.RING&&!t.isRing())return!1;if(e.keyword===Vt.AROMATICRING&&!t.isAromatic())return!1;if(e.keyword===Vt.HETERO&&!t.isHetero())return!1;if(e.keyword===Vt.PROTEIN&&!t.isProtein())return!1;if(e.keyword===Vt.NUCLEIC&&!t.isNucleic())return!1;if(e.keyword===Vt.RNA&&!t.isRna())return!1;if(e.keyword===Vt.DNA&&!t.isDna())return!1;if(e.keyword===Vt.POLYMER&&!t.isPolymer())return!1;if(e.keyword===Vt.WATER&&!t.isWater())return!1;if(e.keyword===Vt.HELIX&&!t.isHelix())return!1;if(e.keyword===Vt.SHEET&&!t.isSheet())return!1;if(e.keyword===Vt.TURN&&!t.isTurn())return!1;if(e.keyword===Vt.ION&&!t.isIon())return!1;if(e.keyword===Vt.SACCHARIDE&&!t.isSaccharide())return!1;if(e.keyword===Vt.METAL&&!t.isMetal())return!1;if(e.keyword===Vt.POLARH&&!t.isPolarHydrogen())return!1}if(void 0!==e.atomname&&e.atomname!==t.atomname)return!1;if(void 0!==e.element&&e.element!==t.element)return!1;if(void 0!==e.altloc&&e.altloc!==t.altloc)return!1;if(void 0!==e.atomindex&&pt(e.atomindex,t.index)<0)return!1;if(void 0!==e.resname)if(Array.isArray(e.resname)){if(!e.resname.includes(t.resname))return!1}else if(e.resname!==t.resname)return!1;if(void 0!==e.sstruc&&e.sstruc!==t.sstruc)return!1;if(void 0!==e.resno)if(Array.isArray(e.resno)&&2===e.resno.length){if(e.resno[0]>t.resno||e.resno[1]t.resno||e.resno[1]0?t:null}function he(t,e=!1){let i=t;return e&&(i=le(t,(function(t){return void 0!==t.keyword&&!jt.includes(t.keyword)||(void 0!==t.model||(void 0!==t.chainname||(void 0!==t.resname||(void 0!==t.resno||void 0!==t.sstruc))))}))),ce(i,se)}function de(t,e=!1){let i=t;return e&&(i=le(t,(function(t){return!(void 0===t.keyword||!jt.includes(t.keyword))||(void 0!==t.model||(void 0!==t.chainname||(void 0!==t.atomname||(void 0!==t.element||void 0!==t.altloc))))}))),ce(i,ne)}function ue(t,e=!1){let i=t;return e&&(i=le(t,(function(t){return void 0!==t.keyword&&!Ht.includes(t.keyword)||(void 0!==t.resname||(void 0!==t.resno||(void 0!==t.atomname||(void 0!==t.element||(void 0!==t.altloc||(void 0!==t.sstruc||void 0!==t.inscode))))))}))),ce(i,oe)}function me(t,e=!1){let i=t;return e&&(i=le(t,(function(t){return void 0!==t.keyword||(void 0!==t.chainname||(void 0!==t.resname||(void 0!==t.resno||(void 0!==t.atomname||(void 0!==t.element||(void 0!==t.altloc||(void 0!==t.sstruc||void 0!==t.inscode)))))))}))),ce(i,ae)}class pe{constructor(t){this.signals={stringChanged:new et},this.setString(t)}get type(){return"selection"}setString(t,e){if(void 0===t&&(t=this.string||""),t===this.string)return;try{this.selection=function(t){let e={operator:void 0,rules:[]};if(!t)return e;let i,r,s=e;const n=[];"("===(t=t.replace(/\(/g," ( ").replace(/\)/g," ) ").trim()).charAt(0)&&")"===t.substr(-1)&&(t=t.slice(1,-1).trim());const o=t.split(/\s+/),a=t=>{i={operator:t,rules:[]},void 0===s?(s=i,e=i):(s.rules.push(i),n.push(s),s=i)},c=function(t){r=s,s=n.pop(),void 0===s&&(a(t),l(r))},l=function(t){s.rules.push(t)};let h=!1;for(let t=0;t0)if("NOT"===i)h=1;else if(1===h)h=2;else{if(2!==h)throw new Error("something went wrong with 'not'");h=!1,c()}if("AND"===i){if("OR"===s.operator){const t=s.rules.pop();a("AND"),l(t)}else s.operator="AND";continue}if("OR"===i){"AND"===s.operator?c("OR"):s.operator="OR";continue}if("NOT"===e.toUpperCase()){h=1,a(),s.negate=!0;continue}if(+i!=+i){const t=Vt[i];if(void 0!==t){l({keyword:t});continue}}if("HYDROGEN"===i){l({operator:"OR",rules:[{element:"H"},{element:"D"}]});continue}if("SMALL"===i){l({resname:Wt});continue}if("NUCLEOPHILIC"===i){l({resname:qt});continue}if("HYDROPHOBIC"===i){l({resname:Xt});continue}if("AROMATIC"===i){l({resname:Yt});continue}if("AMIDE"===i){l({resname:Kt});continue}if("ACIDIC"===i){l({resname:Zt});continue}if("BASIC"===i){l({resname:Qt});continue}if("CHARGED"===i){l({resname:Jt});continue}if("POLAR"===i){l({resname:te});continue}if("NONPOLAR"===i){l({resname:ee});continue}if("CYCLIC"===i){l({resname:ie});continue}if("ALIPHATIC"===i){l({resname:re});continue}if("SIDECHAINATTACHED"===i){l({operator:"OR",rules:[{keyword:Vt.SIDECHAIN},{operator:"AND",negate:!1,rules:[{keyword:Vt.PROTEIN},{operator:"OR",negate:!1,rules:[{atomname:"CA"},{atomname:"BB"}]}]},{operator:"AND",negate:!1,rules:[{resname:"PRO"},{atomname:"N"}]},{operator:"AND",negate:!1,rules:[{keyword:Vt.NUCLEIC},{operator:"OR",negate:!0,rules:[{atomname:"P"},{atomname:"OP1"},{atomname:"OP2"},{atomname:"O3'"},{atomname:"O3*"},{atomname:"HO3'"},{atomname:"O5'"},{atomname:"O5*"},{atomname:"HO5'"},{atomname:"C5'"},{atomname:"C5*"},{atomname:"H5'"},{atomname:"H5''"}]}]}]});continue}if("APOLARH"===i){l({operator:"AND",negate:!1,rules:[{element:"H"},{negate:!0,operator:void 0,rules:[{keyword:Vt.POLARH}]}]});continue}if("LIGAND"===i){l({operator:"AND",rules:[{operator:"OR",rules:[{operator:"AND",rules:[{keyword:Vt.HETERO},{negate:!0,operator:void 0,rules:[{keyword:Vt.POLYMER}]}]},{negate:!0,operator:void 0,rules:[{keyword:Vt.POLYMER}]}]},{negate:!0,operator:void 0,rules:[{operator:"OR",rules:[{keyword:Vt.WATER},{keyword:Vt.ION}]}]}]});continue}if(-1!==Gt.indexOf(i)){l({keyword:Vt.ALL});continue}if("@"===e.charAt(0)){const t=e.substr(1).split(",").map((t=>parseInt(t)));t.sort((function(t,e){return t-e})),l({atomindex:t});continue}if("#"===e.charAt(0)){console.error("# for element selection deprecated, use _"),l({element:i.substr(1)});continue}if("_"===e.charAt(0)){l({element:i.substr(1)});continue}if("["===e[0]&&"]"===e[e.length-1]){const t=i.substr(1,e.length-2).split(","),r=t.length>1?t:t[0];l({resname:r});continue}if(e.length>=1&&e.length<=4&&"^"!==e[0]&&":"!==e[0]&&"."!==e[0]&&"%"!==e[0]&&"/"!==e[0]&&isNaN(parseInt(e))){l({resname:i});continue}const r={operator:"AND",rules:[]},n=e.split("/");if(n.length>1&&n[1]){if(isNaN(parseInt(n[1])))throw new Error("model must be an integer");r.rules.push({model:parseInt(n[1])})}const d=n[0].split("%");d.length>1&&r.rules.push({altloc:d[1]});const u=d[0].split(".");if(u.length>1&&u[1]){if(u[1].length>4)throw new Error("atomname must be one to four characters");r.rules.push({atomname:u[1].substring(0,4).toUpperCase()})}const m=u[0].split(":");m.length>1&&m[1]&&r.rules.push({chainname:m[1]});const p=m[0].split("^");if(p.length>1&&r.rules.push({inscode:p[1]}),p[0]){let t,e;"-"===p[0][0]&&(p[0]=p[0].substr(1),t=!0),p[0].includes("--")&&(p[0]=p[0].replace("--","-"),e=!0);let i=p[0].split("-");if(1===i.length){let e=parseInt(i[0]);if(isNaN(e))throw new Error("resi must be an integer");t&&(e*=-1),r.rules.push({resno:e})}else{if(2!==i.length)throw new Error("resi range must contain one '-'");{const s=i.map((t=>parseInt(t)));t&&(s[0]*=-1),e&&(s[1]*=-1),r.rules.push({resno:[s[0],s[1]]})}}}if(1===r.rules.length)l(r.rules[0]);else{if(!(r.rules.length>1))throw new Error("empty selection chunk");l(r)}}return void 0===e.operator&&1===e.rules.length&&e.rules[0].hasOwnProperty("operator")&&(e=e.rules[0]),e}(t)}catch(t){this.selection={error:t.message}}const i=this.selection;this.string=t,this.test=he(i),this.residueTest=de(i),this.chainTest=ue(i),this.modelTest=me(i),this.atomOnlyTest=he(i,!0),this.residueOnlyTest=de(i,!0),this.chainOnlyTest=ue(i,!0),this.modelOnlyTest=me(i,!0),e||this.signals.stringChanged.dispatch(this.string)}isAllSelection(){return Gt.includes(this.string.toUpperCase())}isNoneSelection(){return Ut.includes(this.string.toUpperCase())}}class fe extends zt{constructor(t){super(t),this.colormakerList=[],this.selectionList=[];(t.dataList||[]).forEach((t=>{const[e,i,r={}]=t;Fe.hasScheme(e)?Object.assign(r,{scheme:e,structure:this.parameters.structure}):Object.assign(r,{scheme:"uniform",value:new s(e).getHex()}),this.colormakerList.push(Fe.getScheme(r)),this.selectionList.push(new pe(i))}))}atomColor(t){for(let e=0,i=this.selectionList.length;e{}),t)}catch(t){}const Se="undefined"!=typeof window&&void 0!==window.orientation;let Ce=!1;function Pe(t){Ce=t}let Ie=!1;function ke(t){Ie=t}const Me={log:Function.prototype.bind.call(console.log,console),info:Function.prototype.bind.call(console.info,console),warn:Function.prototype.bind.call(console.warn,console),error:Function.prototype.bind.call(console.error,console),time:Function.prototype.bind.call(console.time,console),timeEnd:Function.prototype.bind.call(console.timeEnd,console)};let Te={color:"green",labelColor:8421504,labelAttachment:"bottom-center",labelSize:.7,labelZOffset:.5,labelYOffset:.1,labelBorder:!0,labelBorderColor:13882323,labelBorderWidth:.25,lineOpacity:.8,linewidth:5,opacity:.6,labelUnit:"angstrom",arcVisible:!0,planeVisible:!1};function Be(t={}){Object.assign(Te,t)}let De=!!($e=rt("debug"))&&("string"!=typeof $e||/^1|true|t|yes|y$/i.test($e));var $e;function Oe(t){De=t}const Re=["ngl","js"],Ee=new class{constructor(){this.activeWorkerCount=0,this._funcDict={},this._depsDict={},this._blobDict={}}add(t,e,i){this._funcDict[t]=e,this._depsDict[t]=i}get(t){return this._blobDict[t]||(this._blobDict[t]=we(this._funcDict[t],this._depsDict[t])),this._blobDict[t]}},Fe=new class{constructor(){this.schemes={},this.userSchemes={}}getScheme(t){const e=((t||{}).scheme||"").toLowerCase();let i;return i=e in this.schemes?this.schemes[e]:e in this.userSchemes?this.userSchemes[e]:zt,new i(t)}getSchemes(){const t={};return Object.keys(this.schemes).forEach((function(e){t[e]=e})),Object.keys(this.userSchemes).forEach((function(e){t[e]=e.split("|")[1]})),t}getScales(){return ge}getModes(){return ye}add(t,e){t=t.toLowerCase(),this.schemes[t]=e}addScheme(t,e){return function(t){return t instanceof zt}(t)||(t=this._createScheme(t)),this._addUserScheme(t,e)}_addUserScheme(t,e){e=e||"";const i=`${Bt()}|${e}`.toLowerCase();return this.userSchemes[i]=t,i}removeScheme(t){t=t.toLowerCase(),delete this.userSchemes[t]}_createScheme(t){return class extends zt{constructor(e){super(e),t.call(this,e)}}}addSelectionScheme(t,e){return this._addUserScheme(class extends fe{constructor(e){super(Object.assign({dataList:t},e))}},e)}hasScheme(t){return(t=t.toLowerCase())in this.schemes||t in this.userSchemes}},Le=new It("datasource"),Ne=new It("representatation"),ze=new class extends It{constructor(){super("parser")}__hasObjName(t,e){const i=this.get(t);return i&&i.prototype.__objName===e}isTrajectory(t){return this.__hasObjName(t,"frames")}isStructure(t){return this.__hasObjName(t,"structure")}isVolume(t){return this.__hasObjName(t,"volume")}isSurface(t){return this.__hasObjName(t,"surface")}isBinary(t){const e=this.get(t);return e&&e.prototype.isBinary}isXml(t){const e=this.get(t);return e&&e.prototype.isXml}isJson(t){const e=this.get(t);return e&&e.prototype.isJson}getTrajectoryExtensions(){return this.names.filter((t=>this.isTrajectory(t)))}getStructureExtensions(){return this.names.filter((t=>this.isStructure(t)))}getVolumeExtensions(){return this.names.filter((t=>this.isVolume(t)))}getSurfaceExtensions(){return this.names.filter((t=>this.isSurface(t)))}},Ve=new It("shader"),Ge=new It("decompressor"),Ue=new It("component"),je=new It("buffer"),He=new It("picker");let We,qe;function Xe(t){We=t}function Ye(t){qe=t}class Ke{constructor(t,e={}){this.chunkSize=10485760,this.newline="\n",this.__pointer=0,this.__partialLine="",this.compressed=st(e.compressed,!1),this.binary=st(e.binary,!1),this.json=st(e.json,!1),this.xml=st(e.xml,!1),this.src=t}isBinary(){return this.binary||this.compressed}read(){return this._read().then((t=>{const e=this.compressed?Ge.get(this.compressed):void 0;return this.compressed&&e?this.data=e(t):((this.binary||this.compressed)&&t instanceof ArrayBuffer&&(t=new Uint8Array(t)),this.data=t),this.data}))}_chunk(t,e){return e=Math.min(this.data.length,e),0===t&&this.data.length===e?this.data:this.isBinary()?this.data.subarray(t,e):this.data.substring(t,e)}chunk(t){const e=t+this.chunkSize;return this._chunk(t,e)}peekLines(t){const e=this.data,i=e.length,r=this.isBinary()?this.newline.charCodeAt(0):this.newline;let s,n=0;for(s=0;si).lines}chunkCount(){return Math.floor(this.data.length/this.chunkSize)+1}asText(){return this.isBinary()?yt(this.data):this.data}chunkToLines(t,e,i){const r=this.newline;if(!this.isBinary()&&t.length===this.data.length)return{lines:t.split(r),partialLine:""};let s=[];const n=this.isBinary()?yt(t):t,o=n.lastIndexOf(r);if(-1===o)e+=n;else{const t=e+n.substr(0,o);s=s.concat(t.split(r)),e=o===n.length-r.length?"":n.substr(o+r.length)}return i&&""!==e&&s.push(e),{lines:s,partialLine:e}}nextChunk(){const t=this.__pointer;if(!(t>this.data.length))return this.__pointer+=this.chunkSize,this.chunk(t)}nextChunkOfLines(){const t=this.nextChunk();if(void 0===t)return;const e=this.__pointer>this.data.length,i=this.chunkToLines(t,this.__partialLine,e);return this.__partialLine=i.partialLine,i.lines}eachChunk(t){const e=this.chunkSize,i=this.data.length,r=this.chunkCount();for(let s=0;s{const s=i===r+1,n=this.chunkToLines(e,this.__partialLine,s);this.__partialLine=n.partialLine,t(n.lines,i,r)}))}dispose(){delete this.src}}class Ze extends Ke{_read(){return new Promise(((t,e)=>{const i=this.src,r=new FileReader;r.onload=e=>{e.target&&t(e.target.result)},r.onerror=t=>e(t),this.binary||this.compressed?r.readAsArrayBuffer(i):r.readAsText(i)}))}}class Qe extends Ke{_read(){return new Promise(((t,e)=>{const i=this.src,r=new XMLHttpRequest;r.open("GET",i,!0),r.addEventListener("load",(()=>{if(200===r.status||304===r.status||0===r.status)try{t(r.response)}catch(t){e(t)}else e(r.statusText)}),!1),r.addEventListener("error",(t=>e("network error")),!1),this.isBinary()?r.responseType="arraybuffer":this.json?r.responseType="json":this.xml?r.responseType="document":r.responseType="text",r.send()}))}}class Je{constructor(t,e={}){this.parameters=nt(e,{ext:"",compressed:!1,binary:ze.isBinary(e.ext||""),name:"",dir:"",path:"",protocol:""});const i={compressed:this.parameters.compressed,binary:this.parameters.binary,json:ze.isJson(this.parameters.ext),xml:ze.isXml(this.parameters.ext)};"undefined"!=typeof File&&t instanceof File||"undefined"!=typeof Blob&&t instanceof Blob?this.streamer=new Ze(t,i):this.streamer=new Qe(t,i)}}class ti extends Je{constructor(t,e={}){super(t,e),this.parserParams={voxelSize:e.voxelSize,firstModelOnly:e.firstModelOnly,asTrajectory:e.asTrajectory,cAlphaOnly:e.cAlphaOnly,delimiter:e.delimiter,comment:e.comment,columnNames:e.columnNames,inferBonds:e.inferBonds,name:this.parameters.name,path:this.parameters.path}}load(){return new(ze.get(this.parameters.ext))(this.streamer,this.parserParams).parse()}}class ei{constructor(t,e,i){this.name=e,this.path=i,this.signals={elementAdded:new et,elementRemoved:new et,nameChanged:new et},this.type="Script",this.dir=i.substring(0,i.lastIndexOf("/")+1);try{this.fn=new Function("stage","__name","__path","__dir",t)}catch(t){Me.error("Script compilation failed",t),this.fn=function(){}}}run(t){return new Promise(((e,i)=>{try{this.fn.apply(null,[t,this.name,this.path,this.dir]),e()}catch(t){Me.error("Script.fn",t),i(t)}}))}}class ii extends Je{load(){return this.streamer.read().then((()=>new ei(this.streamer.asText(),this.parameters.name,this.parameters.path)))}}function ri(t){const e=Ge.names;let i,r,s="";i=t instanceof File?t.name:t instanceof Blob?"":t;const n=i.lastIndexOf("?"),o=-1!==n?i.substring(n):"";i=i.substring(0,-1===n?i.length:n);const a=i.replace(/^.*[\\/]/,"");let c=a.substring(0,a.lastIndexOf("."));const l=a.split(".");let h=l.length>1?(l.pop()||"").toLowerCase():"";const d=i.match(/^(.+):\/\/(.+)$/);d&&(s=d[1].toLowerCase(),i=d[2]||"");const u=i.substring(0,i.lastIndexOf("/")+1);if(e.includes(h)){r=h;const t=i.length-h.length-1;h=(i.substr(0,t).split(".").pop()||"").toLowerCase();const e=c.length-h.length-1;c=c.substr(0,e)}else r=!1;return{path:i,name:a,ext:h,base:c,dir:u,compressed:r,protocol:s,query:o,src:t}}function si(t){let e=ri(t);const i=Le.get(e.protocol);return i&&(e=ri(i.getUrl(e.src)),!e.ext&&i.getExt&&(e.ext=i.getExt(t))),e}function ni(t,e={}){const i=Object.assign(si(t),e);let r;return ze.names.includes(i.ext)?r=new ti(i.src,i):Re.includes(i.ext)&&(r=new ii(i.src,i)),r?r.load():Promise.reject(new Error(`autoLoad: ext '${i.ext}' unknown`))}class oi{getBlob(){return new Blob([this.getData()],{type:this.mimeType})}download(t,e){t=st(t,this.defaultName),e=st(e,this.defaultExt),dt(this.getBlob(),`${t}.${e}`)}}class ai extends oi{constructor(t,e){super(),this.mimeType="text/plain",this.defaultName="structure",this.defaultExt="pdb";const i=Object.assign({},e);this.renumberSerial=st(i.renumberSerial,!0),this.remarks=function(t){return Array.isArray(t)?t:[t]}(st(i.remarks,[])),this.structure=t,this._records=[]}_writeRecords(){this._records.length=0,this._writeTitle(),this._writeRemarks(),this._writeAtoms()}_writeTitle(){this._records.push(it("TITLE %-74s",this.structure.name))}_writeRemarks(){this.remarks.forEach((t=>{this._records.push(it("REMARK %-73s",t))})),this.structure.trajectory&&(this._records.push(it("REMARK %-73s","Trajectory '"+this.structure.trajectory.name+"'")),this._records.push(it("REMARK %-73s",`Frame ${this.structure.trajectory.frame}`)))}_writeAtoms(){let t=1,e=1,i=" ",r=" ";const s=this.structure.modelStore.count>1;this.structure.eachModel((n=>{s&&this._records.push(it("MODEL %4d%-66s",e++,"")),n.eachAtom((e=>{const s=e.hetero?"HETATM%5d %-4s %3s %1s%4d %8.3f%8.3f%8.3f%6.2f%6.2f %4s%2s%1s%1s":"ATOM %5d %-4s %3s %1s%4d %8.3f%8.3f%8.3f%6.2f%6.2f %4s%2s%1s%1s",n=this.renumberSerial?t:e.serial;let o=e.atomname;(1===o.length||o.length<4&&1===e.element.length&&o[0]===e.element)&&(o=" "+o),e.formalCharge?(i=Math.abs(e.formalCharge).toPrecision(1),r=e.formalCharge>0?"+":"-"):(i=" ",r=" "),this._records.push(it(s,n,o,e.resname,st(e.chainname," "),e.resno,e.x,e.y,e.z,st(e.occupancy,1),st(e.bfactor,0),"",st(e.element,""),i,r)),t+=1}),this.structure.getSelection()),s&&this._records.push(it("%-80s","ENDMDL"))})),this._records.push(it("%-80s","END"))}getString(){return console.warn("PdbWriter.getString() is deprecated, use .getData instead"),this.getData()}getData(){return this._writeRecords(),this._records.join("\n")}}class ci extends oi{constructor(t){super(),this.mimeType="text/plain",this.defaultName="structure",this.defaultExt="sdf",this.structure=t,this._records=[]}get idString(){return this.structure.id}get titleString(){return" "+this.structure.title}get countsString(){return it("%3i%3i 0 0 0 0 0 0 0 0999 V2000",this.structure.atomCount,this.structure.bondCount)}get chargeLines(){const t=[];this.structure.eachAtom((e=>{null!=e.formalCharge&&0!==e.formalCharge&&t.push([e.index,e.formalCharge])}));const e=[];for(let i=0;i{this._records.push(this.formatAtom(t))})),this.structure.eachBond((t=>{this._records.push(this.formatBond(t))})),this.chargeLines.forEach((t=>{this._records.push(t)})),this._records.push("M END")}_writeFooter(){this._records.push("$$$$")}getData(){return this._writeRecords(),this._records.join("\n")}}const li=[];class hi{constructor(t,e={}){this._mark=0,this._marks=[],this.offset=0,this.littleEndian=!0;let i=!1;void 0===t&&(t=8192),"number"==typeof t?t=new ArrayBuffer(t):i=!0;const r=e.offset?e.offset>>>0:0;let s=t.byteLength-r,n=r;t instanceof ArrayBuffer||(t.byteLength!==t.buffer.byteLength&&(n=t.byteOffset+r),t=t.buffer),this._lastWrittenByte=i?s:0,this.buffer=t,this.length=s,this.byteLength=s,this.byteOffset=n,this._data=new DataView(this.buffer,n,s)}available(t){return void 0===t&&(t=1),this.offset+t<=this.length}isLittleEndian(){return this.littleEndian}setLittleEndian(){return this.littleEndian=!0,this}isBigEndian(){return!this.littleEndian}setBigEndian(){return this.littleEndian=!1,this}skip(t){return void 0===t&&(t=1),this.offset+=t,this}seek(t){return this.offset=t,this}mark(){return this._mark=this.offset,this}reset(){return this.offset=this._mark,this}pushMark(){return this._marks.push(this.offset),this}popMark(){const t=this._marks.pop();if(void 0===t)throw new Error("Mark stack empty");return this.seek(t),this}rewind(){return this.offset=0,this}ensureAvailable(t){if(void 0===t&&(t=1),!this.available(t)){const e=2*(this.offset+t),i=new Uint8Array(e);i.set(new Uint8Array(this.buffer)),this.buffer=i.buffer,this.length=this.byteLength=e,this._data=new DataView(this.buffer)}return this}readBoolean(){return 0!==this.readUint8()}readInt8(){return this._data.getInt8(this.offset++)}readUint8(){return this._data.getUint8(this.offset++)}readByte(){return this.readUint8()}readBytes(t){void 0===t&&(t=1);for(var e=new Uint8Array(t),i=0;ithis._lastWrittenByte&&(this._lastWrittenByte=this.offset)}}class di extends oi{constructor(t){super(),this.mimeType="application/vnd.ms-pki.stl",this.defaultName="surface",this.defaultExt="stl",this.surface=t}getData(){const t=this.surface.index.length/3,i=new hi(2*t+3*t*4*4+80+4);i.skip(80),i.writeUint32(t);const r=new e,s=new e,n=new e,o=new e;for(let e=0;e{0===this.count&&(this.signals.countChanged.remove(i,this),t.call(e))};this.signals.countChanged.add(i,this)}}dispose(){this.clear(),this.signals.countChanged.dispose()}}Ve.add("shader/BasicLine.vert","void main(){\n#include begin_vertex\n#include project_vertex\n}"),Ve.add("shader/BasicLine.frag","uniform vec3 uColor;\n#include common\n#include fog_pars_fragment\nvoid main(){\ngl_FragColor = vec4( uColor, 1.0 );\n#include premultiplied_alpha_fragment\n#include tonemapping_fragment\n#include encodings_fragment\n#include fog_fragment\n}"),Ve.add("shader/Quad.vert","varying vec2 vUv;\nvoid main() {\nvUv = uv;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}"),Ve.add("shader/Quad.frag","varying vec2 vUv;\nuniform sampler2D tForeground;\nuniform float scale;\nvoid main() {\nvec4 foreground = texture2D( tForeground, vUv );\ngl_FragColor = foreground * scale;\n}");class mi{constructor(){this.signals={updated:new tt.Signal},this.maxDuration=-1/0,this.minDuration=1/0,this.avgDuration=14,this.lastDuration=1/0,this.prevFpsTime=0,this.lastFps=1/0,this.lastFrames=1,this.frames=0,this.count=0,this.begin()}update(){this.startTime=this.end(),this.currentTime=this.startTime,this.signals.updated.dispatch()}begin(){this.startTime=window.performance.now(),this.lastFrames=this.frames}end(){const t=window.performance.now();return this.count+=1,this.frames+=1,this.lastDuration=t-this.startTime,this.minDuration=Math.min(this.minDuration,this.lastDuration),this.maxDuration=Math.max(this.maxDuration,this.lastDuration),this.avgDuration-=this.avgDuration/30,this.avgDuration+=this.lastDuration/30,t>this.prevFpsTime+1e3&&(this.lastFps=this.frames,this.prevFpsTime=t,this.frames=0),t}}Ve.add("shader/chunk/fog_fragment.glsl","#ifdef USE_FOG\nfloat depth = length( vViewPosition );\n#ifdef FOG_EXP2\nfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );\n#else\nfloat fogFactor = smoothstep( fogNear, fogFar, depth );\n#endif\ngl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif"),Ve.add("shader/chunk/interior_fragment.glsl","if( gl_FrontFacing == false ){\n#ifdef USE_INTERIOR_COLOR\noutgoingLight.xyz = interiorColor;\n#else\n#ifdef DIFFUSE_INTERIOR\noutgoingLight.xyz = vColor;\n#endif\n#endif\noutgoingLight.xyz *= 1.0 - interiorDarkening;\n}"),Ve.add("shader/chunk/matrix_scale.glsl","float matrixScale( in mat4 m ){\nvec4 r = m[ 0 ];\nreturn sqrt( r[ 0 ] * r[ 0 ] + r[ 1 ] * r[ 1 ] + r[ 2 ] * r[ 2 ] );\n}"),Ve.add("shader/chunk/nearclip_vertex.glsl","#ifdef NEAR_CLIP\nif( vViewPosition.z < clipNear - 5.0 )\ngl_Position.z = 2.0 * gl_Position.w;\n#endif"),Ve.add("shader/chunk/nearclip_fragment.glsl","#ifdef NEAR_CLIP\nif( vViewPosition.z < clipNear )\ndiscard;\n#endif"),Ve.add("shader/chunk/opaque_back_fragment.glsl","#ifdef OPAQUE_BACK\n#ifdef FLIP_SIDED\nif( gl_FrontFacing == true ){\ngl_FragColor.a = 1.0;\n}\n#else\nif( gl_FrontFacing == false ){\ngl_FragColor.a = 1.0;\n}\n#endif\n#endif"),Ve.add("shader/chunk/radiusclip_vertex.glsl","#ifdef RADIUS_CLIP\nif( distance( vViewPosition, vClipCenter ) > clipRadius + 5.0 )\ngl_Position.z = 2.0 * gl_Position.w;\n#endif"),Ve.add("shader/chunk/radiusclip_fragment.glsl","#ifdef RADIUS_CLIP\nif( distance( vViewPosition, vClipCenter ) > clipRadius )\ndiscard;\n#endif"),Ve.add("shader/chunk/unpack_color.glsl","vec3 unpackColor(float f) {\nvec3 color;\ncolor.r = floor(f / 256.0 / 256.0);\ncolor.g = floor((f - color.r * 256.0 * 256.0) / 256.0);\ncolor.b = floor(f - color.r * 256.0 * 256.0 - color.g * 256.0);\nreturn color / 255.0;\n}");const pi=/^(?!\/\/)\s*#include\s+(\S+)/gim,fi={};function gi(t,e={}){let i=t+"|";for(const t in e)i+=t+":"+e[t];if(!fi[i]){const r=function(t){if(void 0===t)return"";const e=[];for(const i in t){const r=t[i];r&&e.push(`#define ${i} ${r}`)}return e.join("\n")+"\n"}(e);let s=Ve.get(`shader/${t}`);if(!s)throw new Error(`empty shader, '${t}'`);s=s.replace(pi,(function(t,e){const i=`shader/chunk/${e}.glsl`,r=Ve.get(i)||n[e];if(!r)throw new Error(`empty chunk, '${e}'`);return r})),fi[i]=r+s}return fi[i]}if("undefined"!=typeof WebGLRenderingContext){const t=WebGLRenderingContext.prototype,e=t.getShaderParameter;t.getShaderParameter=function(){return!De||e.apply(this,arguments)};const i=t.getShaderInfoLog;t.getShaderInfoLog=function(){return De?i.apply(this,arguments):""};const r=t.getProgramParameter;t.getProgramParameter=function(e,i){return!De&&i===t.LINK_STATUS||r.apply(this,arguments)};const s=t.getProgramInfoLog;t.getProgramInfoLog=function(){return De?s.apply(this,arguments):""}}const yi=[[[0,0]],[[4,4],[-4,-4]],[[-2,-6],[6,-2],[-6,2],[2,6]],[[1,-3],[-1,3],[5,1],[-3,-5],[-5,5],[-7,-1],[3,7],[7,-7]],[[1,1],[-1,-3],[-3,2],[4,-1],[-5,-2],[2,5],[5,3],[3,-5],[-2,6],[0,-7],[-4,-6],[-6,4],[-8,0],[7,-4],[6,7],[-7,-8]],[[-4,-7],[-7,-5],[-3,-5],[-5,-4],[-1,-4],[-2,-2],[-6,-1],[-4,0],[-7,1],[-1,2],[-6,3],[-3,3],[-7,6],[-3,6],[-5,7],[-1,7],[5,-7],[1,-6],[6,-5],[4,-4],[2,-3],[7,-2],[1,-1],[4,-1],[2,1],[6,2],[0,4],[4,4],[2,5],[7,5],[5,6],[3,7]]];yi.forEach((t=>{t.forEach((t=>{t[0]*=.0625,t[1]*=.0625}))}));class bi{constructor(t,e,i,r){this.canvas=document.createElement("canvas"),this._viewer=i,this._factor=st(r.factor,2),this._antialias=st(r.antialias,!1),this._onProgress=r.onProgress,this._onFinish=r.onFinish,this._antialias&&(this._factor*=2),this._n=this._factor*this._factor,this._width=this._viewer.width,this._height=this._viewer.height,this._antialias?(this.canvas.width=this._width*this._factor/2,this.canvas.height=this._height*this._factor/2):(this.canvas.width=this._width*this._factor,this.canvas.height=this._height*this._factor),this._ctx=this.canvas.getContext("2d"),this._viewerSampleLevel=i.sampleLevel,this._viewer.setSampling(-1)}_renderTile(t){const e=this._viewer,i=this._width,r=this._height,s=this._factor,n=t%s*i,o=Math.floor(t/s)*r;if(e.camera.setViewOffset(i*s,r*s,n,o,i,r),e.render(),this._antialias){const t=Math.round((n+i)/2)-Math.round(n/2),s=Math.round((o+r)/2)-Math.round(o/2);this._ctx.drawImage(e.renderer.domElement,Math.round(n/2),Math.round(o/2),t,s)}else this._ctx.drawImage(e.renderer.domElement,Math.floor(n),Math.floor(o),Math.ceil(i),Math.ceil(r));"function"==typeof this._onProgress&&this._onProgress(t+1,this._n,!1)}_finalize(){this._viewer.setSampling(this._viewerSampleLevel),this._viewer.camera.view=null,"function"==typeof this._onFinish&&this._onFinish(this._n+1,this._n,!1)}render(){for(let t=0;t<=this._n;++t)t===this._n?this._finalize():this._renderTile(t)}renderAsync(){let t=0;const e=this._n,i=()=>{t===e?this._finalize():this._renderTile(t),t+=1};for(let t=0;t<=e;++t)setTimeout(i,0)}}const xi=2*Math.PI,vi=180/Math.PI;function wi(t,e,i=1,r=0,s){const n=s?s.length:t.length/i;let o=0,a=0;if(s)for(let c=0;ce&&(e=t[i]);return e}function Di(t){let e=1/0;for(let i=0,r=t.length;i=0;l--){for(c=o-1;c>=0;c--)if(d=4*(l*o+c),a[d]!==e||a[d+1]!==i||a[d+2]!==r||a[d+3]!==s){h=!0;break}if(h)break}const p=l;for(h=!1,c=o-1;c>=0;c--){for(l=n-1;l>=0;l--)if(d=4*(l*o+c),a[d]!==e||a[d+1]!==i||a[d+2]!==r||a[d+3]!==s){h=!0;break}if(h)break}const f=c,g=document.createElement("canvas");return g.width=f-m,g.height=p-u,g.getContext("2d").drawImage(t,m,u,g.width,g.height,0,0,g.width,g.height),g}(t,n?0:255*e.r,n?0:255*e.g,n?0:255*e.b,n?0:255)}return t}function u(t,i,r){"function"==typeof e.onProgress&&e.onProgress(t,i,r)}return new Promise((function(e,i){const l=new bi(o,a,t,{factor:r,antialias:s,onProgress:u,onFinish:function(r,s){d(l.canvas).toBlob((function(r){o.setClearAlpha(c),h(!0),t.requestRender(),u(s,s,!0),r?e(r):i("error creating image")}),"image/png")}});o.setClearAlpha(n?0:1),h(),l.renderAsync()}))}const Fi=new e,Li=new i,Ni=new i;const zi=new t,Vi=new i,Gi=new i;function Ui(t,e){Vi.getInverse(e.projectionMatrix),Gi.copy(e.projectionMatrix).transpose(),t.traverse((function(t){const e=t.material;if(!e)return;const i=e.uniforms;i&&(i.projectionMatrixInverse&&i.projectionMatrixInverse.value.copy(Vi),i.projectionMatrixTranspose&&i.projectionMatrixTranspose.value.copy(Gi))}))}function ji(t,e,i){const r=t.createShader(i);if(!r)return void console.log(`error creating WebGL shader ${i}`);t.shaderSource(r,e),t.compileShader(r);return t.getShaderParameter(r,t.COMPILE_STATUS)?r:(console.log(`error compiling shader ${r}: ${t.getShaderInfoLog(r)}`),t.deleteShader(r),null)}function Hi(t,e){const i=t.getExtension(e);return i||console.log(`extension '${e}' not available`),i}const Wi=new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]);function qi(t){const e=document.createElement("canvas");e.width=16,e.height=16,e.style.width="16px",e.style.height="16px";const i=e.getContext("webgl")||e.getContext("experimental-webgl");if(!i)return console.log(`error creating webgl context for ${t}`),!1;if(!(i instanceof WebGLRenderingContext))return console.log("Got unexpected type for WebGL rendering context"),!1;Hi(i,"OES_texture_float"),Hi(i,"OES_texture_half_float"),Hi(i,"WEBGL_color_buffer_float");const r=ji(i,"\nattribute vec4 a_position;\n\nvoid main() {\n gl_Position = a_position;\n}",i.VERTEX_SHADER),s=ji(i,"\nprecision mediump float;\nuniform vec4 u_color;\nuniform sampler2D u_texture;\n\nvoid main() {\n gl_FragColor = texture2D(u_texture, vec2(0.5, 0.5)) * u_color;\n}",i.FRAGMENT_SHADER);if(!r||!s)return!1;const n=function(t,e,i,r){const s=t.createProgram();return s?(e.forEach((e=>t.attachShader(s,e))),i&&i.forEach(((e,i)=>{t.bindAttribLocation(s,r?r[i]:i,e)})),t.linkProgram(s),t.getProgramParameter(s,t.LINK_STATUS)?s:(console.log(`error linking program: ${t.getProgramInfoLog(s)}`),t.deleteProgram(s),null)):void console.log("error creating WebGL program")}(i,[r,s]);if(!n)return console.log("error creating WebGL program"),!1;i.useProgram(n);const o=i.getAttribLocation(n,"a_position"),a=i.getUniformLocation(n,"u_color");if(!a)return console.log("error getting 'u_color' uniform location"),!1;const c=i.createBuffer();i.bindBuffer(i.ARRAY_BUFFER,c),i.bufferData(i.ARRAY_BUFFER,Wi,i.STATIC_DRAW),i.enableVertexAttribArray(o),i.vertexAttribPointer(o,2,i.FLOAT,!1,0,0);const l=i.createTexture(),h=new Uint8Array([255,255,255,255]);i.bindTexture(i.TEXTURE_2D,l),i.texImage2D(i.TEXTURE_2D,0,i.RGBA,1,1,0,i.RGBA,i.UNSIGNED_BYTE,h);const d=i.createTexture();i.bindTexture(i.TEXTURE_2D,d),i.texImage2D(i.TEXTURE_2D,0,i.RGBA,1,1,0,i.RGBA,t,null),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MIN_FILTER,i.NEAREST),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MAG_FILTER,i.NEAREST);const u=i.createFramebuffer();i.bindFramebuffer(i.FRAMEBUFFER,u),i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,i.TEXTURE_2D,d,0);if(i.checkFramebufferStatus(i.FRAMEBUFFER)!==i.FRAMEBUFFER_COMPLETE)return console.log(`error creating framebuffer for ${t}`),!1;i.bindTexture(i.TEXTURE_2D,l),i.uniform4fv(a,[0,10,20,1]),i.drawArrays(i.TRIANGLES,0,6),i.bindTexture(i.TEXTURE_2D,d),i.bindFramebuffer(i.FRAMEBUFFER,null),i.clearColor(1,0,0,1),i.clear(i.COLOR_BUFFER_BIT),i.uniform4fv(a,[0,.1,.05,1]),i.drawArrays(i.TRIANGLES,0,6);const m=new Uint8Array(4);if(i.readPixels(0,0,1,1,i.RGBA,i.UNSIGNED_BYTE,m),0!==m[0]||m[1]<248||m[2]<248||m[3]<254)return console.log(`not able to actually render to ${t} texture`),!1;if(t===i.FLOAT){i.bindFramebuffer(i.FRAMEBUFFER,u);const t=new Float32Array(4);i.readPixels(0,0,1,1,i.RGBA,i.FLOAT,t);const e=i.getError();if(e)return console.log(`error reading pixels as float: '${function(t,e){switch(e){case t.NO_ERROR:return"no error";case t.INVALID_ENUM:return"invalid enum";case t.INVALID_VALUE:return"invalid value";case t.INVALID_OPERATION:return"invalid operation";case t.INVALID_FRAMEBUFFER_OPERATION:return"invalid framebuffer operation";case t.OUT_OF_MEMORY:return"out of memory";case t.CONTEXT_LOST_WEBGL:return"context lost"}return"unknown error"}(i,e)}'`),!1}return!0}const Xi=new Float32Array(100),Yi=new Uint8Array(100),Ki=[12,7,13,17,11,6,8,18,16,2,14,22,10,1,3,9,19,23,21,15,5,0,4,24,20],Zi=new i;function Qi(t,e,i,r,s){const n=s.uniforms,o=[];if(n&&(n.objectId&&(n.objectId.value=Ce?this.id:this.id/255,o.push("objectId")),(n.modelViewMatrixInverse||n.modelViewMatrixInverseTranspose||n.modelViewProjectionMatrix||n.modelViewProjectionMatrixInverse)&&this.modelViewMatrix.multiplyMatrices(i.matrixWorldInverse,this.matrixWorld),n.modelViewMatrixInverse&&(n.modelViewMatrixInverse.value.getInverse(this.modelViewMatrix),o.push("modelViewMatrixInverse")),n.modelViewMatrixInverseTranspose&&(n.modelViewMatrixInverse?n.modelViewMatrixInverseTranspose.value.copy(n.modelViewMatrixInverse.value).transpose():n.modelViewMatrixInverseTranspose.value.getInverse(this.modelViewMatrix).transpose(),o.push("modelViewMatrixInverseTranspose")),n.modelViewProjectionMatrix&&(n.modelViewProjectionMatrix.value.multiplyMatrices(i.projectionMatrix,this.modelViewMatrix),o.push("modelViewProjectionMatrix")),n.modelViewProjectionMatrixInverse&&(n.modelViewProjectionMatrix?(Zi.copy(n.modelViewProjectionMatrix.value),n.modelViewProjectionMatrixInverse.value.getInverse(Zi)):(Zi.multiplyMatrices(i.projectionMatrix,this.modelViewMatrix),n.modelViewProjectionMatrixInverse.value.getInverse(Zi)),o.push("modelViewProjectionMatrixInverse")),o.length)){const e=t.properties.get(s);if(e.program){const i=t.getContext(),r=e.program;i.useProgram(r.program);const s=r.getUniforms();o.forEach((function(t){s.setValue(i,t,n[t].value)}))}}}class Ji{constructor(t){if(this.boundingBox=new a,this.boundingBoxSize=new e,this.boundingBoxLength=0,this.info={memory:{programs:0,geometries:0,textures:0},render:{calls:0,vertices:0,faces:0,points:0}},this.distVector=new e,this.signals={ticked:new et,rendered:new et},"string"==typeof t){const e=document.getElementById(t);this.container=null===e?document.createElement("div"):e}else t instanceof HTMLElement?this.container=t:this.container=document.createElement("div");if(this.container===document.body)this.width=window.innerWidth||1,this.height=window.innerHeight||1;else{const t=this.container.getBoundingClientRect();this.width=t.width||1,this.height=t.height||1,this.container.style.overflow="hidden"}this.wrapper=document.createElement("div"),this.wrapper.style.position="relative",this.container.appendChild(this.wrapper),this._initParams(),this._initStats(),this._initCamera(),this._initScene(),!1!==this._initRenderer()?(this._initHelper(),this.setBackground(),this.setFog(),this.animate=this.animate.bind(this)):Me.error("Viewer: could not initialize renderer")}_initParams(){this.parameters={fogColor:new s(0),fogNear:50,fogFar:100,backgroundColor:new s(0),cameraType:"perspective",cameraFov:40,cameraEyeSep:.3,cameraZ:-80,clipNear:0,clipFar:100,clipDist:10,clipMode:"scene",clipScale:"relative",lightColor:new s(14540253),lightIntensity:1,ambientColor:new s(14540253),ambientIntensity:.2,sampleLevel:0,rendererEncoding:c}}_initCamera(){const t=new e(0,0,0),{width:i,height:r}=this;this.perspectiveCamera=new l(this.parameters.cameraFov,i/r),this.perspectiveCamera.position.z=this.parameters.cameraZ,this.perspectiveCamera.lookAt(t),this.orthographicCamera=new h(i/-2,i/2,r/2,r/-2),this.orthographicCamera.position.z=this.parameters.cameraZ,this.orthographicCamera.lookAt(t),this.stereoCamera=new d,this.stereoCamera.aspect=.5,this.stereoCamera.eyeSep=this.parameters.cameraEyeSep;const s=this.parameters.cameraType;if("orthographic"===s)this.camera=this.orthographicCamera;else{if("perspective"!==s&&"stereo"!==s)throw new Error(`Unknown cameraType '${s}'`);this.camera=this.perspectiveCamera}this.camera.updateProjectionMatrix()}_initStats(){this.stats=new mi}_initScene(){this.scene||(this.scene=new u,this.scene.name="scene"),this.rotationGroup=new m,this.rotationGroup.name="rotationGroup",this.scene.add(this.rotationGroup),this.translationGroup=new m,this.translationGroup.name="translationGroup",this.rotationGroup.add(this.translationGroup),this.modelGroup=new m,this.modelGroup.name="modelGroup",this.translationGroup.add(this.modelGroup),this.pickingGroup=new m,this.pickingGroup.name="pickingGroup",this.translationGroup.add(this.pickingGroup),this.backgroundGroup=new m,this.backgroundGroup.name="backgroundGroup",this.translationGroup.add(this.backgroundGroup),this.helperGroup=new m,this.helperGroup.name="helperGroup",this.translationGroup.add(this.helperGroup),this.scene.fog=new p(this.parameters.fogColor.getHex()),this.spotLight=new f(this.parameters.lightColor.getHex(),this.parameters.lightIntensity),this.scene.add(this.spotLight),this.ambientLight=new g(this.parameters.ambientColor.getHex(),this.parameters.ambientIntensity),this.scene.add(this.ambientLight)}_initRenderer(){const t=window.devicePixelRatio,{width:e,height:i}=this;try{this.renderer=new y({preserveDrawingBuffer:!0,alpha:!0,antialias:!0})}catch(t){return this.wrapper.innerHTML='

Your browser/graphics card does not seem to support WebGL.

Find out how to get it here.

',!1}this.renderer.setPixelRatio(t),this.renderer.setSize(e,i),this.renderer.autoClear=!1,this.renderer.sortObjects=!0,this.renderer.outputEncoding=this.parameters.rendererEncoding;const r=this.renderer.getContext();this.renderer.capabilities.isWebGL2?(ke(!0),Pe(this.renderer.extensions.get("EXT_color_buffer_float")),this.supportsHalfFloat=!0):(ke(this.renderer.extensions.get("EXT_frag_depth")),this.renderer.extensions.get("OES_element_index_uint"),Pe(this.renderer.extensions.get("OES_texture_float")&&this.renderer.extensions.get("WEBGL_color_buffer_float")||this.renderer.extensions.get("OES_texture_float")&&qi(r.FLOAT)),this.renderer.extensions.get("OES_texture_float"),this.supportsHalfFloat=this.renderer.extensions.get("OES_texture_half_float")&&qi(36193)),this.wrapper.appendChild(this.renderer.domElement);const s=e*t,n=i*t;De&&console.log(JSON.stringify({Browser:Ae,OES_texture_float:!!this.renderer.extensions.get("OES_texture_float"),OES_texture_half_float:!!this.renderer.extensions.get("OES_texture_half_float"),WEBGL_color_buffer_float:!!this.renderer.extensions.get("WEBGL_color_buffer_float"),"testTextureSupport Float":qi(r.FLOAT),"testTextureSupport HalfFloat":qi(36193),"this.supportsHalfFloat":this.supportsHalfFloat,SupportsReadPixelsFloat:Ce},null,2)),this.pickingTarget=new b(s,n,{minFilter:x,magFilter:x,stencilBuffer:!1,format:v,type:Ce?D:w}),this.pickingTarget.texture.generateMipmaps=!1,this.pickingTarget.texture.encoding=this.parameters.rendererEncoding,this.renderer.setRenderTarget(this.pickingTarget),this.renderer.clear(),this.renderer.setRenderTarget(null),this.sampleTarget=new b(s,n,{minFilter:A,magFilter:A,format:v}),this.sampleTarget.texture.encoding=this.parameters.rendererEncoding,this.holdTarget=new b(s,n,{minFilter:x,magFilter:x,format:v,type:w}),this.holdTarget.texture.encoding=this.parameters.rendererEncoding,this.compositeUniforms={tForeground:new _(this.sampleTarget.texture),scale:new _(1)},this.compositeMaterial=new S({uniforms:this.compositeUniforms,vertexShader:gi("Quad.vert"),fragmentShader:gi("Quad.frag"),premultipliedAlpha:!0,transparent:!0,blending:C,depthTest:!1,depthWrite:!1}),this.compositeCamera=new h(-1,1,1,-1,0,1),this.compositeScene=new u,this.compositeScene.name="compositeScene",this.compositeScene.add(new P(new I(2,2),this.compositeMaterial))}_initHelper(){const t=new Uint16Array([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7]),e=new Float32Array(24),i=new k;i.setIndex(new M(t,1)),i.setAttribute("position",new M(e,3));const r=new S({uniforms:{uColor:{value:new s("skyblue")}},vertexShader:gi("BasicLine.vert"),fragmentShader:gi("BasicLine.frag")});this.boundingBoxMesh=new T(i,r),this.helperGroup.add(this.boundingBoxMesh)}updateHelper(){const t=this.boundingBoxMesh.geometry.attributes.position,e=t.array,{min:i,max:r}=this.boundingBox;e[0]=r.x,e[1]=r.y,e[2]=r.z,e[3]=i.x,e[4]=r.y,e[5]=r.z,e[6]=i.x,e[7]=i.y,e[8]=r.z,e[9]=r.x,e[10]=i.y,e[11]=r.z,e[12]=r.x,e[13]=r.y,e[14]=i.z,e[15]=i.x,e[16]=r.y,e[17]=i.z,e[18]=i.x,e[19]=i.y,e[20]=i.z,e[21]=r.x,e[22]=i.y,e[23]=i.z,t.needsUpdate=!0,this.boundingBox.isEmpty()||this.boundingBoxMesh.geometry.computeBoundingSphere()}get cameraDistance(){return Math.abs(this.camera.position.z)}set cameraDistance(t){this.camera.position.z=-t}add(t,e){e?e.forEach((e=>this.addBuffer(t,e))):this.addBuffer(t),t.group.name="meshGroup",t.wireframeGroup.name="wireframeGroup",t.parameters.background?(this.backgroundGroup.add(t.group),this.backgroundGroup.add(t.wireframeGroup)):(this.modelGroup.add(t.group),this.modelGroup.add(t.wireframeGroup)),t.pickable&&this.pickingGroup.add(t.pickingGroup),De&&this.updateHelper()}addBuffer(t,e){function i(r){r instanceof m?r.children.forEach(i):(r.userData.buffer=t,r.userData.instance=e,r.onBeforeRender=Qi)}const r=t.getMesh();e&&r.applyMatrix4(e.matrix),i(r),t.group.add(r);const s=t.getWireframeMesh();if(e&&(s.matrix.copy(r.matrix),s.position.copy(r.position),s.quaternion.copy(r.quaternion),s.scale.copy(r.scale)),i(s),t.wireframeGroup.add(s),t.pickable){const s=t.getPickingMesh();e&&(s.matrix.copy(r.matrix),s.position.copy(r.position),s.quaternion.copy(r.quaternion),s.scale.copy(r.scale)),i(s),t.pickingGroup.add(s)}e?this._updateBoundingBox(t.geometry,t.matrix,e.matrix):this._updateBoundingBox(t.geometry,t.matrix)}remove(t){this.translationGroup.children.forEach((function(e){e.remove(t.group),e.remove(t.wireframeGroup)})),t.pickable&&this.pickingGroup.remove(t.pickingGroup),this.updateBoundingBox(),De&&this.updateHelper()}_updateBoundingBox(t,e,i){const r=this.boundingBox;function s(t,e,i){null==t.boundingBox&&t.computeBoundingBox();const s=t.boundingBox.clone();e&&s.applyMatrix4(e),i&&s.applyMatrix4(i),s.min.equals(s.max)&&s.expandByScalar(5),r.union(s)}function n(t){if(void 0!==t.geometry){let e,i;t.userData.buffer&&(e=t.userData.buffer.matrix),t.userData.instance&&(i=t.userData.instance.matrix),s(t.geometry,e,i)}}t?s(t,e,i):(r.makeEmpty(),this.modelGroup.traverse(n),this.backgroundGroup.traverse(n)),r.getSize(this.boundingBoxSize),this.boundingBoxLength=this.boundingBoxSize.length()}updateBoundingBox(){this._updateBoundingBox(),De&&this.updateHelper()}getPickingPixels(){const{width:t,height:e}=this,i=t*e*4,r=Ce?new Float32Array(i):new Uint8Array(i);return this.render(!0),this.renderer.readRenderTargetPixels(this.pickingTarget,0,0,t,e,r),r}getImage(t){return new Promise((e=>{if(t){const{width:t,height:i}=this,r=t*i*4;let s=this.getPickingPixels();if(Ce){const t=new Uint8Array(r);for(let e=0;e500&&!this.isStill&&this.sampleLevel<3&&-1!==this.sampleLevel){const t=this.sampleLevel;this.sampleLevel=3,this.renderPending=!0,this.render(),this.isStill=!0,this.sampleLevel=t,De&&Me.log("rendered still frame")}this.frameRequest=window.requestAnimationFrame(this.animate)}pick(t,e){if("stereo"===this.parameters.cameraType)return{pid:0,instance:void 0,picker:void 0};t*=window.devicePixelRatio,e*=window.devicePixelRatio,t=Math.max(t-2,0),e=Math.max(e-2,0);let i,r,s=0;const n=Ce?Xi:Yi;this.render(!0),this.renderer.readRenderTargetPixels(this.pickingTarget,t,e,5,5,n);for(let t=0;t22&&(this.stats.begin(),this.isStill=!1),this.renderPending=!0,window.requestAnimationFrame((()=>{this.render(),this.stats.update()})))}updateZoom(){const t=kt(this.perspectiveCamera.fov),e=2*Math.tan(t/2)*this.cameraDistance;this.orthographicCamera.zoom=this.height/e}absoluteToRelative(t){return 50*(1-t/this.bRadius)}relativeToAbsolute(t){return this.bRadius*(1-t/50)}__updateClipping(){const t=this.parameters;this.bRadius=Math.max(10,.5*this.boundingBoxLength),isFinite(this.bRadius)||(this.bRadius=50),this.camera.getWorldPosition(this.distVector),this.cDist=this.distVector.length(),this.cDist||(this.cameraDistance=Math.abs(t.cameraZ),this.cDist=Math.abs(t.cameraZ));const e=this.scene.fog;if(e.color.set(t.fogColor),"camera"===t.clipMode)this.camera.near=t.clipNear,this.camera.far=t.clipFar,e.near=t.fogNear,e.far=t.fogFar;else if("absolute"===t.clipScale)this.camera.near=this.cDist-t.clipNear,this.camera.far=this.cDist+t.clipFar,e.near=this.cDist-t.fogNear,e.far=this.cDist+t.fogFar;else{const i=(50-t.clipNear)/50,r=-(50-t.clipFar)/50;this.camera.near=this.cDist-this.bRadius*i,this.camera.far=this.cDist+this.bRadius*r;const s=(50-t.fogNear)/50,n=-(50-t.fogFar)/50;e.near=this.cDist-this.bRadius*s,e.far=this.cDist+this.bRadius*n}"camera"!==t.clipMode&&("PerspectiveCamera"===this.camera.type?(this.camera.near=Math.max(.1,t.clipDist,this.camera.near),this.camera.far=Math.max(1,this.camera.far),e.near=Math.max(.1,e.near),e.far=Math.max(1,e.far)):"OrthographicCamera"===this.camera.type&&t.clipDist>0&&(this.camera.near=Math.max(t.clipDist,this.camera.near)))}__updateCamera(){const e=this.camera;e.updateMatrix(),e.updateMatrixWorld(!0),e.updateProjectionMatrix(),function(e,i,r,s,n){let o=new t;r.getSize(o);const a=o.height,c=r.getPixelRatio(),l="OrthographicCamera"===i.type;zi.set(o.width,o.height),Vi.getInverse(i.projectionMatrix),Gi.copy(i.projectionMatrix).transpose(),e.traverse((function(t){const e=t.material;if(!e)return;const i=e.uniforms;if(i){if(e.clipNear){const t=(50-e.clipNear)/50,r=s-n*t;i.clipNear.value=r}i.canvasHeight&&(i.canvasHeight.value=a),i.resolution&&i.resolution.value.copy(zi),i.pixelRatio&&(i.pixelRatio.value=c),i.projectionMatrixInverse&&i.projectionMatrixInverse.value.copy(Vi),i.projectionMatrixTranspose&&i.projectionMatrixTranspose.value.copy(Gi),i.ortho&&(i.ortho.value=l)}}))}(this.scene,e,this.renderer,this.cDist,this.bRadius),function(t,e){t.traverseVisible((function(t){if(!(t instanceof o&&t.userData.buffer.parameters.sortParticles))return;const i=t.geometry.attributes,r=i.position.count;if(0===r)return;let s,n,a,c,l,h,d,u;Li.multiplyMatrices(e.matrixWorldInverse,t.matrixWorld),Ni.multiplyMatrices(e.projectionMatrix,Li),t.userData.sortData?(s=t.userData.sortData,a=s.__zArray,n=s.__sortArray,c=s.__cmpFn):(a=new Float32Array(r),n=new Uint32Array(r),c=function(t,e){const i=a[t],r=a[e];return i>r?1:ie?1:t=l&&e(t[o],n)>0;)t[o+1]=t[o],--o;t[o+1]=n}if(-1===c)break;h=s[c--],l=s[c--]}else{for(o=l+1,a=h,d(l+h>>1,o),e(t[l],t[h])>0&&d(l,h),e(t[o],t[h])>0&&d(o,h),e(t[l],t[o])>0&&d(l,o),n=t[o];;){do{o++}while(e(t[o],n)<0);do{a--}while(e(t[a],n)>0);if(a=a-l?(s[++c]=o,s[++c]=h,h=a-1):(s[++c]=l,s[++c]=a-1,l=o)}}(n,c);for(let t in i){const e=i[t],o=e.array,a=e.itemSize;s[t]||(s[t]=new Float32Array(a*r)),u=s[t],s[t]=o;for(let t=0;t0&&"stereo"!==this.parameters.cameraType?this.__renderSuperSample(e,i):this.__renderModelGroup(e,i)}render(t=!1,e){if(this.rendering)Me.warn("'tried to call 'render' from within 'render'");else{this.rendering=!0;try{this.__updateClipping(),this.__updateCamera(),this.__updateLights(),this.updateInfo(!0),"stereo"===this.parameters.cameraType?this.__renderStereo(t,e):this.__render(t,this.camera,e),this.lastRenderedPicking=t}finally{this.rendering=!1,this.renderPending=!1}this.signals.rendered.dispatch()}}clear(){Me.log("scene cleared"),this.scene.remove(this.rotationGroup),this._initScene(),this.renderer.clear()}dispose(){this.renderer.dispose(),window.cancelAnimationFrame(this.frameRequest)}}const tr=1,er=2,ir=3;function rr(t){const e=t.touches[0].pageX-t.touches[1].pageX,i=t.touches[0].pageY-t.touches[1].pageY;return Math.sqrt(e*e+i*i)}class sr{constructor(e,i={}){this.domElement=e,this.signals={moved:new et,scrolled:new et,dragged:new et,dropped:new et,clicked:new et,hovered:new et,doubleClicked:new et},this.position=new t,this.prevPosition=new t,this.down=new t,this.canvasPosition=new t,this.prevClickCP=new t,this.moving=!1,this.hovering=!0,this.scrolled=!1,this.lastMoved=1/0,this.which=0,this.buttons=0,this.pressed=!1,this.altKey=!1,this.ctrlKey=!1,this.metaKey=!1,this.shiftKey=!1,this.domElement.style.touchAction="none",this.hoverTimeout=st(i.hoverTimeout,50),this.handleScroll=st(i.handleScroll,!0),this.doubleClickSpeed=st(i.doubleClickSpeed,500),this._listen=this._listen.bind(this),this._onMousewheel=this._onMousewheel.bind(this),this._onMousemove=this._onMousemove.bind(this),this._onMousedown=this._onMousedown.bind(this),this._onMouseup=this._onMouseup.bind(this),this._onContextmenu=this._onContextmenu.bind(this),this._onTouchstart=this._onTouchstart.bind(this),this._onTouchend=this._onTouchend.bind(this),this._onTouchmove=this._onTouchmove.bind(this),this._listen();const r={passive:!1};document.addEventListener("mousewheel",this._onMousewheel,r),document.addEventListener("wheel",this._onMousewheel,r),document.addEventListener("MozMousePixelScroll",this._onMousewheel,r),document.addEventListener("mousemove",this._onMousemove,r),document.addEventListener("mousedown",this._onMousedown,r),document.addEventListener("mouseup",this._onMouseup,r),document.addEventListener("contextmenu",this._onContextmenu,r),document.addEventListener("touchstart",this._onTouchstart,r),document.addEventListener("touchend",this._onTouchend,r),document.addEventListener("touchmove",this._onTouchmove,r)}get key(){let t=0;return this.altKey&&(t+=1),this.ctrlKey&&(t+=2),this.metaKey&&(t+=4),this.shiftKey&&(t+=8),t}setParameters(t={}){this.hoverTimeout=st(t.hoverTimeout,this.hoverTimeout)}_listen(){const t=window.performance.now(),e=this.canvasPosition;this.doubleClickPending&&t-this.lastClicked>this.doubleClickSpeed&&(this.doubleClickPending=!1),t-this.lastMoved>this.hoverTimeout&&(this.moving=!1),(this.scrolled||!this.moving&&!this.hovering)&&(this.scrolled=!1,-1!==this.hoverTimeout&&this.overElement&&(this.hovering=!0,this.signals.hovered.dispatch(e.x,e.y))),this.frameRequest=window.requestAnimationFrame(this._listen)}_onMousewheel(t){if(t.target!==this.domElement||!this.handleScroll)return;t.preventDefault(),this._setKeys(t);let e=0;"deltaY"in t&&"deltaMode"in t&&void 0!==t.deltaY&&void 0!==t.deltaMode?e=t.deltaMode===WheelEvent.DOM_DELTA_PIXEL?.025*-t.deltaY:t.deltaMode===WheelEvent.DOM_DELTA_LINE?-t.deltaY*(2.5/3):2.5*-t.deltaY:"deltaY"in t&&!("detail"in t)?e=.025*-t.deltaY:void 0!==t.wheelDelta?e=.025*-t.wheelDelta:void 0!==t.wheelDeltaY?e=.025*-t.wheelDeltaY:void 0!==t.detail&&(e=-t.detail/3),this.signals.scrolled.dispatch(e),setTimeout((()=>{this.scrolled=!0}),this.hoverTimeout)}_onMousemove(t){t.target===this.domElement?(t.preventDefault(),this.overElement=!0):this.overElement=!1,this._setKeys(t),this.moving=!0,this.hovering=!1,this.lastMoved=window.performance.now(),this.prevPosition.copy(this.position),this.position.set(t.clientX,t.clientY),this._setCanvasPosition(t);const e=this.prevPosition.x-this.position.x,i=this.prevPosition.y-this.position.y;this.signals.moved.dispatch(e,i),this.pressed&&this.signals.dragged.dispatch(e,i)}_onMousedown(t){t.target===this.domElement&&(t.preventDefault(),this._setKeys(t),this.moving=!1,this.hovering=!1,this.down.set(t.clientX,t.clientY),this.position.set(t.clientX,t.clientY),this.which=t.which,this.buttons=function(t){if("object"==typeof t){if("buttons"in t)return t.buttons;if("which"in t){const e=t.which;if(2===e)return 4;if(3===e)return 2;if(e>0)return 1<=0)return 1<2&&this.handleScroll&&this.position.distanceTo(this.prevPosition)<2)this.which=0,this.buttons=0,this.signals.scrolled.dispatch(i/2);else{this.which=3,this.buttons=2;const t=this.prevPosition.x-this.position.x,e=this.prevPosition.y-this.position.y;this.signals.moved.dispatch(t,e),this.pressed&&this.signals.dragged.dispatch(t,e)}}}}_distance(){return this.position.distanceTo(this.down)}_setCanvasPosition(t){const e=this.domElement.getBoundingClientRect();let i,r;"clientX"in t&&"clientY"in t?(i=t.clientX-e.left,r=t.clientY-e.top):(i=t.offsetX,r=t.offsetY),this.canvasPosition.set(i,e.height-r)}_setKeys(t){this.altKey=t.altKey,this.ctrlKey=t.ctrlKey,this.metaKey=t.metaKey,this.shiftKey=t.shiftKey}dispose(){document.removeEventListener("mousewheel",this._onMousewheel),document.removeEventListener("wheel",this._onMousewheel),document.removeEventListener("MozMousePixelScroll",this._onMousewheel),document.removeEventListener("mousemove",this._onMousemove),document.removeEventListener("mousedown",this._onMousedown),document.removeEventListener("mouseup",this._onMouseup),document.removeEventListener("contextmenu",this._onContextmenu),document.removeEventListener("touchstart",this._onTouchstart),document.removeEventListener("touchend",this._onTouchend),document.removeEventListener("touchmove",this._onTouchmove),window.cancelAnimationFrame(this.frameRequest)}}const nr=new i,or=new i,ar=new i,cr=new i,lr=new i,hr=new e,dr=new r,ur=new r,mr=new i,pr=new e,fr=new e;class gr{constructor(t,e={}){this.stage=t,this.rotateSpeed=st(e.rotateSpeed,2),this.zoomSpeed=st(e.zoomSpeed,1.2),this.panSpeed=st(e.panSpeed,1),this.viewer=t.viewer,this.mouse=t.mouseObserver,this.controls=t.viewerControls}get component(){return this.stage.transformComponent}get atom(){return this.stage.transformAtom}_setPanVector(t,e,i=0){const r=this.controls.getCanvasScaleFactor(i);pr.set(t,e,0),pr.multiplyScalar(this.panSpeed*r)}_getRotateXY(t,e){return[this.rotateSpeed*-t*.01,this.rotateSpeed*e*.01]}_getCameraRotation(t){return t.extractRotation(this.viewer.camera.matrixWorld),t.multiply(or.makeRotationY(Math.PI)),t}_transformPanVector(){this.component&&(mr.extractRotation(this.component.transform),mr.premultiply(this.viewer.rotationGroup.matrix),mr.getInverse(mr),mr.multiply(this._getCameraRotation(cr)),pr.applyMatrix4(mr))}zoom(t){this.controls.zoom(this.zoomSpeed*t*.02)}pan(t,e){this._setPanVector(t,e),mr.getInverse(this.viewer.rotationGroup.matrix),mr.multiply(this._getCameraRotation(cr)),pr.applyMatrix4(mr),this.controls.translate(pr)}panComponent(t,e){this.component&&(this._setPanVector(t,e),this._transformPanVector(),this.component.position.add(pr),this.component.updateMatrix())}panAtom(t,e){this.atom&&this.component&&(this.atom.positionToVector3(fr),fr.add(this.viewer.translationGroup.position),fr.applyMatrix4(this.viewer.rotationGroup.matrix),this._setPanVector(t,e,fr.z),this._transformPanVector(),this.atom.positionAdd(pr),this.component.updateRepresentations({position:!0}))}rotate(t,e){const[i,r]=this._getRotateXY(t,e);this._getCameraRotation(cr),hr.set(1,0,0),hr.applyMatrix4(cr),dr.setFromAxisAngle(hr,r),hr.set(0,1,0),hr.applyMatrix4(cr),ur.setFromAxisAngle(hr,i),dr.multiply(ur),cr.makeRotationFromQuaternion(dr),this.controls.applyMatrix(cr)}zRotate(t,e){const i=this.rotateSpeed*((-t+e)/-2)*.01;ar.makeRotationZ(i),this.controls.applyMatrix(ar)}rotateComponent(t,e){if(!this.component)return;const[i,r]=this._getRotateXY(t,e);this._getCameraRotation(lr),cr.extractRotation(this.component.transform),cr.premultiply(this.viewer.rotationGroup.matrix),cr.getInverse(cr),cr.premultiply(lr),hr.set(1,0,0),hr.applyMatrix4(cr),nr.makeRotationAxis(hr,r),hr.set(0,1,0),hr.applyMatrix4(cr),or.makeRotationAxis(hr,i),nr.multiply(or),dr.setFromRotationMatrix(nr),this.component.quaternion.premultiply(dr),this.component.quaternion.normalize(),this.component.updateMatrix()}}const yr=new e;class br{constructor(t,e){this.stage=e,this.pid=t.pid,this.picker=t.picker,this.instance=t.instance,this.stage=e,this.controls=e.viewerControls,this.mouse=e.mouseObserver}get type(){return this.picker.type}get altKey(){return this.mouse.altKey}get ctrlKey(){return this.mouse.ctrlKey}get metaKey(){return this.mouse.metaKey}get shiftKey(){return this.mouse.shiftKey}get canvasPosition(){return this.mouse.canvasPosition}get component(){return this.stage.getComponentsByObject(this.picker.data).list[0]}get object(){return this.picker.getObject(this.pid)}get position(){return this.picker.getPosition(this.pid,this.instance,this.component)}get closestBondAtom(){if("bond"!==this.type||!this.bond)return;const t=this.bond,e=this.controls,i=this.canvasPosition,r=t.atom1.positionToVector3(),s=t.atom2.positionToVector3();r.applyMatrix4(this.component.matrix),s.applyMatrix4(this.component.matrix);const n=e.getPositionOnCanvas(r),o=e.getPositionOnCanvas(s);return c=n,l=o,(a=i).distanceTo(c)=t.length))return new br(i,this.stage);console.error("pid >= picker.array.length")}}}const vr=new r,wr=new e,Ar=new e,_r=new e,Sr=new e,Cr=new i,Pr=new e,Ir=new i;class kr{constructor(t){this.stage=t,this.signals={changed:new tt.Signal},this.viewer=t.viewer}get position(){return this.viewer.translationGroup.position}get rotation(){return this.viewer.rotationGroup.quaternion}changed(){this.viewer.requestRender(),this.signals.changed.dispatch()}getPositionOnCanvas(e,i){const r=wt(i,t);const s=this.viewer;return _r.copy(e).add(s.translationGroup.position).applyMatrix4(s.rotationGroup.matrix).project(s.camera),r.set((_r.x+1)*s.width/2,(_r.y+1)*s.height/2)}getCanvasScaleFactor(t=0){const e=this.viewer.camera;if(e instanceof h)return 1/e.zoom;{t=Math.abs(t),t+=this.getCameraDistance();const i=kt(e.fov);return 2*t*Math.tan(i/2)/this.viewer.height}}getOrientation(t){const e=_t(t);e.copy(this.viewer.rotationGroup.matrix);const i=this.getCameraDistance();return e.scale(Sr.set(i,i,i)),e.setPosition(this.viewer.translationGroup.position),e}orient(t){_t(t).decompose(wr,vr,Ar);const e=this.viewer;e.rotationGroup.setRotationFromQuaternion(vr),e.translationGroup.position.copy(wr),e.cameraDistance=Ar.z,e.updateZoom(),this.changed()}translate(t){this.viewer.translationGroup.position.add(At(t)),this.changed()}center(t){this.viewer.translationGroup.position.copy(At(t)).negate(),this.changed()}zoom(t){this.distance(this.getCameraDistance()*(1-t))}getCameraDistance(){return this.viewer.cameraDistance}distance(t){this.viewer.cameraDistance=Math.max(Math.abs(t),.2),this.viewer.updateZoom(),this.changed()}spin(t,e){Cr.getInverse(this.viewer.rotationGroup.matrix),Pr.copy(At(t)).applyMatrix4(Cr),this.viewer.rotationGroup.rotateOnAxis(Pr,e),this.changed()}rotate(t){this.viewer.rotationGroup.setRotationFromQuaternion(St(t)),this.changed()}align(t){Ir.getInverse(_t(t)),this.viewer.rotationGroup.setRotationFromMatrix(Ir),this.changed()}applyMatrix(t){this.viewer.rotationGroup.applyMatrix4(_t(t)),this.changed()}}class Mr{constructor(t,e,...i){this.pausedTime=-1,this.elapsedDuration=0,this.pausedDuration=0,this.ignoreGlobalToggle=!1,this._paused=!1,this._resolveList=[],this.duration=st(t,1e3),this.controls=e,this.startTime=window.performance.now(),this._init(...i)}get done(){return 1===this.alpha}get paused(){return this._paused}tick(t){if(!this._paused)return this.elapsedDuration=t.currentTime-this.startTime-this.pausedDuration,0===this.duration?this.alpha=1:this.alpha=Rt(0,1,this.elapsedDuration/this.duration),this._tick(t),this.done&&this._resolveList.forEach((t=>t())),this.done}pause(t){t&&(this._hold=!0),-1===this.pausedTime&&(this.pausedTime=window.performance.now()),this._paused=!0}resume(t){!t&&this._hold||(this.pausedDuration+=window.performance.now()-this.pausedTime,this._paused=!1,this._hold=!1,this.pausedTime=-1)}toggle(){this._paused?this.resume():this.pause()}then(t){let e;return e=this.done?Promise.resolve():new Promise((t=>this._resolveList.push(t))),e.then(t)}}class Tr extends Mr{constructor(t,e,...i){super(st(t,1/0),e,...i)}_init(t,i){Array.isArray(t)?this.axis=(new e).fromArray(t):this.axis=st(t,new e(0,1,0)),this.angle=st(i,.01)}_tick(t){this.axis&&this.angle&&this.controls.spin(this.axis,this.angle*t.lastDuration/16)}}class Br extends Mr{constructor(t,e,...i){super(st(t,1/0),e,...i),this.angleSum=0,this.direction=1}_init(t,i,r){Array.isArray(t)?this.axis=(new e).fromArray(t):this.axis=st(t,new e(0,1,0)),this.angleStep=st(i,.01),this.angleEnd=st(r,.2)}_tick(t){if(!this.axis||!this.angleStep||!this.angleEnd)return;const e=Rt(0,1,Math.abs(this.angleSum)/this.angleEnd),i=this.angleStep*this.direction*(1.1-e);this.controls.spin(this.axis,i*t.lastDuration/16),this.angleSum+=this.angleStep,this.angleSum>=this.angleEnd&&(this.direction*=-1,this.angleSum=-this.angleEnd)}}class Dr extends Mr{_init(t,i){this.moveFrom=At(st(t,new e)),this.moveTo=At(st(i,new e))}_tick(){this.controls.position.lerpVectors(this.moveFrom,this.moveTo,this.alpha).negate(),this.controls.changed()}}class $r extends Mr{_init(t,e){this.zoomFrom=t,this.zoomTo=e}_tick(){this.controls.distance($t(this.zoomFrom,this.zoomTo,this.alpha))}}class Or extends Mr{constructor(){super(...arguments),this._currentRotation=new r}_init(t,e){this.rotateFrom=St(t),this.rotateTo=St(e),this._currentRotation=new r}_tick(){this._currentRotation.copy(this.rotateFrom).slerp(this.rotateTo,this.alpha),this.controls.rotate(this._currentRotation)}}class Rr extends Mr{_init(t,e,i){this.valueFrom=t,this.valueTo=e,this.callback=i}_tick(){this.callback($t(this.valueFrom,this.valueTo,this.alpha))}}class Er extends Mr{_init(t){this.callback=t}_tick(){1===this.alpha&&this.callback()}}class Fr{constructor(t=[]){this._resolveList=[],this._list=t}get done(){return this._list.every((t=>t.done))}then(t){let e;return e=this.done?Promise.resolve():new Promise((t=>{this._resolveList.push(t),this._list.forEach((t=>{t.then((()=>{this._resolveList.forEach((t=>{t()})),this._resolveList.length=0}))}))})),e.then(t)}}class Lr{constructor(t){this.stage=t,this.animationList=[],this.finishedList=[],this.viewer=t.viewer,this.controls=t.viewerControls}get paused(){return this.animationList.every((t=>t.paused))}add(t){return 0===t.duration?t.tick(this.viewer.stats):this.animationList.push(t),t}remove(t){const e=this.animationList,i=e.indexOf(t);i>-1&&e.splice(i,1)}run(t){const e=this.finishedList,i=this.animationList,r=i.length;for(let s=0;st.pause()))}resume(){this.animationList.forEach((t=>t.resume()))}toggle(){this.paused?this.resume():this.pause()}clear(){this.animationList.length=0}dispose(){this.clear()}}class Nr{constructor(t,e){if(this.fn=t,this.queue=[],this.pending=!1,this.next=this.next.bind(this),e){for(let t=0,i=e.length;tthis.run(t)))):this.pending=!1}push(t){this.queue.push(t),this.pending||this.next()}kill(){this.queue.length=0}length(){return this.queue.length}}class zr{constructor(t,e,i){this.type="",this.parameters={lazy:{type:"boolean"},clipNear:{type:"range",step:1,max:100,min:0,buffer:!0},clipRadius:{type:"number",precision:1,max:1e3,min:0,buffer:!0},clipCenter:{type:"vector3",precision:1,buffer:!0},flatShaded:{type:"boolean",buffer:!0},opacity:{type:"range",step:.01,max:1,min:0,buffer:!0},depthWrite:{type:"boolean",buffer:!0},side:{type:"select",buffer:!0,options:{front:"front",back:"back",double:"double"}},wireframe:{type:"boolean",buffer:!0},colorData:{type:"hidden",update:"color"},colorScheme:{type:"select",update:"color",options:{}},colorScale:{type:"select",update:"color",options:Fe.getScales()},colorReverse:{type:"boolean",update:"color"},colorValue:{type:"color",update:"color"},colorDomain:{type:"hidden",update:"color"},colorMode:{type:"select",update:"color",options:Fe.getModes()},roughness:{type:"range",step:.01,max:1,min:0,buffer:!0},metalness:{type:"range",step:.01,max:1,min:0,buffer:!0},diffuse:{type:"color",buffer:!0},diffuseInterior:{type:"boolean",buffer:!0},useInteriorColor:{type:"boolean",buffer:!0},interiorColor:{type:"color",buffer:!0},interiorDarkening:{type:"range",step:.01,max:1,min:0,buffer:!0},matrix:{type:"hidden",buffer:!0},disablePicking:{type:"boolean",rebuild:!0}},this.viewer=e,this.tasks=new ui,this.queue=new Nr(this.make.bind(this)),this.bufferList=[],this.parameters.colorScheme&&(this.parameters.colorScheme.options=Fe.getSchemes()),this.toBePrepared=!1}init(t){const r=t||{};this.clipNear=st(r.clipNear,0),this.clipRadius=st(r.clipRadius,0),this.clipCenter=st(r.clipCenter,new e),this.flatShaded=st(r.flatShaded,!1),this.side=st(r.side,"double"),this.opacity=st(r.opacity,1),this.depthWrite=st(r.depthWrite,!0),this.wireframe=st(r.wireframe,!1),this.setColor(r.color,r),this.colorData=st(r.colorData,void 0),this.colorScheme=st(r.colorScheme,"uniform"),this.colorScale=st(r.colorScale,""),this.colorReverse=st(r.colorReverse,!1),this.colorValue=st(r.colorValue,9474192),this.colorDomain=st(r.colorDomain,void 0),this.colorMode=st(r.colorMode,"hcl"),this.visible=st(r.visible,!0),this.quality=st(r.quality,void 0),this.roughness=st(r.roughness,.4),this.metalness=st(r.metalness,0),this.diffuse=st(r.diffuse,16777215),this.diffuseInterior=st(r.diffuseInterior,!1),this.useInteriorColor=st(r.useInteriorColor,!1),this.interiorColor=st(r.interiorColor,2236962),this.interiorDarkening=st(r.interiorDarkening,0),this.lazy=st(r.lazy,!1),this.lazyProps={build:!1,bufferParams:{},what:{}},this.matrix=st(r.matrix,new i),this.disablePicking=st(r.disablePicking,!1);const s=this.parameters;!0===s.sphereDetail&&(s.sphereDetail={type:"integer",max:3,min:0,rebuild:"impostor"}),!0===s.radialSegments&&(s.radialSegments={type:"integer",max:25,min:5,rebuild:"impostor"}),!0===s.openEnded&&(s.openEnded={type:"boolean",rebuild:"impostor",buffer:!0}),!0===s.disableImpostor&&(s.disableImpostor={type:"boolean",rebuild:!0}),"low"===r.quality?(s.sphereDetail&&(this.sphereDetail=0),s.radialSegments&&(this.radialSegments=5)):"medium"===r.quality?(s.sphereDetail&&(this.sphereDetail=1),s.radialSegments&&(this.radialSegments=10)):"high"===r.quality?(s.sphereDetail&&(this.sphereDetail=2),s.radialSegments&&(this.radialSegments=20)):(s.sphereDetail&&(this.sphereDetail=st(r.sphereDetail,1)),s.radialSegments&&(this.radialSegments=st(r.radialSegments,10))),s.openEnded&&(this.openEnded=st(r.openEnded,!0)),s.disableImpostor&&(this.disableImpostor=st(r.disableImpostor,!1))}getColorParams(t){return Object.assign({data:this.colorData,scheme:this.colorScheme,scale:this.colorScale,reverse:this.colorReverse,value:this.colorValue,domain:this.colorDomain,mode:this.colorMode,colorSpace:this.colorSpace},t)}getBufferParams(t={}){return Object.assign({clipNear:this.clipNear,clipRadius:this.clipRadius,clipCenter:this.clipCenter,flatShaded:this.flatShaded,opacity:this.opacity,depthWrite:this.depthWrite,side:this.side,wireframe:this.wireframe,roughness:this.roughness,metalness:this.metalness,diffuse:this.diffuse,diffuseInterior:this.diffuseInterior,useInteriorColor:this.useInteriorColor,interiorColor:this.interiorColor,interiorDarkening:this.interiorDarkening,matrix:this.matrix,disablePicking:this.disablePicking},t)}setColor(t,e){const i=Object.keys(Fe.getSchemes());if("string"==typeof t&&i.includes(t.toLowerCase()))e?e.colorScheme=t:this.setParameters({colorScheme:t});else if(void 0!==t){let i=new s(t).getHex();e?(e.colorScheme="uniform",e.colorValue=i):this.setParameters({colorScheme:"uniform",colorValue:i})}return this}prepare(t){}create(){}update(t){this.build()}build(t){if(!this.lazy||this.visible&&this.opacity){if(!this.toBePrepared)return this.tasks.increment(),void this.make();this.queue.length()>0?(this.tasks.change(1-this.queue.length()),this.queue.kill()):this.tasks.increment(),this.queue.push(t||!1)}else this.lazyProps.build=!0}make(t,e){De&&Me.time("Representation.make "+this.type);const i=()=>{t?(this.update(t),this.viewer.requestRender(),this.tasks.decrement(),e&&e()):(this.clear(),this.create(),this.manualAttach||this.disposed||(De&&Me.time("Representation.attach "+this.type),this.attach((()=>{De&&Me.timeEnd("Representation.attach "+this.type),this.tasks.decrement(),e&&e()})))),De&&Me.timeEnd("Representation.make "+this.type)};this.toBePrepared?this.prepare(i):i()}attach(t){this.setVisibility(this.visible),t()}setVisibility(t,e){if(this.visible=t,this.visible&&this.opacity){const t=this.lazyProps,e=t.bufferParams,i=t.what;if(t.build)return t.build=!1,this.build(),this;(Object.keys(e).length||Object.keys(i).length)&&(t.bufferParams={},t.what={},this.updateParameters(e,i))}return this.bufferList.forEach((function(e){e.setVisibility(t)})),e||this.viewer.requestRender(),this}setParameters(t,e={},i=!1){const r=t||{},s=this.parameters,n={};this.opacity||void 0===r.opacity||(this.lazyProps.build?(this.lazyProps.build=!1,i=!0):(Object.assign(n,this.lazyProps.bufferParams),Object.assign(e,this.lazyProps.what),this.lazyProps.bufferParams={},this.lazyProps.what={})),this.setColor(r.color,r);for(let t in r)if(void 0!==r[t]&&null!=s[t]&&(s[t].int&&(r[t]=parseInt(r[t])),s[t].float&&(r[t]=parseFloat(r[t])),r[t]!==this[t]||r[t].equals&&!r[t].equals(this[t]))){if(this[t]&&this[t].copy&&r[t].copy?this[t].copy(r[t]):this[t]&&this[t].set?this[t].set(r[t]):this[t]=r[t],s[t].buffer)if(!0===s[t].buffer)n[t]=r[t];else{n[s[t].buffer]=r[t]}s[t].update&&(e[s[t].update]=!0),!s[t].rebuild||"impostor"===s[t].rebuild&&Ie&&!this.disableImpostor||(i=!0)}return i?this.build():this.updateParameters(n,e),this}updateParameters(t={},e){if(this.lazy&&(!this.visible||!this.opacity)&&!1===t.hasOwnProperty("opacity"))return Object.assign(this.lazyProps.bufferParams,t),void Object.assign(this.lazyProps.what,e);this.bufferList.forEach((function(e){e.setParameters(t)})),Object.keys(e).length&&this.update(e),this.viewer.requestRender()}getParameters(){const t={lazy:this.lazy,visible:this.visible,quality:this.quality};return Object.keys(this.parameters).forEach((e=>{null!==this.parameters[e]&&(t[e]=this[e])})),t}clear(){this.bufferList.forEach((t=>{this.viewer.remove(t),t.dispose()})),this.bufferList.length=0,this.viewer.requestRender()}dispose(){this.disposed=!0,this.queue.kill(),this.tasks.dispose(),this.clear()}}class Vr{constructor(t){this.pending=0,this.postCount=0,this.onmessageDict={},this.onerrorDict={},this.name=t,this.blobUrl=window.URL.createObjectURL(Ee.get(t)),this.worker=new Worker(this.blobUrl),Ee.activeWorkerCount+=1,this.worker.onmessage=e=>{this.pending-=1;const i=e.data.__postId;De&&Me.timeEnd("Worker.postMessage "+t+" #"+i);const r=this.onmessageDict[i];r&&r.call(this.worker,e),delete this.onmessageDict[i],delete this.onerrorDict[i]},this.worker.onerror=e=>{if(this.pending-=1,e.data){const i=e.data.__postId,r=this.onerrorDict[i];r?r.call(this.worker,e):Me.error("Worker.onerror",i,t,e),delete this.onmessageDict[i],delete this.onerrorDict[i]}else Me.error("Worker.onerror",t,e)}}post(t={},e,i,r){this.onmessageDict[this.postCount]=i,this.onerrorDict[this.postCount]=r,t.__name=this.name,t.__postId=this.postCount,t.__debug=De,De&&Me.time(`Worker.postMessage ${this.name} #${this.postCount}`);try{this.worker.postMessage(t,e)}catch(e){Me.error("worker.post:",e),this.worker.postMessage(t)}return this.pending+=1,this.postCount+=1,this}terminate(){this.worker?(this.worker.terminate(),window.URL.revokeObjectURL(this.blobUrl),Ee.activeWorkerCount-=1):Me.log("no worker to terminate")}}class Gr{constructor(t,e=2){this.pool=[],this.count=0,this.maxCount=Math.min(8,e),this.name=t}post(t={},e,i,r){const s=this.getNextWorker();return s?s.post(t,e,i,r):console.error("unable to get worker from pool"),this}terminate(){this.pool.forEach((function(t){t.terminate()}))}getNextWorker(){let t,e=1/0;for(let i=0;i=this.count){t=new Vr(this.name),this.pool.push(t),this.count+=1;break}const r=this.pool[i];if(0===r.pending){t=r;break}r.pendings&&(s=c),l>n&&(n=l),h>o&&(o=h)}return[Yr([e,i,r]),Yr([s,n,o])]}function Wr(t,e){for(let i=0,r=e.length;i0){const o=1/Math.sqrt(n);t[e]=i*o,t[e+1]=r*o,t[e+2]=s*o}}}function Yr(t){return new Float32Array(t||3)}function Kr(t,e,i){const r=e[0],s=e[1],n=e[2],o=i[0],a=i[1],c=i[2];t[0]=s*c-n*a,t[1]=n*o-r*c,t[2]=r*a-s*o}function Zr(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}function Qr(t,e,i){t[0]=e[0]-i[0],t[1]=e[1]-i[1],t[2]=e[2]-i[2]}function Jr(t,e,i){t[0]=e[0]+i[0],t[1]=e[1]+i[1],t[2]=e[2]+i[2]}function ts(t,e,i=0){t[0]=e[i],t[1]=e[i+1],t[2]=e[i+2]}function es(t,e,i=0){e[i]=t[0],e[i+1]=t[1],e[i+2]=t[2]}function is(t){return t[0]*t[0]+t[1]*t[1]+t[2]*t[2]}function rs(t){return Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2])}function ss(t,e,i){ns(t,e,1/i)}function ns(t,e,i){t[0]=e[0]*i,t[1]=e[1]*i,t[2]=e[2]*i}function os(t,e){const i=is(e);0==i?(t[0]=e[0],t[1]=e[1],t[2]=e[2]):ns(t,e,1/Math.sqrt(i))}function as(t,e,i){t[0]=e[0]-i,t[1]=e[1]-i,t[2]=e[2]-i}function cs(t,e,i){t[0]=e[0]+i,t[1]=e[1]+i,t[2]=e[2]+i}function ls(t,e){t[0]=Math.floor(e[0]),t[1]=Math.floor(e[1]),t[2]=Math.floor(e[2])}function hs(t,e){t[0]=Math.ceil(e[0]),t[1]=Math.ceil(e[1]),t[2]=Math.ceil(e[2])}function ds(t,e){t[0]=-e[0],t[1]=-e[1],t[2]=-e[2]}function us(t,e){const i=t[0],r=t[1],s=t[2],n=e[0],o=e[1],a=e[2],c=r*a-s*o,l=s*n-i*a,h=i*o-r*n,d=Math.sqrt(c*c+l*l+h*h),u=i*n+r*o+s*a;return Math.atan2(d,u)}function ms(t,i=9){const r=Math.floor(i/2),s=t.position1.length/3,n=3*(r*s),o=1/i,a=_i(t.position1,t.position2),c=new Float32Array(n),l=new Float32Array(n),h=new e;for(let e=0;e0){const e=3*p;n[e]=t.position2[3*d-3],n[e+1]=t.position2[3*d-2],n[e+1]=t.position2[3*d-1]}const y=new Float32Array(s),b=new Float32Array(n),x=Ai(y,b),v=new Float32Array(o),w={position:x,position1:y,position2:b,color:v,color2:v};return a&&(w.radius=new Float32Array(a)),c&&t.picking&&(t.picking.array=new Float32Array(c),w.picking=t.picking),l&&(w.primitiveId=new Float32Array(l)),w}Gr.prototype.constructor=Gr,Hr.__deps=[Yr],ss.__deps=[ns],os.__deps=[ns,is];const gs=new e;class ys{static get Picker(){return He.get(this.type)}static get Buffer(){return je.get(this.type)}static getShapeKey(t){return this.type+t[0].toUpperCase()+t.substr(1)}static expandBoundingBox(t,e){}static valueToShape(t,e,i){const r=t._primitiveData[this.getShapeKey(e)];switch(this.fields[e]){case"v3":case"c":n=r,void 0!==(s=i).toArray?s=s.toArray():void 0!==s.x?s=[s.x,s.y,s.z]:void 0!==s.r&&(s=[s.r,s.g,s.b]),n.push.apply(n,s);break;default:r.push(i)}var s,n}static objectToShape(t,e){Object.keys(this.fields).forEach((i=>{this.valueToShape(t,i,e[i])})),this.valueToShape(t,"name",e.name),this.expandBoundingBox(t.boundingBox,e)}static valueFromShape(t,i,r){const n=t._primitiveData[this.getShapeKey(r)];switch(this.fields[r]){case"v3":return(new e).fromArray(n,3*i);case"c":return(new s).fromArray(n,3*i);default:return n[i]}}static objectFromShape(t,e){let i=this.valueFromShape(t,e,"name");void 0===i&&(i=`${this.type}: ${e} (${t.name})`);const r={shape:t,name:i};return Object.keys(this.fields).forEach((i=>{r[i]=this.valueFromShape(t,e,i)})),r}static arrayFromShape(t,e){const i=t._primitiveData[this.getShapeKey(e)];return"s"===this.fields[e]?i:new Float32Array(i)}static dataFromShape(t){const e={};return this.Picker&&(e.picking=new this.Picker(t)),Object.keys(this.fields).forEach((i=>{e[i]=this.arrayFromShape(t,i)})),e}static bufferFromShape(t,e){return new this.Buffer(this.dataFromShape(t),e)}}ys.type="",ys.fields={};class bs extends ys{static positionFromShape(t,e){return this.valueFromShape(t,e,"position")}static expandBoundingBox(t,e){t.expandByPoint(gs.fromArray(e.position))}}bs.type="sphere",bs.fields={position:"v3",color:"c",radius:"f"};class xs extends ys{static positionFromShape(t,e){return this.valueFromShape(t,e,"position")}static expandBoundingBox(t,e){t.expandByPoint(gs.fromArray(e.position))}}xs.type="box",xs.fields={position:"v3",color:"c",size:"f",heightAxis:"v3",depthAxis:"v3"};class vs extends xs{}vs.type="octahedron";class ws extends xs{}ws.type="tetrahedron";class As extends ys{static positionFromShape(t,e){const i=this.valueFromShape(t,e,"position1"),r=this.valueFromShape(t,e,"position2");return i.add(r).multiplyScalar(.5)}static expandBoundingBox(t,e){t.expandByPoint(gs.fromArray(e.position1)),t.expandByPoint(gs.fromArray(e.position2))}static bufferFromShape(t,e={}){let i=this.dataFromShape(t);return"cylinder"===this.type&&e.dashedCylinder&&(i=ps(i)),new this.Buffer(i,e)}}As.type="cylinder",As.fields={position1:"v3",position2:"v3",color:"c",radius:"f"};class _s extends As{}_s.type="arrow";class Ss extends As{}Ss.type="cone";class Cs extends bs{}Cs.type="ellipsoid",Cs.fields={position:"v3",color:"c",radius:"f",majorAxis:"v3",minorAxis:"v3"};class Ps extends Cs{}Ps.type="torus";class Is extends ys{static positionFromShape(t,e){return this.valueFromShape(t,e,"position")}static expandBoundingBox(t,e){t.expandByPoint(gs.fromArray(e.position))}}Is.type="text",Is.fields={position:"v3",color:"c",size:"f",text:"s"};class ks extends ys{static positionFromShape(t,e){return this.valueFromShape(t,e,"position")}static expandBoundingBox(t,e){t.expandByPoint(gs.fromArray(e.position))}}ks.type="point",ks.fields={position:"v3",color:"c"};class Ms extends ys{static positionFromShape(t,e){const i=this.valueFromShape(t,e,"position1"),r=this.valueFromShape(t,e,"position2");return i.add(r).multiplyScalar(.5)}static expandBoundingBox(t,e){t.expandByPoint(gs.fromArray(e.position1)),t.expandByPoint(gs.fromArray(e.position2))}}Ms.type="wideline",Ms.fields={position1:"v3",position2:"v3",color:"c"};class Ts{constructor(t,e){this.exp=3;const i=e||function(t){const{x:e,y:i,z:r}=t,s=new a,n=e.length,{min:o,max:c}=s;for(let t=0;t>this.exp),this.boundY=1+(i.max.y-this.minY>>this.exp),this.boundZ=1+(i.max.z-this.minZ>>this.exp);const r=this.boundX*this.boundY*this.boundZ,s=void 0!==t.count?t.count:t.x.length,n=t.x,o=t.y,c=t.z;let l=0;const h=new Uint32Array(r),d=new Int32Array(s);for(let t=0;t>this.exp,i=o[t]-this.minY>>this.exp,r=c[t]-this.minZ>>this.exp,s=(e*this.boundY+i)*this.boundZ+r;1===(h[s]+=1)&&(l+=1),d[t]=s}const u=new Uint16Array(l);for(let t=0,e=0;t0&&(h[t]=e+1,u[e]=i,e+=1)}const m=new Uint32Array(l);for(let t=1;t0){const i=e-1;f[m[i]+p[i]]=t,p[i]+=1}}this.grid=h,this.bucketCount=u,this.bucketOffset=m,this.bucketArray=f,this.xArray=n,this.yArray=o,this.zArray=c}within(t,e,i,r){const s=[];return this.eachWithin(t,e,i,r,(t=>s.push(t))),s}eachWithin(t,e,i,r,s){const n=r*r,o=Math.max(0,t-r-this.minX>>this.exp),a=Math.max(0,e-r-this.minY>>this.exp),c=Math.max(0,i-r-this.minZ>>this.exp),l=Math.min(this.boundX,1+(t+r-this.minX>>this.exp)),h=Math.min(this.boundY,1+(e+r-this.minY>>this.exp)),d=Math.min(this.boundZ,1+(i+r-this.minZ>>this.exp));for(let r=o;r0){const r=l-1,o=this.bucketOffset[r],a=o+this.bucketCount[r];for(let r=o;rr?s.set(this[e].subarray(0,r)):s.set(this[e]),this[e]=s}}growIfFull(){if(this.count>=this.length){const t=Math.round(1.5*this.length);this.resize(Math.max(256,t))}}copyFrom(t,e,i,r){for(let s=0,n=this._fields.length;s0;)h-=1;l<=h&&(l===c?c=h:h===c&&(c=l),(o=l)!==(a=h)&&(i.copyFrom(e,0,o,1),e.copyWithin(o,a,1),e.copyFrom(i,a,0,1)),l+=1,h-=1)}while(l<=h);r(s,h),r(l,n)}var o,a}(0,this.count-1),Me.timeEnd("Store.sort")}clear(){this.count=0}dispose(){for(let t=0,e=this._fields.length;t>>1&1431655765))+(t>>>2&858993459))+(t>>>4)&252645135)>>>24}class Os{constructor(t,e){this.length=t,this._words=new Uint32Array(t+32>>>5),!0===e&&this.setAll()}get(t){return 0!=(this._words[t>>>5]&1<>>5]|=1<>>5]&=~(1<>>5]^=1<>>5,o=e>>>5;for(let t=n+1;t>>5]|=1<>>5]|=1<>>5]|=1<>>5]&=~(1<>>5]&=~(1<>>5]&=~(1<>>5]|=1<>>5]&=~(1<>>i,this}_isRangeValue(t,e,i){if(e>>5,o=e>>>5;for(let t=n+1;t>>5]&1<>>5]&1<>>5]&1<>>5]&1<>>5]&1<0){const{types:r,groups:s,centers:n,atomSets:o}=t;r.push(e.type),s.push(e.group),n.x.push(e.x/i),n.y.push(e.y/i),n.z.push(e.z/i),o.push(e.atomSet)}}const Ns=0,zs=["D-BETA-PEPTIDE, C-GAMMA LINKING","D-GAMMA-PEPTIDE, C-DELTA LINKING","D-PEPTIDE COOH CARBOXY TERMINUS","D-PEPTIDE NH3 AMINO TERMINUS","D-PEPTIDE LINKING","L-BETA-PEPTIDE, C-GAMMA LINKING","L-GAMMA-PEPTIDE, C-DELTA LINKING","L-PEPTIDE COOH CARBOXY TERMINUS","L-PEPTIDE NH3 AMINO TERMINUS","L-PEPTIDE LINKING","PEPTIDE LINKING","PEPTIDE-LIKE"],Vs=["RNA OH 3 PRIME TERMINUS","RNA OH 5 PRIME TERMINUS","RNA LINKING"],Gs=["DNA OH 3 PRIME TERMINUS","DNA OH 5 PRIME TERMINUS","DNA LINKING","L-DNA LINKING","L-RNA LINKING"],Us=["D-SACCHARIDE","D-SACCHARIDE 1,4 AND 1,4 LINKING","D-SACCHARIDE 1,4 AND 1,6 LINKING","L-SACCHARIDE","L-SACCHARIDE 1,4 AND 1,4 LINKING","L-SACCHARIDE 1,4 AND 1,6 LINKING","SACCHARIDE"],js=["NON-POLYMER"].concat(["OTHER"],Us),Hs=["h","g","i"],Ws=["e","b"],qs=["s","t","l",""],Xs={H:1,D:1,T:1,HE:2,LI:3,BE:4,B:5,C:6,N:7,O:8,F:9,NE:10,NA:11,MG:12,AL:13,SI:14,P:15,S:16,CL:17,AR:18,K:19,CA:20,SC:21,TI:22,V:23,CR:24,MN:25,FE:26,CO:27,NI:28,CU:29,ZN:30,GA:31,GE:32,AS:33,SE:34,BR:35,KR:36,RB:37,SR:38,Y:39,ZR:40,NB:41,MO:42,TC:43,RU:44,RH:45,PD:46,AG:47,CD:48,IN:49,SN:50,SB:51,TE:52,I:53,XE:54,CS:55,BA:56,LA:57,CE:58,PR:59,ND:60,PM:61,SM:62,EU:63,GD:64,TB:65,DY:66,HO:67,ER:68,TM:69,YB:70,LU:71,HF:72,TA:73,W:74,RE:75,OS:76,IR:77,PT:78,AU:79,HG:80,TL:81,PB:82,BI:83,PO:84,AT:85,RN:86,FR:87,RA:88,AC:89,TH:90,PA:91,U:92,NP:93,PU:94,AM:95,CM:96,BK:97,CF:98,ES:99,FM:100,MD:101,NO:102,LR:103,RF:104,DB:105,SG:106,BH:107,HS:108,MT:109,DS:110,RG:111,CN:112,NH:113,FL:114,MC:115,LV:116,TS:117,OG:118},Ys={1:1.1,2:1.4,3:1.81,4:1.53,5:1.92,6:1.7,7:1.55,8:1.52,9:1.47,10:1.54,11:2.27,12:1.73,13:1.84,14:2.1,15:1.8,16:1.8,17:1.75,18:1.88,19:2.75,20:2.31,21:2.3,22:2.15,23:2.05,24:2.05,25:2.05,26:2.05,27:2,28:2,29:2,30:2.1,31:1.87,32:2.11,33:1.85,34:1.9,35:1.83,36:2.02,37:3.03,38:2.49,39:2.4,40:2.3,41:2.15,42:2.1,43:2.05,44:2.05,45:2,46:2.05,47:2.1,48:2.2,49:2.2,50:1.93,51:2.17,52:2.06,53:1.98,54:2.16,55:3.43,56:2.68,57:2.5,58:2.48,59:2.47,60:2.45,61:2.43,62:2.42,63:2.4,64:2.38,65:2.37,66:2.35,67:2.33,68:2.32,69:2.3,70:2.28,71:2.27,72:2.25,73:2.2,74:2.1,75:2.05,76:2,77:2,78:2.05,79:2.1,80:2.05,81:1.96,82:2.02,83:2.07,84:1.97,85:2.02,86:2.2,87:3.48,88:2.83,89:2,90:2.4,91:2,92:2.3,93:2,94:2,95:2,96:2,97:2,98:2,99:2,100:2,101:2,102:2,103:2,104:2,105:2,106:2,107:2,108:2,109:2,110:2,111:2,112:2,113:2,114:2,115:2,116:2,117:2,118:2},Ks={1:.31,2:.28,3:1.28,4:.96,5:.84,6:.76,7:.71,8:.66,9:.57,10:.58,11:1.66,12:1.41,13:1.21,14:1.11,15:1.07,16:1.05,17:1.02,18:1.06,19:2.03,20:1.76,21:1.7,22:1.6,23:1.53,24:1.39,25:1.39,26:1.32,27:1.26,28:1.24,29:1.32,30:1.22,31:1.22,32:1.2,33:1.19,34:1.2,35:1.2,36:1.16,37:2.2,38:1.95,39:1.9,40:1.75,41:1.64,42:1.54,43:1.47,44:1.46,45:1.42,46:1.39,47:1.45,48:1.44,49:1.42,50:1.39,51:1.39,52:1.38,53:1.39,54:1.4,55:2.44,56:2.15,57:2.07,58:2.04,59:2.03,60:2.01,61:1.99,62:1.98,63:1.98,64:1.96,65:1.94,66:1.92,67:1.92,68:1.89,69:1.9,70:1.87,71:1.87,72:1.75,73:1.7,74:1.62,75:1.51,76:1.44,77:1.41,78:1.36,79:1.36,80:1.32,81:1.45,82:1.46,83:1.48,84:1.4,85:1.5,86:1.5,87:2.6,88:2.21,89:2.15,90:2.06,91:2,92:1.96,93:1.9,94:1.87,95:1.8,96:1.69,97:1.6,98:1.6,99:1.6,100:1.6,101:1.6,102:1.6,103:1.6,104:1.6,105:1.6,106:1.6,107:1.6,108:1.6,109:1.6,110:1.6,111:1.6,112:1.6,113:1.6,114:1.6,115:1.6,116:1.6,117:1.6,118:1.6},Zs={1:[1],2:[0],3:[1],4:[2],5:[3],6:[4],7:[3],8:[2],9:[1],10:[0],11:[1],12:[2],13:[6],14:[6],15:[3,5,7],16:[2,4,6],17:[1],18:[0],19:[1],20:[2],31:[3],32:[4],33:[3,5],34:[2,4,6],35:[1],36:[0],37:[1],38:[2],49:[3],50:[4],51:[3,5],52:[2],53:[1,2,5],54:[0,2],55:[1],56:[2],81:[3],82:[4],83:[3],84:[2],85:[1],86:[0],87:[1],88:[2]},Qs={1:1,2:2,3:1,4:2,5:3,6:4,7:5,8:6,9:7,10:8,11:1,12:2,13:3,14:4,15:5,16:6,17:7,18:8,19:1,20:2,21:3,22:4,23:5,24:6,25:7,26:8,27:9,28:10,29:11,30:2,31:3,32:4,33:5,34:6,35:7,36:8,37:1,38:2,39:3,40:4,41:5,42:6,43:7,44:8,45:9,46:10,47:11,48:2,49:3,50:4,51:5,52:6,53:7,54:8,55:1,56:2,57:3,58:4,59:3,60:4,61:5,62:6,63:7,64:8,65:9,66:10,67:11,68:12,69:13,70:14,71:15,72:4,73:5,74:6,75:7,76:8,77:9,78:10,79:11,80:2,81:3,82:4,83:5,84:6,85:7,86:8,87:1,88:2,89:3,90:4,91:3,92:4,93:5,94:6,95:7,96:8,97:9,98:10,99:11,100:12,101:13,102:14,103:15,104:2,105:2,106:2,107:2,108:2,109:2,110:2,111:2,112:2,113:3,114:4,115:5,116:6,117:7,118:8},Js={ALA:[.17,.5,.33],ARG:[.81,1.81,1],ASN:[.42,.85,.43],ASP:[1.23,3.64,2.41],ASH:[-.07,.43,.5],CYS:[-.24,-.02,.22],GLN:[.58,.77,.19],GLU:[2.02,3.63,1.61],GLH:[-.01,.11,.12],GLY:[.01,1.15,1.14],HIS:[.17,.11,-.06],ILE:[-.31,-1.12,-.81],LEU:[-.56,-1.25,-.69],LYS:[.99,2.8,1.81],MET:[-.23,-.67,-.44],PHE:[-1.13,-1.71,-.58],PRO:[.45,.14,-.31],SER:[.13,.46,.33],THR:[.14,.25,.11],TRP:[-1.85,-2.09,-.24],TYR:[-.94,-.71,.23],VAL:[.07,-.46,-.53]},tn=[0,0,0],en={HIS:"H",ARG:"R",LYS:"K",ILE:"I",PHE:"F",LEU:"L",TRP:"W",ALA:"A",MET:"M",PRO:"P",CYS:"C",ASN:"N",VAL:"V",GLY:"G",SER:"S",GLN:"Q",TYR:"Y",ASP:"D",GLU:"E",THR:"T",SEC:"U",PYL:"O"},rn=Object.keys(en),sn=["A","C","T","G","U","I"],nn=["DA","DC","DT","DG","DU","DI"],on=["A","G","I","DA","DG","DI"],an=sn.concat(nn),cn=["SOL","WAT","HOH","H2O","W","DOD","D3O","TIP3","TIP4","SPC"],ln=["118","119","1AL","1CU","2FK","2HP","2OF","3CO","3MT","3NI","3OF","3P8","4MO","4PU","543","6MO","ACT","AG","AL","ALF","AM","ATH","AU","AU3","AUC","AZI","BA","BCT","BEF","BF4","BO4","BR","BS3","BSY","CA","CAC","CD","CD1","CD3","CD5","CE","CHT","CL","CO","CO3","CO5","CON","CR","CS","CSB","CU","CU1","CU3","CUA","CUZ","CYN","DME","DMI","DSC","DTI","DY","E4N","EDR","EMC","ER3","EU","EU3","F","FE","FE2","FPO","GA","GD3","GEP","HAI","HG","HGC","IN","IOD","IR","IR3","IRI","IUM","K","KO4","LA","LCO","LCP","LI","LU","MAC","MG","MH2","MH3","MLI","MLT","MMC","MN","MN3","MN5","MN6","MO1","MO2","MO3","MO4","MO5","MO6","MOO","MOS","MOW","MW1","MW2","MW3","NA","NA2","NA5","NA6","NAO","NAW","NCO","NET","NH4","NI","NI1","NI2","NI3","NO2","NO3","NRU","O4M","OAA","OC1","OC2","OC3","OC4","OC5","OC6","OC7","OC8","OCL","OCM","OCN","OCO","OF1","OF2","OF3","OH","OS","OS4","OXL","PB","PBM","PD","PDV","PER","PI","PO3","PO4","PR","PT","PT4","PTN","RB","RH3","RHD","RU","SB","SCN","SE4","SEK","SM","SMO","SO3","SO4","SR","T1A","TB","TBA","TCN","TEA","TH","THE","TL","TMA","TRA","UNX","V","VN3","VO4","W","WO5","Y1","YB","YB2","YH","YT3","ZCM","ZN","ZN2","ZN3","ZNO","ZO3","OHX"],hn=["045","0AT","0BD","0MK","0NZ","0TS","0V4","0XY","0YT","10M","147","149","14T","15L","16G","18T","18Y","1AR","1BW","1GL","1GN","1JB","1LL","1NA","1S3","26M","26Q","26R","26V","26W","26Y","27C","289","291","293","2DG","2F8","2FG","2FL","2FP","2GL","2M4","2M5","32O","34V","3CM","3DO","3DY","3FM","3LR","3MF","3MG","3SA","3ZW","46D","46M","46Z","48Z","4CQ","4GC","4NN","50A","5DI","5GF","5MM","5RP","5SA","5SP","64K","6PG","6SA","7JZ","7SA","A1Q","A2G","AAB","AAL","AAO","ABC","ABD","ABE","ABF","ABL","ACG","ACI","ACR","ACX","ADA","ADG","ADR","AF1","AFD","AFL","AFO","AFP","AFR","AGC","AGH","AGL","AHR","AIG","ALL","ALX","AMU","AOG","AOS","ARA","ARB","ARE","ARI","ASG","ASO","AXP","AXR","B0D","B16","B2G","B4G","B6D","B8D","B9D","BBK","BCD","BDG","BDP","BDR","BEM","BFP","BGC","BGL","BGP","BGS","BHG","BMA","BMX","BNG","BNX","BOG","BRI","BXF","BXP","BXX","BXY","C3X","C4X","C5X","CAP","CBI","CBK","CBS","CDR","CEG","CGF","CHO","CR1","CR6","CRA","CT3","CTO","CTR","CTT","D6G","DAF","DAG","DDA","DDB","DDL","DEL","DFR","DFX","DG0","DGC","DGD","DGM","DGS","DIG","DLF","DLG","DMU","DNO","DOM","DP5","DQQ","DQR","DR2","DR3","DR4","DRI","DSR","DT6","DVC","E4P","E5G","EAG","EBG","EBQ","EGA","EJT","EPG","ERE","ERI","F1P","F1X","F6P","FBP","FCA","FCB","FCT","FDP","FDQ","FFC","FIX","FMO","FRU","FSI","FU4","FUB","FUC","FUD","FUL","FXP","G16","G1P","G2F","G3I","G4D","G4S","G6D","G6P","G6S","GAC","GAD","GAL","GC1","GC4","GCD","GCN","GCO","GCS","GCT","GCU","GCV","GCW","GCX","GE1","GFG","GFP","GIV","GL0","GL2","GL5","GL6","GL7","GL9","GLA","GLB","GLC","GLD","GLF","GLG","GLO","GLP","GLS","GLT","GLW","GMH","GN1","GNX","GP1","GP4","GPH","GPM","GQ1","GQ2","GQ4","GS1","GS4","GSA","GSD","GTE","GTH","GTK","GTR","GTZ","GU0","GU1","GU2","GU3","GU4","GU5","GU6","GU8","GU9","GUF","GUP","GUZ","GYP","GYV","H2P","HDL","HMS","HS2","HSD","HSG","HSH","HSJ","HSQ","HSR","HSU","HSX","HSY","HSZ","IAB","IDG","IDR","IDS","IDT","IDU","IDX","IDY","IMK","IN1","IPT","ISL","KBG","KD2","KDA","KDM","KDO","KFN","KO1","KO2","KTU","L6S","LAG","LAI","LAK","LAO","LAT","LB2","LBT","LCN","LDY","LGC","LGU","LM2","LMT","LMU","LOG","LOX","LPK","LSM","LTM","LVZ","LXB","LXZ","M1F","M3M","M6P","M8C","MA1","MA2","MA3","MAB","MAG","MAL","MAN","MAT","MAV","MAW","MBG","MCU","MDA","MDM","MDP","MFA","MFB","MFU","MG5","MGA","MGL","MLB","MMA","MMN","MN0","MRP","MTT","MUG","MVP","MXY","N1L","N9S","NAA","NAG","NBG","NDG","NED","NG1","NG6","NGA","NGB","NGC","NGE","NGF","NGL","NGS","NGY","NHF","NM6","NM9","NTF","NTO","NTP","NXD","NYT","OPG","OPM","ORP","OX2","P3M","P53","P6P","PA5","PNA","PNG","PNW","PRP","PSJ","PSV","PTQ","QDK","QPS","QV4","R1P","R1X","R2B","R5P","RAA","RAE","RAF","RAM","RAO","RAT","RB5","RBL","RCD","RDP","REL","RER","RF5","RG1","RGG","RHA","RIB","RIP","RNS","RNT","ROB","ROR","RPA","RST","RUB","RUU","RZM","S6P","S7P","SA0","SCR","SDD","SF6","SF9","SG4","SG5","SG6","SG7","SGA","SGC","SGD","SGN","SGS","SHB","SHG","SI3","SIO","SOE","SOL","SSG","SUC","SUP","SUS","T6P","T6T","TAG","TCB","TDG","TGK","TGY","TH1","TIA","TM5","TM6","TM9","TMR","TMX","TOA","TOC","TRE","TYV","UCD","UDC","VG1","X0X","X1X","X2F","X4S","X5S","X6X","XBP","XDN","XDP","XIF","XIM","XLF","XLS","XMM","XUL","XXR","XYP","XYS","YO5","Z3Q","Z6J","Z9M","ZDC","ZDM"],dn=["CA","C","N","O","O1","O2","OC1","OC2","OX1","OXT","OT1","OT2","H","H1","H2","H3","HA","HN","BB"],un=["P","OP1","OP2","HOP2","HOP3","O2'","O3'","O4'","O5'","C1'","C2'","C3'","C4'","C5'","H1'","H2'","H2''","HO2'","H3'","H4'","H5'","H5''","HO3'","HO5'","O2*","O3*","O4*","O5*","C1*","C2*","C3*","C4*","C5*"],mn={1:{trace:"CA",direction1:"C",direction2:["O","OC1","O1","OX1","OXT","OT1","OT2"],backboneStart:"N",backboneEnd:"C"},2:{trace:["C4'","C4*"],direction1:["C1'","C1*"],direction2:["C3'","C3*"],backboneStart:"P",backboneEnd:["O3'","O3*"]},3:{trace:["C3'","C3*"],direction1:["C2'","C2*"],direction2:["O4'","O4*"],backboneStart:"P",backboneEnd:["O3'","O3*"]},4:{trace:["CA","BB"],backboneStart:["CA","BB"],backboneEnd:["CA","BB"]},5:{trace:["C4'","C4*","P"],backboneStart:["C4'","C4*","P"],backboneEnd:["C4'","C4*","P"]},6:{trace:["C3'","C3*","C2'","P"],backboneStart:["C3'","C3*","C2'","P"],backboneEnd:["C3'","C3*","C2'","P"]}};mn[Ns]={};const pn={HD:"H",HS:"H",A:"C",NA:"N",NS:"N",OA:"O",OS:"O",SA:"S",G0:"C",G1:"C",G2:"C",G3:"C",CG0:"C",CG1:"C",CG2:"C",CG3:"C",W:"O"};function fn(t){switch(t){case 0:return 0;case 1:return 1;case 2:return 2;case 3:return 3;case 4:return 4;default:return 8}}const gn=new Map([[2,kt(180)],[3,kt(120)],[4,kt(109.4721)],[6,kt(90)]]);function yn(t,i){let r=[];const s=new e,n=new e;return s.subVectors(i,t),t.eachBondedAtom((e=>{1!==e.number&&(n.subVectors(e,t),r.push(s.angleTo(n)))})),r}function bn(t,i){const r=t.clone(),s=new e;s.subVectors(i,t);const n=[new e,new e];let o=0;if(t.eachBondedAtom((e=>{o>1||1!==e.number&&(r.index=e.index,n[o++].subVectors(e,t))})),1===o&&r.eachBondedAtom((e=>{o>1||1!==e.number&&e.index!==t.index&&n[o++].subVectors(e,t)})),2!==o)return;const a=n[0].cross(n[1]);return Math.abs(Math.PI/2-a.angleTo(s))}function xn(t,e){const i=t.structure,r=i.atomCount,s=new Int8Array(r),n=new Int8Array(r),o=new Int8Array(r),a=new Int8Array(r);return i.eachAtom((t=>{const i=t.index,[r,c,l,h]=function(t,e){const i=t.bondToElementCount(1);let r=t.formalCharge||0;const s="always"===e.assignCharge||"auto"===e.assignCharge&&0===r,n="always"===e.assignH||"auto"===e.assignH&&0===i,o=t.bondCount,a=function(t){let e=0;return t.eachBond((t=>e+=t.bondOrder)),e}(t),c=function(t){const e=t.structure.getBondProxy(),i=t.number,r=8===i||7===i;if(r&&4===t.bondCount)return!1;let s=!1;return t.eachBond((i=>{if(i.bondOrder>1)s=!0;else if(r){const r=i.getOtherAtom(t);r.eachBond((t=>{if(t.bondOrder>1){const e=r.number;if((15===e||16===e)&&8===t.getOtherAtom(r).number)return;s=!0}}),e)}})),s}(t),l=a-o>0;let h=0,d=8;switch(t.number){case 1:s&&(0===o?(r=1,d=0):1===o&&(r=0,d=1));break;case 6:s&&(r=0),n&&(h=Math.max(0,4-a-Math.abs(r))),d=fn(o+h+Math.max(0,-r));break;case 7:if(s)if(n)if(c&&a<4)r=o-i==1&&a-i==2?1:0;else{let e=!1;t.eachBondedAtom((t=>{(16===t.number||t.isMetal())&&(e=!0)})),r=e?0:1}else r=a-3;n&&(h=Math.max(0,3-a+r)),d=fn(c&&!l?o+h-r:o+h+1-r);break;case 8:s&&(n||(r=a-2),1===a&&t.eachBondedAtom((e=>{e.eachBond((i=>{const s=i.getOtherAtom(e);s.index!==t.index&&8===s.number&&2===i.bondOrder&&(r=-1)}))}))),n&&(h=Math.max(0,2-a+r)),d=fn(c&&!l?o+h-r+1:o+h-r+2);break;case 16:s&&(n||(r=a<=3&&!t.bondToElementCount(8)?a-2:0)),n&&a<2&&(h=Math.max(0,2-a+r)),a<=3&&(d=fn(o+h-r+2));break;case 9:case 17:case 35:case 53:case 85:s&&(r=a-1);break;case 3:case 11:case 19:case 37:case 55:case 87:s&&(r=1-a);break;case 4:case 12:case 20:case 38:case 56:case 88:s&&(r=2-a);break;default:console.warn("Requested charge, protonation for an unhandled element",t.element)}return[r,h,h+i,d]}(t,e);s[i]=r,n[i]=c,o[i]=l,a[i]=h})),{charge:s,implicitH:n,totalH:o,idealGeometry:a}}function vn(t){if(t["@valenceModel"])return t["@valenceModel"];const e=xn(t,{assignCharge:"auto",assignH:"auto"});return t["@valenceModel"]=e,e}function wn(t){return 15===t.number&&t.bondToElementCount(8)===t.bondCount}const An=["ARG","HIS","LYS"],_n=["GLU","ASP"];function Sn(t,e){return 2===t&&1===e||1===t&&2===e}function Cn(t,e){return 3===t&&3===e}function Pn(t,e){return 3===t&&1===e||1===t&&3===e}function In(t){return"HIS"===t.resname&&7==t.number&&t.isRing()}function kn(t,e){return 5===t&&4===e||4===t&&5===e}function Mn(t,e){return 9===t&&5===e||5===t&&9===e}const Tn=[3,11,19,37,55,12,20,38,56,13,31,49,81,21,50,82,83,51,80];function Bn(t,e){return 12===t?11===e||12===e:13===t?10===e:void 0}const Dn=[17,35,53,85];const $n=[7,8,16],On=[6,7,15,16];const Rn=kt(180),En=kt(120);function Fn(t,e,i){return!Nn(t,e,i)&&(t.modelIndex!==e.modelIndex||t.altloc&&e.altloc&&t.altloc!==e.altloc)}const Ln={maxHydrophobicDist:4,maxHbondDist:3.5,maxHbondSulfurDist:4.1,maxHbondAccAngle:45,maxHbondDonAngle:45,maxHbondAccPlaneAngle:90,maxHbondDonPlaneAngle:30,maxPiStackingDist:5.5,maxPiStackingOffset:2,maxPiStackingAngle:30,maxCationPiDist:6,maxCationPiOffset:2,maxIonicDist:5,maxHalogenBondDist:4,maxHalogenBondAngle:30,maxMetalDist:3,refineSaltBridges:!0,masterModelIndex:-1,lineOfSightDistFactor:1};function Nn(t,e,i){return t.modelIndex===i&&e.modelIndex!==i||e.modelIndex===i&&t.modelIndex!==i}function zn(t,e,i){return!Nn(t,e,i)&&(t.modelIndex!==e.modelIndex||t.residueIndex===e.residueIndex||t.altloc&&e.altloc&&t.altloc!==e.altloc)}function Vn(t){const e={types:[],groups:[],centers:{x:[],y:[],z:[]},atomSets:[]};return De&&Me.time("calculateFeatures"),function(t,e){const{charge:i}=vn(t.data),r={};t.eachResidue((t=>{if(An.includes(t.resname)){const i=Es(1);t.eachAtom((t=>{7===t.number&&t.isSidechain()&&Fs(i,t)})),Ls(e,i)}else rn.includes(t.resname)||t.isNucleic()||(t.eachAtom((t=>{let i=!1;const s=Es(1);!function(t){let e=0;return 6===t.number&&3===t.bondCount&&3===t.bondToElementCount(7)&&t.eachBondedAtom((t=>{t.bondCount-t.bondToElementCount(1)==1&&++e})),2===e}(t)?function(t){let e=0;return 6===t.number&&3===t.bondCount&&2===t.bondToElementCount(7)&&1===t.bondToElementCount(6)&&t.eachBondedAtom((t=>{t.bondCount-t.bondToElementCount(1)==1&&++e})),2===e}(t)&&(s.group=9,i=!0):(s.group=8,i=!0),i&&(t.eachBondedAtom((t=>{7===t.number&&(r[t.index]=!0,Fs(s,t))})),Ls(e,s))})),t.eachAtom((t=>{const s=Es(1);i[t.index]>0&&(r[t.index]||(Fs(s,t),Ls(e,s)))})))}))}(t,e),function(t,e){const{charge:i}=vn(t.data),r={};t.eachResidue((t=>{if(_n.includes(t.resname)){const i=Es(2);t.eachAtom((t=>{8===t.number&&t.isSidechain()&&Fs(i,t)})),Ls(e,i)}else if(an.includes(t.resname)){const i=Es(2);t.eachAtom((t=>{wn(t)&&(i.group=6,t.eachBondedAtom((t=>{8===t.number&&Fs(i,t)})),Ls(e,i))}))}else rn.includes(t.resname)||an.includes(t.resname)||(t.eachAtom((t=>{let i=!1;const s=Es(2);!function(t){return 16===t.number&&3===t.bondToElementCount(8)}(t)?wn(t)?(s.group=6,i=!0):function(t){return 16===t.number&&4===t.bondToElementCount(8)}(t)?(s.group=5,i=!0):function(t){let e=0;return 6===t.number&&2===t.bondToElementCount(8)&&1===t.bondToElementCount(6)&&t.eachBondedAtom((t=>{8===t.number&&t.bondCount-t.bondToElementCount(1)==1&&++e})),2===e}(t)&&(s.group=10,i=!0):(s.group=4,i=!0),i&&(t.eachBondedAtom((t=>{8===t.number&&(r[t.index]=!0,Fs(s,t))})),Ls(e,s))})),t.eachAtom((t=>{const s=Es(2);i[t.index]<0&&(r[t.index]||(Fs(s,t),Ls(e,s)))})))}))}(t,e),function(t,e){const i=t.getAtomProxy();t.eachResidue((t=>{const r=t.getAromaticRings();if(r){const s=t.atomOffset;r.forEach((t=>{const r=Es(3);t.forEach((t=>{i.index=t+s,Fs(r,i)})),Ls(e,r)}))}}))}(t,e),function(t,e){const{charge:i,implicitH:r,idealGeometry:s}=vn(t.data);t.eachAtom((t=>{const n=Es(5),o=t.number;if(8===o)Fs(n,t),Ls(e,n);else if(7===o){if(In(t))Fs(n,t),Ls(e,n);else if(i[t.index]<1){const i=t.bondCount+r[t.index],o=s[t.index];(4===o&&i<4||3===o&&i<3||2===o&&i<2)&&(Fs(n,t),Ls(e,n))}}else 16===o&&("CYS"!==t.resname&&"MET"!==t.resname&&-1!==t.formalCharge||(Fs(n,t),Ls(e,n)))}))}(t,e),function(t,e){const{totalH:i}=vn(t.data);t.eachAtom((t=>{const r=Es(4),s=t.number;(In(t)||i[t.index]>0&&(7===s||8===s||16===s))&&(Fs(r,t),Ls(e,r))}))}(t,e),function(t,e){const{totalH:i}=vn(t.data);t.eachAtom((t=>{if(6===t.number&&i[t.index]>0&&(t.bondToElementCount(7)>0||t.bondToElementCount(8)>0||function(t){if(!t.isAromatic())return!1;const e=t.residueType.getRings();if(!e)return!1;let i=!1;return e.rings.forEach((e=>{i||e.some((e=>t.index-t.residueAtomOffset===e))&&(i=e.some((e=>{const i=t.residueType.atomTypeIdList[e],r=t.atomMap.get(i).number;return 7===r||8===r})))})),i}(t))){const i=Es(9);Fs(i,t),Ls(e,i)}}))}(t,e),function(t,e){t.eachAtom((t=>{let i=!1,r=!1;const s=rn.includes(t.resname),n=an.includes(t.resname);if(s||n?s?8===t.number?(["ASP","GLU","SER","THR","TYR","ASN","GLN"].includes(t.resname)&&t.isSidechain()||t.isBackbone())&&(i=!0,r=!0):16===t.number&&"CYS"===t.resname?(i=!0,r=!0):7===t.number&&"HIS"===t.resname&&t.isSidechain()&&(i=!0):n&&(8===t.number&&t.isBackbone()?(i=!0,r=!0):["N3","N4","N7"].includes(t.atomname)?i=!0:["O2","O4","O6"].includes(t.atomname)&&(i=!0,r=!0)):t.isHalogen()||8===t.number||16===t.number?(i=!0,r=!0):7===t.number&&(i=!0),i){const i=Es(11);Fs(i,t),Ls(e,i)}if(r){const i=Es(10);Fs(i,t),Ls(e,i)}}))}(t,e),function(t,e){t.eachAtom((t=>{if(t.isTransitionMetal()||30===t.number||48===t.number){const i=Es(12);Fs(i,t),Ls(e,i)}else if(Tn.includes(t.number)){const i=Es(13);Fs(i,t),Ls(e,i)}}))}(t,e),function(t,e){t.eachAtom((t=>{const i=Es(8);let r=!1;6===t.number?(r=!0,t.eachBondedAtom((t=>{const e=t.number;6!==e&&1!==e&&(r=!1)}))):9===t.number&&(r=!0),r&&(Fs(i,t),Ls(e,i))}))}(t,e),function(t,e){t.eachAtom((t=>{if($n.includes(t.number)){let i=!1;if(t.eachBondedAtom((t=>{On.includes(t.number)&&(i=!0)})),i){const i=Es(7);Fs(i,t),Ls(e,i)}}}))}(t,e),function(t,e){t.eachAtom((t=>{if(Dn.includes(t.number)&&1===t.bondToElementCount(6)){const i=Es(6);Fs(i,t),Ls(e,i)}}))}(t,e),De&&Me.timeEnd("calculateFeatures"),e}function Gn(t,i=Ln){const r=function(t){const{types:e,centers:i}=t;return{features:t,spatialHash:new Ts(i),contactStore:new Ds,featureSet:new Os(e.length,!1)}}(Vn(t));De&&Me.time("calculateContacts"),function(t,i,r={}){const s=st(r.maxIonicDist,Ln.maxIonicDist),n=st(r.maxPiStackingDist,Ln.maxPiStackingDist),o=st(r.maxPiStackingOffset,Ln.maxPiStackingOffset),a=st(r.maxPiStackingAngle,Ln.maxPiStackingAngle),c=st(r.maxCationPiDist,Ln.maxCationPiDist),l=st(r.maxCationPiOffset,Ln.maxCationPiOffset),h=st(r.masterModelIndex,Ln.masterModelIndex),d=Math.max(s+2,n,c),u=n*n,m=c*c,{features:p,spatialHash:f,contactStore:g,featureSet:y}=i,{types:b,centers:x,atomSets:v}=p,{x:w,y:A,z:_}=x,S=b.length,C=t.atomStore.x,P=t.atomStore.y,I=t.atomStore.z,k=t.getAtomProxy(),M=t.getAtomProxy(),T=function(t,e,i){const r=t.length,s=e.length;for(let n=0;n{if(e<=t)return;if(k.index=v[t][0],M.index=v[e][0],zn(k,M,h))return;const r=b[t],n=b[e];if(Sn(r,n))T(v[t],v[e],s)&&z(t,e,1);else if(Cn(r,n)){if(i<=u){L(v[t],E),L(v[e],F);const i=57.29578*E.angleTo(F);Math.min(N(t,e,F),N(e,t,E))<=o&&(i<=a||i>=180-a||i<=a+90&&i>=90-a)&&z(t,e,3)}}else if(Pn(r,n)&&i<=m){const[i,s]=3===r?[t,e]:[e,t];L(v[i],E),N(s,i,E)<=l&&z(i,s,2)}}))}(t,r,i),function(t,e,i={}){const r=st(i.maxHbondDist,Ln.maxHbondDist),s=st(i.maxHbondSulfurDist,Ln.maxHbondSulfurDist),n=kt(st(i.maxHbondAccAngle,Ln.maxHbondAccAngle)),o=kt(st(i.maxHbondDonAngle,Ln.maxHbondDonAngle)),a=kt(st(i.maxHbondAccPlaneAngle,Ln.maxHbondAccPlaneAngle)),c=kt(st(i.maxHbondDonPlaneAngle,Ln.maxHbondDonPlaneAngle)),l=st(i.masterModelIndex,Ln.masterModelIndex),h=Math.max(r,s),d=r*r,{features:u,spatialHash:m,contactStore:p,featureSet:f}=e,{types:g,centers:y,atomSets:b}=u,{x:x,y:v,z:w}=y,A=g.length,{idealGeometry:_}=vn(t.data),S=t.getAtomProxy(),C=t.getAtomProxy();for(let t=0;t{if(e<=t)return;const r=g[t],s=g[e],h=Mn(r,s);if(!h&&!kn(r,s))return;const[u,m]=5===s?[t,e]:[e,t];if(S.index=b[u][0],C.index=b[m][0],C.index===S.index)return;if(zn(S,C,l))return;if(16!==S.number&&16!==C.number&&i>d)return;if(S.connectedTo(C))return;const y=yn(S,C),x=gn.get(_[S.index])||kt(120);if(y.some((t=>Math.abs(x-t)>o)))return;if(3===_[S.index]){const t=bn(S,C);if(void 0!==t&&t>c)return}const v=yn(C,S),w=gn.get(_[C.index])||kt(120);if(v.some((t=>w-t>n)))return;if(3===_[C.index]){const t=bn(C,S);if(void 0!==t&&t>a)return}f.setBits(u,m);const A=h?8:function(t,e){return t.isWater()&&e.isWater()}(P=S,I=C)?9:function(t,e){return t.isBackbone()&&e.isBackbone()}(P,I)?10:4;var P,I;p.addContact(u,m,A)}))}(t,r,i),function(t,e,i={}){const r=st(i.maxMetalDist,Ln.maxMetalDist),s=st(i.masterModelIndex,Ln.masterModelIndex),{features:n,spatialHash:o,contactStore:a,featureSet:c}=e,{types:l,centers:h,atomSets:d}=n,{x:u,y:m,z:p}=h,f=l.length,g=t.getAtomProxy(),y=t.getAtomProxy();for(let t=0;t{if(e<=t)return;if(g.index=d[t][0],y.index=d[e][0],zn(g,y,s))return;const r=g.isMetal(),n=y.isMetal();if(!r&&!n)return;const[o,h]=r?[l[t],l[e]]:[l[e],l[t]];Bn(o,h)&&(c.setBits(t,e),a.addContact(t,e,7))}))}(t,r,i),function(t,e,i={}){const r=st(i.maxHydrophobicDist,Ln.maxHydrophobicDist),s=st(i.masterModelIndex,Ln.masterModelIndex),{features:n,spatialHash:o,contactStore:a,featureSet:c}=e,{types:l,centers:h,atomSets:d}=n,{x:u,y:m,z:p}=h,f=l.length,g=t.getAtomProxy(),y=t.getAtomProxy();for(let t=0;t{var r,n;e<=t||(g.index=d[t][0],y.index=d[e][0],zn(g,y,s)||9===g.number&&9===y.number||g.connectedTo(y)||(r=l[t],n=l[e],8===r&&8===n&&(c.setBits(t,e),a.addContact(t,e,6))))}))}(t,r,i),function(t,e,i={}){const r=st(i.maxHalogenBondDist,Ln.maxHalogenBondDist),s=kt(st(i.maxHalogenBondAngle,Ln.maxHalogenBondAngle)),n=st(i.masterModelIndex,Ln.masterModelIndex),{features:o,spatialHash:a,contactStore:c,featureSet:l}=e,{types:h,centers:d,atomSets:u}=o,{x:m,y:p,z:f}=d,g=h.length,y=t.getAtomProxy(),b=t.getAtomProxy();for(let t=0;t{if(e<=t)return;if(y.index=u[t][0],b.index=u[e][0],zn(y,b,n))return;if(r=h[t],o=h[e],!(7===r&&6===o||6===r&&7===o))return;var r,o;const[a,d]=6===h[t]?[y,b]:[b,y],m=yn(a,d);if(1!==m.length)return;if(Rn-m[0]>s)return;const p=yn(d,a);0!==p.length&&(p.some((t=>En-t>s))||(l.setBits(t,e),c.addContact(t,e,5)))}))}(t,r,i);const s=function(t){const{index1:e,index2:i,count:r}=t.contactStore,s=Rs({nodeArray1:e,nodeArray2:i,edgeCount:r,nodeCount:t.featureSet.length}),n=new Os(t.contactStore.count,!0);return Object.assign({adjacencyList:s,contactSet:n},t)}(r);return function(t,i,r={}){De&&Me.time("refineLineOfSight");const s=st(r.lineOfSightDistFactor,Ln.lineOfSightDistFactor),n=st(r.masterModelIndex,Ln.masterModelIndex),o=t.spatialHash,{contactSet:a,contactStore:c,features:l}=i,{index1:h,index2:d}=c,{centers:u,atomSets:m}=l,{x:p,y:f,z:g}=u,y=t.getAtomProxy(),b=t.getAtomProxy(),x=t.getAtomProxy(),v=new e,w=new e,A=3*s,_=s*s;a.forEach((t=>{v.set(p[h[t]],f[h[t]],g[h[t]]),w.set(p[d[t]],f[d[t]],g[d[t]]);const e=(v.x+w.x)/2,i=(v.y+w.y)/2,r=(v.z+w.z)/2,s=m[h[t]],c=m[d[t]];y.index=s[0],b.index=c[0],o.eachWithin(e,i,r,A,((e,i)=>{x.index=e,1!==x.number&&x.vdw*x.vdw*_>i&&!Fn(y,x,n)&&!Fn(b,x,n)&&!s.includes(e)&&!c.includes(e)&&v.distanceToSquared(x)>1&&w.distanceToSquared(x)>1&&(a.clear(t),De&&Me.log("removing",y.qualifiedName(),b.qualifiedName(),"because",x.qualifiedName()))}))})),De&&Me.timeEnd("refineLineOfSight")}(t,s,i),function(t,e){const{contactSet:i,contactStore:r,features:s}=e,{type:n,index1:o,index2:a}=r,{atomSets:c}=s,l=t.getAtomProxy(),h=t.getAtomProxy(),d={},u=function(t,e,r){const[s,n]=d[r]||[1/0,-1];t{if(6!==n[t])return;l.index=c[o[t]][0],h.index=c[a[t]][0];const e=l.distanceTo(h);u(e,t,`${l.index}|${h.residueIndex}`),u(e,t,`${h.index}|${l.residueIndex}`)}))}(t,s),i.refineSaltBridges&&function(t,e){const{contactSet:i,contactStore:r,features:s}=e,{type:n,index1:o,index2:a}=r,{atomSets:c}=s,l={},h=function(t,e){l[t]||(l[t]=[]),l[t].push(e)};i.forEach((t=>{1===n[t]&&(c[o[t]].forEach((e=>h(e,t))),c[a[t]].forEach((e=>h(e,t))))})),i.forEach((t=>{if(!function(t){return 4===t||9===t||10===t}(n[t]))return;const e=l[c[o[t]][0]],r=l[c[a[t]][0]];if(!e||!r)return;const s=e.length;for(let n=0;n{3===n[t]&&(c[o[t]].forEach((e=>h(e,t))),c[a[t]].forEach((e=>h(e,t))))})),i.forEach((t=>{if(6!==n[t]&&2!==n[t])return;const e=l[c[o[t]][0]],r=l[c[a[t]][0]];if(!e||!r)return;const s=e.length;for(let n=0;n{1===n[t]&&(c[o[t]].forEach((e=>h(e,t))),c[a[t]].forEach((e=>h(e,t))))})),i.forEach((t=>{if(7!==n[t])return;const e=l[c[o[t]][0]],r=l[c[a[t]][0]];if(!e||!r)return;const s=e.length;for(let t=0;te.getAtomSet(new pe(t)))):e.getAtomSet(new pe(r.filterSele))),o.forEach((t=>{const e=f[t];if(!s.includes(e))return;if(w){const e=l[m[t]][0],i=l[p[t]][0];if(Array.isArray(w)){if(!(w[0].isSet(e)&&w[1].isSet(i)||w[1].isSet(e)&&w[0].isSet(i)))return}else if(!w.isSet(e)&&!w.isSet(i))return}const i=m[t],n=p[t];g.push(h[i],d[i],u[i]),y.push(h[n],d[n],u[n]),b.push(...function(t){switch(t){case 4:case 9:case 10:return Hn.setHex(2851770).toArray();case 6:return Hn.setHex(8421504).toArray();case 5:return Hn.setHex(4259775).toArray();case 1:return Hn.setHex(15779860).toArray();case 7:return Hn.setHex(9191577).toArray();case 2:return Hn.setHex(16744448).toArray();case 3:return Hn.setHex(9220966).toArray();case 8:return Hn.setHex(12967404).toArray();default:return Hn.setHex(13421772).toArray()}}(e)),x.push(r.radius),v.push(t)})),{position1:new Float32Array(g),position2:new Float32Array(y),color:new Float32Array(b),color2:new Float32Array(b),radius:new Float32Array(x),picking:new Qn(v,t,e)}}class qn{constructor(t){this.array=t}get type(){return""}get data(){return{}}getIndex(t){return this.array?this.array[t]:t}getObject(t){return{}}_applyTransformations(t,e,i){return e&&t.applyMatrix4(e.matrix),i&&t.applyMatrix4(i.matrix),t}_getPosition(t){return new e}getPosition(t,e,i){return this._applyTransformations(this._getPosition(t),e,i)}}class Xn extends qn{constructor(t){super(),this.shape=t}get primitive(){}get data(){return this.shape}get type(){return this.primitive.type}getObject(t){return this.primitive.objectFromShape(this.shape,this.getIndex(t))}_getPosition(t){return this.primitive.positionFromShape(this.shape,this.getIndex(t))}}class Yn extends qn{constructor(t,e){super(t),this.structure=e}get type(){return"atom"}get data(){return this.structure}getObject(t){return this.structure.getAtomProxy(this.getIndex(t))}_getPosition(t){return(new e).copy(this.getObject(t))}}class Kn extends qn{constructor(t){super(),this.axes=t}get type(){return"axes"}get data(){return this.axes}getObject(){return{axes:this.axes}}_getPosition(){return this.axes.center.clone()}}class Zn extends qn{constructor(t,e,i){super(t),this.structure=e,this.bondStore=i||e.bondStore}get type(){return"bond"}get data(){return this.structure}getObject(t){const e=this.structure.getBondProxy(this.getIndex(t));return e.bondStore=this.bondStore,e}_getPosition(t){const i=this.getObject(t);return(new e).copy(i.atom1).add(i.atom2).multiplyScalar(.5)}}class Qn extends qn{constructor(t,e,i){super(t),this.contacts=e,this.structure=i}get type(){return"contact"}get data(){return this.contacts}getObject(t){const i=this.getIndex(t),{features:r,contactStore:s}=this.contacts,{centers:n,atomSets:o}=r,{x:a,y:c,z:l}=n,{index1:h,index2:d,type:u}=s,m=h[i],p=d[i];return{center1:new e(a[m],c[m],l[m]),center2:new e(a[p],c[p],l[p]),atom1:this.structure.getAtomProxy(o[m][0]),atom2:this.structure.getAtomProxy(o[p][0]),type:Un(u[i])}}_getPosition(t){const{center1:i,center2:r}=this.getObject(t);return(new e).addVectors(i,r).multiplyScalar(.5)}}class Jn extends qn{constructor(t,e,i){super(t),this.validation=e,this.structure=i}get type(){return"clash"}get data(){return this.validation}getObject(t){const e=this.validation,i=this.getIndex(t);return{validation:e,index:i,clash:e.clashArray[i]}}_getAtomProxyFromSele(t){const e=new pe(t),i=this.structure.getAtomIndices(e)[0];return this.structure.getAtomProxy(i)}_getPosition(t){const i=this.getObject(t).clash,r=this._getAtomProxyFromSele(i.sele1),s=this._getAtomProxyFromSele(i.sele2);return(new e).copy(r).add(s).multiplyScalar(.5)}}class to extends Zn{get type(){return"distance"}}class eo extends qn{get type(){return"ignore"}}class io extends Xn{constructor(t,e){super(t),this.mesh=e}get type(){return"mesh"}getObject(){const t=this.mesh;return{shape:this.shape,name:t.name,serial:t.serial}}_getPosition(){return this.__position||(this.__position=Ur(this.mesh.position)),this.__position}}class ro extends qn{constructor(t,e){super(t),this.surface=e}get type(){return"surface"}get data(){return this.surface}getObject(t){return{surface:this.surface,index:this.getIndex(t)}}_getPosition(){return this.surface.center.clone()}}class so extends qn{constructor(t,e){super(),this.unitcell=t,this.structure=e}get type(){return"unitcell"}get data(){return this.unitcell}getObject(){return{unitcell:this.unitcell,structure:this.structure}}_getPosition(){return this.unitcell.getCenter(this.structure)}}class no extends qn{constructor(t,e){super(t),this.volume=e}get type(){return"volume"}get data(){return this.volume}getObject(t){const e=this.volume,i=this.getIndex(t);return{volume:e,index:i,value:e.data[i]}}_getPosition(t){const i=this.volume.position,r=this.getIndex(t);return new e(i[3*r],i[3*r+1],i[3*r+2])}}class oo extends no{get type(){return"slice"}}function ao(){return new Uint32Array([0,265,515,778,1030,1295,1541,1804,2060,2309,2575,2822,3082,3331,3593,3840,400,153,915,666,1430,1183,1941,1692,2460,2197,2975,2710,3482,3219,3993,3728,560,825,51,314,1590,1855,1077,1340,2620,2869,2111,2358,3642,3891,3129,3376,928,681,419,170,1958,1711,1445,1196,2988,2725,2479,2214,4010,3747,3497,3232,1120,1385,1635,1898,102,367,613,876,3180,3429,3695,3942,2154,2403,2665,2912,1520,1273,2035,1786,502,255,1013,764,3580,3317,4095,3830,2554,2291,3065,2800,1616,1881,1107,1370,598,863,85,348,3676,3925,3167,3414,2650,2899,2137,2384,1984,1737,1475,1226,966,719,453,204,4044,3781,3535,3270,3018,2755,2505,2240,2240,2505,2755,3018,3270,3535,3781,4044,204,453,719,966,1226,1475,1737,1984,2384,2137,2899,2650,3414,3167,3925,3676,348,85,863,598,1370,1107,1881,1616,2800,3065,2291,2554,3830,4095,3317,3580,764,1013,255,502,1786,2035,1273,1520,2912,2665,2403,2154,3942,3695,3429,3180,876,613,367,102,1898,1635,1385,1120,3232,3497,3747,4010,2214,2479,2725,2988,1196,1445,1711,1958,170,419,681,928,3376,3129,3891,3642,2358,2111,2869,2620,1340,1077,1855,1590,314,51,825,560,3728,3993,3219,3482,2710,2975,2197,2460,1692,1941,1183,1430,666,915,153,400,3840,3593,3331,3082,2822,2575,2309,2060,1804,1541,1295,1030,778,515,265,0])}function co(){return new Int32Array([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,8,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,8,3,9,8,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,2,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,8,3,1,2,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,9,2,10,0,2,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,2,8,3,2,10,8,10,9,8,-1,-1,-1,-1,-1,-1,-1,3,11,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,11,2,8,11,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,9,0,2,3,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,11,2,1,9,11,9,8,11,-1,-1,-1,-1,-1,-1,-1,3,10,1,11,10,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,10,1,0,8,10,8,11,10,-1,-1,-1,-1,-1,-1,-1,3,9,0,3,11,9,11,10,9,-1,-1,-1,-1,-1,-1,-1,9,8,10,10,8,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,7,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,3,0,7,3,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,9,8,4,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,1,9,4,7,1,7,3,1,-1,-1,-1,-1,-1,-1,-1,1,2,10,8,4,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,3,4,7,3,0,4,1,2,10,-1,-1,-1,-1,-1,-1,-1,9,2,10,9,0,2,8,4,7,-1,-1,-1,-1,-1,-1,-1,2,10,9,2,9,7,2,7,3,7,9,4,-1,-1,-1,-1,8,4,7,3,11,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,4,7,11,2,4,2,0,4,-1,-1,-1,-1,-1,-1,-1,9,0,1,8,4,7,2,3,11,-1,-1,-1,-1,-1,-1,-1,4,7,11,9,4,11,9,11,2,9,2,1,-1,-1,-1,-1,3,10,1,3,11,10,7,8,4,-1,-1,-1,-1,-1,-1,-1,1,11,10,1,4,11,1,0,4,7,11,4,-1,-1,-1,-1,4,7,8,9,0,11,9,11,10,11,0,3,-1,-1,-1,-1,4,7,11,4,11,9,9,11,10,-1,-1,-1,-1,-1,-1,-1,9,5,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,9,5,4,0,8,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,5,4,1,5,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,8,5,4,8,3,5,3,1,5,-1,-1,-1,-1,-1,-1,-1,1,2,10,9,5,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,3,0,8,1,2,10,4,9,5,-1,-1,-1,-1,-1,-1,-1,5,2,10,5,4,2,4,0,2,-1,-1,-1,-1,-1,-1,-1,2,10,5,3,2,5,3,5,4,3,4,8,-1,-1,-1,-1,9,5,4,2,3,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,11,2,0,8,11,4,9,5,-1,-1,-1,-1,-1,-1,-1,0,5,4,0,1,5,2,3,11,-1,-1,-1,-1,-1,-1,-1,2,1,5,2,5,8,2,8,11,4,8,5,-1,-1,-1,-1,10,3,11,10,1,3,9,5,4,-1,-1,-1,-1,-1,-1,-1,4,9,5,0,8,1,8,10,1,8,11,10,-1,-1,-1,-1,5,4,0,5,0,11,5,11,10,11,0,3,-1,-1,-1,-1,5,4,8,5,8,10,10,8,11,-1,-1,-1,-1,-1,-1,-1,9,7,8,5,7,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,9,3,0,9,5,3,5,7,3,-1,-1,-1,-1,-1,-1,-1,0,7,8,0,1,7,1,5,7,-1,-1,-1,-1,-1,-1,-1,1,5,3,3,5,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,9,7,8,9,5,7,10,1,2,-1,-1,-1,-1,-1,-1,-1,10,1,2,9,5,0,5,3,0,5,7,3,-1,-1,-1,-1,8,0,2,8,2,5,8,5,7,10,5,2,-1,-1,-1,-1,2,10,5,2,5,3,3,5,7,-1,-1,-1,-1,-1,-1,-1,7,9,5,7,8,9,3,11,2,-1,-1,-1,-1,-1,-1,-1,9,5,7,9,7,2,9,2,0,2,7,11,-1,-1,-1,-1,2,3,11,0,1,8,1,7,8,1,5,7,-1,-1,-1,-1,11,2,1,11,1,7,7,1,5,-1,-1,-1,-1,-1,-1,-1,9,5,8,8,5,7,10,1,3,10,3,11,-1,-1,-1,-1,5,7,0,5,0,9,7,11,0,1,0,10,11,10,0,-1,11,10,0,11,0,3,10,5,0,8,0,7,5,7,0,-1,11,10,5,7,11,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,10,6,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,8,3,5,10,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,9,0,1,5,10,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,8,3,1,9,8,5,10,6,-1,-1,-1,-1,-1,-1,-1,1,6,5,2,6,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,6,5,1,2,6,3,0,8,-1,-1,-1,-1,-1,-1,-1,9,6,5,9,0,6,0,2,6,-1,-1,-1,-1,-1,-1,-1,5,9,8,5,8,2,5,2,6,3,2,8,-1,-1,-1,-1,2,3,11,10,6,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,0,8,11,2,0,10,6,5,-1,-1,-1,-1,-1,-1,-1,0,1,9,2,3,11,5,10,6,-1,-1,-1,-1,-1,-1,-1,5,10,6,1,9,2,9,11,2,9,8,11,-1,-1,-1,-1,6,3,11,6,5,3,5,1,3,-1,-1,-1,-1,-1,-1,-1,0,8,11,0,11,5,0,5,1,5,11,6,-1,-1,-1,-1,3,11,6,0,3,6,0,6,5,0,5,9,-1,-1,-1,-1,6,5,9,6,9,11,11,9,8,-1,-1,-1,-1,-1,-1,-1,5,10,6,4,7,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,3,0,4,7,3,6,5,10,-1,-1,-1,-1,-1,-1,-1,1,9,0,5,10,6,8,4,7,-1,-1,-1,-1,-1,-1,-1,10,6,5,1,9,7,1,7,3,7,9,4,-1,-1,-1,-1,6,1,2,6,5,1,4,7,8,-1,-1,-1,-1,-1,-1,-1,1,2,5,5,2,6,3,0,4,3,4,7,-1,-1,-1,-1,8,4,7,9,0,5,0,6,5,0,2,6,-1,-1,-1,-1,7,3,9,7,9,4,3,2,9,5,9,6,2,6,9,-1,3,11,2,7,8,4,10,6,5,-1,-1,-1,-1,-1,-1,-1,5,10,6,4,7,2,4,2,0,2,7,11,-1,-1,-1,-1,0,1,9,4,7,8,2,3,11,5,10,6,-1,-1,-1,-1,9,2,1,9,11,2,9,4,11,7,11,4,5,10,6,-1,8,4,7,3,11,5,3,5,1,5,11,6,-1,-1,-1,-1,5,1,11,5,11,6,1,0,11,7,11,4,0,4,11,-1,0,5,9,0,6,5,0,3,6,11,6,3,8,4,7,-1,6,5,9,6,9,11,4,7,9,7,11,9,-1,-1,-1,-1,10,4,9,6,4,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,10,6,4,9,10,0,8,3,-1,-1,-1,-1,-1,-1,-1,10,0,1,10,6,0,6,4,0,-1,-1,-1,-1,-1,-1,-1,8,3,1,8,1,6,8,6,4,6,1,10,-1,-1,-1,-1,1,4,9,1,2,4,2,6,4,-1,-1,-1,-1,-1,-1,-1,3,0,8,1,2,9,2,4,9,2,6,4,-1,-1,-1,-1,0,2,4,4,2,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,8,3,2,8,2,4,4,2,6,-1,-1,-1,-1,-1,-1,-1,10,4,9,10,6,4,11,2,3,-1,-1,-1,-1,-1,-1,-1,0,8,2,2,8,11,4,9,10,4,10,6,-1,-1,-1,-1,3,11,2,0,1,6,0,6,4,6,1,10,-1,-1,-1,-1,6,4,1,6,1,10,4,8,1,2,1,11,8,11,1,-1,9,6,4,9,3,6,9,1,3,11,6,3,-1,-1,-1,-1,8,11,1,8,1,0,11,6,1,9,1,4,6,4,1,-1,3,11,6,3,6,0,0,6,4,-1,-1,-1,-1,-1,-1,-1,6,4,8,11,6,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,10,6,7,8,10,8,9,10,-1,-1,-1,-1,-1,-1,-1,0,7,3,0,10,7,0,9,10,6,7,10,-1,-1,-1,-1,10,6,7,1,10,7,1,7,8,1,8,0,-1,-1,-1,-1,10,6,7,10,7,1,1,7,3,-1,-1,-1,-1,-1,-1,-1,1,2,6,1,6,8,1,8,9,8,6,7,-1,-1,-1,-1,2,6,9,2,9,1,6,7,9,0,9,3,7,3,9,-1,7,8,0,7,0,6,6,0,2,-1,-1,-1,-1,-1,-1,-1,7,3,2,6,7,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,2,3,11,10,6,8,10,8,9,8,6,7,-1,-1,-1,-1,2,0,7,2,7,11,0,9,7,6,7,10,9,10,7,-1,1,8,0,1,7,8,1,10,7,6,7,10,2,3,11,-1,11,2,1,11,1,7,10,6,1,6,7,1,-1,-1,-1,-1,8,9,6,8,6,7,9,1,6,11,6,3,1,3,6,-1,0,9,1,11,6,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,8,0,7,0,6,3,11,0,11,6,0,-1,-1,-1,-1,7,11,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,6,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,3,0,8,11,7,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,9,11,7,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,8,1,9,8,3,1,11,7,6,-1,-1,-1,-1,-1,-1,-1,10,1,2,6,11,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,2,10,3,0,8,6,11,7,-1,-1,-1,-1,-1,-1,-1,2,9,0,2,10,9,6,11,7,-1,-1,-1,-1,-1,-1,-1,6,11,7,2,10,3,10,8,3,10,9,8,-1,-1,-1,-1,7,2,3,6,2,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,0,8,7,6,0,6,2,0,-1,-1,-1,-1,-1,-1,-1,2,7,6,2,3,7,0,1,9,-1,-1,-1,-1,-1,-1,-1,1,6,2,1,8,6,1,9,8,8,7,6,-1,-1,-1,-1,10,7,6,10,1,7,1,3,7,-1,-1,-1,-1,-1,-1,-1,10,7,6,1,7,10,1,8,7,1,0,8,-1,-1,-1,-1,0,3,7,0,7,10,0,10,9,6,10,7,-1,-1,-1,-1,7,6,10,7,10,8,8,10,9,-1,-1,-1,-1,-1,-1,-1,6,8,4,11,8,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,3,6,11,3,0,6,0,4,6,-1,-1,-1,-1,-1,-1,-1,8,6,11,8,4,6,9,0,1,-1,-1,-1,-1,-1,-1,-1,9,4,6,9,6,3,9,3,1,11,3,6,-1,-1,-1,-1,6,8,4,6,11,8,2,10,1,-1,-1,-1,-1,-1,-1,-1,1,2,10,3,0,11,0,6,11,0,4,6,-1,-1,-1,-1,4,11,8,4,6,11,0,2,9,2,10,9,-1,-1,-1,-1,10,9,3,10,3,2,9,4,3,11,3,6,4,6,3,-1,8,2,3,8,4,2,4,6,2,-1,-1,-1,-1,-1,-1,-1,0,4,2,4,6,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,9,0,2,3,4,2,4,6,4,3,8,-1,-1,-1,-1,1,9,4,1,4,2,2,4,6,-1,-1,-1,-1,-1,-1,-1,8,1,3,8,6,1,8,4,6,6,10,1,-1,-1,-1,-1,10,1,0,10,0,6,6,0,4,-1,-1,-1,-1,-1,-1,-1,4,6,3,4,3,8,6,10,3,0,3,9,10,9,3,-1,10,9,4,6,10,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,9,5,7,6,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,8,3,4,9,5,11,7,6,-1,-1,-1,-1,-1,-1,-1,5,0,1,5,4,0,7,6,11,-1,-1,-1,-1,-1,-1,-1,11,7,6,8,3,4,3,5,4,3,1,5,-1,-1,-1,-1,9,5,4,10,1,2,7,6,11,-1,-1,-1,-1,-1,-1,-1,6,11,7,1,2,10,0,8,3,4,9,5,-1,-1,-1,-1,7,6,11,5,4,10,4,2,10,4,0,2,-1,-1,-1,-1,3,4,8,3,5,4,3,2,5,10,5,2,11,7,6,-1,7,2,3,7,6,2,5,4,9,-1,-1,-1,-1,-1,-1,-1,9,5,4,0,8,6,0,6,2,6,8,7,-1,-1,-1,-1,3,6,2,3,7,6,1,5,0,5,4,0,-1,-1,-1,-1,6,2,8,6,8,7,2,1,8,4,8,5,1,5,8,-1,9,5,4,10,1,6,1,7,6,1,3,7,-1,-1,-1,-1,1,6,10,1,7,6,1,0,7,8,7,0,9,5,4,-1,4,0,10,4,10,5,0,3,10,6,10,7,3,7,10,-1,7,6,10,7,10,8,5,4,10,4,8,10,-1,-1,-1,-1,6,9,5,6,11,9,11,8,9,-1,-1,-1,-1,-1,-1,-1,3,6,11,0,6,3,0,5,6,0,9,5,-1,-1,-1,-1,0,11,8,0,5,11,0,1,5,5,6,11,-1,-1,-1,-1,6,11,3,6,3,5,5,3,1,-1,-1,-1,-1,-1,-1,-1,1,2,10,9,5,11,9,11,8,11,5,6,-1,-1,-1,-1,0,11,3,0,6,11,0,9,6,5,6,9,1,2,10,-1,11,8,5,11,5,6,8,0,5,10,5,2,0,2,5,-1,6,11,3,6,3,5,2,10,3,10,5,3,-1,-1,-1,-1,5,8,9,5,2,8,5,6,2,3,8,2,-1,-1,-1,-1,9,5,6,9,6,0,0,6,2,-1,-1,-1,-1,-1,-1,-1,1,5,8,1,8,0,5,6,8,3,8,2,6,2,8,-1,1,5,6,2,1,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,3,6,1,6,10,3,8,6,5,6,9,8,9,6,-1,10,1,0,10,0,6,9,5,0,5,6,0,-1,-1,-1,-1,0,3,8,5,6,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,10,5,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,5,10,7,5,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,5,10,11,7,5,8,3,0,-1,-1,-1,-1,-1,-1,-1,5,11,7,5,10,11,1,9,0,-1,-1,-1,-1,-1,-1,-1,10,7,5,10,11,7,9,8,1,8,3,1,-1,-1,-1,-1,11,1,2,11,7,1,7,5,1,-1,-1,-1,-1,-1,-1,-1,0,8,3,1,2,7,1,7,5,7,2,11,-1,-1,-1,-1,9,7,5,9,2,7,9,0,2,2,11,7,-1,-1,-1,-1,7,5,2,7,2,11,5,9,2,3,2,8,9,8,2,-1,2,5,10,2,3,5,3,7,5,-1,-1,-1,-1,-1,-1,-1,8,2,0,8,5,2,8,7,5,10,2,5,-1,-1,-1,-1,9,0,1,5,10,3,5,3,7,3,10,2,-1,-1,-1,-1,9,8,2,9,2,1,8,7,2,10,2,5,7,5,2,-1,1,3,5,3,7,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,8,7,0,7,1,1,7,5,-1,-1,-1,-1,-1,-1,-1,9,0,3,9,3,5,5,3,7,-1,-1,-1,-1,-1,-1,-1,9,8,7,5,9,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,5,8,4,5,10,8,10,11,8,-1,-1,-1,-1,-1,-1,-1,5,0,4,5,11,0,5,10,11,11,3,0,-1,-1,-1,-1,0,1,9,8,4,10,8,10,11,10,4,5,-1,-1,-1,-1,10,11,4,10,4,5,11,3,4,9,4,1,3,1,4,-1,2,5,1,2,8,5,2,11,8,4,5,8,-1,-1,-1,-1,0,4,11,0,11,3,4,5,11,2,11,1,5,1,11,-1,0,2,5,0,5,9,2,11,5,4,5,8,11,8,5,-1,9,4,5,2,11,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,2,5,10,3,5,2,3,4,5,3,8,4,-1,-1,-1,-1,5,10,2,5,2,4,4,2,0,-1,-1,-1,-1,-1,-1,-1,3,10,2,3,5,10,3,8,5,4,5,8,0,1,9,-1,5,10,2,5,2,4,1,9,2,9,4,2,-1,-1,-1,-1,8,4,5,8,5,3,3,5,1,-1,-1,-1,-1,-1,-1,-1,0,4,5,1,0,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,8,4,5,8,5,3,9,0,5,0,3,5,-1,-1,-1,-1,9,4,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,11,7,4,9,11,9,10,11,-1,-1,-1,-1,-1,-1,-1,0,8,3,4,9,7,9,11,7,9,10,11,-1,-1,-1,-1,1,10,11,1,11,4,1,4,0,7,4,11,-1,-1,-1,-1,3,1,4,3,4,8,1,10,4,7,4,11,10,11,4,-1,4,11,7,9,11,4,9,2,11,9,1,2,-1,-1,-1,-1,9,7,4,9,11,7,9,1,11,2,11,1,0,8,3,-1,11,7,4,11,4,2,2,4,0,-1,-1,-1,-1,-1,-1,-1,11,7,4,11,4,2,8,3,4,3,2,4,-1,-1,-1,-1,2,9,10,2,7,9,2,3,7,7,4,9,-1,-1,-1,-1,9,10,7,9,7,4,10,2,7,8,7,0,2,0,7,-1,3,7,10,3,10,2,7,4,10,1,10,0,4,0,10,-1,1,10,2,8,7,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,9,1,4,1,7,7,1,3,-1,-1,-1,-1,-1,-1,-1,4,9,1,4,1,7,0,8,1,8,7,1,-1,-1,-1,-1,4,0,3,7,4,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,8,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,9,10,8,10,11,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,3,0,9,3,9,11,11,9,10,-1,-1,-1,-1,-1,-1,-1,0,1,10,0,10,8,8,10,11,-1,-1,-1,-1,-1,-1,-1,3,1,10,11,3,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,2,11,1,11,9,9,11,8,-1,-1,-1,-1,-1,-1,-1,3,0,9,3,9,11,1,2,9,2,11,9,-1,-1,-1,-1,0,2,11,8,0,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,3,2,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,2,3,8,2,8,10,10,8,9,-1,-1,-1,-1,-1,-1,-1,9,10,2,0,9,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,2,3,8,2,8,10,0,1,8,1,10,8,-1,-1,-1,-1,1,10,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,3,8,9,1,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,9,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,3,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1])}function lo(t,e,i,r,s){var n,o,a,c,l,h,d,u=[[0,4,4,4,2,0,0,0,2,2,0,0],[4,0,4,4,0,8,0,0,0,8,8,0],[4,4,0,4,0,0,8,0,0,0,8,8],[4,4,4,0,0,0,0,1,1,0,0,1],[2,0,0,0,0,8,8,8,2,2,0,0],[0,8,0,0,8,0,8,8,0,8,8,0],[0,0,8,0,8,8,0,8,0,0,8,8],[0,0,0,1,8,8,8,0,1,0,0,1],[2,0,0,1,2,0,0,1,0,2,0,1],[2,8,0,0,2,8,0,0,2,0,8,0],[0,8,8,0,0,8,8,0,0,8,0,8],[0,0,8,1,0,0,8,1,1,0,8,0]],m=0,p=!1,f=!1,g=!1,y=!1,b=-1,x=e*i*r,v=e,w=e*i,A=new Int32Array(12),_=[],S=[],C=[],P=[],I=ao(),k=co();function M(t,e,i){return t+(e-t)*i}function T(t,s,n){return w*(n=(n+d)%r)+v*(s=(s+h)%i)+(t=(t+l)%e)}function B(t,e,i,r,c,l,h){var d=3*t;if(o[d]<0){var u=(m-l)/(h-l),f=n,g=3*a;if(_[g]=i+u,_[g+1]=r,_[g+2]=c,!p){var y=3*t;S[g]=b*M(f[y],f[y+3],u),S[g+1]=b*M(f[y+1],f[y+4],u),S[g+2]=b*M(f[y+2],f[y+5],u)}s&&(P[a]=s[t+Math.round(u)]),o[d]=a,A[e]=a,a+=1}else A[e]=o[d]}function D(t,e,i,r,c,l,h){var d=3*t+1;if(o[d]<0){var u=(m-l)/(h-l),f=n,g=3*a;if(_[g]=i,_[g+1]=r+u,_[g+2]=c,!p){var y=3*t,x=y+3*v;S[g]=b*M(f[y],f[x],u),S[g+1]=b*M(f[y+1],f[x+1],u),S[g+2]=b*M(f[y+2],f[x+2],u)}s&&(P[a]=s[t+Math.round(u)*v]),o[d]=a,A[e]=a,a+=1}else A[e]=o[d]}function $(t,e,i,r,c,l,h){var d=3*t+2;if(o[d]<0){var u=(m-l)/(h-l),f=n,g=3*a;if(_[g]=i,_[g+1]=r,_[g+2]=c+u,!p){var y=3*t,x=y+3*w;S[g]=b*M(f[y],f[x],u),S[g+1]=b*M(f[y+1],f[x+1],u),S[g+2]=b*M(f[y+2],f[x+2],u)}s&&(P[a]=s[t+Math.round(u)*w]),o[d]=a,A[e]=a,a+=1}else A[e]=o[d]}function O(e){var i=3*e;0===n[i]&&(n[i]=t[(e-1+x)%x]-t[(e+1)%x],n[i+1]=t[(e-v+x)%x]-t[(e+v)%x],n[i+2]=t[(e-w+x)%x]-t[(e+w)%x])}function R(e,i,r,s,n){var o,a,l,h,d,b,x;g?(s=T(e,i,r),o=T(e+1,i,r),a=T(e,i+1,r),l=T(e,i,r+1),h=T(e+1,i+1,r),d=T(e+1,i,r+1),b=T(e,i+1,r+1),x=T(e+1,i+1,r+1)):(o=s+1,h=(a=s+v)+1,d=(l=s+w)+1,x=(b=a+w)+1);var _=0,S=t[s],P=t[o],M=t[a],R=t[h],E=t[l],F=t[d],L=t[b],N=t[x];S=m){$=b,M=!0;break}if(M)break}if(M)break}for(M=!1,y=n;y=m){D=y,M=!0;break}if(M)break}if(M)break}for(M=!1,f=s;f=m){B=f,M=!0;break}if(M)break}if(M)break}for(M=!1,b=h;b>=a;--b){for(y=l;y>=n;--y){for(f=c;f>=s;--f)if(d=e*i*b+e*y+f,t[d]>=m){F=b,M=!0;break}if(M)break}if(M)break}for(M=!1,y=l;y>=n;--y){for(b=F;b>=a;--b){for(f=c;f>=s;--f)if(d=e*i*b+e*y+f,t[d]>=m){E=y,M=!0;break}if(M)break}if(M)break}for(M=!1,f=c;f>=s;--f){for(y=E;y>=n;--y){for(b=F;b>=a;--b)if(d=e*i*b+e*y+f,t[d]>=m){O=f,M=!0;break}if(M)break}if(M)break}p?(s=Math.max(0,B-1),n=Math.max(0,D-1),a=Math.max(0,$-1),c=Math.min(e-1,O+1),l=Math.min(i-1,E+1),h=Math.min(r-1,F+1)):(s=Math.max(1,B-1),n=Math.max(1,D-1),a=Math.max(1,$-1),c=Math.min(e-2,O+1),l=Math.min(i-2,E+1),h=Math.min(r-2,F+1))}var L=15;for(b=a;b0?-1:1,n||(n=new Float32Array(3*x)));var I=3*x;if(o&&o.length===I||(o=new Int32Array(I)),a=0,c=0,void 0!==v){var k=v[0].map(Math.round),M=v[1].map(Math.round);l=e*Math.ceil(Math.abs(k[0])/e),h=i*Math.ceil(Math.abs(k[1])/i),d=r*Math.ceil(Math.abs(k[2])/r),E(k[0],k[1],k[2],M[0],M[1],M[2])}else l=h=d=0,E();return _.length=3*a,p||(S.length=3*a),C.length=c,s&&(P.length=a),{position:new Float32Array(_),normal:p?void 0:new Float32Array(S),index:xt(C,_.length/3),atomindex:s?new Int32Array(P):void 0,contour:f}}}He.add("arrow",class extends Xn{get primitive(){return _s}}),He.add("box",class extends Xn{get primitive(){return xs}}),He.add("cone",class extends Xn{get primitive(){return Ss}}),He.add("cylinder",class extends Xn{get primitive(){return As}}),He.add("ellipsoid",class extends Xn{get primitive(){return Cs}}),He.add("octahedron",class extends Xn{get primitive(){return vs}}),He.add("sphere",class extends Xn{get primitive(){return bs}}),He.add("tetrahedron",class extends Xn{get primitive(){return ws}}),He.add("torus",class extends Xn{get primitive(){return Ps}}),He.add("point",class extends Xn{get primitive(){return ks}}),He.add("wideline",class extends Xn{get primitive(){return Ms}}),Object.assign(lo,{__deps:[ao,co,xt]});class ho{constructor(t,e){this.cols=t,this.rows=e,this.size=this.cols*this.rows,this.data=new Float32Array(this.size)}copyTo(t){t.data.set(this.data)}}function uo(t,e){let i=0,r=0;const s=e.rows,n=e.cols;let o=0,a=0,c=0;const l=e.data,h=t.data;for(;i(e=Math.abs(e))?(e/=t,t*Math.sqrt(1+e*e)):e>0?(t/=e,e*Math.sqrt(1+t*t)):0}const xo=1.192092896e-7,vo=1e-37;function wo(t,e,i,r){let s=0,n=0;const o=t.rows,a=t.cols;let c=o,l=a;c>16)?O:-O,t[h*e+u]=$;for(m=0;m<2;m++)for(d=0;d{const e=t.data.sd,i=t.data.p;o(this._makeSurface(e,i.isolevel,i.smooth))}),(a=>{console.warn("Volume.getSurfaceWorker error - trying without worker",a);const c=this.getSurface(t,e,i,r,s,n);o(c)}))}else{const a=this.getSurface(t,e,i,r,s,n);o(a)}}getValueForSigma(t){return this.mean+st(t,2)*this.rms}getSigmaForValue(t){return(st(t,0)-this.mean)/this.rms}get position(){if(!this._position){const t=this.nz,e=this.ny,i=this.nx,r=new Float32Array(i*e*t*3);let s=0;for(let n=0;ni){const t=e;e=i,i=t}const r=t[e];return void 0===r?(t[e]=[i],!0):!r.includes(i)&&(r.push(i),!0)}const i=this.geometry,r=i.index;if(this.parameters.wireframe)if(r){const s=r.array;let n,o=s.length;if(i.drawRange.count!==1/0&&(o=i.drawRange.count),this.wireframeIndex&&this.wireframeIndex.length>2*o)n=this.wireframeIndex;else{n=xt(2*o,i.attributes.position.count)}let a=0;t.length=0;for(let t=0;t2*t?this.wireframeIndex:xt(2*t,t);for(let i=0,r=0;ithis.wireframeGeometry.index.array.length)this.wireframeGeometry.setIndex(new M(this.wireframeIndex,1).setUsage(this.dynamic?WebGLRenderingContext.DYNAMIC_DRAW:0));else{const t=this.wireframeGeometry.getIndex();if(!t)return void Me.error("Index is null");t.set(this.wireframeIndex),t.needsUpdate=this.wireframeIndexCount>0,t.updateRange.count=this.wireframeIndexCount}this.wireframeGeometry.setDrawRange(0,this.wireframeIndexCount)}}getRenderOrder(){let t=0;return this.isText?t=1:this.transparent&&(t=this.isSurface?3:2),t}_getMesh(t){this.material||this.makeMaterial();const e=this.geometry,i=this[t];let r;return r=this.isLine?new T(e,i):this.isPoint?new o(e,i):new P(e,i),r.frustumCulled=!1,r.renderOrder=this.getRenderOrder(),r}getMesh(){return this._getMesh("material")}getWireframeMesh(){let t;return this.material||this.makeMaterial(),this.wireframeGeometry||this.makeWireframeGeometry(),t=new T(this.wireframeGeometry,this.wireframeMaterial),t.frustumCulled=!1,t.renderOrder=this.getRenderOrder(),t}getPickingMesh(){return this._getMesh("pickingMaterial")}getShader(t,e){return gi(t,this.getDefines(e))}getVertexShader(t){return this.getShader(this.vertexShader,t)}getFragmentShader(t){return this.getShader(this.fragmentShader,t)}getDefines(t){const e={};return this.parameters.clipNear&&(e.NEAR_CLIP=1),this.parameters.clipRadius&&(e.RADIUS_CLIP=1),"picking"===t?e.PICKING=1:(("background"===t||this.parameters.background)&&(e.NOLIGHT=1),this.parameters.flatShaded&&(e.FLAT_SHADED=1),this.parameters.opaqueBack&&(e.OPAQUE_BACK=1),this.parameters.diffuseInterior&&(e.DIFFUSE_INTERIOR=1),this.parameters.useInteriorColor&&(e.USE_INTERIOR_COLOR=1)),e}getParameters(){return this.parameters}addUniforms(t){this.uniforms=R.merge([this.uniforms,t]),this.pickingUniforms=R.merge([this.pickingUniforms,t])}addAttributes(t){for(let e in t){let i;const r=t[e],s=this.attributeSize*Lo[r.type];r.value?(s!==r.value.length&&Me.error("attribute value has wrong length",e),i=r.value):i=bt("float32",s),this.geometry.setAttribute(e,new M(i,Lo[r.type]).setUsage(this.dynamic?WebGLRenderingContext.DYNAMIC_DRAW:0))}}updateRenderOrder(){const t=this.getRenderOrder();function e(e){e.renderOrder=t}this.group.children.forEach(e),this.pickingGroup&&this.pickingGroup.children.forEach(e)}updateShader(){const t=this.material,e=this.wireframeMaterial,i=this.pickingMaterial;t.vertexShader=this.getVertexShader(),t.fragmentShader=this.getFragmentShader(),t.needsUpdate=!0,e.vertexShader=this.getShader("Line.vert"),e.fragmentShader=this.getShader("Line.frag"),e.needsUpdate=!0,i.vertexShader=this.getVertexShader("picking"),i.fragmentShader=this.getFragmentShader("picking"),i.needsUpdate=!0}setParameters(t){const e=t,i=this.parameterTypes,r=this.parameters,s={},n={};let o=!1,a=!1;for(const t in e){const c=e[t];void 0!==c&&(r[t]=c,void 0!==i[t]&&(i[t].property&&(!0!==i[t].property?s[i[t].property]=c:s[t]=c),i[t].uniform&&(!0!==i[t].uniform?n[i[t].uniform]=c:n[t]=c),i[t].updateShader&&(o=!0),i[t].updateVisibility&&(a=!0),this.dynamic&&"wireframe"===t&&!0===c&&this.updateWireframeIndex(),"forceTransparent"===t&&(s.transparent=this.transparent),"matrix"===t&&(this.matrix=c)))}this.setProperties(s),this.setUniforms(n),o&&this.updateShader(),a&&this.setVisibility(this.visible)}setAttributes(t){const e=this.geometry,i=e.attributes;for(const r in t){if("picking"===r)continue;const s=t[r],n=s.length;if("index"===r){const t=e.getIndex();if(!t){Me.error("Index is null");continue}e.setDrawRange(0,1/0),n>t.array.length?e.setIndex(new M(s,1).setUsage(this.dynamic?WebGLRenderingContext.DYNAMIC_DRAW:0)):(t.set(s),t.count=n,t.needsUpdate=n>0,t.updateRange.count=n,e.setDrawRange(0,n)),this.indexVersion++,this.parameters.wireframe&&this.updateWireframeIndex()}else{const t=i[r];n>t.array.length?e.setAttribute(r,new M(s,t.itemSize).setUsage(this.dynamic?WebGLRenderingContext.DYNAMIC_DRAW:0)):(i[r].set(s),i[r].needsUpdate=n>0,i[r].updateRange.count=n)}}}setUniforms(t){if(!t)return;const e=this.material.uniforms,i=this.wireframeMaterial.uniforms,r=this.pickingMaterial.uniforms;for(let s in t)"opacity"===s&&this.setProperties({transparent:this.transparent}),void 0!==e[s]&&(e[s].value.isVector3?e[s].value.copy(t[s]):e[s].value.set?e[s].value.set(t[s]):e[s].value=t[s]),void 0!==i[s]&&(i[s].value.isVector3?i[s].value.copy(t[s]):i[s].value.set?i[s].value.set(t[s]):i[s].value=t[s]),void 0!==r[s]&&(r[s].value.isVector3?r[s].value.copy(t[s]):r[s].value.set?r[s].value.set(t[s]):r[s].value=t[s])}setProperties(t){if(!t)return;const e=this.material,i=this.wireframeMaterial,r=this.pickingMaterial;for(const s in t){const n=s;let o=t[n];"transparent"===n?this.updateRenderOrder():"side"===n&&(o=Fo(o)),e[n]=o,i[n]=o,r[n]=o}e.needsUpdate=!0,i.needsUpdate=!0,r.needsUpdate=!0}setVisibility(t){this.visible=t,this.parameters.wireframe?(this.group.visible=!1,this.wireframeGroup.visible=t,this.pickable&&(this.pickingGroup.visible=!1)):(this.group.visible=t,this.wireframeGroup.visible=!1,this.pickable&&(this.pickingGroup.visible=t))}dispose(){this.material&&this.material.dispose(),this.wireframeMaterial&&this.wireframeMaterial.dispose(),this.pickingMaterial&&this.pickingMaterial.dispose(),this.geometry.dispose(),this.wireframeGeometry&&this.wireframeGeometry.dispose()}toJSON(){var t={};for(var e in this)"group"!==e&&"wireframeGroup"!==e&&"pickingGroup"!=e&&"picking"!==e&&(t[e]=this[e]);return t}}class Uo extends Go{constructor(t,e={}){super(t,e),this.vertexShader="Mesh.vert",this.fragmentShader="Mesh.frag",this.addAttributes({normal:{type:"v3",value:t.normal}}),void 0===t.normal&&this.geometry.computeVertexNormals()}}class jo extends Uo{constructor(){super(...arguments),this.isSurface=!0}}function Ho(t){t.visible=!0}function Wo(t){t.visible=!1}class qo{constructor(t){this.group=new m,this.wireframeGroup=new m,this.pickingGroup=new m,this.frontMeshes=[],this.backMeshes=[],this.size=t.size,this.side=t.parameters.side,this.visible=t.visible,this.geometry=t.geometry,this.picking=t.picking,this.group=new m,this.wireframeGroup=new m,this.pickingGroup=new m,this.matrix=t.matrix;const e=t,i=new t.constructor({position:new Float32Array(0)});e.makeMaterial(),i.makeMaterial(),i.picking=t.picking,i.geometry=t.geometry,i.wireframeGeometry=t.wireframeGeometry,i.setParameters(t.getParameters()),i.updateShader(),e.setParameters({side:"front"}),i.setParameters({side:"back",opacity:i.parameters.opacity}),this.buffer=t,this.frontBuffer=e,this.backBuffer=i}set matrix(t){Go.prototype.setMatrix.call(this,t)}get matrix(){return this.group.matrix.clone()}get pickable(){return!!this.picking&&!this.parameters.disablePicking}get parameters(){return this.buffer.parameters}getParameters(){const t=Object.assign({},this.buffer.parameters);return t.side=this.side,t}getMesh(t){let e,i;return t?(i=this.backBuffer.getPickingMesh(),e=this.frontBuffer.getPickingMesh()):(i=this.backBuffer.getMesh(),e=this.frontBuffer.getMesh()),this.frontMeshes.push(e),this.backMeshes.push(i),this.setParameters({side:this.side}),(new m).add(i,e)}getWireframeMesh(){return this.buffer.getWireframeMesh()}getPickingMesh(){return this.getMesh(!0)}setAttributes(t){this.buffer.setAttributes(t)}setParameters(t){"front"===(t=Object.assign({},t)).side?(this.frontMeshes.forEach(Ho),this.backMeshes.forEach(Wo)):"back"===t.side?(this.frontMeshes.forEach(Wo),this.backMeshes.forEach(Ho)):"double"===t.side&&(this.frontMeshes.forEach(Ho),this.backMeshes.forEach(Ho)),void 0!==t.side&&(this.side=t.side),delete t.side,void 0!==t.matrix&&(this.matrix=t.matrix),delete t.matrix,this.frontBuffer.setParameters(t),void 0!==t.wireframe&&(this.wireframe=t.wireframe,this.setVisibility(this.visible)),delete t.wireframe,this.backBuffer.setParameters(t)}setVisibility(t){this.visible=t,this.parameters.wireframe?(this.group.visible=!1,this.wireframeGroup.visible=t,this.pickable&&(this.pickingGroup.visible=!1)):(this.group.visible=t,this.wireframeGroup.visible=!1,this.pickable&&(this.pickingGroup.visible=t))}dispose(){this.frontBuffer.dispose(),this.backBuffer.dispose()}toJSON(){var t={};for(var e in this)["side","size","visible","matrix","parameters"].includes(e)&&(t[e]=this[e]);return t}}Ve.add("shader/Line.vert","uniform float clipNear;\nuniform vec3 clipCenter;\nvarying vec3 vViewPosition;\n#if defined( RADIUS_CLIP )\nvarying vec3 vClipCenter;\n#endif\n#include color_pars_vertex\nvoid main(){\n#include color_vertex\n#include begin_vertex\n#include project_vertex\nvViewPosition = -mvPosition.xyz;\n#if defined( RADIUS_CLIP )\nvClipCenter = -( modelViewMatrix * vec4( clipCenter, 1.0 ) ).xyz;\n#endif\n#include nearclip_vertex\n}"),Ve.add("shader/Line.frag","uniform float opacity;\nuniform float clipNear;\nuniform float clipRadius;\nvarying vec3 vViewPosition;\n#if defined( RADIUS_CLIP )\nvarying vec3 vClipCenter;\n#endif\n#include common\n#include color_pars_fragment\n#include fog_pars_fragment\nvoid main(){\n#include nearclip_fragment\n#include radiusclip_fragment\ngl_FragColor = vec4( vColor, opacity );\n#include premultiplied_alpha_fragment\n#include tonemapping_fragment\n#include encodings_fragment\n#include fog_fragment\n}");class Xo extends Go{constructor(){super(...arguments),this.isLine=!0,this.vertexShader="Line.vert",this.fragmentShader="Line.frag"}}class Yo extends zr{constructor(t,r,s){super(t,r,s),this.type="surface",this.parameters=Object.assign({isolevelType:{type:"select",options:{value:"value",sigma:"sigma"}},isolevel:{type:"number",precision:2,max:1e3,min:-1e3},negateIsolevel:{type:"boolean"},isolevelScroll:{type:"boolean"},smooth:{type:"integer",precision:1,max:10,min:0},background:{type:"boolean",rebuild:!0},opaqueBack:{type:"boolean",buffer:!0},boxSize:{type:"integer",precision:1,max:100,min:0},colorVolume:{type:"hidden"},contour:{type:"boolean",rebuild:!0},useWorker:{type:"boolean",rebuild:!0},wrap:{type:"boolean",rebuild:!0}},this.parameters),t instanceof Eo?(this.surface=void 0,this.volume=t):(this.surface=t,this.volume=void 0),this.boxCenter=new e,this.__boxCenter=new e,this.box=new a,this.__box=new a,this._position=new e,this.inverseMatrix=new i,this.setBox=function(){this._position.copy(r.translationGroup.position).negate(),this._position.applyMatrix4(this.inverseMatrix),this._position.equals(this.boxCenter)||this.setParameters({boxCenter:this._position})},this.toBePrepared=!0,this.viewer.signals.ticked.add(this.setBox,this),this.init(s)}init(t){const e=t||{};e.colorScheme=st(e.colorScheme,"uniform"),e.colorValue=st(e.colorValue,14540253),this.isolevelType=st(e.isolevelType,"sigma"),this.isolevel=st(e.isolevel,2),this.negateIsolevel=st(e.negateIsolevel,!1),this.isolevelScroll=st(e.isolevelScroll,!1),this.smooth=st(e.smooth,0),this.background=st(e.background,!1),this.opaqueBack=st(e.opaqueBack,!0),this.boxSize=st(e.boxSize,0),this.colorVolume=st(e.colorVolume,void 0),this.contour=st(e.contour,!1),this.useWorker=st(e.useWorker,!0),this.wrap=st(e.wrap,!1),super.init(e),this.inverseMatrix.getInverse(this.matrix),this.build()}attach(t){this.bufferList.forEach((t=>{this.viewer.add(t)})),this.setVisibility(this.visible),t()}prepare(t){if(this.volume){let e;if(e="sigma"===this.isolevelType?this.volume.getValueForSigma(this.isolevel):this.isolevel,this.negateIsolevel&&(e*=-1),!this.surface||this.__isolevel!==e||this.__smooth!==this.smooth||this.__contour!==this.contour||this.__wrap!==this.wrap||this.__boxSize!==this.boxSize||this.boxSize>0&&!this.__boxCenter.equals(this.boxCenter)){this.__isolevel=e,this.__smooth=this.smooth,this.__contour=this.contour,this.__wrap=this.wrap,this.__boxSize=this.boxSize,this.__boxCenter.copy(this.boxCenter),this.__box.copy(this.box);const i=e=>{this.surface=e,t()};this.useWorker?this.volume.getSurfaceWorker(e,this.smooth,this.boxCenter,this.boxSize,this.contour,this.wrap,i):i(this.volume.getSurface(e,this.smooth,this.boxCenter,this.boxSize,this.contour,this.wrap))}else t()}else t()}create(){const t={position:this.surface.getPosition(),color:this.surface.getColor(this.getColorParams()),index:this.surface.getIndex()};let e;if(this.contour)e=new Xo(t,this.getBufferParams({wireframe:!1}));else{Object.assign(t,{normal:this.surface.getNormal(),picking:this.surface.getPicking()});const i=new jo(t,this.getBufferParams({background:this.background,opaqueBack:this.opaqueBack,dullInterior:!1}));e=new qo(i)}this.bufferList.push(e)}update(t){if(0===this.bufferList.length)return;const e={};(t=t||{}).position&&(e.position=this.surface.getPosition()),t.color&&(e.color=this.surface.getColor(this.getColorParams())),t.index&&(e.index=this.surface.getIndex()),t.normal&&(e.normal=this.surface.getNormal()),this.bufferList.forEach((function(t){t.setAttributes(e)}))}setParameters(t,e,i){return t&&void 0!==t.isolevelType&&this.volume&&("value"===this.isolevelType&&"sigma"===t.isolevelType?this.isolevel=this.volume.getSigmaForValue(this.isolevel):"sigma"===this.isolevelType&&"value"===t.isolevelType&&(this.isolevel=this.volume.getValueForSigma(this.isolevel)),this.isolevelType=t.isolevelType),t&&t.boxCenter&&(this.boxCenter.copy(t.boxCenter),delete t.boxCenter),t&&t.wireframe&&(t.contour||void 0===t.contour&&this.contour)&&(t.wireframe=!1),super.setParameters(t,e,i),t.matrix&&this.inverseMatrix.getInverse(t.matrix),this.volume&&this.volume.getBox(this.boxCenter,this.boxSize,this.box),t&&void 0!==t.colorVolume&&e&&(e.color=!0),this.surface&&(void 0!==t.isolevel||void 0!==t.negateIsolevel||void 0!==t.smooth||void 0!==t.wrap||void 0!==t.boxSize||this.boxSize>0&&!this.__box.equals(this.box))&&this.build({position:!0,color:!0,index:!0,normal:!this.contour}),this}getColorParams(){const t=super.getColorParams();return t.volume=this.colorVolume,t}dispose(){this.viewer.signals.ticked.remove(this.setBox,this),super.dispose()}}class Ko{static zoomScroll(t,e){t.trackballControls.zoom(e)}static clipNearScroll(t,e){const i=t.getParameters();t.setParameters({clipNear:i.clipNear+e/10})}static focusScroll(t,e){const i=t.getFocus(),r=Math.sign(e)*function(t,e,i){if(t>e)return t;const r=t/e;return((2*i-e)*r+(2*e-3*i))*r*r+i}((100-i)/10,5,.2);t.setFocus(i+r)}static zoomFocusScroll(t,e){t.trackballControls.zoom(e);const i=t.viewer.camera.position.z;t.setFocus(100-Math.abs(i/8))}static isolevelScroll(t,e){const i=Math.sign(e)/10;t.eachRepresentation(((t,e)=>{if(t.repr instanceof Yo){const e=t.getParameters();e.isolevelScroll&&t.setParameters({isolevel:e.isolevel+i})}}))}static panDrag(t,e,i){t.trackballControls.pan(e,i)}static rotateDrag(t,e,i){t.trackballControls.rotate(e,i)}static zRotateDrag(t,e,i){t.trackballControls.zRotate(e,i)}static zoomDrag(t,e,i){t.trackballControls.zoom((e+i)/-2)}static zoomFocusDrag(t,e,i){t.trackballControls.zoom((e+i)/-2);const r=t.viewer.camera.position.z;t.setFocus(100-Math.abs(r/8))}static panComponentDrag(t,e,i){t.trackballControls.panComponent(e,i)}static panAtomDrag(t,e,i){t.trackballControls.panAtom(e,i)}static rotateComponentDrag(t,e,i){t.trackballControls.rotateComponent(e,i)}static movePick(t,e){e&&t.animationControls.move(e.position.clone())}static tooltipPick(t,e){const i=t.tooltip;if(t.getParameters().tooltip&&e){const t=e.mouse.position;i.innerText=e.getLabel(),i.style.bottom=window.innerHeight-t.y+3+"px",i.style.left=t.x+3+"px",i.style.display="block"}else i.style.display="none"}static measurePick(t,e){if(e&&(e.atom||e.bond)){const t=e.atom||e.closestBondAtom;e.component.measurePick(t)}else t.measureClear()}}const Zo={default:[["scroll",Ko.zoomScroll],["scroll-shift",Ko.focusScroll],["scroll-ctrl",Ko.isolevelScroll],["scroll-shift-ctrl",Ko.zoomFocusScroll],["drag-left",Ko.rotateDrag],["drag-right",Ko.panDrag],["drag-ctrl-left",Ko.panDrag],["drag-ctrl-right",Ko.zRotateDrag],["drag-shift-left",Ko.zoomDrag],["drag-middle",Ko.zoomFocusDrag],["drag-ctrl-shift-right",Ko.panComponentDrag],["drag-ctrl-shift-left",Ko.rotateComponentDrag],["clickPick-right",Ko.measurePick],["clickPick-ctrl-left",Ko.measurePick],["clickPick-middle",Ko.movePick],["clickPick-left",Ko.movePick],["hoverPick",Ko.tooltipPick]],pymol:[["drag-left",Ko.rotateDrag],["drag-middle",Ko.panDrag],["drag-right",Ko.zoomDrag],["scroll",Ko.focusScroll],["drag-shift-right",Ko.focusScroll],["clickPick-ctrl+shift-middle",Ko.movePick],["hoverPick",Ko.tooltipPick]],coot:[["scroll",Ko.isolevelScroll],["drag-left",Ko.rotateDrag],["drag-middle",Ko.panDrag],["drag-ctrl-left",Ko.panDrag],["drag-right",Ko.zoomFocusDrag],["drag-ctrl-right",Ko.focusScroll],["clickPick-middle",Ko.movePick],["hoverPick",Ko.tooltipPick]],astexviewer:[["drag-left",Ko.rotateDrag],["drag-ctrl-left",Ko.panDrag],["drag-shift-left",Ko.zoomDrag],["scroll",Ko.focusScroll],["clickPick-middle",Ko.movePick],["hoverPick",Ko.tooltipPick]]};function Qo(t){const e=t.split(/[-+]/);let i="";e.includes("scroll")&&(i="scroll"),e.includes("drag")&&(i="drag"),e.includes("click")&&(i="click"),e.includes("doubleClick")&&(i="doubleClick"),e.includes("hover")&&(i="hover"),e.includes("clickPick")&&(i="clickPick"),e.includes("hoverPick")&&(i="hoverPick");let r=0;e.includes("alt")&&(r+=1),e.includes("ctrl")&&(r+=2),e.includes("meta")&&(r+=4),e.includes("shift")&&(r+=8);let s=0;return e.includes("left")&&(s+=1),e.includes("right")&&(s+=2),e.includes("middle")&&(s+=4),[i,r,s]}class Jo{constructor(t,e={}){this.stage=t,this.actionList=[],this.mouse=t.mouseObserver,this.disabled=e.disabled||!1,this.preset(e.preset||"default")}run(t,...e){if(this.disabled)return;const i=this.mouse.key||0,r=this.mouse.buttons||0;this.actionList.forEach((s=>{s.type===t&&s.key===i&&s.button===r&&s.callback(this.stage,...e)}))}add(t,e){const[i,r,s]=Qo(t);this.actionList.push({type:i,key:r,button:s,callback:e})}remove(t,e){const i=t.includes("*"),[r,s,n]=Qo(t),o=this.actionList.filter((function(t){return!((t.type===r||i&&""===r)&&(t.key===s||i&&0===s)&&(t.button===n||i&&0===n)&&(t.callback===e||void 0===e))}));this.actionList=o}preset(t){this.clear();(Zo[t]||[]).forEach((t=>this.add(t[0],t[1])))}clear(){this.actionList.length=0}}class ta{static autoView(t){t.autoView(1e3)}static toggleAnimations(t){t.animationControls.toggle()}static toggleRock(t){t.toggleRock()}static toggleSpin(t){t.toggleSpin()}static toggleAntialiasing(t){const e=t.getParameters();t.setParameters({sampleLevel:-1===e.sampleLevel?0:-1})}}const ea={default:[["i",ta.toggleSpin],["k",ta.toggleRock],["p",ta.toggleAnimations],["a",ta.toggleAntialiasing],["r",ta.autoView]]};class ia{constructor(t,e={}){this.stage=t,this.actionList=[],this.disabled=e.disabled||!1,this.preset(e.preset||"default")}run(t){this.disabled||this.actionList.forEach((e=>{e.key===t&&e.callback(this.stage)}))}add(t,e){this.actionList.push({key:t,callback:e})}remove(t,e){const i=this.actionList.filter((function(i){return!(i.key===t&&(i.callback===e||void 0===e))}));this.actionList=i}preset(t){this.clear();(ea[t]||[]).forEach((t=>this.add(t[0],t[1])))}clear(){this.actionList.length=0}}class ra{constructor(t){this.stage=t,this.stage=t,this.mouse=t.mouseObserver,this.controls=t.mouseControls,this.mouse.signals.clicked.add(this._onClick,this),this.mouse.signals.hovered.add(this._onHover,this)}_onClick(t,e){const i=this.stage.pickingControls.pick(t,e);this.stage.signals.clicked.dispatch(i),this.controls.run("clickPick",i)}_onHover(t,e){const i=this.stage.pickingControls.pick(t,e);i&&this.mouse.down.equals(this.mouse.position)&&(this.stage.transformComponent=i.component,this.stage.transformAtom=i.atom),this.stage.signals.hovered.dispatch(i),this.controls.run("hoverPick",i)}dispose(){this.mouse.signals.clicked.remove(this._onClick,this),this.mouse.signals.hovered.remove(this._onHover,this)}}class sa{constructor(t){this.stage=t,this.stage=t,this.mouse=t.mouseObserver,this.controls=t.mouseControls,this.mouse.signals.moved.add(this._onMove,this),this.mouse.signals.scrolled.add(this._onScroll,this),this.mouse.signals.dragged.add(this._onDrag,this),this.mouse.signals.clicked.add(this._onClick,this),this.mouse.signals.hovered.add(this._onHover,this),this.mouse.signals.doubleClicked.add(this._onDblclick,this)}_onMove(){this.stage.tooltip.style.display="none"}_onScroll(t){this.controls.run("scroll",t)}_onDrag(t,e){this.controls.run("drag",t,e)}_onClick(t,e){this.controls.run("click",t,e)}_onDblclick(t,e){this.controls.run("doubleClick",t,e)}_onHover(t,e){this.controls.run("hover",t,e)}dispose(){this.mouse.signals.moved.remove(this._onMove,this),this.mouse.signals.scrolled.remove(this._onScroll,this),this.mouse.signals.dragged.remove(this._onDrag,this),this.mouse.signals.clicked.remove(this._onClick,this),this.mouse.signals.hovered.remove(this._onHover,this)}}class na{constructor(t){this.stage=t,this.viewer=t.viewer,this.animationControls=t.animationControls,this.viewer.signals.ticked.add(this._onTick,this)}_onTick(t){this.animationControls.run(t)}dispose(){this.viewer.signals.ticked.remove(this._onTick,this)}}const oa=!!_e&&{passive:!0};class aa{constructor(t){this.stage=t,this.stage=t,this.controls=t.keyControls,this.domElement=t.viewer.renderer.domElement,this.domElement.setAttribute("tabIndex","-1"),this.domElement.style.outline="none",this._focusDomElement=this._focusDomElement.bind(this),this._onKeydown=this._onKeydown.bind(this),this._onKeyup=this._onKeyup.bind(this),this._onKeypress=this._onKeypress.bind(this),this.domElement.addEventListener("mousedown",this._focusDomElement),this.domElement.addEventListener("touchstart",this._focusDomElement,oa),this.domElement.addEventListener("keydown",this._onKeydown),this.domElement.addEventListener("keyup",this._onKeyup),this.domElement.addEventListener("keypress",this._onKeypress)}_onKeydown(){}_onKeyup(){}_onKeypress(t){let e;e="key"in KeyboardEvent.prototype?t.key:String.fromCharCode(t.which||t.keyCode),this.controls.run(e)}_focusDomElement(){this.domElement.focus()}dispose(){this.domElement.removeEventListener("mousedown",this._focusDomElement),this.domElement.removeEventListener("touchstart",this._focusDomElement,oa),this.domElement.removeEventListener("keydown",this._onKeypress),this.domElement.removeEventListener("keyup",this._onKeypress),this.domElement.removeEventListener("keypress",this._onKeypress)}}class ca{constructor(i,r,s,n={}){this.component=i,this.position=r,this.offsetX=st(n.offsetX,0),this.offsetY=st(n.offsetY,0),this.visible=st(n.visible,!0),this.stage=i.stage,this.viewer=i.stage.viewer,this._viewerPosition=new e,this._updateViewerPosition(),this._canvasPosition=new t,this._cameraPosition=new e,this.element=document.createElement("div"),Object.assign(this.element.style,{display:"block",position:"absolute",pointerEvents:"none",whiteSpace:"nowrap",left:"-10000px"}),this.viewer.wrapper.appendChild(this.element),this.setContent(s),this.updateVisibility(),this.viewer.signals.rendered.add(this._update,this),this.component.signals.matrixChanged.add(this._updateViewerPosition,this)}setContent(t){const e=this.element.style.display;if("none"===e&&(this.element.style.left="-10000px",this.element.style.display="block"),t instanceof HTMLElement)this.element.appendChild(t);else{const e=document.createElement("div");e.innerText=t,Object.assign(e.style,{backgroundColor:"rgba( 0, 0, 0, 0.6 )",color:"lightgrey",padding:"8px",fontFamily:"sans-serif"}),this.element.appendChild(e)}this._clientRect=this.element.getBoundingClientRect(),"none"===e&&(this.element.style.display=e)}setVisibility(t){this.visible=t,this.updateVisibility()}getVisibility(){return this.visible&&this.component.parameters.visible}updateVisibility(){this.element.style.display=this.getVisibility()?"block":"none"}_updateViewerPosition(){this._viewerPosition.copy(this.position).applyMatrix4(this.component.matrix)}_update(){if(!this.getVisibility())return;const t=this.element.style,e=this._canvasPosition,i=this._viewerPosition,r=this._clientRect;if(this._cameraPosition.copy(i).add(this.viewer.translationGroup.position).applyMatrix4(this.viewer.rotationGroup.matrix).sub(this.viewer.camera.position),this._cameraPosition.z<0)return void(t.display="none");t.display="block";const s=this._cameraPosition.length(),n=this.viewer.scene.fog;t.opacity=(1-Rt(n.near,n.far,s)).toString(),t.zIndex=Math.round(100*(n.far-s)).toString(),this.stage.viewerControls.getPositionOnCanvas(i,e),t.bottom=this.offsetX+e.y+r.height/2+"px",t.left=this.offsetY+e.x-r.width/2+"px"}dispose(){this.viewer.wrapper.removeChild(this.element),this.viewer.signals.ticked.remove(this._update,this),this.component.signals.matrixChanged.remove(this._updateViewerPosition,this)}}const la=new i,ha=new e,da=new r;class ua{constructor(t){this.component=t,this.signals={changed:new tt.Signal},this.stage=t.stage,this.viewer=t.stage.viewer}get position(){return this.component.position}get rotation(){return this.component.quaternion}changed(){this.component.updateMatrix(),this.viewer.requestRender(),this.signals.changed.dispatch()}spin(t,e){la.getInverse(this.viewer.rotationGroup.matrix),ha.copy(At(t)).applyMatrix4(la),la.extractRotation(this.component.transform),la.premultiply(this.viewer.rotationGroup.matrix),la.getInverse(la),ha.copy(At(t)),ha.applyMatrix4(la),la.makeRotationAxis(ha,e),da.setFromRotationMatrix(la),this.component.quaternion.premultiply(da),this.changed()}}const ma={"":"",vdw:"by vdW radius",covalent:"by covalent radius",sstruc:"by secondary structure",bfactor:"by bfactor",size:"size",data:"data",explicit:"explicit"};class pa{constructor(t={}){this.max=10,this.type=st(t.type,"size"),this.scale=st(t.scale,1),this.size=st(t.size,1),this.data=st(t.data,{})}atomRadius(t){let e;switch(this.type){case"vdw":e=t.vdw;break;case"covalent":e=t.covalent;break;case"bfactor":e=t.bfactor||1;break;case"sstruc":const i=t.sstruc;e="h"===i||"g"===i||"i"===i||"e"===i||"b"===i?.25:un.includes(t.atomname)?.4:.1;break;case"data":e=st(this.data[t.index],1);break;case"explicit":e=t.radius,null===e&&(e=this.size);break;default:e=this.size}return Math.min(e*this.scale,this.max)}}pa.types=ma;const fa=new e(-1,-1,-1),ga=new i;class ya{constructor(t){const i=t.rows,r=i/3,s=new ho(i,3),n=new ho(3,3),o=new ho(1,3),a=new ho(3,3),c=new ho(3,3),l=fo(t);go(t,l),uo(s,t),mo(n,s,s),wo(n,o,a,c);const h=new e(l[0],l[1],l[2]),d=new e(a.data[0],a.data[3],a.data[6]),u=new e(a.data[1],a.data[4],a.data[7]),m=new e(a.data[2],a.data[5],a.data[8]),p=d.clone().multiplyScalar(Math.sqrt(o.data[0]/r)),f=u.clone().multiplyScalar(Math.sqrt(o.data[1]/r)),g=m.clone().multiplyScalar(Math.sqrt(o.data[2]/r));this.begA=h.clone().sub(p),this.endA=h.clone().add(p),this.begB=h.clone().sub(f),this.endB=h.clone().add(f),this.begC=h.clone().sub(g),this.endC=h.clone().add(g),this.center=h,this.vecA=p,this.vecB=f,this.vecC=g,this.normVecA=d,this.normVecB=u,this.normVecC=m}getBasisMatrix(t=new i){const e=t;return e.makeBasis(this.normVecB,this.normVecA,this.normVecC),e.determinant()<0&&e.scale(fa),e}getRotationQuaternion(t=new r){const e=t;return e.setFromRotationMatrix(this.getBasisMatrix(ga)),e.inverse()}getProjectedScaleForAtoms(t){let i=-1/0,r=-1/0,s=-1/0,n=-1/0,o=-1/0,a=-1/0;const c=new e,l=new e,h=this.center,d=this.normVecA,u=this.normVecB,m=this.normVecC;return t.eachAtom((function(t){jr(c.copy(t),d,h);const e=l.subVectors(c,h).normalize().dot(d),p=c.distanceTo(h);e>0?p>i&&(i=p):p>r&&(r=p),jr(c.copy(t),u,h);const f=l.subVectors(c,h).normalize().dot(u),g=c.distanceTo(h);f>0?g>s&&(s=g):g>n&&(n=g),jr(c.copy(t),m,h);const y=l.subVectors(c,h).normalize().dot(m),b=c.distanceTo(h);y>0?b>o&&(o=b):b>a&&(a=b)})),{d1a:i,d2a:s,d3a:o,d1b:-r,d2b:-n,d3b:-a}}}class ba{constructor(t,e,i,r){this.volume=t,this.setFilter(e,i,r)}get header(){return this.volume.header}get matrix(){return this.volume.matrix}get normalMatrix(){return this.volume.normalMatrix}get inverseMatrix(){return this.volume.inverseMatrix}get center(){return this.volume.center}get boundingBox(){return this.volume.boundingBox}get min(){return this.volume.min}get max(){return this.volume.max}get mean(){return this.volume.mean}get rms(){return this.volume.rms}_getFilterHash(t,e,i){return JSON.stringify([t,e,i])}setFilter(t,e,i){isNaN(t)&&this.header&&(t=this.header.DMEAN+2*this.header.ARMS),t=void 0===t||isNaN(t)?-1/0:t,e=st(e,1/0),i=st(i,!1);const r=this.volume.data,s=this.volume.position,n=this.volume.atomindex,o=this._getFilterHash(t,e,i);if(o!==this._filterHash){if(t===-1/0&&e===1/0)this.data=r,this.position=s,this.atomindex=n;else{const o=r.length;this._dataBuffer||(this._dataBuffer=new ArrayBuffer(4*o),this._positionBuffer=new ArrayBuffer(3*o*4),n&&(this._atomindexBuffer=new ArrayBuffer(4*o)));const a=new Float32Array(this._dataBuffer),c=new Float32Array(this._positionBuffer);let l;n&&(l=new Uint32Array(this._atomindexBuffer));let h=0;for(let d=0;d=t&&u<=e||i&&(ue)){const t=3*h;a[h]=u,c[t+0]=s[o+0],c[t+1]=s[o+1],c[t+2]=s[o+2],n&&l&&(l[h]=n[d]),h+=1}}this.data=new Float32Array(this._dataBuffer,0,h),this.position=new Float32Array(this._positionBuffer,0,3*h),n&&(this.atomindex=new Int32Array(this._atomindexBuffer,0,h))}this._filterHash=o}}}ba.prototype.getValueForSigma=Eo.prototype.getValueForSigma,ba.prototype.getSigmaForValue=Eo.prototype.getSigmaForValue,ba.prototype.getDataAtomindex=Eo.prototype.getDataAtomindex,ba.prototype.getDataPosition=Eo.prototype.getDataPosition,ba.prototype.getDataColor=Eo.prototype.getDataColor,ba.prototype.getDataPicking=Eo.prototype.getDataPicking,ba.prototype.getDataSize=Eo.prototype.getDataSize;class xa{constructor(t,e){const i=Rs({nodeArray1:t.atomIndex1,nodeArray2:t.atomIndex2,edgeCount:t.count,nodeCount:e});this.countArray=i.countArray,this.offsetArray=i.offsetArray,this.indexArray=i.indexArray}}class va extends Bs{get _defaultFields(){return[["atomIndex1",1,"int32"],["atomIndex2",1,"int32"],["bondOrder",1,"int8"]]}addBond(t,e,i){this.growIfFull();const r=this.count,s=t.index,n=e.index;s0&&(a[e]=v.angleTo(w));const r=Math.cos(f.angleTo(g));h[e]=180/Math.PI*Math.acos(r);const s=f.length(),x=g.length();c[e]=Math.sqrt(x*s)/Math.max(2,2*(1-r)),l[e]=Math.abs(m.dot(v)),y.copy(f).multiplyScalar(c[e]/s),b.copy(g).multiplyScalar(c[e]/x),y.subVectors(P,y),b.subVectors(I,b),y.toArray(n,i+3),b.toArray(n,i+6),A.subVectors(C,_),A.toArray(d,i),w.copy(v),_.copy(y)}y.fromArray(n,3),b.fromArray(n,6),v.subVectors(y,b).normalize(),C.index=t.getAtomIndexByType(0,S),_.copy(C),x.copy(C),jr(x,v,y),x.toArray(n,0),A.subVectors(_,y),A.toArray(d,0),y.fromArray(n,3*r-6),b.fromArray(n,3*r-9),v.subVectors(y,b).normalize(),C.index=t.getAtomIndexByType(r-1,S),_.copy(C),x.copy(C),jr(x,v,y),x.toArray(n,3*r-3);for(let e=r-3;ei||h.bending[e]>t)&&(E=!0)),E){if(e-p<4){p=e,E=!1;continue}$.index=B.traceAtomIndex,I=h.axis.subarray(3*p+3,3*e),k=h.center.subarray(3*p,3*e+3),C=Ur(I).normalize(),P=Ur(k),M.fromArray(k),jr(M,C,P),T.fromArray(k,k.length-3),jr(T,C,P),C.subVectors(T,M),C.toArray(g,f),P.toArray(y,f),M.toArray(b,f),T.toArray(x,f),u.atomColorToArray($,v,f),w.push($.index),A.push(m.atomRadius($)),_.push(l+p),S.push(l+e+1-p),f+=3,p=e,E=!1}const F=new Float32Array(w);return{axis:new Float32Array(g),center:new Float32Array(y),begin:new Float32Array(b),end:new Float32Array(x),color:new Float32Array(v),picking:new Yn(F,a),size:new Float32Array(A),residueOffset:_,residueCount:S}}}class Ia{constructor(t){this.scoreFunction=t,this.content=[],this.scoreFunction=t}push(t){this.content.push(t),this.bubbleUp(this.content.length-1)}pop(){const t=this.content[0],e=this.content.pop();return e&&this.content.length>0&&(this.content[0]=e,this.sinkDown(0)),t}peek(){return this.content[0]}remove(t){const e=this.content.length;for(let i=0;i0;){const i=Math.floor((t+1)/2)-1,r=this.content[i];if(!(this.scoreFunction(e)e?(o&&(clearTimeout(o),o=null),a=l,s=t.apply(r,n),o||(r=n=null)):o||!1===i.trailing||(o=setTimeout(c,h)),s}}function dt(t,e){return te?1:0}function mt(t,e,i=dt){let r=0,n=t.length-1;for(;r<=n;){const s=r+n>>1,o=i(e,t[s]);if(o>0)r=s+1;else{if(!(o<0))return s;n=s-1}}return-r-1}function ft(t,e,i){const r=function(t,e){let i=t.length-1;if(t[i]>1;t[n]>=e?i=n-1:r=n+1}return i+1}(t,e),n=function(t,e){if(t[0]>e)return-1;let i=0,r=t.length-1;for(;i<=r;){const n=i+r>>1;t[n]>e?r=n-1:i=n+1}return i-1}(t,i);return-1===r||-1===n||r>n?0:n-r+1}function pt(t){return t.sort().filter((function(t,e,i){return 0===e||t!==i[e-1]}))}function gt(t){const e=28672;if(t.length>e){const i=[];for(let r=0;r65535?Uint32Array:Uint16Array)(t)}function _t(t){return t.buffer&&t.buffer instanceof ArrayBuffer?t.buffer:t}function xt(t,e){return void 0===t?t=new e:Array.isArray(t)&&(t=(new e).fromArray(t)),t}function vt(t){return xt(t,e)}function wt(t){return xt(t,i)}function At(t){return xt(t,r)}function St(t){return e=t,i=Float32Array,e instanceof i?e:new i(e);var e,i}function Ct(t){return rt(t,"").toString().toLowerCase()}class Pt{constructor(t){this.name=t,this._dict={}}add(t,e){this._dict[Ct(t)]=e}get(t){return this._dict[Ct(t)]}get names(){return Object.keys(this._dict)}}function It(t){return.01745*t}const kt="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split(""),Mt=new Array(36);function Tt(){let t,e=0;for(let i=0;i<36;i++)8===i||13===i||18===i||23===i?Mt[i]="-":14===i?Mt[i]="4":(e<=2&&(e=33554432+16777216*Math.random()|0),t=15&e,e>>=4,Mt[i]=kt[19===i?3&t|8:t]);return Mt.join("")}function Dt(t,e,i){return Math.max(e,Math.min(i,t))}function Bt(t,e,i){return t+(e-t)*i}function Ft(t,e,i,r,n,s){const o=(i-t)*s,a=(r-e)*s,c=n*n;return(2*e-2*i+o+a)*(n*c)+(-3*e+3*i-2*o-a)*c+o*n+e}function Et(t,e,i){var r;return r=function(t,e,i){return(t-e)/(i-e)}(i,t,e),(i=Dt(r,0,1))*i*(3-2*i)}var $t="sRGB";const Ot={scale:"uniform",mode:"hcl",domain:[0,1],value:16777215,reverse:!1},Rt=new n;function Lt(t,e,i){const r=i.value;return i.value=function(t,e){let i=r.bind(this,t,e)();return"linear"==$t?(Rt.set(i),Rt.convertSRGBToLinear(),Rt.getHex()):i},i}class Nt{constructor(t={}){this.parameters=nt(t,Ot),"string"==typeof this.parameters.value&&(this.parameters.value=Rt.set(this.parameters.value).getHex()),this.parameters.structure&&(this.atomProxy=this.parameters.structure.getAtomProxy())}getScale(t={}){const e=nt(t,this.parameters);return"rainbow"===e.scale?e.scale=["red","orange","yellow","green","blue"]:"rwb"===e.scale&&(e.scale=["red","white","blue"]),e.reverse&&(e.domain=e.domain.slice().reverse()),Q.scale(e.scale).mode(e.mode).domain(e.domain).out("num")}colorToArray(t,e=[],i=0){return e[i]=(t>>16&255)/255,e[i+1]=(t>>8&255)/255,e[i+2]=(255&t)/255,e}atomColorToArray(t,e,i){return this.colorToArray(this.atomColor?this.atomColor(t):0,e,i)}bondColor(t,e){return this.atomProxy&&this.atomColor?(this.atomProxy.index=e?t.atomIndex1:t.atomIndex2,this.atomColor(this.atomProxy)):0}bondColorToArray(t,e,i,r){return this.colorToArray(this.bondColor(t,e),i,r)}volumeColorToArray(t,e,i){return this.colorToArray(this.volumeColor?this.volumeColor(t):0,e,i)}positionColorToArray(t,e,i){return this.colorToArray(this.positionColor?this.positionColor(t):0,e,i)}}var zt;!function(t){t[t.PROTEIN=1]="PROTEIN",t[t.NUCLEIC=2]="NUCLEIC",t[t.RNA=3]="RNA",t[t.DNA=4]="DNA",t[t.POLYMER=5]="POLYMER",t[t.WATER=6]="WATER",t[t.HELIX=7]="HELIX",t[t.SHEET=8]="SHEET",t[t.TURN=9]="TURN",t[t.BACKBONE=10]="BACKBONE",t[t.SIDECHAIN=11]="SIDECHAIN",t[t.ALL=12]="ALL",t[t.HETERO=13]="HETERO",t[t.ION=14]="ION",t[t.SACCHARIDE=15]="SACCHARIDE",t[t.SUGAR=15]="SUGAR",t[t.BONDED=16]="BONDED",t[t.RING=17]="RING",t[t.AROMATICRING=18]="AROMATICRING",t[t.METAL=19]="METAL",t[t.POLARH=20]="POLARH",t[t.NONE=21]="NONE"}(zt||(zt={}));const Ut=["*","","ALL"],Vt=["NONE"],jt=[zt.BACKBONE,zt.SIDECHAIN,zt.BONDED,zt.RING,zt.AROMATICRING,zt.METAL,zt.POLARH],Gt=[zt.POLYMER,zt.WATER],Ht=["ALA","GLY","SER"],qt=["CYS","SER","THR"],Wt=["ALA","ILE","LEU","MET","PHE","PRO","TRP","VAL"],Xt=["PHE","TRP","TYR","HIS"],Yt=["ASN","GLN"],Kt=["ASP","GLU"],Zt=["ARG","HIS","LYS"],Qt=["ARG","ASP","GLU","HIS","LYS"],Jt=["ASN","ARG","ASP","CYS","GLY","GLN","GLU","HIS","LYS","SER","THR","TYR"],te=["ALA","ILE","LEU","MET","PHE","PRO","TRP","VAL"],ee=["HIS","PHE","PRO","TRP","TYR"],ie=["ALA","GLY","ILE","LEU","VAL"];function re(t,e){if(void 0===e.atomname&&void 0===e.element&&void 0===e.altloc&&void 0===e.atomindex&&void 0===e.keyword&&void 0===e.inscode&&void 0===e.resname&&void 0===e.sstruc&&void 0===e.resno&&void 0===e.chainname&&void 0===e.model)return-1;if(void 0!==e.keyword){if(e.keyword===zt.BACKBONE&&!t.isBackbone())return!1;if(e.keyword===zt.SIDECHAIN&&!t.isSidechain())return!1;if(e.keyword===zt.BONDED&&!t.isBonded())return!1;if(e.keyword===zt.RING&&!t.isRing())return!1;if(e.keyword===zt.AROMATICRING&&!t.isAromatic())return!1;if(e.keyword===zt.HETERO&&!t.isHetero())return!1;if(e.keyword===zt.PROTEIN&&!t.isProtein())return!1;if(e.keyword===zt.NUCLEIC&&!t.isNucleic())return!1;if(e.keyword===zt.RNA&&!t.isRna())return!1;if(e.keyword===zt.DNA&&!t.isDna())return!1;if(e.keyword===zt.POLYMER&&!t.isPolymer())return!1;if(e.keyword===zt.WATER&&!t.isWater())return!1;if(e.keyword===zt.HELIX&&!t.isHelix())return!1;if(e.keyword===zt.SHEET&&!t.isSheet())return!1;if(e.keyword===zt.TURN&&!t.isTurn())return!1;if(e.keyword===zt.ION&&!t.isIon())return!1;if(e.keyword===zt.SACCHARIDE&&!t.isSaccharide())return!1;if(e.keyword===zt.METAL&&!t.isMetal())return!1;if(e.keyword===zt.POLARH&&!t.isPolarHydrogen())return!1}if(void 0!==e.atomname&&e.atomname!==t.atomname)return!1;if(void 0!==e.element&&e.element!==t.element)return!1;if(void 0!==e.altloc&&e.altloc!==t.altloc)return!1;if(void 0!==e.atomindex&&mt(e.atomindex,t.index)<0)return!1;if(void 0!==e.resname)if(Array.isArray(e.resname)){if(!e.resname.includes(t.resname))return!1}else if(e.resname!==t.resname)return!1;if(void 0!==e.sstruc&&e.sstruc!==t.sstruc)return!1;if(void 0!==e.resno)if(Array.isArray(e.resno)&&2===e.resno.length){if(e.resno[0]>t.resno||e.resno[1]t.resno||e.resno[1]0?t:null}function le(t,e=!1){let i=t;return e&&(i=ce(t,(function(t){return void 0!==t.keyword&&!jt.includes(t.keyword)||(void 0!==t.model||(void 0!==t.chainname||(void 0!==t.resname||(void 0!==t.resno||void 0!==t.sstruc))))}))),ae(i,re)}function he(t,e=!1){let i=t;return e&&(i=ce(t,(function(t){return!(void 0===t.keyword||!jt.includes(t.keyword))||(void 0!==t.model||(void 0!==t.chainname||(void 0!==t.atomname||(void 0!==t.element||void 0!==t.altloc))))}))),ae(i,ne)}function ue(t,e=!1){let i=t;return e&&(i=ce(t,(function(t){return void 0!==t.keyword&&!Gt.includes(t.keyword)||(void 0!==t.resname||(void 0!==t.resno||(void 0!==t.atomname||(void 0!==t.element||(void 0!==t.altloc||(void 0!==t.sstruc||void 0!==t.inscode))))))}))),ae(i,se)}function de(t,e=!1){let i=t;return e&&(i=ce(t,(function(t){return void 0!==t.keyword||(void 0!==t.chainname||(void 0!==t.resname||(void 0!==t.resno||(void 0!==t.atomname||(void 0!==t.element||(void 0!==t.altloc||(void 0!==t.sstruc||void 0!==t.inscode)))))))}))),ae(i,oe)}class me{constructor(t){this.signals={stringChanged:new tt},this.setString(t)}get type(){return"selection"}setString(t,e){if(void 0===t&&(t=this.string||""),t===this.string)return;try{this.selection=function(t){let e={operator:void 0,rules:[]};if(!t)return e;let i,r,n=e;const s=[];"("===(t=t.replace(/\(/g," ( ").replace(/\)/g," ) ").trim()).charAt(0)&&")"===t.substr(-1)&&(t=t.slice(1,-1).trim());const o=t.split(/\s+/),a=t=>{i={operator:t,rules:[]},void 0===n?(n=i,e=i):(n.rules.push(i),s.push(n),n=i)},c=function(t){r=n,n=s.pop(),void 0===n&&(a(t),l(r))},l=function(t){n.rules.push(t)};let h=!1;for(let t=0;t0)if("NOT"===i)h=1;else if(1===h)h=2;else{if(2!==h)throw new Error("something went wrong with 'not'");h=!1,c()}if("AND"===i){if("OR"===n.operator){const t=n.rules.pop();a("AND"),l(t)}else n.operator="AND";continue}if("OR"===i){"AND"===n.operator?c("OR"):n.operator="OR";continue}if("NOT"===e.toUpperCase()){h=1,a(),n.negate=!0;continue}if(+i!=+i){const t=zt[i];if(void 0!==t){l({keyword:t});continue}}if("HYDROGEN"===i){l({operator:"OR",rules:[{element:"H"},{element:"D"}]});continue}if("SMALL"===i){l({resname:Ht});continue}if("NUCLEOPHILIC"===i){l({resname:qt});continue}if("HYDROPHOBIC"===i){l({resname:Wt});continue}if("AROMATIC"===i){l({resname:Xt});continue}if("AMIDE"===i){l({resname:Yt});continue}if("ACIDIC"===i){l({resname:Kt});continue}if("BASIC"===i){l({resname:Zt});continue}if("CHARGED"===i){l({resname:Qt});continue}if("POLAR"===i){l({resname:Jt});continue}if("NONPOLAR"===i){l({resname:te});continue}if("CYCLIC"===i){l({resname:ee});continue}if("ALIPHATIC"===i){l({resname:ie});continue}if("SIDECHAINATTACHED"===i){l({operator:"OR",rules:[{keyword:zt.SIDECHAIN},{operator:"AND",negate:!1,rules:[{keyword:zt.PROTEIN},{operator:"OR",negate:!1,rules:[{atomname:"CA"},{atomname:"BB"}]}]},{operator:"AND",negate:!1,rules:[{resname:"PRO"},{atomname:"N"}]},{operator:"AND",negate:!1,rules:[{keyword:zt.NUCLEIC},{operator:"OR",negate:!0,rules:[{atomname:"P"},{atomname:"OP1"},{atomname:"OP2"},{atomname:"O3'"},{atomname:"O3*"},{atomname:"HO3'"},{atomname:"O5'"},{atomname:"O5*"},{atomname:"HO5'"},{atomname:"C5'"},{atomname:"C5*"},{atomname:"H5'"},{atomname:"H5''"}]}]}]});continue}if("APOLARH"===i){l({operator:"AND",negate:!1,rules:[{element:"H"},{negate:!0,operator:void 0,rules:[{keyword:zt.POLARH}]}]});continue}if("LIGAND"===i){l({operator:"AND",rules:[{operator:"OR",rules:[{operator:"AND",rules:[{keyword:zt.HETERO},{negate:!0,operator:void 0,rules:[{keyword:zt.POLYMER}]}]},{negate:!0,operator:void 0,rules:[{keyword:zt.POLYMER}]}]},{negate:!0,operator:void 0,rules:[{operator:"OR",rules:[{keyword:zt.WATER},{keyword:zt.ION}]}]}]});continue}if(-1!==Ut.indexOf(i)){l({keyword:zt.ALL});continue}if("@"===e.charAt(0)){const t=e.substr(1).split(",").map((t=>parseInt(t)));t.sort((function(t,e){return t-e})),l({atomindex:t});continue}if("#"===e.charAt(0)){console.error("# for element selection deprecated, use _"),l({element:i.substr(1)});continue}if("_"===e.charAt(0)){l({element:i.substr(1)});continue}if("["===e[0]&&"]"===e[e.length-1]){const t=i.substr(1,e.length-2).split(","),r=t.length>1?t:t[0];l({resname:r});continue}if(e.length>=1&&e.length<=4&&"^"!==e[0]&&":"!==e[0]&&"."!==e[0]&&"%"!==e[0]&&"/"!==e[0]&&isNaN(parseInt(e))){l({resname:i});continue}const r={operator:"AND",rules:[]},s=e.split("/");if(s.length>1&&s[1]){if(isNaN(parseInt(s[1])))throw new Error("model must be an integer");r.rules.push({model:parseInt(s[1])})}const u=s[0].split("%");u.length>1&&r.rules.push({altloc:u[1]});const d=u[0].split(".");if(d.length>1&&d[1]){if(d[1].length>4)throw new Error("atomname must be one to four characters");r.rules.push({atomname:d[1].substring(0,4).toUpperCase()})}const m=d[0].split(":");m.length>1&&m[1]&&r.rules.push({chainname:m[1]});const f=m[0].split("^");if(f.length>1&&r.rules.push({inscode:f[1]}),f[0]){let t,e;"-"===f[0][0]&&(f[0]=f[0].substr(1),t=!0),f[0].includes("--")&&(f[0]=f[0].replace("--","-"),e=!0);let i=f[0].split("-");if(1===i.length){let e=parseInt(i[0]);if(isNaN(e))throw new Error("resi must be an integer");t&&(e*=-1),r.rules.push({resno:e})}else{if(2!==i.length)throw new Error("resi range must contain one '-'");{const n=i.map((t=>parseInt(t)));t&&(n[0]*=-1),e&&(n[1]*=-1),r.rules.push({resno:[n[0],n[1]]})}}}if(1===r.rules.length)l(r.rules[0]);else{if(!(r.rules.length>1))throw new Error("empty selection chunk");l(r)}}return void 0===e.operator&&1===e.rules.length&&e.rules[0].hasOwnProperty("operator")&&(e=e.rules[0]),e}(t)}catch(t){this.selection={error:t.message}}const i=this.selection;this.string=t,this.test=le(i),this.residueTest=he(i),this.chainTest=ue(i),this.modelTest=de(i),this.atomOnlyTest=le(i,!0),this.residueOnlyTest=he(i,!0),this.chainOnlyTest=ue(i,!0),this.modelOnlyTest=de(i,!0),e||this.signals.stringChanged.dispatch(this.string)}isAllSelection(){return Ut.includes(this.string.toUpperCase())}isNoneSelection(){return Vt.includes(this.string.toUpperCase())}}class fe extends Nt{constructor(t){super(t),this.colormakerList=[],this.selectionList=[];(t.dataList||[]).forEach((t=>{const[e,i,r={}]=t;Oe.hasScheme(e)?Object.assign(r,{scheme:e,structure:this.parameters.structure}):Object.assign(r,{scheme:"uniform",value:new n(e).getHex()}),this.colormakerList.push(Oe.getScheme(r)),this.selectionList.push(new me(i))}))}atomColor(t){for(let e=0,i=this.selectionList.length;e{}),t)}catch(t){}const Ae="undefined"!=typeof window&&void 0!==window.orientation;let Se=!1;function Ce(t){Se=t}let Pe=!1;function Ie(t){Pe=t}const ke={log:Function.prototype.bind.call(console.log,console),info:Function.prototype.bind.call(console.info,console),warn:Function.prototype.bind.call(console.warn,console),error:Function.prototype.bind.call(console.error,console),time:Function.prototype.bind.call(console.time,console),timeEnd:Function.prototype.bind.call(console.timeEnd,console)};let Me={color:"green",labelColor:8421504,labelAttachment:"bottom-center",labelSize:.7,labelZOffset:.5,labelYOffset:.1,labelBorder:!0,labelBorderColor:13882323,labelBorderWidth:.25,lineOpacity:.8,linewidth:5,opacity:.6,labelUnit:"angstrom",arcVisible:!0,planeVisible:!1};function Te(t={}){Object.assign(Me,t)}let De=!!(Be=it("debug"))&&("string"!=typeof Be||/^1|true|t|yes|y$/i.test(Be));var Be;function Fe(t){De=t}const Ee=["ngl","js"],$e=new class{constructor(){this.activeWorkerCount=0,this._funcDict={},this._depsDict={},this._blobDict={}}add(t,e,i){this._funcDict[t]=e,this._depsDict[t]=i}get(t){return this._blobDict[t]||(this._blobDict[t]=xe(this._funcDict[t],this._depsDict[t])),this._blobDict[t]}},Oe=new class{constructor(){this.schemes={},this.userSchemes={}}getScheme(t){const e=((t||{}).scheme||"").toLowerCase();let i;return i=e in this.schemes?this.schemes[e]:e in this.userSchemes?this.userSchemes[e]:Nt,new i(t)}getSchemes(){const t={};return Object.keys(this.schemes).forEach((function(e){t[e]=e})),Object.keys(this.userSchemes).forEach((function(e){t[e]=e.split("|")[1]})),t}getScales(){return pe}getModes(){return ge}add(t,e){t=t.toLowerCase(),this.schemes[t]=e}addScheme(t,e){return function(t){return t instanceof Nt}(t)||(t=this._createScheme(t)),this._addUserScheme(t,e)}_addUserScheme(t,e){e=e||"";const i=`${Tt()}|${e}`.toLowerCase();return this.userSchemes[i]=t,i}removeScheme(t){t=t.toLowerCase(),delete this.userSchemes[t]}_createScheme(t){return class extends Nt{constructor(e){super(e),t.call(this,e)}}}addSelectionScheme(t,e){return this._addUserScheme(class extends fe{constructor(e){super(Object.assign({dataList:t},e))}},e)}hasScheme(t){return(t=t.toLowerCase())in this.schemes||t in this.userSchemes}},Re=new Pt("datasource"),Le=new Pt("representatation"),Ne=new class extends Pt{constructor(){super("parser")}__hasObjName(t,e){const i=this.get(t);return i&&i.prototype.__objName===e}isTrajectory(t){return this.__hasObjName(t,"frames")}isStructure(t){return this.__hasObjName(t,"structure")}isVolume(t){return this.__hasObjName(t,"volume")}isSurface(t){return this.__hasObjName(t,"surface")}isBinary(t){const e=this.get(t);return e&&e.prototype.isBinary}isXml(t){const e=this.get(t);return e&&e.prototype.isXml}isJson(t){const e=this.get(t);return e&&e.prototype.isJson}getTrajectoryExtensions(){return this.names.filter((t=>this.isTrajectory(t)))}getStructureExtensions(){return this.names.filter((t=>this.isStructure(t)))}getVolumeExtensions(){return this.names.filter((t=>this.isVolume(t)))}getSurfaceExtensions(){return this.names.filter((t=>this.isSurface(t)))}},ze=new Pt("shader"),Ue=new Pt("decompressor"),Ve=new Pt("component"),je=new Pt("buffer"),Ge=new Pt("picker");let He,qe;function We(t){He=t}function Xe(t){qe=t}class Ye{constructor(t,e={}){this.chunkSize=10485760,this.newline="\n",this.__pointer=0,this.__partialLine="",this.compressed=rt(e.compressed,!1),this.binary=rt(e.binary,!1),this.json=rt(e.json,!1),this.xml=rt(e.xml,!1),this.src=t}isBinary(){return this.binary||this.compressed}read(){return this._read().then((t=>{const e=this.compressed?Ue.get(this.compressed):void 0;return this.compressed&&e?this.data=e(t):((this.binary||this.compressed)&&t instanceof ArrayBuffer&&(t=new Uint8Array(t)),this.data=t),this.data}))}_chunk(t,e){return e=Math.min(this.data.length,e),0===t&&this.data.length===e?this.data:this.isBinary()?this.data.subarray(t,e):this.data.substring(t,e)}chunk(t){const e=t+this.chunkSize;return this._chunk(t,e)}peekLines(t){const e=this.data,i=e.length,r=this.isBinary()?this.newline.charCodeAt(0):this.newline;let n,s=0;for(n=0;ni).lines}chunkCount(){return Math.floor(this.data.length/this.chunkSize)+1}asText(){return this.isBinary()?gt(this.data):this.data}chunkToLines(t,e,i){const r=this.newline;if(!this.isBinary()&&t.length===this.data.length)return{lines:t.split(r),partialLine:""};let n=[];const s=this.isBinary()?gt(t):t,o=s.lastIndexOf(r);if(-1===o)e+=s;else{const t=e+s.substr(0,o);n=n.concat(t.split(r)),e=o===s.length-r.length?"":s.substr(o+r.length)}return i&&""!==e&&n.push(e),{lines:n,partialLine:e}}nextChunk(){const t=this.__pointer;if(!(t>this.data.length))return this.__pointer+=this.chunkSize,this.chunk(t)}nextChunkOfLines(){const t=this.nextChunk();if(void 0===t)return;const e=this.__pointer>this.data.length,i=this.chunkToLines(t,this.__partialLine,e);return this.__partialLine=i.partialLine,i.lines}eachChunk(t){const e=this.chunkSize,i=this.data.length,r=this.chunkCount();for(let n=0;n{const n=i===r+1,s=this.chunkToLines(e,this.__partialLine,n);this.__partialLine=s.partialLine,t(s.lines,i,r)}))}dispose(){delete this.src}}class Ke extends Ye{_read(){return new Promise(((t,e)=>{const i=this.src,r=new FileReader;r.onload=e=>{e.target&&t(e.target.result)},r.onerror=t=>e(t),this.binary||this.compressed?r.readAsArrayBuffer(i):r.readAsText(i)}))}}class Ze extends Ye{_read(){return new Promise(((t,e)=>{const i=this.src,r=new XMLHttpRequest;r.open("GET",i,!0),r.addEventListener("load",(()=>{if(200===r.status||304===r.status||0===r.status)try{t(r.response)}catch(t){e(t)}else e(r.statusText)}),!1),r.addEventListener("error",(t=>e("network error")),!1),this.isBinary()?r.responseType="arraybuffer":this.json?r.responseType="json":this.xml?r.responseType="document":r.responseType="text",r.send()}))}}class Qe{constructor(t,e={}){this.parameters=nt(e,{ext:"",compressed:!1,binary:Ne.isBinary(e.ext||""),name:"",dir:"",path:"",protocol:""});const i={compressed:this.parameters.compressed,binary:this.parameters.binary,json:Ne.isJson(this.parameters.ext),xml:Ne.isXml(this.parameters.ext)};"undefined"!=typeof File&&t instanceof File||"undefined"!=typeof Blob&&t instanceof Blob?this.streamer=new Ke(t,i):this.streamer=new Ze(t,i)}}class Je extends Qe{constructor(t,e={}){super(t,e),this.parserParams={voxelSize:e.voxelSize,firstModelOnly:e.firstModelOnly,asTrajectory:e.asTrajectory,cAlphaOnly:e.cAlphaOnly,delimiter:e.delimiter,comment:e.comment,columnNames:e.columnNames,inferBonds:e.inferBonds,name:this.parameters.name,path:this.parameters.path}}load(){return new(Ne.get(this.parameters.ext))(this.streamer,this.parserParams).parse()}}class ti{constructor(t,e,i){this.name=e,this.path=i,this.signals={elementAdded:new tt,elementRemoved:new tt,nameChanged:new tt},this.type="Script",this.dir=i.substring(0,i.lastIndexOf("/")+1);try{this.fn=new Function("stage","__name","__path","__dir",t)}catch(t){ke.error("Script compilation failed",t),this.fn=function(){}}}run(t){return new Promise(((e,i)=>{try{this.fn.apply(null,[t,this.name,this.path,this.dir]),e()}catch(t){ke.error("Script.fn",t),i(t)}}))}}class ei extends Qe{load(){return this.streamer.read().then((()=>new ti(this.streamer.asText(),this.parameters.name,this.parameters.path)))}}function ii(t){const e=Ue.names;let i,r,n="";i=t instanceof File?t.name:t instanceof Blob?"":t;const s=i.lastIndexOf("?"),o=-1!==s?i.substring(s):"";i=i.substring(0,-1===s?i.length:s);const a=i.replace(/^.*[\\/]/,"");let c=a.substring(0,a.lastIndexOf("."));const l=a.split(".");let h=l.length>1?(l.pop()||"").toLowerCase():"";const u=i.match(/^(.+):\/\/(.+)$/);u&&(n=u[1].toLowerCase(),i=u[2]||"");const d=i.substring(0,i.lastIndexOf("/")+1);if(e.includes(h)){r=h;const t=i.length-h.length-1;h=(i.substr(0,t).split(".").pop()||"").toLowerCase();const e=c.length-h.length-1;c=c.substr(0,e)}else r=!1;return{path:i,name:a,ext:h,base:c,dir:d,compressed:r,protocol:n,query:o,src:t}}function ri(t){let e=ii(t);const i=Re.get(e.protocol);return i&&(e=ii(i.getUrl(e.src)),!e.ext&&i.getExt&&(e.ext=i.getExt(t))),e}function ni(t,e={}){const i=Object.assign(ri(t),e);let r;return Ne.names.includes(i.ext)?r=new Je(i.src,i):Ee.includes(i.ext)&&(r=new ei(i.src,i)),r?r.load():Promise.reject(new Error(`autoLoad: ext '${i.ext}' unknown`))}class si{getBlob(){return new Blob([this.getData()],{type:this.mimeType})}download(t,e){t=rt(t,this.defaultName),e=rt(e,this.defaultExt),ht(this.getBlob(),`${t}.${e}`)}}class oi extends si{constructor(t,e){super(),this.mimeType="text/plain",this.defaultName="structure",this.defaultExt="pdb";const i=Object.assign({},e);this.renumberSerial=rt(i.renumberSerial,!0),this.remarks=function(t){return Array.isArray(t)?t:[t]}(rt(i.remarks,[])),this.structure=t,this._records=[]}_writeRecords(){this._records.length=0,this._writeTitle(),this._writeRemarks(),this._writeAtoms()}_writeTitle(){this._records.push(et("TITLE %-74s",this.structure.name))}_writeRemarks(){this.remarks.forEach((t=>{this._records.push(et("REMARK %-73s",t))})),this.structure.trajectory&&(this._records.push(et("REMARK %-73s","Trajectory '"+this.structure.trajectory.name+"'")),this._records.push(et("REMARK %-73s",`Frame ${this.structure.trajectory.frame}`)))}_writeAtoms(){let t=1,e=1,i=" ",r=" ";const n=this.structure.modelStore.count>1;this.structure.eachModel((s=>{n&&this._records.push(et("MODEL %4d%-66s",e++,"")),s.eachAtom((e=>{const n=e.hetero?"HETATM%5d %-4s %3s %1s%4d %8.3f%8.3f%8.3f%6.2f%6.2f %4s%2s%1s%1s":"ATOM %5d %-4s %3s %1s%4d %8.3f%8.3f%8.3f%6.2f%6.2f %4s%2s%1s%1s",s=this.renumberSerial?t:e.serial;let o=e.atomname;(1===o.length||o.length<4&&1===e.element.length&&o[0]===e.element)&&(o=" "+o),e.formalCharge?(i=Math.abs(e.formalCharge).toPrecision(1),r=e.formalCharge>0?"+":"-"):(i=" ",r=" "),this._records.push(et(n,s,o,e.resname,rt(e.chainname," "),e.resno,e.x,e.y,e.z,rt(e.occupancy,1),rt(e.bfactor,0),"",rt(e.element,""),i,r)),t+=1}),this.structure.getSelection()),n&&this._records.push(et("%-80s","ENDMDL"))})),this._records.push(et("%-80s","END"))}getString(){return console.warn("PdbWriter.getString() is deprecated, use .getData instead"),this.getData()}getData(){return this._writeRecords(),this._records.join("\n")}}class ai extends si{constructor(t){super(),this.mimeType="text/plain",this.defaultName="structure",this.defaultExt="sdf",this.structure=t,this._records=[]}get idString(){return this.structure.id}get titleString(){return" "+this.structure.title}get countsString(){return et("%3i%3i 0 0 0 0 0 0 0 0999 V2000",this.structure.atomCount,this.structure.bondCount)}get chargeLines(){const t=[];this.structure.eachAtom((e=>{null!=e.formalCharge&&0!==e.formalCharge&&t.push([e.index,e.formalCharge])}));const e=[];for(let i=0;i{this._records.push(this.formatAtom(t))})),this.structure.eachBond((t=>{this._records.push(this.formatBond(t))})),this.chargeLines.forEach((t=>{this._records.push(t)})),this._records.push("M END")}_writeFooter(){this._records.push("$$$$")}getData(){return this._writeRecords(),this._records.join("\n")}}const ci=[];class li{constructor(t,e={}){this._mark=0,this._marks=[],this.offset=0,this.littleEndian=!0;let i=!1;void 0===t&&(t=8192),"number"==typeof t?t=new ArrayBuffer(t):i=!0;const r=e.offset?e.offset>>>0:0;let n=t.byteLength-r,s=r;t instanceof ArrayBuffer||(t.byteLength!==t.buffer.byteLength&&(s=t.byteOffset+r),t=t.buffer),this._lastWrittenByte=i?n:0,this.buffer=t,this.length=n,this.byteLength=n,this.byteOffset=s,this._data=new DataView(this.buffer,s,n)}available(t){return void 0===t&&(t=1),this.offset+t<=this.length}isLittleEndian(){return this.littleEndian}setLittleEndian(){return this.littleEndian=!0,this}isBigEndian(){return!this.littleEndian}setBigEndian(){return this.littleEndian=!1,this}skip(t){return void 0===t&&(t=1),this.offset+=t,this}seek(t){return this.offset=t,this}mark(){return this._mark=this.offset,this}reset(){return this.offset=this._mark,this}pushMark(){return this._marks.push(this.offset),this}popMark(){const t=this._marks.pop();if(void 0===t)throw new Error("Mark stack empty");return this.seek(t),this}rewind(){return this.offset=0,this}ensureAvailable(t){if(void 0===t&&(t=1),!this.available(t)){const e=2*(this.offset+t),i=new Uint8Array(e);i.set(new Uint8Array(this.buffer)),this.buffer=i.buffer,this.length=this.byteLength=e,this._data=new DataView(this.buffer)}return this}readBoolean(){return 0!==this.readUint8()}readInt8(){return this._data.getInt8(this.offset++)}readUint8(){return this._data.getUint8(this.offset++)}readByte(){return this.readUint8()}readBytes(t){void 0===t&&(t=1);for(var e=new Uint8Array(t),i=0;ithis._lastWrittenByte&&(this._lastWrittenByte=this.offset)}}class hi extends si{constructor(t){super(),this.mimeType="application/vnd.ms-pki.stl",this.defaultName="surface",this.defaultExt="stl",this.surface=t}getData(){const t=this.surface.index.length/3,i=new li(2*t+3*t*4*4+80+4);i.skip(80),i.writeUint32(t);const r=new e,n=new e,s=new e,o=new e;for(let e=0;e{0===this.count&&(this.signals.countChanged.remove(i,this),t.call(e))};this.signals.countChanged.add(i,this)}}dispose(){this.clear(),this.signals.countChanged.dispose()}}ze.add("shader/BasicLine.vert","void main(){\n#include begin_vertex\n#include project_vertex\n}"),ze.add("shader/BasicLine.frag","uniform vec3 uColor;\n#include common\n#include fog_pars_fragment\nvoid main(){\ngl_FragColor = vec4( uColor, 1.0 );\n#include premultiplied_alpha_fragment\n#include tonemapping_fragment\n#include colorspace_fragment\n#include fog_fragment\n}"),ze.add("shader/Quad.vert","varying vec2 vUv;\nvoid main() {\nvUv = uv;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}"),ze.add("shader/Quad.frag","varying vec2 vUv;\nuniform sampler2D tForeground;\nuniform float scale;\nvoid main() {\nvec4 foreground = texture2D( tForeground, vUv );\ngl_FragColor = foreground * scale;\n}");class di{constructor(){this.signals={updated:new J.Signal},this.maxDuration=-1/0,this.minDuration=1/0,this.avgDuration=14,this.lastDuration=1/0,this.prevFpsTime=0,this.lastFps=1/0,this.lastFrames=1,this.frames=0,this.count=0,this.begin()}update(){this.startTime=this.end(),this.currentTime=this.startTime,this.signals.updated.dispatch()}begin(){this.startTime=window.performance.now(),this.lastFrames=this.frames}end(){const t=window.performance.now();return this.count+=1,this.frames+=1,this.lastDuration=t-this.startTime,this.minDuration=Math.min(this.minDuration,this.lastDuration),this.maxDuration=Math.max(this.maxDuration,this.lastDuration),this.avgDuration-=this.avgDuration/30,this.avgDuration+=this.lastDuration/30,t>this.prevFpsTime+1e3&&(this.lastFps=this.frames,this.prevFpsTime=t,this.frames=0),t}}ze.add("shader/chunk/fog_fragment.glsl","#ifdef USE_FOG\nfloat depth = length( vViewPosition );\n#ifdef FOG_EXP2\nfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );\n#else\nfloat fogFactor = smoothstep( fogNear, fogFar, depth );\n#endif\ngl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif"),ze.add("shader/chunk/interior_fragment.glsl","if( gl_FrontFacing == false ){\n#ifdef USE_INTERIOR_COLOR\noutgoingLight.xyz = interiorColor;\n#else\n#ifdef DIFFUSE_INTERIOR\noutgoingLight.xyz = vColor;\n#endif\n#endif\noutgoingLight.xyz *= 1.0 - interiorDarkening;\n}"),ze.add("shader/chunk/matrix_scale.glsl","float matrixScale( in mat4 m ){\nvec4 r = m[ 0 ];\nreturn sqrt( r[ 0 ] * r[ 0 ] + r[ 1 ] * r[ 1 ] + r[ 2 ] * r[ 2 ] );\n}"),ze.add("shader/chunk/nearclip_vertex.glsl","#ifdef NEAR_CLIP\nif( vViewPosition.z < clipNear - 5.0 )\ngl_Position.z = 2.0 * gl_Position.w;\n#endif"),ze.add("shader/chunk/nearclip_fragment.glsl","#ifdef NEAR_CLIP\nif( vViewPosition.z < clipNear )\ndiscard;\n#endif"),ze.add("shader/chunk/opaque_back_fragment.glsl","#ifdef OPAQUE_BACK\n#ifdef FLIP_SIDED\nif( gl_FrontFacing == true ){\ngl_FragColor.a = 1.0;\n}\n#else\nif( gl_FrontFacing == false ){\ngl_FragColor.a = 1.0;\n}\n#endif\n#endif"),ze.add("shader/chunk/radiusclip_vertex.glsl","#ifdef RADIUS_CLIP\nif( distance( vViewPosition, vClipCenter ) > clipRadius + 5.0 )\ngl_Position.z = 2.0 * gl_Position.w;\n#endif"),ze.add("shader/chunk/radiusclip_fragment.glsl","#ifdef RADIUS_CLIP\nif( distance( vViewPosition, vClipCenter ) > clipRadius )\ndiscard;\n#endif"),ze.add("shader/chunk/unpack_color.glsl","vec3 unpackColor(float f) {\nvec3 color;\ncolor.r = floor(f / 256.0 / 256.0);\ncolor.g = floor((f - color.r * 256.0 * 256.0) / 256.0);\ncolor.b = floor(f - color.r * 256.0 * 256.0 - color.g * 256.0);\nreturn color / 255.0;\n}");const mi=/^(?!\/\/)\s*#include\s+(\S+)/gim,fi={};function pi(t,e={}){let i=t+"|";for(const t in e)i+=t+":"+e[t];if(!fi[i]){const r=function(t){if(void 0===t)return"";const e=[];for(const i in t){const r=t[i];r&&e.push(`#define ${i} ${r}`)}return e.join("\n")+"\n"}(e);let n=ze.get(`shader/${t}`);if(!n)throw new Error(`empty shader, '${t}'`);n=n.replace(mi,(function(t,e){const i=`shader/chunk/${e}.glsl`,r=ze.get(i)||s[e];if(!r)throw new Error(`empty chunk, '${e}'`);return r})),fi[i]=r+n}return fi[i]}if("undefined"!=typeof WebGLRenderingContext){const t=WebGLRenderingContext.prototype,e=t.getShaderParameter;t.getShaderParameter=function(){return!De||e.apply(this,arguments)};const i=t.getShaderInfoLog;t.getShaderInfoLog=function(){return De?i.apply(this,arguments):""};const r=t.getProgramParameter;t.getProgramParameter=function(e,i){return!De&&i===t.LINK_STATUS||r.apply(this,arguments)};const n=t.getProgramInfoLog;t.getProgramInfoLog=function(){return De?n.apply(this,arguments):""}}const gi=[[[0,0]],[[4,4],[-4,-4]],[[-2,-6],[6,-2],[-6,2],[2,6]],[[1,-3],[-1,3],[5,1],[-3,-5],[-5,5],[-7,-1],[3,7],[7,-7]],[[1,1],[-1,-3],[-3,2],[4,-1],[-5,-2],[2,5],[5,3],[3,-5],[-2,6],[0,-7],[-4,-6],[-6,4],[-8,0],[7,-4],[6,7],[-7,-8]],[[-4,-7],[-7,-5],[-3,-5],[-5,-4],[-1,-4],[-2,-2],[-6,-1],[-4,0],[-7,1],[-1,2],[-6,3],[-3,3],[-7,6],[-3,6],[-5,7],[-1,7],[5,-7],[1,-6],[6,-5],[4,-4],[2,-3],[7,-2],[1,-1],[4,-1],[2,1],[6,2],[0,4],[4,4],[2,5],[7,5],[5,6],[3,7]]];gi.forEach((t=>{t.forEach((t=>{t[0]*=.0625,t[1]*=.0625}))}));class yi{constructor(t,e,i,r){this.canvas=document.createElement("canvas"),this._viewer=i,this._factor=rt(r.factor,2),this._antialias=rt(r.antialias,!1),this._onProgress=r.onProgress,this._onFinish=r.onFinish,this._antialias&&(this._factor*=2),this._n=this._factor*this._factor,this._width=this._viewer.width,this._height=this._viewer.height,this._antialias?(this.canvas.width=this._width*this._factor/2,this.canvas.height=this._height*this._factor/2):(this.canvas.width=this._width*this._factor,this.canvas.height=this._height*this._factor),this._ctx=this.canvas.getContext("2d"),this._viewerSampleLevel=i.sampleLevel,this._viewer.setSampling(-1)}_renderTile(t){const e=this._viewer,i=this._width,r=this._height,n=this._factor,s=t%n*i,o=Math.floor(t/n)*r;if(e.camera.setViewOffset(i*n,r*n,s,o,i,r),e.render(),this._antialias){const t=Math.round((s+i)/2)-Math.round(s/2),n=Math.round((o+r)/2)-Math.round(o/2);this._ctx.drawImage(e.renderer.domElement,Math.round(s/2),Math.round(o/2),t,n)}else this._ctx.drawImage(e.renderer.domElement,Math.floor(s),Math.floor(o),Math.ceil(i),Math.ceil(r));"function"==typeof this._onProgress&&this._onProgress(t+1,this._n,!1)}_finalize(){this._viewer.setSampling(this._viewerSampleLevel),this._viewer.camera.view=null,"function"==typeof this._onFinish&&this._onFinish(this._n+1,this._n,!1)}render(){for(let t=0;t<=this._n;++t)t===this._n?this._finalize():this._renderTile(t)}renderAsync(){let t=0;const e=this._n,i=()=>{t===e?this._finalize():this._renderTile(t),t+=1};for(let t=0;t<=e;++t)setTimeout(i,0)}}const bi=2*Math.PI,_i=180/Math.PI;function xi(t,e,i=1,r=0,n){const s=n?n.length:t.length/i;let o=0,a=0;if(n)for(let c=0;ce&&(e=t[i]);return e}function Di(t){let e=1/0;for(let i=0,r=t.length;i=0;l--){for(c=o-1;c>=0;c--)if(u=4*(l*o+c),a[u]!==e||a[u+1]!==i||a[u+2]!==r||a[u+3]!==n){h=!0;break}if(h)break}const f=l;for(h=!1,c=o-1;c>=0;c--){for(l=s-1;l>=0;l--)if(u=4*(l*o+c),a[u]!==e||a[u+1]!==i||a[u+2]!==r||a[u+3]!==n){h=!0;break}if(h)break}const p=c,g=document.createElement("canvas");return g.width=p-m,g.height=f-d,g.getContext("2d").drawImage(t,m,d,g.width,g.height,0,0,g.width,g.height),g}(t,o?0:255*e.r,o?0:255*e.g,o?0:255*e.b,o?0:255)}return t}function m(t,i,r){"function"==typeof e.onProgress&&e.onProgress(t,i,r)}return new Promise((function(e,i){const n=new yi(a,c,t,{factor:r,antialias:s,onProgress:m,onFinish:function(r,s){d(n.canvas).toBlob((function(r){a.setClearAlpha(l),u(!0),t.requestRender(),m(s,s,!0),r?e(r):i("error creating image")}),"image/png")}});a.setClearAlpha(o?0:1),u(),n.renderAsync()}))}const Oi=new e,Ri=new i,Li=new i;const Ni=new t,zi=new i,Ui=new i;function Vi(t,e){zi.copy(e.projectionMatrix).invert(),Ui.copy(e.projectionMatrix).transpose(),t.traverse((function(t){const e=t.material;if(!e)return;const i=e.uniforms;i&&(i.projectionMatrixInverse&&i.projectionMatrixInverse.value.copy(zi),i.projectionMatrixTranspose&&i.projectionMatrixTranspose.value.copy(Ui))}))}function ji(t,e,i){const r=t.createShader(i);if(!r)return void console.log(`error creating WebGL shader ${i}`);t.shaderSource(r,e),t.compileShader(r);return t.getShaderParameter(r,t.COMPILE_STATUS)?r:(console.log(`error compiling shader ${r}: ${t.getShaderInfoLog(r)}`),t.deleteShader(r),null)}function Gi(t,e){const i=t.getExtension(e);return i||console.log(`extension '${e}' not available`),i}const Hi=new Float32Array([-1,-1,1,-1,-1,1,-1,1,1,-1,1,1]);function qi(t){const e=document.createElement("canvas");e.width=16,e.height=16,e.style.width="16px",e.style.height="16px";const i=e.getContext("webgl")||e.getContext("experimental-webgl");if(!i)return console.log(`error creating webgl context for ${t}`),!1;if(!(i instanceof WebGLRenderingContext))return console.log("Got unexpected type for WebGL rendering context"),!1;Gi(i,"OES_texture_float"),Gi(i,"OES_texture_half_float"),Gi(i,"WEBGL_color_buffer_float");const r=ji(i,"\nattribute vec4 a_position;\n\nvoid main() {\n gl_Position = a_position;\n}",i.VERTEX_SHADER),n=ji(i,"\nprecision mediump float;\nuniform vec4 u_color;\nuniform sampler2D u_texture;\n\nvoid main() {\n gl_FragColor = texture2D(u_texture, vec2(0.5, 0.5)) * u_color;\n}",i.FRAGMENT_SHADER);if(!r||!n)return!1;const s=function(t,e,i,r){const n=t.createProgram();return n?(e.forEach((e=>t.attachShader(n,e))),i&&i.forEach(((e,i)=>{t.bindAttribLocation(n,r?r[i]:i,e)})),t.linkProgram(n),t.getProgramParameter(n,t.LINK_STATUS)?n:(console.log(`error linking program: ${t.getProgramInfoLog(n)}`),t.deleteProgram(n),null)):void console.log("error creating WebGL program")}(i,[r,n]);if(!s)return console.log("error creating WebGL program"),!1;i.useProgram(s);const o=i.getAttribLocation(s,"a_position"),a=i.getUniformLocation(s,"u_color");if(!a)return console.log("error getting 'u_color' uniform location"),!1;const c=i.createBuffer();i.bindBuffer(i.ARRAY_BUFFER,c),i.bufferData(i.ARRAY_BUFFER,Hi,i.STATIC_DRAW),i.enableVertexAttribArray(o),i.vertexAttribPointer(o,2,i.FLOAT,!1,0,0);const l=i.createTexture(),h=new Uint8Array([255,255,255,255]);i.bindTexture(i.TEXTURE_2D,l),i.texImage2D(i.TEXTURE_2D,0,i.RGBA,1,1,0,i.RGBA,i.UNSIGNED_BYTE,h);const u=i.createTexture();i.bindTexture(i.TEXTURE_2D,u),i.texImage2D(i.TEXTURE_2D,0,i.RGBA,1,1,0,i.RGBA,t,null),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MIN_FILTER,i.NEAREST),i.texParameteri(i.TEXTURE_2D,i.TEXTURE_MAG_FILTER,i.NEAREST);const d=i.createFramebuffer();i.bindFramebuffer(i.FRAMEBUFFER,d),i.framebufferTexture2D(i.FRAMEBUFFER,i.COLOR_ATTACHMENT0,i.TEXTURE_2D,u,0);if(i.checkFramebufferStatus(i.FRAMEBUFFER)!==i.FRAMEBUFFER_COMPLETE)return console.log(`error creating framebuffer for ${t}`),!1;i.bindTexture(i.TEXTURE_2D,l),i.uniform4fv(a,[0,10,20,1]),i.drawArrays(i.TRIANGLES,0,6),i.bindTexture(i.TEXTURE_2D,u),i.bindFramebuffer(i.FRAMEBUFFER,null),i.clearColor(1,0,0,1),i.clear(i.COLOR_BUFFER_BIT),i.uniform4fv(a,[0,.1,.05,1]),i.drawArrays(i.TRIANGLES,0,6);const m=new Uint8Array(4);if(i.readPixels(0,0,1,1,i.RGBA,i.UNSIGNED_BYTE,m),0!==m[0]||m[1]<248||m[2]<248||m[3]<254)return console.log(`not able to actually render to ${t} texture`),!1;if(t===i.FLOAT){i.bindFramebuffer(i.FRAMEBUFFER,d);const t=new Float32Array(4);i.readPixels(0,0,1,1,i.RGBA,i.FLOAT,t);const e=i.getError();if(e)return console.log(`error reading pixels as float: '${function(t,e){switch(e){case t.NO_ERROR:return"no error";case t.INVALID_ENUM:return"invalid enum";case t.INVALID_VALUE:return"invalid value";case t.INVALID_OPERATION:return"invalid operation";case t.INVALID_FRAMEBUFFER_OPERATION:return"invalid framebuffer operation";case t.OUT_OF_MEMORY:return"out of memory";case t.CONTEXT_LOST_WEBGL:return"context lost"}return"unknown error"}(i,e)}'`),!1}return!0}const Wi=new Float32Array(100),Xi=new Uint8Array(100),Yi=[12,7,13,17,11,6,8,18,16,2,14,22,10,1,3,9,19,23,21,15,5,0,4,24,20],Ki=new i;function Zi(t,e,i,r,n){const s=n.uniforms,o=[];if(s&&(s.objectId&&(s.objectId.value=Se?this.id:this.id/255,o.push("objectId")),(s.modelViewMatrixInverse||s.modelViewMatrixInverseTranspose||s.modelViewProjectionMatrix||s.modelViewProjectionMatrixInverse)&&this.modelViewMatrix.multiplyMatrices(i.matrixWorldInverse,this.matrixWorld),s.modelViewMatrixInverse&&(s.modelViewMatrixInverse.value.copy(this.modelViewMatrix).invert(),o.push("modelViewMatrixInverse")),s.modelViewMatrixInverseTranspose&&(s.modelViewMatrixInverse?s.modelViewMatrixInverseTranspose.value.copy(s.modelViewMatrixInverse.value).transpose():s.modelViewMatrixInverseTranspose.value.copy(this.modelViewMatrix).invert().transpose(),o.push("modelViewMatrixInverseTranspose")),s.modelViewProjectionMatrix&&(s.modelViewProjectionMatrix.value.multiplyMatrices(i.projectionMatrix,this.modelViewMatrix),o.push("modelViewProjectionMatrix")),s.modelViewProjectionMatrixInverse&&(s.modelViewProjectionMatrix?(Ki.copy(s.modelViewProjectionMatrix.value),s.modelViewProjectionMatrixInverse.value.copy(Ki.invert())):(Ki.multiplyMatrices(i.projectionMatrix,this.modelViewMatrix),s.modelViewProjectionMatrixInverse.value.copy(Ki.invert())),o.push("modelViewProjectionMatrixInverse")),o.length)){const e=t.properties.get(n);if(e.program){const i=t.getContext(),r=e.program;i.useProgram(r.program);const n=r.getUniforms();o.forEach((function(t){n.setValue(i,t,s[t].value)}))}}}class Qi{constructor(t){if(this.boundingBox=new a,this.boundingBoxSize=new e,this.boundingBoxLength=0,this.info={memory:{programs:0,geometries:0,textures:0},render:{calls:0,vertices:0,faces:0,points:0}},this.distVector=new e,this.signals={ticked:new tt,rendered:new tt},"string"==typeof t){const e=document.getElementById(t);this.container=null===e?document.createElement("div"):e}else t instanceof HTMLElement?this.container=t:this.container=document.createElement("div");if(this.container===document.body)this.width=window.innerWidth||1,this.height=window.innerHeight||1;else{const t=this.container.getBoundingClientRect();this.width=t.width||1,this.height=t.height||1,this.container.style.overflow="hidden"}this.wrapper=document.createElement("div"),this.wrapper.style.position="relative",this.container.appendChild(this.wrapper),this._initParams(),this._initStats(),this._initCamera(),this._initScene(),!1!==this._initRenderer()?(this._initHelper(),this.setBackground(),this.setFog(),this.animate=this.animate.bind(this)):ke.error("Viewer: could not initialize renderer")}_initParams(){this.parameters={fogColor:new n(0),fogNear:50,fogFar:100,backgroundColor:new n(0),cameraType:"perspective",cameraFov:40,cameraEyeSep:.3,cameraZ:-80,clipNear:0,clipFar:100,clipDist:10,clipMode:"scene",clipScale:"relative",lightColor:new n(14540253),lightIntensity:1.2,ambientColor:new n(14540253),ambientIntensity:.3,sampleLevel:0,outputColorSpace:"srgb-linear"}}_initCamera(){const t=new e(0,0,0),{width:i,height:r}=this;this.perspectiveCamera=new c(this.parameters.cameraFov,i/r),this.perspectiveCamera.position.z=this.parameters.cameraZ,this.perspectiveCamera.lookAt(t),this.orthographicCamera=new l(i/-2,i/2,r/2,r/-2),this.orthographicCamera.position.z=this.parameters.cameraZ,this.orthographicCamera.lookAt(t),this.stereoCamera=new h,this.stereoCamera.aspect=.5,this.stereoCamera.eyeSep=this.parameters.cameraEyeSep;const n=this.parameters.cameraType;if("orthographic"===n)this.camera=this.orthographicCamera;else{if("perspective"!==n&&"stereo"!==n)throw new Error(`Unknown cameraType '${n}'`);this.camera=this.perspectiveCamera}this.camera.updateProjectionMatrix()}_initStats(){this.stats=new di}_initScene(){this.scene||(this.scene=new u,this.scene.name="scene"),this.rotationGroup=new d,this.rotationGroup.name="rotationGroup",this.scene.add(this.rotationGroup),this.translationGroup=new d,this.translationGroup.name="translationGroup",this.rotationGroup.add(this.translationGroup),this.modelGroup=new d,this.modelGroup.name="modelGroup",this.translationGroup.add(this.modelGroup),this.pickingGroup=new d,this.pickingGroup.name="pickingGroup",this.translationGroup.add(this.pickingGroup),this.backgroundGroup=new d,this.backgroundGroup.name="backgroundGroup",this.translationGroup.add(this.backgroundGroup),this.helperGroup=new d,this.helperGroup.name="helperGroup",this.translationGroup.add(this.helperGroup),this.scene.fog=new m(this.parameters.fogColor.getHex()),this.directionalLight=new f(this.parameters.lightColor.getHex(),this.parameters.lightIntensity),this.scene.add(this.directionalLight),this.ambientLight=new p(this.parameters.ambientColor.getHex(),this.parameters.ambientIntensity),this.scene.add(this.ambientLight)}_initRenderer(){const t=window.devicePixelRatio,{width:e,height:i}=this;try{this.renderer=new g({preserveDrawingBuffer:!0,alpha:!0,antialias:!0})}catch(t){return this.wrapper.innerHTML='

Your browser/graphics card does not seem to support WebGL.

Find out how to get it here.

',!1}this.renderer.setPixelRatio(t),this.renderer.setSize(e,i),this.renderer.autoClear=!1,this.renderer.sortObjects=!0,this.renderer.outputColorSpace=this.parameters.outputColorSpace,this.renderer.useLegacyLights=!0;const r=this.renderer.getContext();this.renderer.capabilities.isWebGL2?(Ie(!0),Ce(this.renderer.extensions.get("EXT_color_buffer_float")),this.supportsHalfFloat=!0):(Ie(this.renderer.extensions.get("EXT_frag_depth")),this.renderer.extensions.get("OES_element_index_uint"),Ce(this.renderer.extensions.get("OES_texture_float")&&this.renderer.extensions.get("WEBGL_color_buffer_float")||this.renderer.extensions.get("OES_texture_float")&&qi(r.FLOAT)),this.renderer.extensions.get("OES_texture_float"),this.supportsHalfFloat=this.renderer.extensions.get("OES_texture_half_float")&&qi(36193)),this.wrapper.appendChild(this.renderer.domElement);const n=e*t,s=i*t;De&&console.log(JSON.stringify({Browser:ve,OES_texture_float:!!this.renderer.extensions.get("OES_texture_float"),OES_texture_half_float:!!this.renderer.extensions.get("OES_texture_half_float"),WEBGL_color_buffer_float:!!this.renderer.extensions.get("WEBGL_color_buffer_float"),"testTextureSupport Float":qi(r.FLOAT),"testTextureSupport HalfFloat":qi(36193),"this.supportsHalfFloat":this.supportsHalfFloat,SupportsReadPixelsFloat:Se},null,2)),this.pickingTarget=new y(n,s,{minFilter:b,magFilter:b,stencilBuffer:!1,format:_,type:Se?D:x}),this.pickingTarget.texture.generateMipmaps=!1,this.pickingTarget.texture.colorSpace=this.parameters.outputColorSpace,this.renderer.setRenderTarget(this.pickingTarget),this.renderer.clear(),this.renderer.setRenderTarget(null),this.sampleTarget=new y(n,s,{minFilter:v,magFilter:v,format:_,type:this.supportsHalfFloat?w:Se?D:x}),this.sampleTarget.texture.colorSpace=this.parameters.outputColorSpace,this.holdTarget=new y(n,s,{minFilter:b,magFilter:b,format:_,type:this.supportsHalfFloat?w:Se?D:x}),this.holdTarget.texture.colorSpace=this.parameters.outputColorSpace,this.compositeUniforms={tForeground:new A(this.sampleTarget.texture),scale:new A(1)},this.compositeMaterial=new S({uniforms:this.compositeUniforms,vertexShader:pi("Quad.vert"),fragmentShader:pi("Quad.frag"),premultipliedAlpha:!0,transparent:!0,blending:C,depthTest:!1,depthWrite:!1}),this.compositeCamera=new l(-1,1,1,-1,0,1),this.compositeScene=new u,this.compositeScene.name="compositeScene",this.compositeScene.add(new P(new I(2,2),this.compositeMaterial))}_initHelper(){const t=new Uint16Array([0,1,1,2,2,3,3,0,4,5,5,6,6,7,7,4,0,4,1,5,2,6,3,7]),e=new Float32Array(24),i=new k;i.setIndex(new M(t,1)),i.setAttribute("position",new M(e,3));const r=new S({uniforms:{uColor:{value:new n("skyblue")}},vertexShader:pi("BasicLine.vert"),fragmentShader:pi("BasicLine.frag")});this.boundingBoxMesh=new T(i,r),this.helperGroup.add(this.boundingBoxMesh)}updateHelper(){const t=this.boundingBoxMesh.geometry.attributes.position,e=t.array,{min:i,max:r}=this.boundingBox;e[0]=r.x,e[1]=r.y,e[2]=r.z,e[3]=i.x,e[4]=r.y,e[5]=r.z,e[6]=i.x,e[7]=i.y,e[8]=r.z,e[9]=r.x,e[10]=i.y,e[11]=r.z,e[12]=r.x,e[13]=r.y,e[14]=i.z,e[15]=i.x,e[16]=r.y,e[17]=i.z,e[18]=i.x,e[19]=i.y,e[20]=i.z,e[21]=r.x,e[22]=i.y,e[23]=i.z,t.needsUpdate=!0,this.boundingBox.isEmpty()||this.boundingBoxMesh.geometry.computeBoundingSphere()}get cameraDistance(){return Math.abs(this.camera.position.z)}set cameraDistance(t){this.camera.position.z=-t}add(t,e){e?e.forEach((e=>this.addBuffer(t,e))):this.addBuffer(t),t.group.name="meshGroup",t.wireframeGroup.name="wireframeGroup",t.parameters.background?(this.backgroundGroup.add(t.group),this.backgroundGroup.add(t.wireframeGroup)):(this.modelGroup.add(t.group),this.modelGroup.add(t.wireframeGroup)),t.pickable&&this.pickingGroup.add(t.pickingGroup),De&&this.updateHelper()}addBuffer(t,e){function i(r){r instanceof d?r.children.forEach(i):(r.userData.buffer=t,r.userData.instance=e,r.onBeforeRender=Zi)}const r=t.getMesh();e&&r.applyMatrix4(e.matrix),i(r),t.group.add(r);const n=t.getWireframeMesh();if(e&&(n.matrix.copy(r.matrix),n.position.copy(r.position),n.quaternion.copy(r.quaternion),n.scale.copy(r.scale)),i(n),t.wireframeGroup.add(n),t.pickable){const n=t.getPickingMesh();e&&(n.matrix.copy(r.matrix),n.position.copy(r.position),n.quaternion.copy(r.quaternion),n.scale.copy(r.scale)),i(n),t.pickingGroup.add(n)}e?this._updateBoundingBox(t.geometry,t.matrix,e.matrix):this._updateBoundingBox(t.geometry,t.matrix)}remove(t){this.translationGroup.children.forEach((function(e){e.remove(t.group),e.remove(t.wireframeGroup)})),t.pickable&&this.pickingGroup.remove(t.pickingGroup),this.updateBoundingBox(),De&&this.updateHelper()}_updateBoundingBox(t,e,i){const r=this.boundingBox;function n(t,e,i){null==t.boundingBox&&t.computeBoundingBox();const n=t.boundingBox.clone();e&&n.applyMatrix4(e),i&&n.applyMatrix4(i),n.min.equals(n.max)&&n.expandByScalar(5),r.union(n)}function s(t){if(void 0!==t.geometry){let e,i;t.userData.buffer&&(e=t.userData.buffer.matrix),t.userData.instance&&(i=t.userData.instance.matrix),n(t.geometry,e,i)}}t?n(t,e,i):(r.makeEmpty(),this.modelGroup.traverse(s),this.backgroundGroup.traverse(s)),r.getSize(this.boundingBoxSize),this.boundingBoxLength=this.boundingBoxSize.length()}updateBoundingBox(){this._updateBoundingBox(),De&&this.updateHelper()}getPickingPixels(){const{width:t,height:e}=this,i=t*e*4,r=Se?new Float32Array(i):new Uint8Array(i);return this.render(!0),this.renderer.readRenderTargetPixels(this.pickingTarget,0,0,t,e,r),r}getImage(t){return new Promise((e=>{if(t){const{width:t,height:i}=this,r=t*i*4;let n=this.getPickingPixels();if(Se){const t=new Uint8Array(r);for(let e=0;e500&&!this.isStill&&this.sampleLevel<3&&-1!==this.sampleLevel){const t=this.sampleLevel;this.sampleLevel=3,this.renderPending=!0,this.render(),this.isStill=!0,this.sampleLevel=t,De&&ke.log("rendered still frame")}this.frameRequest=window.requestAnimationFrame(this.animate)}pick(t,e){if("stereo"===this.parameters.cameraType)return{pid:0,instance:void 0,picker:void 0};t*=window.devicePixelRatio,e*=window.devicePixelRatio,t=Math.max(t-2,0),e=Math.max(e-2,0);let i,r,n=0;const s=Se?Wi:Xi;this.render(!0),this.renderer.readRenderTargetPixels(this.pickingTarget,t,e,5,5,s);for(let t=0;t22&&(this.stats.begin(),this.isStill=!1),this.renderPending=!0,window.requestAnimationFrame((()=>{this.render(),this.stats.update()})))}updateZoom(){const t=It(this.perspectiveCamera.fov),e=2*Math.tan(t/2)*this.cameraDistance;this.orthographicCamera.zoom=this.height/e}absoluteToRelative(t){return 50*(1-t/this.bRadius)}relativeToAbsolute(t){return this.bRadius*(1-t/50)}__updateClipping(){const t=this.parameters;this.bRadius=Math.max(10,.5*this.boundingBoxLength),isFinite(this.bRadius)||(this.bRadius=50),this.camera.getWorldPosition(this.distVector),this.cDist=this.distVector.length(),this.cDist||(this.cameraDistance=Math.abs(t.cameraZ),this.cDist=Math.abs(t.cameraZ));const e=this.scene.fog;if(e.color.set(t.fogColor),"camera"===t.clipMode)this.camera.near=t.clipNear,this.camera.far=t.clipFar,e.near=t.fogNear,e.far=t.fogFar;else if("absolute"===t.clipScale)this.camera.near=this.cDist-t.clipNear,this.camera.far=this.cDist+t.clipFar,e.near=this.cDist-t.fogNear,e.far=this.cDist+t.fogFar;else{const i=(50-t.clipNear)/50,r=-(50-t.clipFar)/50;this.camera.near=this.cDist-this.bRadius*i,this.camera.far=this.cDist+this.bRadius*r;const n=(50-t.fogNear)/50,s=-(50-t.fogFar)/50;e.near=this.cDist-this.bRadius*n,e.far=this.cDist+this.bRadius*s}"camera"!==t.clipMode&&("PerspectiveCamera"===this.camera.type?(this.camera.near=Math.max(.1,t.clipDist,this.camera.near),this.camera.far=Math.max(1,this.camera.far),e.near=Math.max(.1,e.near),e.far=Math.max(1,e.far)):"OrthographicCamera"===this.camera.type&&t.clipDist>0&&(this.camera.near=Math.max(t.clipDist,this.camera.near)))}__updateCamera(){const e=this.camera;e.updateMatrix(),e.updateMatrixWorld(!0),e.updateProjectionMatrix(),function(e,i,r,n,s){let o=new t;r.getSize(o);const a=o.height,c=r.getPixelRatio(),l="OrthographicCamera"===i.type;Ni.set(o.width,o.height),zi.copy(i.projectionMatrix).invert(),Ui.copy(i.projectionMatrix).transpose(),e.traverse((function(t){const e=t.material;if(!e)return;const i=e.uniforms;if(i){if(e.clipNear){const t=(50-e.clipNear)/50,r=n-s*t;i.clipNear.value=r}i.canvasHeight&&(i.canvasHeight.value=a),i.resolution&&i.resolution.value.copy(Ni),i.pixelRatio&&(i.pixelRatio.value=c),i.projectionMatrixInverse&&i.projectionMatrixInverse.value.copy(zi),i.projectionMatrixTranspose&&i.projectionMatrixTranspose.value.copy(Ui),i.ortho&&(i.ortho.value=l)}}))}(this.scene,e,this.renderer,this.cDist,this.bRadius),function(t,e){t.traverseVisible((function(t){if(!(t instanceof o&&t.userData.buffer.parameters.sortParticles))return;const i=t.geometry.attributes,r=i.position.count;if(0===r)return;let n,s,a,c,l,h,u,d;Ri.multiplyMatrices(e.matrixWorldInverse,t.matrixWorld),Li.multiplyMatrices(e.projectionMatrix,Ri),t.userData.sortData?(n=t.userData.sortData,a=n.__zArray,s=n.__sortArray,c=n.__cmpFn):(a=new Float32Array(r),s=new Uint32Array(r),c=function(t,e){const i=a[t],r=a[e];return i>r?1:ie?1:t=l&&e(t[o],s)>0;)t[o+1]=t[o],--o;t[o+1]=s}if(-1===c)break;h=n[c--],l=n[c--]}else{for(o=l+1,a=h,u(l+h>>1,o),e(t[l],t[h])>0&&u(l,h),e(t[o],t[h])>0&&u(o,h),e(t[l],t[o])>0&&u(l,o),s=t[o];;){do{o++}while(e(t[o],s)<0);do{a--}while(e(t[a],s)>0);if(a=a-l?(n[++c]=o,n[++c]=h,h=a-1):(n[++c]=l,n[++c]=a-1,l=o)}}(s,c);for(let t in i){const e=i[t],o=e.array,a=e.itemSize;n[t]||(n[t]=new Float32Array(a*r)),d=n[t],n[t]=o;for(let t=0;t0&&"stereo"!==this.parameters.cameraType?this.__renderSuperSample(e,i):this.__renderModelGroup(e,i)}render(t=!1,e){if(this.rendering)ke.warn("'tried to call 'render' from within 'render'");else{this.rendering=!0;try{this.__updateClipping(),this.__updateCamera(),this.__updateLights(),this.updateInfo(!0),"stereo"===this.parameters.cameraType?this.__renderStereo(t,e):this.__render(t,this.camera,e),this.lastRenderedPicking=t}finally{this.rendering=!1,this.renderPending=!1}this.signals.rendered.dispatch()}}clear(){ke.log("scene cleared"),this.scene.remove(this.rotationGroup),this._initScene(),this.renderer.clear()}dispose(){this.renderer.dispose(),window.cancelAnimationFrame(this.frameRequest)}}const Ji=1,tr=2,er=3;function ir(t){const e=t.touches[0].pageX-t.touches[1].pageX,i=t.touches[0].pageY-t.touches[1].pageY;return Math.sqrt(e*e+i*i)}class rr{constructor(e,i={}){this.domElement=e,this.signals={moved:new tt,scrolled:new tt,dragged:new tt,dropped:new tt,clicked:new tt,hovered:new tt,doubleClicked:new tt},this.position=new t,this.prevPosition=new t,this.down=new t,this.canvasPosition=new t,this.prevClickCP=new t,this.moving=!1,this.hovering=!0,this.scrolled=!1,this.lastMoved=1/0,this.which=0,this.buttons=0,this.pressed=!1,this.altKey=!1,this.ctrlKey=!1,this.metaKey=!1,this.shiftKey=!1,this.domElement.style.touchAction="none",this.hoverTimeout=rt(i.hoverTimeout,50),this.handleScroll=rt(i.handleScroll,!0),this.doubleClickSpeed=rt(i.doubleClickSpeed,500),this._listen=this._listen.bind(this),this._onMousewheel=this._onMousewheel.bind(this),this._onMousemove=this._onMousemove.bind(this),this._onMousedown=this._onMousedown.bind(this),this._onMouseup=this._onMouseup.bind(this),this._onContextmenu=this._onContextmenu.bind(this),this._onTouchstart=this._onTouchstart.bind(this),this._onTouchend=this._onTouchend.bind(this),this._onTouchmove=this._onTouchmove.bind(this),this._listen();const r={passive:!1};document.addEventListener("mousewheel",this._onMousewheel,r),document.addEventListener("wheel",this._onMousewheel,r),document.addEventListener("MozMousePixelScroll",this._onMousewheel,r),document.addEventListener("mousemove",this._onMousemove,r),document.addEventListener("mousedown",this._onMousedown,r),document.addEventListener("mouseup",this._onMouseup,r),document.addEventListener("contextmenu",this._onContextmenu,r),document.addEventListener("touchstart",this._onTouchstart,r),document.addEventListener("touchend",this._onTouchend,r),document.addEventListener("touchmove",this._onTouchmove,r)}get key(){let t=0;return this.altKey&&(t+=1),this.ctrlKey&&(t+=2),this.metaKey&&(t+=4),this.shiftKey&&(t+=8),t}setParameters(t={}){this.hoverTimeout=rt(t.hoverTimeout,this.hoverTimeout)}_listen(){const t=window.performance.now(),e=this.canvasPosition;this.doubleClickPending&&t-this.lastClicked>this.doubleClickSpeed&&(this.doubleClickPending=!1),t-this.lastMoved>this.hoverTimeout&&(this.moving=!1),(this.scrolled||!this.moving&&!this.hovering)&&(this.scrolled=!1,-1!==this.hoverTimeout&&this.overElement&&(this.hovering=!0,this.signals.hovered.dispatch(e.x,e.y))),this.frameRequest=window.requestAnimationFrame(this._listen)}_onMousewheel(t){if(t.target!==this.domElement||!this.handleScroll)return;t.preventDefault(),this._setKeys(t);let e=0;"deltaY"in t&&"deltaMode"in t&&void 0!==t.deltaY&&void 0!==t.deltaMode?e=t.deltaMode===WheelEvent.DOM_DELTA_PIXEL?.025*-t.deltaY:t.deltaMode===WheelEvent.DOM_DELTA_LINE?-t.deltaY*(2.5/3):2.5*-t.deltaY:"deltaY"in t&&!("detail"in t)?e=.025*-t.deltaY:void 0!==t.wheelDelta?e=.025*-t.wheelDelta:void 0!==t.wheelDeltaY?e=.025*-t.wheelDeltaY:void 0!==t.detail&&(e=-t.detail/3),this.signals.scrolled.dispatch(e),setTimeout((()=>{this.scrolled=!0}),this.hoverTimeout)}_onMousemove(t){t.target===this.domElement?(t.preventDefault(),this.overElement=!0):this.overElement=!1,this._setKeys(t),this.moving=!0,this.hovering=!1,this.lastMoved=window.performance.now(),this.prevPosition.copy(this.position),this.position.set(t.clientX,t.clientY),this._setCanvasPosition(t);const e=this.prevPosition.x-this.position.x,i=this.prevPosition.y-this.position.y;this.signals.moved.dispatch(e,i),this.pressed&&this.signals.dragged.dispatch(e,i)}_onMousedown(t){t.target===this.domElement&&(t.preventDefault(),this._setKeys(t),this.moving=!1,this.hovering=!1,this.down.set(t.clientX,t.clientY),this.position.set(t.clientX,t.clientY),this.which=t.which,this.buttons=function(t){if("object"==typeof t){if("buttons"in t)return t.buttons;if("which"in t){const e=t.which;if(2===e)return 4;if(3===e)return 2;if(e>0)return 1<=0)return 1<2&&this.handleScroll&&this.position.distanceTo(this.prevPosition)<2)this.which=0,this.buttons=0,this.signals.scrolled.dispatch(i/2);else{this.which=3,this.buttons=2;const t=this.prevPosition.x-this.position.x,e=this.prevPosition.y-this.position.y;this.signals.moved.dispatch(t,e),this.pressed&&this.signals.dragged.dispatch(t,e)}}}}_distance(){return this.position.distanceTo(this.down)}_setCanvasPosition(t){const e=this.domElement.getBoundingClientRect();let i,r;"clientX"in t&&"clientY"in t?(i=t.clientX-e.left,r=t.clientY-e.top):(i=t.offsetX,r=t.offsetY),this.canvasPosition.set(i,e.height-r)}_setKeys(t){this.altKey=t.altKey,this.ctrlKey=t.ctrlKey,this.metaKey=t.metaKey,this.shiftKey=t.shiftKey}dispose(){document.removeEventListener("mousewheel",this._onMousewheel),document.removeEventListener("wheel",this._onMousewheel),document.removeEventListener("MozMousePixelScroll",this._onMousewheel),document.removeEventListener("mousemove",this._onMousemove),document.removeEventListener("mousedown",this._onMousedown),document.removeEventListener("mouseup",this._onMouseup),document.removeEventListener("contextmenu",this._onContextmenu),document.removeEventListener("touchstart",this._onTouchstart),document.removeEventListener("touchend",this._onTouchend),document.removeEventListener("touchmove",this._onTouchmove),window.cancelAnimationFrame(this.frameRequest)}}const nr=new i,sr=new i,or=new i,ar=new i,cr=new i,lr=new e,hr=new r,ur=new r,dr=new i,mr=new e,fr=new e;class pr{constructor(t,e={}){this.stage=t,this.rotateSpeed=rt(e.rotateSpeed,2),this.zoomSpeed=rt(e.zoomSpeed,1.2),this.panSpeed=rt(e.panSpeed,1),this.viewer=t.viewer,this.mouse=t.mouseObserver,this.controls=t.viewerControls}get component(){return this.stage.transformComponent}get atom(){return this.stage.transformAtom}_setPanVector(t,e,i=0){const r=this.controls.getCanvasScaleFactor(i);mr.set(t,e,0),mr.multiplyScalar(this.panSpeed*r)}_getRotateXY(t,e){return[this.rotateSpeed*-t*.01,this.rotateSpeed*e*.01]}_getCameraRotation(t){return t.extractRotation(this.viewer.camera.matrixWorld),t.multiply(sr.makeRotationY(Math.PI)),t}_transformPanVector(){this.component&&(dr.extractRotation(this.component.transform),dr.premultiply(this.viewer.rotationGroup.matrix),dr.invert(),dr.multiply(this._getCameraRotation(ar)),mr.applyMatrix4(dr))}zoom(t){this.controls.zoom(this.zoomSpeed*t*.02)}pan(t,e){this._setPanVector(t,e),dr.copy(this.viewer.rotationGroup.matrix).invert(),dr.multiply(this._getCameraRotation(ar)),mr.applyMatrix4(dr),this.controls.translate(mr)}panComponent(t,e){this.component&&(this._setPanVector(t,e),this._transformPanVector(),this.component.position.add(mr),this.component.updateMatrix())}panAtom(t,e){this.atom&&this.component&&(this.atom.positionToVector3(fr),fr.add(this.viewer.translationGroup.position),fr.applyMatrix4(this.viewer.rotationGroup.matrix),this._setPanVector(t,e,fr.z),this._transformPanVector(),this.atom.positionAdd(mr),this.component.updateRepresentations({position:!0}))}rotate(t,e){const[i,r]=this._getRotateXY(t,e);this._getCameraRotation(ar),lr.set(1,0,0),lr.applyMatrix4(ar),hr.setFromAxisAngle(lr,r),lr.set(0,1,0),lr.applyMatrix4(ar),ur.setFromAxisAngle(lr,i),hr.multiply(ur),ar.makeRotationFromQuaternion(hr),this.controls.applyMatrix(ar)}zRotate(t,e){const i=this.rotateSpeed*((-t+e)/-2)*.01;or.makeRotationZ(i),this.controls.applyMatrix(or)}rotateComponent(t,e){if(!this.component)return;const[i,r]=this._getRotateXY(t,e);this._getCameraRotation(cr),ar.extractRotation(this.component.transform),ar.premultiply(this.viewer.rotationGroup.matrix),ar.invert(),ar.premultiply(cr),lr.set(1,0,0),lr.applyMatrix4(ar),nr.makeRotationAxis(lr,r),lr.set(0,1,0),lr.applyMatrix4(ar),sr.makeRotationAxis(lr,i),nr.multiply(sr),hr.setFromRotationMatrix(nr),this.component.quaternion.premultiply(hr),this.component.quaternion.normalize(),this.component.updateMatrix()}}const gr=new e;class yr{constructor(t,e){this.stage=e,this.pid=t.pid,this.picker=t.picker,this.instance=t.instance,this.stage=e,this.controls=e.viewerControls,this.mouse=e.mouseObserver}get type(){return this.picker.type}get altKey(){return this.mouse.altKey}get ctrlKey(){return this.mouse.ctrlKey}get metaKey(){return this.mouse.metaKey}get shiftKey(){return this.mouse.shiftKey}get canvasPosition(){return this.mouse.canvasPosition}get component(){return this.stage.getComponentsByObject(this.picker.data).list[0]}get object(){return this.picker.getObject(this.pid)}get position(){return this.picker.getPosition(this.pid,this.instance,this.component)}get closestBondAtom(){if("bond"!==this.type||!this.bond)return;const t=this.bond,e=this.controls,i=this.canvasPosition,r=t.atom1.positionToVector3(),n=t.atom2.positionToVector3();r.applyMatrix4(this.component.matrix),n.applyMatrix4(this.component.matrix);const s=e.getPositionOnCanvas(r),o=e.getPositionOnCanvas(n);return c=s,l=o,(a=i).distanceTo(c)=t.length))return new yr(i,this.stage);console.error("pid >= picker.array.length")}}}const _r=new r,xr=new e,vr=new e,wr=new e,Ar=new e,Sr=new i,Cr=new e,Pr=new i;class Ir{constructor(t){this.stage=t,this.signals={changed:new J.Signal},this.viewer=t.viewer}get position(){return this.viewer.translationGroup.position}get rotation(){return this.viewer.rotationGroup.quaternion}changed(){this.viewer.requestRender(),this.signals.changed.dispatch()}getPositionOnCanvas(e,i){const r=xt(i,t);const n=this.viewer;return wr.copy(e).add(n.translationGroup.position).applyMatrix4(n.rotationGroup.matrix).project(n.camera),r.set((wr.x+1)*n.width/2,(wr.y+1)*n.height/2)}getCanvasScaleFactor(t=0){const e=this.viewer.camera;if(e instanceof l)return 1/e.zoom;{t=Math.abs(t),t+=this.getCameraDistance();const i=It(e.fov);return 2*t*Math.tan(i/2)/this.viewer.height}}getOrientation(t){const e=wt(t);e.copy(this.viewer.rotationGroup.matrix);const i=this.getCameraDistance();return e.scale(Ar.set(i,i,i)),e.setPosition(this.viewer.translationGroup.position),e}orient(t){wt(t).decompose(xr,_r,vr);const e=this.viewer;e.rotationGroup.setRotationFromQuaternion(_r),e.translationGroup.position.copy(xr),e.cameraDistance=vr.z,e.updateZoom(),this.changed()}translate(t){this.viewer.translationGroup.position.add(vt(t)),this.changed()}center(t){this.viewer.translationGroup.position.copy(vt(t)).negate(),this.changed()}zoom(t){this.distance(this.getCameraDistance()*(1-t))}getCameraDistance(){return this.viewer.cameraDistance}distance(t){this.viewer.cameraDistance=Math.max(Math.abs(t),.2),this.viewer.updateZoom(),this.changed()}spin(t,e){Sr.copy(this.viewer.rotationGroup.matrix).invert(),Cr.copy(vt(t)).applyMatrix4(Sr),this.viewer.rotationGroup.rotateOnAxis(Cr,e),this.changed()}rotate(t){this.viewer.rotationGroup.setRotationFromQuaternion(At(t)),this.changed()}align(t){Pr.copy(wt(t)).invert(),this.viewer.rotationGroup.setRotationFromMatrix(Pr),this.changed()}applyMatrix(t){this.viewer.rotationGroup.applyMatrix4(wt(t)),this.changed()}}class kr{constructor(t,e,...i){this.pausedTime=-1,this.elapsedDuration=0,this.pausedDuration=0,this.ignoreGlobalToggle=!1,this._paused=!1,this._resolveList=[],this.duration=rt(t,1e3),this.controls=e,this.startTime=window.performance.now(),this._init(...i)}get done(){return 1===this.alpha}get paused(){return this._paused}tick(t){if(!this._paused)return this.elapsedDuration=t.currentTime-this.startTime-this.pausedDuration,0===this.duration?this.alpha=1:this.alpha=Et(0,1,this.elapsedDuration/this.duration),this._tick(t),this.done&&this._resolveList.forEach((t=>t())),this.done}pause(t){t&&(this._hold=!0),-1===this.pausedTime&&(this.pausedTime=window.performance.now()),this._paused=!0}resume(t){!t&&this._hold||(this.pausedDuration+=window.performance.now()-this.pausedTime,this._paused=!1,this._hold=!1,this.pausedTime=-1)}toggle(){this._paused?this.resume():this.pause()}then(t){let e;return e=this.done?Promise.resolve():new Promise((t=>this._resolveList.push(t))),e.then(t)}}class Mr extends kr{constructor(t,e,...i){super(rt(t,1/0),e,...i)}_init(t,i){Array.isArray(t)?this.axis=(new e).fromArray(t):this.axis=rt(t,new e(0,1,0)),this.angle=rt(i,.01)}_tick(t){this.axis&&this.angle&&this.controls.spin(this.axis,this.angle*t.lastDuration/16)}}class Tr extends kr{constructor(t,e,...i){super(rt(t,1/0),e,...i),this.angleSum=0,this.direction=1}_init(t,i,r){Array.isArray(t)?this.axis=(new e).fromArray(t):this.axis=rt(t,new e(0,1,0)),this.angleStep=rt(i,.01),this.angleEnd=rt(r,.2)}_tick(t){if(!this.axis||!this.angleStep||!this.angleEnd)return;const e=Et(0,1,Math.abs(this.angleSum)/this.angleEnd),i=this.angleStep*this.direction*(1.1-e);this.controls.spin(this.axis,i*t.lastDuration/16),this.angleSum+=this.angleStep,this.angleSum>=this.angleEnd&&(this.direction*=-1,this.angleSum=-this.angleEnd)}}class Dr extends kr{_init(t,i){this.moveFrom=vt(rt(t,new e)),this.moveTo=vt(rt(i,new e))}_tick(){this.controls.position.lerpVectors(this.moveFrom,this.moveTo,this.alpha).negate(),this.controls.changed()}}class Br extends kr{_init(t,e){this.zoomFrom=t,this.zoomTo=e}_tick(){this.controls.distance(Bt(this.zoomFrom,this.zoomTo,this.alpha))}}class Fr extends kr{constructor(){super(...arguments),this._currentRotation=new r}_init(t,e){this.rotateFrom=At(t),this.rotateTo=At(e),this._currentRotation=new r}_tick(){this._currentRotation.copy(this.rotateFrom).slerp(this.rotateTo,this.alpha),this.controls.rotate(this._currentRotation)}}class Er extends kr{_init(t,e,i){this.valueFrom=t,this.valueTo=e,this.callback=i}_tick(){this.callback(Bt(this.valueFrom,this.valueTo,this.alpha))}}class $r extends kr{_init(t){this.callback=t}_tick(){1===this.alpha&&this.callback()}}class Or{constructor(t=[]){this._resolveList=[],this._list=t}get done(){return this._list.every((t=>t.done))}then(t){let e;return e=this.done?Promise.resolve():new Promise((t=>{this._resolveList.push(t),this._list.forEach((t=>{t.then((()=>{this._resolveList.forEach((t=>{t()})),this._resolveList.length=0}))}))})),e.then(t)}}class Rr{constructor(t){this.stage=t,this.animationList=[],this.finishedList=[],this.viewer=t.viewer,this.controls=t.viewerControls}get paused(){return this.animationList.every((t=>t.paused))}add(t){return 0===t.duration?t.tick(this.viewer.stats):this.animationList.push(t),t}remove(t){const e=this.animationList,i=e.indexOf(t);i>-1&&e.splice(i,1)}run(t){const e=this.finishedList,i=this.animationList,r=i.length;for(let n=0;nt.pause()))}resume(){this.animationList.forEach((t=>t.resume()))}toggle(){this.paused?this.resume():this.pause()}clear(){this.animationList.length=0}dispose(){this.clear()}}class Lr{constructor(t,e){if(this.fn=t,this.queue=[],this.pending=!1,this.next=this.next.bind(this),e){for(let t=0,i=e.length;tthis.run(t)))):this.pending=!1}push(t){this.queue.push(t),this.pending||this.next()}kill(){this.queue.length=0}length(){return this.queue.length}}class Nr{constructor(t,e,i){this.type="",this.parameters={lazy:{type:"boolean"},clipNear:{type:"range",step:1,max:100,min:0,buffer:!0},clipRadius:{type:"number",precision:1,max:1e3,min:0,buffer:!0},clipCenter:{type:"vector3",precision:1,buffer:!0},flatShaded:{type:"boolean",buffer:!0},opacity:{type:"range",step:.01,max:1,min:0,buffer:!0},depthWrite:{type:"boolean",buffer:!0},side:{type:"select",buffer:!0,options:{front:"front",back:"back",double:"double"}},wireframe:{type:"boolean",buffer:!0},colorData:{type:"hidden",update:"color"},colorScheme:{type:"select",update:"color",options:{}},colorScale:{type:"select",update:"color",options:Oe.getScales()},colorReverse:{type:"boolean",update:"color"},colorValue:{type:"color",update:"color"},colorDomain:{type:"hidden",update:"color"},colorMode:{type:"select",update:"color",options:Oe.getModes()},roughness:{type:"range",step:.01,max:1,min:0,buffer:!0},metalness:{type:"range",step:.01,max:1,min:0,buffer:!0},diffuse:{type:"color",buffer:!0},diffuseInterior:{type:"boolean",buffer:!0},useInteriorColor:{type:"boolean",buffer:!0},interiorColor:{type:"color",buffer:!0},interiorDarkening:{type:"range",step:.01,max:1,min:0,buffer:!0},matrix:{type:"hidden",buffer:!0},disablePicking:{type:"boolean",rebuild:!0}},this.viewer=e,this.tasks=new ui,this.queue=new Lr(this.make.bind(this)),this.bufferList=[],this.parameters.colorScheme&&(this.parameters.colorScheme.options=Oe.getSchemes()),this.toBePrepared=!1}init(t){const r=t||{};this.clipNear=rt(r.clipNear,0),this.clipRadius=rt(r.clipRadius,0),this.clipCenter=rt(r.clipCenter,new e),this.flatShaded=rt(r.flatShaded,!1),this.side=rt(r.side,"double"),this.opacity=rt(r.opacity,1),this.depthWrite=rt(r.depthWrite,!0),this.wireframe=rt(r.wireframe,!1),this.setColor(r.color,r),this.colorData=rt(r.colorData,void 0),this.colorScheme=rt(r.colorScheme,"uniform"),this.colorScale=rt(r.colorScale,""),this.colorReverse=rt(r.colorReverse,!1),this.colorValue=rt(r.colorValue,9474192),this.colorDomain=rt(r.colorDomain,void 0),this.colorMode=rt(r.colorMode,"hcl"),this.visible=rt(r.visible,!0),this.quality=rt(r.quality,void 0),this.roughness=rt(r.roughness,.4),this.metalness=rt(r.metalness,0),this.diffuse=rt(r.diffuse,16777215),this.diffuseInterior=rt(r.diffuseInterior,!1),this.useInteriorColor=rt(r.useInteriorColor,!1),this.interiorColor=rt(r.interiorColor,2236962),this.interiorDarkening=rt(r.interiorDarkening,0),this.lazy=rt(r.lazy,!1),this.lazyProps={build:!1,bufferParams:{},what:{}},this.matrix=rt(r.matrix,new i),this.disablePicking=rt(r.disablePicking,!1);const n=this.parameters;!0===n.sphereDetail&&(n.sphereDetail={type:"integer",max:3,min:0,rebuild:"impostor"}),!0===n.radialSegments&&(n.radialSegments={type:"integer",max:25,min:5,rebuild:"impostor"}),!0===n.openEnded&&(n.openEnded={type:"boolean",rebuild:"impostor",buffer:!0}),!0===n.disableImpostor&&(n.disableImpostor={type:"boolean",rebuild:!0}),"low"===r.quality?(n.sphereDetail&&(this.sphereDetail=0),n.radialSegments&&(this.radialSegments=5)):"medium"===r.quality?(n.sphereDetail&&(this.sphereDetail=1),n.radialSegments&&(this.radialSegments=10)):"high"===r.quality?(n.sphereDetail&&(this.sphereDetail=2),n.radialSegments&&(this.radialSegments=20)):(n.sphereDetail&&(this.sphereDetail=rt(r.sphereDetail,1)),n.radialSegments&&(this.radialSegments=rt(r.radialSegments,10))),n.openEnded&&(this.openEnded=rt(r.openEnded,!0)),n.disableImpostor&&(this.disableImpostor=rt(r.disableImpostor,!1))}getColorParams(t){return Object.assign({data:this.colorData,scheme:this.colorScheme,scale:this.colorScale,reverse:this.colorReverse,value:this.colorValue,domain:this.colorDomain,mode:this.colorMode,colorSpace:this.colorSpace},t)}getBufferParams(t={}){return Object.assign({clipNear:this.clipNear,clipRadius:this.clipRadius,clipCenter:this.clipCenter,flatShaded:this.flatShaded,opacity:this.opacity,depthWrite:this.depthWrite,side:this.side,wireframe:this.wireframe,roughness:this.roughness,metalness:this.metalness,diffuse:this.diffuse,diffuseInterior:this.diffuseInterior,useInteriorColor:this.useInteriorColor,interiorColor:this.interiorColor,interiorDarkening:this.interiorDarkening,matrix:this.matrix,disablePicking:this.disablePicking},t)}setColor(t,e){const i=Object.keys(Oe.getSchemes());if("string"==typeof t&&i.includes(t.toLowerCase()))e?e.colorScheme=t:this.setParameters({colorScheme:t});else if(void 0!==t){let i=new n(t).getHex();e?(e.colorScheme="uniform",e.colorValue=i):this.setParameters({colorScheme:"uniform",colorValue:i})}return this}prepare(t){}create(){}update(t){this.build()}build(t){if(!this.lazy||this.visible&&this.opacity){if(!this.toBePrepared)return this.tasks.increment(),void this.make();this.queue.length()>0?(this.tasks.change(1-this.queue.length()),this.queue.kill()):this.tasks.increment(),this.queue.push(t||!1)}else this.lazyProps.build=!0}make(t,e){De&&ke.time("Representation.make "+this.type);const i=()=>{t?(this.update(t),this.viewer.requestRender(),this.tasks.decrement(),e&&e()):(this.clear(),this.create(),this.manualAttach||this.disposed||(De&&ke.time("Representation.attach "+this.type),this.attach((()=>{De&&ke.timeEnd("Representation.attach "+this.type),this.tasks.decrement(),e&&e()})))),De&&ke.timeEnd("Representation.make "+this.type)};this.toBePrepared?this.prepare(i):i()}attach(t){this.setVisibility(this.visible),t()}setVisibility(t,e){if(this.visible=t,this.visible&&this.opacity){const t=this.lazyProps,e=t.bufferParams,i=t.what;if(t.build)return t.build=!1,this.build(),this;(Object.keys(e).length||Object.keys(i).length)&&(t.bufferParams={},t.what={},this.updateParameters(e,i))}return this.bufferList.forEach((function(e){e.setVisibility(t)})),e||this.viewer.requestRender(),this}setParameters(t,e={},i=!1){const r=t||{},n=this.parameters,s={};this.opacity||void 0===r.opacity||(this.lazyProps.build?(this.lazyProps.build=!1,i=!0):(Object.assign(s,this.lazyProps.bufferParams),Object.assign(e,this.lazyProps.what),this.lazyProps.bufferParams={},this.lazyProps.what={})),this.setColor(r.color,r);for(let t in r)if(void 0!==r[t]&&null!=n[t]&&(n[t].int&&(r[t]=parseInt(r[t])),n[t].float&&(r[t]=parseFloat(r[t])),r[t]!==this[t]||r[t].equals&&!r[t].equals(this[t]))){if(this[t]&&this[t].copy&&r[t].copy?this[t].copy(r[t]):this[t]&&this[t].set?this[t].set(r[t]):this[t]=r[t],n[t].buffer)if(!0===n[t].buffer)s[t]=r[t];else{s[n[t].buffer]=r[t]}n[t].update&&(e[n[t].update]=!0),!n[t].rebuild||"impostor"===n[t].rebuild&&Pe&&!this.disableImpostor||(i=!0)}return i?this.build():this.updateParameters(s,e),this}updateParameters(t={},e){if(this.lazy&&(!this.visible||!this.opacity)&&!1===t.hasOwnProperty("opacity"))return Object.assign(this.lazyProps.bufferParams,t),void Object.assign(this.lazyProps.what,e);this.bufferList.forEach((function(e){e.setParameters(t)})),Object.keys(e).length&&this.update(e),this.viewer.requestRender()}getParameters(){const t={lazy:this.lazy,visible:this.visible,quality:this.quality};return Object.keys(this.parameters).forEach((e=>{null!==this.parameters[e]&&(t[e]=this[e])})),t}clear(){this.bufferList.forEach((t=>{this.viewer.remove(t),t.dispose()})),this.bufferList.length=0,this.viewer.requestRender()}dispose(){this.disposed=!0,this.queue.kill(),this.tasks.dispose(),this.clear()}}class zr{constructor(t){this.pending=0,this.postCount=0,this.onmessageDict={},this.onerrorDict={},this.name=t,this.blobUrl=window.URL.createObjectURL($e.get(t)),this.worker=new Worker(this.blobUrl),$e.activeWorkerCount+=1,this.worker.onmessage=e=>{this.pending-=1;const i=e.data.__postId;De&&ke.timeEnd("Worker.postMessage "+t+" #"+i);const r=this.onmessageDict[i];r&&r.call(this.worker,e),delete this.onmessageDict[i],delete this.onerrorDict[i]},this.worker.onerror=e=>{if(this.pending-=1,e.data){const i=e.data.__postId,r=this.onerrorDict[i];r?r.call(this.worker,e):ke.error("Worker.onerror",i,t,e),delete this.onmessageDict[i],delete this.onerrorDict[i]}else ke.error("Worker.onerror",t,e)}}post(t={},e,i,r){this.onmessageDict[this.postCount]=i,this.onerrorDict[this.postCount]=r,t.__name=this.name,t.__postId=this.postCount,t.__debug=De,De&&ke.time(`Worker.postMessage ${this.name} #${this.postCount}`);try{this.worker.postMessage(t,e)}catch(e){ke.error("worker.post:",e),this.worker.postMessage(t)}return this.pending+=1,this.postCount+=1,this}terminate(){this.worker?(this.worker.terminate(),window.URL.revokeObjectURL(this.blobUrl),$e.activeWorkerCount-=1):ke.log("no worker to terminate")}}class Ur{constructor(t,e=2){this.pool=[],this.count=0,this.maxCount=Math.min(8,e),this.name=t}post(t={},e,i,r){const n=this.getNextWorker();return n?n.post(t,e,i,r):console.error("unable to get worker from pool"),this}terminate(){this.pool.forEach((function(t){t.terminate()}))}getNextWorker(){let t,e=1/0;for(let i=0;i=this.count){t=new zr(this.name),this.pool.push(t),this.count+=1;break}const r=this.pool[i];if(0===r.pending){t=r;break}r.pendingn&&(n=c),l>s&&(s=l),h>o&&(o=h)}return[Xr([e,i,r]),Xr([n,s,o])]}function Hr(t,e){for(let i=0,r=e.length;i0){const o=1/Math.sqrt(s);t[e]=i*o,t[e+1]=r*o,t[e+2]=n*o}}}function Xr(t){return new Float32Array(t||3)}function Yr(t,e,i){const r=e[0],n=e[1],s=e[2],o=i[0],a=i[1],c=i[2];t[0]=n*c-s*a,t[1]=s*o-r*c,t[2]=r*a-n*o}function Kr(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}function Zr(t,e,i){t[0]=e[0]-i[0],t[1]=e[1]-i[1],t[2]=e[2]-i[2]}function Qr(t,e,i){t[0]=e[0]+i[0],t[1]=e[1]+i[1],t[2]=e[2]+i[2]}function Jr(t,e,i=0){t[0]=e[i],t[1]=e[i+1],t[2]=e[i+2]}function tn(t,e,i=0){e[i]=t[0],e[i+1]=t[1],e[i+2]=t[2]}function en(t){return t[0]*t[0]+t[1]*t[1]+t[2]*t[2]}function rn(t){return Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2])}function nn(t,e,i){sn(t,e,1/i)}function sn(t,e,i){t[0]=e[0]*i,t[1]=e[1]*i,t[2]=e[2]*i}function on(t,e){const i=en(e);0==i?(t[0]=e[0],t[1]=e[1],t[2]=e[2]):sn(t,e,1/Math.sqrt(i))}function an(t,e,i){t[0]=e[0]-i,t[1]=e[1]-i,t[2]=e[2]-i}function cn(t,e,i){t[0]=e[0]+i,t[1]=e[1]+i,t[2]=e[2]+i}function ln(t,e){t[0]=Math.floor(e[0]),t[1]=Math.floor(e[1]),t[2]=Math.floor(e[2])}function hn(t,e){t[0]=Math.ceil(e[0]),t[1]=Math.ceil(e[1]),t[2]=Math.ceil(e[2])}function un(t,e){t[0]=-e[0],t[1]=-e[1],t[2]=-e[2]}function dn(t,e){const i=t[0],r=t[1],n=t[2],s=e[0],o=e[1],a=e[2],c=r*a-n*o,l=n*s-i*a,h=i*o-r*s,u=Math.sqrt(c*c+l*l+h*h),d=i*s+r*o+n*a;return Math.atan2(u,d)}function mn(t,i=9){const r=Math.floor(i/2),n=t.position1.length/3,s=3*(r*n),o=1/i,a=wi(t.position1,t.position2),c=new Float32Array(s),l=new Float32Array(s),h=new e;for(let e=0;e0){const e=3*f;s[e]=t.position2[3*u-3],s[e+1]=t.position2[3*u-2],s[e+1]=t.position2[3*u-1]}const y=new Float32Array(n),b=new Float32Array(s),_=vi(y,b),x=new Float32Array(o),v={position:_,position1:y,position2:b,color:x,color2:x};return a&&(v.radius=new Float32Array(a)),c&&t.picking&&(t.picking.array=new Float32Array(c),v.picking=t.picking),l&&(v.primitiveId=new Float32Array(l)),v}Ur.prototype.constructor=Ur,Gr.__deps=[Xr],nn.__deps=[sn],on.__deps=[sn,en];const gn=new e;class yn{static get Picker(){return Ge.get(this.type)}static get Buffer(){return je.get(this.type)}static getShapeKey(t){return this.type+t[0].toUpperCase()+t.substr(1)}static expandBoundingBox(t,e){}static valueToShape(t,e,i){const r=t._primitiveData[this.getShapeKey(e)];switch(this.fields[e]){case"v3":case"c":!function(t,e){void 0!==t.toArray?t=t.toArray():void 0!==t.x?t=[t.x,t.y,t.z]:void 0!==t.r&&(t=[t.r,t.g,t.b]),e.push.apply(e,t)}(i,r);break;default:r.push(i)}}static objectToShape(t,e){Object.keys(this.fields).forEach((i=>{this.valueToShape(t,i,e[i])})),this.valueToShape(t,"name",e.name),this.expandBoundingBox(t.boundingBox,e)}static valueFromShape(t,i,r){const s=t._primitiveData[this.getShapeKey(r)];switch(this.fields[r]){case"v3":return(new e).fromArray(s,3*i);case"c":return(new n).fromArray(s,3*i);default:return s[i]}}static objectFromShape(t,e){let i=this.valueFromShape(t,e,"name");void 0===i&&(i=`${this.type}: ${e} (${t.name})`);const r={shape:t,name:i};return Object.keys(this.fields).forEach((i=>{r[i]=this.valueFromShape(t,e,i)})),r}static arrayFromShape(t,e){const i=t._primitiveData[this.getShapeKey(e)];return"s"===this.fields[e]?i:new Float32Array(i)}static dataFromShape(t){const e={};return this.Picker&&(e.picking=new this.Picker(t)),Object.keys(this.fields).forEach((i=>{e[i]=this.arrayFromShape(t,i)})),e}static bufferFromShape(t,e){return new this.Buffer(this.dataFromShape(t),e)}}yn.type="",yn.fields={};class bn extends yn{static positionFromShape(t,e){return this.valueFromShape(t,e,"position")}static expandBoundingBox(t,e){t.expandByPoint(gn.fromArray(e.position))}}bn.type="sphere",bn.fields={position:"v3",color:"c",radius:"f"};class _n extends yn{static positionFromShape(t,e){return this.valueFromShape(t,e,"position")}static expandBoundingBox(t,e){t.expandByPoint(gn.fromArray(e.position))}}_n.type="box",_n.fields={position:"v3",color:"c",size:"f",heightAxis:"v3",depthAxis:"v3"};class xn extends _n{}xn.type="octahedron";class vn extends _n{}vn.type="tetrahedron";class wn extends yn{static positionFromShape(t,e){const i=this.valueFromShape(t,e,"position1"),r=this.valueFromShape(t,e,"position2");return i.add(r).multiplyScalar(.5)}static expandBoundingBox(t,e){t.expandByPoint(gn.fromArray(e.position1)),t.expandByPoint(gn.fromArray(e.position2))}static bufferFromShape(t,e={}){let i=this.dataFromShape(t);return"cylinder"===this.type&&e.dashedCylinder&&(i=fn(i)),new this.Buffer(i,e)}}wn.type="cylinder",wn.fields={position1:"v3",position2:"v3",color:"c",radius:"f"};class An extends wn{}An.type="arrow";class Sn extends wn{}Sn.type="cone";class Cn extends bn{}Cn.type="ellipsoid",Cn.fields={position:"v3",color:"c",radius:"f",majorAxis:"v3",minorAxis:"v3"};class Pn extends Cn{}Pn.type="torus";class In extends yn{static positionFromShape(t,e){return this.valueFromShape(t,e,"position")}static expandBoundingBox(t,e){t.expandByPoint(gn.fromArray(e.position))}}In.type="text",In.fields={position:"v3",color:"c",size:"f",text:"s"};class kn extends yn{static positionFromShape(t,e){return this.valueFromShape(t,e,"position")}static expandBoundingBox(t,e){t.expandByPoint(gn.fromArray(e.position))}}kn.type="point",kn.fields={position:"v3",color:"c"};class Mn extends yn{static positionFromShape(t,e){const i=this.valueFromShape(t,e,"position1"),r=this.valueFromShape(t,e,"position2");return i.add(r).multiplyScalar(.5)}static expandBoundingBox(t,e){t.expandByPoint(gn.fromArray(e.position1)),t.expandByPoint(gn.fromArray(e.position2))}}Mn.type="wideline",Mn.fields={position1:"v3",position2:"v3",color:"c"};class Tn{constructor(t,e){this.exp=3;const i=e||function(t){const{x:e,y:i,z:r}=t,n=new a,s=e.length,{min:o,max:c}=n;for(let t=0;t>this.exp),this.boundY=1+(i.max.y-this.minY>>this.exp),this.boundZ=1+(i.max.z-this.minZ>>this.exp);const r=this.boundX*this.boundY*this.boundZ,n=void 0!==t.count?t.count:t.x.length,s=t.x,o=t.y,c=t.z;let l=0;const h=new Uint32Array(r),u=new Int32Array(n);for(let t=0;t>this.exp,i=o[t]-this.minY>>this.exp,r=c[t]-this.minZ>>this.exp,n=(e*this.boundY+i)*this.boundZ+r;1===(h[n]+=1)&&(l+=1),u[t]=n}const d=new Uint16Array(l);for(let t=0,e=0;t0&&(h[t]=e+1,d[e]=i,e+=1)}const m=new Uint32Array(l);for(let t=1;t0){const i=e-1;p[m[i]+f[i]]=t,f[i]+=1}}this.grid=h,this.bucketCount=d,this.bucketOffset=m,this.bucketArray=p,this.xArray=s,this.yArray=o,this.zArray=c}within(t,e,i,r){const n=[];return this.eachWithin(t,e,i,r,(t=>n.push(t))),n}eachWithin(t,e,i,r,n){const s=r*r,o=Math.max(0,t-r-this.minX>>this.exp),a=Math.max(0,e-r-this.minY>>this.exp),c=Math.max(0,i-r-this.minZ>>this.exp),l=Math.min(this.boundX,1+(t+r-this.minX>>this.exp)),h=Math.min(this.boundY,1+(e+r-this.minY>>this.exp)),u=Math.min(this.boundZ,1+(i+r-this.minZ>>this.exp));for(let r=o;r0){const r=l-1,o=this.bucketOffset[r],a=o+this.bucketCount[r];for(let r=o;rr?n.set(this[e].subarray(0,r)):n.set(this[e]),this[e]=n}}growIfFull(){if(this.count>=this.length){const t=Math.round(1.5*this.length);this.resize(Math.max(256,t))}}copyFrom(t,e,i,r){for(let n=0,s=this._fields.length;n0;)h-=1;l<=h&&(l===c?c=h:h===c&&(c=l),(o=l)!==(a=h)&&(i.copyFrom(e,0,o,1),e.copyWithin(o,a,1),e.copyFrom(i,a,0,1)),l+=1,h-=1)}while(l<=h);r(n,h),r(l,s)}var o,a}(0,this.count-1),ke.timeEnd("Store.sort")}clear(){this.count=0}dispose(){for(let t=0,e=this._fields.length;t>>1&1431655765))+(t>>>2&858993459))+(t>>>4)&252645135)>>>24}class En{constructor(t,e){this.length=t,this._words=new Uint32Array(t+32>>>5),!0===e&&this.setAll()}get(t){return!!(this._words[t>>>5]&1<>>5]|=1<>>5]&=~(1<>>5]^=1<>>5,o=e>>>5;for(let t=s+1;t>>5]|=1<>>5]|=1<>>5]|=1<>>5]&=~(1<>>5]&=~(1<>>5]&=~(1<>>5]|=1<>>5]&=~(1<>>i,this}_isRangeValue(t,e,i){if(e>>5,o=e>>>5;for(let t=s+1;t>>5]&1<>>5]&1<>>5]&1<>>5]&1<>>5]&1<0){const{types:r,groups:n,centers:s,atomSets:o}=t;r.push(e.type),n.push(e.group),s.x.push(e.x/i),s.y.push(e.y/i),s.z.push(e.z/i),o.push(e.atomSet)}}const Nn=0,zn=["D-BETA-PEPTIDE, C-GAMMA LINKING","D-GAMMA-PEPTIDE, C-DELTA LINKING","D-PEPTIDE COOH CARBOXY TERMINUS","D-PEPTIDE NH3 AMINO TERMINUS","D-PEPTIDE LINKING","L-BETA-PEPTIDE, C-GAMMA LINKING","L-GAMMA-PEPTIDE, C-DELTA LINKING","L-PEPTIDE COOH CARBOXY TERMINUS","L-PEPTIDE NH3 AMINO TERMINUS","L-PEPTIDE LINKING","PEPTIDE LINKING","PEPTIDE-LIKE"],Un=["RNA OH 3 PRIME TERMINUS","RNA OH 5 PRIME TERMINUS","RNA LINKING"],Vn=["DNA OH 3 PRIME TERMINUS","DNA OH 5 PRIME TERMINUS","DNA LINKING","L-DNA LINKING","L-RNA LINKING"],jn=["D-SACCHARIDE","D-SACCHARIDE 1,4 AND 1,4 LINKING","D-SACCHARIDE 1,4 AND 1,6 LINKING","L-SACCHARIDE","L-SACCHARIDE 1,4 AND 1,4 LINKING","L-SACCHARIDE 1,4 AND 1,6 LINKING","SACCHARIDE"],Gn=["NON-POLYMER"].concat(["OTHER"],jn),Hn=["h","g","i"],qn=["e","b"],Wn=["s","t","l",""],Xn={H:1,D:1,T:1,HE:2,LI:3,BE:4,B:5,C:6,N:7,O:8,F:9,NE:10,NA:11,MG:12,AL:13,SI:14,P:15,S:16,CL:17,AR:18,K:19,CA:20,SC:21,TI:22,V:23,CR:24,MN:25,FE:26,CO:27,NI:28,CU:29,ZN:30,GA:31,GE:32,AS:33,SE:34,BR:35,KR:36,RB:37,SR:38,Y:39,ZR:40,NB:41,MO:42,TC:43,RU:44,RH:45,PD:46,AG:47,CD:48,IN:49,SN:50,SB:51,TE:52,I:53,XE:54,CS:55,BA:56,LA:57,CE:58,PR:59,ND:60,PM:61,SM:62,EU:63,GD:64,TB:65,DY:66,HO:67,ER:68,TM:69,YB:70,LU:71,HF:72,TA:73,W:74,RE:75,OS:76,IR:77,PT:78,AU:79,HG:80,TL:81,PB:82,BI:83,PO:84,AT:85,RN:86,FR:87,RA:88,AC:89,TH:90,PA:91,U:92,NP:93,PU:94,AM:95,CM:96,BK:97,CF:98,ES:99,FM:100,MD:101,NO:102,LR:103,RF:104,DB:105,SG:106,BH:107,HS:108,MT:109,DS:110,RG:111,CN:112,NH:113,FL:114,MC:115,LV:116,TS:117,OG:118},Yn={1:1.1,2:1.4,3:1.81,4:1.53,5:1.92,6:1.7,7:1.55,8:1.52,9:1.47,10:1.54,11:2.27,12:1.73,13:1.84,14:2.1,15:1.8,16:1.8,17:1.75,18:1.88,19:2.75,20:2.31,21:2.3,22:2.15,23:2.05,24:2.05,25:2.05,26:2.05,27:2,28:2,29:2,30:2.1,31:1.87,32:2.11,33:1.85,34:1.9,35:1.83,36:2.02,37:3.03,38:2.49,39:2.4,40:2.3,41:2.15,42:2.1,43:2.05,44:2.05,45:2,46:2.05,47:2.1,48:2.2,49:2.2,50:1.93,51:2.17,52:2.06,53:1.98,54:2.16,55:3.43,56:2.68,57:2.5,58:2.48,59:2.47,60:2.45,61:2.43,62:2.42,63:2.4,64:2.38,65:2.37,66:2.35,67:2.33,68:2.32,69:2.3,70:2.28,71:2.27,72:2.25,73:2.2,74:2.1,75:2.05,76:2,77:2,78:2.05,79:2.1,80:2.05,81:1.96,82:2.02,83:2.07,84:1.97,85:2.02,86:2.2,87:3.48,88:2.83,89:2,90:2.4,91:2,92:2.3,93:2,94:2,95:2,96:2,97:2,98:2,99:2,100:2,101:2,102:2,103:2,104:2,105:2,106:2,107:2,108:2,109:2,110:2,111:2,112:2,113:2,114:2,115:2,116:2,117:2,118:2},Kn={1:.31,2:.28,3:1.28,4:.96,5:.84,6:.76,7:.71,8:.66,9:.57,10:.58,11:1.66,12:1.41,13:1.21,14:1.11,15:1.07,16:1.05,17:1.02,18:1.06,19:2.03,20:1.76,21:1.7,22:1.6,23:1.53,24:1.39,25:1.39,26:1.32,27:1.26,28:1.24,29:1.32,30:1.22,31:1.22,32:1.2,33:1.19,34:1.2,35:1.2,36:1.16,37:2.2,38:1.95,39:1.9,40:1.75,41:1.64,42:1.54,43:1.47,44:1.46,45:1.42,46:1.39,47:1.45,48:1.44,49:1.42,50:1.39,51:1.39,52:1.38,53:1.39,54:1.4,55:2.44,56:2.15,57:2.07,58:2.04,59:2.03,60:2.01,61:1.99,62:1.98,63:1.98,64:1.96,65:1.94,66:1.92,67:1.92,68:1.89,69:1.9,70:1.87,71:1.87,72:1.75,73:1.7,74:1.62,75:1.51,76:1.44,77:1.41,78:1.36,79:1.36,80:1.32,81:1.45,82:1.46,83:1.48,84:1.4,85:1.5,86:1.5,87:2.6,88:2.21,89:2.15,90:2.06,91:2,92:1.96,93:1.9,94:1.87,95:1.8,96:1.69,97:1.6,98:1.6,99:1.6,100:1.6,101:1.6,102:1.6,103:1.6,104:1.6,105:1.6,106:1.6,107:1.6,108:1.6,109:1.6,110:1.6,111:1.6,112:1.6,113:1.6,114:1.6,115:1.6,116:1.6,117:1.6,118:1.6},Zn={1:[1],2:[0],3:[1],4:[2],5:[3],6:[4],7:[3],8:[2],9:[1],10:[0],11:[1],12:[2],13:[6],14:[6],15:[3,5,7],16:[2,4,6],17:[1],18:[0],19:[1],20:[2],31:[3],32:[4],33:[3,5],34:[2,4,6],35:[1],36:[0],37:[1],38:[2],49:[3],50:[4],51:[3,5],52:[2],53:[1,2,5],54:[0,2],55:[1],56:[2],81:[3],82:[4],83:[3],84:[2],85:[1],86:[0],87:[1],88:[2]},Qn={1:1,2:2,3:1,4:2,5:3,6:4,7:5,8:6,9:7,10:8,11:1,12:2,13:3,14:4,15:5,16:6,17:7,18:8,19:1,20:2,21:3,22:4,23:5,24:6,25:7,26:8,27:9,28:10,29:11,30:2,31:3,32:4,33:5,34:6,35:7,36:8,37:1,38:2,39:3,40:4,41:5,42:6,43:7,44:8,45:9,46:10,47:11,48:2,49:3,50:4,51:5,52:6,53:7,54:8,55:1,56:2,57:3,58:4,59:3,60:4,61:5,62:6,63:7,64:8,65:9,66:10,67:11,68:12,69:13,70:14,71:15,72:4,73:5,74:6,75:7,76:8,77:9,78:10,79:11,80:2,81:3,82:4,83:5,84:6,85:7,86:8,87:1,88:2,89:3,90:4,91:3,92:4,93:5,94:6,95:7,96:8,97:9,98:10,99:11,100:12,101:13,102:14,103:15,104:2,105:2,106:2,107:2,108:2,109:2,110:2,111:2,112:2,113:3,114:4,115:5,116:6,117:7,118:8},Jn={ALA:[.17,.5,.33],ARG:[.81,1.81,1],ASN:[.42,.85,.43],ASP:[1.23,3.64,2.41],ASH:[-.07,.43,.5],CYS:[-.24,-.02,.22],GLN:[.58,.77,.19],GLU:[2.02,3.63,1.61],GLH:[-.01,.11,.12],GLY:[.01,1.15,1.14],HIS:[.17,.11,-.06],ILE:[-.31,-1.12,-.81],LEU:[-.56,-1.25,-.69],LYS:[.99,2.8,1.81],MET:[-.23,-.67,-.44],PHE:[-1.13,-1.71,-.58],PRO:[.45,.14,-.31],SER:[.13,.46,.33],THR:[.14,.25,.11],TRP:[-1.85,-2.09,-.24],TYR:[-.94,-.71,.23],VAL:[.07,-.46,-.53]},ts=[0,0,0],es={HIS:"H",ARG:"R",LYS:"K",ILE:"I",PHE:"F",LEU:"L",TRP:"W",ALA:"A",MET:"M",PRO:"P",CYS:"C",ASN:"N",VAL:"V",GLY:"G",SER:"S",GLN:"Q",TYR:"Y",ASP:"D",GLU:"E",THR:"T",SEC:"U",PYL:"O"},is=Object.keys(es),rs=["A","C","T","G","U","I"],ns=["DA","DC","DT","DG","DU","DI"],ss=["A","G","I","DA","DG","DI"],os=rs.concat(ns),as=["SOL","WAT","HOH","H2O","W","DOD","D3O","TIP3","TIP4","SPC"],cs=["118","119","1AL","1CU","2FK","2HP","2OF","3CO","3MT","3NI","3OF","3P8","4MO","4PU","543","6MO","ACT","AG","AL","ALF","AM","ATH","AU","AU3","AUC","AZI","BA","BCT","BEF","BF4","BO4","BR","BS3","BSY","CA","CAC","CD","CD1","CD3","CD5","CE","CHT","CL","CO","CO3","CO5","CON","CR","CS","CSB","CU","CU1","CU3","CUA","CUZ","CYN","DME","DMI","DSC","DTI","DY","E4N","EDR","EMC","ER3","EU","EU3","F","FE","FE2","FPO","GA","GD3","GEP","HAI","HG","HGC","IN","IOD","IR","IR3","IRI","IUM","K","KO4","LA","LCO","LCP","LI","LU","MAC","MG","MH2","MH3","MLI","MLT","MMC","MN","MN3","MN5","MN6","MO1","MO2","MO3","MO4","MO5","MO6","MOO","MOS","MOW","MW1","MW2","MW3","NA","NA2","NA5","NA6","NAO","NAW","NCO","NET","NH4","NI","NI1","NI2","NI3","NO2","NO3","NRU","O4M","OAA","OC1","OC2","OC3","OC4","OC5","OC6","OC7","OC8","OCL","OCM","OCN","OCO","OF1","OF2","OF3","OH","OS","OS4","OXL","PB","PBM","PD","PDV","PER","PI","PO3","PO4","PR","PT","PT4","PTN","RB","RH3","RHD","RU","SB","SCN","SE4","SEK","SM","SMO","SO3","SO4","SR","T1A","TB","TBA","TCN","TEA","TH","THE","TL","TMA","TRA","UNX","V","VN3","VO4","W","WO5","Y1","YB","YB2","YH","YT3","ZCM","ZN","ZN2","ZN3","ZNO","ZO3","OHX"],ls=["045","0AT","0BD","0MK","0NZ","0TS","0V4","0XY","0YT","10M","147","149","14T","15L","16G","18T","18Y","1AR","1BW","1GL","1GN","1JB","1LL","1NA","1S3","26M","26Q","26R","26V","26W","26Y","27C","289","291","293","2DG","2F8","2FG","2FL","2FP","2GL","2M4","2M5","32O","34V","3CM","3DO","3DY","3FM","3LR","3MF","3MG","3SA","3ZW","46D","46M","46Z","48Z","4CQ","4GC","4NN","50A","5DI","5GF","5MM","5RP","5SA","5SP","64K","6PG","6SA","7JZ","7SA","A1Q","A2G","AAB","AAL","AAO","ABC","ABD","ABE","ABF","ABL","ACG","ACI","ACR","ACX","ADA","ADG","ADR","AF1","AFD","AFL","AFO","AFP","AFR","AGC","AGH","AGL","AHR","AIG","ALL","ALX","AMU","AOG","AOS","ARA","ARB","ARE","ARI","ASG","ASO","AXP","AXR","B0D","B16","B2G","B4G","B6D","B8D","B9D","BBK","BCD","BDG","BDP","BDR","BEM","BFP","BGC","BGL","BGP","BGS","BHG","BMA","BMX","BNG","BNX","BOG","BRI","BXF","BXP","BXX","BXY","C3X","C4X","C5X","CAP","CBI","CBK","CBS","CDR","CEG","CGF","CHO","CR1","CR6","CRA","CT3","CTO","CTR","CTT","D6G","DAF","DAG","DDA","DDB","DDL","DEL","DFR","DFX","DG0","DGC","DGD","DGM","DGS","DIG","DLF","DLG","DMU","DNO","DOM","DP5","DQQ","DQR","DR2","DR3","DR4","DRI","DSR","DT6","DVC","E4P","E5G","EAG","EBG","EBQ","EGA","EJT","EPG","ERE","ERI","F1P","F1X","F6P","FBP","FCA","FCB","FCT","FDP","FDQ","FFC","FIX","FMO","FRU","FSI","FU4","FUB","FUC","FUD","FUL","FXP","G16","G1P","G2F","G3I","G4D","G4S","G6D","G6P","G6S","GAC","GAD","GAL","GC1","GC4","GCD","GCN","GCO","GCS","GCT","GCU","GCV","GCW","GCX","GE1","GFG","GFP","GIV","GL0","GL2","GL5","GL6","GL7","GL9","GLA","GLB","GLC","GLD","GLF","GLG","GLO","GLP","GLS","GLT","GLW","GMH","GN1","GNX","GP1","GP4","GPH","GPM","GQ1","GQ2","GQ4","GS1","GS4","GSA","GSD","GTE","GTH","GTK","GTR","GTZ","GU0","GU1","GU2","GU3","GU4","GU5","GU6","GU8","GU9","GUF","GUP","GUZ","GYP","GYV","H2P","HDL","HMS","HS2","HSD","HSG","HSH","HSJ","HSQ","HSR","HSU","HSX","HSY","HSZ","IAB","IDG","IDR","IDS","IDT","IDU","IDX","IDY","IMK","IN1","IPT","ISL","KBG","KD2","KDA","KDM","KDO","KFN","KO1","KO2","KTU","L6S","LAG","LAI","LAK","LAO","LAT","LB2","LBT","LCN","LDY","LGC","LGU","LM2","LMT","LMU","LOG","LOX","LPK","LSM","LTM","LVZ","LXB","LXZ","M1F","M3M","M6P","M8C","MA1","MA2","MA3","MAB","MAG","MAL","MAN","MAT","MAV","MAW","MBG","MCU","MDA","MDM","MDP","MFA","MFB","MFU","MG5","MGA","MGL","MLB","MMA","MMN","MN0","MRP","MTT","MUG","MVP","MXY","N1L","N9S","NAA","NAG","NBG","NDG","NED","NG1","NG6","NGA","NGB","NGC","NGE","NGF","NGL","NGS","NGY","NHF","NM6","NM9","NTF","NTO","NTP","NXD","NYT","OPG","OPM","ORP","OX2","P3M","P53","P6P","PA5","PNA","PNG","PNW","PRP","PSJ","PSV","PTQ","QDK","QPS","QV4","R1P","R1X","R2B","R5P","RAA","RAE","RAF","RAM","RAO","RAT","RB5","RBL","RCD","RDP","REL","RER","RF5","RG1","RGG","RHA","RIB","RIP","RNS","RNT","ROB","ROR","RPA","RST","RUB","RUU","RZM","S6P","S7P","SA0","SCR","SDD","SF6","SF9","SG4","SG5","SG6","SG7","SGA","SGC","SGD","SGN","SGS","SHB","SHG","SI3","SIO","SOE","SOL","SSG","SUC","SUP","SUS","T6P","T6T","TAG","TCB","TDG","TGK","TGY","TH1","TIA","TM5","TM6","TM9","TMR","TMX","TOA","TOC","TRE","TYV","UCD","UDC","VG1","X0X","X1X","X2F","X4S","X5S","X6X","XBP","XDN","XDP","XIF","XIM","XLF","XLS","XMM","XUL","XXR","XYP","XYS","YO5","Z3Q","Z6J","Z9M","ZDC","ZDM"],hs=["CA","C","N","O","O1","O2","OC1","OC2","OX1","OXT","OT1","OT2","H","H1","H2","H3","HA","HN","BB"],us=["P","OP1","OP2","HOP2","HOP3","O2'","O3'","O4'","O5'","C1'","C2'","C3'","C4'","C5'","H1'","H2'","H2''","HO2'","H3'","H4'","H5'","H5''","HO3'","HO5'","O2*","O3*","O4*","O5*","C1*","C2*","C3*","C4*","C5*"],ds={1:{trace:"CA",direction1:"C",direction2:["O","OC1","O1","OX1","OXT","OT1","OT2"],backboneStart:"N",backboneEnd:"C"},2:{trace:["C4'","C4*"],direction1:["C1'","C1*"],direction2:["C3'","C3*"],backboneStart:"P",backboneEnd:["O3'","O3*"]},3:{trace:["C3'","C3*"],direction1:["C2'","C2*"],direction2:["O4'","O4*"],backboneStart:"P",backboneEnd:["O3'","O3*"]},4:{trace:["CA","BB"],backboneStart:["CA","BB"],backboneEnd:["CA","BB"]},5:{trace:["C4'","C4*","P"],backboneStart:["C4'","C4*","P"],backboneEnd:["C4'","C4*","P"]},6:{trace:["C3'","C3*","C2'","P"],backboneStart:["C3'","C3*","C2'","P"],backboneEnd:["C3'","C3*","C2'","P"]}};ds[Nn]={};const ms={HD:"H",HS:"H",A:"C",NA:"N",NS:"N",OA:"O",OS:"O",SA:"S",G0:"C",G1:"C",G2:"C",G3:"C",CG0:"C",CG1:"C",CG2:"C",CG3:"C",W:"O"};function fs(t){switch(t){case 0:return 0;case 1:return 1;case 2:return 2;case 3:return 3;case 4:return 4;default:return 8}}const ps=new Map([[2,It(180)],[3,It(120)],[4,It(109.4721)],[6,It(90)]]);function gs(t,i){let r=[];const n=new e,s=new e;return n.subVectors(i,t),t.eachBondedAtom((e=>{1!==e.number&&(s.subVectors(e,t),r.push(n.angleTo(s)))})),r}function ys(t,i){const r=t.clone(),n=new e;n.subVectors(i,t);const s=[new e,new e];let o=0;if(t.eachBondedAtom((e=>{o>1||1!==e.number&&(r.index=e.index,s[o++].subVectors(e,t))})),1===o&&r.eachBondedAtom((e=>{o>1||1!==e.number&&e.index!==t.index&&s[o++].subVectors(e,t)})),2!==o)return;const a=s[0].cross(s[1]);return Math.abs(Math.PI/2-a.angleTo(n))}function bs(t,e){const i=t.structure,r=i.atomCount,n=new Int8Array(r),s=new Int8Array(r),o=new Int8Array(r),a=new Int8Array(r);return i.eachAtom((t=>{const i=t.index,[r,c,l,h]=function(t,e){const i=t.bondToElementCount(1);let r=t.formalCharge||0;const n="always"===e.assignCharge||"auto"===e.assignCharge&&0===r,s="always"===e.assignH||"auto"===e.assignH&&0===i,o=t.bondCount,a=function(t){let e=0;return t.eachBond((t=>e+=t.bondOrder)),e}(t),c=function(t){const e=t.structure.getBondProxy(),i=t.number,r=8===i||7===i;if(r&&4===t.bondCount)return!1;let n=!1;return t.eachBond((i=>{if(i.bondOrder>1)n=!0;else if(r){const r=i.getOtherAtom(t);r.eachBond((t=>{if(t.bondOrder>1){const e=r.number;if((15===e||16===e)&&8===t.getOtherAtom(r).number)return;n=!0}}),e)}})),n}(t),l=a-o>0;let h=0,u=8;switch(t.number){case 1:n&&(0===o?(r=1,u=0):1===o&&(r=0,u=1));break;case 6:n&&(r=0),s&&(h=Math.max(0,4-a-Math.abs(r))),u=fs(o+h+Math.max(0,-r));break;case 7:if(n)if(s)if(c&&a<4)r=o-i==1&&a-i==2?1:0;else{let e=!1;t.eachBondedAtom((t=>{(16===t.number||t.isMetal())&&(e=!0)})),r=e?0:1}else r=a-3;s&&(h=Math.max(0,3-a+r)),u=fs(c&&!l?o+h-r:o+h+1-r);break;case 8:n&&(s||(r=a-2),1===a&&t.eachBondedAtom((e=>{e.eachBond((i=>{const n=i.getOtherAtom(e);n.index!==t.index&&8===n.number&&2===i.bondOrder&&(r=-1)}))}))),s&&(h=Math.max(0,2-a+r)),u=fs(c&&!l?o+h-r+1:o+h-r+2);break;case 16:n&&(s||(r=a<=3&&!t.bondToElementCount(8)?a-2:0)),s&&a<2&&(h=Math.max(0,2-a+r)),a<=3&&(u=fs(o+h-r+2));break;case 9:case 17:case 35:case 53:case 85:n&&(r=a-1);break;case 3:case 11:case 19:case 37:case 55:case 87:n&&(r=1-a);break;case 4:case 12:case 20:case 38:case 56:case 88:n&&(r=2-a);break;default:console.warn("Requested charge, protonation for an unhandled element",t.element)}return[r,h,h+i,u]}(t,e);n[i]=r,s[i]=c,o[i]=l,a[i]=h})),{charge:n,implicitH:s,totalH:o,idealGeometry:a}}function _s(t){if(t["@valenceModel"])return t["@valenceModel"];const e=bs(t,{assignCharge:"auto",assignH:"auto"});return t["@valenceModel"]=e,e}function xs(t){return 15===t.number&&t.bondToElementCount(8)===t.bondCount}const vs=["ARG","HIS","LYS"],ws=["GLU","ASP"];function As(t,e){return 2===t&&1===e||1===t&&2===e}function Ss(t,e){return 3===t&&3===e}function Cs(t,e){return 3===t&&1===e||1===t&&3===e}function Ps(t){return"HIS"===t.resname&&7==t.number&&t.isRing()}function Is(t,e){return 5===t&&4===e||4===t&&5===e}function ks(t,e){return 9===t&&5===e||5===t&&9===e}const Ms=[3,11,19,37,55,12,20,38,56,13,31,49,81,21,50,82,83,51,80];function Ts(t,e){return 12===t?11===e||12===e:13===t?10===e:void 0}const Ds=[17,35,53,85];const Bs=[7,8,16],Fs=[6,7,15,16];const Es=It(180),$s=It(120);function Os(t,e,i){return!Ls(t,e,i)&&(t.modelIndex!==e.modelIndex||t.altloc&&e.altloc&&t.altloc!==e.altloc)}const Rs={maxHydrophobicDist:4,maxHbondDist:3.5,maxHbondSulfurDist:4.1,maxHbondAccAngle:45,maxHbondDonAngle:45,maxHbondAccPlaneAngle:90,maxHbondDonPlaneAngle:30,maxPiStackingDist:5.5,maxPiStackingOffset:2,maxPiStackingAngle:30,maxCationPiDist:6,maxCationPiOffset:2,maxIonicDist:5,maxHalogenBondDist:4,maxHalogenBondAngle:30,maxMetalDist:3,refineSaltBridges:!0,masterModelIndex:-1,lineOfSightDistFactor:1};function Ls(t,e,i){return t.modelIndex===i&&e.modelIndex!==i||e.modelIndex===i&&t.modelIndex!==i}function Ns(t,e,i){return!Ls(t,e,i)&&(t.modelIndex!==e.modelIndex||t.residueIndex===e.residueIndex||t.altloc&&e.altloc&&t.altloc!==e.altloc)}function zs(t){const e={types:[],groups:[],centers:{x:[],y:[],z:[]},atomSets:[]};return De&&ke.time("calculateFeatures"),function(t,e){const{charge:i}=_s(t.data),r={};t.eachResidue((t=>{if(vs.includes(t.resname)){const i=On(1);t.eachAtom((t=>{7===t.number&&t.isSidechain()&&Rn(i,t)})),Ln(e,i)}else is.includes(t.resname)||t.isNucleic()||(t.eachAtom((t=>{let i=!1;const n=On(1);!function(t){let e=0;return 6===t.number&&3===t.bondCount&&3===t.bondToElementCount(7)&&t.eachBondedAtom((t=>{t.bondCount-t.bondToElementCount(1)==1&&++e})),2===e}(t)?function(t){let e=0;return 6===t.number&&3===t.bondCount&&2===t.bondToElementCount(7)&&1===t.bondToElementCount(6)&&t.eachBondedAtom((t=>{t.bondCount-t.bondToElementCount(1)==1&&++e})),2===e}(t)&&(n.group=9,i=!0):(n.group=8,i=!0),i&&(t.eachBondedAtom((t=>{7===t.number&&(r[t.index]=!0,Rn(n,t))})),Ln(e,n))})),t.eachAtom((t=>{const n=On(1);i[t.index]>0&&(r[t.index]||(Rn(n,t),Ln(e,n)))})))}))}(t,e),function(t,e){const{charge:i}=_s(t.data),r={};t.eachResidue((t=>{if(ws.includes(t.resname)){const i=On(2);t.eachAtom((t=>{8===t.number&&t.isSidechain()&&Rn(i,t)})),Ln(e,i)}else if(os.includes(t.resname)){const i=On(2);t.eachAtom((t=>{xs(t)&&(i.group=6,t.eachBondedAtom((t=>{8===t.number&&Rn(i,t)})),Ln(e,i))}))}else is.includes(t.resname)||os.includes(t.resname)||(t.eachAtom((t=>{let i=!1;const n=On(2);!function(t){return 16===t.number&&3===t.bondToElementCount(8)}(t)?xs(t)?(n.group=6,i=!0):function(t){return 16===t.number&&4===t.bondToElementCount(8)}(t)?(n.group=5,i=!0):function(t){let e=0;return 6===t.number&&2===t.bondToElementCount(8)&&1===t.bondToElementCount(6)&&t.eachBondedAtom((t=>{8===t.number&&t.bondCount-t.bondToElementCount(1)==1&&++e})),2===e}(t)&&(n.group=10,i=!0):(n.group=4,i=!0),i&&(t.eachBondedAtom((t=>{8===t.number&&(r[t.index]=!0,Rn(n,t))})),Ln(e,n))})),t.eachAtom((t=>{const n=On(2);i[t.index]<0&&(r[t.index]||(Rn(n,t),Ln(e,n)))})))}))}(t,e),function(t,e){const i=t.getAtomProxy();t.eachResidue((t=>{const r=t.getAromaticRings();if(r){const n=t.atomOffset;r.forEach((t=>{const r=On(3);t.forEach((t=>{i.index=t+n,Rn(r,i)})),Ln(e,r)}))}}))}(t,e),function(t,e){const{charge:i,implicitH:r,idealGeometry:n}=_s(t.data);t.eachAtom((t=>{const s=On(5),o=t.number;if(8===o)Rn(s,t),Ln(e,s);else if(7===o){if(Ps(t))Rn(s,t),Ln(e,s);else if(i[t.index]<1){const i=t.bondCount+r[t.index],o=n[t.index];(4===o&&i<4||3===o&&i<3||2===o&&i<2)&&(Rn(s,t),Ln(e,s))}}else 16===o&&("CYS"!==t.resname&&"MET"!==t.resname&&-1!==t.formalCharge||(Rn(s,t),Ln(e,s)))}))}(t,e),function(t,e){const{totalH:i}=_s(t.data);t.eachAtom((t=>{const r=On(4),n=t.number;(Ps(t)||i[t.index]>0&&(7===n||8===n||16===n))&&(Rn(r,t),Ln(e,r))}))}(t,e),function(t,e){const{totalH:i}=_s(t.data);t.eachAtom((t=>{if(6===t.number&&i[t.index]>0&&(t.bondToElementCount(7)>0||t.bondToElementCount(8)>0||function(t){if(!t.isAromatic())return!1;const e=t.residueType.getRings();if(!e)return!1;let i=!1;return e.rings.forEach((e=>{i||e.some((e=>t.index-t.residueAtomOffset===e))&&(i=e.some((e=>{const i=t.residueType.atomTypeIdList[e],r=t.atomMap.get(i).number;return 7===r||8===r})))})),i}(t))){const i=On(9);Rn(i,t),Ln(e,i)}}))}(t,e),function(t,e){t.eachAtom((t=>{let i=!1,r=!1;const n=is.includes(t.resname),s=os.includes(t.resname);if(n||s?n?8===t.number?(["ASP","GLU","SER","THR","TYR","ASN","GLN"].includes(t.resname)&&t.isSidechain()||t.isBackbone())&&(i=!0,r=!0):16===t.number&&"CYS"===t.resname?(i=!0,r=!0):7===t.number&&"HIS"===t.resname&&t.isSidechain()&&(i=!0):s&&(8===t.number&&t.isBackbone()?(i=!0,r=!0):["N3","N4","N7"].includes(t.atomname)?i=!0:["O2","O4","O6"].includes(t.atomname)&&(i=!0,r=!0)):t.isHalogen()||8===t.number||16===t.number?(i=!0,r=!0):7===t.number&&(i=!0),i){const i=On(11);Rn(i,t),Ln(e,i)}if(r){const i=On(10);Rn(i,t),Ln(e,i)}}))}(t,e),function(t,e){t.eachAtom((t=>{if(t.isTransitionMetal()||30===t.number||48===t.number){const i=On(12);Rn(i,t),Ln(e,i)}else if(Ms.includes(t.number)){const i=On(13);Rn(i,t),Ln(e,i)}}))}(t,e),function(t,e){t.eachAtom((t=>{const i=On(8);let r=!1;6===t.number?(r=!0,t.eachBondedAtom((t=>{const e=t.number;6!==e&&1!==e&&(r=!1)}))):9===t.number&&(r=!0),r&&(Rn(i,t),Ln(e,i))}))}(t,e),function(t,e){t.eachAtom((t=>{if(Bs.includes(t.number)){let i=!1;if(t.eachBondedAtom((t=>{Fs.includes(t.number)&&(i=!0)})),i){const i=On(7);Rn(i,t),Ln(e,i)}}}))}(t,e),function(t,e){t.eachAtom((t=>{if(Ds.includes(t.number)&&1===t.bondToElementCount(6)){const i=On(6);Rn(i,t),Ln(e,i)}}))}(t,e),De&&ke.timeEnd("calculateFeatures"),e}function Us(t,i=Rs){const r=function(t){const{types:e,centers:i}=t;return{features:t,spatialHash:new Tn(i),contactStore:new Bn,featureSet:new En(e.length,!1)}}(zs(t));De&&ke.time("calculateContacts"),function(t,i,r={}){const n=rt(r.maxIonicDist,Rs.maxIonicDist),s=rt(r.maxPiStackingDist,Rs.maxPiStackingDist),o=rt(r.maxPiStackingOffset,Rs.maxPiStackingOffset),a=rt(r.maxPiStackingAngle,Rs.maxPiStackingAngle),c=rt(r.maxCationPiDist,Rs.maxCationPiDist),l=rt(r.maxCationPiOffset,Rs.maxCationPiOffset),h=rt(r.masterModelIndex,Rs.masterModelIndex),u=Math.max(n+2,s,c),d=s*s,m=c*c,{features:f,spatialHash:p,contactStore:g,featureSet:y}=i,{types:b,centers:_,atomSets:x}=f,{x:v,y:w,z:A}=_,S=b.length,C=t.atomStore.x,P=t.atomStore.y,I=t.atomStore.z,k=t.getAtomProxy(),M=t.getAtomProxy(),T=function(t,e,i){const r=t.length,n=e.length;for(let s=0;s{if(e<=t)return;if(k.index=x[t][0],M.index=x[e][0],Ns(k,M,h))return;const r=b[t],s=b[e];if(As(r,s))T(x[t],x[e],n)&&z(t,e,1);else if(Ss(r,s)){if(i<=d){L(x[t],O),L(x[e],R);const i=57.29578*O.angleTo(R);Math.min(N(t,e,R),N(e,t,O))<=o&&(i<=a||i>=180-a||i<=a+90&&i>=90-a)&&z(t,e,3)}}else if(Cs(r,s)&&i<=m){const[i,n]=3===r?[t,e]:[e,t];L(x[i],O),N(n,i,O)<=l&&z(i,n,2)}}))}(t,r,i),function(t,e,i={}){const r=rt(i.maxHbondDist,Rs.maxHbondDist),n=rt(i.maxHbondSulfurDist,Rs.maxHbondSulfurDist),s=It(rt(i.maxHbondAccAngle,Rs.maxHbondAccAngle)),o=It(rt(i.maxHbondDonAngle,Rs.maxHbondDonAngle)),a=It(rt(i.maxHbondAccPlaneAngle,Rs.maxHbondAccPlaneAngle)),c=It(rt(i.maxHbondDonPlaneAngle,Rs.maxHbondDonPlaneAngle)),l=rt(i.masterModelIndex,Rs.masterModelIndex),h=Math.max(r,n),u=r*r,{features:d,spatialHash:m,contactStore:f,featureSet:p}=e,{types:g,centers:y,atomSets:b}=d,{x:_,y:x,z:v}=y,w=g.length,{idealGeometry:A}=_s(t.data),S=t.getAtomProxy(),C=t.getAtomProxy();for(let t=0;t{if(e<=t)return;const r=g[t],n=g[e],h=ks(r,n);if(!h&&!Is(r,n))return;const[d,m]=5===n?[t,e]:[e,t];if(S.index=b[d][0],C.index=b[m][0],C.index===S.index)return;if(Ns(S,C,l))return;if(16!==S.number&&16!==C.number&&i>u)return;if(S.connectedTo(C))return;const y=gs(S,C),_=ps.get(A[S.index])||It(120);if(y.some((t=>Math.abs(_-t)>o)))return;if(3===A[S.index]){const t=ys(S,C);if(void 0!==t&&t>c)return}const x=gs(C,S),v=ps.get(A[C.index])||It(120);if(x.some((t=>v-t>s)))return;if(3===A[C.index]){const t=ys(C,S);if(void 0!==t&&t>a)return}p.setBits(d,m);const w=h?8:function(t,e){return t.isWater()&&e.isWater()}(P=S,I=C)?9:function(t,e){return t.isBackbone()&&e.isBackbone()}(P,I)?10:4;var P,I;f.addContact(d,m,w)}))}(t,r,i),function(t,e,i={}){const r=rt(i.maxMetalDist,Rs.maxMetalDist),n=rt(i.masterModelIndex,Rs.masterModelIndex),{features:s,spatialHash:o,contactStore:a,featureSet:c}=e,{types:l,centers:h,atomSets:u}=s,{x:d,y:m,z:f}=h,p=l.length,g=t.getAtomProxy(),y=t.getAtomProxy();for(let t=0;t{if(e<=t)return;if(g.index=u[t][0],y.index=u[e][0],Ns(g,y,n))return;const r=g.isMetal(),s=y.isMetal();if(!r&&!s)return;const[o,h]=r?[l[t],l[e]]:[l[e],l[t]];Ts(o,h)&&(c.setBits(t,e),a.addContact(t,e,7))}))}(t,r,i),function(t,e,i={}){const r=rt(i.maxHydrophobicDist,Rs.maxHydrophobicDist),n=rt(i.masterModelIndex,Rs.masterModelIndex),{features:s,spatialHash:o,contactStore:a,featureSet:c}=e,{types:l,centers:h,atomSets:u}=s,{x:d,y:m,z:f}=h,p=l.length,g=t.getAtomProxy(),y=t.getAtomProxy();for(let t=0;t{var r,s;e<=t||(g.index=u[t][0],y.index=u[e][0],Ns(g,y,n)||9===g.number&&9===y.number||g.connectedTo(y)||(r=l[t],s=l[e],8===r&&8===s&&(c.setBits(t,e),a.addContact(t,e,6))))}))}(t,r,i),function(t,e,i={}){const r=rt(i.maxHalogenBondDist,Rs.maxHalogenBondDist),n=It(rt(i.maxHalogenBondAngle,Rs.maxHalogenBondAngle)),s=rt(i.masterModelIndex,Rs.masterModelIndex),{features:o,spatialHash:a,contactStore:c,featureSet:l}=e,{types:h,centers:u,atomSets:d}=o,{x:m,y:f,z:p}=u,g=h.length,y=t.getAtomProxy(),b=t.getAtomProxy();for(let t=0;t{if(e<=t)return;if(y.index=d[t][0],b.index=d[e][0],Ns(y,b,s))return;if(r=h[t],o=h[e],!(7===r&&6===o||6===r&&7===o))return;var r,o;const[a,u]=6===h[t]?[y,b]:[b,y],m=gs(a,u);if(1!==m.length)return;if(Es-m[0]>n)return;const f=gs(u,a);0!==f.length&&(f.some((t=>$s-t>n))||(l.setBits(t,e),c.addContact(t,e,5)))}))}(t,r,i);const n=function(t){const{index1:e,index2:i,count:r}=t.contactStore,n=$n({nodeArray1:e,nodeArray2:i,edgeCount:r,nodeCount:t.featureSet.length}),s=new En(t.contactStore.count,!0);return Object.assign({adjacencyList:n,contactSet:s},t)}(r);return function(t,i,r={}){De&&ke.time("refineLineOfSight");const n=rt(r.lineOfSightDistFactor,Rs.lineOfSightDistFactor),s=rt(r.masterModelIndex,Rs.masterModelIndex),o=t.spatialHash,{contactSet:a,contactStore:c,features:l}=i,{index1:h,index2:u}=c,{centers:d,atomSets:m}=l,{x:f,y:p,z:g}=d,y=t.getAtomProxy(),b=t.getAtomProxy(),_=t.getAtomProxy(),x=new e,v=new e,w=3*n,A=n*n;a.forEach((t=>{x.set(f[h[t]],p[h[t]],g[h[t]]),v.set(f[u[t]],p[u[t]],g[u[t]]);const e=(x.x+v.x)/2,i=(x.y+v.y)/2,r=(x.z+v.z)/2,n=m[h[t]],c=m[u[t]];y.index=n[0],b.index=c[0],o.eachWithin(e,i,r,w,((e,i)=>{_.index=e,1!==_.number&&_.vdw*_.vdw*A>i&&!Os(y,_,s)&&!Os(b,_,s)&&!n.includes(e)&&!c.includes(e)&&x.distanceToSquared(_)>1&&v.distanceToSquared(_)>1&&(a.clear(t),De&&ke.log("removing",y.qualifiedName(),b.qualifiedName(),"because",_.qualifiedName()))}))})),De&&ke.timeEnd("refineLineOfSight")}(t,n,i),function(t,e){const{contactSet:i,contactStore:r,features:n}=e,{type:s,index1:o,index2:a}=r,{atomSets:c}=n,l=t.getAtomProxy(),h=t.getAtomProxy(),u={},d=function(t,e,r){const[n,s]=u[r]||[1/0,-1];t{if(6!==s[t])return;l.index=c[o[t]][0],h.index=c[a[t]][0];const e=l.distanceTo(h);d(e,t,`${l.index}|${h.residueIndex}`),d(e,t,`${h.index}|${l.residueIndex}`)}))}(t,n),i.refineSaltBridges&&function(t,e){const{contactSet:i,contactStore:r,features:n}=e,{type:s,index1:o,index2:a}=r,{atomSets:c}=n,l={},h=function(t,e){l[t]||(l[t]=[]),l[t].push(e)};i.forEach((t=>{1===s[t]&&(c[o[t]].forEach((e=>h(e,t))),c[a[t]].forEach((e=>h(e,t))))})),i.forEach((t=>{if(!function(t){return 4===t||9===t||10===t}(s[t]))return;const e=l[c[o[t]][0]],r=l[c[a[t]][0]];if(!e||!r)return;const n=e.length;for(let s=0;s{3===s[t]&&(c[o[t]].forEach((e=>h(e,t))),c[a[t]].forEach((e=>h(e,t))))})),i.forEach((t=>{if(6!==s[t]&&2!==s[t])return;const e=l[c[o[t]][0]],r=l[c[a[t]][0]];if(!e||!r)return;const n=e.length;for(let s=0;s{1===s[t]&&(c[o[t]].forEach((e=>h(e,t))),c[a[t]].forEach((e=>h(e,t))))})),i.forEach((t=>{if(7!==s[t])return;const e=l[c[o[t]][0]],r=l[c[a[t]][0]];if(!e||!r)return;const n=e.length;for(let t=0;te.getAtomSet(new me(t)))):e.getAtomSet(new me(r.filterSele))),o.forEach((t=>{const e=p[t];if(!n.includes(e))return;if(v){const e=l[m[t]][0],i=l[f[t]][0];if(Array.isArray(v)){if(!(v[0].isSet(e)&&v[1].isSet(i)||v[1].isSet(e)&&v[0].isSet(i)))return}else if(!v.isSet(e)&&!v.isSet(i))return}const i=m[t],s=f[t];g.push(h[i],u[i],d[i]),y.push(h[s],u[s],d[s]),b.push(...function(t){switch(t){case 4:case 9:case 10:return Gs.setHex(2851770).toArray();case 6:return Gs.setHex(8421504).toArray();case 5:return Gs.setHex(4259775).toArray();case 1:return Gs.setHex(15779860).toArray();case 7:return Gs.setHex(9191577).toArray();case 2:return Gs.setHex(16744448).toArray();case 3:return Gs.setHex(9220966).toArray();case 8:return Gs.setHex(12967404).toArray();default:return Gs.setHex(13421772).toArray()}}(e)),_.push(r.radius),x.push(t)})),{position1:new Float32Array(g),position2:new Float32Array(y),color:new Float32Array(b),color2:new Float32Array(b),radius:new Float32Array(_),picking:new Zs(x,t,e)}}class qs{constructor(t){this.array=t}get type(){return""}get data(){return{}}getIndex(t){return this.array?this.array[t]:t}getObject(t){return{}}_applyTransformations(t,e,i){return e&&t.applyMatrix4(e.matrix),i&&t.applyMatrix4(i.matrix),t}_getPosition(t){return new e}getPosition(t,e,i){return this._applyTransformations(this._getPosition(t),e,i)}}class Ws extends qs{constructor(t){super(),this.shape=t}get primitive(){}get data(){return this.shape}get type(){return this.primitive.type}getObject(t){return this.primitive.objectFromShape(this.shape,this.getIndex(t))}_getPosition(t){return this.primitive.positionFromShape(this.shape,this.getIndex(t))}}class Xs extends qs{constructor(t,e){super(t),this.structure=e}get type(){return"atom"}get data(){return this.structure}getObject(t){return this.structure.getAtomProxy(this.getIndex(t))}_getPosition(t){return(new e).copy(this.getObject(t))}}class Ys extends qs{constructor(t){super(),this.axes=t}get type(){return"axes"}get data(){return this.axes}getObject(){return{axes:this.axes}}_getPosition(){return this.axes.center.clone()}}class Ks extends qs{constructor(t,e,i){super(t),this.structure=e,this.bondStore=i||e.bondStore}get type(){return"bond"}get data(){return this.structure}getObject(t){const e=this.structure.getBondProxy(this.getIndex(t));return e.bondStore=this.bondStore,e}_getPosition(t){const i=this.getObject(t);return(new e).copy(i.atom1).add(i.atom2).multiplyScalar(.5)}}class Zs extends qs{constructor(t,e,i){super(t),this.contacts=e,this.structure=i}get type(){return"contact"}get data(){return this.contacts}getObject(t){const i=this.getIndex(t),{features:r,contactStore:n}=this.contacts,{centers:s,atomSets:o}=r,{x:a,y:c,z:l}=s,{index1:h,index2:u,type:d}=n,m=h[i],f=u[i];return{center1:new e(a[m],c[m],l[m]),center2:new e(a[f],c[f],l[f]),atom1:this.structure.getAtomProxy(o[m][0]),atom2:this.structure.getAtomProxy(o[f][0]),type:Vs(d[i])}}_getPosition(t){const{center1:i,center2:r}=this.getObject(t);return(new e).addVectors(i,r).multiplyScalar(.5)}}class Qs extends qs{constructor(t,e,i){super(t),this.validation=e,this.structure=i}get type(){return"clash"}get data(){return this.validation}getObject(t){const e=this.validation,i=this.getIndex(t);return{validation:e,index:i,clash:e.clashArray[i]}}_getAtomProxyFromSele(t){const e=new me(t),i=this.structure.getAtomIndices(e)[0];return this.structure.getAtomProxy(i)}_getPosition(t){const i=this.getObject(t).clash,r=this._getAtomProxyFromSele(i.sele1),n=this._getAtomProxyFromSele(i.sele2);return(new e).copy(r).add(n).multiplyScalar(.5)}}class Js extends Ks{get type(){return"distance"}}class to extends qs{get type(){return"ignore"}}class eo extends Ws{constructor(t,e){super(t),this.mesh=e}get type(){return"mesh"}getObject(){const t=this.mesh;return{shape:this.shape,name:t.name,serial:t.serial}}_getPosition(){return this.__position||(this.__position=Vr(this.mesh.position)),this.__position}}class io extends qs{constructor(t,e){super(t),this.surface=e}get type(){return"surface"}get data(){return this.surface}getObject(t){return{surface:this.surface,index:this.getIndex(t)}}_getPosition(){return this.surface.center.clone()}}class ro extends qs{constructor(t,e){super(),this.unitcell=t,this.structure=e}get type(){return"unitcell"}get data(){return this.unitcell}getObject(){return{unitcell:this.unitcell,structure:this.structure}}_getPosition(){return this.unitcell.getCenter(this.structure)}}class no extends qs{constructor(t,e){super(t),this.volume=e}get type(){return"volume"}get data(){return this.volume}getObject(t){const e=this.volume,i=this.getIndex(t);return{volume:e,index:i,value:e.data[i]}}_getPosition(t){const i=this.volume.position,r=this.getIndex(t);return new e(i[3*r],i[3*r+1],i[3*r+2])}}class so extends no{get type(){return"slice"}}function oo(){return new Uint32Array([0,265,515,778,1030,1295,1541,1804,2060,2309,2575,2822,3082,3331,3593,3840,400,153,915,666,1430,1183,1941,1692,2460,2197,2975,2710,3482,3219,3993,3728,560,825,51,314,1590,1855,1077,1340,2620,2869,2111,2358,3642,3891,3129,3376,928,681,419,170,1958,1711,1445,1196,2988,2725,2479,2214,4010,3747,3497,3232,1120,1385,1635,1898,102,367,613,876,3180,3429,3695,3942,2154,2403,2665,2912,1520,1273,2035,1786,502,255,1013,764,3580,3317,4095,3830,2554,2291,3065,2800,1616,1881,1107,1370,598,863,85,348,3676,3925,3167,3414,2650,2899,2137,2384,1984,1737,1475,1226,966,719,453,204,4044,3781,3535,3270,3018,2755,2505,2240,2240,2505,2755,3018,3270,3535,3781,4044,204,453,719,966,1226,1475,1737,1984,2384,2137,2899,2650,3414,3167,3925,3676,348,85,863,598,1370,1107,1881,1616,2800,3065,2291,2554,3830,4095,3317,3580,764,1013,255,502,1786,2035,1273,1520,2912,2665,2403,2154,3942,3695,3429,3180,876,613,367,102,1898,1635,1385,1120,3232,3497,3747,4010,2214,2479,2725,2988,1196,1445,1711,1958,170,419,681,928,3376,3129,3891,3642,2358,2111,2869,2620,1340,1077,1855,1590,314,51,825,560,3728,3993,3219,3482,2710,2975,2197,2460,1692,1941,1183,1430,666,915,153,400,3840,3593,3331,3082,2822,2575,2309,2060,1804,1541,1295,1030,778,515,265,0])}function ao(){return new Int32Array([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,8,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,8,3,9,8,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,2,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,8,3,1,2,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,9,2,10,0,2,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,2,8,3,2,10,8,10,9,8,-1,-1,-1,-1,-1,-1,-1,3,11,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,11,2,8,11,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,9,0,2,3,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,11,2,1,9,11,9,8,11,-1,-1,-1,-1,-1,-1,-1,3,10,1,11,10,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,10,1,0,8,10,8,11,10,-1,-1,-1,-1,-1,-1,-1,3,9,0,3,11,9,11,10,9,-1,-1,-1,-1,-1,-1,-1,9,8,10,10,8,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,7,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,3,0,7,3,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,9,8,4,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,1,9,4,7,1,7,3,1,-1,-1,-1,-1,-1,-1,-1,1,2,10,8,4,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,3,4,7,3,0,4,1,2,10,-1,-1,-1,-1,-1,-1,-1,9,2,10,9,0,2,8,4,7,-1,-1,-1,-1,-1,-1,-1,2,10,9,2,9,7,2,7,3,7,9,4,-1,-1,-1,-1,8,4,7,3,11,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,4,7,11,2,4,2,0,4,-1,-1,-1,-1,-1,-1,-1,9,0,1,8,4,7,2,3,11,-1,-1,-1,-1,-1,-1,-1,4,7,11,9,4,11,9,11,2,9,2,1,-1,-1,-1,-1,3,10,1,3,11,10,7,8,4,-1,-1,-1,-1,-1,-1,-1,1,11,10,1,4,11,1,0,4,7,11,4,-1,-1,-1,-1,4,7,8,9,0,11,9,11,10,11,0,3,-1,-1,-1,-1,4,7,11,4,11,9,9,11,10,-1,-1,-1,-1,-1,-1,-1,9,5,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,9,5,4,0,8,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,5,4,1,5,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,8,5,4,8,3,5,3,1,5,-1,-1,-1,-1,-1,-1,-1,1,2,10,9,5,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,3,0,8,1,2,10,4,9,5,-1,-1,-1,-1,-1,-1,-1,5,2,10,5,4,2,4,0,2,-1,-1,-1,-1,-1,-1,-1,2,10,5,3,2,5,3,5,4,3,4,8,-1,-1,-1,-1,9,5,4,2,3,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,11,2,0,8,11,4,9,5,-1,-1,-1,-1,-1,-1,-1,0,5,4,0,1,5,2,3,11,-1,-1,-1,-1,-1,-1,-1,2,1,5,2,5,8,2,8,11,4,8,5,-1,-1,-1,-1,10,3,11,10,1,3,9,5,4,-1,-1,-1,-1,-1,-1,-1,4,9,5,0,8,1,8,10,1,8,11,10,-1,-1,-1,-1,5,4,0,5,0,11,5,11,10,11,0,3,-1,-1,-1,-1,5,4,8,5,8,10,10,8,11,-1,-1,-1,-1,-1,-1,-1,9,7,8,5,7,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,9,3,0,9,5,3,5,7,3,-1,-1,-1,-1,-1,-1,-1,0,7,8,0,1,7,1,5,7,-1,-1,-1,-1,-1,-1,-1,1,5,3,3,5,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,9,7,8,9,5,7,10,1,2,-1,-1,-1,-1,-1,-1,-1,10,1,2,9,5,0,5,3,0,5,7,3,-1,-1,-1,-1,8,0,2,8,2,5,8,5,7,10,5,2,-1,-1,-1,-1,2,10,5,2,5,3,3,5,7,-1,-1,-1,-1,-1,-1,-1,7,9,5,7,8,9,3,11,2,-1,-1,-1,-1,-1,-1,-1,9,5,7,9,7,2,9,2,0,2,7,11,-1,-1,-1,-1,2,3,11,0,1,8,1,7,8,1,5,7,-1,-1,-1,-1,11,2,1,11,1,7,7,1,5,-1,-1,-1,-1,-1,-1,-1,9,5,8,8,5,7,10,1,3,10,3,11,-1,-1,-1,-1,5,7,0,5,0,9,7,11,0,1,0,10,11,10,0,-1,11,10,0,11,0,3,10,5,0,8,0,7,5,7,0,-1,11,10,5,7,11,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,10,6,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,8,3,5,10,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,9,0,1,5,10,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,8,3,1,9,8,5,10,6,-1,-1,-1,-1,-1,-1,-1,1,6,5,2,6,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,6,5,1,2,6,3,0,8,-1,-1,-1,-1,-1,-1,-1,9,6,5,9,0,6,0,2,6,-1,-1,-1,-1,-1,-1,-1,5,9,8,5,8,2,5,2,6,3,2,8,-1,-1,-1,-1,2,3,11,10,6,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,0,8,11,2,0,10,6,5,-1,-1,-1,-1,-1,-1,-1,0,1,9,2,3,11,5,10,6,-1,-1,-1,-1,-1,-1,-1,5,10,6,1,9,2,9,11,2,9,8,11,-1,-1,-1,-1,6,3,11,6,5,3,5,1,3,-1,-1,-1,-1,-1,-1,-1,0,8,11,0,11,5,0,5,1,5,11,6,-1,-1,-1,-1,3,11,6,0,3,6,0,6,5,0,5,9,-1,-1,-1,-1,6,5,9,6,9,11,11,9,8,-1,-1,-1,-1,-1,-1,-1,5,10,6,4,7,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,3,0,4,7,3,6,5,10,-1,-1,-1,-1,-1,-1,-1,1,9,0,5,10,6,8,4,7,-1,-1,-1,-1,-1,-1,-1,10,6,5,1,9,7,1,7,3,7,9,4,-1,-1,-1,-1,6,1,2,6,5,1,4,7,8,-1,-1,-1,-1,-1,-1,-1,1,2,5,5,2,6,3,0,4,3,4,7,-1,-1,-1,-1,8,4,7,9,0,5,0,6,5,0,2,6,-1,-1,-1,-1,7,3,9,7,9,4,3,2,9,5,9,6,2,6,9,-1,3,11,2,7,8,4,10,6,5,-1,-1,-1,-1,-1,-1,-1,5,10,6,4,7,2,4,2,0,2,7,11,-1,-1,-1,-1,0,1,9,4,7,8,2,3,11,5,10,6,-1,-1,-1,-1,9,2,1,9,11,2,9,4,11,7,11,4,5,10,6,-1,8,4,7,3,11,5,3,5,1,5,11,6,-1,-1,-1,-1,5,1,11,5,11,6,1,0,11,7,11,4,0,4,11,-1,0,5,9,0,6,5,0,3,6,11,6,3,8,4,7,-1,6,5,9,6,9,11,4,7,9,7,11,9,-1,-1,-1,-1,10,4,9,6,4,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,10,6,4,9,10,0,8,3,-1,-1,-1,-1,-1,-1,-1,10,0,1,10,6,0,6,4,0,-1,-1,-1,-1,-1,-1,-1,8,3,1,8,1,6,8,6,4,6,1,10,-1,-1,-1,-1,1,4,9,1,2,4,2,6,4,-1,-1,-1,-1,-1,-1,-1,3,0,8,1,2,9,2,4,9,2,6,4,-1,-1,-1,-1,0,2,4,4,2,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,8,3,2,8,2,4,4,2,6,-1,-1,-1,-1,-1,-1,-1,10,4,9,10,6,4,11,2,3,-1,-1,-1,-1,-1,-1,-1,0,8,2,2,8,11,4,9,10,4,10,6,-1,-1,-1,-1,3,11,2,0,1,6,0,6,4,6,1,10,-1,-1,-1,-1,6,4,1,6,1,10,4,8,1,2,1,11,8,11,1,-1,9,6,4,9,3,6,9,1,3,11,6,3,-1,-1,-1,-1,8,11,1,8,1,0,11,6,1,9,1,4,6,4,1,-1,3,11,6,3,6,0,0,6,4,-1,-1,-1,-1,-1,-1,-1,6,4,8,11,6,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,10,6,7,8,10,8,9,10,-1,-1,-1,-1,-1,-1,-1,0,7,3,0,10,7,0,9,10,6,7,10,-1,-1,-1,-1,10,6,7,1,10,7,1,7,8,1,8,0,-1,-1,-1,-1,10,6,7,10,7,1,1,7,3,-1,-1,-1,-1,-1,-1,-1,1,2,6,1,6,8,1,8,9,8,6,7,-1,-1,-1,-1,2,6,9,2,9,1,6,7,9,0,9,3,7,3,9,-1,7,8,0,7,0,6,6,0,2,-1,-1,-1,-1,-1,-1,-1,7,3,2,6,7,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,2,3,11,10,6,8,10,8,9,8,6,7,-1,-1,-1,-1,2,0,7,2,7,11,0,9,7,6,7,10,9,10,7,-1,1,8,0,1,7,8,1,10,7,6,7,10,2,3,11,-1,11,2,1,11,1,7,10,6,1,6,7,1,-1,-1,-1,-1,8,9,6,8,6,7,9,1,6,11,6,3,1,3,6,-1,0,9,1,11,6,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,8,0,7,0,6,3,11,0,11,6,0,-1,-1,-1,-1,7,11,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,6,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,3,0,8,11,7,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,9,11,7,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,8,1,9,8,3,1,11,7,6,-1,-1,-1,-1,-1,-1,-1,10,1,2,6,11,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,2,10,3,0,8,6,11,7,-1,-1,-1,-1,-1,-1,-1,2,9,0,2,10,9,6,11,7,-1,-1,-1,-1,-1,-1,-1,6,11,7,2,10,3,10,8,3,10,9,8,-1,-1,-1,-1,7,2,3,6,2,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,7,0,8,7,6,0,6,2,0,-1,-1,-1,-1,-1,-1,-1,2,7,6,2,3,7,0,1,9,-1,-1,-1,-1,-1,-1,-1,1,6,2,1,8,6,1,9,8,8,7,6,-1,-1,-1,-1,10,7,6,10,1,7,1,3,7,-1,-1,-1,-1,-1,-1,-1,10,7,6,1,7,10,1,8,7,1,0,8,-1,-1,-1,-1,0,3,7,0,7,10,0,10,9,6,10,7,-1,-1,-1,-1,7,6,10,7,10,8,8,10,9,-1,-1,-1,-1,-1,-1,-1,6,8,4,11,8,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,3,6,11,3,0,6,0,4,6,-1,-1,-1,-1,-1,-1,-1,8,6,11,8,4,6,9,0,1,-1,-1,-1,-1,-1,-1,-1,9,4,6,9,6,3,9,3,1,11,3,6,-1,-1,-1,-1,6,8,4,6,11,8,2,10,1,-1,-1,-1,-1,-1,-1,-1,1,2,10,3,0,11,0,6,11,0,4,6,-1,-1,-1,-1,4,11,8,4,6,11,0,2,9,2,10,9,-1,-1,-1,-1,10,9,3,10,3,2,9,4,3,11,3,6,4,6,3,-1,8,2,3,8,4,2,4,6,2,-1,-1,-1,-1,-1,-1,-1,0,4,2,4,6,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,9,0,2,3,4,2,4,6,4,3,8,-1,-1,-1,-1,1,9,4,1,4,2,2,4,6,-1,-1,-1,-1,-1,-1,-1,8,1,3,8,6,1,8,4,6,6,10,1,-1,-1,-1,-1,10,1,0,10,0,6,6,0,4,-1,-1,-1,-1,-1,-1,-1,4,6,3,4,3,8,6,10,3,0,3,9,10,9,3,-1,10,9,4,6,10,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,9,5,7,6,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,8,3,4,9,5,11,7,6,-1,-1,-1,-1,-1,-1,-1,5,0,1,5,4,0,7,6,11,-1,-1,-1,-1,-1,-1,-1,11,7,6,8,3,4,3,5,4,3,1,5,-1,-1,-1,-1,9,5,4,10,1,2,7,6,11,-1,-1,-1,-1,-1,-1,-1,6,11,7,1,2,10,0,8,3,4,9,5,-1,-1,-1,-1,7,6,11,5,4,10,4,2,10,4,0,2,-1,-1,-1,-1,3,4,8,3,5,4,3,2,5,10,5,2,11,7,6,-1,7,2,3,7,6,2,5,4,9,-1,-1,-1,-1,-1,-1,-1,9,5,4,0,8,6,0,6,2,6,8,7,-1,-1,-1,-1,3,6,2,3,7,6,1,5,0,5,4,0,-1,-1,-1,-1,6,2,8,6,8,7,2,1,8,4,8,5,1,5,8,-1,9,5,4,10,1,6,1,7,6,1,3,7,-1,-1,-1,-1,1,6,10,1,7,6,1,0,7,8,7,0,9,5,4,-1,4,0,10,4,10,5,0,3,10,6,10,7,3,7,10,-1,7,6,10,7,10,8,5,4,10,4,8,10,-1,-1,-1,-1,6,9,5,6,11,9,11,8,9,-1,-1,-1,-1,-1,-1,-1,3,6,11,0,6,3,0,5,6,0,9,5,-1,-1,-1,-1,0,11,8,0,5,11,0,1,5,5,6,11,-1,-1,-1,-1,6,11,3,6,3,5,5,3,1,-1,-1,-1,-1,-1,-1,-1,1,2,10,9,5,11,9,11,8,11,5,6,-1,-1,-1,-1,0,11,3,0,6,11,0,9,6,5,6,9,1,2,10,-1,11,8,5,11,5,6,8,0,5,10,5,2,0,2,5,-1,6,11,3,6,3,5,2,10,3,10,5,3,-1,-1,-1,-1,5,8,9,5,2,8,5,6,2,3,8,2,-1,-1,-1,-1,9,5,6,9,6,0,0,6,2,-1,-1,-1,-1,-1,-1,-1,1,5,8,1,8,0,5,6,8,3,8,2,6,2,8,-1,1,5,6,2,1,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,3,6,1,6,10,3,8,6,5,6,9,8,9,6,-1,10,1,0,10,0,6,9,5,0,5,6,0,-1,-1,-1,-1,0,3,8,5,6,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,10,5,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,5,10,7,5,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,5,10,11,7,5,8,3,0,-1,-1,-1,-1,-1,-1,-1,5,11,7,5,10,11,1,9,0,-1,-1,-1,-1,-1,-1,-1,10,7,5,10,11,7,9,8,1,8,3,1,-1,-1,-1,-1,11,1,2,11,7,1,7,5,1,-1,-1,-1,-1,-1,-1,-1,0,8,3,1,2,7,1,7,5,7,2,11,-1,-1,-1,-1,9,7,5,9,2,7,9,0,2,2,11,7,-1,-1,-1,-1,7,5,2,7,2,11,5,9,2,3,2,8,9,8,2,-1,2,5,10,2,3,5,3,7,5,-1,-1,-1,-1,-1,-1,-1,8,2,0,8,5,2,8,7,5,10,2,5,-1,-1,-1,-1,9,0,1,5,10,3,5,3,7,3,10,2,-1,-1,-1,-1,9,8,2,9,2,1,8,7,2,10,2,5,7,5,2,-1,1,3,5,3,7,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,8,7,0,7,1,1,7,5,-1,-1,-1,-1,-1,-1,-1,9,0,3,9,3,5,5,3,7,-1,-1,-1,-1,-1,-1,-1,9,8,7,5,9,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,5,8,4,5,10,8,10,11,8,-1,-1,-1,-1,-1,-1,-1,5,0,4,5,11,0,5,10,11,11,3,0,-1,-1,-1,-1,0,1,9,8,4,10,8,10,11,10,4,5,-1,-1,-1,-1,10,11,4,10,4,5,11,3,4,9,4,1,3,1,4,-1,2,5,1,2,8,5,2,11,8,4,5,8,-1,-1,-1,-1,0,4,11,0,11,3,4,5,11,2,11,1,5,1,11,-1,0,2,5,0,5,9,2,11,5,4,5,8,11,8,5,-1,9,4,5,2,11,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,2,5,10,3,5,2,3,4,5,3,8,4,-1,-1,-1,-1,5,10,2,5,2,4,4,2,0,-1,-1,-1,-1,-1,-1,-1,3,10,2,3,5,10,3,8,5,4,5,8,0,1,9,-1,5,10,2,5,2,4,1,9,2,9,4,2,-1,-1,-1,-1,8,4,5,8,5,3,3,5,1,-1,-1,-1,-1,-1,-1,-1,0,4,5,1,0,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,8,4,5,8,5,3,9,0,5,0,3,5,-1,-1,-1,-1,9,4,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,11,7,4,9,11,9,10,11,-1,-1,-1,-1,-1,-1,-1,0,8,3,4,9,7,9,11,7,9,10,11,-1,-1,-1,-1,1,10,11,1,11,4,1,4,0,7,4,11,-1,-1,-1,-1,3,1,4,3,4,8,1,10,4,7,4,11,10,11,4,-1,4,11,7,9,11,4,9,2,11,9,1,2,-1,-1,-1,-1,9,7,4,9,11,7,9,1,11,2,11,1,0,8,3,-1,11,7,4,11,4,2,2,4,0,-1,-1,-1,-1,-1,-1,-1,11,7,4,11,4,2,8,3,4,3,2,4,-1,-1,-1,-1,2,9,10,2,7,9,2,3,7,7,4,9,-1,-1,-1,-1,9,10,7,9,7,4,10,2,7,8,7,0,2,0,7,-1,3,7,10,3,10,2,7,4,10,1,10,0,4,0,10,-1,1,10,2,8,7,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,9,1,4,1,7,7,1,3,-1,-1,-1,-1,-1,-1,-1,4,9,1,4,1,7,0,8,1,8,7,1,-1,-1,-1,-1,4,0,3,7,4,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,8,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,9,10,8,10,11,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,3,0,9,3,9,11,11,9,10,-1,-1,-1,-1,-1,-1,-1,0,1,10,0,10,8,8,10,11,-1,-1,-1,-1,-1,-1,-1,3,1,10,11,3,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,2,11,1,11,9,9,11,8,-1,-1,-1,-1,-1,-1,-1,3,0,9,3,9,11,1,2,9,2,11,9,-1,-1,-1,-1,0,2,11,8,0,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,3,2,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,2,3,8,2,8,10,10,8,9,-1,-1,-1,-1,-1,-1,-1,9,10,2,0,9,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,2,3,8,2,8,10,0,1,8,1,10,8,-1,-1,-1,-1,1,10,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,3,8,9,1,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,9,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,3,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1])}function co(t,e,i,r,n){var s,o,a,c,l,h,u,d=[[0,4,4,4,2,0,0,0,2,2,0,0],[4,0,4,4,0,8,0,0,0,8,8,0],[4,4,0,4,0,0,8,0,0,0,8,8],[4,4,4,0,0,0,0,1,1,0,0,1],[2,0,0,0,0,8,8,8,2,2,0,0],[0,8,0,0,8,0,8,8,0,8,8,0],[0,0,8,0,8,8,0,8,0,0,8,8],[0,0,0,1,8,8,8,0,1,0,0,1],[2,0,0,1,2,0,0,1,0,2,0,1],[2,8,0,0,2,8,0,0,2,0,8,0],[0,8,8,0,0,8,8,0,0,8,0,8],[0,0,8,1,0,0,8,1,1,0,8,0]],m=0,f=!1,p=!1,g=!1,y=!1,b=-1,_=e*i*r,x=e,v=e*i,w=new Int32Array(12),A=[],S=[],C=[],P=[],I=oo(),k=ao();function M(t,e,i){return t+(e-t)*i}function T(t,n,s){return v*(s=(s+u)%r)+x*(n=(n+h)%i)+(t=(t+l)%e)}function D(t,e,i,r,c,l,h){var u=3*t;if(o[u]<0){var d=(m-l)/(h-l),p=s,g=3*a;if(A[g]=i+d,A[g+1]=r,A[g+2]=c,!f){var y=3*t;S[g]=b*M(p[y],p[y+3],d),S[g+1]=b*M(p[y+1],p[y+4],d),S[g+2]=b*M(p[y+2],p[y+5],d)}n&&(P[a]=n[t+Math.round(d)]),o[u]=a,w[e]=a,a+=1}else w[e]=o[u]}function B(t,e,i,r,c,l,h){var u=3*t+1;if(o[u]<0){var d=(m-l)/(h-l),p=s,g=3*a;if(A[g]=i,A[g+1]=r+d,A[g+2]=c,!f){var y=3*t,_=y+3*x;S[g]=b*M(p[y],p[_],d),S[g+1]=b*M(p[y+1],p[_+1],d),S[g+2]=b*M(p[y+2],p[_+2],d)}n&&(P[a]=n[t+Math.round(d)*x]),o[u]=a,w[e]=a,a+=1}else w[e]=o[u]}function F(t,e,i,r,c,l,h){var u=3*t+2;if(o[u]<0){var d=(m-l)/(h-l),p=s,g=3*a;if(A[g]=i,A[g+1]=r,A[g+2]=c+d,!f){var y=3*t,_=y+3*v;S[g]=b*M(p[y],p[_],d),S[g+1]=b*M(p[y+1],p[_+1],d),S[g+2]=b*M(p[y+2],p[_+2],d)}n&&(P[a]=n[t+Math.round(d)*v]),o[u]=a,w[e]=a,a+=1}else w[e]=o[u]}function E(e){var i=3*e;0===s[i]&&(s[i]=t[(e-1+_)%_]-t[(e+1)%_],s[i+1]=t[(e-x+_)%_]-t[(e+x)%_],s[i+2]=t[(e-v+_)%_]-t[(e+v)%_])}function $(e,i,r,n,s){var o,a,l,h,u,b,_;g?(n=T(e,i,r),o=T(e+1,i,r),a=T(e,i+1,r),l=T(e,i,r+1),h=T(e+1,i+1,r),u=T(e+1,i,r+1),b=T(e,i+1,r+1),_=T(e+1,i+1,r+1)):(o=n+1,h=(a=n+x)+1,u=(l=n+v)+1,_=(b=a+v)+1);var A=0,S=t[n],P=t[o],M=t[a],$=t[h],O=t[l],R=t[u],L=t[b],N=t[_];S=m){F=b,M=!0;break}if(M)break}if(M)break}for(M=!1,y=s;y=m){B=y,M=!0;break}if(M)break}if(M)break}for(M=!1,p=n;p=m){D=p,M=!0;break}if(M)break}if(M)break}for(M=!1,b=h;b>=a;--b){for(y=l;y>=s;--y){for(p=c;p>=n;--p)if(u=e*i*b+e*y+p,t[u]>=m){R=b,M=!0;break}if(M)break}if(M)break}for(M=!1,y=l;y>=s;--y){for(b=R;b>=a;--b){for(p=c;p>=n;--p)if(u=e*i*b+e*y+p,t[u]>=m){O=y,M=!0;break}if(M)break}if(M)break}for(M=!1,p=c;p>=n;--p){for(y=O;y>=s;--y){for(b=R;b>=a;--b)if(u=e*i*b+e*y+p,t[u]>=m){E=p,M=!0;break}if(M)break}if(M)break}f?(n=Math.max(0,D-1),s=Math.max(0,B-1),a=Math.max(0,F-1),c=Math.min(e-1,E+1),l=Math.min(i-1,O+1),h=Math.min(r-1,R+1)):(n=Math.max(1,D-1),s=Math.max(1,B-1),a=Math.max(1,F-1),c=Math.min(e-2,E+1),l=Math.min(i-2,O+1),h=Math.min(r-2,R+1))}var L=15;for(b=a;b0?-1:1,s||(s=new Float32Array(3*_)));var I=3*_;if(o&&o.length===I||(o=new Int32Array(I)),a=0,c=0,void 0!==x){var k=x[0].map(Math.round),M=x[1].map(Math.round);l=e*Math.ceil(Math.abs(k[0])/e),h=i*Math.ceil(Math.abs(k[1])/i),u=r*Math.ceil(Math.abs(k[2])/r),O(k[0],k[1],k[2],M[0],M[1],M[2])}else l=h=u=0,O();return A.length=3*a,f||(S.length=3*a),C.length=c,n&&(P.length=a),{position:new Float32Array(A),normal:f?void 0:new Float32Array(S),index:bt(C,A.length/3),atomindex:n?new Int32Array(P):void 0,contour:p}}}Ge.add("arrow",class extends Ws{get primitive(){return An}}),Ge.add("box",class extends Ws{get primitive(){return _n}}),Ge.add("cone",class extends Ws{get primitive(){return Sn}}),Ge.add("cylinder",class extends Ws{get primitive(){return wn}}),Ge.add("ellipsoid",class extends Ws{get primitive(){return Cn}}),Ge.add("octahedron",class extends Ws{get primitive(){return xn}}),Ge.add("sphere",class extends Ws{get primitive(){return bn}}),Ge.add("tetrahedron",class extends Ws{get primitive(){return vn}}),Ge.add("torus",class extends Ws{get primitive(){return Pn}}),Ge.add("point",class extends Ws{get primitive(){return kn}}),Ge.add("wideline",class extends Ws{get primitive(){return Mn}}),Object.assign(co,{__deps:[oo,ao,bt]});class lo{constructor(t,e){this.cols=t,this.rows=e,this.size=this.cols*this.rows,this.data=new Float32Array(this.size)}copyTo(t){t.data.set(this.data)}}function ho(t,e){let i=0,r=0;const n=e.rows,s=e.cols;let o=0,a=0,c=0;const l=e.data,h=t.data;for(;i(e=Math.abs(e))?(e/=t,t*Math.sqrt(1+e*e)):e>0?(t/=e,e*Math.sqrt(1+t*t)):0}const bo=1.192092896e-7,_o=1e-37;function xo(t,e,i,r){let n=0,s=0;const o=t.rows,a=t.cols;let c=o,l=a;c>16?E:-E,t[h*e+d]=F;for(m=0;m<2;m++)for(u=0;u{const e=t.data.sd,i=t.data.p;o(this._makeSurface(e,i.isolevel,i.smooth))}),(a=>{console.warn("Volume.getSurfaceWorker error - trying without worker",a);const c=this.getSurface(t,e,i,r,n,s);o(c)}))}else{const a=this.getSurface(t,e,i,r,n,s);o(a)}}getValueForSigma(t){return this.mean+rt(t,2)*this.rms}getSigmaForValue(t){return(rt(t,0)-this.mean)/this.rms}get position(){if(!this._position){const t=this.nz,e=this.ny,i=this.nx,r=new Float32Array(i*e*t*3);let n=0;for(let s=0;si){const t=e;e=i,i=t}const r=t[e];return void 0===r?(t[e]=[i],!0):!r.includes(i)&&(r.push(i),!0)}const i=this.geometry,r=i.index;if(this.parameters.wireframe)if(r){const n=r.array;let s,o=n.length;if(i.drawRange.count!==1/0&&(o=i.drawRange.count),this.wireframeIndex&&this.wireframeIndex.length>2*o)s=this.wireframeIndex;else{s=bt(2*o,i.attributes.position.count)}let a=0;t.length=0;for(let t=0;t2*t?this.wireframeIndex:bt(2*t,t);for(let i=0,r=0;ithis.wireframeGeometry.index.array.length)this.wireframeGeometry.setIndex(new M(this.wireframeIndex,1).setUsage(this.dynamic?$:O));else{const t=this.wireframeGeometry.getIndex();if(!t)return void ke.error("Index is null");t.set(this.wireframeIndex),t.needsUpdate=this.wireframeIndexCount>0,t.updateRange.count=this.wireframeIndexCount}this.wireframeGeometry.setDrawRange(0,this.wireframeIndexCount)}}getRenderOrder(){let t=0;return this.isText?t=1:this.transparent&&(t=this.isSurface?3:2),t}_getMesh(t){this.material||this.makeMaterial();const e=this.geometry,i=this[t];let r;return r=this.isLine?new T(e,i):this.isPoint?new o(e,i):new P(e,i),r.frustumCulled=!1,r.renderOrder=this.getRenderOrder(),r}getMesh(){return this._getMesh("material")}getWireframeMesh(){let t;return this.material||this.makeMaterial(),this.wireframeGeometry||this.makeWireframeGeometry(),t=new T(this.wireframeGeometry,this.wireframeMaterial),t.frustumCulled=!1,t.renderOrder=this.getRenderOrder(),t}getPickingMesh(){return this._getMesh("pickingMaterial")}getShader(t,e){return pi(t,this.getDefines(e))}getVertexShader(t){return this.getShader(this.vertexShader,t)}getFragmentShader(t){return this.getShader(this.fragmentShader,t)}getDefines(t){const e={};return this.parameters.clipNear&&(e.NEAR_CLIP=1),this.parameters.clipRadius&&(e.RADIUS_CLIP=1),"picking"===t?e.PICKING=1:(("background"===t||this.parameters.background)&&(e.NOLIGHT=1),this.parameters.flatShaded&&(e.FLAT_SHADED=1),this.parameters.opaqueBack&&(e.OPAQUE_BACK=1),this.parameters.diffuseInterior&&(e.DIFFUSE_INTERIOR=1),this.parameters.useInteriorColor&&(e.USE_INTERIOR_COLOR=1)),e}getParameters(){return this.parameters}addUniforms(t){this.uniforms=F.merge([this.uniforms,t]),this.pickingUniforms=F.merge([this.pickingUniforms,t])}addAttributes(t){for(let e in t){let i;const r=t[e],n=this.attributeSize*Ro[r.type];r.value?(n!==r.value.length&&ke.error("attribute value has wrong length",e),i=r.value):i=yt("float32",n),this.geometry.setAttribute(e,new M(i,Ro[r.type]).setUsage(this.dynamic?$:O))}}updateRenderOrder(){const t=this.getRenderOrder();function e(e){e.renderOrder=t}this.group.children.forEach(e),this.pickingGroup&&this.pickingGroup.children.forEach(e)}updateShader(){const t=this.material,e=this.wireframeMaterial,i=this.pickingMaterial;t.vertexShader=this.getVertexShader(),t.fragmentShader=this.getFragmentShader(),t.needsUpdate=!0,e.vertexShader=this.getShader("Line.vert"),e.fragmentShader=this.getShader("Line.frag"),e.needsUpdate=!0,i.vertexShader=this.getVertexShader("picking"),i.fragmentShader=this.getFragmentShader("picking"),i.needsUpdate=!0}setParameters(t){const e=t,i=this.parameterTypes,r=this.parameters,n={},s={};let o=!1,a=!1;for(const t in e){const c=e[t];void 0!==c&&(r[t]=c,void 0!==i[t]&&(i[t].property&&(!0!==i[t].property?n[i[t].property]=c:n[t]=c),i[t].uniform&&(!0!==i[t].uniform?s[i[t].uniform]=c:s[t]=c),i[t].updateShader&&(o=!0),i[t].updateVisibility&&(a=!0),this.dynamic&&"wireframe"===t&&!0===c&&this.updateWireframeIndex(),"forceTransparent"===t&&(n.transparent=this.transparent),"matrix"===t&&(this.matrix=c)))}this.setProperties(n),this.setUniforms(s),o&&this.updateShader(),a&&this.setVisibility(this.visible)}setAttributes(t){const e=this.geometry,i=e.attributes;for(const r in t){if("picking"===r)continue;const n=t[r],s=n.length;if("index"===r){const t=e.getIndex();if(!t){ke.error("Index is null");continue}e.setDrawRange(0,1/0),s>t.array.length?e.setIndex(new M(n,1).setUsage(this.dynamic?$:O)):(t.set(n),t.needsUpdate=s>0,t.updateRange.count=s,e.setDrawRange(0,s)),this.indexVersion++,this.parameters.wireframe&&this.updateWireframeIndex()}else{const t=i[r];s>t.array.length?e.setAttribute(r,new M(n,t.itemSize).setUsage(this.dynamic?$:O)):(i[r].set(n),i[r].needsUpdate=s>0,i[r].updateRange.count=s)}}}setUniforms(t){if(!t)return;const e=this.material.uniforms,i=this.wireframeMaterial.uniforms,r=this.pickingMaterial.uniforms;for(let n in t)"opacity"===n&&this.setProperties({transparent:this.transparent}),void 0!==e[n]&&(e[n].value.isVector3?e[n].value.copy(t[n]):e[n].value.set?e[n].value.set(t[n]):e[n].value=t[n]),void 0!==i[n]&&(i[n].value.isVector3?i[n].value.copy(t[n]):i[n].value.set?i[n].value.set(t[n]):i[n].value=t[n]),void 0!==r[n]&&(r[n].value.isVector3?r[n].value.copy(t[n]):r[n].value.set?r[n].value.set(t[n]):r[n].value=t[n])}setProperties(t){if(!t)return;const e=this.material,i=this.wireframeMaterial,r=this.pickingMaterial;for(const n in t){const s=n;let o=t[s];"transparent"===s?this.updateRenderOrder():"side"===s&&(o=Oo(o)),e[s]=o,i[s]=o,r[s]=o}e.needsUpdate=!0,i.needsUpdate=!0,r.needsUpdate=!0}setVisibility(t){this.visible=t,this.parameters.wireframe?(this.group.visible=!1,this.wireframeGroup.visible=t,this.pickable&&(this.pickingGroup.visible=!1)):(this.group.visible=t,this.wireframeGroup.visible=!1,this.pickable&&(this.pickingGroup.visible=t))}dispose(){this.material&&this.material.dispose(),this.wireframeMaterial&&this.wireframeMaterial.dispose(),this.pickingMaterial&&this.pickingMaterial.dispose(),this.geometry.dispose(),this.wireframeGeometry&&this.wireframeGeometry.dispose()}toJSON(){var t={};for(var e in this)"group"!==e&&"wireframeGroup"!==e&&"pickingGroup"!=e&&"picking"!==e&&(t[e]=this[e]);return t}}class Vo extends Uo{constructor(t,e={}){super(t,e),this.vertexShader="Mesh.vert",this.fragmentShader="Mesh.frag",this.addAttributes({normal:{type:"v3",value:t.normal}}),void 0===t.normal&&this.geometry.computeVertexNormals()}}class jo extends Vo{constructor(){super(...arguments),this.isSurface=!0}}function Go(t){t.visible=!0}function Ho(t){t.visible=!1}class qo{constructor(t){this.group=new d,this.wireframeGroup=new d,this.pickingGroup=new d,this.frontMeshes=[],this.backMeshes=[],this.size=t.size,this.side=t.parameters.side,this.visible=t.visible,this.geometry=t.geometry,this.picking=t.picking,this.group=new d,this.wireframeGroup=new d,this.pickingGroup=new d,this.matrix=t.matrix;const e=t,i=new t.constructor({position:new Float32Array(0)});e.makeMaterial(),i.makeMaterial(),i.picking=t.picking,i.geometry=t.geometry,i.wireframeGeometry=t.wireframeGeometry,i.setParameters(t.getParameters()),i.updateShader(),e.setParameters({side:"front"}),i.setParameters({side:"back",opacity:i.parameters.opacity}),this.buffer=t,this.frontBuffer=e,this.backBuffer=i}set matrix(t){Uo.prototype.setMatrix.call(this,t)}get matrix(){return this.group.matrix.clone()}get pickable(){return!!this.picking&&!this.parameters.disablePicking}get parameters(){return this.buffer.parameters}getParameters(){const t=Object.assign({},this.buffer.parameters);return t.side=this.side,t}getMesh(t){let e,i;return t?(i=this.backBuffer.getPickingMesh(),e=this.frontBuffer.getPickingMesh()):(i=this.backBuffer.getMesh(),e=this.frontBuffer.getMesh()),this.frontMeshes.push(e),this.backMeshes.push(i),this.setParameters({side:this.side}),(new d).add(i,e)}getWireframeMesh(){return this.buffer.getWireframeMesh()}getPickingMesh(){return this.getMesh(!0)}setAttributes(t){this.buffer.setAttributes(t)}setParameters(t){"front"===(t=Object.assign({},t)).side?(this.frontMeshes.forEach(Go),this.backMeshes.forEach(Ho)):"back"===t.side?(this.frontMeshes.forEach(Ho),this.backMeshes.forEach(Go)):"double"===t.side&&(this.frontMeshes.forEach(Go),this.backMeshes.forEach(Go)),void 0!==t.side&&(this.side=t.side),delete t.side,void 0!==t.matrix&&(this.matrix=t.matrix),delete t.matrix,this.frontBuffer.setParameters(t),void 0!==t.wireframe&&(this.wireframe=t.wireframe,this.setVisibility(this.visible)),delete t.wireframe,this.backBuffer.setParameters(t)}setVisibility(t){this.visible=t,this.parameters.wireframe?(this.group.visible=!1,this.wireframeGroup.visible=t,this.pickable&&(this.pickingGroup.visible=!1)):(this.group.visible=t,this.wireframeGroup.visible=!1,this.pickable&&(this.pickingGroup.visible=t))}dispose(){this.frontBuffer.dispose(),this.backBuffer.dispose()}toJSON(){var t={};for(var e in this)["side","size","visible","matrix","parameters"].includes(e)&&(t[e]=this[e]);return t}}ze.add("shader/Line.vert","uniform float clipNear;\nuniform vec3 clipCenter;\nvarying vec3 vViewPosition;\n#if defined( RADIUS_CLIP )\nvarying vec3 vClipCenter;\n#endif\n#include color_pars_vertex\nvoid main(){\n#include color_vertex\n#include begin_vertex\n#include project_vertex\nvViewPosition = -mvPosition.xyz;\n#if defined( RADIUS_CLIP )\nvClipCenter = -( modelViewMatrix * vec4( clipCenter, 1.0 ) ).xyz;\n#endif\n#include nearclip_vertex\n}"),ze.add("shader/Line.frag","uniform float opacity;\nuniform float clipNear;\nuniform float clipRadius;\nvarying vec3 vViewPosition;\n#if defined( RADIUS_CLIP )\nvarying vec3 vClipCenter;\n#endif\n#include common\n#include color_pars_fragment\n#include fog_pars_fragment\nvoid main(){\n#include nearclip_fragment\n#include radiusclip_fragment\ngl_FragColor = vec4( vColor, opacity );\n#include premultiplied_alpha_fragment\n#include tonemapping_fragment\n#include colorspace_fragment\n#include fog_fragment\n}");class Wo extends Uo{constructor(){super(...arguments),this.isLine=!0,this.vertexShader="Line.vert",this.fragmentShader="Line.frag"}}class Xo extends Nr{constructor(t,r,n){super(t,r,n),this.type="surface",this.parameters=Object.assign({isolevelType:{type:"select",options:{value:"value",sigma:"sigma"}},isolevel:{type:"number",precision:2,max:1e3,min:-1e3},negateIsolevel:{type:"boolean"},isolevelScroll:{type:"boolean"},smooth:{type:"integer",precision:1,max:10,min:0},background:{type:"boolean",rebuild:!0},opaqueBack:{type:"boolean",buffer:!0},boxSize:{type:"integer",precision:1,max:100,min:0},colorVolume:{type:"hidden"},contour:{type:"boolean",rebuild:!0},useWorker:{type:"boolean",rebuild:!0},wrap:{type:"boolean",rebuild:!0}},this.parameters),t instanceof $o?(this.surface=void 0,this.volume=t):(this.surface=t,this.volume=void 0),this.boxCenter=new e,this.__boxCenter=new e,this.box=new a,this.__box=new a,this._position=new e,this.inverseMatrix=new i,this.setBox=function(){this._position.copy(r.translationGroup.position).negate(),this._position.applyMatrix4(this.inverseMatrix),this._position.equals(this.boxCenter)||this.setParameters({boxCenter:this._position})},this.toBePrepared=!0,this.viewer.signals.ticked.add(this.setBox,this),this.init(n)}init(t){const e=t||{};e.colorScheme=rt(e.colorScheme,"uniform"),e.colorValue=rt(e.colorValue,14540253),this.isolevelType=rt(e.isolevelType,"sigma"),this.isolevel=rt(e.isolevel,2),this.negateIsolevel=rt(e.negateIsolevel,!1),this.isolevelScroll=rt(e.isolevelScroll,!1),this.smooth=rt(e.smooth,0),this.background=rt(e.background,!1),this.opaqueBack=rt(e.opaqueBack,!0),this.boxSize=rt(e.boxSize,0),this.colorVolume=rt(e.colorVolume,void 0),this.contour=rt(e.contour,!1),this.useWorker=rt(e.useWorker,!0),this.wrap=rt(e.wrap,!1),super.init(e),this.inverseMatrix.copy(this.matrix).invert(),this.build()}attach(t){this.bufferList.forEach((t=>{this.viewer.add(t)})),this.setVisibility(this.visible),t()}prepare(t){if(this.volume){let e;if(e="sigma"===this.isolevelType?this.volume.getValueForSigma(this.isolevel):this.isolevel,this.negateIsolevel&&(e*=-1),!this.surface||this.__isolevel!==e||this.__smooth!==this.smooth||this.__contour!==this.contour||this.__wrap!==this.wrap||this.__boxSize!==this.boxSize||this.boxSize>0&&!this.__boxCenter.equals(this.boxCenter)){this.__isolevel=e,this.__smooth=this.smooth,this.__contour=this.contour,this.__wrap=this.wrap,this.__boxSize=this.boxSize,this.__boxCenter.copy(this.boxCenter),this.__box.copy(this.box);const i=e=>{this.surface=e,t()};this.useWorker?this.volume.getSurfaceWorker(e,this.smooth,this.boxCenter,this.boxSize,this.contour,this.wrap,i):i(this.volume.getSurface(e,this.smooth,this.boxCenter,this.boxSize,this.contour,this.wrap))}else t()}else t()}create(){const t={position:this.surface.getPosition(),color:this.surface.getColor(this.getColorParams()),index:this.surface.getIndex()};let e;if(this.contour)e=new Wo(t,this.getBufferParams({wireframe:!1}));else{Object.assign(t,{normal:this.surface.getNormal(),picking:this.surface.getPicking()});const i=new jo(t,this.getBufferParams({background:this.background,opaqueBack:this.opaqueBack,dullInterior:!1}));e=new qo(i)}this.bufferList.push(e)}update(t){if(0===this.bufferList.length)return;const e={};(t=t||{}).position&&(e.position=this.surface.getPosition()),t.color&&(e.color=this.surface.getColor(this.getColorParams())),t.index&&(e.index=this.surface.getIndex()),t.normal&&(e.normal=this.surface.getNormal()),this.bufferList.forEach((function(t){t.setAttributes(e)}))}setParameters(t,e,i){return t&&void 0!==t.isolevelType&&this.volume&&("value"===this.isolevelType&&"sigma"===t.isolevelType?this.isolevel=this.volume.getSigmaForValue(this.isolevel):"sigma"===this.isolevelType&&"value"===t.isolevelType&&(this.isolevel=this.volume.getValueForSigma(this.isolevel)),this.isolevelType=t.isolevelType),t&&t.boxCenter&&(this.boxCenter.copy(t.boxCenter),delete t.boxCenter),t&&t.wireframe&&(t.contour||void 0===t.contour&&this.contour)&&(t.wireframe=!1),super.setParameters(t,e,i),t.matrix&&this.inverseMatrix.copy(t.matrix).invert(),this.volume&&this.volume.getBox(this.boxCenter,this.boxSize,this.box),t&&void 0!==t.colorVolume&&e&&(e.color=!0),this.surface&&(void 0!==t.isolevel||void 0!==t.negateIsolevel||void 0!==t.smooth||void 0!==t.wrap||void 0!==t.boxSize||this.boxSize>0&&!this.__box.equals(this.box))&&this.build({position:!0,color:!0,index:!0,normal:!this.contour}),this}getColorParams(){const t=super.getColorParams();return t.volume=this.colorVolume,t}dispose(){this.viewer.signals.ticked.remove(this.setBox,this),super.dispose()}}class Yo{static zoomScroll(t,e){t.trackballControls.zoom(e)}static clipNearScroll(t,e){const i=t.getParameters();t.setParameters({clipNear:i.clipNear+e/10})}static focusScroll(t,e){const i=t.getFocus(),r=Math.sign(e)*function(t,e,i){if(t>e)return t;const r=t/e;return((2*i-e)*r+(2*e-3*i))*r*r+i}((100-i)/10,5,.2);t.setFocus(i+r)}static zoomFocusScroll(t,e){t.trackballControls.zoom(e);const i=t.viewer.camera.position.z;t.setFocus(100-Math.abs(i/8))}static isolevelScroll(t,e){const i=Math.sign(e)/10;t.eachRepresentation(((t,e)=>{if(t.repr instanceof Xo){const e=t.getParameters();e.isolevelScroll&&t.setParameters({isolevel:e.isolevel+i})}}))}static panDrag(t,e,i){t.trackballControls.pan(e,i)}static rotateDrag(t,e,i){t.trackballControls.rotate(e,i)}static zRotateDrag(t,e,i){t.trackballControls.zRotate(e,i)}static zoomDrag(t,e,i){t.trackballControls.zoom((e+i)/-2)}static zoomFocusDrag(t,e,i){t.trackballControls.zoom((e+i)/-2);const r=t.viewer.camera.position.z;t.setFocus(100-Math.abs(r/8))}static panComponentDrag(t,e,i){t.trackballControls.panComponent(e,i)}static panAtomDrag(t,e,i){t.trackballControls.panAtom(e,i)}static rotateComponentDrag(t,e,i){t.trackballControls.rotateComponent(e,i)}static movePick(t,e){e&&t.animationControls.move(e.position.clone())}static tooltipPick(t,e){const i=t.tooltip;if(t.getParameters().tooltip&&e){const t=e.mouse.position;i.innerText=e.getLabel(),i.style.bottom=window.innerHeight-t.y+3+"px",i.style.left=t.x+3+"px",i.style.display="block"}else i.style.display="none"}static measurePick(t,e){if(e&&(e.atom||e.bond)){const t=e.atom||e.closestBondAtom;e.component.measurePick(t)}else t.measureClear()}}const Ko={default:[["scroll",Yo.zoomScroll],["scroll-shift",Yo.focusScroll],["scroll-ctrl",Yo.isolevelScroll],["scroll-shift-ctrl",Yo.zoomFocusScroll],["drag-left",Yo.rotateDrag],["drag-right",Yo.panDrag],["drag-ctrl-left",Yo.panDrag],["drag-ctrl-right",Yo.zRotateDrag],["drag-shift-left",Yo.zoomDrag],["drag-middle",Yo.zoomFocusDrag],["drag-ctrl-shift-right",Yo.panComponentDrag],["drag-ctrl-shift-left",Yo.rotateComponentDrag],["clickPick-right",Yo.measurePick],["clickPick-ctrl-left",Yo.measurePick],["clickPick-middle",Yo.movePick],["clickPick-left",Yo.movePick],["hoverPick",Yo.tooltipPick]],pymol:[["drag-left",Yo.rotateDrag],["drag-middle",Yo.panDrag],["drag-right",Yo.zoomDrag],["scroll",Yo.focusScroll],["drag-shift-right",Yo.focusScroll],["clickPick-ctrl+shift-middle",Yo.movePick],["hoverPick",Yo.tooltipPick]],coot:[["scroll",Yo.isolevelScroll],["drag-left",Yo.rotateDrag],["drag-middle",Yo.panDrag],["drag-ctrl-left",Yo.panDrag],["drag-right",Yo.zoomFocusDrag],["drag-ctrl-right",Yo.focusScroll],["clickPick-middle",Yo.movePick],["hoverPick",Yo.tooltipPick]],astexviewer:[["drag-left",Yo.rotateDrag],["drag-ctrl-left",Yo.panDrag],["drag-shift-left",Yo.zoomDrag],["scroll",Yo.focusScroll],["clickPick-middle",Yo.movePick],["hoverPick",Yo.tooltipPick]]};function Zo(t){const e=t.split(/[-+]/);let i="";e.includes("scroll")&&(i="scroll"),e.includes("drag")&&(i="drag"),e.includes("click")&&(i="click"),e.includes("doubleClick")&&(i="doubleClick"),e.includes("hover")&&(i="hover"),e.includes("clickPick")&&(i="clickPick"),e.includes("hoverPick")&&(i="hoverPick");let r=0;e.includes("alt")&&(r+=1),e.includes("ctrl")&&(r+=2),e.includes("meta")&&(r+=4),e.includes("shift")&&(r+=8);let n=0;return e.includes("left")&&(n+=1),e.includes("right")&&(n+=2),e.includes("middle")&&(n+=4),[i,r,n]}class Qo{constructor(t,e={}){this.stage=t,this.actionList=[],this.mouse=t.mouseObserver,this.disabled=e.disabled||!1,this.preset(e.preset||"default")}run(t,...e){if(this.disabled)return;const i=this.mouse.key||0,r=this.mouse.buttons||0;this.actionList.forEach((n=>{n.type===t&&n.key===i&&n.button===r&&n.callback(this.stage,...e)}))}add(t,e){const[i,r,n]=Zo(t);this.actionList.push({type:i,key:r,button:n,callback:e})}remove(t,e){const i=t.includes("*"),[r,n,s]=Zo(t),o=this.actionList.filter((function(t){return!((t.type===r||i&&""===r)&&(t.key===n||i&&0===n)&&(t.button===s||i&&0===s)&&(t.callback===e||void 0===e))}));this.actionList=o}preset(t){this.clear();(Ko[t]||[]).forEach((t=>this.add(t[0],t[1])))}clear(){this.actionList.length=0}}class Jo{static autoView(t){t.autoView(1e3)}static toggleAnimations(t){t.animationControls.toggle()}static toggleRock(t){t.toggleRock()}static toggleSpin(t){t.toggleSpin()}static toggleAntialiasing(t){const e=t.getParameters();t.setParameters({sampleLevel:-1===e.sampleLevel?0:-1})}}const ta={default:[["i",Jo.toggleSpin],["k",Jo.toggleRock],["p",Jo.toggleAnimations],["a",Jo.toggleAntialiasing],["r",Jo.autoView]]};class ea{constructor(t,e={}){this.stage=t,this.actionList=[],this.disabled=e.disabled||!1,this.preset(e.preset||"default")}run(t){this.disabled||this.actionList.forEach((e=>{e.key===t&&e.callback(this.stage)}))}add(t,e){this.actionList.push({key:t,callback:e})}remove(t,e){const i=this.actionList.filter((function(i){return!(i.key===t&&(i.callback===e||void 0===e))}));this.actionList=i}preset(t){this.clear();(ta[t]||[]).forEach((t=>this.add(t[0],t[1])))}clear(){this.actionList.length=0}}class ia{constructor(t){this.stage=t,this.stage=t,this.mouse=t.mouseObserver,this.controls=t.mouseControls,this.mouse.signals.clicked.add(this._onClick,this),this.mouse.signals.hovered.add(this._onHover,this)}_onClick(t,e){const i=this.stage.pickingControls.pick(t,e);this.stage.signals.clicked.dispatch(i),this.controls.run("clickPick",i)}_onHover(t,e){const i=this.stage.pickingControls.pick(t,e);i&&this.mouse.down.equals(this.mouse.position)&&(this.stage.transformComponent=i.component,this.stage.transformAtom=i.atom),this.stage.signals.hovered.dispatch(i),this.controls.run("hoverPick",i)}dispose(){this.mouse.signals.clicked.remove(this._onClick,this),this.mouse.signals.hovered.remove(this._onHover,this)}}class ra{constructor(t){this.stage=t,this.stage=t,this.mouse=t.mouseObserver,this.controls=t.mouseControls,this.mouse.signals.moved.add(this._onMove,this),this.mouse.signals.scrolled.add(this._onScroll,this),this.mouse.signals.dragged.add(this._onDrag,this),this.mouse.signals.clicked.add(this._onClick,this),this.mouse.signals.hovered.add(this._onHover,this),this.mouse.signals.doubleClicked.add(this._onDblclick,this)}_onMove(){this.stage.tooltip.style.display="none"}_onScroll(t){this.controls.run("scroll",t)}_onDrag(t,e){this.controls.run("drag",t,e)}_onClick(t,e){this.controls.run("click",t,e)}_onDblclick(t,e){this.controls.run("doubleClick",t,e)}_onHover(t,e){this.controls.run("hover",t,e)}dispose(){this.mouse.signals.moved.remove(this._onMove,this),this.mouse.signals.scrolled.remove(this._onScroll,this),this.mouse.signals.dragged.remove(this._onDrag,this),this.mouse.signals.clicked.remove(this._onClick,this),this.mouse.signals.hovered.remove(this._onHover,this)}}class na{constructor(t){this.stage=t,this.viewer=t.viewer,this.animationControls=t.animationControls,this.viewer.signals.ticked.add(this._onTick,this)}_onTick(t){this.animationControls.run(t)}dispose(){this.viewer.signals.ticked.remove(this._onTick,this)}}const sa=!!we&&{passive:!0};class oa{constructor(t){this.stage=t,this.stage=t,this.controls=t.keyControls,this.domElement=t.viewer.renderer.domElement,this.domElement.setAttribute("tabIndex","-1"),this.domElement.style.outline="none",this._focusDomElement=this._focusDomElement.bind(this),this._onKeydown=this._onKeydown.bind(this),this._onKeyup=this._onKeyup.bind(this),this._onKeypress=this._onKeypress.bind(this),this.domElement.addEventListener("mousedown",this._focusDomElement),this.domElement.addEventListener("touchstart",this._focusDomElement,sa),this.domElement.addEventListener("keydown",this._onKeydown),this.domElement.addEventListener("keyup",this._onKeyup),this.domElement.addEventListener("keypress",this._onKeypress)}_onKeydown(){}_onKeyup(){}_onKeypress(t){let e;e="key"in KeyboardEvent.prototype?t.key:String.fromCharCode(t.which||t.keyCode),this.controls.run(e)}_focusDomElement(){this.domElement.focus()}dispose(){this.domElement.removeEventListener("mousedown",this._focusDomElement),this.domElement.removeEventListener("touchstart",this._focusDomElement,sa),this.domElement.removeEventListener("keydown",this._onKeypress),this.domElement.removeEventListener("keyup",this._onKeypress),this.domElement.removeEventListener("keypress",this._onKeypress)}}class aa{constructor(i,r,n,s={}){this.component=i,this.position=r,this.offsetX=rt(s.offsetX,0),this.offsetY=rt(s.offsetY,0),this.visible=rt(s.visible,!0),this.stage=i.stage,this.viewer=i.stage.viewer,this._viewerPosition=new e,this._updateViewerPosition(),this._canvasPosition=new t,this._cameraPosition=new e,this.element=document.createElement("div"),Object.assign(this.element.style,{display:"block",position:"absolute",pointerEvents:"none",whiteSpace:"nowrap",left:"-10000px"}),this.viewer.wrapper.appendChild(this.element),this.setContent(n),this.updateVisibility(),this.viewer.signals.rendered.add(this._update,this),this.component.signals.matrixChanged.add(this._updateViewerPosition,this)}setContent(t){const e=this.element.style.display;if("none"===e&&(this.element.style.left="-10000px",this.element.style.display="block"),t instanceof HTMLElement)this.element.appendChild(t);else{const e=document.createElement("div");e.innerText=t,Object.assign(e.style,{backgroundColor:"rgba( 0, 0, 0, 0.6 )",color:"lightgrey",padding:"8px",fontFamily:"sans-serif"}),this.element.appendChild(e)}this._clientRect=this.element.getBoundingClientRect(),"none"===e&&(this.element.style.display=e)}setVisibility(t){this.visible=t,this.updateVisibility()}getVisibility(){return this.visible&&this.component.parameters.visible}updateVisibility(){this.element.style.display=this.getVisibility()?"block":"none"}_updateViewerPosition(){this._viewerPosition.copy(this.position).applyMatrix4(this.component.matrix)}_update(){if(!this.getVisibility())return;const t=this.element.style,e=this._canvasPosition,i=this._viewerPosition,r=this._clientRect;if(this._cameraPosition.copy(i).add(this.viewer.translationGroup.position).applyMatrix4(this.viewer.rotationGroup.matrix).sub(this.viewer.camera.position),this._cameraPosition.z<0)return void(t.display="none");t.display="block";const n=this._cameraPosition.length(),s=this.viewer.scene.fog;t.opacity=(1-Et(s.near,s.far,n)).toString(),t.zIndex=Math.round(100*(s.far-n)).toString(),this.stage.viewerControls.getPositionOnCanvas(i,e),t.bottom=this.offsetX+e.y+r.height/2+"px",t.left=this.offsetY+e.x-r.width/2+"px"}dispose(){this.viewer.wrapper.removeChild(this.element),this.viewer.signals.ticked.remove(this._update,this),this.component.signals.matrixChanged.remove(this._updateViewerPosition,this)}}const ca=new i,la=new e,ha=new r;class ua{constructor(t){this.component=t,this.signals={changed:new J.Signal},this.stage=t.stage,this.viewer=t.stage.viewer}get position(){return this.component.position}get rotation(){return this.component.quaternion}changed(){this.component.updateMatrix(),this.viewer.requestRender(),this.signals.changed.dispatch()}spin(t,e){ca.copy(this.viewer.rotationGroup.matrix).invert(),la.copy(vt(t)).applyMatrix4(ca),ca.extractRotation(this.component.transform),ca.premultiply(this.viewer.rotationGroup.matrix),ca.invert(),la.copy(vt(t)),la.applyMatrix4(ca),ca.makeRotationAxis(la,e),ha.setFromRotationMatrix(ca),this.component.quaternion.premultiply(ha),this.changed()}}const da={"":"",vdw:"by vdW radius",covalent:"by covalent radius",sstruc:"by secondary structure",bfactor:"by bfactor",size:"size",data:"data",explicit:"explicit"};class ma{constructor(t={}){this.max=10,this.type=rt(t.type,"size"),this.scale=rt(t.scale,1),this.size=rt(t.size,1),this.data=rt(t.data,{})}atomRadius(t){let e;switch(this.type){case"vdw":e=t.vdw;break;case"covalent":e=t.covalent;break;case"bfactor":e=t.bfactor||1;break;case"sstruc":const i=t.sstruc;e="h"===i||"g"===i||"i"===i||"e"===i||"b"===i?.25:us.includes(t.atomname)?.4:.1;break;case"data":e=rt(this.data[t.index],1);break;case"explicit":e=t.radius,null===e&&(e=this.size);break;default:e=this.size}return Math.min(e*this.scale,this.max)}}ma.types=da;const fa=new e(-1,-1,-1),pa=new i;class ga{constructor(t){const i=t.rows,r=i/3,n=new lo(i,3),s=new lo(3,3),o=new lo(1,3),a=new lo(3,3),c=new lo(3,3),l=fo(t);po(t,l),ho(n,t),uo(s,n,n),xo(s,o,a,c);const h=new e(l[0],l[1],l[2]),u=new e(a.data[0],a.data[3],a.data[6]),d=new e(a.data[1],a.data[4],a.data[7]),m=new e(a.data[2],a.data[5],a.data[8]),f=u.clone().multiplyScalar(Math.sqrt(o.data[0]/r)),p=d.clone().multiplyScalar(Math.sqrt(o.data[1]/r)),g=m.clone().multiplyScalar(Math.sqrt(o.data[2]/r));this.begA=h.clone().sub(f),this.endA=h.clone().add(f),this.begB=h.clone().sub(p),this.endB=h.clone().add(p),this.begC=h.clone().sub(g),this.endC=h.clone().add(g),this.center=h,this.vecA=f,this.vecB=p,this.vecC=g,this.normVecA=u,this.normVecB=d,this.normVecC=m}getBasisMatrix(t=new i){const e=t;return e.makeBasis(this.normVecB,this.normVecA,this.normVecC),e.determinant()<0&&e.scale(fa),e}getRotationQuaternion(t=new r){const e=t;return e.setFromRotationMatrix(this.getBasisMatrix(pa)),e.invert()}getProjectedScaleForAtoms(t){let i=-1/0,r=-1/0,n=-1/0,s=-1/0,o=-1/0,a=-1/0;const c=new e,l=new e,h=this.center,u=this.normVecA,d=this.normVecB,m=this.normVecC;return t.eachAtom((function(t){jr(c.copy(t),u,h);const e=l.subVectors(c,h).normalize().dot(u),f=c.distanceTo(h);e>0?f>i&&(i=f):f>r&&(r=f),jr(c.copy(t),d,h);const p=l.subVectors(c,h).normalize().dot(d),g=c.distanceTo(h);p>0?g>n&&(n=g):g>s&&(s=g),jr(c.copy(t),m,h);const y=l.subVectors(c,h).normalize().dot(m),b=c.distanceTo(h);y>0?b>o&&(o=b):b>a&&(a=b)})),{d1a:i,d2a:n,d3a:o,d1b:-r,d2b:-s,d3b:-a}}}class ya{constructor(t,e,i,r){this.volume=t,this.setFilter(e,i,r)}get header(){return this.volume.header}get matrix(){return this.volume.matrix}get normalMatrix(){return this.volume.normalMatrix}get inverseMatrix(){return this.volume.inverseMatrix}get center(){return this.volume.center}get boundingBox(){return this.volume.boundingBox}get min(){return this.volume.min}get max(){return this.volume.max}get mean(){return this.volume.mean}get rms(){return this.volume.rms}_getFilterHash(t,e,i){return JSON.stringify([t,e,i])}setFilter(t,e,i){isNaN(t)&&this.header&&(t=this.header.DMEAN+2*this.header.ARMS),t=void 0===t||isNaN(t)?-1/0:t,e=rt(e,1/0),i=rt(i,!1);const r=this.volume.data,n=this.volume.position,s=this.volume.atomindex,o=this._getFilterHash(t,e,i);if(o!==this._filterHash){if(t===-1/0&&e===1/0)this.data=r,this.position=n,this.atomindex=s;else{const o=r.length;this._dataBuffer||(this._dataBuffer=new ArrayBuffer(4*o),this._positionBuffer=new ArrayBuffer(3*o*4),s&&(this._atomindexBuffer=new ArrayBuffer(4*o)));const a=new Float32Array(this._dataBuffer),c=new Float32Array(this._positionBuffer);let l;s&&(l=new Uint32Array(this._atomindexBuffer));let h=0;for(let u=0;u=t&&d<=e||i&&(de)){const t=3*h;a[h]=d,c[t+0]=n[o+0],c[t+1]=n[o+1],c[t+2]=n[o+2],s&&l&&(l[h]=s[u]),h+=1}}this.data=new Float32Array(this._dataBuffer,0,h),this.position=new Float32Array(this._positionBuffer,0,3*h),s&&(this.atomindex=new Int32Array(this._atomindexBuffer,0,h))}this._filterHash=o}}}ya.prototype.getValueForSigma=$o.prototype.getValueForSigma,ya.prototype.getSigmaForValue=$o.prototype.getSigmaForValue,ya.prototype.getDataAtomindex=$o.prototype.getDataAtomindex,ya.prototype.getDataPosition=$o.prototype.getDataPosition,ya.prototype.getDataColor=$o.prototype.getDataColor,ya.prototype.getDataPicking=$o.prototype.getDataPicking,ya.prototype.getDataSize=$o.prototype.getDataSize;class ba{constructor(t,e){const i=$n({nodeArray1:t.atomIndex1,nodeArray2:t.atomIndex2,edgeCount:t.count,nodeCount:e});this.countArray=i.countArray,this.offsetArray=i.offsetArray,this.indexArray=i.indexArray}}class _a extends Dn{get _defaultFields(){return[["atomIndex1",1,"int32"],["atomIndex2",1,"int32"],["bondOrder",1,"int8"]]}addBond(t,e,i){this.growIfFull();const r=this.count,n=t.index,s=e.index;n0&&(a[e]=x.angleTo(v));const r=Math.cos(p.angleTo(g));h[e]=180/Math.PI*Math.acos(r);const n=p.length(),_=g.length();c[e]=Math.sqrt(_*n)/Math.max(2,2*(1-r)),l[e]=Math.abs(m.dot(x)),y.copy(p).multiplyScalar(c[e]/n),b.copy(g).multiplyScalar(c[e]/_),y.subVectors(P,y),b.subVectors(I,b),y.toArray(s,i+3),b.toArray(s,i+6),w.subVectors(C,A),w.toArray(u,i),v.copy(x),A.copy(y)}y.fromArray(s,3),b.fromArray(s,6),x.subVectors(y,b).normalize(),C.index=t.getAtomIndexByType(0,S),A.copy(C),_.copy(C),jr(_,x,y),_.toArray(s,0),w.subVectors(A,y),w.toArray(u,0),y.fromArray(s,3*r-6),b.fromArray(s,3*r-9),x.subVectors(y,b).normalize(),C.index=t.getAtomIndexByType(r-1,S),A.copy(C),_.copy(C),jr(_,x,y),_.toArray(s,3*r-3);for(let e=r-3;ei||h.bending[e]>t)&&(O=!0)),O){if(e-f<4){f=e,O=!1;continue}F.index=D.traceAtomIndex,I=h.axis.subarray(3*f+3,3*e),k=h.center.subarray(3*f,3*e+3),C=Vr(I).normalize(),P=Vr(k),M.fromArray(k),jr(M,C,P),T.fromArray(k,k.length-3),jr(T,C,P),C.subVectors(T,M),C.toArray(g,p),P.toArray(y,p),M.toArray(b,p),T.toArray(_,p),d.atomColorToArray(F,x,p),v.push(F.index),w.push(m.atomRadius(F)),A.push(l+f),S.push(l+e+1-f),p+=3,f=e,O=!1}const R=new Float32Array(v);return{axis:new Float32Array(g),center:new Float32Array(y),begin:new Float32Array(b),end:new Float32Array(_),color:new Float32Array(x),picking:new Xs(R,a),size:new Float32Array(w),residueOffset:A,residueCount:S}}}class Pa{constructor(t){this.scoreFunction=t,this.content=[],this.scoreFunction=t}push(t){this.content.push(t),this.bubbleUp(this.content.length-1)}pop(){const t=this.content[0],e=this.content.pop();return e&&this.content.length>0&&(this.content[0]=e,this.sinkDown(0)),t}peek(){return this.content[0]}remove(t){const e=this.content.length;for(let i=0;i0;){const i=Math.floor((t+1)/2)-1,r=this.content[i];if(!(this.scoreFunction(e)this.maxDepth&&(this.maxDepth=t);const s=r-i;if(0===s)return-1;const n=4*this.currentNode,o=this.nodes;if(this.currentNode+=1,1===s)return o[n]=i,o[n+1]=-1,o[n+2]=-1,o[n+3]=e,n;const a=this.indices,c=this.points,l=i+Math.floor(s/2),h=t%3;let d,u,m,p,f,g=i,y=r-1;for(;y>g;){for(m=g+y>>1,p=c[3*a[m]+h],u=a[m],a[m]=a[y],a[y]=u,f=g,d=g;d-t[1])),s=this.nodes,n=this.points,o=this.indices,a=c=>{let l,h;const d=this.getNodeDepth(c)%3,u=3*o[s[c]],m=[n[u+0],n[u+1],n[u+2]],p=this.metric(t,m);function f(t,i){r.push([t,i]),r.size()>e&&r.pop()}const g=s[c+1],y=s[c+2];if(-1===y&&-1===g)return void((r.size()n[3*o[s[t]]+r])throw new Error("left child is > parent!");i+=this.verify(a,e+1)}if(-1!==c){if(n[3*o[s[c]]+r]0}isBackbone(){const t=this.residueType.backboneIndexList;return t.length>0&&t.includes(this.index-this.residueAtomOffset)}isPolymer(){if(this.structure.entityList.length>0)return this.entity.isPolymer();{const t=this.residueType.moleculeType;return 3===t||4===t||5===t}}isSidechain(){return this.isPolymer()&&!this.isBackbone()}isCg(){const t=this.residueType.backboneType;return 4===t||5===t||6===t}isTrace(){return this.index===this.residueType.traceAtomIndex+this.residueAtomOffset}isHetero(){return 1===this.residueType.hetero}isProtein(){return 3===this.residueType.moleculeType}isNucleic(){const t=this.residueType.moleculeType;return 4===t||5===t}isRna(){return 4===this.residueType.moleculeType}isDna(){return 5===this.residueType.moleculeType}isWater(){return 1===this.residueType.moleculeType}isIon(){return 2===this.residueType.moleculeType}isSaccharide(){return 6===this.residueType.moleculeType}isHelix(){return Hs.includes(this.sstruc)}isSheet(){return Ws.includes(this.sstruc)}isTurn(){return qs.includes(this.sstruc)&&this.isProtein()}isBonded(){return 0!==this.bondHash.countArray[this.index]}isRing(){return void 0!==this.residueType.getRings().atomRings[this.index-this.residueAtomOffset]}isAromatic(){return 1===this.aromatic}isPolarHydrogen(){let t=!1;return 1!==this.number||(t=!this.hasBondToElement(6)),t}isMetal(){return this.atomType.isMetal()}isNonmetal(){return this.atomType.isNonmetal()}isMetalloid(){return this.atomType.isMetalloid()}isHalogen(){return this.atomType.isHalogen()}isDiatomicNonmetal(){return this.atomType.isDiatomicNonmetal()}isPolyatomicNonmetal(){return this.atomType.isPolyatomicNonmetal()}isAlkaliMetal(){return this.atomType.isAlkaliMetal()}isAlkalineEarthMetal(){return this.atomType.isAlkalineEarthMetal()}isNobleGas(){return this.atomType.isNobleGas()}isTransitionMetal(){return this.atomType.isTransitionMetal()}isPostTransitionMetal(){return this.atomType.isPostTransitionMetal()}isLanthanide(){return this.atomType.isLanthanide()}isActinide(){return this.atomType.isActinide()}getDefaultValence(){return this.atomType.getDefaultValence()}getValenceList(){return this.atomType.getValenceList()}getOuterShellElectronCount(){return this.atomType.getOuterShellElectronCount()}distanceTo(t){const e=this.atomStore,i=t.atomStore,r=this.index,s=t.index,n=e.x[r]-i.x[s],o=e.y[r]-i.y[s],a=e.z[r]-i.z[s],c=n*n+o*o+a*a;return Math.sqrt(c)}connectedTo(t){const e=this.atomStore,i=t.atomStore,r=this.index,s=t.index;if(e.altloc&&i.altloc){const t=e.altloc[r],n=i.altloc[s];if(0!==t&&0!==n&&32!==t&&32!==n&&t!==n)return!1}const n=e.x[r]-i.x[s],o=e.y[r]-i.y[s],a=e.z[r]-i.z[s],c=n*n+o*o+a*a;if(c<48&&this.isCg())return!0;if(isNaN(c))return!1;const l=this.covalent+t.covalent,h=l+.3,d=l-.5;return cd*d}positionFromArray(t,e=0){return this.x=t[e+0],this.y=t[e+1],this.z=t[e+2],this}positionToArray(t=[],e=0){const i=this.index,r=this.atomStore;return t[e+0]=r.x[i],t[e+1]=r.y[i],t[e+2]=r.z[i],t}positionToVector3(t){return void 0===t&&(t=new e),t.x=this.x,t.y=this.y,t.z=this.z,t}positionFromVector3(t){return this.x=t.x,this.y=t.y,this.z=t.z,this}positionAdd(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this}positionSub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this}getResidueBonds(t=!1){const e=this.residueAtomOffset,i=this.index-this.residueAtomOffset,r=this.residueType.getBonds(),s=r.atomIndices1,n=r.atomIndices2;let o,a,c,l;for(t||(l=[]),o=s.indexOf(i);-1!==o;){if(c=n[o]+e,!l)return c;l.push(c),o=s.indexOf(i,o+1)}for(a=n.indexOf(i);-1!==a;){if(c=s[a]+e,!l)return c;l.push(c),a=n.indexOf(i,a+1)}return l}qualifiedName(t=!1){var e="";return this.resname&&!t&&(e+="["+this.resname+"]"),void 0!==this.resno&&(e+=this.resno),this.inscode&&(e+="^"+this.inscode),this.chainname&&(e+=":"+this.chainname),this.atomname&&(e+="."+this.atomname),this.altloc&&(e+="%"+this.altloc),this.structure.modelStore.count>1&&(e+="/"+this.modelIndex),e}clone(){return new Ma(this.structure,this.index)}toObject(){return{index:this.index,residueIndex:this.residueIndex,resname:this.resname,x:this.x,y:this.y,z:this.z,element:this.element,chainname:this.chainname,resno:this.resno,serial:this.serial,vdw:this.vdw,covalent:this.covalent,hetero:this.hetero,bfactor:this.bfactor,altloc:this.altloc,atomname:this.atomname,modelIndex:this.modelIndex}}}function Ta(t,e){const i=t[0]-e[0],r=t[1]-e[1],s=t[2]-e[2];return i*i+r*r+s*s}function Ba(t,e){return Math.sqrt(Ta(t,e))}const Da=new Float32Array(3);class $a{constructor(t,e=!1){De&&Me.time("Kdtree build");const i=e?Ta:Ba,r=new Float32Array(3*t.atomCount),s=new Uint32Array(t.atomCount);let n=0;t.eachAtom((function(t){r[n+0]=t.x,r[n+1]=t.y,r[n+2]=t.z,s[n/3]=t.index,n+=3})),this.atomIndices=s,this.points=r,this.kdtree=new ka(r,i),De&&Me.timeEnd("Kdtree build")}nearest(t,i,r){t instanceof e?t.toArray(Da):t instanceof Ma&&t.positionToArray(Da);const s=this.kdtree.nearest(Da,i,r),n=this.kdtree.indices,o=this.kdtree.nodes,a=this.atomIndices,c=[];for(let t=0,e=s.length;t":"3/4-Z","?":"X-Y","@":"Y-X",A:"Z+1/3",B:"Z+2/3",C:"X+2/3",D:"Y+1/3",E:"-Y+2/3",F:"X-Y+1/3",G:"Y-X+2/3",H:"-X+1/3",I:"X+1/3",J:"Y+2/3",K:"-Y+1/3",L:"X-Y+2/3",M:"Y-X+1/3",N:"-X+2/3",O:"2/3+X",P:"1/3+Y",Q:"1/3+Z",R:"2/3-Y",S:"1/3+X-Y",T:"2/3+Y-X",U:"1/3-X",V:"2/3-X",W:"1/3-Y",X:"1/3-Z",Y:"2/3+Y",Z:"1/3+Y-X","[":"2/3+X-Y","]":"1/3+X","^":"2/3+Z",_:"2/3-Z","`":"5/6+Z",a:"1/6+Z",b:"5/6-Z",c:"1/6-Z",d:"Z+5/6",e:"Z+1/6",f:"Z+1/4",g:"+Y"},Ra={"P 1":" !#","P -1":" !#$%&","P 1 2 1":" !#$!&","P 1 21 1":" !#$'&","C 1 2 1":" !#$!&()#*)&","P 1 m 1":" !# %#","P 1 c 1":" !# %+","C 1 m 1":" !# %#()#(,#","C 1 c 1":" !# %+()#(,+","P 1 2/m 1":" !# %#$!&$%&","P 1 21/m 1":" !#$)&$%& ,#","C 1 2/m 1":" !# %#$!&$%&()#(,#*)&*,&","P 1 2/c 1":" !#$!-$%& %+","P 1 21/c 1":" !#$%&$)- ,+","C 1 2/c 1":" !#$!-$%& %+()#*)-*,&(,+","P 2 2 2":" !#$%#$!& %&","P 2 2 21":" !#$%+$!- %&","P 21 21 2":" !#$%#*)&(,&","P 21 21 21":" !#*%+$)-(,&","C 2 2 21":" !#$%+$!- %&()#*,+*)-(,&","C 2 2 2":" !#$%#$!& %&()#*,#*)&(,&","F 2 2 2":" !#$%#$!& %& )+$,+$)- ,-(!+*%+*!-(%-()#*,#*)&(,&","I 2 2 2":" !#$%# %&$!&.'/01/.120'2","I 21 21 21":" !#*%+$)-(,&()+$,#*!& %-","P m m 2":" !#$%# %#$!#","P m c 21":" !#$%+ %+$!#","P c c 2":" !#$%# %+$!+","P m a 2":" !#$%#(%#*!#","P c a 21":" !#$%+(%#*!+","P n c 2":" !#$%# ,+$)+","P m n 21":" !#*%+(%+$!#","P b a 2":" !#$%#(,#*)#","P n a 21":" !#$%+(,#*)+","P n n 2":" !#$%#(,+*)+","C m m 2":" !#$%# %#$!#()#*,#(,#*)#","C m c 21":" !#$%+ %+$!#()#*,+(,+*)#","C c c 2":" !#$%# %+$!+()#*,#(,+*)+","A m m 2":" !#$%# %#$!# )+$,+ ,+$)+","A b m 2":" !#$%# ,#$)# )+$,+ %+$!+","A m a 2":" !#$%#(%#*!# )+$,+(,+*)+","A b a 2":" !#$%#(,#*)# )+$,+(%+*!+","F m m 2":" !#$%# %#$!# )+$,+ ,+$)+(!+*%+(%+*!+()#*,#(,#*)#","F d d 2":" !#$%#345675 )+$,+3896:9(!+*%+;49<79()#*,#;85<:5","I m m 2":" !#$%# %#$!#()+*,+(,+*)+","I b a 2":" !#$%#(,#*)#()+*,+ %+$!+","I m a 2":" !#$%#(%#*!#()+*,+ ,+$)+","P 2/m 2/m 2/m":" !#$%#$!& %&$%& !& %#$!#","P 2/n 2/n 2/n":" !#$%#$!& %&*,-()-(,+*)+","P 2/c 2/c 2/m":" !#$%#$!- %-$%& !& %+$!+","P 2/b 2/a 2/n":" !#$%#$!& %&*,&()&(,#*)#","P 21/m 2/m 2/a":" !#*%#$!&(%&$%&(!& %#*!#","P 2/n 21/n 2/a":" !#*%#*)- ,-$%&(!&(,+$)+","P 2/m 2/n 21/a":" !#*%+*!- %&$%&(!-(%+$!#","P 21/c 2/c 2/a":" !#*%#$!-(%-$%&(!& %+*!+","P 21/b 21/a 2/m":" !#$%#*)&(,&$%& !&(,#*)#","P 21/c 21/c 2/n":" !#*,#$)-(%-$%&()& ,+*!+","P 2/b 21/c 21/m":" !#$%+$)- ,&$%& !- ,+$)#","P 21/n 21/n 2/m":" !#$%#*)-(,-$%& !&(,+*)+","P 21/m 21/m 2/n":" !#$%#*'&.,&*,&.'& %#$!#","P 21/b 2/c 21/n":" !#*,+$!-(,&$%&()- %+*)#","P 21/b 21/c 21/a":" !#*%+$)-(,&$%&(!- ,+*)#","P 21/n 21/m 21/a":" !#0%/$'&.12$%&.!2 1#0'/","C 2/m 2/c 21/m":" !#$%+$!- %&$%& !- %+$!#()#*,+*)-(,&*,&()-(,+*)#","C 2/m 2/c 21/a":" !#$,+$)- %&$%& )- ,+$!#()#*%+*!-(,&*,&(!-(%+*)#","C 2/m 2/m 2/m":" !#$%#$!& %&$%& !& %#$!#()#*,#*)&(,&*,&()&(,#*)#","C 2/c 2/c 2/m":" !#$%#$!- %-$%& !& %+$!+()#*,#*)-(,-*,&()&(,+*)+","C 2/m 2/m 2/a":" !#$,#$)& %&$%& )& ,#$!#()#*%#*!&(,&*,&(!&(%#*)#","C 2/c 2/c 2/a":" !#*,#$!&(,&$,-(!- ,+*!+()#$%#*)& %&*%- )-(%+$)+","F 2/m 2/m 2/m":" !#$%#$!& %&$%& !& %#$!# )+$,+$)- ,-$,- )- ,+$)+(!+*%+*!-(%-*%-(!-(%+*!+()#*,#*)&(,&*,&()&(,#*)#","F 2/d 2/d 2/d":" !#$%#$!& %&64=37=345675 )+$,+$)- ,-68>3:>3896:9(!+*%+*!-(%-<4>;7>;49<79()#*,#*)&(,&<8=;:=;85<:5","I 2/m 2/m 2/m":" !#$%#$!& %&$%& !& %#$!#()+*,+*)-(,-*,-()-(,+*)+","I 2/b 2/a 2/m":" !#$%#*)&(,&$%& !&(,#*)#()+*,+$!- %-*,-()- %+$!+","I 21/b 21/c 21/a":" !#*%+$)-(,&$%&(!- ,+*)#()+$,#*!& %-*,- )&(%#$!+","I 21/m 21/m 21/a":" !#$,#$)& %&$%& )& ,#$!#()+*%+*!-(,-*,-(!-(%+*)+","P 4":" !#$%#% #!$#","P 41":" !#$%+% 5!$9","P 42":" !#$%#% +!$+","P 43":" !#$%+% 9!$5","I 4":" !#$%#% #!$#()+*,+,(+)*+","I 41":" !#*,+%(5)$9()+$%#, 9!*5","P -4":" !#$%#!$&% &","I -4":" !#$%#!$&% &()+*,+)*-,(-","P 4/m":" !#$%#% #!$#$%& !&!$&% &","P 42/m":" !#$%#% +!$+$%& !&!$-% -","P 4/n":" !#$%#,(#)*#*,&()&!$&% &","P 42/n":" !#$%#,(+)*+*,-()-!$&% &","I 4/m":" !#$%#% #!$#$%& !&!$&% &()+*,+,(+)*+*,-()-)*-,(-","I 41/a":" !#*,+%(5)$9$,=(!>!$&,(-()+$%#, 9!*5*%> )=)*-% &","P 4 2 2":" !#$%#% #!$#$!& %&! &%$&","P 4 21 2":" !#$%#,(#)*#*)&(,&! &%$&","P 41 2 2":" !#$%+% 5!$9$!& %-! >%$=","P 41 21 2":" !#$%+,(5)*9*)=(,>! &%$-","P 42 2 2":" !#$%#% +!$+$!& %&! -%$-","P 42 21 2":" !#$%#,(+)*+*)-(,-! &%$&","P 43 2 2":" !#$%+% 9!$5$!& %-! =%$>","P 43 21 2":" !#$%+,(9)*5*)>(,=! &%$-","I 4 2 2":" !#$%#% #!$#$!& %&! &%$&()+*,+,(+)*+*)-(,-)(-,*-","I 41 2 2":" !#*,+%(5)$9*!> ,=)(-%$&()+$%#, 9!*5$)=(%>! &,*-","P 4 m m":" !#$%#% #!$# %#$!#%$#! #","P 4 b m":" !#$%#% #!$#(,#*)#,*#)(#","P 42 c m":" !#$%#% +!$+ %+$!+%$#! #","P 42 n m":" !#$%#,(+)*+(,+*)+%$#! #","P 4 c c":" !#$%#% #!$# %+$!+%$+! +","P 4 n c":" !#$%#% #!$#(,+*)+,*+)(+","P 42 m c":" !#$%#% +!$+ %#$!#%$+! +","P 42 b c":" !#$%#% +!$+(,#*)#,*+)(+","I 4 m m":" !#$%#% #!$# %#$!#%$#! #()+*,+,(+)*+(,+*)+,*+)(+","I 4 c m":" !#$%#% #!$# %+$!+%$+! +()+*,+,(+)*+(,#*)#,*#)(#","I 41 m d":" !#*,+%(5)$9 %#*)+%*5) 9()+$%#, 9!*5(,+$!#,$9!(5","I 41 c d":" !#*,+%(5)$9 %+*)#%*9) 5()+$%#, 9!*5(,#$!+,$5!(9","P -4 2 m":" !#$%#% &!$&$!& %&%$#! #","P -4 2 c":" !#$%#% &!$&$!- %-%$+! +","P -4 21 m":" !#$%#% &!$&*)&(,&,*#)(#","P -4 21 c":" !#$%#% &!$&*)-(,-,*+)(+","P -4 m 2":" !#$%#!$&% & %#$!#! &%$&","P -4 c 2":" !#$%#% &!$& %+$!+! -%$-","P -4 b 2":" !#$%#% &!$&(,#*)#)(&,*&","P -4 n 2":" !#$%#% &!$&(,+*)+)(-,*-","I -4 m 2":" !#$%#% &!$& %#$!#! &%$&()+*,+,(-)*-(,+*)+)(-,*-","I -4 c 2":" !#$%#% &!$& %+$!+! -%$-()+*,+,(-)*-(,#*)#)(&,*&","I -4 2 m":" !#$%#% &!$&$!& %&%$#! #()+*,+,(-)*-*)-(,-,*+)(+","I -4 2 d":" !#$%#% &!$&*!>(%>,$9) 9()+*,+,(-)*-$)= ,=%*5!(5","P 4/m 2/m 2/m":" !#$%#% #!$#$!& %&! &%$&$%& !&!$&% & %#$!#%$#! #","P 4/m 2/c 2/c":" !#$%#% #!$#$!- %-! -%$-$%& !&!$&% & %+$!+%$+! +","P 4/n 2/b 2/m":" !#$%#% #!$#$!& %&! &%$&*,&()&)*&,(&(,#*)#,*#)(#","P 4/n 2/n 2/c":" !#$%#% #!$#$!& %&! &%$&*,-()-)*-,(-(,+*)+,*+)(+","P 4/m 21/b 2/m":" !#$%#% #!$#*)&(,&)(&,*&$%& !&!$&% &(,#*)#,*#)(#","P 4/m 21/n 2/c":" !#$%#% #!$#*)-(,-)(-,*-$%& !&!$&% &(,+*)+,*+)(+","P 4/n 21/m 2/m":" !#$%#,(#)*#*)&(,&! &%$&*,&()&!$&% & %#$!#,*#)(#","P 4/n 2/c 2/c":" !#$%#,(#)*#*)-(,-! -%$-*,&()&!$&% & %+$!+,*+)(+","P 42/m 2/m 2/c":" !#$%#% +!$+$!& %&! -%$-$%& !&!$-% - %#$!#%$+! +","P 42/m 2/c 2/m":" !#$%#% +!$+$!- %-! &%$&$%& !&!$-% - %+$!+%$#! #","P 42/n 2/b 2/c":" !#$%#,(+)*+$!- %-)(&,*&*,-()-!$&% &(,#*)#%$+! +","P 42/n 2/n 2/m":" !#$%#,(+)*+$!& %&)(-,*-*,-()-!$&% &(,+*)+%$#! #","P 42/m 21/b 2/c":" !#$%#% +!$+*)&(,&)(-,*-$%& !&!$-% -(,#*)#,*+)(+","P 42/m 21/n 2/m":" !#$%#,./'*/*'-.,-! &%$&$%& !&'*-,.-.,/*'/%$#! #","P 42/n 21/m 2/c":" !#$%#,(+)*+*)-(,-! &%$&*,-()-!$&% & %#$!#,*+)(+","P 42/n 21/c 2/m":" !#$%#,(+)*+*)&(,&! -%$-*,-()-!$&% & %+$!+,*#)(#","I 4/m 2/m 2/m":" !#$%#% #!$#$!& %&! &%$&$%& !&!$&% & %#$!#%$#! #()+*,+,(+)*+*)-(,-)(-,*-*,-()-)*-,(-(,+*)+,*+)(+","I 4/m 2/c 2/m":" !#$%#% #!$#$!- %-! -%$-$%& !&!$&% & %+$!+%$+! +()+*,+,(+)*+*)&(,&)(&,*&*,-()-)*-,(-(,#*)#,*#)(#","I 41/a 2/m 2/d":" !#*,+%(5)$9*!> ,=)(-%$&$,=(!>!$&,(-(,+$!#,$9!(5()+$%#, 9!*5$)=(%>! &,*-*%> )=)*-% & %#*)+%*5) 9","I 41/a 2/c 2/d":" !#*,+%(5)$9*!= ,>)(&%$-$,=(!>!$&,(-(,#$!+,$5!(9()+$%#, 9!*5$)>(%=! -,*&*%> )=)*-% & %+*)#%*9) 5","P 3":" !#%?#@$#","P 31":" !#%?A@$B","P 32":" !#%?B@$A","H 3":" !#%?#@$#CDAEFAGHAIJBKLBMNB","R 3":" !## !!# ","P -3":" !#%?#@$#$%&!@&? &","H -3":" !#%?#@$#$%&!@&? &OPQRSQTUQVWXYZX[]X]Y^W[^ZV^UR_PT_SO_","R -3":" !## !!# $%&&$%%&$","P 3 1 2":" !#%?#@$#%$&@!& ?&","P 3 2 1":" !#%?#@$#! &?%&$@&","P 31 1 2":" !#%?Q@$^%$_@!X ?&","P 31 2 1":" !#%?A@$B! &?%_$@X","P 32 1 2":" !#%?^@$Q%$X@!_ ?&","P 32 2 1":" !#%?B@$A! &?%X$@_","H 3 2":" !#%?#@$#! &?%&$@&OPQRSQTUQY]X[WXVZX]Y^W[^ZV^PO_SR_UT_","R 3 2":" !## !!# %$&$&%&%$","P 3 m 1":" !#%?#@$#%$#@!# ?#","P 3 1 m":" !#%?#@$#! #?%#$@#","P 3 c 1":" !#%?#@$#%$+@!+ ?+","P 3 1 c":" !#%?#@$#! +?%+$@+","H 3 m":" !#%?#@$#%$#@!# ?#OPQRSQTUQRUQTPQOSQ]Y^W[^ZV^WV^ZY^][^","R 3 m":" !## !!# ! # #!#! ","H 3 c":" !#%?#@$#%$+@!+ ?+OPQRSQTUQRU`TP`OS`]Y^W[^ZV^WVaZYa][a","R 3 c":" !## !!# '././'/'.","P -3 1 2/m":" !#%?#@$#%$&@!& ?&$%&!@&? &! #?%#$@#","P -3 1 2/c":" !#%?#@$#%$-@!- ?-$%&!@&? &! +?%+$@+","P -3 2/m 1":" !#%?#@$#! &?%&$@&$%&!@&? &%$#@!# ?#","P -3 2/c 1":" !#%?#@$#! -?%-$@-$%&!@&? &%$+@!+ ?+","H -3 2/m":" !#%?#@$#! &?%&$@&$%&!@&? &%$#@!# ?#OPQRSQTUQY]X[WXVZXVWXYZX[]XRUQTPQOSQ]Y^W[^ZV^PO_SR_UT_UR_PT_SO_WV^ZY^][^","R -3 2/m":" !## !!# %$&$&%&%$$%&&$%%&$! # #!#! ","H -3 2/c":" !#%?#@$#! -?%-$@-$%&!@&? &%$+@!+ ?+OPQRSQTUQY]b[WbVZbVWXYZX[]XRU`TP`OS`]Y^W[^ZV^POcSRcUTcUR_PT_SO_WVaZYa][a","R -3 2/c":" !## !!# 102021210$%&&$%%&$'././'/'.","P 6":" !#%?#@$#$%#!@#? #","P 61":" !#%?A@$B$%/!@d? e","P 65":" !#%?B@$A$%/!@e? d","P 62":" !#%?^@$Q$%#!@^? Q","P 64":" !#%?Q@$^$%#!@Q? ^","P 63":" !#%?#@$#$%+!@+? +","P -6":" !#%?#@$# !&%?&@$&","P 6/m":" !#%?#@$#$%#!@#? #$%&!@&? & !&%?&@$&","P 63/m":" !#%?#@$#$%+!@+? +$%&!@&? & !-%?-@$-","P 6 2 2":" !#%?#@$#$%#!@#? #! &?%&$@&%$&@!& ?&","P 61 2 2":" !#%?Q@$^$%+!@`? a! X?%&$@_%$b@!- ?c","P 65 2 2":" !#%?^@$Q$%+!@a? `! _?%&$@X%$c@!- ?b","P 62 2 2":" !#%?^@$Q$%#!@^? Q! _?%&$@X%$_@!& ?X","P 64 2 2":" !#%?Q@$^$%#!@Q? ^! X?%&$@_%$X@!& ?_","P 63 2 2":" !#%?#@$#$%+!@+? +! &?%&$@&%$-@!- ?-","P 6 m m":" !#%?#@$#$%#!@#? #%$#@!# ?#! #?%#$@#","P 6 c c":" !#%?#@$#$%#!@#? #%$+@!+ ?+! +?%+$@+","P 63 c m":" !#%?#@$#$%+!@+? +%$+@!+ ?+! #?%#$@#","P 63 m c":" !#%?#@$#$%+!@+? +%$#@!# ?#! +?%+$@+","P -6 m 2":" !#%?#@$# !&%?&@$&%$#@!# ?#%$&@!& ?&","P -6 c 2":" !#%?#@$# !-%?-@$-%$+@!+ ?+%$&@!& ?&","P -6 2 m":" !#%?#@$# !&%?&@$&! &?%&$@&! #?%#$@#","P -6 2 c":" !#%?#@$# !-%?-@$-! &?%&$@&! +?%+$@+","P 6/m 2/m 2/m":" !#%?#@$#$%#!@#? #! &?%&$@&%$&@!& ?&$%&!@&? & !&@$&%?&%$#@!# ?#! #?%#$@#","P 6/m 2/c 2/c":" !#%?#@$#$%#!@#? #! -?%-$@-%$-@!- ?-$%&!@&? & !&@$&%?&%$+@!+ ?+! +?%+$@+","P 63/m 2/c 2/m":" !#%?#@$#$%+!@+? +! -?%-$@-%$&@!& ?&$%&!@&? & !-@$-%?-%$+@!+ ?+! #?%#$@#","P 63/m 2/m 2/c":" !#%?#@$#$%+!@+? +! &?%&$@&%$-@!- ?-$%&!@&? & !-@$-%?-%$#@!# ?#! +?%+$@+","P 2 3":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ","F 2 3":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-((!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- ","I 2 3":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-(","P 21 3":" !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(","I 21 3":" !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(()+$,#*!& %-+()#$,&*!- %)+(,#$!&*%- ","P 2/m -3":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& $%& !& %#$!#&$%& !# %#$!%&$!& %# !#$","P 2/n -3":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& *,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*","F 2/m -3":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& $%& !& %#$!#&$%& !# %#$!%&$!& %# !#$ )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-($,- )- ,+$)+&*,&()#(,#*)%-*!-(%+(!+*(!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(*%-(!-(%+*!+-$,- )+ ,+$),&*)&(,#()#*()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- *,&()&(,#*)#-*%-(!+(%+*!,-$)- ,+ )+$","F 2/d -3":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& 64=37=345675=64=375345674=67=3453756 )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-(68>3:>3896:9=<8=;:5;85<:4><7>;49;79<(!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(<4>;7>;49<79>68>3:93896:8=<:=;85;:5<()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- <8=;:=;8f<:f><4>;79;49<78>6:>3893:96","I 2/m -3":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& $%& !& %#$!#&$%& !# %#$!%&$!& %# !#$()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-(*,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*","P 21/a -3":" !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&($%&(!- ,+*)#&$%-(!+ ,#*)%&$!-(,+ )#*","I 21/a -3":" !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&($%&(!- ,+*)#&$%-(!+ ,#*)%&$!-(,+ )#*()+$,#*g& %-+()#$,&*!- %)+(,#$!&*%- *,- )&(%#$!+-*,& )#(%+$!,-*)& %#(!+$","P 4 3 2":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$","P 42 3 2":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,*","F 4 3 2":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$ )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-(!(-%*-!*+%(+ +,$+)$-, -)#)*#,(&)(&,*(!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&() -,$-)$+, +(#,*#)*&,(&)+!*+%(-!(-%*()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- )(&,*&)*#,(#(+%*+!*-%(-!+)$+, -) -,$","F 41 3 2":" !#$,+*)&(%-# !+$,&*)-(%!# ,+$)&*%-(:3>46=7<98;5;58<976=43>:97<58;>:3=46 )+$%#*!-(,&#()+*%&$!- ,!+(,#*)-$%& :;=4<>765839;94<5:6>83=79:6543>7;=8<(!+*,#$)- %&+ )#$%-*!&(,)#(%+*!&$,- 73=86>:<54;935469:<=8;>7576983=:;>4<()#*%+$!& ,-+(!#*,-$)& %)+ %#$!-*,&(7;>8<=:69435398657<>4;=:5:<94;=73>86","I 4 3 2":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-()(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,*","P 43 3 2":" !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(7;>46=:<5839398<5:6=4;>75:<983>7;=46","P 41 3 2":" !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(:3=8<>7694;5;54697<>83=:97654;=:3>8<","I 41 3 2":" !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(:3=8<>7694;5;54697<>83=:97654;=:3>8<()+$,#*!& %-+()#$,&*!- %)+(,#$!&*%- 7;>46=:<5839398<5:6=4;>75:<983>7;=46","P -4 3 m":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! #%$#!$&% & #!$#%$&! &%#! #%$&!$&% ","F -4 3 m":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! #%$#!$&% & #!$#%$&! &%#! #%$&!$&% )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-(!(+%*+!*-%(- +)$+,$-) -,#)(#,*&)*&,((!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&() +,$+)$-, -(#)*#,*&)(&,+!(+%*-!*-%(()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- )(#,*#)*&,(&(+!*+%*-!(-%+) +,$-)$-, ","I -4 3 m":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! #%$#!$&% & #!$#%$&! &%#! #%$&!$&% ()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-()(+,*+)*-,(-(+)*+,*-)(-,+)(+,*-)*-,(","P -4 3 n":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(+,*+)*-,(-(+)*+,*-)(-,+)(+,*-)*-,(","F -4 3 c":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(+,*+)*-,(-(+)*+,*-)(-,+)(+,*-)*-,( )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-() #,$#)$&, &(#!*#%*&!(&%+! +%$-!$-% (!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(!(#%*#!*&%(& +!$+%$-! -%#) #,$&)$&, ()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- ! +%$+!$-% - #)$#,$&) &,#!(#%*&!*&%(","I -4 3 d":" !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(7354<9:6>8;=357<946>:;=857394<>:6=8;()+$,#*!& %-+()#$,&*!- %)+(,#$!&*%- :;98657<=43>;9:658<=73>49:;586=7<>43","P 4/m -3 2/m":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$%$#! #% &!$&$&! &% #!$#%&% &!$#%$#! ","P 4/n -3 2/n":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$*,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*,*+)(+,(-)*-*-)(-,(+)*+,-,(-)*+,*+)(","P 42/m -3 2/n":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,*$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$,*+)(+,(-)*-*-)(-,(+)*+,-,(-)*+,*+)(","P 42/n -3 2/m":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,**,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*%$#! #% &!$&$&! &% #!$#%&% &!$#%$#! ","F 4/m -3 2/m":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$%$#! #% &!$&$&! &% #!$#%&% &!$#%$#! )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-(!(-%*-!*+%(+ +,$+)$-, -)#)*#,(&)(&,*$,- )- ,+$)+&*,&()#(,#*)%-*!-(%+(!+*%*+!(+%(-!*-$-) -, +)$+,&,(&)*#,*#)((!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&() -,$-)$+, +(#,*#)*&,(&)+!*+%(-!(-%**%-(!-(%+*!+-$,- )+ ,+$),&*)&(,#()#*,$+) +, -)$-*&)(&,(#)*#,-%(-!*+%*+!(()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- )(&,*&)*#,(#(+%*+!*-%(-!+)$+, -) -,$*,&()&(,#*)#-*%-(!+(%+*!,-$)- ,+ )+$,*#)(#,(&)*&*-!(-%(+!*+%-, -)$+,$+) ","F 4/m -3 2/c":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,*$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$,*+)(+,(-)*-*-)(-,(+)*+,-,(-)*+,*+)( )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-() &,$&)$#, #(#%*#!*&%(&!+!$+% -! -%$$,- )- ,+$)+&*,&()#(,#*)%-*!-(%+(!+*,$#) #, &)$&*&!(&%(#!*#%-% -!$+%$+! (!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(!(&%*&!*#%(# +%$+!$-% -!#)$#, &) &,$*%-(!-(%+*!+-$,- )+ ,+$),&*)&(,#()#*%*#!(#%(&!*&$-! -% +!$+%&, &)$#,$#) ()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- ! -%$-!$+% + #,$#)$&, &)#!*#%(&!(&%**,&()&(,#*)#-*%-(!+(%+*!,-$)- ,+ )+$%$+! +% -!$-$&) &, #)$#,&%(&!*#%*#!(","F 41/d -3 2/m":" !#$,+*)&(%-# !+$,&*)-(%!# ,+$)&*%-(:3>46=7<98;5;58<976=43>:97<58;>:3=4664=3:>;85<79=64>3:5;89<74=6:>385;79<,$+! #%(-)*&*&)(-% #!$+,-%(&)*+,$#! )+$%#*!-(,&#()+*%&$!- ,!+(,#*)-$%& :;=4<>765839;94<5:6>83=79:6543>7;=8<68>37=;49<:5=<8>;753496:4><:=;893756,*#!(+% &)$-*-!(&, +)$#%-, &!$+%*#)((!+*,#$)- %&+ )#$%-*!&(,)#(%+*!&$,- 73=86>:<54;935469:<=8;>7576983=:;>4<<4>;:=389675>68=379;45<:8=<7>;453:96%$#) +,(&!*-$&! -,(#)*+%&% -)$#,*+!(()#*%+$!& ,-+(!#*,-$)& %)+ %#$!-*,&(7;>8<=:69435398657<>4;=:5:<94;=73>86<8=;7>3456:9><4=;:9385678>67=349;:5<%*+)(#, -!$&$-) &%(+!*#,&,(-!*#%$+) ","F 41/d -3 2/c":" !#$,+*)&(%-# !+$,&*)-(%!# ,+$)&*%-(:3>46=7<98;5;58<976=43>:97<58;>:3=46<8>;7=3496:5><8=;793456:8><7=;493:56%*#)(+, &!$-$-! &,(+)*#%&, -!$#%*+)( )+$%#*!-(,&#()+*%&$!- ,!+(,#*)-$%& :;=4<>765839;94<5:6>83=79:6543>7;=8<<4=;:>385679>64=3:9;85<78=67>345;:9<%$+) #,(-!*&$&) -%(#!*+,&%(-)*#,$+! (!+*,#$)- %&+ )#$%-*!&(,)#(%+*!&$,- 73=86>:<54;935469:<=8;>7576983=:;>4<68=37>;45<:9=<4>;:5389674>6:=389;75<,*+!(#% -)$&*-)(&% +!$#,-,(&!*+%$#) ()#*%+$!& ,-+(!#*,-$)& %)+ %#$!-*,&(7;>8<=:69435398657<>4;=:5:<94;=73>8664>3:=;89<75=68>375;49<:4=<:>;853796,$#! +%(&)*-*&!(-, #)$+%-% &)$+,*#!(","I 4/m -3 2/m":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$%$#! #% &!$&$&! &% #!$#%&% &!$#%$#! ()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-()(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,**,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*,*+)(+,(-)*-*-)(-,(+)*+,-,(-)*+,*+)(","I 41/a -3 2/d":" !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(:3=8<>7694;5;54697<>83=:97654;=:3>8<$%&(!- ,+*)#&$%-(!+ ,#*)%&$!-(,+ )#*4<97358;=:6>6>:;=8357<94=8;>:694<573()+$,#*!& %-+()#$,&*!- %)+(,#$!&*%- 7;>46=:<5839398<5:6=4;>75:<983>7;=46*,- )&(%#$!+-*,& )#(%+$!,-*)& %#(!+$865:;943>7<=<=73>4;9:658>43=7<5869:;","P 1 1 2":" !#$%#","P 1 1 21":" !#$%+","B 1 1 2":" !#$%#(g+*%+","A 1 2 1":" !#$!& )+$)-","C 1 21 1":" !#$)&()#*!&","I 1 2 1":" !#$!&.'/0'2","I 1 21 1":" !#$)&.'/0!-","P 1 1 m":" !# !&","P 1 1 b":" !# )&","B 1 1 m":" !# !&(!+(!-","B 1 1 b":" !# )&(!+()-","P 1 1 2/m":" !# !&$%#$%&","P 1 1 21/m":" !#$%+$%& !-","B 1 1 2/m":" !# !&$%#$%&(!+(!-*%+*%-","P 1 1 2/b":" !#$,#$%& )&","P 1 1 21/b":" !#$%&$,+ )-","B 1 1 2/b":" !#$,#$%& )&(!+*,+*%-()-","P 21 2 2":" !#$!&(%&*%#","P 2 21 2":" !# ,&$)&$%#","P 21 21 2 (a)":" !#*,#.%&$'&","P 21 2 21":" !#$!&(%-*%+","P 2 21 21":" !# %&$)-$,+","C 2 2 21a)":" !#*%+(,&$)-()#$,+ %&*!-","C 2 2 2a":" !#*,#.%&$'&()#$%# ,&*!&","F 2 2 2a":" !#*,#.%&$'& '/*%/.12$!2.!/$,/ %20'2.'#$%# 1&0!&","I 2 2 2a":" !#*,#.%&$'&()+$%+*!- ,-","P 21/m 21/m 2/n a":" !#*,#$)&(%&$%&.'& ,#*!#","P 42 21 2a":" !#*,#%.+'$+$'&.%&! -,*-","I 2 3a":" !#*,#.%&$'&!# ,- '&$%/$# !-*!/$%&.%()+$%+ ,-*!-)+(%&(!-*,#*+()&$)#*,- ,"},Ea=/^[1-9]$/;function Fa(t){let e="";return t.length>0&&(e=":"+gt(t).join(" OR :")),new pe(e)}class La{constructor(t=""){this.name=t,this.partList=[]}get type(){return"Assembly"}addPart(t,e){const i=new Na(t,e);return this.partList.push(i),i}getAtomCount(t){return this.partList.reduce(((e,i)=>e+i.getAtomCount(t)),0)}getResidueCount(t){return this.partList.reduce(((e,i)=>e+i.getResidueCount(t)),0)}getInstanceCount(){let t=0;return this.partList.forEach((function(e){t+=e.matrixList.length})),t}isIdentity(t){if(1!==this.partList.length)return!1;const e=this.partList[0];if(1!==e.matrixList.length)return!1;if(!(new i).equals(e.matrixList[0]))return!1;let r=[];return t.eachChain((function(t){r.push(t.chainname)})),r=gt(r),e.chainList.length===r.length}getBoundingBox(t){const e=new a;return this.partList.forEach((function(i){const r=i.getBoundingBox(t);e.expandByPoint(r.min),e.expandByPoint(r.max)})),e}getCenter(t){return this.getBoundingBox(t).getCenter(new e)}getSelection(){let t=[];return this.partList.forEach((function(e){t=t.concat(e.chainList)})),Fa(t)}}class Na{constructor(t=[],e=[]){this.matrixList=t,this.chainList=e}get type(){return"AssemblyPart"}_getCount(t,e){let i=0;return t.eachChain((t=>{(0===this.chainList.length||this.chainList.includes(t.chainname))&&(i+=t[e])})),this.matrixList.length*i}getAtomCount(t){return this._getCount(t,"atomCount")}getResidueCount(t){return this._getCount(t,"residueCount")}getBoundingBox(t){const e=new a,i=new a,r=this.getSelection(),s=t.getBoundingBox(r);return this.matrixList.forEach((function(t){i.copy(s).applyMatrix4(t),e.expandByPoint(i.min),e.expandByPoint(i.max)})),e}getSelection(){return Fa(this.chainList)}getView(t){const e=this.getSelection();return e?t.getView(e):t}getInstanceList(){const t=[];for(let e=0,i=this.matrixList.length;e0&&this.addResidueType(this.ri-1),l.growIfFull(),l.resno[this.ri]=s,void 0!==o&&(l.sstruc[this.ri]=o.charCodeAt(0)),void 0!==a&&(l.inscode[this.ri]=a.charCodeAt(0)),l.atomOffset[this.ri]=this.ai,l.atomCount[this.ri]=0,l.count+=1,l.chainIndex[this.ri]=this.ci,h.residueCount[this.ci]+=1),c.count+=1,c.residueIndex[this.ai]=this.ri,l.atomCount[this.ri]+=1,this.currentModelindex=t,this.currentChainid=i,this.currentResname=r,this.currentResno=s,this.currentInscode=a,this.currentHetero=n}finalize(){this.previousResname=this.currentResname,this.previousHetero=this.currentHetero,this.ri>-1&&this.addResidueType(this.ri)}}function Va(t,e){if(!e)return;De&&Me.time("assignSecondaryStructure");const i=[];t.eachModel((function(t){t.eachChain((function(t){i.push(t.chainname)}))}));const r=i.slice().sort(),s=[];r.forEach((function(t){s.push(i.indexOf(t))}));const n=e.helices.filter((function(t){return pt(r,t[0])>=0}));n.sort((function(t,e){const i=t[0],n=e[0],o=t[1],a=e[1];if(i===n)return o===a?0:o=0}));a.sort((function(t,e){const i=t[0],n=e[0];if(i===n)return 0;const o=pt(r,i),a=pt(r,n);return s[o]=t.residueCount)continue;o.index=n+s,a.index=n+s+e,c.index=o.traceAtomIndex,l.index=a.traceAtomIndex;const h=c.distanceTo(l);if(Math.abs(h-i[e-2])>r)return!1}return!0},i=function(e,i){return t(e,i,[5.45,5.18,6.37],2.1)},r=function(e,i){return t(e,i,[6.1,10.4,13],1.42)};return function(t){De&&Me.time("calculateSecondaryStructure"),t.eachPolymer((function(t){if(t.residueCount<4)return;if(t.isCg())!function(t){const i=t.residueStore,r=t.residueIndexStart,s=new Pa(t).position,n=new e,o=new e;for(let e=0,a=t.residueCount;e1&&s.bending[e]<20&&(i.sstruc[r+e]="h".charCodeAt(0),i.sstruc[r+e+1]="h".charCodeAt(0))}}(t);else{if(!t.isProtein())return;!function(t){const e=t.residueStore,s=t.residueIndexStart;for(let n=0,o=t.residueCount;n=e;)i=Math.floor(i/e),s+=Ua[i%e],r+=1;return r>=5&&Me.warn("chainname overflow"),s}function Ha(t,e=!1){De&&Me.time("calculateChainnames");let i=!0;if(t.eachChain((function(t){t.chainname&&(i=!1)})),i){const i=t.modelStore,r=t.chainStore,s=t.residueStore,n=function(t,e,n,o){const a=r.count;for(let t=0;t{h.add(e),t.forEach((t=>{h.add(t)}))}))),t.eachResidue((function(t){if(!e&&l){const e=t.atomCount,s=t.atomOffset;if(e>500)return void Me.warn("more than 500 atoms, skip residue for auto-bonding",t.qualifiedName());if("auto"===i&&t.hetero)for(let e=t.atomOffset;e{u.forEach((i=>{e.push(t.clone().multiply(i))}))})),h.addPart(e)}else h.addPart(d);const m=new e,p=new La("SUPERCELL"),f=Array.prototype.concat.call(l(m.set(1,0,0)),l(m.set(0,1,0)),l(m.set(0,0,1)),l(m.set(-1,0,0)),l(m.set(0,-1,0)),l(m.set(0,0,-1)),l(m.set(1,1,0)),l(m.set(1,0,1)),l(m.set(0,1,1)),l(m.set(-1,-1,0)),l(m.set(-1,0,-1)),l(m.set(0,-1,-1)),l(m.set(1,-1,-1)),l(m.set(1,1,-1)),l(m.set(1,-1,1)),l(m.set(-1,1,1)),l(m.set(-1,-1,1)),l(m.set(-1,1,-1)),l(m.set(0,1,-1)),l(m.set(0,-1,1)),l(m.set(1,0,-1)),l(m.set(-1,0,1)),l(m.set(1,-1,0)),l(m.set(-1,1,0)),l(),l(m.set(1,1,1)),l(m.set(-1,-1,-1)));if(t.biomolDict.NCS){const t=[];f.forEach((function(e){u.forEach((function(i){t.push(e.clone().multiply(i))}))})),p.addPart(t)}else p.addPart(f);t.biomolDict.UNITCELL=h,t.biomolDict.SUPERCELL=p,De&&Me.timeEnd("buildUnitcellAssembly")}const Qa=["H","C","O","N","S","P"],Ja=["NA","CL","FE"];function tc(t){let e=t.toUpperCase(),i=0,r=0;for(let t=0;t0)break;++i}else r=t+1;(i>0||r=3&&-1!==Qa.indexOf(e[0])?e[0]:""}function ec(t){const e=t.bondHash,i=e.countArray,r=e.offsetArray,s=e.indexArray,n=t.getBondProxy();t.eachResidue((function(t){const e=t.residueType;if(void 0!==e.bonds)return;var o=t.atomOffset,a=[],c=[],l=[],h={};const d=o+t.atomCount;t.eachAtom((function(t){const e=t.index,u=r[e];for(let t=0,r=i[e];t=d)continue;let i=n.atomIndex2;if(i=d)continue;if(e>i){const t=i;i=e,e=t}const r=e+"|"+i;void 0===h[r]&&(h[r]=!0,a.push(e-o),c.push(i-o),l.push(n.bondOrder))}})),e.bonds={atomIndices1:a,atomIndices2:c,bondOrders:l}}))}function ic(t,...e){De&&Me.time("concatStructures");const i=new Cc(t,""),r=new za(i),s=i.atomStore,n=i.atomMap;s.addField("formalCharge",1,"int8"),s.addField("partialCharge",1,"float32");const o={};let a=0,c=0,l=0;e.forEach((t=>{t.eachAtom((t=>{s.growIfFull(),s.atomTypeId[a]=n.add(t.atomname,t.element),s.x[a]=t.x,s.y[a]=t.y,s.z[a]=t.z,s.serial[a]=t.serial,s.formalCharge[a]=t.formalCharge,s.partialCharge[a]=t.partialCharge,s.altloc[a]=t.altloc,s.occupancy[a]=t.occupancy,s.bfactor[a]=t.bfactor,r.addAtom(t.modelIndex+l,t.chainname,t.chainid,t.resname,t.resno,1===t.hetero,t.sstruc,t.inscode),o[t.index+c]=a,a+=1})),c+=t.atomStore.count,l+=t.modelStore.count}));const h=i.bondStore,d=i.getAtomProxy(),u=i.getAtomProxy();return c=0,e.forEach((t=>{t.eachBond((t=>{d.index=o[t.atomIndex1+c],u.index=o[t.atomIndex2+c],h.addBond(d,u,t.bondOrder)})),c+=t.atomStore.count})),r.finalize(),Ka(i,!0),Ya(i,!0),i.finalizeAtoms(),i.finalizeBonds(),ec(i),De&&Me.timeEnd("concatStructures"),i}const rc=[3,11,19,37,55,87],sc=[4,12,20,38,56,88],nc=[6,15,16,34],oc=[1,7,8,9,17,35,53],ac=[2,10,18,36,54,86],cc=[13,30,31,48,49,50,80,81,82,83,84,85,112],lc=[5,14,32,33,51,52,85],hc=[9,17,35,53,85];class dc{constructor(t,e,i){this.structure=t,this.atomname=e,i=i||tc(e),this.element=i,this.number=Xs[i]||0,this.vdw=Ys[this.number]||2,this.covalent=Ks[this.number]||1.6}getDefaultValence(){const t=Zs[this.number];return t?t[0]:-1}getValenceList(){return Zs[this.number]||[]}getOuterShellElectronCount(){return Qs[this.number]||2}isMetal(){return this.isAlkaliMetal()||this.isAlkalineEarthMetal()||this.isLanthanide()||this.isActinide()||this.isTransitionMetal()||this.isPostTransitionMetal()}isNonmetal(){return this.isDiatomicNonmetal()||this.isPolyatomicNonmetal()||this.isNobleGas()}isMetalloid(){return lc.includes(this.number)}isHalogen(){return hc.includes(this.number)}isDiatomicNonmetal(){return oc.includes(this.number)}isPolyatomicNonmetal(){return nc.includes(this.number)}isAlkaliMetal(){return rc.includes(this.number)}isAlkalineEarthMetal(){return sc.includes(this.number)}isNobleGas(){return ac.includes(this.number)}isTransitionMetal(){const t=this.number;return t>=21&&t<=29||t>=39&&t<=47||t>=72&&t<=79||t>=104&&t<=108}isPostTransitionMetal(){return cc.includes(this.number)}isLanthanide(){return this.number>=57&&this.number<=71}isActinide(){return this.number>=89&&this.number<=103}}class uc{constructor(t){this.structure=t,this.dict={},this.list=[],this.structure=t}add(t,e){const i=function(t,e){return t+"|"+e}(t=t.toUpperCase(),e=e?e.toUpperCase():tc(t));let r=this.dict[i];if(void 0===r){const s=new dc(this.structure,t,e);r=this.list.length,this.dict[i]=r,this.list.push(s)}return r}get(t){return this.list[t]}}class mc{constructor(t,e,i,r,s,n){this.structure=t,this.bondReferenceAtomIndices=[],this.resname=e,this.atomTypeIdList=i,this.hetero=r?1:0,this.chemCompType=s,this.bonds=n,this.atomCount=i.length,this.moleculeType=this.getMoleculeType(),this.backboneType=this.getBackboneType(0),this.backboneEndType=this.getBackboneType(-1),this.backboneStartType=this.getBackboneType(1),this.backboneIndexList=this.getBackboneIndexList();const o=mn[this.backboneType],a=mn[this.backboneStartType],c=mn[this.backboneEndType],l=this.getAtomIndexByName(o.trace);this.traceAtomIndex=st(l,-1);const h=this.getAtomIndexByName(o.direction1);this.direction1AtomIndex=st(h,-1);const d=this.getAtomIndexByName(o.direction2);this.direction2AtomIndex=st(d,-1);const u=this.getAtomIndexByName(a.backboneStart);this.backboneStartAtomIndex=st(u,-1);const m=this.getAtomIndexByName(c.backboneEnd);let p;this.backboneEndAtomIndex=st(m,-1),p=on.includes(e)?this.getAtomIndexByName("N1"):this.getAtomIndexByName("N3"),this.rungEndAtomIndex=st(p,-1)}getBackboneIndexList(){const t=[];let e;switch(this.moleculeType){case 3:e=dn;break;case 4:case 5:e=un;break;default:return t}const i=this.structure.atomMap,r=this.atomTypeIdList;for(let s=0,n=this.atomCount;s500)De&&Me.warn("more than 500 atoms, skip residue for auto-bonding",t.qualifiedName());else if(s>50){const e=new $a(t,!0),s=t.isCg()?1.2:2.3;for(let t=n;t=0||yc(t,e);this.rings={atomRings:t.atomRings,rings:t.rings}}isAromatic(t){return this.aromaticAtoms=this.getAromatic(t),1===this.aromaticAtoms[t.index-t.residueAtomOffset]}calculateAromatic(t){const e=this.aromaticAtoms=new Uint8Array(this.atomCount),i=this.getRings().rings,r=i.map((e=>function(t){if(t.some((t=>!pc.includes(t.number))))return!1;let e=0;const i=new ho(3,t.length),r=i.data;t.forEach((t=>{r[e+0]=t.x,r[e+1]=t.y,r[e+2]=t.z,e+=3}));return new ya(i).vecC.length()this.structure.getAtomProxy(e+t.atomOffset)))))),s=this.aromaticRings=[];i.forEach(((t,i)=>{r[i]&&(s.push(t),t.forEach((t=>e[t]=1)))}))}assignBondReferenceAtomIndices(){const t=this.getBondGraph(),e=this.getRings(),i=e.atomRings,r=e.rings,s=this.bonds,n=s.atomIndices1,o=s.atomIndices2,a=s.bondOrders,c=this.bondReferenceAtomIndices,l=s.atomIndices1.length;c.length=0;for(let e=0;e1)for(let i=0;i1)for(let i=0;i=0;t--)p[f++]=o[t];const g=t.rings.length;for(let e=0;e0?n[c]!==e&&n[e]!==c&&gc(t,e,c):(r[c]=1,s[a++]=c,n[c]=e)}}}const bc=4;class xc{constructor(t){this.structure=t,this.dict={},this.list=[]}add(t,e,i,r="",s){const n=function(t,e,i,r=""){return t+"|"+e.join(",")+"|"+(i?1:0)+"|"+r}(t=t.toUpperCase(),e,i,r);let o=this.dict[n];if(void 0===o){const a=new mc(this.structure,t,e,i,r,s);o=this.list.length,this.dict[n]=o,this.list.push(a)}return o}get(t){return this.list[t]}}class vc{constructor(t,i=0){this.structure=t,this.index=i,this.bondStore=t.bondStore,this._v12=new e,this._v13=new e,this._ap1=this.structure.getAtomProxy(),this._ap2=this.structure.getAtomProxy(),this._ap3=this.structure.getAtomProxy()}get atom1(){return this.structure.getAtomProxy(this.atomIndex1)}get atom2(){return this.structure.getAtomProxy(this.atomIndex2)}get atomIndex1(){return this.bondStore.atomIndex1[this.index]}set atomIndex1(t){this.bondStore.atomIndex1[this.index]=t}get atomIndex2(){return this.bondStore.atomIndex2[this.index]}set atomIndex2(t){this.bondStore.atomIndex2[this.index]=t}get bondOrder(){return this.bondStore.bondOrder[this.index]}set bondOrder(t){this.bondStore.bondOrder[this.index]=t}getOtherAtomIndex(t){return t===this.atomIndex1?this.atomIndex2:this.atomIndex1}getOtherAtom(t){return this.structure.getAtomProxy(this.getOtherAtomIndex(t.index))}getReferenceAtomIndex(){const t=this._ap1,e=this._ap2;if(t.index=this.atomIndex1,e.index=this.atomIndex2,t.residueIndex!==e.residueIndex)return;const i=t.index-t.residueAtomOffset,r=e.index-e.residueAtomOffset,s=t.residueType.getBondReferenceAtomIndex(i,r);if(void 0!==s)return s+t.residueAtomOffset;console.warn("No reference atom found",t.index,e.index)}calculateShiftDir(t=new e){const i=this._ap1,r=this._ap2,s=this._ap3,n=this._v12,o=this._v13;i.index=this.atomIndex1,r.index=this.atomIndex2;const a=this.getReferenceAtomIndex();n.subVectors(i,r).normalize(),void 0!==a?(s.index=a,o.subVectors(i,s)):o.copy(i),o.normalize();let c=n.dot(o);return 1-Math.abs(c)<1e-5&&(o.set(1,0,0),c=n.dot(o),1-Math.abs(c)<1e-5&&(o.set(0,1,0),c=n.dot(o))),t.copy(o.sub(n.multiplyScalar(c))).normalize()}qualifiedName(){return this.atomIndex1+"="+this.atomIndex2}clone(){return new vc(this.structure,this.index)}toObject(){return{atomIndex1:this.atomIndex1,atomIndex2:this.atomIndex2,bondOrder:this.bondOrder}}}class wc{constructor(t,e=0){this.structure=t,this.index=e,this.chainStore=t.chainStore,this.residueStore=t.residueStore,this.atomStore=t.atomStore,this.residueMap=t.residueMap,this.atomMap=t.atomMap}get entity(){return this.structure.entityList[this.entityIndex]}get entityIndex(){return this.chainStore.entityIndex[this.chainIndex]}get chain(){return this.structure.getChainProxy(this.chainIndex)}get chainIndex(){return this.residueStore.chainIndex[this.index]}set chainIndex(t){this.residueStore.chainIndex[this.index]=t}get atomOffset(){return this.residueStore.atomOffset[this.index]}set atomOffset(t){this.residueStore.atomOffset[this.index]=t}get atomCount(){return this.residueStore.atomCount[this.index]}set atomCount(t){this.residueStore.atomCount[this.index]=t}get atomEnd(){return this.atomOffset+this.atomCount-1}get modelIndex(){return this.chainStore.modelIndex[this.chainIndex]}get chainname(){return this.chainStore.getChainname(this.chainIndex)}get chainid(){return this.chainStore.getChainid(this.chainIndex)}get resno(){return this.residueStore.resno[this.index]}set resno(t){this.residueStore.resno[this.index]=t}get sstruc(){return this.residueStore.getSstruc(this.index)}set sstruc(t){this.residueStore.setSstruc(this.index,t)}get inscode(){return this.residueStore.getInscode(this.index)}set inscode(t){this.residueStore.setInscode(this.index,t)}get residueType(){return this.residueMap.get(this.residueStore.residueTypeId[this.index])}get resname(){return this.residueType.resname}get hetero(){return this.residueType.hetero}get moleculeType(){return this.residueType.moleculeType}get backboneType(){return this.residueType.backboneType}get backboneStartType(){return this.residueType.backboneStartType}get backboneEndType(){return this.residueType.backboneEndType}get traceAtomIndex(){return this.residueType.traceAtomIndex+this.atomOffset}get direction1AtomIndex(){return this.residueType.direction1AtomIndex+this.atomOffset}get direction2AtomIndex(){return this.residueType.direction2AtomIndex+this.atomOffset}get backboneStartAtomIndex(){return this.residueType.backboneStartAtomIndex+this.atomOffset}get backboneEndAtomIndex(){return this.residueType.backboneEndAtomIndex+this.atomOffset}get rungEndAtomIndex(){return this.residueType.rungEndAtomIndex+this.atomOffset}get x(){let t=0;for(let e=this.atomOffset;e<=this.atomEnd;++e)t+=this.atomStore.x[e];return t/this.atomCount}get y(){let t=0;for(let e=this.atomOffset;e<=this.atomEnd;++e)t+=this.atomStore.y[e];return t/this.atomCount}get z(){let t=0;for(let e=this.atomOffset;e<=this.atomEnd;++e)t+=this.atomStore.z[e];return t/this.atomCount}eachAtom(t,e){const i=this.atomCount,r=this.atomOffset,s=this.structure._ap,n=r+i;if(e&&e.atomOnlyTest){const i=e.atomOnlyTest;for(let e=r;e0)return this.entity.isPolymer();{const t=this.residueType.moleculeType;return 3===t||4===t||5===t}}isHetero(){return 1===this.residueType.hetero}isWater(){return 1===this.residueType.moleculeType}isIon(){return 2===this.residueType.moleculeType}isSaccharide(){return 6===this.residueType.moleculeType}isStandardAminoacid(){return this.residueType.isStandardAminoacid()}isStandardBase(){return this.residueType.isStandardBase()}isHelix(){return Hs.includes(this.sstruc)}isSheet(){return Ws.includes(this.sstruc)}isTurn(){return qs.includes(this.sstruc)&&this.isProtein()}getAtomType(t){return this.atomMap.get(this.atomStore.atomTypeId[t])}getResname1(){return en[this.resname.toUpperCase()]||"X"}getBackboneType(t){switch(t){case-1:return this.residueType.backboneStartType;case 1:return this.residueType.backboneEndType;default:return this.residueType.backboneType}}getAtomIndexByName(t){let e=this.residueType.getAtomIndexByName(t);return void 0!==e&&(e+=this.atomOffset),e}hasAtomWithName(t){return this.residueType.hasAtomWithName(t)}getAtomnameList(){console.warn("getAtomnameList - might be expensive");const t=this.atomCount,e=this.atomOffset,i=new Array(t);for(let r=0;r=e){const e=st(t,this.structure.getResidueProxy());if(e.index=i,e.connectedTo(this))return e}else if(i===e-1){const i=this.chainStore.residueCount[this.chainIndex],r=st(t,this.structure.getResidueProxy());if(r.index=e+i-1,r.connectedTo(this))return r}}getBonds(){return this.residueType.getBonds(this)}getRings(){return this.residueType.getRings()}getAromaticRings(){return this.residueType.getAromaticRings(this)}qualifiedName(t=!1){let e="";return this.resname&&!t&&(e+="["+this.resname+"]"),void 0!==this.resno&&(e+=this.resno),this.inscode&&(e+="^"+this.inscode),this.chain&&(e+=":"+this.chainname),e+="/"+this.modelIndex,e}clone(){return new wc(this.structure,this.index)}toObject(){return{index:this.index,chainIndex:this.chainIndex,atomOffset:this.atomOffset,atomCount:this.atomCount,resno:this.resno,resname:this.resname,sstruc:this.sstruc}}}class Ac{constructor(t,e,i){this.structure=t,this.residueIndexStart=e,this.residueIndexEnd=i,this.chainStore=t.chainStore,this.residueStore=t.residueStore,this.atomStore=t.atomStore,this.residueCount=i-e+1;const r=this.structure.getResidueProxy(this.residueIndexStart),s=this.structure.getResidueProxy(this.residueIndexEnd);this.isPrevConnected=void 0!==r.getPreviousConnectedResidue();const n=s.getNextConnectedResidue();this.isNextConnected=void 0!==n,this.isNextNextConnected=void 0!==n&&void 0!==n.getNextConnectedResidue(),this.isCyclic=s.connectedTo(r),this.__residueProxy=this.structure.getResidueProxy()}get chainIndex(){return this.residueStore.chainIndex[this.residueIndexStart]}get modelIndex(){return this.chainStore.modelIndex[this.chainIndex]}get chainname(){return this.chainStore.getChainname(this.chainIndex)}isProtein(){return this.__residueProxy.index=this.residueIndexStart,this.__residueProxy.isProtein()}isCg(){return this.__residueProxy.index=this.residueIndexStart,this.__residueProxy.isCg()}isNucleic(){return this.__residueProxy.index=this.residueIndexStart,this.__residueProxy.isNucleic()}getMoleculeType(){return this.__residueProxy.index=this.residueIndexStart,this.__residueProxy.moleculeType}getBackboneType(t){return this.__residueProxy.index=this.residueIndexStart,this.__residueProxy.getBackboneType(t)}getAtomIndexByType(t,e){this.isCyclic?-1===t?t=this.residueCount-1:t===this.residueCount&&(t=0):(-1!==t||this.isPrevConnected||(t+=1),t!==this.residueCount||this.isNextNextConnected||(t-=1));const i=this.__residueProxy;let r;switch(i.index=this.residueIndexStart+t,e){case"trace":r=i.traceAtomIndex;break;case"direction1":r=i.direction1AtomIndex;break;case"direction2":r=i.direction2AtomIndex;break;default:r=i.getAtomIndexByName(e)}return r}eachAtom(t,e){this.eachResidue((function(i){i.eachAtom(t,e)}))}eachAtomN(t,e,i){const r=this.residueCount,s=new Array(t);for(let e=0;e1&&t(new Ac(n,i,l.index)),i=r)):(o!==Ns&&l.index-i>1&&t(new Ac(n,i,l.index)),i=r)}r-i>1&&this.structure.getResidueProxy(i).backboneEndType&&t(new Ac(n,i,r))}qualifiedName(){return":"+this.chainname+"/"+this.modelIndex}clone(){return new _c(this.structure,this.index)}toObject(){return{index:this.index,residueOffset:this.residueOffset,residueCount:this.residueCount,chainname:this.chainname}}}class Sc{constructor(t,e=0){this.structure=t,this.index=e,this.modelStore=t.modelStore,this.chainStore=t.chainStore,this.residueStore=t.residueStore}get chainOffset(){return this.modelStore.chainOffset[this.index]}set chainOffset(t){this.modelStore.chainOffset[this.index]=t}get chainCount(){return this.modelStore.chainCount[this.index]}set chainCount(t){this.modelStore.chainCount[this.index]=t}get residueOffset(){return this.chainStore.residueOffset[this.chainOffset]}get atomOffset(){return this.residueStore.atomOffset[this.residueOffset]}get chainEnd(){return this.chainOffset+this.chainCount-1}get residueEnd(){return this.chainStore.residueOffset[this.chainEnd]+this.chainStore.residueCount[this.chainEnd]-1}get atomEnd(){return this.residueStore.atomOffset[this.residueEnd]+this.residueStore.atomCount[this.residueEnd]-1}get residueCount(){return 0===this.chainCount?0:this.residueEnd-this.residueOffset+1}get atomCount(){return 0===this.residueCount?0:this.atomEnd-this.atomOffset+1}eachAtom(t,e){this.eachChain((function(i){i.eachAtom(t,e)}),e)}eachResidue(t,e){this.eachChain((function(i){i.eachResidue(t,e)}),e)}eachPolymer(t,e){if(e&&e.chainOnlyTest){const i=e.chainOnlyTest;this.eachChain((function(r){i(r)&&r.eachPolymer(t,e)}))}else this.eachChain((function(i){i.eachPolymer(t,e)}))}eachChain(t,e){const i=this.chainCount,r=this.chainOffset,s=this.structure._cp,n=r+i;if(e&&e.test){const i=e.chainOnlyTest;if(i)for(let e=r;e{const i=3*e;a.index=t,l&&a.positionToArray(l,i),h&&n.atomColorToArray(a,h,i),d&&(d.array[e]=t),u&&(u[e]=s.atomRadius(a)),m&&(m[e]=t)})),o}getBondData(t){const i=Object.assign({},t);i.colorParams&&(i.colorParams.structure=this.getStructure());const r=i.what,s=st(i.bondSet,this.bondSet),n=st(i.multipleBond,"off"),o="off"!==n,a="offset"===n,c=st(i.bondScale,.4),l=st(i.bondSpacing,1);let h,d;const u={},m=this.getBondProxy();i.bondStore&&(m.bondStore=i.bondStore);const p=this.getAtomProxy(),f=this.getAtomProxy();let g;if(o){const t=m.bondStore.bondOrder;g=0,s.forEach((function(e){g+=t[e]}))}else g=s.getSize();r&&!r.position||(u.position1=new Float32Array(3*g),u.position2=new Float32Array(3*g)),r&&!r.color||!i.colorParams||(u.color=new Float32Array(3*g),u.color2=new Float32Array(3*g),d=Fe.getScheme(i.colorParams)),r&&!r.picking||(u.picking=new Zn(new Float32Array(g),this.getStructure(),i.bondStore)),(!r||r.radius||o&&r.position)&&(h=new pa(i.radiusParams)),r&&!r.radius||(u.radius=new Float32Array(g),i.radius2&&(u.radius2=new Float32Array(g)));const{position1:y,position2:b,color:x,color2:v,picking:w,radius:A,radius2:_}=u;let S,C,P,I,k,M,T=0;const B=new e,D=new e,$=new e;return s.forEach((t=>{if(C=3*T,m.index=t,p.index=m.atomIndex1,f.index=m.atomIndex2,I=m.bondOrder,y)if(o&&I>1){const t=h.atomRadius(p);M=t*c/(.5*I),m.calculateShiftDir($),a?(k=2*l*t,$.multiplyScalar(k),$.negate(),D.subVectors(f,p).multiplyScalar(Math.max(.1,k/1.88)),p.positionToArray(y,C),f.positionToArray(b,C),I>=2&&(B.addVectors(p,$).add(D).toArray(y,C+3),B.addVectors(f,$).sub(D).toArray(b,C+3),I>=3&&(B.subVectors(p,$).add(D).toArray(y,C+6),B.subVectors(f,$).sub(D).toArray(b,C+6)))):(k=(l-c)*t,$.multiplyScalar(k),2===I?(B.addVectors(p,$).toArray(y,C),B.subVectors(p,$).toArray(y,C+3),B.addVectors(f,$).toArray(b,C),B.subVectors(f,$).toArray(b,C+3)):3===I?(p.positionToArray(y,C),B.addVectors(p,$).toArray(y,C+3),B.subVectors(p,$).toArray(y,C+6),f.positionToArray(b,C),B.addVectors(f,$).toArray(b,C+3),B.subVectors(f,$).toArray(b,C+6)):(p.positionToArray(y,C),f.positionToArray(b,C)))}else p.positionToArray(y,C),f.positionToArray(b,C);if(x&&v&&(d.bondColorToArray(m,1,x,C),d.bondColorToArray(m,0,v,C),o&&I>1))for(S=1;S1))for(S=1;S1))for(M=A[T]*c/(a?1:.5*I),S=a?1:0;S1))for(M=_[T]*c/(a?1:.5*I),S=a?1:0;S{const e=t.x,a=t.y,l=t.z;en&&(n=e),a>o&&(o=a),l>c&&(c=l)}),t),e.min.set(i,r,s),e.max.set(n,o,c),De&&Me.timeEnd("getBoundingBox"),e}getPrincipalAxes(t){De&&Me.time("getPrincipalAxes");let e=0;const i=new ho(3,this.atomCount),r=i.data;return this.eachAtom((t=>{r[e+0]=t.x,r[e+1]=t.y,r[e+2]=t.z,e+=3}),t),De&&Me.timeEnd("getPrincipalAxes"),new ya(i)}atomCenter(t){return t?this.getBoundingBox(t).getCenter(new e):this.center.clone()}hasCoords(){if(void 0===this._hasCoords){const t=this.atomStore;this._hasCoords=0!==Di(t.x)||0!==Bi(t.x)||0!==Di(t.y)||0!==Bi(t.y)||0!==Di(t.z)||0!==Bi(t.z)||t.count/this.modelStore.count==1}return this._hasCoords}getSequence(t){const e=[],i=this.getResidueProxy();return this.eachAtom((function(t){i.index=t.residueIndex,t.index===i.traceAtomIndex&&e.push(i.getResname1())}),t),e}getAtomIndices(t){if(t&&t.string){const e=[];return this.eachAtom((function(t){e.push(t.index)}),t),new Uint32Array(e)}{const t={what:{index:!0}};return this.getAtomData(t).index}}getChainnameCount(t){const e=new Set;return this.eachChain((function(t){t.residueCount&&e.add(t.chainname)}),t),e.size}updatePosition(t,e=!0){let i=0;this.eachAtom((function(e){e.positionFromArray(t,i),i+=3}),void 0),this._hasCoords=void 0,e&&this.refreshPosition()}refreshPosition(){this.getBoundingBox(void 0,this.boundingBox),this.boundingBox.getCenter(this.center),this.spatialHash=new Ts(this.atomStore,this.boundingBox),this.signals.refreshed.dispatch(this)}dispose(){this.frames&&(this.frames.length=0),this.boxes&&(this.boxes.length=0),this.bondStore.dispose(),this.backboneBondStore.dispose(),this.rungBondStore.dispose(),this.atomStore.dispose(),this.residueStore.dispose(),this.chainStore.dispose(),this.modelStore.dispose(),delete this.bondSet,delete this.atomSet}}const Pc=new a,Ic=[_s,xs,Ss,As,Cs,vs,bs,ws,Is,Ps,ks,Ms],kc={aspectRatio:1.5,sphereDetail:2,radialSegments:50,disableImpostor:!1,openEnded:!1,dashedCylinder:!1,labelParams:{},pointSize:2,sizeAttenuation:!1,useTexture:!0,linewidth:2};class Mc{constructor(t="shape",e={}){this.boundingBox=new a,this.bufferList=[],this.meshCount=0,this._primitiveData={},this.name=t,this.parameters=nt(e,kc),Ic.forEach((t=>{Object.keys(t.fields).forEach((e=>{this._primitiveData[t.getShapeKey(e)]=[]})),this._primitiveData[t.getShapeKey("name")]=[]}))}addBuffer(t){this.bufferList.push(t);const e=t.geometry;return e.boundingBox||e.computeBoundingBox(),this.boundingBox.union(e.boundingBox),this}addMesh(t,e,i,r,s){let n;t=Ct(t),e=Ct(e),Array.isArray(i)&&(i=xt(i,t.length)),r&&(r=Ct(r)),n=void 0===r||0==r.length?{position:t,color:e,index:i}:{position:t,color:e,index:i,normal:r};const o=new io(this,Object.assign({serial:this.meshCount,name:s},n)),a=new Uo(Object.assign({picking:o},n));return this.bufferList.push(a),Pc.setFromArray(t),this.boundingBox.union(Pc),this.meshCount+=1,this}addSphere(t,e,i,r){return bs.objectToShape(this,{position:t,color:e,radius:i,name:r}),this}addEllipsoid(t,e,i,r,s,n){return Cs.objectToShape(this,{position:t,color:e,radius:i,majorAxis:r,minorAxis:s,name:n}),this}addTorus(t,e,i,r,s,n){return Ps.objectToShape(this,{position:t,color:e,radius:i,majorAxis:r,minorAxis:s,name:n}),this}addCylinder(t,e,i,r,s){return As.objectToShape(this,{position1:t,position2:e,color:i,radius:r,name:s}),this}addCone(t,e,i,r,s){return Ss.objectToShape(this,{position1:t,position2:e,color:i,radius:r,name:s}),this}addArrow(t,e,i,r,s){return _s.objectToShape(this,{position1:t,position2:e,color:i,radius:r,name:s}),this}addBox(t,e,i,r,s,n){return xs.objectToShape(this,{position:t,color:e,size:i,heightAxis:r,depthAxis:s,name:n}),this}addOctahedron(t,e,i,r,s,n){return vs.objectToShape(this,{position:t,color:e,size:i,heightAxis:r,depthAxis:s,name:n}),this}addTetrahedron(t,e,i,r,s,n){return ws.objectToShape(this,{position:t,color:e,size:i,heightAxis:r,depthAxis:s,name:n}),this}addText(t,e,i,r){return Is.objectToShape(this,{position:t,color:e,size:i,text:r}),this}addPoint(t,e,i){return ks.objectToShape(this,{position:t,color:e,name:i}),this}addWideline(t,e,i,r,s){return this.parameters.linewidth=r,Ms.objectToShape(this,{position1:t,position2:e,color:i,name:s}),this}addLabel(t,e,i,r){return console.warn("Shape.addLabel is deprecated, use .addText instead"),this.addText(t,e,i,r)}getBufferList(){const t=[];return Ic.forEach((e=>{this._primitiveData[e.getShapeKey("color")].length&&t.push(e.bufferFromShape(this,this.parameters))})),this.bufferList.concat(t)}dispose(){this.bufferList.forEach((function(t){t.dispose()})),this.bufferList.length=0,Ic.forEach((t=>{Object.keys(t.fields).forEach((e=>{this._primitiveData[t.getShapeKey(e)].length=0})),this._primitiveData[t.getShapeKey("name")].length=0}))}get center(){return this._center||(this._center=this.boundingBox.getCenter(new e)),this._center}get type(){return"Shape"}}class Tc extends zr{constructor(t,e,i){Array.isArray(t)||(t=[t]),super(t,e,i),this.type="buffer",this.parameters=Object.assign({},this.parameters,{colorScheme:null,colorScale:null,colorValue:null,colorDomain:null,colorMode:null}),this.buffer=t,this.init(i)}init(t){super.init(t),this.build()}create(){this.bufferList.push.apply(this.bufferList,this.buffer)}attach(t){this.bufferList.forEach((t=>{this.viewer.add(t),t.setParameters(this.getBufferParams())})),this.setVisibility(this.visible),t()}}const Bc=new i,Dc=new O;class $c extends Uo{constructor(t,e={},i){super(function(t,e){const i=e.attributes.position.array,r=e.index?e.index.array:void 0,s=t.position.length/3,n=i.length/3,o=s*n,a=new Float32Array(3*o),c=new Float32Array(3*o),l=new Float32Array(3*o);let h;return r&&(h=xt(s*r.length,o)),{position:a,color:l,index:h,normal:c,primitiveId:t.primitiveId||Ii(s,n),picking:t.picking}}(t,i),e),this.updateNormals=!1;const r=i.attributes.position.array,s=i.attributes.normal.array,n=i.index?i.index.array:void 0;this.geoPosition=r,this.geoNormal=s,this.geoIndex=n,this.positionCount=t.position.length/3,this.geoPositionCount=r.length/3,this.transformedGeoPosition=new Float32Array(3*this.geoPositionCount),this.transformedGeoNormal=new Float32Array(3*this.geoPositionCount);const o=this.geometry.attributes;if(this.meshPosition=o.position.array,this.meshColor=o.color.array,this.meshNormal=o.normal.array,this.setAttributes(t),n){const t=this.geometry.getIndex();if(!t)return void Me.error("Index is null");this.meshIndex=t.array,this.makeIndex()}}setAttributes(t={},e=!1){const i=this.geometry.attributes;let r,s,n,o,a,c,l,h,d;const u=this.updateNormals;t.position&&(r=t.position,n=this.geoPosition,l=this.meshPosition,a=this.transformedGeoPosition,i.position.needsUpdate=!0,(u||e)&&(o=this.geoNormal,d=this.meshNormal,c=this.transformedGeoNormal,i.normal.needsUpdate=!0)),t.color&&(s=t.color,h=this.meshColor,i.color.needsUpdate=!0);const m=this.positionCount,p=this.geoPositionCount;for(let t=0;t 0.0 ){\ncameraPos = rayDirection * posT + rayOrigin;\ninterior = true;\nflag2 = true;\n}\n#else\nif( calcDepth( cameraPos ) <= 0.0 ){\ncameraPos = rayDirection * posT + rayOrigin;\ninterior = true;\n}\n#endif\ncameraNormal = normalize( cameraPos - cameraSpherePos );\ncameraNormal *= float(!interior) * 2.0 - 1.0;\nreturn !interior;\n}\nvoid main(void){\nbool flag = Impostor( cameraPos, cameraNormal );\n#ifdef NEAR_CLIP\nif( calcClip( cameraPos ) > 0.0 )\ndiscard;\n#endif\ngl_FragDepthEXT = calcDepth( cameraPos );\nif( !flag ){\n#ifdef NEAR_CLIP\nif( flag2 ){\ngl_FragDepthEXT = max( 0.0, calcDepth( vec3( - ( clipNear - 0.5 ) ) ) + ( 0.0000001 / vRadius ) );\n}else if( gl_FragDepthEXT >= 0.0 ){\ngl_FragDepthEXT = 0.0 + ( 0.0000001 / vRadius );\n}\n#else\nif( gl_FragDepthEXT >= 0.0 ){\ngl_FragDepthEXT = 0.0 + ( 0.0000001 / vRadius );\n}\n#endif\n}\nif (gl_FragDepthEXT < 0.0)\ndiscard;\nif (gl_FragDepthEXT > 1.0)\ndiscard;\n#ifdef PICKING\nif( opacity < 0.3 )\ndiscard;\ngl_FragColor = vec4( vPickingColor, objectId );\n#else\nvec3 vNormal = cameraNormal;\nvec3 vViewPosition = -cameraPos;\nvec4 diffuseColor = vec4( diffuse, opacity );\nReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\nvec3 totalEmissiveLight = emissive;\n#include color_fragment\n#include roughnessmap_fragment\n#include metalnessmap_fragment\n#include normal_fragment_begin\n#include lights_physical_fragment\n#include lights_fragment_begin\n#include lights_fragment_end\nvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveLight;\nif( interior ){\n#ifdef USE_INTERIOR_COLOR\noutgoingLight.xyz = interiorColor;\n#else\n#ifdef DIFFUSE_INTERIOR\noutgoingLight.xyz = vColor;\n#endif\n#endif\noutgoingLight.xyz *= 1.0 - interiorDarkening;\n}\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );\n#include premultiplied_alpha_fragment\n#include tonemapping_fragment\n#include encodings_fragment\n#include fog_fragment\n#endif\n}");class Fc extends Go{constructor(t,e,i={}){super(e,i),this.index=xt(this.indexSize,this.attributeSize),this.makeIndex(),this.initIndex(this.index),this.addAttributes({mapping:{type:t,value:null}}),this.setAttributes({primitiveId:Pi(this.size)})}get attributeSize(){return this.size*this.mappingSize}get indexSize(){return this.size*this.mappingIndicesSize}addAttributes(t){const e={};for(const i in t){const r=t[i];e[i]={type:r.type,value:null}}super.addAttributes(e)}getAttributeIndex(t){return 3*t*this.mappingSize}setAttributes(t){t&&!t.position&&t.position1&&t.position2&&(t.position=Ai(t.position1,t.position2));const e=this.size,i=this.mappingSize,r=this.geometry.attributes;let s,n,o,a,c,l,h;for(const d in t)if("index"!==d&&"picking"!==d){n=t[d],s=r[d],o=s.itemSize,a=s.array;for(let t=0;t0&&this.parameters.alphaTest<=1&&(e.ALPHATEST=this.parameters.alphaTest.toPrecision(2)),e}setUniforms(t){t&&void 0!==t.edgeBleach&&(this.makeTexture(),t.map=this.tex),super.setUniforms(t)}dispose(){super.dispose(),this.tex&&this.tex.dispose()}}je.add("point",Wc);class qc extends zr{constructor(t,e,i){super(t,e,i),this.type="dot",this.parameters=Object.assign({thresholdType:{type:"select",rebuild:!0,options:{value:"value",sigma:"sigma"}},thresholdMin:{type:"number",precision:3,max:1/0,min:-1/0,rebuild:!0},thresholdMax:{type:"number",precision:3,max:1/0,min:-1/0,rebuild:!0},thresholdOut:{type:"boolean",rebuild:!0},dotType:{type:"select",rebuild:!0,options:{"":"",sphere:"sphere",point:"point"}},radiusType:{type:"select",options:{"":"",value:"value","abs-value":"abs-value","value-min":"value-min",deviation:"deviation",size:"size"}},radius:{type:"number",precision:3,max:10,min:.001,property:"size"},scale:{type:"number",precision:3,max:10,min:.001},sphereDetail:!0,disableImpostor:!0,pointSize:{type:"number",precision:1,max:100,min:0,buffer:!0},sizeAttenuation:{type:"boolean",buffer:!0},sortParticles:{type:"boolean",rebuild:!0},useTexture:{type:"boolean",buffer:!0},alphaTest:{type:"range",step:.001,max:1,min:0,buffer:!0},forceTransparent:{type:"boolean",buffer:!0},edgeBleach:{type:"range",step:.001,max:1,min:0,buffer:!0}},this.parameters,{colorScheme:{type:"select",update:"color",options:{"":"",value:"value",uniform:"uniform",random:"random"}}}),t instanceof Eo?(this.surface=void 0,this.volume=new ba(t)):(this.surface=t,this.volume=void 0),this.init(i)}init(t){var e=t||{};e.colorScheme=st(e.colorScheme,"uniform"),e.colorValue=st(e.colorValue,14540253),this.thresholdType=st(e.thresholdType,"sigma"),this.thresholdMin=st(e.thresholdMin,2),this.thresholdMax=st(e.thresholdMax,1/0),this.thresholdOut=st(e.thresholdOut,!1),this.dotType=st(e.dotType,"point"),this.radius=st(e.radius,.1),this.scale=st(e.scale,1),this.pointSize=st(e.pointSize,1),this.sizeAttenuation=st(e.sizeAttenuation,!0),this.sortParticles=st(e.sortParticles,!1),this.useTexture=st(e.useTexture,!1),this.alphaTest=st(e.alphaTest,.5),this.forceTransparent=st(e.forceTransparent,!1),this.edgeBleach=st(e.edgeBleach,0),super.init(e),this.build()}attach(t){this.bufferList.forEach((t=>{this.viewer.add(t)})),this.setVisibility(this.visible),t()}create(){var t={};if(this.volume){var e,i,r=this.volume;"sigma"===this.thresholdType?(e=r.getValueForSigma(this.thresholdMin),i=r.getValueForSigma(this.thresholdMax)):(e=this.thresholdMin,i=this.thresholdMax),r.setFilter(e,i,this.thresholdOut),Object.assign(t,{position:r.getDataPosition(),color:r.getDataColor(this.getColorParams())}),"sphere"===this.dotType&&Object.assign(t,{radius:r.getDataSize(this.radius,this.scale),picking:r.getDataPicking()})}else{var s=this.surface;Object.assign(t,{position:s.getPosition(),color:s.getColor(this.getColorParams())}),"sphere"===this.dotType&&Object.assign(t,{radius:s.getSize(this.radius,this.scale),picking:s.getPicking()})}"sphere"===this.dotType?this.dotBuffer=new Gc(t,this.getBufferParams({sphereDetail:this.sphereDetail,disableImpostor:this.disableImpostor,dullInterior:!1})):this.dotBuffer=new Wc(t,this.getBufferParams({pointSize:this.pointSize,sizeAttenuation:this.sizeAttenuation,sortParticles:this.sortParticles,useTexture:this.useTexture,alphaTest:this.alphaTest,forceTransparent:this.forceTransparent,edgeBleach:this.edgeBleach})),this.bufferList.push(this.dotBuffer)}update(t={}){if(0===this.bufferList.length)return;const e={};t.color&&(this.volume?Object.assign(e,{color:this.volume.getDataColor(this.getColorParams())}):Object.assign(e,{color:this.surface.getColor(this.getColorParams())})),"sphere"===this.dotType&&(t.radius||t.scale)&&(this.volume?Object.assign(e,{radius:this.volume.getDataSize(this.radius,this.scale)}):Object.assign(e,{radius:this.surface.getSize(this.radius,this.scale)})),this.dotBuffer.setAttributes(e)}setParameters(t,e={},i){return t&&void 0!==t.thresholdType&&this.volume instanceof Eo&&("value"===this.thresholdType&&"sigma"===t.thresholdType?(this.thresholdMin=this.volume.getSigmaForValue(this.thresholdMin),this.thresholdMax=this.volume.getSigmaForValue(this.thresholdMax)):"sigma"===this.thresholdType&&"value"===t.thresholdType&&(this.thresholdMin=this.volume.getValueForSigma(this.thresholdMin),this.thresholdMax=this.volume.getValueForSigma(this.thresholdMax)),this.thresholdType=t.thresholdType),t&&void 0!==t.radiusType&&("radius"===t.radiusType?this.radius=.1:this.radius=parseFloat(t.radiusType),e.radius=!0,"sphere"!==this.dotType||Ie&&!this.disableImpostor||(i=!0)),t&&void 0!==t.radius&&(e.radius=!0,"sphere"!==this.dotType||Ie&&!this.disableImpostor||(i=!0)),t&&void 0!==t.scale&&(e.scale=!0,"sphere"!==this.dotType||Ie&&!this.disableImpostor||(i=!0)),super.setParameters(t,e,i),this}}Ve.add("shader/Image.vert","uniform float clipRadius;\nuniform vec3 clipCenter;\nvarying vec2 vUv;\n#if defined( NEAR_CLIP ) || defined( RADIUS_CLIP ) || !defined( PICKING )\nvarying vec3 vViewPosition;\n#endif\n#if defined( RADIUS_CLIP )\nvarying vec3 vClipCenter;\n#endif\nvoid main() {\n#include begin_vertex\n#include project_vertex\nvUv = uv;\n#if defined( NEAR_CLIP ) || defined( RADIUS_CLIP ) || !defined( PICKING )\nvViewPosition = -mvPosition.xyz;\n#endif\n#if defined( RADIUS_CLIP )\nvClipCenter = -( modelViewMatrix * vec4( clipCenter, 1.0 ) ).xyz;\n#endif\n}"),Ve.add("shader/Image.frag","uniform sampler2D map;\nuniform float opacity;\nuniform vec2 mapSize;\nuniform float clipNear;\nuniform float clipRadius;\nvarying vec2 vUv;\n#if defined( NEAR_CLIP ) || defined( RADIUS_CLIP ) || !defined( PICKING )\nvarying vec3 vViewPosition;\n#endif\n#if defined( RADIUS_CLIP )\nvarying vec3 vClipCenter;\n#endif\n#if defined( PICKING )\nuniform sampler2D pickingMap;\nuniform float objectId;\n#else\n#include fog_pars_fragment\n#endif\n#if defined( CUBIC_INTERPOLATION )\n#if defined( CATMULROM_FILTER ) || defined( MITCHELL_FILTER )\n#if defined( CATMULROM_FILTER )\nconst float B = 0.0;\nconst float C = 0.5;\n#elif defined( MITCHELL_FILTER )\nconst float B = 0.333;\nconst float C = 0.333;\n#endif\nfloat filter( float x ){\nfloat f = x;\nif( f < 0.0 ){\nf = -f;\n}\nif( f < 1.0 ){\nreturn ( ( 12.0 - 9.0 * B - 6.0 * C ) * ( f * f * f ) +\n( -18.0 + 12.0 * B + 6.0 *C ) * ( f * f ) +\n( 6.0 - 2.0 * B ) ) / 6.0;\n}else if( f >= 1.0 && f < 2.0 ){\nreturn ( ( -B - 6.0 * C ) * ( f * f * f )\n+ ( 6.0 * B + 30.0 * C ) * ( f *f ) +\n( - ( 12.0 * B ) - 48.0 * C ) * f +\n8.0 * B + 24.0 * C ) / 6.0;\n}else{\nreturn 0.0;\n}\n}\n#elif defined( BSPLINE_FILTER )\nfloat filter( float x ){\nfloat f = x;\nif( f < 0.0 ){\nf = -f;\n}\nif( f >= 0.0 && f <= 1.0 ){\nreturn ( 2.0 / 3.0 ) + ( 0.5 ) * ( f * f * f ) - ( f * f );\n}else if( f > 1.0 && f <= 2.0 ){\nreturn 1.0 / 6.0 * pow( ( 2.0 - f ), 3.0 );\n}\nreturn 1.0;\n}\n#else\nfloat filter( float x ){\nreturn 1.0;\n}\n#endif\nvec4 biCubic( sampler2D tex, vec2 texCoord ){\nvec2 texelSize = 1.0 / mapSize;\ntexCoord -= texelSize / 2.0;\nvec4 nSum = vec4( 0.0 );\nfloat nDenom = 0.0;\nvec2 cell = fract( texCoord * mapSize );\nfor( float m = -1.0; m <= 2.0; ++m ){\nfor( float n = -1.0; n <= 2.0; ++n ){\nvec4 vecData = texture2D(\ntex, texCoord + texelSize * vec2( m, n )\n);\nfloat c = filter( m - cell.x ) * filter( -n + cell.y );\nnSum += vecData * c;\nnDenom += c;\n}\n}\nreturn nSum / nDenom;\n}\n#endif\nvoid main(){\n#include nearclip_fragment\n#include radiusclip_fragment\n#if defined( CUBIC_INTERPOLATION )\ngl_FragColor = biCubic( map, vUv );\n#else\ngl_FragColor = texture2D( map, vUv );\n#endif\n#if defined( PICKING )\nif( gl_FragColor.a < 0.3 )\ndiscard;\ngl_FragColor = vec4( texture2D( pickingMap, vUv ).xyz, objectId );\n#else\nif( gl_FragColor.a < 0.01 )\ndiscard;\ngl_FragColor.a *= opacity;\n#include fog_fragment\n#endif\n}");const Xc=new Uint16Array([0,1,2,1,3,2]),Yc=new Float32Array([0,1,0,0,1,1,1,0]),Kc=Object.assign({filter:"nearest",forceTransparent:!0},zo),Zc=Object.assign({filter:{updateShader:!0,uniform:!0}},Vo);class Qc extends Go{constructor(e,i){super({position:e.position,index:Xc,picking:e.picking},i),this.parameterTypes=Zc,this.alwaysTransparent=!0,this.hasWireframe=!1,this.vertexShader="Image.vert",this.fragmentShader="Image.frag";const{imageData:r,width:s,height:n}=e,o=new G(r,s,n);o.flipY=!0,this.tex=o;const a=r.length,c=new Uint8Array(a);for(let t=0;t>16&255,c[t+1]=e>>8&255,c[t+2]=255&e}const l=new G(c,s,n);l.flipY=!0,l.minFilter=x,l.magFilter=x,this.pickingTex=l,this.addUniforms({map:{value:o},pickingMap:{value:l},mapSize:{value:new t(s,n)}}),this.geometry.setAttribute("uv",new M(Yc,2))}get defaultParameters(){return Kc}getDefines(t){const e=super.getDefines(t),i=this.parameters.filter;return i.startsWith("cubic")&&(e.CUBIC_INTERPOLATION=1,i.endsWith("bspline")?e.BSPLINE_FILTER=1:i.endsWith("catmulrom")?e.CATMULROM_FILTER=1:i.endsWith("mitchell")&&(e.MITCHELL_FILTER=1)),e}updateTexture(){const t=this.tex,e=this.parameters.filter;e.startsWith("cubic")?(t.minFilter=x,t.magFilter=x):"linear"===e?(t.minFilter=A,t.magFilter=A):(t.minFilter=x,t.magFilter=x),t.needsUpdate=!0,this.pickingTex.needsUpdate=!0}makeMaterial(){super.makeMaterial(),this.updateTexture();const t=this.material;t.uniforms.map.value=this.tex,t.blending=U,t.needsUpdate=!0;const e=this.wireframeMaterial;e.uniforms.map.value=this.tex,e.blending=U,e.needsUpdate=!0;const i=this.pickingMaterial;i.uniforms.map.value=this.tex,i.uniforms.pickingMap.value=this.pickingTex,i.blending=U,i.needsUpdate=!0}setUniforms(t){t&&void 0!==t.filter&&(this.updateTexture(),t.map=this.tex),super.setUniforms(t)}}class Jc{constructor(t,e){const i=e||{};this.dimension=st(i.dimension,"x"),this.positionType=st(i.positionType,"percent"),this.position=st(i.position,30),this.thresholdType=st(i.thresholdType,"sigma"),this.thresholdMin=st(i.thresholdMin,-1/0),this.thresholdMax=st(i.thresholdMax,1/0),this.normalize=st(i.normalize,!1),this.volume=t}getPositionFromCoordinate(t){const i=this.dimension,r=this.volume,s=r.matrix,n=(new e).setFromMatrixPosition(s)[i],o=(new e).setFromMatrixScale(s)[i];let a;return a="x"===i?r.nx:"y"===i?r.ny:r.nz,Math.round(((t-n)/(a/100)+1)/o)}getData(t){t=t||{};const i=this.volume,r=i.data,s=i.matrix;let n;function o(t){return Math.round(t/100*(n-1))}function a(t,e,r,s){return 3*(r*i.ny*i.nx+e*i.nx+t)+s}n="coordinate"===this.positionType?this.getPositionFromCoordinate(this.position):this.position;const c=new Float32Array(12),l=new e;let h,d,u,m,p,f=0,g=0,y=0,b=i.nx,x=i.ny,v=i.nz;function w(t,e,i,r){l.set(t,e,i).applyMatrix4(s).toArray(c,r)}"x"===this.dimension?(u=o(i.nx),m=i.ny-1,p=i.nz-1,h=i.nz,d=i.ny,f=u,b=f+1,w(u,0,0,0),w(u,m,0,3),w(u,0,p,6),w(u,m,p,9)):"y"===this.dimension?(u=i.nx-1,m=o(i.ny),p=i.nz-1,h=i.nz,d=i.nx,g=m,x=g+1,w(0,m,0,0),w(u,m,0,3),w(0,m,p,6),w(u,m,p,9)):"z"===this.dimension&&(u=i.nx-1,m=i.ny-1,p=o(i.nz),h=i.nx,d=i.ny,y=p,v=y+1,w(0,0,p,0),w(0,m,p,3),w(u,0,p,6),w(u,m,p,9));let A=0,_=0;const S=new Uint8Array(h*d*4),C=new Float32Array(h*d);let P,I;"sigma"===this.thresholdType?(P=i.getValueForSigma(this.thresholdMin),I=i.getValueForSigma(this.thresholdMax)):(P=this.thresholdMin,I=this.thresholdMax);const k=Object.assign({},t.colorParams,{volume:i});this.normalize&&(k.domain=[0,1]);const M=Fe.getScheme(k),T=new Float32Array(3),B=M.getScale();let D,$=0,O=0;if(this.normalize){$=1/0,D=-1/0;for(let t=g;tD&&(D=s)}O=D-$}for(let t=g;tP&&n{this.viewer.add(t)})),this.setVisibility(this.visible),t()}create(){const t=new Jc(this.volume,{positionType:this.positionType,position:this.position,dimension:this.dimension,thresholdType:this.thresholdType,thresholdMin:this.thresholdMin,thresholdMax:this.thresholdMax,normalize:this.normalize}),e=new Qc(t.getData({colorParams:this.getColorParams()}),this.getBufferParams({filter:this.filter}));this.bufferList.push(e)}}function el(t){Me.error(`makeRepresentation: representation type ${t} unknown`)}const il={name:"some element",status:""};class rl{constructor(t,e={}){this.stage=t,this.signals={statusChanged:new et,nameChanged:new et,disposed:new et},this.parameters=nt(e,this.defaultParameters),this.uuid=Bt()}get defaultParameters(){return il}get name(){return this.parameters.name}setStatus(t){return this.parameters.status=t,this.signals.statusChanged.dispatch(t),this}setName(t){return this.parameters.name=t,this.signals.nameChanged.dispatch(t),this}dispose(){this.signals.disposed.dispatch()}}const sl=Object.assign({visible:!0},il);class nl extends rl{constructor(t,e,i={},r){super(t,Object.assign({name:e.type},i)),this.parent=r,this.signals=Object.assign({visibilityChanged:new et,parametersChanged:new et},this.signals),this.setRepresentation(e)}get defaultParameters(){return sl}get visible(){return this.parameters.visible}get type(){return"representation"}getType(){return this.repr.type}setRepresentation(t){this._disposeRepresentation(),this.repr=t,this.stage.tasks.listen(this.repr.tasks),this.updateVisibility()}_disposeRepresentation(){this.repr&&(this.stage.tasks.unlisten(this.repr.tasks),this.repr.dispose())}dispose(){this.parent&&this.parent.hasRepresentation(this)?this.parent.removeRepresentation(this):(this._disposeRepresentation(),this.signals.disposed.dispatch())}setVisibility(t){return this.parameters.visible=t,this.updateVisibility(),this.signals.visibilityChanged.dispatch(this.parameters.visible),this}getVisibility(){return this.parent?this.parent.parameters.visible&&this.parameters.visible:this.parameters.visible}toggleVisibility(){return this.setVisibility(!this.parameters.visible)}updateVisibility(){this.repr.setVisibility(this.getVisibility())}update(t){return this.repr.update(t),this}build(t){return this.repr.build(t),this}setSelection(t){const e=this.repr;return e.setSelection&&e.setSelection(t),this}setParameters(t){return this.repr.setParameters(t),this.signals.parametersChanged.dispatch(this.repr.getParameters()),this}getParameters(){return this.repr.getParameters()}setColor(t){return this.repr.setColor(t),this}}const ol=new i,al=new e,cl={name:"",status:"",visible:!0};class ll{constructor(t,s,n={}){this.stage=t,this.object=s,this.signals={representationAdded:new et,representationRemoved:new et,visibilityChanged:new et,matrixChanged:new et,statusChanged:new et,nameChanged:new et,disposed:new et},this.reprList=[],this.annotationList=[],this.matrix=new i,this.position=new e,this.quaternion=new r,this.scale=new e(1,1,1),this.transform=new i,this.parameters=nt(n,this.defaultParameters),this.uuid=Bt(),this.viewer=t.viewer,this.controls=new ua(this)}get defaultParameters(){return cl}get name(){return this.parameters.name}get status(){return this.parameters.status}get visible(){return this.parameters.visible}setPosition(t){return Array.isArray(t)?this.position.fromArray(t):this.position.copy(t),this.updateMatrix(),this}setRotation(t){if(Array.isArray(t))if(3===t.length){const e=(new j).fromArray(t);this.quaternion.setFromEuler(e)}else this.quaternion.fromArray(t);else t instanceof j?this.quaternion.setFromEuler(t):this.quaternion.copy(t);return this.updateMatrix(),this}setScale(t){return this.scale.set(t,t,t),this.updateMatrix(),this}setTransform(t){return this.transform.copy(t),this.updateMatrix(),this}updateMatrix(){const t=this.getCenterUntransformed(al);this.matrix.makeTranslation(-t.x,-t.y,-t.z),ol.makeRotationFromQuaternion(this.quaternion),this.matrix.premultiply(ol),ol.makeScale(this.scale.x,this.scale.y,this.scale.z),this.matrix.premultiply(ol);const e=this.position;ol.makeTranslation(e.x+t.x,e.y+t.y,e.z+t.z),this.matrix.premultiply(ol),this.matrix.premultiply(this.transform),this.updateRepresentationMatrices(),this.stage.viewer.updateBoundingBox(),this.signals.matrixChanged.dispatch(this.matrix)}updateRepresentationMatrices(){this.reprList.forEach((t=>{t.setParameters({matrix:this.matrix})}))}addAnnotation(t,e,i){const r=new ca(this,t,e,i);return this.annotationList.push(r),r}eachAnnotation(t){this.annotationList.slice().forEach(t)}removeAnnotation(t){const e=this.annotationList.indexOf(t);-1!==e&&(this.annotationList.splice(e,1),t.dispose())}removeAllAnnotations(){this.eachAnnotation((t=>t.dispose())),this.annotationList.length=0}_addRepresentation(t,e,i,r=!1){const s=i||{},n=this.stage.getParameters();s.matrix=this.matrix.clone(),s.quality=s.quality||n.quality,s.disableImpostor=st(s.disableImpostor,!n.impostor),s.useWorker=st(s.useWorker,n.workerDefault),s.visible=st(s.visible,!0);const o=Object.assign({},s,{visible:this.parameters.visible&&s.visible}),a=function(t,e,i,r){var s;if(De&&Me.time("makeRepresentation "+t),e instanceof Cc){if(!(s=Ne.get(t)))return void el(t)}else if(e instanceof Oo)if("surface"===t)s=Yo;else{if("dot"!==t)return void el(t);s=qc}else if(e instanceof Eo)if("surface"===t)s=Yo;else if("dot"===t)s=qc;else{if("slice"!==t)return void el(t);s=tl}else if(e instanceof Mc)s=Tc,e=e.getBufferList();else{if("buffer"!==t)return void Me.error("makeRepresentation: object "+e+" unknown");s=Tc}const n=new s(e,i,r);return De&&Me.timeEnd("makeRepresentation "+t),n}(t,e,this.viewer,o),c=new nl(this.stage,a,s,this);return r||(this.reprList.push(c),this.signals.representationAdded.dispatch(c)),c}addBufferRepresentation(t,e){return this._addRepresentation.call(this,"buffer",t,e)}hasRepresentation(t){return-1!==this.reprList.indexOf(t)}eachRepresentation(t){this.reprList.slice().forEach(t)}removeRepresentation(t){const e=this.reprList.indexOf(t);-1!==e&&(this.reprList.splice(e,1),t.dispose(),this.signals.representationRemoved.dispatch(t))}updateRepresentations(t){this.reprList.forEach((e=>e.update(t))),this.stage.viewer.requestRender()}removeAllRepresentations(){this.eachRepresentation((t=>t.dispose()))}dispose(){this.removeAllAnnotations(),this.removeAllRepresentations(),this.reprList.length=0,this.signals.disposed.dispatch()}setVisibility(t){return this.parameters.visible=t,this.eachRepresentation((t=>t.updateVisibility())),this.eachAnnotation((t=>t.updateVisibility())),this.signals.visibilityChanged.dispatch(t),this}setStatus(t){return this.parameters.status=t,this.signals.statusChanged.dispatch(t),this}setName(t){return this.parameters.name=t,this.signals.nameChanged.dispatch(t),this}getBox(...t){return this.getBoxUntransformed(...t).clone().applyMatrix4(this.matrix)}getCenter(...t){return this.getCenterUntransformed(...t).clone().applyMatrix4(this.matrix)}getZoom(...t){return this.stage.getZoomForBox(this.getBox(...t))}getBoxUntransformed(...t){return new a}getCenterUntransformed(...t){return this.getBoxUntransformed().getCenter(new e)}autoView(t){this.stage.animationControls.zoomMove(this.getCenter(),this.getZoom(),st(t,0))}}class hl{constructor(t=[]){this.list=t;const e=t.length;for(let i=0;i0?this.list[0]:void 0}forEach(t){return this.list.forEach(t),this}dispose(){return this.forEach((t=>t.dispose()))}}class dl extends hl{setParameters(t){return this.forEach((e=>e.setParameters(t)))}setVisibility(t){return this.forEach((e=>e.setVisibility(t)))}setSelection(t){return this.forEach((e=>e.setSelection(t)))}setColor(t){return this.forEach((e=>e.setColor(t)))}update(t){return this.forEach((e=>e.update(t)))}build(t){return this.forEach((e=>e.build(t)))}dispose(t){return this.forEach((t=>t.dispose()))}}const ul=Object.assign({defaultStep:1,defaultTimeout:50,defaultInterpolateType:"",defaultInterpolateStep:5,defaultMode:"loop",defaultDirection:"forward",initialFrame:0},il);class ml extends rl{constructor(t,e,i={}){super(t,Object.assign({name:e.name},i)),this.trajectory=e,this.signals=Object.assign(this.signals,{frameChanged:new et,playerChanged:new et,countChanged:new et,parametersChanged:new et}),e.signals.frameChanged.add((t=>{this.signals.frameChanged.dispatch(t)})),e.signals.playerChanged.add((t=>{this.signals.playerChanged.dispatch(t)})),e.signals.countChanged.add((t=>{this.signals.countChanged.dispatch(t)})),void 0!==i.initialFrame&&this.setFrame(i.initialFrame)}get defaultParameters(){return ul}get type(){return"trajectory"}setFrame(t){this.trajectory.setFrame(t)}setParameters(t={}){this.trajectory.setParameters(t),this.signals.parametersChanged.dispatch(t)}dispose(){this.trajectory.dispose(),super.dispose()}}class pl{constructor(t,e){this.name=t,this.path=e,this.coordinates=[],this.boxes=[],this.times=[],this.timeOffset=0,this.deltaTime=1}get type(){return"Frames"}}class fl{constructor(t,e){let r,s;if(this.A=new ho(3,3),this.W=new ho(1,3),this.U=new ho(3,3),this.V=new ho(3,3),this.VH=new ho(3,3),this.R=new ho(3,3),this.tmp=new ho(3,3),this.c=new ho(3,3),t instanceof Cc)r=t.atomCount;else{if(!(t instanceof Float32Array))return;r=t.length/3}if(e instanceof Cc)s=e.atomCount;else{if(!(e instanceof Float32Array))return;s=e.length/3}const n=Math.min(r,s),o=new ho(3,n),a=new ho(3,n);this.coords1t=new ho(n,3),this.coords2t=new ho(n,3),this.transformationMatrix=new i,this.c.data.set([1,0,0,0,1,0,0,0,-1]),this.prepCoords(t,o,n,!1),this.prepCoords(e,a,n,!1),this._superpose(o,a)}_superpose(t,e){this.mean1=fo(t),this.mean2=fo(e),go(t,this.mean1),go(e,this.mean2),uo(this.coords1t,t),uo(this.coords2t,e),mo(this.A,this.coords2t,this.coords1t),wo(this.A,this.W,this.U,this.V),function(t,e){const i=t.data,r=e.data,s=i[4],n=i[8],o=i[5],a=i[7],c=i[0],l=c*s,h=c*o,d=i[3],u=i[1],m=d*u,p=i[2],f=d*p,g=i[6],y=g*u,b=g*p,x=1/(l*n-h*a-m*n+f*a+y*o-b*s);r[0]=(s*n-o*a)*x,r[1]=-(u*n-p*a)*x,r[2]=-(-u*o+p*s)*x,r[3]=-(d*n-o*g)*x,r[4]=(c*n-b)*x,r[5]=-(h-f)*x,r[6]=-(-d*a+s*g)*x,r[7]=-(c*a-y)*x,r[8]=(l-m)*x}(this.V,this.VH),po(this.R,this.U,this.VH),function(t){const e=t.data;return e[0]*e[4]*e[8]-e[0]*e[5]*e[7]-e[3]*e[1]*e[8]+e[3]*e[2]*e[7]+e[6]*e[1]*e[5]-e[6]*e[2]*e[4]}(this.R)<0&&(De&&Me.log("R not a right handed system"),po(this.tmp,this.c,this.VH),po(this.R,this.U,this.tmp));const i=new ho(4,4),r=new ho(4,4),s=new ho(4,4),n=new ho(4,4),o=new ho(4,4),a=new ho(4,4),c=this.R.data,l=this.mean1,h=this.mean2;n.data.set([1,0,0,-l[0],0,1,0,-l[1],0,0,1,-l[2],0,0,0,1]),o.data.set([c[0],c[1],c[2],0,c[3],c[4],c[5],0,c[6],c[7],c[8],0,0,0,0,1]),a.data.set([1,0,0,h[0],0,1,0,h[1],0,0,1,h[2],0,0,0,1]),uo(r,n),mo(i,o,r),uo(s,i),mo(r,a,s),uo(i,r),this.transformationMatrix.elements=i.data}prepCoords(t,e,i,r){let s=0;const n=e.data;let o=3,a=3*i;if(r&&(a=4*i,o=4),t instanceof Cc)t.eachAtom((function(t){s{t!==this&&this.pause()}),this);const i=st(t.frameCount,1);this.traj=t,this.parameters=nt(e,gl),this.parameters.end=Math.min(st(e.end,i-1),i-1),this.parameters.step=st(e.step,Math.ceil((i+1)/100)),this._currentFrame=this.parameters.start,this._direction="bounce"===this.parameters.direction?"forward":this.parameters.direction,t.signals.countChanged.add((t=>{this.parameters.end=Math.min(st(this.parameters.end,t-1),t-1)}),this),this._animate=this._animate.bind(this)}get isRunning(){return this._run}setParameters(t={}){ot(this.parameters,t),void 0!==t.direction&&"bounce"!==this.parameters.direction&&(this._direction=this.parameters.direction)}_animate(){if(!this._run)return;this._currentTime=window.performance.now();const t=this._currentTime-this._previousTime,e=this.parameters.interpolateType?this.parameters.interpolateStep:1,i=this.parameters.timeout/e,r=this.traj;if(r&&r.frameCount&&!r.inProgress&&t>=i)if(this.parameters.interpolateType)if(this._currentStep>this.parameters.interpolateStep&&(this._currentStep=1),1===this._currentStep&&(this._currentFrame=this._nextInterpolated()),r.hasFrame(this._currentFrame)){this._currentStep+=1;const t=this._currentStep/(this.parameters.interpolateStep+1),[e,i,s,n]=this._currentFrame;r.setFrameInterpolated(e,i,s,n,t,this.parameters.interpolateType),this._previousTime=this._currentTime}else r.loadFrame(this._currentFrame);else{const t=this._next();r.hasFrame(t)?(r.setFrame(t),this._previousTime=this._currentTime):r.loadFrame(t)}window.requestAnimationFrame(this._animate)}_next(){const t=this.parameters;let e;return e="forward"===this._direction?this.traj.currentFrame+t.step:this.traj.currentFrame-t.step,(e>t.end||e=t.end?i=t.start:"backward"===t.direction&&e<=t.start&&(i=t.end),this.traj.setFrame(i),this._run=!0,this._animate(),this.signals.startedRunning.dispatch()}}pause(){this._run=!1,this.signals.haltedRunning.dispatch()}stop(){this.pause(),this.traj.setFrame(this.parameters.start)}}class bl{constructor(t,e,i={}){this.signals={countChanged:new et,frameChanged:new et,playerChanged:new et},this.frameCache={},this.loadQueue={},this.boxCache={},this.pathCache={},this.frameCacheSize=0,this._frameCount=0,this._currentFrame=-1,this._disposed=!1,this.deltaTime=st(i.deltaTime,0),this.timeOffset=st(i.timeOffset,0),this.centerPbc=st(i.centerPbc,!1),this.removePbc=st(i.removePbc,!1),this.removePeriodicity=st(i.removePeriodicity,!1),this.superpose=st(i.superpose,!1),this.name=t.replace(/^.*[\\/]/,""),this.trajPath=t,this.selection=new pe(st(i.sele,"backbone and not hydrogen")),this.selection.signals.stringChanged.add((()=>{this.selectionIndices=this.structure.getAtomIndices(this.selection),this._resetCache(),this._saveInitialCoords(),this.setFrame(this._currentFrame)}))}get frameCount(){return this._frameCount}get currentFrame(){return this._currentFrame}_init(t){this.setStructure(t),this._loadFrameCount(),this.setPlayer(new yl(this))}_loadFrameCount(){}setStructure(t){this.structure=t,this.atomCount=t.atomCount,this.backboneIndices=this._getIndices(new pe("backbone and not hydrogen")),this._makeAtomIndices(),this._saveStructureCoords(),this.selectionIndices=this._getIndices(this.selection),this._resetCache(),this._saveInitialCoords(),this.setFrame(this._currentFrame)}_saveInitialCoords(){this.structure.hasCoords()?(this.initialCoords=new Float32Array(this.structureCoords),this._makeSuperposeCoords()):this.frameCache[0]?(this.initialCoords=new Float32Array(this.frameCache[0]),this._makeSuperposeCoords()):this.loadFrame(0,(()=>this._saveInitialCoords()))}_saveStructureCoords(){this.structureCoords=this.structure.getAtomData({what:{position:!0}}).position}setSelection(t){return this.selection.setString(t),this}_getIndices(t){let e=0;const i=t.test,r=[];return i&&this.structure.eachAtom((t=>{i(t)&&r.push(e),e+=1})),r}_makeSuperposeCoords(){const t=3*this.selectionIndices.length;this.coords1=new Float32Array(t),this.coords2=new Float32Array(t);const e=this.initialCoords,i=this.coords2;for(let r=0;r!!this.frameCache[t])):!!this.frameCache[t]}setFrame(t,e){return void 0===t||(this.inProgress=!0,-1===t||this.frameCache[t]?(this._updateStructure(t),e&&e()):this.loadFrame(t,(()=>{this._updateStructure(t),e&&e()}))),this}_interpolate(t,e,i,r,s,n){const o=this.frameCache;let a;a="spline"===n?function(t,e,i,r,s){const n=t.length,o=new Float32Array(n);for(let a=0;a{this._interpolate(t,e,i,r,s,n),o&&o()})):(this._interpolate(t,e,i,r,s,n),o&&o()),this}loadFrame(t,e){Array.isArray(t)?t.forEach((t=>{this.loadQueue[t]||this.frameCache[t]||(this.loadQueue[t]=!0,this._loadFrame(t,(()=>{delete this.loadQueue[t]})))})):this.loadQueue[t]||this.frameCache[t]||(this.loadQueue[t]=!0,this._loadFrame(t,(()=>{delete this.loadQueue[t],e&&e()})))}_loadFrame(t,e){Me.error("Trajectory._loadFrame not implemented",t,e)}_updateStructure(t){this._disposed?console.error("updateStructure: traj disposed"):(-1===t?this.structureCoords&&this.structure.updatePosition(this.structureCoords):this.structure.updatePosition(this.frameCache[t]),this.structure.trajectory={name:this.trajPath,frame:t},this._currentFrame=t,this.inProgress=!1,this.signals.frameChanged.dispatch(t))}_doSuperpose(t){const e=3*this.selectionIndices.length,i=this.coords1,r=this.coords2;for(let r=0;r0&&this.centerPbc){const t=[e[0],e[4],e[8]],r=function(t,e,i){return[wi(e,i[0],3,0,t),wi(e,i[1],3,1,t),wi(e,i[2],3,2,t)]}(this.backboneIndices,i,t);!function(t,e,i){if(0===i[0]||0===i[8]||0===i[4])return;const r=t.length,s=i[0],n=i[1],o=i[2],a=-e[0]+s+s/2,c=-e[1]+n+n/2,l=-e[2]+o+o/2;for(let e=0;e.5&&(t[s+r]-=e[3*r+r]*Math.round(n))}}(i,e,t)}this.removePbc&&function(t,e){if(0===e[0]||0===e[8]||0===e[4])return;const i=t.length;for(let r=3;r.9*e[3*i+i])if(s>0)for(let s=0;s<3;++s)t[r+s]-=e[3*i+s];else for(let s=0;s<3;++s)t[r+s]+=e[3*i+s]}}(i,e)}this.selectionIndices.length>0&&this.coords1&&this.superpose&&this._doSuperpose(i),this.frameCache[t]=i,this.boxCache[t]=e,this.frameCacheSize+=1}_setFrameCount(t){t!==this._frameCount&&(this._frameCount=t,this.signals.countChanged.dispatch(t))}dispose(){this._resetCache(),this._disposed=!0,this.player&&this.player.stop()}setPlayer(t){this.player=t,this.signals.playerChanged.dispatch(t)}getFrameTime(t){return this.timeOffset+t*this.deltaTime}}class xl extends bl{constructor(t,e,i){const r=i||{};r.timeOffset=st(r.timeOffset,t.timeOffset),r.deltaTime=st(r.deltaTime,t.deltaTime),super("",e,r),this.name=t.name,this.path=t.path,this.frames=t.coordinates,this.boxes=t.boxes,this._init(e)}get type(){return"frames"}_makeAtomIndices(){"StructureView"===this.structure.type?this.atomIndices=this.structure.getAtomIndices():this.atomIndices=void 0}_loadFrame(t,e){let i;const r=this.frames[t];if(this.atomIndices){const t=this.atomIndices,e=t.length;i=new Float32Array(3*e);for(let s=0;s{const s=i.response;if(!s)return void Me.error(`empty arrayBuffer for '${r}'`);const n=new Int32Array(s,0,1)[0],o=new Float32Array(s,8,9),a=new Float32Array(s,44);this._process(t,o,a,n),"function"==typeof e&&e()}),!1),i.send(s)}_loadFrameCount(){const t=new XMLHttpRequest,e=qe.getCountUrl(this.trajPath);t.open("GET",e,!0),t.addEventListener("load",(()=>{this._setFrameCount(parseInt(t.response))}),!1),t.send()}}class Al extends bl{constructor(t,e,i){super("",e,i),this.requestCallback=t,this._init(e)}get type(){return"callback"}_makeAtomIndices(){const t=[];if("StructureView"===this.structure.type){const e=this.structure.getAtomIndices(),i=e.length;let r=e[0],s=e[0];for(let n=1;n{this._process(t,i,r,s),"function"==typeof e&&e()}),t,this.atomIndices)}_loadFrameCount(){this.requestCallback((t=>this._setFrameCount(t)))}}Cc.prototype.getView=function(t){return new _l(this,t)};class _l extends Cc{constructor(t,i){super(),this.structure=t,this.selection=i,this.center=new e,this.boundingBox=new a,this._bp=this.getBondProxy(),this._ap=this.getAtomProxy(),this._rp=this.getResidueProxy(),this._cp=this.getChainProxy(),this.selection&&this.selection.signals.stringChanged.add(this.refresh,this),this.structure.signals.refreshed.add(this.refresh,this),this.refresh()}init(){}get type(){return"StructureView"}get name(){return this.structure.name}get path(){return this.structure.path}get title(){return this.structure.title}get id(){return this.structure.id}get data(){return this.structure.data}get atomSetDict(){return this.structure.atomSetDict}get biomolDict(){return this.structure.biomolDict}get entityList(){return this.structure.entityList}get unitcell(){return this.structure.unitcell}get frames(){return this.structure.frames}get boxes(){return this.structure.boxes}get validation(){return this.structure.validation}get bondStore(){return this.structure.bondStore}get backboneBondStore(){return this.structure.backboneBondStore}get rungBondStore(){return this.structure.rungBondStore}get atomStore(){return this.structure.atomStore}get residueStore(){return this.structure.residueStore}get chainStore(){return this.structure.chainStore}get modelStore(){return this.structure.modelStore}get atomMap(){return this.structure.atomMap}get residueMap(){return this.structure.residueMap}get bondHash(){return this.structure.bondHash}get spatialHash(){return this.structure.spatialHash}get _hasCoords(){return this.structure._hasCoords}set _hasCoords(t){this.structure._hasCoords=t}refresh(){De&&Me.time("StructureView.refresh"),this.atomSetCache={};const t=this.structure;if(this.selection.isAllSelection()&&t!==this&&t.atomSet&&t.bondSet){this.atomSet=t.atomSet.clone(),this.bondSet=t.bondSet.clone();for(let t in this.atomSetDict){const e=this.atomSetDict[t];this.atomSetCache["__"+t]=e.clone()}this.atomCount=t.atomCount,this.bondCount=t.bondCount,this.boundingBox.copy(t.boundingBox),this.center.copy(t.center)}else if(this.selection.isNoneSelection()&&t!==this&&t.atomSet&&t.bondSet){this.atomSet=new Os(t.atomCount),this.bondSet=new Os(t.bondCount);for(let e in this.atomSetDict)this.atomSetCache["__"+e]=new Os(t.atomCount);this.atomCount=0,this.bondCount=0,this.boundingBox.makeEmpty(),this.center.set(0,0,0)}else{this.atomSet=this.getAtomSet(this.selection,!0),t.atomSet&&(this.atomSet=this.atomSet.intersection(t.atomSet)),this.bondSet=this.getBondSet();for(let t in this.atomSetDict){const e=this.atomSetDict[t];this.atomSetCache["__"+t]=e.makeIntersection(this.atomSet)}this.atomCount=this.atomSet.getSize(),this.bondCount=this.bondSet.getSize(),this.boundingBox=this.getBoundingBox(),this.center=this.boundingBox.getCenter(new e)}De&&Me.timeEnd("StructureView.refresh"),this.signals.refreshed.dispatch()}setSelection(t){this.selection=t,this.refresh()}getSelection(t){const e=[];t&&t.string&&e.push(t.string);const i=this.structure.getSelection();i&&i.string&&e.push(i.string),this.selection&&this.selection.string&&e.push(this.selection.string);let r="";return e.length>0&&(r=`( ${e.join(" ) AND ( ")} )`),new pe(r)}getStructure(){return this.structure.getStructure()}eachBond(t,e){this.structure.eachBond(t,this.getSelection(e))}eachAtom(t,e){const i=this.getAtomProxy(),r=this.getAtomSet(e),s=this.atomStore.count;if(r.getSize()=this.V[i][r]?(e="S",this.score=this.S[i][r]):this.V[i][r]>=this.H[i][r]?(e="V",this.score=this.V[i][r]):(e="H",this.score=this.H[i][r]),De&&Me.log("Alignment: SCORE",this.score),De&&Me.log("Alignment: S, V, H",this.S[i][r],this.V[i][r],this.H[i][r]);i>0&&r>0;)"S"===e?this.S[i][r]===this.S[i-1][r-1]+t(i-1,r-1)?(this.ali1=this.seq1[i-1]+this.ali1,this.ali2=this.seq2[r-1]+this.ali2,--i,--r,e="S"):this.S[i][r]===this.V[i][r]?e="V":this.S[i][r]===this.H[i][r]?e="H":(--i,--r):"V"===e?this.V[i][r]===this.V[i-1][r]+this.gapExtensionPenalty?(this.ali1=this.seq1[i-1]+this.ali1,this.ali2="-"+this.ali2,--i,e="V"):this.V[i][r]===this.S[i-1][r]+this.gap(0)?(this.ali1=this.seq1[i-1]+this.ali1,this.ali2="-"+this.ali2,--i,e="S"):--i:"H"===e?this.H[i][r]===this.H[i][r-1]+this.gapExtensionPenalty?(this.ali1="-"+this.ali1,this.ali2=this.seq2[r-1]+this.ali2,--r,e="H"):this.H[i][r]===this.S[i][r-1]+this.gap(0)?(this.ali1="-"+this.ali1,this.ali2=this.seq2[r-1]+this.ali2,--r,e="S"):--r:Me.error("Alignment: no matrix");for(;i>0;)this.ali1=this.seq1[i-1]+this.ali1,this.ali2="-"+this.ali2,--i;for(;r>0;)this.ali1="-"+this.ali1,this.ali2=this.seq2[r-1]+this.ali2,--r;De&&Me.timeEnd("Alignment.trace"),De&&Me.log([this.ali1,this.ali2])}}function kl(t,e,i=!1,r="",s=""){let n,o,a,c,l;if(i){let i=t,h=e;r&&s&&(i=t.getView(new pe(r)),h=e.getView(new pe(s)));const d=i.getSequence(),u=h.getSequence(),m=new Il(d.join(""),u.join(""));let p,f;m.calc(),m.trace(),n=0,o=0,a=m.ali1.length;const g=[],y=[];for(let t=0;tt[e]))}}}(),this.spacefillRepresentation=this.addRepresentation("spacefill",{sele:"none",opacity:Te.opacity,color:Te.color,disablePicking:!0,radiusType:"data"},!0),this.distanceRepresentation=this.addRepresentation("distance",Te,!0),this.angleRepresentation=this.addRepresentation("angle",Te,!0),this.dihedralRepresentation=this.addRepresentation("dihedral",Te,!0),this.measureRepresentations=new dl([this.spacefillRepresentation,this.distanceRepresentation,this.angleRepresentation,this.dihedralRepresentation]),this.setDefaultAssembly(this.parameters.defaultAssembly),this.structure.signals.refreshed.add((()=>{this.updateRepresentations({position:!0})}))}get defaultParameters(){return Ml}get type(){return"structure"}initSelection(t){this.selection=new pe(t),this.structureView=new _l(this.structure,this.selection),this.selection.signals.stringChanged.add((()=>{this.structureView.setSelection(this.selection),this.rebuildRepresentations(),this.rebuildTrajectories()}))}setSelection(t){return this.parameters.sele=t,this.selection.setString(t),this}setDefaultAssembly(t){if(void 0===this.structure.biomolDict[t]&&(t=""),this.parameters.defaultAssembly!==t){const e={defaultAssembly:t};this.reprList.forEach((t=>t.setParameters(e))),this.measureRepresentations.setParameters(e),this.parameters.defaultAssembly=t,this.signals.defaultAssemblyChanged.dispatch(t)}return this}rebuildRepresentations(){this.reprList.forEach((t=>{t.build()})),this.measureRepresentations.build()}rebuildTrajectories(){this.trajList.forEach((t=>{t.trajectory.setStructure(this.structureView)}))}updateRepresentations(t){super.updateRepresentations(t),this.measureRepresentations.update(t)}updateRepresentationMatrices(){super.updateRepresentationMatrices(),this.measureRepresentations.setParameters({matrix:this.matrix})}addRepresentation(t,e={},i=!1){e.defaultAssembly=this.parameters.defaultAssembly;const r=this._addRepresentation(t,this.structureView,e,i);return i||r.signals.parametersChanged.add((()=>this.measureUpdate())),r}addTrajectory(t="",e={}){const i=function(t,e,i){let r;return r=t&&t instanceof pl?new xl(t,e,i):!t&&e.frames?new vl(t,e,i):t&&"function"==typeof t?new Al(t,e,i):new wl(t,e,i),r}(t,this.structureView,e),r=new ml(this.stage,i,e);return this.trajList.push(r),this.signals.trajectoryAdded.dispatch(r),r}removeTrajectory(t){const e=this.trajList.indexOf(t);-1!==e&&this.trajList.splice(e,1),t.dispose(),this.signals.trajectoryRemoved.dispatch(t)}dispose(){this.trajList.slice().forEach((t=>t.dispose())),this.trajList.length=0,this.structure.dispose(),this.measureRepresentations.dispose(),super.dispose()}autoView(t,e){"number"==typeof t&&(e=t,t=""),this.stage.animationControls.zoomMove(this.getCenter(t),this.getZoom(t),st(e,0))}getBoxUntransformed(t){let e;return e=t?this.structureView.getBoundingBox(new pe(t)):this.structureView.boundingBox,e}getCenterUntransformed(t){return t&&"string"==typeof t?this.structure.atomCenter(new pe(t)):this.structure.center}superpose(t,e,i,r){return kl(this.structureView,t.structureView,e,i,r),this.updateRepresentations({position:!0}),this}getMaxRepresentationRadius(t){let e=0;const i=this.structure.getAtomProxy(t);return this.eachRepresentation((t=>{if(t.getVisibility()){const r=t.repr;e=Math.max(r.getAtomRadius(i),e)}})),e}measurePick(t){const e=this.pickBuffer.count;if(this.lastPick===t.index&&e>=1){if(e>1){const t=this.pickBuffer.data,i=this.pickBuffer.data.sort();this.pickDict.has(i)?this.pickDict.del(i):this.pickDict.add(i,t),2===e?this.distanceRepresentation.setParameters({atomPair:this.pickDict.values.filter((t=>2===t.length))}):3===e?this.angleRepresentation.setParameters({atomTriple:this.pickDict.values.filter((t=>3===t.length))}):4===e&&this.dihedralRepresentation.setParameters({atomQuad:this.pickDict.values.filter((t=>4===t.length))})}this.pickBuffer.clear(),this.lastPick=void 0}else this.pickBuffer.has(t.index)||this.pickBuffer.push(t.index),this.lastPick=t.index;this.measureUpdate()}measureClear(){this.pickBuffer.clear(),this.lastPick=void 0,this.spacefillRepresentation.setSelection("none")}measureBuild(){const t=this.measureData();this.distanceRepresentation.setParameters({atomPair:t.distance}),this.angleRepresentation.setParameters({atomTriple:t.angle}),this.dihedralRepresentation.setParameters({atomQuad:t.dihedral})}measureUpdate(){const t=this.pickBuffer.data,e={};t.forEach((t=>{const i=Math.max(.1,this.getMaxRepresentationRadius(t));e[t]=i*(2.3-Rt(.1,2,i))})),this.spacefillRepresentation.setSelection(t.length?"@"+t.join(","):"none"),t.length&&this.spacefillRepresentation.setParameters({radiusData:e})}measureData(){const t=this.pickDict.values;return{distance:t.filter((t=>2===t.length)),angle:t.filter((t=>3===t.length)),dihedral:t.filter((t=>4===t.length))}}removeAllMeasurements(t){const e=this.pickDict,i=e.values,r=function(t){i.filter((e=>e.length===t)).forEach((t=>e.del(t.slice().sort())))};(!t||1&t)&&r(2),(!t||2&t)&&r(3),(!t||4&t)&&r(4),this.measureBuild()}removeMeasurement(t){this.pickDict.del(t.slice().sort()),this.measureBuild()}addMeasurement(t){if(t.length<2||t.length>4)return;const e=t.slice().sort();this.pickDict.has(e)||this.pickDict.add(e,t),this.measureBuild()}}Ue.add("structure",Tl),Ue.add("structureview",Tl);class Bl extends ll{constructor(t,e,i={}){super(t,e,Object.assign({name:e.name},i)),this.surface=e}get type(){return"surface"}addRepresentation(t,e={}){return this._addRepresentation(t,this.surface,e)}getBoxUntransformed(){return this.surface.boundingBox}getCenterUntransformed(){return this.surface.center}dispose(){this.surface.dispose(),super.dispose()}}Ue.add("surface",Bl);class Dl extends ll{constructor(t,e,i={}){super(t,e,Object.assign({name:e.name},i)),this.volume=e}get type(){return"volume"}addRepresentation(t,e={}){return this._addRepresentation(t,this.volume,e)}getBoxUntransformed(){return this.volume.boundingBox}getCenterUntransformed(){return this.volume.center}dispose(){this.volume.dispose(),super.dispose()}}Ue.add("volume",Dl);class $l extends hl{addRepresentation(t,e){return this.forEach((i=>i.addRepresentation(t,e)))}autoView(t){return this.forEach((e=>e.autoView(t)))}}function Ol(t,e){return t instanceof RegExp?null!==e.name.match(t):e.name===t}const Rl=new e,El={impostor:!0,quality:"medium",workerDefault:!0,sampleLevel:0,backgroundColor:"black",rotateSpeed:2,zoomSpeed:1.2,panSpeed:1,clipNear:0,clipFar:100,clipDist:10,clipMode:"scene",clipScale:"relative",fogNear:50,fogFar:100,cameraFov:40,cameraEyeSep:.3,cameraType:"perspective",lightColor:14540253,lightIntensity:1,ambientColor:14540253,ambientIntensity:.2,hoverTimeout:0,tooltip:!0,mousePreset:"default"};class Fl{constructor(t,e={}){this.signals={parametersChanged:new et,fullscreenChanged:new et,componentAdded:new et,componentRemoved:new et,clicked:new et,hovered:new et},this.tasks=new ui,this.compList=[],this.defaultFileParams={},this.logList=[],this.viewer=new Ji(t),this.viewer.renderer&&(this.tooltip=document.createElement("div"),Object.assign(this.tooltip.style,{display:"none",position:"fixed",zIndex:"1000000",pointerEvents:"none",backgroundColor:"rgba( 0, 0, 0, 0.6 )",color:"lightgrey",padding:"8px",fontFamily:"sans-serif"}),this.viewer.container.appendChild(this.tooltip),this.mouseObserver=new sr(this.viewer.renderer.domElement),this.viewerControls=new kr(this),this.trackballControls=new gr(this),this.pickingControls=new xr(this),this.animationControls=new Lr(this),this.mouseControls=new Jo(this),this.keyControls=new ia(this),this.pickingBehavior=new ra(this),this.mouseBehavior=new sa(this),this.animationBehavior=new na(this),this.keyBehavior=new aa(this),this.spinAnimation=this.animationControls.spin([0,1,0],.005),this.spinAnimation.pause(!0),this.rockAnimation=this.animationControls.rock([0,1,0],.005),this.rockAnimation.pause(!0),this.parameters=nt(e,El),this.setParameters(this.parameters),this.viewer.animate())}setParameters(t={}){ot(this.parameters,t);const e=t,i=this.parameters,r=this.viewer,s=this.trackballControls;return void 0!==e.quality&&this.setQuality(i.quality),void 0!==e.impostor&&this.setImpostor(i.impostor),void 0!==e.rotateSpeed&&(s.rotateSpeed=i.rotateSpeed),void 0!==e.zoomSpeed&&(s.zoomSpeed=i.zoomSpeed),void 0!==e.panSpeed&&(s.panSpeed=i.panSpeed),void 0!==e.mousePreset&&this.mouseControls.preset(i.mousePreset),this.mouseObserver.setParameters({hoverTimeout:i.hoverTimeout}),r.setClip(i.clipNear,i.clipFar,i.clipDist,i.clipMode,i.clipScale),r.setFog(void 0,i.fogNear,i.fogFar),r.setCamera(i.cameraType,i.cameraFov,i.cameraEyeSep),r.setSampling(i.sampleLevel),r.setBackground(i.backgroundColor),r.setLight(i.lightColor,i.lightIntensity,i.ambientColor,i.ambientIntensity),this.signals.parametersChanged.dispatch(this.getParameters()),this}log(t){console.log("STAGE LOG",t),this.logList.push(t)}getParameters(){return Object.assign({},this.parameters)}defaultFileRepresentation(t){if(t instanceof Tl){let e,i,r;t.setSelection("/0");const s=t.structure;if(s.biomolDict.BU1){const n=s.biomolDict.BU1;e=n.getAtomCount(s),i=n.getResidueCount(s),r=n.getInstanceCount(),t.setDefaultAssembly("BU1")}else e=s.getModelProxy(0).atomCount,i=s.getModelProxy(0).residueCount,r=1;let n=e;Se&&(n*=4);const o=s.atomStore.count/s.residueStore.count<2;o&&(n*=10);let a="chainname",c="RdYlBu",l=!1;if(1===s.getChainnameCount(new pe("polymer and /0"))&&(a="residueindex",c="Spectral",l=!0),De&&console.log(n,e,r,o),i/r<4)t.addRepresentation("ball+stick",{colorScheme:"element",radiusScale:2,aspectRatio:1.5,bondScale:.3,bondSpacing:.75,quality:"auto"});else if(r>5&&n>15e3||n>7e5){let e=Math.min(2,Math.max(.1,6e3/(n/r)));o&&(e=Math.min(e,.5)),t.addRepresentation("surface",{colorScheme:a,colorScale:c,colorReverse:l,sele:"polymer",surfaceType:"av",probeRadius:1.4,scaleFactor:e,useWorker:!1})}else n>25e4?t.addRepresentation("backbone",{colorScheme:a,colorScale:c,colorReverse:l,lineOnly:!0}):n>1e5?t.addRepresentation("backbone",{colorScheme:a,colorScale:c,colorReverse:l,quality:"low",disableImpostor:!0,radiusScale:2}):n>8e4?t.addRepresentation("backbone",{colorScheme:a,colorScale:c,colorReverse:l,radiusScale:2}):(t.addRepresentation("cartoon",{colorScheme:a,colorScale:c,colorReverse:l,radiusScale:.7,aspectRatio:5,quality:"auto"}),n<5e4&&t.addRepresentation("base",{colorScheme:a,colorScale:c,colorReverse:l,quality:"auto"}),t.addRepresentation("ball+stick",{sele:"ligand",colorScheme:"element",radiusScale:2,aspectRatio:1.5,bondScale:.3,bondSpacing:.75,quality:"auto"}));t.structure.frames.length&&t.addTrajectory()}else(t instanceof Bl||t instanceof Dl)&&t.addRepresentation("surface");this.tasks.onZeroOnce(this.autoView,this)}loadFile(t,e={}){const i=Object.assign({},this.defaultFileParams,e),r=ri(t).name;this.tasks.increment(),this.log(`loading file '${r}'`);const s=st(i.ext,ri(t).ext);let n;return n=ze.isTrajectory(s)?Promise.reject(new Error(`loadFile: ext '${s}' is a trajectory and must be loaded into a structure component`)):ni(t,i),n.then((t=>{this.log(`loaded '${r}'`);const e=this.addComponentFromObject(t,i);return i.defaultRepresentation&&this.defaultFileRepresentation(e),this.tasks.decrement(),e}),(t=>{this.tasks.decrement();const e=`error loading file: '${t}'`;throw this.log(e),e}))}loadScript(t){const e=ri(t).name;return this.log(`loading script '${e}'`),ni(t).then((t=>{this.tasks.increment(),this.log(`running script '${e}'`),t.run(this).then((()=>{this.tasks.decrement(),this.log(`finished script '${e}'`)})),this.log(`called script '${e}'`)}),(t=>{this.tasks.decrement();const i=`errored script '${e}' "${t}"`;throw this.log(i),i}))}addComponent(t){t?(this.compList.push(t),this.signals.componentAdded.dispatch(t)):Me.warn("Stage.addComponent: no component given")}addComponentFromObject(t,e={}){const i=Ue.get(t.type);if(i){const r=new i(this,t,e);return this.addComponent(r),r}Me.warn("no component for object type",t.type)}removeComponent(t){const e=this.compList.indexOf(t);-1!==e&&(this.compList.splice(e,1),t.dispose(),this.signals.componentRemoved.dispatch(t))}removeAllComponents(){this.compList.slice().forEach((t=>this.removeComponent(t)))}handleResize(){this.viewer.handleResize()}setSize(t,e){const i=this.viewer.container;i!==document.body&&(void 0!==t&&(i.style.width=t),void 0!==e&&(i.style.height=e),this.handleResize())}toggleFullscreen(t){if(!(document.fullscreenEnabled||document.mozFullScreenEnabled||document.webkitFullscreenEnabled||document.msFullscreenEnabled))return void Me.log("fullscreen mode (currently) not possible");const e=this;function i(){return document.fullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement||document.msFullscreenElement}function r(){if(!i()&&e.lastFullscreenElement){const t=e.lastFullscreenElement;t.style.width=t.dataset.normalWidth||"",t.style.height=t.dataset.normalHeight||"",document.removeEventListener("fullscreenchange",r),document.removeEventListener("mozfullscreenchange",r),document.removeEventListener("webkitfullscreenchange",r),document.removeEventListener("MSFullscreenChange",r),e.handleResize(),e.signals.fullscreenChanged.dispatch(!1)}}t=t||this.viewer.container,this.lastFullscreenElement=t,i()?document.exitFullscreen?document.exitFullscreen():document.msExitFullscreen?document.msExitFullscreen():document.mozCancelFullScreen?document.mozCancelFullScreen():document.webkitExitFullscreen&&document.webkitExitFullscreen():(t.dataset.normalWidth=t.style.width||"",t.dataset.normalHeight=t.style.height||"",t.style.width=window.screen.width+"px",t.style.height=window.screen.height+"px",t.requestFullscreen?t.requestFullscreen():t.msRequestFullscreen?t.msRequestFullscreen():t.mozRequestFullScreen?t.mozRequestFullScreen():t.webkitRequestFullscreen&&t.webkitRequestFullscreen(),document.addEventListener("fullscreenchange",r),document.addEventListener("mozfullscreenchange",r),document.addEventListener("webkitfullscreenchange",r),document.addEventListener("MSFullscreenChange",r),this.handleResize(),this.signals.fullscreenChanged.dispatch(!0),setTimeout((function(){e.handleResize()}),100))}setSpin(t){t?(this.spinAnimation.resume(!0),this.rockAnimation.pause(!0)):this.spinAnimation.pause(!0)}setRock(t){t?(this.rockAnimation.resume(!0),this.spinAnimation.pause(!0)):this.rockAnimation.pause(!0)}toggleSpin(){this.setSpin(this.spinAnimation.paused)}toggleRock(){this.setRock(this.rockAnimation.paused)}getFocus(){const t=this.parameters;if("scene"!==t.clipMode)return 0;let e=t.clipNear;return"absolute"===t.clipScale&&(e=this.viewer.absoluteToRelative(e)),2*e}setFocus(t){if("scene"!==this.parameters.clipMode)return;let e,i,r,s;"relative"===this.parameters.clipScale?(e=Dt(t/2,0,49.9),i=100-e,r=50,s=function(t){return Dt(t,0,100)}(2*i-50)):(e=this.viewer.relativeToAbsolute(t/2),i=e,r=0,s=2*i),this.setParameters({clipNear:e,clipFar:i,fogNear:r,fogFar:s})}getZoomForBox(t){const e=t.getSize(Rl),i=Math.max(e.x,e.y,e.z),r=Math.min(e.x,e.y,e.z);let s=i+Math.sqrt(r);const n=kt(this.viewer.perspectiveCamera.fov),o=this.viewer.width,a=this.viewer.height,c=a{this.tasks.onZeroOnce((()=>{this.tasks.increment(),this.viewer.makeImage(t).then((t=>{this.tasks.decrement(),e(t)})).catch((t=>{this.tasks.decrement(),i(t)}))}))}))}setImpostor(t){this.parameters.impostor=t;const e=["spacefill","ball+stick","licorice","hyperball","backbone","rocket","helixorient","contact","distance","dot"];this.eachRepresentation((function(i){if(!e.includes(i.getType()))return;const r=i.getParameters();r.disableImpostor=!t,i.build(r)}))}setQuality(t){this.parameters.quality=t;const e=["tube","cartoon","ribbon","trace","rope"],i=["spacefill","ball+stick","licorice","hyperball","backbone","rocket","helixorient","contact","distance","dot"];this.eachRepresentation((function(r){const s=r.getParameters();if(!e.includes(r.getType())){if(!i.includes(r.getType()))return;if(!s.disableImpostor)return void(r.repr.quality=t)}s.quality=t,r.build(s)}))}eachComponent(t,e){this.compList.slice().forEach((i=>{void 0!==e&&e!==i.type||t(i)}))}eachRepresentation(t,e){this.eachComponent((i=>{i.reprList.slice().forEach((r=>{void 0!==e&&e!==r.getType()||t(r,i)}))}))}getComponentsByName(t){const e=[];return this.eachComponent((i=>{(void 0===t||Ol(t,i))&&e.push(i)})),new $l(e)}getComponentsByObject(t){const e=[];return this.eachComponent((i=>{i.object===t&&e.push(i)})),new $l(e)}getRepresentationsByName(t){const e=[];return this.eachRepresentation(((i,r)=>{(void 0===t||Ol(t,i))&&e.push(i)})),new dl(e)}measureClear(){this.eachComponent((t=>t.measureClear()),"structure")}measureUpdate(){this.eachComponent((t=>t.measureUpdate()),"structure")}dispose(){this.tasks.dispose(),this.viewer.dispose(),this.mouseObserver.dispose()}}class Ll extends ll{constructor(t,e,i={}){super(t,e,Object.assign({name:e.name},i)),this.shape=e}get type(){return"shape"}addRepresentation(t,e={}){return this._addRepresentation(t,this.shape,e)}getBoxUntransformed(){return this.shape.boundingBox}getCenterUntransformed(){return this.shape.center}dispose(){this.shape.dispose(),super.dispose()}}function Nl(t,e,i,r){var s,n=arguments.length,o=n<3?e:null===r?r=Object.getOwnPropertyDescriptor(e,i):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(t,e,i,r);else for(var a=t.length-1;a>=0;a--)(s=t[a])&&(o=(n<3?s(o):n>3?s(e,i,o):s(e,i))||o);return n>3&&o&&Object.defineProperty(e,i,o),o}Ue.add("shape",Ll);class zl extends zt{constructor(t){super(t),t.scale||(this.parameters.scale="rainbow",this.parameters.reverse=st(t.reverse,!0)),this.scalePerModel={},t.structure.eachModel((t=>{this.parameters.domain=[t.atomOffset,t.atomEnd],this.scalePerModel[t.index]=this.getScale()}))}atomColor(t){return this.scalePerModel[t.modelIndex](t.index)}}Nl([Nt],zl.prototype,"atomColor",null),Fe.add("atomindex",zl);class Vl extends zt{constructor(t){if(super(t),t.scale||(this.parameters.scale="OrRd"),!t.domain){let e,i=1/0,r=-1/0;t.sele&&(e=new pe(t.sele)),t.structure.eachAtom((function(t){const e=t.bfactor;i=Math.min(i,e),r=Math.max(r,e)}),e),this.parameters.domain=[i,r]}this.bfactorScale=this.getScale()}atomColor(t){return this.bfactorScale(t.bfactor)}}Nl([Nt],Vl.prototype,"atomColor",null),Fe.add("bfactor",Vl);class Gl extends zt{constructor(t){super(t),this.chainidDictPerModel={},this.scalePerModel={},t.scale||(this.parameters.scale="Spectral"),t.structure.eachModel((t=>{let e=0;const i={};t.eachChain((function(t){void 0===i[t.chainid]&&(i[t.chainid]=e,e+=1)})),this.parameters.domain=[0,e-1],this.chainidDictPerModel[t.index]=i,this.scalePerModel[t.index]=this.getScale()}))}atomColor(t){const e=this.chainidDictPerModel[t.modelIndex];return this.scalePerModel[t.modelIndex](e[t.chainid])}}Nl([Nt],Gl.prototype,"atomColor",null),Fe.add("chainid",Gl);class Ul extends zt{constructor(t){super(t),this.scalePerModel={},t.scale||(this.parameters.scale="Spectral"),t.structure.eachModel((t=>{this.parameters.domain=[t.chainOffset,t.chainEnd],this.scalePerModel[t.index]=this.getScale()}))}atomColor(t){return this.scalePerModel[t.modelIndex](t.chainIndex)}}Nl([Nt],Ul.prototype,"atomColor",null),Fe.add("chainindex",Ul);class jl extends zt{constructor(t){super(t),this.chainnameDictPerModel={},this.scalePerModel={},t.scale||(this.parameters.scale="Spectral"),t.structure.eachModel((t=>{let e=0;const i={};t.eachChain((function(t){void 0===i[t.chainname]&&(i[t.chainname]=e,e+=1)})),this.parameters.domain=[0,e-1],this.chainnameDictPerModel[t.index]=i,this.scalePerModel[t.index]=this.getScale()}))}atomColor(t){const e=this.chainnameDictPerModel[t.modelIndex];return this.scalePerModel[t.modelIndex](e[t.chainname])}}Nl([Nt],jl.prototype,"atomColor",null),Fe.add("chainname",jl);class Hl extends zt{constructor(t){super(t),this.rsrzDict={},this.rsccDict={},t.scale||(this.parameters.scale="RdYlBu"),this.rsrzScale=this.getScale({domain:[2,0]}),this.rsccScale=this.getScale({domain:[.678,1]});const e=t.structure.validation;e&&(this.rsrzDict=e.rsrzDict,this.rsccDict=e.rsccDict)}atomColor(t){let e=t.resno+"";t.inscode&&(e+="^"+t.inscode),t.chainname&&(e+=":"+t.chainname),e+="/"+t.modelIndex;const i=this.rsrzDict[e];if(void 0!==i)return this.rsrzScale(i);const r=this.rsccDict[e];return void 0!==r?this.rsccScale(r):9474192}}Nl([Nt],Hl.prototype,"atomColor",null),Fe.add("densityfit",Hl);const Wl={ARG:{CD:.1,CZ:.5,NE:-.1},ASN:{CG:.55,OD1:-.55},ASP:{CB:-.16,CG:.36,OD1:-.6,OD2:-.6},CYS:{CB:.19,SG:-.19},GLN:{CD:.55,OE1:-.55},GLU:{CD:.36,CG:-.16,OE1:-.6,OE2:-.6},HIS:{CB:.1,CD2:.2,CE1:.45,CG:.15,ND1:.05,NE2:.05},LYS:{CE:.25,NZ:.75},MET:{CE:.06,CG:.06,SD:-.12},PTR:{C:.55,CA:.1,CZ:.25,N:-.35,O:-.55,O1P:-.85,O2P:-.85,O3P:-.85,OG1:-1.1,P:1.4},SEP:{C:.55,CA:.1,CB:.25,N:-.35,O:-.55,O1P:-.85,O2P:-.85,O3P:-.85,OG1:-1.1,P:1.4},SER:{CB:.25,OG:-.25},THR:{CB:.25,OG1:-.25},TPO:{C:.55,CA:.1,CB:.25,N:-.35,O:-.55,OG1:-1.1,O1P:-.85,O2P:-.85,O3P:-.85,P:1.4},TRP:{CD1:.06,CD2:.1,CE2:-.04,CE3:-.03,CG:-.03,NE1:-.06},TYR:{CZ:.25,OH:-.25},backbone:{C:.55,O:-.55,N:-.35,CA:.1}};class ql extends zt{constructor(t){super(t),this.delta=new e,this.hCharges=[],t.scale||(this.parameters.scale="rwb"),t.domain||(this.parameters.domain=[-50,50]),this.scale=this.getScale(),this.charges=new Float32Array(t.structure.atomCount);const i=[];t.structure.eachAtom((t=>{var r;if(this.charges[t.index]=(null!==(r=t).partialCharge?r.partialCharge:r.isProtein()&&(Wl[r.resname]&&Wl[r.resname][r.atomname]||Wl.backbone[r.atomname])||0)*t.occupancy,"N"===t.atomname){if(t.bondCount>=3)return;if(t.bondToElementCount(1))return;const r=function(t,i=new e){let r=!1,s=!1,n=!1;return i.set(2*t.x,2*t.y,2*t.z),t.eachBondedAtom((function(t){if(!r)return"H"===t.atomname?(i.set(t.x,t.y,t.z),void(r=!0)):void(s||"CA"!==t.atomname?n||"C"!==t.atomname||(n=!0,i.sub(t)):(i.sub(t),s=!0))})),r?i:s&&n?(i.normalize(),i.multiplyScalar(1.04),i.add(t),i):void 0}(t);void 0!==r&&(i.push(r),this.hCharges.push(.25*t.occupancy))}}));const r=t.structure.getBoundingBox();r.expandByScalar(1.04),this.hStore=function(t){const e=t.length,i=new Float32Array(e),r=new Float32Array(e),s=new Float32Array(e);for(let e=0;e{const s=e[t];0!==s&&(r+=s/i)})),this.hHash.eachWithin(t.x,t.y,t.z,12,((t,e)=>{const s=i[t];0!==s&&(r+=s/e)})),this.scale(332*r)}}Nl([Nt],ql.prototype,"positionColor",null),Fe.add("electrostatic",ql);const Xl={H:16777215,HE:14286847,LI:13402367,BE:12779264,B:16758197,C:9474192,N:3166456,O:16715021,F:9494608,NE:11789301,NA:11230450,MG:9109248,AL:12560038,SI:1578e4,P:16744448,S:16777008,CL:2093087,AR:8442339,K:9388244,CA:4062976,SC:15132390,TI:12567239,V:10921643,CR:9083335,MN:10255047,FE:14706227,CO:15765664,NI:5296208,CU:13140019,ZN:8224944,GA:12750735,GE:6721423,AS:12419299,SE:16752896,BR:10889513,KR:6076625,RB:7351984,SR:65280,Y:9764863,ZR:9756896,NB:7586505,MO:5551541,TC:3907230,RU:2396047,RH:687500,PD:27013,AG:12632256,CD:16767375,IN:10909043,SN:6717568,SB:10380213,TE:13924864,I:9699476,XE:9699476,CS:5707663,BA:51456,LA:7394559,CE:16777159,PR:14286791,ND:13107143,PM:10747847,SM:9437127,EU:6422471,GD:4587463,TB:3211207,DY:2097095,HO:65436,ER:58997,TM:54354,YB:48952,LU:43812,HF:5096191,TA:5089023,W:2200790,RE:2522539,OS:2516630,IR:1528967,PT:13684960,AU:16765219,HG:12105936,TL:10900557,PB:5724513,BI:10375093,PO:11230208,AT:7688005,RN:4358806,FR:4325478,RA:32e3,AC:7384058,TH:47871,PA:41471,U:36863,NP:33023,PU:27647,AM:5528818,CM:7888099,BK:9064419,CF:10565332,ES:11739092,FM:11739066,MD:11734438,NO:12389767,LR:13041766,RF:13369433,DB:13697103,SG:14221381,BH:14680120,HS:15073326,MT:15400998,DS:16777215,RG:16777215,CN:16777215,UUT:16777215,FL:16777215,UUP:16777215,LV:16777215,UUH:16777215,D:16777152,T:16777120};class Yl extends zt{constructor(t){t.value=st(t.value,Xl.C),super(t)}atomColor(t){const e=t.element;return"C"===e?this.parameters.value:Xl[e]||16777215}}Nl([Nt],Yl.prototype,"atomColor",null),Fe.add("element",Yl);class Kl extends zt{constructor(t){super(t),t.scale||(this.parameters.scale="Spectral"),t.domain||(this.parameters.domain=[0,t.structure.entityList.length-1]),this.entityindexScale=this.getScale()}atomColor(t){return this.entityindexScale(t.entityIndex)}}Nl([Nt],Kl.prototype,"atomColor",null),Fe.add("entityindex",Kl);class Zl extends zt{atomColor(t){const e=t.entity;switch(e?e.entityType:void 0){case 1:return 8374655;case 2:return 16629894;case 3:return 12496596;case 4:return 3697840;default:return 16777113}}}Nl([Nt],Zl.prototype,"atomColor",null),Fe.add("entitytype",Zl);class Ql extends zt{constructor(t){super(t),this.geoAtomDict={},this.geoDict={};const e=t.structure.validation;e&&(this.geoAtomDict=e.geoAtomDict,this.geoDict=e.geoDict)}atomColor(t){let e,i=t.resno+"";t.inscode&&(i+="^"+t.inscode),t.chainname&&(i+=":"+t.chainname),i+="/"+t.modelIndex;const r=this.geoAtomDict[i];if(void 0!==r){const i=r[t.atomname]||0;s=i,e=16843009*((s=(858993459&(s-=s>>1&1431655765))+(s>>2&858993459))+(s>>4)&252645135)>>24}else e=this.geoDict[i]||0;var s;return 0===e?2188972:1===e?16703627:2===e?16018755:e>=3?10813478:9474192}}Nl([Nt],Ql.prototype,"atomColor",null),Fe.add("geoquality",Ql);class Jl extends zt{constructor(t){super(t),this.resHF={},t.scale||(this.parameters.scale="RdYlGn");for(const t in Js)this.resHF[t]=Js[t][0];if(this.defaultResidueHydrophobicity=tn[0],!t.domain){let t=1/0,e=-1/0;for(const i in this.resHF){const r=this.resHF[i];t=Math.min(t,r),e=Math.max(e,r)}this.parameters.domain=[t,0,e]}this.hfScale=this.getScale()}atomColor(t){return this.hfScale(this.resHF[t.resname]||this.defaultResidueHydrophobicity)}}Nl([Nt],Jl.prototype,"atomColor",null),Fe.add("hydrophobicity",Jl);class th extends zt{constructor(t){super(t),t.scale||(this.parameters.scale="rainbow"),t.domain||(this.parameters.domain=[0,t.structure.modelStore.count]),this.modelindexScale=this.getScale()}atomColor(t){return this.modelindexScale(t.modelIndex)}}Nl([Nt],th.prototype,"atomColor",null),Fe.add("modelindex",th);class eh extends zt{atomColor(t){switch(t.residueType.moleculeType){case 1:return 3697840;case 2:return 15729279;case 3:return 12496596;case 4:return 16629894;case 5:return 12540695;case 6:return 8374655;default:return 16777113}}}Nl([Nt],eh.prototype,"atomColor",null),Fe.add("moleculetype",eh);class ih extends zt{constructor(t){super(t),t.scale||(this.parameters.scale="PuBu"),t.domain||(this.parameters.domain=[0,1]),this.occupancyScale=this.getScale()}atomColor(t){return this.occupancyScale(t.occupancy)}}Nl([Nt],ih.prototype,"atomColor",null),Fe.add("occupancy",ih);class rh extends zt{constructor(t){super(t),t.scale||(this.parameters.scale="rwb"),t.domain||(this.parameters.domain=[-1,1]),this.partialchargeScale=this.getScale()}atomColor(t){return this.partialchargeScale(t.partialCharge||0)}}function sh(){return 16777215*Math.random()}Nl([Nt],rh.prototype,"atomColor",null),Fe.add("partialcharge",rh);class nh extends zt{atomColor(){return sh()}volumeColor(){return sh()}positionColor(){return sh()}}Nl([Nt],nh.prototype,"atomColor",null),Nl([Nt],nh.prototype,"volumeColor",null),Nl([Nt],nh.prototype,"positionColor",null),Fe.add("random",nh);class oh extends zt{constructor(t){super(t),this.rciDict={},t.scale||(this.parameters.scale="RdYlBu"),this.rciScale=this.getScale({domain:[.6,0]});const e=t.structure.validation;e&&(this.rciDict=e.rciDict)}atomColor(t){let e=`[${t.resname}]${t.resno}`;t.chainname&&(e+=":"+t.chainname);const i=this.rciDict[e];return void 0!==i?this.rciScale(i):9474192}}Nl([Nt],oh.prototype,"atomColor",null),Fe.add("randomcoilindex",oh);class ah extends zt{constructor(t){super(t),this.scalePerChain={},t.scale||(this.parameters.scale="rainbow",this.parameters.reverse=st(t.reverse,!0)),t.structure.eachChain((t=>{this.parameters.domain=[t.residueOffset,t.residueEnd],this.scalePerChain[t.index]=this.getScale()}))}atomColor(t){return this.scalePerChain[t.chainIndex](t.residueIndex)}}Nl([Nt],ah.prototype,"atomColor",null),Fe.add("residueindex",ah);const ch={ALA:9240460,ARG:124,ASN:16743536,ASP:10485826,CYS:16777072,GLN:16731212,GLU:6684672,GLY:16777215,HIS:7368959,ILE:19456,LEU:4546117,LYS:4671416,MET:12099650,PHE:5459026,PRO:5395026,SER:16740418,THR:12078080,TRP:5195264,TYR:9203788,VAL:16747775,ASX:16711935,GLX:16711935,ASH:16711935,GLH:16711935,A:14423100,G:3329330,I:10145074,X:8190976,C:16766720,T:4286945,U:4251856,D:35723,DA:14423100,DG:3329330,DI:10145074,DX:8190976,DC:16766720,DT:4286945,DU:4251856,DD:35723};class lh extends zt{atomColor(t){return ch[t.resname]||16711935}}Nl([Nt],lh.prototype,"atomColor",null),Fe.add("resname",lh);const hh=16711808,dh=10485888,uh=6291584,mh=16762880,ph=6324479,fh=16777215,gh=11403518,yh=16580962,bh=10921722;class xh extends zt{constructor(t){super(t),this.residueProxy=t.structure.getResidueProxy()}atomColor(t){const e=t.sstruc,i=this.residueProxy;return"h"===e?hh:"g"===e?dh:"i"===e?uh:"e"===e||"b"===e?mh:"t"===e?ph:(i.index=t.residueIndex,i.isDna()?gh:i.isRna()?yh:i.isSaccharide()?bh:i.isProtein()||"s"===e||"l"===e?fh:8421504)}}Nl([Nt],xh.prototype,"atomColor",null),Fe.add("sstruc",xh);class vh extends zt{constructor(t){var e,i;super(t),t.scale||(this.parameters.scale="rwb"),this.atomData=null===(e=this.parameters.data)||void 0===e?void 0:e.atomData,this.bondData=null===(i=this.parameters.data)||void 0===i?void 0:i.bondData,this.scale=this.getScale(this.parameters)}atomColor(t){var e;const i=null===(e=this.atomData)||void 0===e?void 0:e[t.index];return void 0!==i?this.scale(i):this.parameters.value}bondColor(t,e){var i;const r=null===(i=this.bondData)||void 0===i?void 0:i[t.index];return void 0!==r?this.scale(r):this.atomProxy?(this.atomProxy.index=e?t.atomIndex1:t.atomIndex2,this.atomColor(this.atomProxy)):this.parameters.value}}Nl([Nt],vh.prototype,"atomColor",null),Nl([Nt],vh.prototype,"bondColor",null),Fe.add("structuredata",vh);class wh extends zt{atomColor(){return this.parameters.value}bondColor(){return this.parameters.value}valueColor(){return this.parameters.value}volumeColor(){return this.parameters.value}}Nl([Nt],wh.prototype,"atomColor",null),Nl([Nt],wh.prototype,"bondColor",null),Nl([Nt],wh.prototype,"valueColor",null),Nl([Nt],wh.prototype,"volumeColor",null),Fe.add("uniform",wh);class Ah extends zt{constructor(t){super(t),this.valueScale=this.getScale()}volumeColor(t){return this.valueScale(this.parameters.volume.data[t])}}Nl([Nt],Ah.prototype,"volumeColor",null),Fe.add("value",Ah);class _h extends zt{constructor(t){super(t),this.vec=new e,this.valueScale=this.getScale()}positionColor(t){const e=this.parameters.volume;if(!e||!e.inverseMatrix)return this.parameters.value;const i=this.vec,r=e.data,s=e.nx,n=e.ny,o=s*n;i.copy(t),i.applyMatrix4(e.inverseMatrix);const a=Math.floor(i.x),c=Math.floor(i.y),l=Math.floor(i.z),h=(l*n+c)*s+a,d=h+1,u=h+s,m=h+o,p=u+1,f=m+1,g=u+o,y=g+1,b=r[h],x=r[d],v=r[u],w=r[m],A=r[p],_=r[f],S=r[g],C=r[y],P=i.x-a,I=i.y-c,k=i.z-l,M=$t(b,x,P),T=$t(w,_,P),B=$t(v,A,P),D=$t(S,C,P),$=$t(M,B,I),O=$t(T,D,I),R=$t($,O,k);return this.valueScale(R)}}Nl([Nt],_h.prototype,"positionColor",null),Fe.add("volume",_h);class Sh extends zr{constructor(t,e,i){const r=i||{};if(super(t,e,r),this.type="structure",this.parameters=Object.assign({radiusType:{type:"select",options:pa.types},radiusData:{type:"hidden"},radiusSize:{type:"number",precision:3,max:10,min:.001},radiusScale:{type:"number",precision:3,max:10,min:.001},assembly:null,defaultAssembly:{type:"hidden"}},this.parameters),this.selection=new pe(r.sele),this.dataList=[],this.structure=t,this.structureView=this.structure.getView(this.selection),t.biomolDict){const e={default:"default","":t.unitcell?"AU":"FULL"};Object.keys(t.biomolDict).forEach((function(t){e[t]=t})),this.parameters.assembly={type:"select",options:e,rebuild:!0}}else this.parameters.assembly=null}get defaultScale(){return{vdw:1,covalent:1,bfactor:.01,sstruc:1}}init(t){const e=t||{};e.colorScheme=st(e.colorScheme,"element"),this.setRadius(e.radius,e),this.radiusType=st(e.radiusType,"vdw"),this.radiusData=st(e.radiusData,{}),this.radiusSize=st(e.radiusSize,1),this.radiusScale=st(e.radiusScale,1),this.assembly=st(e.assembly,"default"),this.defaultAssembly=st(e.defaultAssembly,""),"auto"===e.quality&&(e.quality=this.getQuality()),super.init(e),this.selection.signals.stringChanged.add((()=>{this.build()})),this.build()}setRadius(t,e){const i=Object.keys(ma);return"string"==typeof t&&i.includes(t.toLowerCase())?e.radiusType=t:void 0!==t&&(e.radiusType="size",e.radiusSize=t),this}getAssembly(){const t="default"===this.assembly?this.defaultAssembly:this.assembly;return this.structure.biomolDict[t]}getQuality(){let t;const e=this.structureView,i=this.getAssembly();t=i?i.getAtomCount(e):e.atomCount,Se&&(t*=4);return e.atomStore.count/e.residueStore.count<2&&(t*=10),t<15e3?"high":t<8e4?"medium":"low"}create(){if(0===this.structureView.atomCount)return;if(!this.structureView.hasCoords())return void(this.needsBuild=!0);this.needsBuild=!1;const t=this.getAssembly();if(t)t.partList.forEach(((t,e)=>{const i=t.getView(this.structureView);if(0===i.atomCount)return;const r=this.createData(i,e);r&&(r.sview=i,r.instanceList=t.getInstanceList(),this.dataList.push(r))}));else{const t=this.createData(this.structureView,0);t&&(t.sview=this.structureView,this.dataList.push(t))}}update(t){!this.lazy||this.visible?this.needsBuild?this.build():this.dataList.forEach((e=>{e.bufferList.length>0&&this.updateData(t,e)}),this):Object.assign(this.lazyProps.what,t)}updateData(t,e){this.build()}getColorParams(){return Object.assign(Object.assign({},super.getColorParams()),{structure:this.structure})}getRadiusParams(t){return{type:this.radiusType,scale:this.radiusScale,size:this.radiusSize,data:this.radiusData}}getAtomParams(t,e){return Object.assign({what:t,colorParams:this.getColorParams(),radiusParams:this.getRadiusParams()},e)}getBondParams(t,e){return Object.assign({what:t,colorParams:this.getColorParams(),radiusParams:this.getRadiusParams()},e)}getAtomRadius(t){if(this.structureView.atomSet.isSet(t.index)){return new pa(this.getRadiusParams()).atomRadius(t)}return 0}setSelection(t,e){return this.selection.setString(t,e),this}setParameters(t,e={},i=!1){const r=t||{};return this.setRadius(r.radius,r),void 0===r.radiusType&&void 0===r.radiusData&&void 0===r.radiusSize&&void 0===r.radiusScale||(e.radius=!0,Ie&&!this.disableImpostor||(i=!0)),void 0!==r.defaultAssembly&&r.defaultAssembly!==this.defaultAssembly&&("default"===this.assembly&&void 0===r.assembly||"default"===r.assembly)&&(i=!0),super.setParameters(r,e,i),this}getParameters(){return Object.assign(super.getParameters(),{sele:this.selection?this.selection.string:void 0,defaultAssembly:this.defaultAssembly})}attach(t){const e=this.viewer,i=this.bufferList;this.dataList.forEach((function(t){t.bufferList.forEach((function(r){i.push(r),e.add(r,t.instanceList)}))})),this.setVisibility(this.visible),t()}clear(){this.dataList.length=0,super.clear()}dispose(){this.structureView.dispose(),super.dispose()}}class Ch extends Sh{constructor(t,e,i){super(t,e,i),this.n=0,this.parameters=Object.assign({labelVisible:{type:"boolean"},labelSize:{type:"number",precision:3,max:10,min:.001},labelColor:{type:"color"},labelFontFamily:{type:"select",options:{"sans-serif":"sans-serif",monospace:"monospace",serif:"serif"},buffer:"fontFamily"},labelFontStyle:{type:"select",options:{normal:"normal",italic:"italic"},buffer:"fontStyle"},labelFontWeight:{type:"select",options:{normal:"normal",bold:"bold"},buffer:"fontWeight"},labelsdf:{type:"boolean",buffer:"sdf"},labelXOffset:{type:"number",precision:1,max:20,min:-20,buffer:"xOffset"},labelYOffset:{type:"number",precision:1,max:20,min:-20,buffer:"yOffset"},labelZOffset:{type:"number",precision:1,max:20,min:-20,buffer:"zOffset"},labelAttachment:{type:"select",options:{"bottom-left":"bottom-left","bottom-center":"bottom-center","bottom-right":"bottom-right","middle-left":"middle-left","middle-center":"middle-center","middle-right":"middle-right","top-left":"top-left","top-center":"top-center","top-right":"top-right"},rebuild:!0},labelBorder:{type:"boolean",buffer:"showBorder"},labelBorderColor:{type:"color",buffer:"borderColor"},labelBorderWidth:{type:"number",precision:2,max:.3,min:0,buffer:"borderWidth"},labelBackground:{type:"boolean",rebuild:!0},labelBackgroundColor:{type:"color",buffer:"backgroundColor"},labelBackgroundMargin:{type:"number",precision:2,max:2,min:0,rebuild:!0},labelBackgroundOpacity:{type:"range",step:.01,max:1,min:0,buffer:"backgroundOpacity"},labelFixedSize:{type:"boolean",buffer:"fixedSize"},lineOpacity:{type:"range",min:0,max:1,step:.01},linewidth:{type:"integer",max:50,min:1,buffer:!0}},this.parameters,{flatShaded:null})}init(t){const e=t||{};this.labelVisible=st(e.labelVisible,!0),this.labelSize=st(e.labelSize,2),this.labelColor=st(e.labelColor,16777215),this.labelFontFamily=st(e.labelFontFamily,"sans-serif"),this.labelFontStyle=st(e.labelFontstyle,"normal"),this.labelFontWeight=st(e.labelFontWeight,"bold"),this.labelsdf=st(e.labelsdf,"Chrome"===Ae),this.labelXOffset=st(e.labelXOffset,0),this.labelYOffset=st(e.labelYOffset,0),this.labelZOffset=st(e.labelZOffset,.5),this.labelAttachment=st(e.labelAttachment,"bottom-left"),this.labelBorder=st(e.labelBorder,!1),this.labelBorderColor=st(e.labelBorderColor,"lightgrey"),this.labelBorderWidth=st(e.labelBorderWidth,.15),this.labelBackground=st(e.labelBackground,!1),this.labelBackgroundColor=st(e.labelBackgroundColor,"lightgrey"),this.labelBackgroundMargin=st(e.labelBackgroundMargin,.5),this.labelBackgroundOpacity=st(e.labelBackgroundOpacity,1),this.labelFixedSize=st(e.labelFixedSize,!1),this.lineOpacity=st(e.lineOpacity,1),this.linewidth=st(e.linewidth,2),super.init(e)}update(t){t.position?this.build():super.update(t)}updateData(t,e){const i={};if(t&&!t.labelSize||Object.assign(i,{size:Si(this.n,this.labelSize)}),!t||t.labelColor){const t=new s(this.labelColor);Object.assign(i,{color:Ci(this.n,t.r,t.g,t.b)})}this.textBuffer.setAttributes(i)}setParameters(t,e={},i=!1){return t&&t.labelSize&&(e.labelSize=!0),t&&(t.labelColor||0===t.labelColor)&&(e.labelColor=!0,i=!0),super.setParameters(t,e,i),t&&void 0!==t.opacity&&this.textBuffer.setParameters({opacity:1}),t&&void 0!==t.labelVisible&&this.setVisibility(this.visible),this}setVisibility(t,e){return super.setVisibility(t,!0),this.textBuffer&&this.textBuffer.setVisibility(this.labelVisible&&this.visible),e||this.viewer.requestRender(),this}getLabelBufferParams(t={}){return super.getBufferParams(Object.assign({fontFamily:this.labelFontFamily,fontStyle:this.labelFontStyle,fontWeight:this.labelFontWeight,sdf:this.labelsdf,xOffset:this.labelXOffset,yOffset:this.labelYOffset,zOffset:this.labelZOffset,attachment:this.labelAttachment,showBorder:this.labelBorder,borderColor:this.labelBorderColor,borderWidth:this.labelBorderWidth,showBackground:this.labelBackground,backgroundColor:this.labelBackgroundColor,backgroundMargin:this.labelBackgroundMargin,backgroundOpacity:this.labelBackgroundOpacity,fixedSize:this.labelFixedSize,disablePicking:!0,visible:this.labelVisible},t,{opacity:1}))}getAtomRadius(){return 0}}function Ph(t,e){const i=t.getAtomProxy(),r=new pe,s=e.length;if(0===s)return new Float32Array(0);const n=e[0].length,o=t.getAtomSet(),a=new Float32Array(s*n*3);let c=0;return e.forEach((function(e){let s=!1;for(let l=0;l 1.0 ){\ngl_FragColor = vec4( backgroundColor, backgroundOpacity );\n}else{\nfloat sdf = texture2D( fontTexture, texCoord ).a;\nif( showBorder ) sdf += borderWidth;\nfloat a = smoothstep(padding - gamma, padding + gamma, sdf);\nif( a < 0.2 ) discard;\na *= opacity;\nvec3 outgoingLight = vColor;\nif( showBorder && sdf < ( padding + borderWidth ) ){\noutgoingLight = borderColor;\n}\ngl_FragColor = vec4( outgoingLight, a );\n}\n#if defined( PICKING )\nif( opacity < 0.3 )\ndiscard;\ngl_FragColor = vec4( vPickingColor, objectId );\n#else\n#include premultiplied_alpha_fragment\n#include tonemapping_fragment\n#include encodings_fragment\n#include fog_fragment\n#endif\n}");const Th={};const Bh={font:"sans-serif",size:36,style:"normal",variant:"normal",weight:"normal",outline:3,width:1024,height:1024};class Dh{constructor(t={}){this.gamma=1,this.mapped={},this.scratchW=0,this.scratchH=0,this.currentX=0,this.currentY=0,this.cutoff=.25,this.parameters=nt(t,Bh);const e=this.parameters;this.radius=e.size/8,this.padding=e.size/3;const i=this.lineHeight=e.size+2*e.outline+Math.round(e.size/4),r=this.maxWidth=e.width/4,s=this.canvas=document.createElement("canvas");s.width=r,s.height=i;const n=this.context=this.canvas.getContext("2d");n.font=`${e.style} ${e.variant} ${e.weight} ${e.size}px ${e.font}`,n.fillStyle="black",n.textAlign="left",n.textBaseline="bottom",n.lineJoin="round",this.gridOuter=new Float64Array(i*r),this.gridInner=new Float64Array(i*r),this.f=new Float64Array(Math.max(i,r)),this.d=new Float64Array(Math.max(i,r)),this.z=new Float64Array(Math.max(i,r)+1),this.v=new Int16Array(Math.max(i,r)),this.data=new Uint8Array(e.width*e.height*4),this.canvas2=document.createElement("canvas"),this.canvas2.width=e.width,this.canvas2.height=e.height,this.context2=this.canvas2.getContext("2d"),this.placeholder=this.map(String.fromCharCode(65533));for(let t=32;t<=126;++t)this.map(String.fromCharCode(t));this.map(String.fromCharCode(176)),this.map(String.fromCharCode(8491)),this.texture=new H(this.canvas2),this.texture.flipY=!1,this.texture.needsUpdate=!0}map(t){const e=this.parameters;return void 0===this.mapped[t]&&(this.draw(t),this.currentX+this.scratchW>e.width&&(this.currentX=0,this.currentY+=this.scratchH),this.currentY+this.scratchH>e.height&&console.warn("canvas to small"),this.mapped[t]={x:this.currentX,y:this.currentY,w:this.scratchW,h:this.scratchH},this.context2.drawImage(this.canvas,0,0,this.scratchW,this.scratchH,this.currentX,this.currentY,this.scratchW,this.scratchH),this.currentX+=this.scratchW),this.mapped[t]}get(t){return this.mapped[t]||this.placeholder}draw(t){const e=this.parameters,i=this.lineHeight,r=e.outline,s=this.context,n=this.maxWidth,o=r,a=i-e.outline,c=s.measureText(t),l=Math.min(n,Math.ceil(c.width+2*o+1)),h=l*i;s.clearRect(0,0,l,i),s.fillText(t,o,a);const d=s.getImageData(0,0,l,i),u=d.data;for(let t=0;t= 0.0 ) {\ntrimSegment( start, end );\n} else if ( end.z < 0.0 && start.z >= 0.0 ) {\ntrimSegment( end, start );\n}\n}\nvec4 clipStart = projectionMatrix * start;\nvec4 clipEnd = projectionMatrix * end;\nvec2 ndcStart = clipStart.xy / clipStart.w;\nvec2 ndcEnd = clipEnd.xy / clipEnd.w;\nvec2 dir = ndcEnd - ndcStart;\ndir.x *= aspect;\ndir = normalize( dir );\nvec2 offset = vec2( dir.y, - dir.x );\ndir.x /= aspect;\noffset.x /= aspect;\nif ( mapping.x < 0.0 ) offset *= - 1.0;\noffset *= linewidth;\noffset /= resolution.y;\nvec4 clip = ( mapping.y < 0.5 ) ? clipStart : clipEnd;\noffset *= clip.w;\nclip.xy += offset;\ngl_Position = clip;\n#ifndef PICKING\nvViewPosition = ( projectionMatrixInverse * clip ).xyz;\n#endif\n#if defined( RADIUS_CLIP )\nvClipCenter = -( modelViewMatrix * vec4( clipCenter, 1.0 ) ).xyz;\n#endif\n#include nearclip_vertex\n}"),Ve.add("shader/WideLine.frag","uniform vec3 diffuse;\nuniform float opacity;\nuniform float clipNear;\nuniform float clipRadius;\n#if defined( RADIUS_CLIP )\nvarying vec3 vClipCenter;\n#endif\n#ifdef PICKING\nuniform float objectId;\nvarying vec3 vPickingColor;\n#else\n#include common\n#include fog_pars_fragment\nvarying vec3 vViewPosition;\nvarying vec3 vColor;\nvarying vec3 vColor2;\nvarying float flag;\n#endif\nvoid main() {\n#include nearclip_fragment\n#include radiusclip_fragment\n#if defined( PICKING )\nif( opacity < 0.3 )\ndiscard;\ngl_FragColor = vec4( vPickingColor, objectId );\n#else\nvec3 outgoingLight = vec3( 0.0 );\nvec4 diffuseColor = vec4( diffuse, 1.0 );\nif ( flag < 0.0 ) {\ndiffuseColor.rgb *= vColor;\n} else {\ndiffuseColor.rgb *= vColor2;\n}\n#include alphatest_fragment\noutgoingLight = diffuseColor.rgb;\ngl_FragColor = vec4( outgoingLight, diffuseColor.a * opacity );\n#include premultiplied_alpha_fragment\n#include tonemapping_fragment\n#include encodings_fragment\n#include fog_fragment\n#endif\n}");const Fh=Object.assign({linewidth:2},zo),Lh=Object.assign({linewidth:{uniform:!0}},Vo);class Nh extends zc{constructor(e,r={}){super(e,r),this.parameterTypes=Lh,this.vertexShader="WideLine.vert",this.fragmentShader="WideLine.frag",!e.color2&&e.color&&(e.color2=e.color),this.addUniforms({linewidth:{value:this.parameters.linewidth},resolution:{value:new t},projectionMatrixInverse:{value:new i}}),this.addAttributes({position1:{type:"v3",value:null},position2:{type:"v3",value:null},color2:{type:"c",value:null}}),this.setAttributes(e),this.makeMapping()}get defaultParameters(){return Fh}setParameters(t){super.setParameters(t)}}je.add("wideline",Nh);class zh extends Ch{constructor(t,e,i){super(t,e,i),this.type="angle",this.parameters=Object.assign({atomTriple:{type:"hidden",rebuild:!0},vectorVisible:{type:"boolean",default:!0},arcVisible:{type:"boolean",default:!0},sectorVisible:{type:"boolean",default:!0}},this.parameters),this.init(i)}init(t){const e=t||{};e.side=st(e.side,"double"),e.opacity=st(e.opacity,.5),this.atomTriple=st(e.atomTriple,[]),this.arcVisible=st(e.arcVisible,!0),this.sectorVisible=st(e.sectorVisible,!0),this.vectorVisible=st(e.vectorVisible,!0),super.init(e)}createData(t){if(!t.atomCount||!this.atomTriple.length)return;const e=function(t,e){return function(t){const e=[],i=t.length/9;for(let r=0;r radius2) {\ndiscard;\n}\n#ifdef CAP\nsurface_point = front_point;\n_normal = axis;\n#else\nsurface_point = ray_target + ( (-a1 - sqrt(d)) / a2 ) * ray_direction;\ndNV = dot(-axis, ray_direction);\nnear = dot(axis, end) / dNV;\nnew_point2 = ray_direction * near + ray_origin;\nif (dot(new_point2 - end, new_point2-base) < radius2) {\ndiscard;\n}\ninterior = true;\n#endif\n}\nif( end_cap_test > 0.0 )\n{\nfloat dNV;\nfloat near;\nvec3 end_point;\nif ( ortho == 1.0 ) {\nend_point = ray_target;\n} else {\ndNV = dot(axis, ray_direction);\nif (dNV < 0.0) {\ndiscard;\n}\nnear = dot(axis, end) / dNV;\nend_point = ray_direction * near + ray_origin;\n}\n\nif( dot(end_point - end, end_point-base) > radius2 ) {\ndiscard;\n}\n#ifdef CAP\nsurface_point = end_point;\n_normal = axis;\n#else\nsurface_point = ray_target + ( (-a1 - sqrt(d)) / a2 ) * ray_direction;\ndNV = dot(-axis, ray_direction);\nnear = dot(-axis, (base)) / dNV;\nnew_point2 = ray_direction * near + ray_origin;\nif (dot(new_point2 - base, new_point2-base) < radius2) {\ndiscard;\n}\ninterior = true;\n#endif\n}\ngl_FragDepthEXT = calcDepth( surface_point );\n\n#ifdef NEAR_CLIP\nif( calcClip( surface_point ) > 0.0 ){\ndist = (-a1 - sqrt(d)) / a2;\nsurface_point = ray_target + dist * ray_direction;\nif( calcClip( surface_point ) > 0.0 ) {\ndiscard;\n}\ninterior = true;\ngl_FragDepthEXT = calcDepth( surface_point );\nif( gl_FragDepthEXT >= 0.0 ){\ngl_FragDepthEXT = max( 0.0, calcDepth( vec3( - ( clipNear - 0.5 ) ) ) + ( 0.0000001 / vRadius ) );\n}\n}else if( gl_FragDepthEXT <= 0.0 ){\ndist = (-a1 - sqrt(d)) / a2;\nsurface_point = ray_target + dist * ray_direction;\ninterior = true;\ngl_FragDepthEXT = calcDepth( surface_point );\nif( gl_FragDepthEXT >= 0.0 ){\ngl_FragDepthEXT = 0.0 + ( 0.0000001 / vRadius );\n}\n}\n#else\nif( gl_FragDepthEXT <= 0.0 ){\ndist = (-a1 - sqrt(d)) / a2;\nsurface_point = ray_target + dist * ray_direction;\ninterior = true;\ngl_FragDepthEXT = calcDepth( surface_point );\nif( gl_FragDepthEXT >= 0.0 ){\ngl_FragDepthEXT = 0.0 + ( 0.0000001 / vRadius );\n}\n}\n#endif\nif (gl_FragDepthEXT < 0.0) {\ndiscard;\n}\nif (gl_FragDepthEXT > 1.0) {\ndiscard;\n}\n#ifdef PICKING\nif( opacity < 0.3 )\ndiscard;\ngl_FragColor = vec4( vPickingColor, objectId );\n#else\nvec3 vViewPosition = -surface_point;\nvec3 vNormal = _normal;\nvec3 vColor;\nif( distSq3( surface_point, end ) < distSq3( surface_point, base ) ){\nif( b < 0.0 ){\nvColor = vColor1;\n}else{\nvColor = vColor2;\n}\n}else{\nif( b > 0.0 ){\nvColor = vColor1;\n}else{\nvColor = vColor2;\n}\n}\nvec4 diffuseColor = vec4( diffuse, opacity );\nReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\nvec3 totalEmissiveLight = emissive;\n#include color_fragment\n#include roughnessmap_fragment\n#include metalnessmap_fragment\nvec3 normal = normalize( vNormal );\nvec3 geometryNormal = normal;\n#include lights_physical_fragment\n#include lights_fragment_begin\n#include lights_fragment_end\nvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveLight;\nif( interior ){\n#ifdef USE_INTERIOR_COLOR\noutgoingLight.xyz = interiorColor;\n#else\n#ifdef DIFFUSE_INTERIOR\noutgoingLight.xyz = vColor;\n#endif\n#endif\noutgoingLight.xyz *= 1.0 - interiorDarkening;\n}\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );\n#include premultiplied_alpha_fragment\n#include tonemapping_fragment\n#include encodings_fragment\n#include fog_fragment\n#endif\n}");const Xh=new Float32Array([-1,1,-1,-1,-1,-1,1,1,-1,1,1,1,1,-1,-1,1,-1,1]),Yh=new Uint16Array([0,1,2,1,4,2,2,4,3,4,5,3]);class Kh extends Fc{constructor(t,e={}){super("v3",t,e)}get mapping(){return Xh}get mappingIndices(){return Yh}get mappingIndicesSize(){return 12}get mappingSize(){return 6}get mappingItemSize(){return 3}}const Zh=Object.assign({openEnded:!1},zo),Qh=Object.assign({openEnded:{updateShader:!0}},Vo);class Jh extends Kh{constructor(t,e={}){super(t,e),this.parameterTypes=Qh,this.isImpostor=!0,this.vertexShader="CylinderImpostor.vert",this.fragmentShader="CylinderImpostor.frag",this.addUniforms({modelViewMatrixInverse:{value:new i},ortho:{value:0}}),this.addAttributes({position1:{type:"v3",value:null},position2:{type:"v3",value:null},color2:{type:"c",value:null},radius:{type:"f",value:null}}),this.setAttributes(t),this.makeMapping()}get defaultParameters(){return Zh}getDefines(t){const e=Kh.prototype.getDefines.call(this,t);return this.parameters.openEnded||(e.CAP=1),e}}Object.assign({disableImpostor:!1},Hh,Zh);const td=class{constructor(t,e={}){return!t.color2&&t.color&&(t.color2=t.color),!Ie||e&&e.disableImpostor?new qh(t,e):new Jh(t,e)}};je.add("cylinder",td);class ed extends Sh{constructor(t,e,i){super(t,e,i),this.type="axes",this.parameters=Object.assign({radiusSize:{type:"number",precision:3,max:10,min:.001},sphereDetail:!0,radialSegments:!0,disableImpostor:!0,showAxes:{type:"boolean",rebuild:!0},showBox:{type:"boolean",rebuild:!0}},this.parameters,{assembly:null}),this.init(i)}init(t){const e=t||{};e.radiusSize=st(e.radiusSize,.5),e.colorValue=st(e.colorValue,"lightgreen"),e.useInteriorColor=st(e.useInteriorColor,!0),this.showAxes=st(e.showAxes,!0),this.showBox=st(e.showBox,!1),super.init(e)}getPrincipalAxes(){let t;const e=this.getAssembly();return e&&(t=e.partList[0].getSelection()),this.structureView.getPrincipalAxes(t)}getAxesData(t){const i=this.getPrincipalAxes(),r=new s(this.colorValue);let n=0,o=0;this.showAxes&&(n+=6,o+=3),this.showBox&&(n+=8,o+=12);const a=new Float32Array(3*n),c=Ci(n,r.r,r.g,r.b),l=Si(n,this.radiusSize),h=new Float32Array(3*o),d=new Float32Array(3*o),u=Ci(o,r.r,r.g,r.b),m=Si(o,this.radiusSize);let p=0;if(this.showAxes){const t=function(t,e){t.toArray(a,2*p),e.toArray(a,2*p+3),t.toArray(h,p),e.toArray(d,p),p+=3};t(i.begA,i.endA),t(i.begB,i.endB),t(i.begC,i.endC)}if(this.showBox){const r=new e,{d1a:s,d2a:n,d3a:o,d1b:c,d2b:l,d3b:u}=i.getProjectedScaleForAtoms(t);let m=2*p;const f=function(t,e,s){r.copy(i.center).addScaledVector(i.normVecA,t).addScaledVector(i.normVecB,e).addScaledVector(i.normVecC,s),r.toArray(a,m),m+=3};f(s,n,o),f(s,n,u),f(s,l,u),f(s,l,o),f(c,l,u),f(c,l,o),f(c,n,o),f(c,n,u);let g=p;const y=function(t,e){r.fromArray(a,2*p+3*t).toArray(h,g),r.fromArray(a,2*p+3*e).toArray(d,g),g+=3};y(0,1),y(0,3),y(0,6),y(1,2),y(1,7),y(2,3),y(2,4),y(3,5),y(4,5),y(4,7),y(5,6),y(6,7)}const f=new Kn(i);return{vertex:{position:a,color:c,radius:l,picking:f},edge:{position1:h,position2:d,color:u,color2:u,radius:m,picking:f}}}create(){const t=this.getAxesData(this.structureView);this.sphereBuffer=new Gc(t.vertex,this.getBufferParams({sphereDetail:this.sphereDetail,disableImpostor:this.disableImpostor,dullInterior:!0})),this.cylinderBuffer=new td(t.edge,this.getBufferParams({openEnded:!0,radialSegments:this.radialSegments,disableImpostor:this.disableImpostor,dullInterior:!0})),this.dataList.push({sview:this.structureView,bufferList:[this.sphereBuffer,this.cylinderBuffer]})}createData(t){}updateData(t,e){const i=this.getAxesData(e.sview),r={},s={};t&&!t.position||(Object.assign(r,{position:i.vertex.position}),Object.assign(s,{position1:i.edge.position1,position2:i.edge.position2})),t&&!t.color||(Object.assign(r,{color:i.vertex.color}),Object.assign(s,{color:i.edge.color,color2:i.edge.color})),t&&!t.radius||(Object.assign(r,{radius:i.vertex.radius}),Object.assign(s,{radius:i.edge.radius})),this.sphereBuffer.setAttributes(r),this.cylinderBuffer.setAttributes(s)}}Ne.add("axes",ed);class id extends Sh{constructor(t,e,i){super(t,e,i),this.type="ball+stick",this.parameters=Object.assign({sphereDetail:!0,radialSegments:!0,openEnded:!0,disableImpostor:!0,aspectRatio:{type:"number",precision:1,max:10,min:1},lineOnly:{type:"boolean",rebuild:!0},cylinderOnly:{type:"boolean",rebuild:!0},multipleBond:{type:"select",rebuild:!0,options:{off:"off",symmetric:"symmetric",offset:"offset"}},bondScale:{type:"number",precision:2,max:1,min:.01},bondSpacing:{type:"number",precision:2,max:2,min:.5},linewidth:{type:"integer",max:50,min:1,buffer:!0}},this.parameters),this.init(i)}init(t){var e=t||{};e.radiusType=st(e.radiusType,"size"),e.radiusSize=st(e.radiusSize,.15),e.useInteriorColor=st(e.useInteriorColor,!0),this.aspectRatio=st(e.aspectRatio,2),this.lineOnly=st(e.lineOnly,!1),this.cylinderOnly=st(e.cylinderOnly,!1),this.multipleBond=st(e.multipleBond,"off"),this.bondSpacing=st(e.bondSpacing,1),this.bondScale=st(e.bondScale,.4),this.linewidth=st(e.linewidth,2),super.init(e)}getAtomRadius(t){return this.aspectRatio*super.getAtomRadius(t)}getAtomParams(t,e){var i=super.getAtomParams(t,e);return i.radiusParams.scale*=this.aspectRatio,i}getAtomData(t,e,i){return t.getAtomData(this.getAtomParams(e,i))}getBondParams(t,e){return e=Object.assign({multipleBond:this.multipleBond,bondSpacing:this.bondSpacing,bondScale:this.bondScale},e),super.getBondParams(t,e)}getBondData(t,e,i){return t.getBondData(this.getBondParams(e,i))}createData(t){const e=[];if(this.lineOnly)this.lineBuffer=new Nh(this.getBondData(t,{position:!0,color:!0,picking:!0}),this.getBufferParams({linewidth:this.linewidth})),e.push(this.lineBuffer);else{const i=new td(this.getBondData(t),this.getBufferParams({openEnded:this.openEnded,radialSegments:this.radialSegments,disableImpostor:this.disableImpostor,dullInterior:!0}));if(e.push(i),!this.cylinderOnly){const i=new Gc(this.getAtomData(t),this.getBufferParams({sphereDetail:this.sphereDetail,disableImpostor:this.disableImpostor,dullInterior:!0}));e.push(i)}}return{bufferList:e}}updateData(t,e){"off"!==this.multipleBond&&t&&t.radius&&(t.position=!0);const i=this.getBondData(e.sview,t);if(this.lineOnly){const r={};t&&!t.position||Object.assign(r,{position1:i.position1,position2:i.position2}),t&&!t.color||Object.assign(r,{color:i.color,color2:i.color2}),e.bufferList[0].setAttributes(r)}else{var r={};if(t&&!t.position||Object.assign(r,{position1:i.position1,position2:i.position2}),t&&!t.color||Object.assign(r,{color:i.color,color2:i.color2}),t&&!t.radius||Object.assign(r,{radius:i.radius}),e.bufferList[0].setAttributes(r),!this.cylinderOnly){var s=this.getAtomData(e.sview,t),n={};t&&!t.position||Object.assign(n,{position:s.position}),t&&!t.color||Object.assign(n,{color:s.color}),t&&!t.radius||Object.assign(n,{radius:s.radius}),e.bufferList[1].setAttributes(n)}}}setParameters(t={}){let e=!1;const i={};return(t.aspectRatio||t.bondSpacing||t.bondScale)&&(Object.assign(i,{radius:!0}),Ie&&!this.disableImpostor||(e=!0)),super.setParameters(t,i,e),this}}Ne.add("ball+stick",id);class rd extends id{constructor(t,e,i){super(t,e,i),this.type="backbone",this.parameters=Object.assign({},this.parameters,{multipleBond:null,bondSpacing:null}),this.init(i)}init(t){var e=t||{};e.aspectRatio=st(e.aspectRatio,1),e.radiusSize=st(e.radiusSize,.25),super.init(e)}getAtomRadius(t){return t.isTrace()?super.getAtomRadius(t):0}getAtomData(t,e,i){return t.getBackboneAtomData(this.getAtomParams(e,i))}getBondData(t,e,i){return t.getBackboneBondData(this.getBondParams(e,i))}}Ne.add("backbone",rd);class sd extends id{constructor(t,e,i){super(t,e,i),this.type="base",this.parameters=Object.assign({},this.parameters,{multipleBond:null,bondSpacing:null})}init(t){let e=t||{};e.aspectRatio=st(e.aspectRatio,1),e.radiusSize=st(e.radiusSize,.3),super.init(e)}getAtomData(t,e,i){return t.getRungAtomData(this.getAtomParams(e,i))}getBondData(t,e,i){let r=this.getBondParams(e,i);return Object.assign(r.colorParams,{rung:!0}),t.getRungBondData(r)}}Ne.add("base",sd);class nd{constructor(t,i){this.m=t,this.tension=i,this.dt=1/this.m,this.delta=1e-4,this.vec1=new e,this.vec2=new e,this.vDir=new e,this.vTan=new e,this.vNorm=new e,this.vBin=new e,this.m2=Math.ceil(this.m/2)}interpolateToArr(t,e,i,r,s,n,o){n[o+0]=Ot(t.x,e.x,i.x,r.x,s,this.tension),n[o+1]=Ot(t.y,e.y,i.y,r.y,s,this.tension),n[o+2]=Ot(t.z,e.z,i.z,r.z,s,this.tension)}interpolateToVec(t,e,i,r,s,n){n.x=Ot(t.x,e.x,i.x,r.x,s,this.tension),n.y=Ot(t.y,e.y,i.y,r.y,s,this.tension),n.z=Ot(t.z,e.z,i.z,r.z,s,this.tension)}interpolatePosition(t,e,i,r,s,n){for(var o=0;o1&&(l=1),this.interpolateToVec(t,e,i,r,c,this.vec1),this.interpolateToVec(t,e,i,r,l,this.vec2),this.vec2.sub(this.vec1).normalize(),this.vec2.toArray(s,h)}}vectorSubdivide(t,e,i,r,s){let n,o=e.next(),a=e.next(),c=e.next();const l=e.size,h=l-1;let d=r||0;for(let r=0;r0&&e{if(t.residueCount<4)return;i.push(t);const r=this.getSpline(t),s=this.getAspectRatio(t),n=r.getSubdividedPosition(),o=r.getSubdividedOrientation(),a=r.getSubdividedColor(this.getColorParams()),c=r.getSubdividedPicking(),l=r.getSubdividedSize(this.getRadiusParams());e.push(new hd(Object.assign({},n,o,a,c,l),this.getBufferParams({radialSegments:this.radialSegments,aspectRatio:s,capped:this.capped})))}),t.getSelection()),{bufferList:e,polymerList:i}}updateData(t,e){De&&Me.time(this.type+" repr update"),t=t||{};for(var i=0,r=e.polymerList.length;i0;Qr(A,b,_);const s=Zr(A,v)<0;if(ns(A,v,Zr(v,x)),Qr(S,x,A),ns(A,v,Zr(v,w)),Qr(C,w,A),0===rs(S)||0===rs(C))continue;os(S,S),os(C,C);const D=n[T]=us(S,C);a[T]=(vi*D).toFixed(1)+String.fromCharCode(176),Kr(k,S,v),os(k,k),Zr(k,C)<0&&ds(k,k),Ih(A,_,S,k,D/2),es(A,o,3*T);const $=Math.ceil(D/i),O=$+(e.extendLine?4:2),R=e.extendLine?36:0,E=new Float32Array(3*O),F=new Float32Array(3*O),L=new Float32Array(9*$),N=new Float32Array(R);c[T]=E,l[T]=F,h[T]=L,d[T]=N,e.extendLine&&(r?(Qr(A,f,y),os(A,A),ns(P,A,1/Zr(S,A)),Jr(P,P,y)):(ns(P,x,1/Zr(S,x)),Jr(P,P,g)),s?(Qr(A,b,g),os(A,A),ns(I,A,1/Zr(C,A)),Jr(I,I,g)):(ns(I,w,1/Zr(C,w)),Jr(I,I,y))),Jr(M,_,S);let z=0;e.extendLine?(es(f,E,z),es(P,F,z),z+=3,es(P,E,z),es(M,F,z),z+=3,es(P,N,0),es(M,N,3),es(r?y:g,N,6),es(r?y:g,N,9),es(M,N,12),es(_,N,15)):(es(_,E,z),es(M,F,z),z+=3);const V=function(t,e){const i=9*e;es(_,L,i),es(M,L,i+3),es(M,E,z),Ih(M,_,S,k,t),es(M,L,i+6),es(M,F,z),z+=3};let G=0;for(let t=i;t{const e=pd(i,t);Object.assign(t,e)})),e.side=st(e.side,"double"),e.opacity=st(e.opacity,.5),e.radiusType=st(e.radiusType,"size"),e.radiusSize=st(e.radiusSize,.15),super.init(e)}getHistogramBinBorderBufferParameters(){return this.getBufferParams({linewidth:this.histogramBinBorderWidth,visible:this.histogramBinBorderVisible,opacity:this.histogramBinBorderOpacity})}getBondArrowsBufferParameters(){return this.getBufferParams({linewidth:this.bondArrowWidth,visible:this.bondArrowVisible,opacity:this.bondArrowOpacity})}getOpaqueMiddleDiscBufferParameters(){return this.getBufferParams({visible:this.opaqueMiddleDiscVisible,opacity:this.opaqueMiddleDiscOpacity})}getHistogramBufferParameters(){return this.getBufferParams({visible:!0,opacity:this.histogramOpacity,side:"double"})}createData(t){if(!t.atomCount||!this.histogramsData.length)return;this.histogramsData.forEach((e=>e.atomPositions=Ph(t,[e.atomQuad])));const e=this.scaleBinToSectorArea?function(t){return Math.sqrt(t)}:function(t){return t};function i(t){const e=t.map((t=>t.length)),i=new Float32Array($i(e));let r=0;for(let e=0;et.startPoints))),position2:i(t.map((t=>t.endPoints))),color:i(t.map((t=>t.startColors))),color2:i(t.map((t=>t.endColors)))},e)}function s(t,e){return new Uo({position:i(t.map((t=>t.triangles))),color:i(t.map((t=>t.triangleColors)))},e)}this.histogramsData.forEach((t=>t.histogram360Scaled=t.histogram360.map(e)));const n=[];for(let t=0;t=3&&(e=yd(i)),void 0!==e&&n.push(e)}return this.frontHistogramBinBordersBuffer=r(n.map((t=>t.frontHistogramBinBorders)),this.getHistogramBinBorderBufferParameters()),this.backHistogramBinBordersBuffer=r(n.map((t=>t.backHistogramBinBorders)),this.getHistogramBinBorderBufferParameters()),this.adjacentBondArrowsBuffer=r(n.map((t=>t.adjacentBondArrows)),this.getBondArrowsBufferParameters()),this.distantBondArrowsBuffer=r(n.map((t=>t.distantBondArrows)),this.getBondArrowsBufferParameters()),this.opaqueMiddleDiscBuffer=s(n.map((t=>t.opaqueMiddleDisc)),this.getOpaqueMiddleDiscBufferParameters()),this.frontHistogramBuffer=s(n.map((t=>t.frontHistogram)),this.getHistogramBufferParameters()),this.backHistogramBuffer=s(n.map((t=>t.backHistogram)),this.getHistogramBufferParameters()),{bufferList:[].concat(this.frontHistogramBinBordersBuffer,this.backHistogramBinBordersBuffer,this.adjacentBondArrowsBuffer,this.distantBondArrowsBuffer,this.opaqueMiddleDiscBuffer,this.frontHistogramBuffer,this.backHistogramBuffer)}}setParameters(t){return super.setParameters(t,{},!1),t&&void 0!==t.histogramBinBorderVisible&&this.setVisibility(this.visible),this}setVisibility(t,e){return super.setVisibility(t,!0),this.frontHistogramBinBordersBuffer&&this.frontHistogramBinBordersBuffer.setVisibility(this.histogramBinBorderVisible),this.backHistogramBinBordersBuffer&&this.backHistogramBinBordersBuffer.setVisibility(this.histogramBinBorderVisible),e||this.viewer.requestRender(),this}}function yd(t){const e=t.atomPositions,i=t.histogram360Scaled,r=i.length<=180?360:2*i.length,s={triangles:new Float32Array(3*r*3),triangleColors:fd(t.opaqueMiddleDiscColor,3*r)},n={triangles:new Float32Array(3*i.length*3),triangleColors:fd(t.frontHistogramColor,3*i.length)},o={triangles:new Float32Array(3*i.length*3),triangleColors:fd(t.backHistogramColor,3*i.length)},a={startPoints:new Float32Array(3*i.length),endPoints:new Float32Array(3*i.length),startColors:fd(t.histogramBinBorderColor,i.length),endColors:fd(t.histogramBinBorderColor,i.length)},c={startPoints:new Float32Array(3*i.length),endPoints:new Float32Array(3*i.length),startColors:fd(t.histogramBinBorderColor,i.length),endColors:fd(t.histogramBinBorderColor,i.length)},l={startPoints:new Float32Array(6),endPoints:new Float32Array(6),startColors:fd(t.adjacentBondArrowColor,i.length),endColors:fd(t.adjacentBondArrowColor,i.length)},h={startPoints:new Float32Array(6),endPoints:new Float32Array(6),startColors:fd(t.distantBondArrowColor,i.length),endColors:fd(t.distantBondArrowColor,i.length)},d=Yr(),u=Yr(),m=Yr(),p=Yr(),f=Yr(),g=Yr(),y=Yr(),b=Yr(),x=Yr(),v=Yr(),w=Yr(),A=Yr(),_=Yr(),S=Yr(),C=Yr(),P=Yr(),I=[d,u,m,p];for(let t=0;t{let u=e[0],m=e[1];if("number"==typeof u&&Number.isInteger(u)&&"number"==typeof m&&Number.isInteger(m)){if(!d.get(u)||!d.get(m))return void(h+=1);c.index=u,l.index=m}else{n.setString(u),o.setString(m);var p=t.getAtomIndices(n),f=t.getAtomIndices(o);if(!p.length||!f.length)return void(h+=1);c.index=p[0],l.index=f[0]}a.addBond(c,l,1),i-=h;var g=c.distanceTo(l);switch(this.labelUnit){case"angstrom":r[i]=g.toFixed(2)+" "+String.fromCharCode(8491);break;case"nm":r[i]=(g/10).toFixed(2)+" nm";break;default:r[i]=g.toFixed(2)}var y=3*i;s[y+0]=(c.x+l.x)/2,s[y+1]=(c.y+l.y)/2,s[y+2]=(c.z+l.z)/2})),h>0&&(i-=h,s=s.subarray(0,3*i));var u=new Os(a.count,!0);return{text:r,position:s,bondSet:u,bondStore:a}}getBondData(t,e,i){const r=t.getBondData(this.getBondParams(e,i));return r.picking&&(r.picking=new to(r.picking.array,r.picking.structure,i.bondStore)),r}createData(t){if(!t.atomCount||!this.atomPair.length)return;const e=this.atomPair.length,i=new s(this.labelColor),r=this.getDistanceData(t,this.atomPair);this.textBuffer=new Eh({position:r.position,size:Si(e,this.labelSize),color:Ci(e,i.r,i.g,i.b),text:r.text},this.getLabelBufferParams());const n={bondSet:r.bondSet,bondStore:r.bondStore},o=this.getBondData(t,{position:!0,color:!0,picking:!0,radius:this.useCylinder},n);return this.useCylinder?this.distanceBuffer=new td(o,this.getBufferParams({openEnded:this.openEnded,radialSegments:this.radialSegments,disableImpostor:this.disableImpostor,dullInterior:!0})):this.distanceBuffer=new Nh(ps(o),this.getBufferParams({linewidth:this.linewidth,visible:this.lineVisible,opacity:this.lineOpacity})),{bondSet:r.bondSet,bondStore:r.bondStore,position:r.position,bufferList:[this.textBuffer,this.distanceBuffer]}}updateData(t,e){super.updateData(t,e);const i={bondSet:e.bondSet,bondStore:e.bondStore},r=this.getBondData(e.sview,t,i),s={};t&&!t.color||Object.assign(s,{color:r.color,color2:r.color2}),t&&!t.radius||Object.assign(s,{radius:r.radius}),this.distanceBuffer.setAttributes(s)}setParameters(t){return super.setParameters(t,{},!1),this.useCylinder||(t&&t.lineOpacity&&this.distanceBuffer.setParameters({opacity:t.lineOpacity}),t&&void 0!==t.opacity&&this.distanceBuffer.setParameters({opacity:this.lineOpacity}),t&&t.linewidth&&this.distanceBuffer.setParameters({linewidth:t.linewidth})),this}}function xd(t){return 2*(t.position.length/3)*3}Ne.add("distance",bd);const vd=Object.assign({scale:1,color:"grey"},zo);class wd extends Go{constructor(t,e={}){super({position:new Float32Array(xd(t)),color:new Float32Array(xd(t))},e),this.isLine=!0,this.vertexShader="Line.vert",this.fragmentShader="Line.frag";const i=new s(this.parameters.color),r=this.geometry.attributes;Ci(xd(t)/3,i.r,i.g,i.b,r.color.array),this.setAttributes(t)}get defaultParameters(){return vd}setAttributes(t={}){const e=this.geometry.attributes;let i,r,s;t.position&&t.vector&&(i=t.position,r=t.vector,s=e.position.array,e.position.needsUpdate=!0);const n=this.size/2,o=this.parameters.scale;if(i&&r)for(let t=0;t{if(t.residueCount<4)return;i.push(t);const r=new Ca(t),s=r.getPosition(),n=r.getColor(this.getColorParams()),o=r.getSize(this.getRadiusParams()),a=r.getPicking();e.push(new Gc({position:s.center,color:n.color,radius:o.size,picking:a.picking},this.getBufferParams({sphereDetail:this.sphereDetail,disableImpostor:this.disableImpostor,dullInterior:!0})),new wd({position:s.center,vector:s.axis},this.getBufferParams({color:"skyblue",scale:1})),new wd({position:s.center,vector:s.resdir},this.getBufferParams({color:"lightgreen",scale:1})))}),t.getSelection()),{bufferList:e,polymerList:i}}updateData(t,e){De&&Me.time(this.type+" repr update"),t=t||{};for(let i=0,r=e.polymerList.length;i radius2) {\nspaceposition.y = mapping.y * 1.5 * radius1;\nspaceposition.x = mapping.x * 1.5 * radius1;\n} else {\nspaceposition.y = mapping.y * 1.5 * radius2;\nspaceposition.x = mapping.x * 1.5 * radius2;\n}\nspaceposition.w = 1.0;\nvec4 e3 = vec4( 1.0 );\nvec3 e1, e1_temp, e2, e2_temp;\ne3.xyz = normalize(position_atom1-position_atom2);\nif (e3.z == 0.0) { e3.z = 0.0000000000001;}\nif ( (position_atom1.x - position_atom2.x) == 0.0) { position_atom1.x += 0.001;}\nif ( (position_atom1.y - position_atom2.y) == 0.0) { position_atom1.y += 0.001;}\nif ( (position_atom1.z - position_atom2.z) == 0.0) { position_atom1.z += 0.001;}\nvec4 focus = vec4( 1.0 );\nfocus.x = ( position_atom1.x*position_atom1.x - position_atom2.x*position_atom2.x +\n( radius2*radius2 - radius1*radius1 )*e3.x*e3.x/shrink )/(2.0*(position_atom1.x - position_atom2.x));\nfocus.y = ( position_atom1.y*position_atom1.y - position_atom2.y*position_atom2.y +\n( radius2*radius2 - radius1*radius1 )*e3.y*e3.y/shrink )/(2.0*(position_atom1.y - position_atom2.y));\nfocus.z = ( position_atom1.z*position_atom1.z - position_atom2.z*position_atom2.z +\n( radius2*radius2 - radius1*radius1 )*e3.z*e3.z/shrink )/(2.0*(position_atom1.z - position_atom2.z));\ne1.x = 1.0;\ne1.y = 1.0;\ne1.z = ( (e3.x*focus.x + e3.y*focus.y + e3.z*focus.z) - e1.x*e3.x - e1.y*e3.y)/e3.z;\ne1_temp = e1 - focus.xyz;\ne1 = normalize(e1_temp);\ne2_temp = e1.yzx * e3.zxy - e1.zxy * e3.yzx;\ne2 = normalize(e2_temp);\nmat3 R= mat3( e1.xyz, e2.xyz, e3.xyz );\nvertex_position.xyz = R * spaceposition.xyz;\nvertex_position.w = 1.0;\nvertex_position.x += (position_atom1.x+position_atom2.x) / 2.0;\nvertex_position.y += (position_atom1.y+position_atom2.y) / 2.0;\nvertex_position.z += (position_atom1.z+position_atom2.z) / 2.0;\ngl_Position = modelViewProjectionMatrix * vertex_position;\nvec4 i_near, i_far;\nvec4 near = gl_Position;\nnear.z = 0.0 ;\nnear = modelViewProjectionMatrixInverse * near;\ni_near = near;\nvec4 far = gl_Position;\nfar.z = far.w ;\ni_far = modelViewProjectionMatrixInverse * far;\nprime1 = vec4( position_atom1 - (position_atom1 - focus.xyz)*shrink, 1.0 );\nprime2 = vec4( position_atom2 - (position_atom2 - focus.xyz)*shrink, 1.0 );\nfloat Rsquare = (radius1*radius1/shrink) - (\n(position_atom1.x - focus.x)*(position_atom1.x - focus.x) +\n(position_atom1.y - focus.y)*(position_atom1.y - focus.y) +\n(position_atom1.z - focus.z)*(position_atom1.z - focus.z)\n);\nfocus.w = Rsquare;\nmatrix_near = mat4( i_near, i_far, focus, e3 );\ngl_Position.z = 1.0;\n}"),Ve.add("shader/HyperballStickImpostor.frag","#define STANDARD\n#define IMPOSTOR\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 interiorColor;\nuniform float interiorDarkening;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\nuniform float clipNear;\nuniform float shrink;\nuniform mat4 modelViewMatrix;\nuniform mat4 modelViewProjectionMatrix;\nuniform mat4 modelViewMatrixInverseTranspose;\nuniform mat4 projectionMatrix;\nvarying mat4 matrix_near;\nvarying vec4 prime1;\nvarying vec4 prime2;\nvarying float vRadius;\nvarying float vRadius2;\n#ifdef PICKING\nuniform float objectId;\nvarying vec3 vPickingColor;\n#else\nvarying vec3 vColor1;\nvarying vec3 vColor2;\n#include common\n#include fog_pars_fragment\n#include bsdfs\n#include lights_pars_begin\n#include lights_physical_pars_fragment\n#endif\nbool interior = false;\nfloat calcClip( vec4 cameraPos ){\nreturn dot( cameraPos, vec4( 0.0, 0.0, 1.0, clipNear - 0.5 ) );\n}\nfloat calcClip( vec3 cameraPos ){\nreturn calcClip( vec4( cameraPos, 1.0 ) );\n}\nfloat calcDepth( in vec3 cameraPos ){\nvec2 clipZW = cameraPos.z * projectionMatrix[2].zw + projectionMatrix[3].zw;\nreturn 0.5 + 0.5 * clipZW.x / clipZW.y;\n}\nstruct Ray {\nvec3 origin ;\nvec3 direction ;\n};\nbool cutoff_plane (vec3 M, vec3 cutoff, vec3 x3){\nfloat a = x3.x;\nfloat b = x3.y;\nfloat c = x3.z;\nfloat d = -x3.x*cutoff.x-x3.y*cutoff.y-x3.z*cutoff.z;\nfloat l = a*M.x+b*M.y+c*M.z+d;\nif (l<0.0) {return true;}\nelse{return false;}\n}\nvec3 isect_surf(Ray r, mat4 matrix_coef){\nvec4 direction = vec4(r.direction, 0.0);\nvec4 origin = vec4(r.origin, 1.0);\nfloat a = dot(direction,(matrix_coef*direction));\nfloat b = dot(origin,(matrix_coef*direction));\nfloat c = dot(origin,(matrix_coef*origin));\nfloat delta =b*b-a*c;\ngl_FragColor.a = 1.0;\nif (delta<0.0){\ndiscard;\n}\nfloat t1 =(-b-sqrt(delta))/a;\nreturn r.origin+t1*r.direction;\n}\nvec3 isect_surf2(Ray r, mat4 matrix_coef){\nvec4 direction = vec4(r.direction, 0.0);\nvec4 origin = vec4(r.origin, 1.0);\nfloat a = dot(direction,(matrix_coef*direction));\nfloat b = dot(origin,(matrix_coef*direction));\nfloat c = dot(origin,(matrix_coef*origin));\nfloat delta =b*b-a*c;\ngl_FragColor.a = 1.0;\nif (delta<0.0){\ndiscard;\n}\nfloat t2 =(-b+sqrt(delta))/a;\nreturn r.origin+t2*r.direction;\n}\nRay primary_ray(vec4 near1, vec4 far1){\nvec3 near=near1.xyz/near1.w;\nvec3 far=far1.xyz/far1.w;\nreturn Ray(near,far-near);\n}\nfloat update_z_buffer(vec3 M, mat4 ModelViewP){\nfloat depth1;\nvec4 Ms=(ModelViewP*vec4(M,1.0));\nreturn depth1=(1.0+Ms.z/Ms.w)/2.0;\n}\nvoid main(){\nfloat radius = max( vRadius, vRadius2 );\nvec4 i_near, i_far, focus;\nvec3 e3, e1, e1_temp, e2;\ni_near = vec4(matrix_near[0][0],matrix_near[0][1],matrix_near[0][2],matrix_near[0][3]);\ni_far = vec4(matrix_near[1][0],matrix_near[1][1],matrix_near[1][2],matrix_near[1][3]);\nfocus = vec4(matrix_near[2][0],matrix_near[2][1],matrix_near[2][2],matrix_near[2][3]);\ne3 = vec3(matrix_near[3][0],matrix_near[3][1],matrix_near[3][2]);\ne1.x = 1.0;\ne1.y = 1.0;\ne1.z = ( (e3.x*focus.x + e3.y*focus.y + e3.z*focus.z) - e1.x*e3.x - e1.y*e3.y)/e3.z;\ne1_temp = e1 - focus.xyz;\ne1 = normalize(e1_temp);\ne2 = normalize(cross(e1,e3));\nvec4 equation = focus;\nfloat shrinkfactor = shrink;\nfloat t1 = -1.0/(1.0-shrinkfactor);\nfloat t2 = 1.0/(shrinkfactor);\nvec4 colonne1, colonne2, colonne3, colonne4;\nmat4 mat;\nvec3 equation1 = vec3(t2,t2,t1);\nfloat A1 = - e1.x*equation.x - e1.y*equation.y - e1.z*equation.z;\nfloat A2 = - e2.x*equation.x - e2.y*equation.y - e2.z*equation.z;\nfloat A3 = - e3.x*equation.x - e3.y*equation.y - e3.z*equation.z;\nfloat A11 = equation1.x*e1.x*e1.x + equation1.y*e2.x*e2.x + equation1.z*e3.x*e3.x;\nfloat A21 = equation1.x*e1.x*e1.y + equation1.y*e2.x*e2.y + equation1.z*e3.x*e3.y;\nfloat A31 = equation1.x*e1.x*e1.z + equation1.y*e2.x*e2.z + equation1.z*e3.x*e3.z;\nfloat A41 = equation1.x*e1.x*A1 + equation1.y*e2.x*A2 + equation1.z*e3.x*A3;\nfloat A22 = equation1.x*e1.y*e1.y + equation1.y*e2.y*e2.y + equation1.z*e3.y*e3.y;\nfloat A32 = equation1.x*e1.y*e1.z + equation1.y*e2.y*e2.z + equation1.z*e3.y*e3.z;\nfloat A42 = equation1.x*e1.y*A1 + equation1.y*e2.y*A2 + equation1.z*e3.y*A3;\nfloat A33 = equation1.x*e1.z*e1.z + equation1.y*e2.z*e2.z + equation1.z*e3.z*e3.z;\nfloat A43 = equation1.x*e1.z*A1 + equation1.y*e2.z*A2 + equation1.z*e3.z*A3;\nfloat A44 = equation1.x*A1*A1 + equation1.y*A2*A2 + equation1.z*A3*A3 - equation.w;\ncolonne1 = vec4(A11,A21,A31,A41);\ncolonne2 = vec4(A21,A22,A32,A42);\ncolonne3 = vec4(A31,A32,A33,A43);\ncolonne4 = vec4(A41,A42,A43,A44);\nmat = mat4(colonne1,colonne2,colonne3,colonne4);\nRay ray = primary_ray(i_near,i_far) ;\nvec3 M;\nM = isect_surf(ray, mat);\nif (cutoff_plane(M, prime1.xyz, -e3) || cutoff_plane(M, prime2.xyz, e3)){ discard; }\nvec4 M1 = vec4(M,1.0);\nvec4 M2 = mat*M1;\nvec3 _normal = ( modelViewMatrixInverseTranspose * M2 ).xyz;\ngl_FragDepthEXT = update_z_buffer(M, modelViewProjectionMatrix) ;\n#ifdef NEAR_CLIP\nif( calcClip( modelViewMatrix * vec4( M, 1.0 ) ) > 0.0 ){\nM = isect_surf2(ray, mat);\nif( calcClip( modelViewMatrix * vec4( M, 1.0 ) ) > 0.0 )\ndiscard;\ninterior = true;\ngl_FragDepthEXT = update_z_buffer(M, modelViewProjectionMatrix) ;\nif( gl_FragDepthEXT >= 0.0 ){\ngl_FragDepthEXT = max( 0.0, calcDepth( vec3( - ( clipNear - 0.5 ) ) ) + ( 0.0000001 / radius ) );\n}\n}else if( gl_FragDepthEXT <= 0.0 ){\nM = isect_surf2(ray, mat);\ninterior = true;\ngl_FragDepthEXT = update_z_buffer(M, modelViewProjectionMatrix);\nif( gl_FragDepthEXT >= 0.0 ){\ngl_FragDepthEXT = 0.0 + ( 0.0000001 / radius );\n}\n}\n#else\nif( gl_FragDepthEXT <= 0.0 ){\nM = isect_surf2(ray, mat);\ninterior = true;\ngl_FragDepthEXT = update_z_buffer(M, modelViewProjectionMatrix) ;\nif( gl_FragDepthEXT >= 0.0 ){\ngl_FragDepthEXT = 0.0 + ( 0.0000001 / radius );\n}\n}\n#endif\nif (cutoff_plane(M, prime1.xyz, -e3) || cutoff_plane(M, prime2.xyz, e3)){ discard; }\nif (gl_FragDepthEXT < 0.0)\ndiscard;\nif (gl_FragDepthEXT > 1.0)\ndiscard;\nfloat distance_ratio = ((M.x-prime2.x)*e3.x + (M.y-prime2.y)*e3.y +(M.z-prime2.z)*e3.z) /\ndistance(prime2.xyz,prime1.xyz);\n#ifdef PICKING\nif( opacity < 0.3 )\ndiscard;\ngl_FragColor = vec4( vPickingColor, objectId );\n#else\nvec3 vViewPosition = -( modelViewMatrix * vec4( M, 1.0 ) ).xyz;\nvec3 vNormal = _normal;\nvec3 vColor;\nif( distance_ratio>0.5 ){\nvColor = vColor1;\n}else{\nvColor = vColor2;\n}\nvec4 diffuseColor = vec4( diffuse, opacity );\nReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\nvec3 totalEmissiveLight = emissive;\n#include color_fragment\n#include roughnessmap_fragment\n#include metalnessmap_fragment\nvec3 normal = normalize( vNormal );\nvec3 geometryNormal = normal;\n#include lights_physical_fragment\n#include lights_fragment_begin\n#include lights_fragment_end\nvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveLight;\nif( interior ){\n#ifdef USE_INTERIOR_COLOR\noutgoingLight.xyz = interiorColor;\n#else\n#ifdef DIFFUSE_INTERIOR\noutgoingLight.xyz = vColor;\n#endif\n#endif\noutgoingLight.xyz *= 1.0 - interiorDarkening;\n}\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );\n#include premultiplied_alpha_fragment\n#include tonemapping_fragment\n#include encodings_fragment\n#include fog_fragment\n#endif\n}");const Sd=new Float32Array([-1,-1,-1,1,-1,-1,1,-1,1,-1,-1,1,-1,1,-1,1,1,-1,1,1,1,-1,1,1]),Cd=new Uint16Array([0,1,2,0,2,3,1,5,6,1,6,2,4,6,5,4,7,6,0,7,4,0,3,7,0,5,1,0,4,5,3,2,6,3,6,7]);class Pd extends Fc{constructor(t,e={}){super("v3",t,e)}get mapping(){return Sd}get mappingIndices(){return Cd}get mappingIndicesSize(){return 36}get mappingSize(){return 8}get mappingItemSize(){return 3}}const Id=Object.assign({shrink:.14},zo),kd=Object.assign({shrink:{uniform:!0}},Vo);class Md extends Pd{constructor(t,e={}){super(t,e),this.parameterTypes=kd,this.isImpostor=!0,this.vertexShader="HyperballStickImpostor.vert",this.fragmentShader="HyperballStickImpostor.frag",this.addUniforms({modelViewProjectionMatrix:{value:new i},modelViewProjectionMatrixInverse:{value:new i},modelViewMatrixInverseTranspose:{value:new i},shrink:{value:this.parameters.shrink}}),this.addAttributes({position1:{type:"v3",value:null},position2:{type:"v3",value:null},color2:{type:"c",value:null},radius:{type:"f",value:null},radius2:{type:"f",value:null}}),this.setAttributes(t),this.makeMapping()}get defaultParameters(){return Id}}Object.assign({disableImpostor:!1},Hh,Id);const Td=class{constructor(t,e={}){return!Ie||e&&e.disableImpostor?(t.radius=function(t,e){const i=t.length,r=new Float32Array(i);for(let s=0;sa.push(r.atomLabel(t)))))}else if("residue"===this.labelGrouping){e&&!e.position||(c=[]),e&&!e.color||(h=[]),e&&!e.radius||(l=[]),e&&!e.text||(a=[]),i.colorParams&&(i.colorParams.structure=t.getStructure());const d=Fe.getScheme(i.colorParams),u=new pa(i.radiusParams),m=t.getAtomProxy();let p=0;t.eachResidue((t=>{const i=3*p;t.isProtein()||t.isNucleic()?(m.index=t.traceAtomIndex,e&&!e.position||m.positionToArray(c,i)):(m.index=t.atomOffset,e&&!e.position||t.positionToArray(c,i)),e&&!e.color||d.atomColorToArray(m,h,i),e&&!e.radius||(l[p]=u.atomRadius(m)),e&&!e.text||a.push(r.atomLabel(m)),++p})),e&&!e.position||(s=new Float32Array(c)),e&&!e.color||(o=new Float32Array(h)),e&&!e.radius||(n=new Float32Array(l))}return{position:s,size:n,color:o,text:a}}createData(t){return{bufferList:[new Eh(this.getTextData(t,{position:!0,color:!0,radius:!0,text:!0}),this.getBufferParams({fontFamily:this.fontFamily,fontStyle:this.fontStyle,fontWeight:this.fontWeight,xOffset:this.xOffset,yOffset:this.yOffset,zOffset:this.zOffset,attachment:this.attachment,showBorder:this.showBorder,borderColor:this.borderColor,borderWidth:this.borderWidth,showBackground:this.showBackground,backgroundColor:this.backgroundColor,backgroundMargin:this.backgroundMargin,backgroundOpacity:this.backgroundOpacity,fixedSize:this.fixedSize}))]}}updateData(t,e){e.bufferList[0].setAttributes(this.getTextData(e.sview,t))}getAtomRadius(){return 0}}function Od(t){const e=t.getAtomSet(),i=t.getBondSet(),r=t.getBondProxy();return i.forEach((function(t){r.index=t,e.clear(r.atomIndex1),e.clear(r.atomIndex2)})),e}Ne.add("label",$d);class Rd extends Sh{constructor(t,e,i){super(t,e,i),this.type="line",this.parameters=Object.assign({multipleBond:{type:"select",rebuild:!0,options:{off:"off",symmetric:"symmetric",offset:"offset"}},bondSpacing:{type:"number",precision:2,max:2,min:.5},linewidth:{type:"integer",max:50,min:1,buffer:!0},lines:{type:"boolean",rebuild:!0},crosses:{type:"select",rebuild:!0,options:{off:"off",lone:"lone",all:"all"}},crossSize:{type:"number",precision:2,max:2,min:.1}},this.parameters,{flatShaded:null,side:null,wireframe:null,roughness:null,metalness:null}),this.init(i)}init(t){var e=t||{};this.multipleBond=st(e.multipleBond,"off"),this.bondSpacing=st(e.bondSpacing,1),this.linewidth=st(e.linewidth,2),this.lines=st(e.lines,!0),this.crosses=st(e.crosses,"lone"),this.crossSize=st(e.crossSize,.4),super.init(e)}getAtomRadius(t){return.1}getBondParams(t,e){return e=Object.assign({multipleBond:this.multipleBond,bondSpacing:this.bondSpacing,radiusParams:{type:"size",size:.1,scale:1}},e),super.getBondParams(t,e)}_crossData(t,e){if(t&&!t.position&&!t.color)return;const i={};"lone"===this.crosses&&Object.assign(i,{atomSet:Od(e)});const r=e.getAtomData(this.getAtomParams(t,i)),s={},n=r.position,o=r.color,a=r.picking,c=(n||o).length,l=3*c;let h=new Float32Array(0),d=new Float32Array(0),u=new Float32Array(0),m=new Float32Array(0),p=0,f=new Float32Array(0);t&&!t.position||(h=s.position1=new Float32Array(l),d=s.position2=new Float32Array(l),p=this.crossSize/2),t&&!t.color||(u=s.color=new Float32Array(l),m=s.color2=new Float32Array(l)),t&&!t.picking||(f=new Float32Array(3*r.picking.array.length));for(let e=0;el?u[f]=-1:(c=Math.sqrt(l-a),u[f]=Math.floor(c)),++f;p[g]=d,m[g]=u}}function k(i){var r,s,n,a,d,f,b,v,w,A,S,C,P,I,k,M,T,B,D=3*i,$=i;r=Math.floor(.5+o*(t[D]+u[0])),s=Math.floor(.5+o*(t[D+1]+u[1])),n=Math.floor(.5+o*(t[D+2]+u[2]));var O,R=e[$],E=m[R],F=0,L=l*h,N=p[R];for(A=0;A=c||I>=l||k>=h)){var z=P*L+I*h+k;if(g)if(y[z]&_){if(y[z]&_){var V=x[z];V!==D&&b*b+v*v+w*w<(a=r+b-Math.floor(.5+o*(t[V]+u[0])))*a+(d=s+v-Math.floor(.5+o*(t[V+1]+u[1])))*d+(f=n+w-Math.floor(.5+o*(t[V+2]+u[2])))*f&&(x[z]=i)}}else y[z]|=_,x[z]=i;else y[z]|=_}F++}}function M(e){var i,r;for(console.time("EDTSurface fillvoxels"),i=0,r=y.length;i=c||_>=l||C>=h)){var L=A*F+_*h+C;if(y[L]&S){if(g){var N=x[L];b*b+v*v+w*w<(a=Math.floor(.5+o*(t[N]+u[0])))*a+(d=Math.floor(.5+o*(t[N+1]+u[1])))*d+(f=Math.floor(.5+o*(t[N+2]+u[2])))*f&&(x[L]=i)}}else y[L]|=S,g&&(x[L]=i)}R++}}function B(){var t,e,i,r;console.time("EDTSurface fastdistancemap");var s,n=Ed(c,l,h,Uint16Array,3),o=l*h,d=f*f,u=0;for(t=0;t0);var A,P=a*a,I=new Uint16Array(3);for(t=0;t=P)||(y[s]|=C,g&&y[s]&S&&(n.toArray(t,e,i,I),A=I[0]*o+I[1]*h+I[2],x[s]=x[A])));console.timeEnd("EDTSurface fastdistancemap")}function D(t,e,i,r){var s,n,o,a,d,u,m,p,f,g,x,v,w=new Uint16Array(3),A=0;if(0===i)return A;var I=-1,k=-1,M=-1,T=l*h;for(m=0,f=i;m-1&&k-1&&M-1&&(y[x=I*T+h*k+M]&_&&!(y[x]&S)?(e.fromArray(I,k,M,w),g=(a=I-w[0])*a+(d=k-w[1])*d+(u=M-w[2])*u,b[x]=g,y[x]|=S,y[x]|=C,r[A]=I,r[A+1]=k,r[A+2]=M,A+=3):y[x]&_&&y[x]&S&&(g=(a=I-w[0])*a+(d=k-w[1])*d+(u=M-w[2])*u)-1&&k-1&&M-1&&(y[x=I*T+h*k+M]&_&&!(y[x]&S)?(e.fromArray(I,k,M,w),g=(a=I-w[0])*a+(d=k-w[1])*d+(u=M-w[2])*u,b[x]=g,y[x]|=S,y[x]|=C,r[A]=I,r[A+1]=k,r[A+2]=M,A+=3):y[x]&_&&y[x]&S&&(g=(a=I-w[0])*a+(d=k-w[1])*d+(u=M-w[2])*u)-1&&k-1&&M-1&&(y[x=I*T+h*k+M]&_&&!(y[x]&S)?(e.fromArray(I,k,M,w),g=(a=I-w[0])*a+(d=k-w[1])*d+(u=M-w[2])*u,b[x]=g,y[x]|=S,y[x]|=C,r[A]=I,r[A+1]=k,r[A+2]=M,A+=3):y[x]&_&&y[x]&S&&(g=(a=I-w[0])*a+(d=k-w[1])*d+(u=M-w[2])*u)-1&&o-1&&d-1&&aT&&(T=O)}return{neighbourListLength:27*T+1,withinRadii:function(s,n,o,a,d){for(var u=0,m=p(s,c),f=p(n,l),g=p(o,h),y=Math.max(0,m-1),w=Math.max(0,f-1),_=Math.max(0,g-1),S=Math.min(b,m+2),C=Math.min(x,f+2),M=Math.min(v,g+2),T=y;Tu&&(u=h[t]);!function(){const t=$o(c,l,u,p,0);p=t.scaleFactor,y=t.dim,b=t.matrix,$=Math.max(5,2+Math.floor(m*p)),x=Si(y[0]*y[1]*y[2],-1001),v=new Int32Array(x.length),w=new Float32Array(y[0]),A=new Float32Array(y[1]),_=new Float32Array(y[2]),R(w,c[0],1/p),R(A,c[1],1/p),R(_,c[2],1/p)}(),function(){var t=0,e=2*Math.PI/g;C=new Float32Array(g),S=new Float32Array(g);for(var i=0;i=0;){if(n!==r&&n!==s&&F(n,t,e,i))return k=n,n;n=I[++o]}return k=-1,-1}function F(e,i,r,s){var n=3*e,o=d[e],a=t[n]-i,c=t[n+1]-r,l=t[n+2]-s;return a*a+c*c+l*l0&&u=0;)t{e(this._makeSurface(t.data.sd,i))}),(t=>{console.warn("MolecularSurface.getSurfaceWorker error - trying without worker",t),this.worker.terminate(),this.worker=void 0;const r=this.getSurface(i);e(r)}))}else{const t=this.getSurface(i);e(t)}}dispose(){this.worker&&this.worker.terminate()}}class Vd extends Sh{constructor(t,e,i){super(t,e,i),this.type="surface",this.parameters=Object.assign({surfaceType:{type:"select",rebuild:!0,options:{vws:"vws",sas:"sas",ms:"ms",ses:"ses",av:"av"}},probeRadius:{type:"number",precision:1,max:20,min:0,rebuild:!0},smooth:{type:"integer",precision:1,max:10,min:0,rebuild:!0},scaleFactor:{type:"number",precision:1,max:5,min:0,rebuild:!0},cutoff:{type:"number",precision:2,max:50,min:0,rebuild:!0},contour:{type:"boolean",rebuild:!0},background:{type:"boolean",rebuild:!0},opaqueBack:{type:"boolean",buffer:!0},filterSele:{type:"text",rebuild:!0},colorVolume:{type:"hidden"},useWorker:{type:"boolean",rebuild:!0}},this.parameters,{radius:null,scale:null}),this.__infoList=[],this.structure.signals.refreshed.add((()=>{this.__forceNewMolsurf=!0})),this.toBePrepared=!0,this.init(i)}init(t){const e=t||{};e.colorScheme=st(e.colorScheme,"uniform"),e.colorValue=st(e.colorValue,14540253),e.disablePicking=st(e.disablePicking,!0),this.surfaceType=st(e.surfaceType,"ms"),this.probeRadius=st(e.probeRadius,1.4),this.smooth=st(e.smooth,2),this.scaleFactor=st(e.scaleFactor,2),this.cutoff=st(e.cutoff,0),this.contour=st(e.contour,!1),this.background=st(e.background,!1),this.opaqueBack=st(e.opaqueBack,!0),this.filterSele=st(e.filterSele,""),this.colorVolume=st(e.colorVolume,void 0),this.useWorker=st(e.useWorker,!0),super.init(t)}prepareData(t,i,r){let s=this.__infoList[i];if(s||(s={},this.__infoList[i]=s),s.molsurf&&s.sele===t.selection.string)r(i);else{if(this.filterSele){const s=t.structure.getView(new pe(this.filterSele)),n=s.boundingBox.getSize(new e),o=Math.max(n.x,n.y,n.z),a=t.getAtomSetWithinPoint(s.center,o/2+6);if(0===(t=t.getView(new pe(t.getAtomSetWithinSelection(a,3).toSeleString()))).atomCount)return void r(i)}s.sele=t.selection.string,s.molsurf=new zd(t);const n=this.getSurfaceParams(),o=t=>{s.surface=t,r(i)};this.useWorker?s.molsurf.getSurfaceWorker(n,o):o(s.molsurf.getSurface(n))}}prepare(t){if((this.__forceNewMolsurf||this.__sele!==this.selection.string||this.__surfaceParams!==JSON.stringify(this.getSurfaceParams()))&&(this.__infoList.forEach((t=>{t&&t.molsurf&&t.molsurf.dispose()})),this.__infoList.length=0),0===this.structureView.atomCount)return void t();const e=()=>{this.__sele=this.selection.string,this.__surfaceParams=JSON.stringify(this.getSurfaceParams()),this.__forceNewMolsurf=!1,t()},i="default"===this.assembly?this.defaultAssembly:this.assembly,r=this.structure.biomolDict[i];r?r.partList.forEach(((t,i)=>{const s=t.getView(this.structureView);this.prepareData(s,i,(t=>{t===r.partList.length-1&&e()}))})):this.prepareData(this.structureView,0,e)}createData(t,e){const i=this.__infoList[e],r=i.surface;if(!r)return;const s={position:r.getPosition(),color:r.getColor(this.getColorParams()),index:r.getFilteredIndex(this.filterSele,t)},n=[];if(r.contour){const t=new Xo(s,this.getBufferParams({wireframe:!1}));n.push(t)}else{Object.assign(s,{normal:r.getNormal(),picking:r.getPicking(t.getStructure())});const e=new jo(s,this.getBufferParams({background:this.background,opaqueBack:this.opaqueBack,dullInterior:!1}));if("double"==this.getBufferParams().side){const t=new qo(e);n.push(t)}else n.push(e)}return{bufferList:n,info:i}}updateData(t,e){const i={};if(t.position||t.radius)return this.__forceNewMolsurf=!0,void this.build();t.color&&(i.color=e.info.surface.getColor(this.getColorParams())),t.index&&(i.index=e.info.surface.getFilteredIndex(this.filterSele,e.sview)),e.bufferList[0].setAttributes(i)}setParameters(t,e={},i){return t&&t.filterSele&&(e.index=!0),t&&void 0!==t.colorVolume&&(e.color=!0),t&&t.wireframe&&(t.contour||void 0===t.contour&&this.contour)&&(t.wireframe=!1),super.setParameters(t,e,i),this}getSurfaceParams(t={}){return Object.assign({type:this.surfaceType,probeRadius:this.probeRadius,scaleFactor:this.scaleFactor,smooth:this.smooth&&!this.contour,cutoff:this.cutoff,contour:this.contour,useWorker:this.useWorker,radiusParams:this.getRadiusParams()},t)}getColorParams(){const t=super.getColorParams();return t.volume=this.colorVolume,t}getAtomRadius(){return 0}clear(){super.clear()}dispose(){this.__infoList.forEach((t=>{t&&t.molsurf&&t.molsurf.dispose()})),this.__infoList.length=0,super.dispose()}}Ne.add("surface",Vd);class Gd extends Sh{constructor(t,e,i){super(t,e,i),this.type="point",this.parameters=Object.assign({pointSize:{type:"number",precision:1,max:100,min:0,buffer:!0},sizeAttenuation:{type:"boolean",buffer:!0},sortParticles:{type:"boolean",rebuild:!0},useTexture:{type:"boolean",buffer:!0},alphaTest:{type:"range",step:.001,max:1,min:0,buffer:!0},forceTransparent:{type:"boolean",buffer:!0},edgeBleach:{type:"range",step:.001,max:1,min:0,buffer:!0}},this.parameters,{flatShaded:null,wireframe:null,linewidth:null,side:null,roughness:null,metalness:null}),this.init(i)}init(t){var e=t||{};this.pointSize=st(e.pointSize,1),this.sizeAttenuation=st(e.sizeAttenuation,!0),this.sortParticles=st(e.sortParticles,!1),this.useTexture=st(e.useTexture,!1),this.alphaTest=st(e.alphaTest,.5),this.forceTransparent=st(e.forceTransparent,!1),this.edgeBleach=st(e.edgeBleach,0),super.init(e)}createData(t){var e=t.getAtomData(this.getAtomParams({position:!0,color:!0,picking:!0}));return{bufferList:[new Wc(e,this.getBufferParams({pointSize:this.pointSize,sizeAttenuation:this.sizeAttenuation,sortParticles:this.sortParticles,useTexture:this.useTexture,alphaTest:this.alphaTest,forceTransparent:this.forceTransparent,edgeBleach:this.edgeBleach}))]}}updateData(t,e){var i=e.sview.getAtomData(this.getAtomParams(t)),r={};t&&!t.position||Object.assign(r,{position:i.position}),t&&!t.color||Object.assign(r,{color:i.color}),e.bufferList[0].setAttributes(r)}getAtomRadius(){return.1}}Ne.add("point",Gd),Ve.add("shader/Ribbon.vert","#define STANDARD\nuniform float clipNear;\nuniform vec3 clipCenter;\n#if defined( NEAR_CLIP ) || defined( RADIUS_CLIP ) || !defined( PICKING )\nvarying vec3 vViewPosition;\n#endif\n#if defined( RADIUS_CLIP )\nvarying vec3 vClipCenter;\n#endif\nattribute vec3 dir;\nattribute float size;\n#ifdef PICKING\n#include unpack_color\nattribute float primitiveId;\nvarying vec3 vPickingColor;\n#else\n#include color_pars_vertex\n#ifndef FLAT_SHADED\nvarying vec3 vNormal;\n#endif\n#endif\n#include common\nvoid main(void){\n#ifdef PICKING\nvPickingColor = unpackColor( primitiveId );\n#else\n#include color_vertex\n#include beginnormal_vertex\n#include defaultnormal_vertex\n#ifndef FLAT_SHADED\nvNormal = normalize( transformedNormal );\n#endif\n#endif\n#include begin_vertex\ntransformed += normalize( dir ) * size;\n#include project_vertex\n#if defined( NEAR_CLIP ) || defined( RADIUS_CLIP ) || !defined( PICKING )\nvViewPosition = -mvPosition.xyz;\n#endif\n#if defined( RADIUS_CLIP )\nvClipCenter = -( modelViewMatrix * vec4( clipCenter, 1.0 ) ).xyz;\n#endif\n#include nearclip_vertex\n}");const Ud=new Uint16Array([0,1,2,1,3,2]);function jd(t){return 3*(4*(t.position.length/3-1))}class Hd extends Uo{constructor(t,e={}){super({position:new Float32Array(jd(t)),color:new Float32Array(jd(t)),index:xt(jd(t),jd(t)/3),normal:new Float32Array(jd(t)),picking:t.picking},e),this.vertexShader="Ribbon.vert";const i=t.position.length/3-1,r=4*i,s=3*r;this.addAttributes({dir:{type:"v3",value:new Float32Array(s)}}),this.addAttributes({size:{type:"f",value:new Float32Array(r)}}),t.primitiveId=Pi(i),this.setAttributes(t),this.makeIndex()}setAttributes(t={}){const e=this.size/4,i=this.geometry.attributes;let r,s,n,o,a,c,l,h,d,u,m,p,f,g,y,b,x,v,w;t.position&&(r=t.position,l=i.position.array,i.position.needsUpdate=!0),t.normal&&(s=t.normal,h=i.normal.array,i.normal.needsUpdate=!0),t.size&&(n=t.size,d=i.size.array,i.size.needsUpdate=!0),t.dir&&(o=t.dir,u=i.dir.array,i.dir.needsUpdate=!0),t.color&&(a=t.color,m=i.color.array,i.color.needsUpdate=!0),t.primitiveId&&(c=t.primitiveId,p=i.primitiveId.array,i.primitiveId.needsUpdate=!0);let A=n?n[0]:null;for(f=0;f{if(!(t.residueCount<4)){i.push(t);var r=new od(t,this.getSplineParams()),s=r.getSubdividedPosition(),n=r.getSubdividedOrientation(),o=r.getSubdividedColor(this.getColorParams()),a=r.getSubdividedPicking(),c=r.getSubdividedSize(this.getRadiusParams());e.push(new Hd({position:s.position,normal:n.binormal,dir:n.normal,color:o.color,size:c.size,picking:a.picking},this.getBufferParams()))}}),t.getSelection()),{bufferList:e,polymerList:i}}updateData(t,e){t=t||{};var i=0,r=e.polymerList.length;for(i=0;i{if(t.residueCount<4||t.isNucleic())return;const s=new Pa(t),n=s.getAxis(this.localAngle,this.centerDist,this.ssBorder,this.getColorParams(),this.getRadiusParams());e+=n.size.length,i.push(n),r.push(s)}),t.getSelection());const s={begin:new Float32Array(3*e),end:new Float32Array(3*e),size:new Float32Array(e),color:new Float32Array(3*e),picking:{}};let n=new Float32Array(e),o=0;i.forEach((function(t){s.begin.set(t.begin,3*o),s.end.set(t.end,3*o),s.size.set(t.size,o),s.color.set(t.color,3*o),n.set(t.picking.array,o),o+=t.size.length})),e&&(s.picking=new Yn(n,t.getStructure()));return{bufferList:[new td({position1:s.begin,position2:s.end,color:s.color,color2:s.color,radius:s.size,picking:s.picking},this.getBufferParams({openEnded:this.openEnded,radialSegments:this.radialSegments,disableImpostor:this.disableImpostor,dullInterior:!0}))],axisList:i,helixbundleList:r,axisData:s}}updateData(t,e){if((t=t||{}).position)this.build();else{var i={};if(t.color||t.radius){var r=0;e.helixbundleList.forEach((i=>{var s=i.getAxis(this.localAngle,this.centerDist,this.ssBorder,this.getColorParams(),this.getRadiusParams());t.color&&e.axisData.color.set(s.color,3*r),(t.radius||t.scale)&&e.axisData.size.set(s.size,r),r+=s.size.length})),t.color&&Object.assign(i,{color:e.axisData.color,color2:e.axisData.color}),(t.radius||t.scale)&&Object.assign(i,{radius:e.axisData.size})}e.bufferList[0].setAttributes(i)}}}Ne.add("rocket",qd);class Xd extends dd{constructor(t,e,i){super(t,e,i),this.type="rope",this.parameters=Object.assign({smooth:{type:"integer",max:15,min:0,rebuild:!0}},this.parameters,{aspectRatio:null,smoothSheet:null})}init(t){var e=t||{};e.aspectRatio=1,e.tension=st(e.tension,.5),e.radiusScale=st(e.radiusScale,5),e.smoothSheet=!1,this.smooth=st(e.smooth,2),super.init(e)}getSpline(t){var e=new Ca(t);return new od(t,this.getSplineParams({directional:!1,positionIterator:e.getCenterIterator(this.smooth)}))}}Ne.add("rope",Xd);class Yd extends Sh{constructor(t,e,i){super(t,e,i),this.type="spacefill",this.parameters=Object.assign({sphereDetail:!0,disableImpostor:!0},this.parameters),this.init(i)}init(t){var e=t||{};e.useInteriorColor=st(e.useInteriorColor,!0),super.init(e)}createData(t){return{bufferList:[new Gc(t.getAtomData(this.getAtomParams()),this.getBufferParams({sphereDetail:this.sphereDetail,dullInterior:!0,disableImpostor:this.disableImpostor}))]}}updateData(t,e){var i=e.sview.getAtomData(this.getAtomParams(t)),r={};t&&!t.position||Object.assign(r,{position:i.position}),t&&!t.color||Object.assign(r,{color:i.color}),t&&!t.radius||Object.assign(r,{radius:i.radius}),e.bufferList[0].setAttributes(r)}}function Kd(t){return 3*(t.position.length/3-1)*2}Ne.add("spacefill",Yd);class Zd extends Go{constructor(t,e={}){super({position:new Float32Array(Kd(t)),color:new Float32Array(Kd(t))},e),this.isLine=!0,this.vertexShader="Line.vert",this.fragmentShader="Line.frag",this.setAttributes(t)}setAttributes(t){let e,i,r,s;const n=this.geometry.attributes;if(t.position&&(e=t.position,r=n.position.array,n.position.needsUpdate=!0),t.color&&(i=t.color,s=n.color.array,n.color.needsUpdate=!0),!e&&!i)return void Me.warn("TraceBuffer.prototype.setAttributes no data");let o,a;const c=this.size-1;for(let t=0;t{if(!(t.residueCount<4)){i.push(t);var r=new od(t,this.getSplineParams()),s=r.getSubdividedPosition(),n=r.getSubdividedColor(this.getColorParams());e.push(new Zd(Object.assign({},s,n),this.getBufferParams()))}}),t.getSelection()),{bufferList:e,polymerList:i}}updateData(t,e){t=t||{};var i=0,r=e.polymerList.length;for(i=0;i{t.boundingBox||t.computeBoundingBox(),this.boundingBox.union(t.boundingBox)}))}}const lu=Object.assign({aspectRatio:1.5,radialSegments:50,openEnded:!1,disableImpostor:!1},zo);class hu{constructor(t,e={}){this.group=new m,this.wireframeGroup=new m,this.pickingGroup=new m,this.visible=!0,this.parameters=nt(e,this.defaultParameters),this.splitPosition=new Float32Array(t.position1.length),this.cylinderRadius=new Float32Array(t.radius.length);const r=this.makeAttributes(t),s={radialSegments:this.parameters.radialSegments,openEnded:this.parameters.openEnded,disableImpostor:this.parameters.disableImpostor};this.cylinderBuffer=new td(r.cylinder,s),this.coneBuffer=new au(r.cone,s),this.geometry=new cu([this.cylinderBuffer.geometry,this.coneBuffer.geometry]),this.matrix=st(e.matrix,new i),this.picking=t.picking}get defaultParameters(){return lu}set matrix(t){Go.prototype.setMatrix.call(this,t)}get matrix(){return this.group.matrix.clone()}get pickable(){return!!this.picking}makeAttributes(t={}){const i=this.splitPosition,r=this.cylinderRadius,s=this.parameters.aspectRatio;let n,o;const a={},c={};if(t.radius){for(n=0,o=r.length;n(this._beforeParse(),this._parse(),this._afterParse(),this[this.__objName])))}_parse(){}_beforeParse(){}_afterParse(){De&&Me.log(this[this.__objName])}}class Nu extends Lu{constructor(t,e){var i=e||{};super(t,i),this.firstModelOnly=st(i.firstModelOnly,!1),this.asTrajectory=st(i.asTrajectory,!1),this.cAlphaOnly=st(i.cAlphaOnly,!1),this.structure=new Cc(this.name,this.path),this.structureBuilder=new za(this.structure)}get type(){return"structure"}get __objName(){return"structure"}}class zu{constructor(t,e,i="",r,s=[]){this.structure=t,this.index=e,this.description=i,this.entityType=function(t){switch(t=t.toLowerCase()){case"polymer":return 1;case"non-polymer":return 2;case"macrolide":return 3;case"water":return 4;default:return 0}}(r||""),this.chainIndexList=s,s.forEach((function(i){t.chainStore.entityIndex[i]=e}))}get type(){return function(t){switch(t){case 1:return"polymer";case 2:return"non-polymer";case 3:return"macrolide";case 4:return"water";default:return}}(this.entityType)}getEntityType(){return this.entityType}isPolymer(){return 1===this.entityType}isNonPolymer(){return 2===this.entityType}isMacrolide(){return 3===this.entityType}isWater(){return 4===this.entityType}eachChain(t){const e=this.structure.getChainProxy();this.chainIndexList.forEach((function(i){e.index=i,t(e)}))}}const Vu={a:1,b:1,c:1,alpha:90,beta:90,gamma:90,spacegroup:"P 1"};class Gu{constructor(t=Vu){this.cartToFrac=new i,this.fracToCart=new i,this.a=t.a,this.b=t.b,this.c=t.c,this.alpha=t.alpha,this.beta=t.beta,this.gamma=t.gamma,this.spacegroup=t.spacegroup;const e=kt(this.alpha),r=kt(this.beta),s=kt(this.gamma),n=Math.cos(e),o=Math.cos(r),a=Math.cos(s),c=Math.sin(r),l=Math.sin(s);if(this.volume=this.a*this.b*this.c*Math.sqrt(1-n*n-o*o-a*a+2*n*o*a),void 0===t.cartToFrac){const t=this.a*this.b*l/this.volume,e=(o*a-n)/(c*l);this.fracToCart.set(this.a,0,0,0,this.b*a,this.b*l,0,0,this.c*o,-this.c*c*e,1/t,0,0,0,0,1).transpose(),this.cartToFrac.getInverse(this.fracToCart)}else this.cartToFrac.copy(t.cartToFrac),this.fracToCart.getInverse(this.cartToFrac)}getPosition(t){const i=new Float32Array(24);if(t.unitcell){const r=t.unitcell,s=t.center.clone().applyMatrix4(r.cartToFrac).floor(),n=new e;let o=0;const a=function(t,e,a){n.set(t,e,a).add(s).applyMatrix4(r.fracToCart).toArray(i,o),o+=3};a(0,0,0),a(1,0,0),a(0,1,0),a(0,0,1),a(1,1,0),a(1,0,1),a(0,1,1),a(1,1,1)}return i}getCenter(t){return function(t,i=new e){const r=t.length;for(let e=0;e0)continue;let e,i,r,s,a,g=0;if(n){if(s=S.split(Wu),g=10===s.length?1:0,D=s[2],p&&"CA"!==D)continue;e=parseFloat(s[6-g]),i=parseFloat(s[7-g]),r=parseFloat(s[8-g])}else{if(D=S.substr(12,4).trim(),p&&"CA"!==D)continue;e=parseFloat(S.substr(30,8)),i=parseFloat(S.substr(38,8)),r=parseFloat(S.substr(46,8))}if(m){const t=3*b;if(y[t+0]=e,y[t+1]=i,y[t+2]=r,b+=1,x)continue}n?(P=parseInt(s[1]),a="",$="H"===S[0],I=g?"":s[4],k=parseInt(s[5-g]),B="",M=s[3],R="",T=1):(P=parseInt(S.substr(6,5),h),l&&99999===P&&(h=16),$="H"===S[0],I=S[21].trim(),k=parseInt(S.substr(22,4),d),l&&9999===k&&(d=16),B=S[26].trim(),M=S.substr(17,4).trim()||"MOL",O=parseFloat(S.substr(60,6)),R=S[16].trim(),T=parseFloat(S.substr(54,6)),t||(o?(a=S.substr(76,3).trim(),a in pn&&(a=pn[a])):(a=S.substr(76,2).trim(),I||(I=S.substr(72,4).trim())),E=parseInt((S.substr(79,1)+S.substr(78,1)).trim()))),dt.growIfFull(),dt.atomTypeId[pt]=ht.add(D,a),dt.x[pt]=e,dt.y[pt]=i,dt.z[pt]=r,dt.serial[pt]=P,dt.altloc[pt]=R.charCodeAt(0),dt.occupancy[pt]=isNaN(T)?0:T,n?(dt.partialCharge[pt]=parseFloat(s[9-g]),dt.radius[pt]=parseFloat(s[10-g])):(dt.bfactor[pt]=isNaN(O)?0:O,o&&(dt.partialCharge[pt]=parseFloat(S.substr(70,6))),isFinite(E)&&(dt.formalCharge||dt.addField("formalCharge",1,"int8"),dt.formalCharge[pt]=E));const v=qu(k,I,B);!$||K[v]||ju.includes(M)?tt||et===I||(Q+=1,J=Q.toString()):et===I&&rt===M&&(cn.includes(M)||it===k&&st===B)||(Q+=1,J=Q.toString(),it=k,rt=M,st=B),c.addAtom(ft,I,J,M,k,$,void 0,B),U[P]=pt,pt+=1,tt=!1,et=I}else if("CONECT"===C){const t=U[parseInt(S.substr(6,5))],e=[11,16,21,26],i={};if(void 0===t)continue;for(let r=0;r<4;++r){let s=parseInt(S.substr(e[r],5));if(!Number.isNaN(s)&&(s=U[s],void 0!==s))if(t0)continue;const s=e[l].replace(Zu,"");if(k&&"CA"!==s)continue;const T=parseFloat(e[x]),$=parseFloat(e[v]),O=parseFloat(e[w]);if(I){const e=3*r;if(t[e+0]=T,t[e+1]=$,t[e+2]=O,r+=1,X>0)continue}const R=e[h],E=parseInt(e[-1!==a?a:c]);let F=e[b];F="?"===F?"":F;const L=e[o],N=e[d],z="H"===e[p][0],V=e[g],Y=parseFloat(e[A]),K=parseFloat(e[_]);let Z=e[m];if(Z="."===Z?"":Z,H.growIfFull(),H.atomTypeId[q]=j.add(s,V),H.x[q]=T,H.y[q]=$,H.z[q]=O,H.serial[q]=parseInt(e[f]),H.bfactor[q]=isNaN(Y)?0:Y,H.occupancy[q]=isNaN(K)?0:K,H.altloc[q]=Z.charCodeAt(0),C.addAtom(X,L,N,R,E,z,void 0,F),De){const t=B[N];void 0!==t&&t!==L&&De&&Me.warn(t,L)}B[N]=L;const Q=e[u];D[Q]||(D[Q]=new Set),D[Q].add(S.chainStore.count-1),q+=1}else{const t=n.match(Ku),e=t.length;N===L.length&&(N=0);for(let i=0;ic*c)return o.growIfFull(),o.atomTypeId[f]=o.atomTypeId[t],o.x[f]=u.x,o.y[f]=u.y,o.z[f]=u.z,o.occupancy[f]=o.occupancy[t],o.serial[f]=f,o.altloc[f]="A".charCodeAt(0),s.addAtom(0,"","","HET",1,!0),void(f+=1)}}}))}}(T,S,C),C.finalize(),S.finalizeAtoms(),Wa(S),S.finalizeBonds();else{var Y=function(t,e,i){var r,s,n,o,a=[],c=[],l=t.struct_conf;if(null==l?void 0:l.pdbx_PDB_helix_class)for(em(l,"id"),r=0,s=l.beg_auth_seq_id.length;r0){o=o.split("(");var l=c(o[0]),h=c(o[1]);Object.keys(l).forEach((function(t){Object.keys(h).forEach((function(e){var r=new i;r.multiplyMatrices(l[t],h[e]),s[t+"x"+e]=r}))}))}else s=c(o);var d=[];for(var u in s)d.push(s[u]);var m=t;/^(0|[1-9][0-9]*)$/.test(m)&&(m="BU"+m);for(var p=a.asym_id_list[e].split(","),f=0,g=p.length;fA){var _=w;w=A,A=_;var S=p;p=x,x=S}if(0!==w&&0!==A)for(var C=0;Cb)continue}d=I.substr(5,5).trim(),u=parseInt(I.substr(0,5)),m=parseInt(I.substr(15,5)),v.growIfFull(),v.atomTypeId[w]=x.add(h),v.x[w]=T,v.y[w]=B,v.z[w]=D,v.serial[w]=m,r.addAtom(A,"","",d,u,!1,"l"),w+=1}}}(0,i.length,i)})),r.finalize(),i.finalizeAtoms(),Ha(i),Wa(i),i.finalizeBonds(),Ga(i),De&&Me.timeEnd("GroParser._parse "+this.name)}});var om=["mmtfVersion","mmtfProducer","unitCell","spaceGroup","structureId","title","depositionDate","releaseDate","experimentalMethods","resolution","rFree","rWork","bioAssemblyList","ncsOperatorList","entityList","groupList","numBonds","numAtoms","numGroups","numChains","numModels","groupsPerChain","chainsPerModel"].concat(["xCoordList","yCoordList","zCoordList","groupIdList","groupTypeList","chainIdList","bFactorList","atomIdList","altLocList","occupancyList","secStructList","insCodeList","sequenceIndexList","chainNameList","bondAtomList","bondOrderList"]);function am(t,e,i){return e?new t(e.buffer,e.byteOffset,e.byteLength/(i||1)):void 0}function cm(t){return am(DataView,t)}function lm(t){return am(Int8Array,t)}function hm(t){return am(Int32Array,t,4)}function dm(t,e){var i=t.length/2;e||(e=new Int16Array(i));for(var r=0,s=0;rn&&++a;e=new Int32Array(a)}for(i=0,r=0;is){for(var n=[],o=0;o0&&(o.biomolDict[t]=e)}const O=a.unitCell;O&&Array.isArray(O)&&O[0]?o.unitcell=new Gu({a:O[0],b:O[1],c:O[2],alpha:O[3],beta:O[4],gamma:O[5],spacegroup:a.spaceGroup}):o.unitcell=void 0,Ka(o,!0),Ya(o,!0),o.finalizeAtoms(),o.finalizeBonds(),Za(o),De&&Me.timeEnd("MmtfParser._parse "+this.name)}});const _m=/\s+/,Sm={1:1,2:2,3:3,am:1,ar:1,du:1,un:1,nc:0};ze.add("mol2",class extends Nu{get type(){return"mol2"}_parse(){De&&Me.time("Mol2Parser._parse "+this.name);const t=this.structure,e=this.structureBuilder,i=this.firstModelOnly,r=this.asTrajectory,s=t.frames;let n,o,a=!1;const c=t.atomMap,l=t.atomStore;l.resize(Math.round(this.streamer.data.length/60)),l.addField("partialCharge",1,"float32");let h=0,d=0,u=0,m=-1,p=0,f=0;const g=t.getAtomProxy(),y=t.getAtomProxy();this.streamer.eachChunkOfLines((function(b){!function(b,x,v){for(let w=b;wMOLECULE"===b?(f=1,d=0,++m):"@ATOM"===b?(f=2,u=l.count,r&&(o=0,n=new Float32Array(3*p),s.push(n),m>0&&(a=!0))):f="@BOND"===b?3:0;else if(1===f){if(0===d)t.title=b,t.id=b;else if(1===d){const t=b.split(_m);p=parseInt(t[0])}++d}else if(2===f){const t=b.split(_m);if(i&&m>0)continue;const s=parseFloat(t[2]),d=parseFloat(t[3]),u=parseFloat(t[4]);if(r){const t=3*o;if(n[t+0]=s,n[t+1]=d,n[t+2]=u,o+=1,a)continue}const p=t[0],f=t[1],g=t[5].split(".")[0],y=t[6]?parseInt(t[6]):1,x=t[7]?t[7]:"",v=t[8]?parseFloat(t[8]):0;l.growIfFull(),l.atomTypeId[h]=c.add(f,g),l.x[h]=s,l.y[h]=d,l.z[h]=u,l.serial[h]=p,l.partialCharge[h]=v,e.addAtom(m,"","",x,y,!0),h+=1}else if(3===f){if(i&&m>0)continue;if(r&&m>0)continue;const e=b.split(_m);g.index=parseInt(e[1])-1+u,y.index=parseInt(e[2])-1+u;const s=Sm[e[3]];t.bondStore.addBond(g,y,s)}}}(0,b.length,b)})),e.finalize(),t.finalizeAtoms(),Ha(t),Ya(t,!0),Ka(t,!0),t.finalizeBonds(),ec(t),Ga(t),De&&Me.timeEnd("Mol2Parser._parse "+this.name)}});ze.add("pdbqt",class extends Xu{get type(){return"pdbqt"}});ze.add("pqr",class extends Xu{get type(){return"pqr"}});const Cm=/> +<(.+)>/;class Pm extends Nu{get type(){return"sdf"}_parse(){De&&Me.time("SdfParser._parse "+this.name);const t=this.structure,e=this.structureBuilder,i=this.firstModelOnly,r=this.asTrajectory,s=this.streamer.peekLines(2);t.id=s[0].trim(),t.title=s[1].trim();const n=t.frames;let o,a,c=!1;const l=t.atomMap,h=t.atomStore;h.resize(Math.round(this.streamer.data.length/50)),h.addField("formalCharge",1,"int8");const d=t.getAtomProxy(),u=t.getAtomProxy();let m=0,p=0,f=0,g=0;const y=[];let b,x,v,w,A,_,S,C,P,I,k,M,T,B,D=!1,$={};t.extraData.sdf=y;let O=!1,R=!1,E=!1,F=[],L=[];const N=new Map;this.streamer.eachChunkOfLines((function(s){!function(s,z,V){for(let G=s;G-1,O?N.clear():(x=parseInt(s.substr(0,3)),v=parseInt(s.substr(3,3)),w=4,A=w+x,_=A,S=_+v,r&&(a=0,o=new Float32Array(3*x),n.push(o),f>0&&(c=!0)));else if(O&&"COUNTS"===F[0])x=parseInt(F[1]),r&&(a=0,o=new Float32Array(3*x),n.push(o),f>0&&(c=!0));else if(O&&2==F.length)"ATOM"===F[1]?"BEGIN"===F[0]?R=!0:"END"===F[0]&&(R=!1):"BOND"===F[1]&&("BEGIN"===F[0]?E=!0:"END"===F[0]&&(E=!1));else if(R||!O&&p>=w&&p0)continue;let t=0;if(O){if(C=parseFloat(F[2]),P=parseFloat(F[3]),I=parseFloat(F[4]),M=F[1],T=parseInt(F[0]),N.set(T,m),k=M+T,F.length>6){let e=F.slice(6).find((t=>0===t.indexOf("CHG=")));e&&(t=parseInt(e.substring(4)))}}else C=parseFloat(s.substr(0,10)),P=parseFloat(s.substr(10,10)),I=parseFloat(s.substr(20,10)),M=s.substr(31,3).trim(),k=M+(m-g+1);if(r){const t=3*a;if(o[t+0]=C,o[t+1]=P,o[t+2]=I,a+=1,c)continue}h.growIfFull(),h.atomTypeId[m]=l.add(k,M),h.x[m]=C,h.y[m]=P,h.z[m]=I,h.serial[m]=O?T:m,h.formalCharge[m]=t,e.addAtom(f,"","","HET",1,!0),m+=1}else if(E||!O&&p>=_&&p0)continue;if(r&&f>0)continue;O?(d.index=N.get(parseInt(F[2])),u.index=N.get(parseInt(F[3])),B=parseInt(F[1])):(d.index=parseInt(s.substr(0,3))-1+g,u.index=parseInt(s.substr(3,3))-1+g,B=parseInt(s.substr(6,3))),t.bondStore.addBond(d,u,B)}else if("M CHG"===s.substr(0,6)){const t=parseInt(s.substr(6,3));for(let e=0,i=10;e"===s.charAt(0)&&(b=s.match(Cm))?(D=b[1],$[D]=[]):!1!==D&&s&&$[D].push(s);++p}}}(0,s.length,s)})),e.finalize(),t.finalizeAtoms(),t.finalizeBonds(),ec(t),De&&Me.timeEnd("SdfParser._parse "+this.name)}_postProcess(){ec(this.structure)}}ze.add("sdf",Pm),ze.add("sd",Pm),ze.add("mol",Pm);function Im(t,e,i){return parseInt(t.substr(e,i).trim())}class km extends Nu{get type(){return"prmtop"}_parse(){De&&Me.time("PrmtopParser._parse "+this.name);const t=this.structure,e=this.structureBuilder,i=t.atomMap,r=t.atomStore;r.addField("partialCharge",1,"float32"),r.addField("radius",1,"float32");const s=[],n={},o=["NATOM","NTYPES","NBONH","MBONA","NTHETH","MTHETA","NPHIH","MPHIA","NHPARM","NPARM","NNB","NRES","NBONA","NTHETA","NPHIA","NUMBND","NUMANG","NPTRA","NATYP","NPHB","IFPERT","NBPER","NGPER","NDPER","MBPER","MGPER","MDPER","IFBOX","NMXRS","IFCAP","NUMEXTRA","NCOPY"];let a,c,l,h,d;o.forEach((t=>{n[t]=0}));let u,m,p,f,g,y=new Uint8Array(0);this.streamer.eachChunkOfLines((function(t){!function(t,e,i){for(let b=t;b0)return void Me.error("dcd format with fixed atoms unsupported, aborting");const p=n.NATOM,f=4*p;for(let i=0,a=n.NSET;i=1&&(i.timeOffset=(n.ISTART-1)*i.deltaTime),De&&Me.timeEnd("DcdParser._parse "+this.name)}});const Fm={BYTE:1,CHAR:2,SHORT:3,INT:4,FLOAT:5,DOUBLE:6};function Lm(t){switch(Number(t)){case Fm.BYTE:return"byte";case Fm.CHAR:return"char";case Fm.SHORT:return"short";case Fm.INT:return"int";case Fm.FLOAT:return"float";case Fm.DOUBLE:return"double";default:return"undefined"}}function Nm(t){switch(Number(t)){case Fm.BYTE:case Fm.CHAR:return 1;case Fm.SHORT:return 2;case Fm.INT:case Fm.FLOAT:return 4;case Fm.DOUBLE:return 8;default:return-1}}function zm(t){switch(String(t)){case"byte":return Fm.BYTE;case"char":return Fm.CHAR;case"short":return Fm.SHORT;case"int":return Fm.INT;case"float":return Fm.FLOAT;case"double":return Fm.DOUBLE;default:return-1}}function Vm(t,e){if(1!==t){const i=new Array(t);for(let r=0;r6,"non valid type "+h);const d=t.readUint32();let u=t.readUint32();2===i&&(Om(u>0,"offsets larger than 4GB not supported"),u=t.readUint32()),c[0]===e&&(n+=d),s[r]={name:o,dimensions:c,attributes:l,type:Lm(h),size:d,offset:u,record:c[0]===e}}}return{variables:s,recordStep:n}}(t,r.recordId,e);return i.variables=s.variables,i.recordDimension.recordStep=s.recordStep,i}function Xm(t){let e;const i=t.readUint32();if(i===Um)return Om(t.readUint32()!==Um,"wrong empty tag for list of attributes"),[];{Om(i!==Wm,"wrong tag for list of attributes");const r=t.readUint32();e=new Array(r);for(let i=0;i6,"non valid type "+s);const n=t.readUint32(),o=Gm(t,s,n);Rm(t),e[i]={name:r,type:Lm(s),value:o}}}return e}class Ym{constructor(t){const e=new hi(t);e.setBigEndian(),Om("CDF"!==e.readChars(3),"should start with CDF");const i=e.readByte();Om(i>2,"unknown version"),this.header=qm(e,i),this.buffer=e}get version(){return 1===this.header.version?"classic format":"64-bit offset format"}get recordDimension(){return this.header.recordDimension}get dimensions(){return this.header.dimensions}get globalAttributes(){return this.header.globalAttributes}get variables(){return this.header.variables}hasDataVariable(t){return-1!==this.header.variables.findIndex((function(e){return e.name===t}))}getDataVariable(t){let e;return e="string"==typeof t?this.header.variables.find((function(e){return e.name===t})):t,Om(void 0===e,"variable not found"),this.buffer.seek(e.offset),e.record?function(t,e,i){const r=zm(e.type),s=e.size?e.size/Nm(r):1,n=i.length,o=new Array(n),a=i.recordStep;for(let e=0;e=1&&(e.timeOffset=s[0]),s.length>=2&&(e.deltaTime=s[1]-s[0]),De&&Me.timeEnd("NctrajParser._parse "+this.name)}}ze.add("nctraj",Km),ze.add("ncdf",Km),ze.add("nc",Km);ze.add("trr",class extends $m{get type(){return"trr"}get isBinary(){return!0}_parse(){De&&Me.time("TrrParser._parse "+this.name);const t=vt(this.streamer.data),e=new DataView(t),i=this.frames,r=i.coordinates,s=i.boxes,n=i.times;let o=0;for(;;){o+=8;const i=e.getInt32(o);o+=4,o+=i;const a=e.getInt32(o+8),c=e.getInt32(o+12),l=e.getInt32(o+16),h=e.getInt32(o+28),d=e.getInt32(o+32),u=e.getInt32(o+36),m=e.getInt32(o+40);o+=52;const p=a/9,f=3*m;if(8===p?n.push(e.getFloat64(o)):n.push(e.getFloat32(o)),o+=2*p,a){const t=new Float32Array(9);if(8===p)for(let i=0;i<9;++i)t[i]=10*e.getFloat64(o),o+=8;else for(let i=0;i<9;++i)t[i]=10*e.getFloat32(o),o+=4;s.push(t)}if(o+=c,o+=l,h){let i;if(8===p){i=new Float32Array(f);for(let t=0;t>8&65280|i>>24&255}i=new Float32Array(t,o,f);for(let t=0;t=t.byteLength)break}n.length>=1&&(i.timeOffset=n[0]),n.length>=2&&(i.deltaTime=n[1]-n[0]),De&&Me.timeEnd("TrrParser._parse "+this.name)}});const Zm=new Uint32Array([0,0,0,0,0,0,0,0,0,8,10,12,16,20,25,32,40,50,64,80,101,128,161,203,256,322,406,512,645,812,1024,1290,1625,2048,2580,3250,4096,5060,6501,8192,10321,13003,16384,20642,26007,32768,41285,52015,65536,82570,104031,131072,165140,208063,262144,330280,416127,524287,660561,832255,1048576,1321122,1664510,2097152,2642245,3329021,4194304,5284491,6658042,8388607,10568983,13316085,16777216]);function Qm(t){let e=1,i=0;for(;t>=e&&i<32;)i++,e<<=1;return i}const Jm=new Uint8Array(32);function tp(t,e){let i=1,r=0;Jm[0]=1;for(let r=0;r>=8;for(;0!==s;)Jm[t++]=255&s,s>>=8;i=t}let s=1;for(i--;Jm[i]>=s;)r++,s*=2;return r+8*i}function ep(t,e,i,r){const s=(1<=8;)o=o<<8|e[a++],c|=o>>n<0&&(n>n&(1<8;)ip[a++]=ep(t,e,8,o),r-=8;r>0&&(ip[a++]=ep(t,e,r,o));for(let t=i-1;t>0;t--){let e=0;for(let i=a-1;i>=0;i--){e=e<<8|ip[i];const r=e/s[t]|0;ip[i]=r,e-=r*s[t]}n[t]=e}n[0]=ip[0]|ip[1]<<8|ip[2]<<16|ip[3]<<24}ze.add("xtc",class extends $m{get type(){return"xtc"}get isBinary(){return!0}_parse(){De&&Me.time("XtcParser._parse "+this.name);const t=vt(this.streamer.data),e=new DataView(t),i=this.frames,r=i.coordinates,s=i.boxes,n=i.times,o=new Int32Array(6),a=new Int32Array(3),c=new Int32Array(3),l=new Uint32Array(3),h=new Float32Array(3),d=new Float32Array(3);let u=0;const m=new Int32Array(3),p=new Uint32Array(m.buffer);for(;;){let i;const f=e.getInt32(u+4);u+=12;const g=3*f;n.push(e.getFloat32(u)),u+=4;const y=new Float32Array(9);for(let t=0;t<9;++t)y[t]=10*e.getFloat32(u),u+=4;if(s.push(y),f<=9){i=new Float32Array(f);for(let t=0;t16777215?(c[0]=Qm(a[0]),c[1]=Qm(a[1]),c[2]=Qm(a[2]),f=0):f=tp(3,a);let y=e.getInt32(u);u+=4;let b=y-1;b=9>b?9:b;let x=Zm[b]/2|0,v=Zm[y]/2|0;l[0]=l[1]=l[2]=Zm[y];let w=4*Math.ceil(e.getInt32(u)/4);u+=4;const A=1/n;let _=0,S=0;const C=new Uint8Array(t,u);for(h[0]=h[1]=h[2]=0;S0){h[0]=h[1]=h[2]=0;for(let t=0;t<_;t+=3){if(rp(m,C,3,y,l,h,p),S++,h[0]+=d[0]-v,h[1]+=d[1]-v,h[2]+=d[2]-v,0===t){let t=h[0];h[0]=d[0],d[0]=t,t=h[1],h[1]=d[1],d[1]=t,t=h[2],h[2]=d[2],d[2]=t,i[r++]=d[0]*A,i[r++]=d[1]*A,i[r++]=d[2]*A}else d[0]=h[0],d[1]=h[1],d[2]=h[2];i[r++]=h[0]*A,i[r++]=h[1]*A,i[r++]=h[2]*A}}else i[r++]=h[0]*A,i[r++]=h[1]*A,i[r++]=h[2]*A;if(y+=t,t<0?(v=x,x=y>9?Zm[y-1]/2|0:0):t>0&&(x=v,v=Zm[y]/2|0),l[0]=l[1]=l[2]=Zm[y],0===l[0]||0===l[1]||0===l[2])return void console.error("(xdrfile error) Undefined error.")}u+=w}for(let t=0;t=t.byteLength)break}n.length>=1&&(i.timeOffset=n[0]),n.length>=2&&(i.deltaTime=n[1]-n[0]),De&&Me.timeEnd("XtcParser._parse "+this.name)}});class sp extends Lu{constructor(t,e){const i=e||{};super(t,i),this.volume=new Eo(this.name,this.path),this.voxelSize=st(i.voxelSize,1)}get type(){return"volume"}get __objName(){return"volume"}_afterParse(){this.volume.setMatrix(this.getMatrix()),super._afterParse()}getMatrix(){return new i}}const np=/\s+/,op=/-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?/g,ap=.529177210859;class cp extends sp{get type(){return"cube"}_parse(){De&&Me.time("CubeParser._parse "+this.name);const t=this.volume,i=this.streamer.peekLines(6),r={},s=ap*this.voxelSize;function n(t,e){var r=i[t].trim().split(np)[e];return parseFloat(r)}r.atomCount=Math.abs(n(2,0)),r.originX=n(2,1)*ap,r.originY=n(2,2)*ap,r.originZ=n(2,3)*ap,r.NVX=n(3,0),r.NVY=n(4,0),r.NVZ=n(5,0),r.basisX=new e(n(3,1),n(3,2),n(3,3)).multiplyScalar(s),r.basisY=new e(n(4,1),n(4,2),n(4,3)).multiplyScalar(s),r.basisZ=new e(n(5,1),n(5,2),n(5,3)).multiplyScalar(s);const o=new Float32Array(r.NVX*r.NVY*r.NVZ);let a=0,c=0;const l=n(2,0)>0?0:1;this.streamer.eachChunkOfLines((function(t){!function(t,e,i){for(let s=t;s=r.atomCount+6+l){const e=t.match(op);for(let t=0,i=e.length;t>8&255}e.xStart=n[0],e.yStart=n[1],e.zStart=n[2],e.xExtent=n[3],e.yExtent=n[4],e.zExtent=n[5],e.xRate=n[6],e.yRate=n[7],e.zRate=n[8];const t=1/n[17],s=t*this.voxelSize;e.xlen=n[9]*s,e.ylen=n[10]*s,e.zlen=n[11]*s,e.alpha=n[12]*t,e.beta=n[13]*t,e.gamma=n[14]*t,i=n[15]/100,r=n[16],e.gamma=n[14]*t}t.header=e,De&&Me.log(e,i,r);const c=new Float32Array(e.xExtent*e.yExtent*e.zExtent);let l=512;const h=Math.ceil(e.xExtent/8),d=Math.ceil(e.yExtent/8),u=Math.ceil(e.zExtent/8);for(var m=0;ms){const t=i[r].trim();if(""!==t){const e=t.split(hp);for(let t=0,i=e.length;t=s&&(p-s)%u!=0&&m=0?i-1:i+e/3)},parseNormalIndex:function(t,e){var i=parseInt(t,10);return 3*(i>=0?i-1:i+e/3)},addVertex:function(t,e,i){var r=this.vertices,s=this.object.geometry.vertices;s.push(r[t+0]),s.push(r[t+1]),s.push(r[t+2]),s.push(r[e+0]),s.push(r[e+1]),s.push(r[e+2]),s.push(r[i+0]),s.push(r[i+1]),s.push(r[i+2])},addVertexLine:function(t){var e=this.vertices,i=this.object.geometry.vertices;i.push(e[t+0]),i.push(e[t+1]),i.push(e[t+2])},addNormal:function(t,e,i){var r=this.normals,s=this.object.geometry.normals;s.push(r[t+0]),s.push(r[t+1]),s.push(r[t+2]),s.push(r[e+0]),s.push(r[e+1]),s.push(r[e+2]),s.push(r[i+0]),s.push(r[i+1]),s.push(r[i+2])},addFace:function(t,e,i,r,s,n,o,a){var c,l=this.vertices.length,h=this.parseVertexIndex(t,l),d=this.parseVertexIndex(e,l),u=this.parseVertexIndex(i,l);if(void 0===r?this.addVertex(h,d,u):(c=this.parseVertexIndex(r,l),this.addVertex(h,d,c),this.addVertex(d,u,c)),void 0!==s){var m=this.normals.length;h=this.parseNormalIndex(s,m),d=s===n?h:this.parseNormalIndex(n,m),u=s===o?h:this.parseNormalIndex(o,m),void 0===r?this.addNormal(h,d,u):(c=this.parseNormalIndex(a,m),this.addNormal(h,d,c),this.addNormal(d,u,c))}},addLineGeometry:function(t){this.object.geometry.type="Line";for(var e=this.vertices.length,i=0,r=t.length;i0?x.setAttribute("normal",new M(new Float32Array(b.normals),3)):x.computeVertexNormals(),y.push(x)}}return y}};ze.add("obj",class extends kp{get type(){return"obj"}getLoader(){return new Mp}});const Tp=function(){this.propertyNameMapping={}};Tp.prototype={constructor:Tp,setPropertyNameMapping:function(t){this.propertyNameMapping=t},bin2str:function(t){for(var e=new Uint8Array(t),i="",r=0;r=r.elements[o].count&&(o++,a=0);var h=this.parseASCIIElement(r.elements[o].properties,l);this.handleElement(i,r.elements[o].name,h),a++}}return this.postProcess(i)},postProcess:function(t){if(t.useColor){for(var e=0;e{const s=r.length;for(let n=0;n/g,""),{declaration:e(),root:i()};function e(){if(!s(/^<\?xml\s*/))return;const t={attributes:{}};for(;!n()&&!o("?>");){const e=r();if(!e)return t;t.attributes[e.name]=e.value}return s(/\?>\s*/),t}function i(){const t=s($p);if(!t)return;const e={name:t[1],attributes:{},children:[]};for(;!(n()||o(">")||o("?>")||o("/>"));){const t=r();if(!t)return e;e.attributes[t.name]=t.value}if(s(/^\s*\/>\s*/))return e;let a;for(s(/\??>\s*/),e.content=function(){const t=s(Op);return t?t[1]:""}();a=i();)e.children.push(a);return s(/^<\/[\w-:.]+>\s*/),e}function r(){const t=s(Rp);var e;if(t)return{name:t[1],value:(e=t[2],e.replace(Dp,""))}}function s(e){const i=t.match(e);if(i)return t=t.slice(i[0].length),i}function n(){return 0===t.length}function o(e){return 0===t.indexOf(e)}}class Fp extends Lu{constructor(t,e){const i=e||{};super(t,i),this.useDomParser=st(i.useDomParser,!1),this.xml={name:this.name,path:this.path,data:{}}}get type(){return"xml"}get __objName(){return"xml"}get isXml(){return!0}__xmlParser(t){return Ep(t)}__domParser(t){return(new window.DOMParser).parseFromString(t,"text/xml")}_parse(){De&&Me.time("XmlParser._parse "+this.name),this.useDomParser?this.streamer.data instanceof Document?this.xml.data=this.streamer.data:this.xml.data=this.__domParser(this.streamer.asText()):this.xml.data=this.__xmlParser(this.streamer.asText()),De&&Me.timeEnd("XmlParser._parse "+this.name)}}function Lp(t,e){const i=t.getNamedItem(e);return null!==i?i.value:""}function Np(t,e,i=!1){const r=Lp(t,"icode").trim(),s=Lp(t,"chain").trim(),n=Lp(t,"altcode");let o=Lp(t,"resnum");return r&&(o+="^"+r),s&&(o+=":"+s),e&&(o+="."+e),i&&n.trim()&&(o+="%"+n),o+="/"+(parseInt(Lp(t,"model"))-1),o}function zp(t){const e=Lp(t,"chain").trim();let i=`[${Lp(t,"rescode")}]${Lp(t,"resnum")}`;return e&&(i+=`:${e}`),i}function Vp(t,e,i){void 0===t[e]?t[e]=i:t[e]|=i}function Gp(t,e){return null!==t&&t.value===e}function Up(t,e,i){let r=0;const s=e.getElementsByTagName("clash");for(let e=0,i=s.length;e0&&(r+=1);e.getElementsByTagName("bond-outlier").length>0&&(r+=1);return e.getElementsByTagName("plane-outlier").length>0&&(r+=1),Gp(i.getNamedItem("rota"),"OUTLIER")&&(r+=1),Gp(i.getNamedItem("rama"),"OUTLIER")&&(r+=1),Gp(i.getNamedItem("RNApucker"),"outlier")&&(r+=1),r}ze.add("xml",Fp);class jp{constructor(t,e){this.name=t,this.path=e,this.rsrzDict={},this.rsccDict={},this.rciDict={},this.clashDict={},this.clashArray=[],this.geoDict={},this.geoAtomDict={},this.atomDict={},this.clashSele="NONE"}get type(){return"validation"}fromXml(t){De&&Me.time("Validation.fromXml");const e=this.rsrzDict,i=this.rsccDict,r=this.rciDict,s=this.clashDict,n=this.clashArray,o=this.geoDict,a=this.geoAtomDict,c=this.atomDict,l=t.getElementsByTagName("Entry");if(1===l.length){const t=l[0].getElementsByTagName("chemical_shift_list");if(1===t.length){const e=t[0].getElementsByTagName("random_coil_index");for(let t=0,i=e.length;t0&&(o[r]=t)}else{const t=e.getElementsByTagName("clash"),i=e.getElementsByTagName("mog-bond-outlier"),n=e.getElementsByTagName("mog-angle-outlier");if(i.length>0||n.length>0||t.length>0){const e={};a[r]=e;for(let i=0,r=t.length;i>>16&65535|0,o=0;0!==i;){i-=o=i>2e3?2e3:i;do{n=n+(s=s+e[r++]|0)|0}while(--o);s%=65521,n%=65521}return s|n<<16|0}ze.add("validation",class extends Fp{constructor(t,e){super(t,e||{}),this.useDomParser=!0,this.validation=new jp(this.name,this.path)}get __objName(){return"validation"}get isXml(){return!0}_parse(){super._parse(),De&&Me.time("ValidationParser._parse "+this.name),this.validation.fromXml(this.xml.data),De&&Me.timeEnd("ValidationParser._parse "+this.name)}});var Xp=function(){for(var t,e=[],i=0;i<256;i++){t=i;for(var r=0;r<8;r++)t=1&t?3988292384^t>>>1:t>>>1;e[i]=t}return e}();function Yp(t,e,i,r){var s=Xp,n=r+i;t^=-1;for(var o=r;o>>8^s[255&(t^e[o])];return-1^t}var Kp=30,Zp=12;function Qp(t,e){var i,r,s,n,o,a,c,l,h,d,u,m,p,f,g,y,b,x,v,w,A,_,S,C,P;i=t.state,r=t.next_in,C=t.input,s=r+(t.avail_in-5),n=t.next_out,P=t.output,o=n-(e-t.avail_out),a=n+(t.avail_out-257),c=i.dmax,l=i.wsize,h=i.whave,d=i.wnext,u=i.window,m=i.hold,p=i.bits,f=i.lencode,g=i.distcode,y=(1<>>=v=x>>>24,p-=v,0===(v=x>>>16&255))P[n++]=65535&x;else{if(!(16&v)){if(0==(64&v)){x=f[(65535&x)+(m&(1<>>=v,p-=v),p<15&&(m+=C[r++]<>>=v=x>>>24,p-=v,!(16&(v=x>>>16&255))){if(0==(64&v)){x=g[(65535&x)+(m&(1<c){t.msg="invalid distance too far back",i.mode=Kp;break t}if(m>>>=v,p-=v,A>(v=n-o)){if((v=A-v)>h&&i.sane){t.msg="invalid distance too far back",i.mode=Kp;break t}if(_=0,S=u,0===d){if(_+=l-v,v2;)P[n++]=S[_++],P[n++]=S[_++],P[n++]=S[_++],w-=3;w&&(P[n++]=S[_++],w>1&&(P[n++]=S[_++]))}else{_=n-A;do{P[n++]=P[_++],P[n++]=P[_++],P[n++]=P[_++],w-=3}while(w>2);w&&(P[n++]=P[_++],w>1&&(P[n++]=P[_++]))}break}}break}}while(r>3,m&=(1<<(p-=w<<3))-1,t.next_in=r,t.next_out=n,t.avail_in=r=1&&0===T[w];w--);if(A>w&&(A=w),0===w)return s[n++]=20971520,s[n++]=20971520,a.bits=1,0;for(v=1;v0&&(t===rf||1!==w))return-1;for(B[1]=0,b=1;btf||t===nf&&P>ef)return 1;for(;;){p=b-S,o[x]m?(f=D[$+o[x]],g=k[M+o[x]]):(f=96,g=0),c=1<>S)+(l-=c)]=p<<24|f<<16|g|0}while(0!==l);for(c=1<>=1;if(0!==c?(I&=c-1,I+=c):I=0,x++,0==--T[b]){if(b===w)break;b=e[i+o[x]]}if(b>A&&(I&d)!==h){for(0===S&&(S=A),u+=v,C=1<<(_=b-S);_+Stf||t===nf&&P>ef)return 1;s[h=I&d]=A<<24|_<<16|u-n|0}}return 0!==I&&(s[u+I]=b-S<<24|64<<16|0),a.bits=A,0}var df=1,uf=2,mf=0,pf=-2,ff=1,gf=12,yf=30,bf=852,xf=592;function vf(t){return(t>>>24&255)+(t>>>8&65280)+((65280&t)<<8)+((255&t)<<24)}function wf(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new Uint16Array(320),this.work=new Uint16Array(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function Af(t){var e;return t&&t.state?((e=t.state).wsize=0,e.whave=0,e.wnext=0,function(t){var e;return t&&t.state?(e=t.state,t.total_in=t.total_out=e.total=0,t.msg="",e.wrap&&(t.adler=1&e.wrap),e.mode=ff,e.last=0,e.havedict=0,e.dmax=32768,e.head=null,e.hold=0,e.bits=0,e.lencode=e.lendyn=new Int32Array(bf),e.distcode=e.distdyn=new Int32Array(xf),e.sane=1,e.back=-1,mf):pf}(t)):pf}function _f(t,e){var i,r;return t?(r=new wf,t.state=r,r.window=null,i=function(t,e){var i,r;return t&&t.state?(r=t.state,e<0?(i=0,e=-e):(i=1+(e>>4),e<48&&(e&=15)),e&&(e<8||e>15)?pf:(null!==r.window&&r.wbits!==e&&(r.window=null),r.wrap=i,r.wbits=e,Af(t))):pf}(t,e),i!==mf&&(t.state=null),i):pf}var Sf,Cf,Pf=!0;function If(t){if(Pf){var e;for(Sf=new Int32Array(512),Cf=new Int32Array(32),e=0;e<144;)t.lens[e++]=8;for(;e<256;)t.lens[e++]=9;for(;e<280;)t.lens[e++]=7;for(;e<288;)t.lens[e++]=8;for(hf(df,t.lens,0,288,Sf,0,t.work,{bits:9}),e=0;e<32;)t.lens[e++]=5;hf(uf,t.lens,0,32,Cf,0,t.work,{bits:5}),Pf=!1}t.lencode=Sf,t.lenbits=9,t.distcode=Cf,t.distbits=5}function kf(t,e,i,r){var s,n=t.state;return null===n.window&&(n.wsize=1<=n.wsize?(Wp(n.window,e,i-n.wsize,n.wsize,0),n.wnext=0,n.whave=n.wsize):((s=n.wsize-n.wnext)>r&&(s=r),Wp(n.window,e,i-r,s,n.wnext),(r-=s)?(Wp(n.window,e,i-r,r,0),n.wnext=r,n.whave=n.wsize):(n.wnext+=s,n.wnext===n.wsize&&(n.wnext=0),n.whave>>8&255,i.check=Yp(i.check,I,2,0),l=0,h=0,i.mode=2;break}if(i.flags=0,i.head&&(i.head.done=!1),!(1&i.wrap)||(((255&l)<<8)+(l>>8))%31){t.msg="incorrect header check",i.mode=yf;break}if(8!=(15&l)){t.msg="unknown compression method",i.mode=yf;break}if(h-=4,A=8+(15&(l>>>=4)),0===i.wbits)i.wbits=A;else if(A>i.wbits){t.msg="invalid window size",i.mode=yf;break}i.dmax=1<>8&1),512&i.flags&&(I[0]=255&l,I[1]=l>>>8&255,i.check=Yp(i.check,I,2,0)),l=0,h=0,i.mode=3;case 3:for(;h<32;){if(0===a)break t;a--,l+=r[n++]<>>8&255,I[2]=l>>>16&255,I[3]=l>>>24&255,i.check=Yp(i.check,I,4,0)),l=0,h=0,i.mode=4;case 4:for(;h<16;){if(0===a)break t;a--,l+=r[n++]<>8),512&i.flags&&(I[0]=255&l,I[1]=l>>>8&255,i.check=Yp(i.check,I,2,0)),l=0,h=0,i.mode=5;case 5:if(1024&i.flags){for(;h<16;){if(0===a)break t;a--,l+=r[n++]<>>8&255,i.check=Yp(i.check,I,2,0)),l=0,h=0}else i.head&&(i.head.extra=null);i.mode=6;case 6:if(1024&i.flags&&((m=i.length)>a&&(m=a),m&&(i.head&&(A=i.head.extra_len-i.length,i.head.extra||(i.head.extra=new Array(i.head.extra_len)),Wp(i.head.extra,r,n,m,A)),512&i.flags&&(i.check=Yp(i.check,r,m,n)),a-=m,n+=m,i.length-=m),i.length))break t;i.length=0,i.mode=7;case 7:if(2048&i.flags){if(0===a)break t;m=0;do{A=r[n+m++],i.head&&A&&i.length<65536&&(i.head.name+=String.fromCharCode(A))}while(A&&m>9&1,i.head.done=!0),t.adler=i.check=0,i.mode=gf;break;case 10:for(;h<32;){if(0===a)break t;a--,l+=r[n++]<>>=7&h,h-=7&h,i.mode=27;break}for(;h<3;){if(0===a)break t;a--,l+=r[n++]<>>=1)){case 0:i.mode=14;break;case 1:if(If(i),i.mode=20,6===e){l>>>=2,h-=2;break t}break;case 2:i.mode=17;break;case 3:t.msg="invalid block type",i.mode=yf}l>>>=2,h-=2;break;case 14:for(l>>>=7&h,h-=7&h;h<32;){if(0===a)break t;a--,l+=r[n++]<>>16^65535)){t.msg="invalid stored block lengths",i.mode=yf;break}if(i.length=65535&l,l=0,h=0,i.mode=15,6===e)break t;case 15:i.mode=16;case 16:if(m=i.length){if(m>a&&(m=a),m>c&&(m=c),0===m)break t;Wp(s,r,n,m,o),a-=m,n+=m,c-=m,o+=m,i.length-=m;break}i.mode=gf;break;case 17:for(;h<14;){if(0===a)break t;a--,l+=r[n++]<>>=5,h-=5,i.ndist=1+(31&l),l>>>=5,h-=5,i.ncode=4+(15&l),l>>>=4,h-=4,i.nlen>286||i.ndist>30){t.msg="too many length or distance symbols",i.mode=yf;break}i.have=0,i.mode=18;case 18:for(;i.have>>=3,h-=3}for(;i.have<19;)i.lens[k[i.have++]]=0;if(i.lencode=i.lendyn,i.lenbits=7,S={bits:i.lenbits},_=hf(0,i.lens,0,19,i.lencode,0,i.work,S),i.lenbits=S.bits,_){t.msg="invalid code lengths set",i.mode=yf;break}i.have=0,i.mode=19;case 19:for(;i.have>>16&255,b=65535&P,!((g=P>>>24)<=h);){if(0===a)break t;a--,l+=r[n++]<>>=g,h-=g,i.lens[i.have++]=b;else{if(16===b){for(C=g+2;h>>=g,h-=g,0===i.have){t.msg="invalid bit length repeat",i.mode=yf;break}A=i.lens[i.have-1],m=3+(3&l),l>>>=2,h-=2}else if(17===b){for(C=g+3;h>>=g)),l>>>=3,h-=3}else{for(C=g+7;h>>=g)),l>>>=7,h-=7}if(i.have+m>i.nlen+i.ndist){t.msg="invalid bit length repeat",i.mode=yf;break}for(;m--;)i.lens[i.have++]=A}}if(i.mode===yf)break;if(0===i.lens[256]){t.msg="invalid code -- missing end-of-block",i.mode=yf;break}if(i.lenbits=9,S={bits:i.lenbits},_=hf(df,i.lens,0,i.nlen,i.lencode,0,i.work,S),i.lenbits=S.bits,_){t.msg="invalid literal/lengths set",i.mode=yf;break}if(i.distbits=6,i.distcode=i.distdyn,S={bits:i.distbits},_=hf(uf,i.lens,i.nlen,i.ndist,i.distcode,0,i.work,S),i.distbits=S.bits,_){t.msg="invalid distances set",i.mode=yf;break}if(i.mode=20,6===e)break t;case 20:i.mode=21;case 21:if(a>=6&&c>=258){t.next_out=o,t.avail_out=c,t.next_in=n,t.avail_in=a,i.hold=l,i.bits=h,Qp(t,u),o=t.next_out,s=t.output,c=t.avail_out,n=t.next_in,r=t.input,a=t.avail_in,l=i.hold,h=i.bits,i.mode===gf&&(i.back=-1);break}for(i.back=0;y=(P=i.lencode[l&(1<>>16&255,b=65535&P,!((g=P>>>24)<=h);){if(0===a)break t;a--,l+=r[n++]<>x)])>>>16&255,b=65535&P,!(x+(g=P>>>24)<=h);){if(0===a)break t;a--,l+=r[n++]<>>=x,h-=x,i.back+=x}if(l>>>=g,h-=g,i.back+=g,i.length=b,0===y){i.mode=26;break}if(32&y){i.back=-1,i.mode=gf;break}if(64&y){t.msg="invalid literal/length code",i.mode=yf;break}i.extra=15&y,i.mode=22;case 22:if(i.extra){for(C=i.extra;h>>=i.extra,h-=i.extra,i.back+=i.extra}i.was=i.length,i.mode=23;case 23:for(;y=(P=i.distcode[l&(1<>>16&255,b=65535&P,!((g=P>>>24)<=h);){if(0===a)break t;a--,l+=r[n++]<>x)])>>>16&255,b=65535&P,!(x+(g=P>>>24)<=h);){if(0===a)break t;a--,l+=r[n++]<>>=x,h-=x,i.back+=x}if(l>>>=g,h-=g,i.back+=g,64&y){t.msg="invalid distance code",i.mode=yf;break}i.offset=b,i.extra=15&y,i.mode=24;case 24:if(i.extra){for(C=i.extra;h>>=i.extra,h-=i.extra,i.back+=i.extra}if(i.offset>i.dmax){t.msg="invalid distance too far back",i.mode=yf;break}i.mode=25;case 25:if(0===c)break t;if(m=u-c,i.offset>m){if((m=i.offset-m)>i.whave&&i.sane){t.msg="invalid distance too far back",i.mode=yf;break}m>i.wnext?(m-=i.wnext,p=i.wsize-m):p=i.wnext-m,m>i.length&&(m=i.length),f=i.window}else f=s,p=o-i.offset,m=i.length;m>c&&(m=c),c-=m,i.length-=m;do{s[o++]=f[p++]}while(--m);0===i.length&&(i.mode=21);break;case 26:if(0===c)break t;s[o++]=i.length,c--,i.mode=21;break;case 27:if(i.wrap){for(;h<32;){if(0===a)break t;a--,l|=r[n++]<=252?6:Of>=248?5:Of>=240?4:Of>=224?3:Of>=192?2:1;function Rf(t){var e,i,r,s,n,o=t.length,a=0;for(s=0;s>>6,e[n++]=128|63&i):i<65536?(e[n++]=224|i>>>12,e[n++]=128|i>>>6&63,e[n++]=128|63&i):(e[n++]=240|i>>>18,e[n++]=128|i>>>12&63,e[n++]=128|i>>>6&63,e[n++]=128|63&i);return e}function Ef(t,e){var i,r,s,n,o=e||t.length,a=new Array(2*o);for(r=0,i=0;i4)a[r++]=65533,i+=n-1;else{for(s&=2===n?31:3===n?15:7;n>1&&i1?a[r++]=65533:s<65536?a[r++]=s:(s-=65536,a[r++]=55296|s>>10&1023,a[r++]=56320|1023&s)}return function(t,e){if(e<65537&&(t.subarray&&Df||!t.subarray&&Bf))return String.fromCharCode.apply(null,Hp(t,e));for(var i="",r=0;rt.length&&(e=t.length),i=e-1;i>=0&&128==(192&t[i]);)i--;return i<0||0===i?e:i+$f[t[i]]>e?i:e}$f[254]=$f[254]=1;var Lf=0,Nf={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"};function zf(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}function Vf(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}var Gf=Object.prototype.toString;function Uf(t){if(!(this instanceof Uf))return new Uf(t);this.options=function(t){for(var e=Array.prototype.slice.call(arguments,1);e.length;){var i=e.shift();if(i){if("object"!=typeof i)throw new TypeError(i+"must be non-object");for(var r in i)i.hasOwnProperty(r)&&(t[r]=i[r])}}return t}({chunkSize:16384,windowBits:0,to:""},t||{});var e=this.options;e.raw&&e.windowBits>=0&&e.windowBits<16&&(e.windowBits=-e.windowBits,0===e.windowBits&&(e.windowBits=-15)),!(e.windowBits>=0&&e.windowBits<16)||t&&t.windowBits||(e.windowBits+=32),e.windowBits>15&&e.windowBits<48&&0==(15&e.windowBits)&&(e.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new zf,this.strm.avail_out=0;var i,r,s,n=_f(this.strm,e.windowBits);if(n!==Lf)throw new Error(Nf[n]);this.header=new Vf,i=this.strm,r=this.header,i&&i.state&&(0==(2&(s=i.state).wrap)||(s.head=r,r.done=!1))}Uf.prototype.push=function(t,e){var i,r,s,n,o,a,c=this.strm,l=this.options.chunkSize,h=this.options.dictionary,d=!1;if(this.ended)return!1;r=e===~~e?e:!0===e?4:0,"string"==typeof t?c.input=function(t){for(var e=new Uint8Array(t.length),i=0,r=e.length;i0||0===c.avail_out)&&1!==i);return 1===i&&(r=4),4===r?(i=function(t){if(!t||!t.state)return pf;var e=t.state;return e.window&&(e.window=null),t.state=null,mf}(this.strm),this.onEnd(i),this.ended=!0,i===Lf):2!==r||(this.onEnd(Lf),c.avail_out=0,!0)},Uf.prototype.onData=function(t){this.chunks.push(t)},Uf.prototype.onEnd=function(t){t===Lf&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=function(t){var e,i,r,s,n,o;for(r=0,e=0,i=t.length;e({path:t,data:e.data})))}getUrl(t){const e=ri(t);return`${this.baseUrl}file/${e.path}${e.query}`}getCountUrl(t){const e=ri(t);return`${this.baseUrl}traj/numframes/${e.path}${e.query}`}getFrameUrl(t,e){const i=ri(t);return`${this.baseUrl}traj/frame/${e}/${i.path}${i.query}`}getFrameParams(t,e){return`atomIndices=${e.join(";")}`}getPathUrl(t,e){const i=ri(t);return`${this.baseUrl}traj/path/${e}/${i.path}${i.query}`}getExt(t){return ri(t).ext}}function ig(t,e){return{type:"integer",max:t,min:e}}function rg(t,e,i){return{type:"number",precision:t,max:e,min:i}}function sg(t,e,i){return{type:"range",step:t,max:e,min:i}}function ng(...t){return{type:"select",options:t.reduce(((t,e)=>Object.assign(Object.assign({},t),{[e]:e})),{})}}const og={backgroundColor:{type:"color"},quality:ng("auto","low","medium","high"),sampleLevel:sg(1,5,-1),impostor:{type:"boolean"},workerDefault:{type:"boolean"},rotateSpeed:rg(1,10,0),zoomSpeed:rg(1,10,0),panSpeed:rg(1,10,0),clipNear:sg(1,100,0),clipFar:sg(1,100,0),clipDist:ig(200,0),clipMode:ng("scene","camera"),clipScale:ng("relative","absolute"),fogNear:sg(1,100,0),fogFar:sg(1,100,0),cameraType:ng("perspective","orthographic","stereo"),cameraEyeSep:rg(3,1,.01),cameraFov:sg(1,120,15),lightColor:{type:"color"},lightIntensity:rg(2,10,0),ambientColor:{type:"color"},ambientIntensity:rg(2,10,0),hoverTimeout:ig(1e4,-1),tooltip:{type:"boolean"},mousePreset:ng(...Object.keys(Zo))};const ag="2.2.2";export{zh as AngleRepresentation,hu as ArrowBuffer,La as Assembly,ed as AxesRepresentation,rd as BackboneRepresentation,id as BallAndStickRepresentation,sd as BaseRepresentation,fu as BoxBuffer,Tc as BufferRepresentation,dd as CartoonRepresentation,hl as Collection,zt as Colormaker,Fe as ColormakerRegistry,ll as Component,$l as ComponentCollection,au as ConeBuffer,ud as ContactRepresentation,ui as Counter,td as CylinderBuffer,Le as DatasourceRegistry,De as Debug,Ge as DecompressorRegistry,gd as DihedralHistogramRepresentation,md as DihedralRepresentation,bd as DistanceRepresentation,wu as EllipsoidBuffer,pl as Frames,Ad as HelixorientRepresentation,Bd as HyperballRepresentation,$a as Kdtree,ta as KeyActions,$d as LabelRepresentation,tr as LeftMouseButton,_d as LicoriceRepresentation,Rd as LineRepresentation,We as ListingDatasource,eg as MdsrvDatasource,Te as MeasurementDefaultParams,Uo as MeshBuffer,er as MiddleMouseButton,zd as MolecularSurface,Vd as MolecularSurfaceRepresentation,Ko as MouseActions,Pu as OctahedronBuffer,ze as ParserRegistry,ai as PdbWriter,br as PickingProxy,Wc as PointBuffer,Gd as PointRepresentation,Nr as Queue,dl as RepresentationCollection,nl as RepresentationElement,Ne as RepresentationRegistry,Wd as RibbonRepresentation,ir as RightMouseButton,qd as RocketRepresentation,Xd as RopeRepresentation,Re as ScriptExtensions,ci as SdfWriter,pe as Selection,Mc as Shape,Ll as ShapeComponent,Yd as SpacefillRepresentation,Ts as SpatialHash,Gc as SphereBuffer,Fl as Stage,tg as StaticDatasource,di as StlWriter,Cc as Structure,Tl as StructureComponent,Ml as StructureComponentDefaultParameters,Sh as StructureRepresentation,fl as Superposition,Bl as SurfaceComponent,Bu as TetrahedronBuffer,Eh as TextBuffer,Fu as TorusBuffer,Qd as TraceRepresentation,qe as TrajectoryDatasource,yl as TrajectoryPlayer,Jd as TubeRepresentation,og as UIStageParameters,tu as UnitcellRepresentation,eu as ValidationRepresentation,ag as Version,Ji as Viewer,Eo as Volume,Dl as VolumeComponent,Nh as WidelineBuffer,ni as autoLoad,ic as concatStructures,dt as download,at as flatten,si as getDataInfo,ri as getFileInfo,rt as getQuery,tc as guessElement,Oe as setDebug,Xe as setListingDatasource,Be as setMeasurementDefaultParams,Ye as setTrajectoryDatasource,kl as superpose,ut as throttle,gt as uniqueArray}; + */class Ia{constructor(t,e){this.points=t,this.metric=e,this.maxDepth=0,this.currentNode=0;const i=t.length/3,r=new Uint32Array(i);for(let t=0;tthis.maxDepth&&(this.maxDepth=t);const n=r-i;if(0===n)return-1;const s=4*this.currentNode,o=this.nodes;if(this.currentNode+=1,1===n)return o[s]=i,o[s+1]=-1,o[s+2]=-1,o[s+3]=e,s;const a=this.indices,c=this.points,l=i+Math.floor(n/2),h=t%3;let u,d,m,f,p,g=i,y=r-1;for(;y>g;){for(m=g+y>>1,f=c[3*a[m]+h],d=a[m],a[m]=a[y],a[y]=d,p=g,u=g;u-t[1])),n=this.nodes,s=this.points,o=this.indices,a=c=>{let l,h;const u=this.getNodeDepth(c)%3,d=3*o[n[c]],m=[s[d+0],s[d+1],s[d+2]],f=this.metric(t,m);function p(t,i){r.push([t,i]),r.size()>e&&r.pop()}const g=n[c+1],y=n[c+2];if(-1===y&&-1===g)return void((r.size()s[3*o[n[t]]+r])throw new Error("left child is > parent!");i+=this.verify(a,e+1)}if(-1!==c){if(s[3*o[n[c]]+r]0}isBackbone(){const t=this.residueType.backboneIndexList;return t.length>0&&t.includes(this.index-this.residueAtomOffset)}isPolymer(){if(this.structure.entityList.length>0)return this.entity.isPolymer();{const t=this.residueType.moleculeType;return 3===t||4===t||5===t}}isSidechain(){return this.isPolymer()&&!this.isBackbone()}isCg(){const t=this.residueType.backboneType;return 4===t||5===t||6===t}isTrace(){return this.index===this.residueType.traceAtomIndex+this.residueAtomOffset}isHetero(){return 1===this.residueType.hetero}isProtein(){return 3===this.residueType.moleculeType}isNucleic(){const t=this.residueType.moleculeType;return 4===t||5===t}isRna(){return 4===this.residueType.moleculeType}isDna(){return 5===this.residueType.moleculeType}isWater(){return 1===this.residueType.moleculeType}isIon(){return 2===this.residueType.moleculeType}isSaccharide(){return 6===this.residueType.moleculeType}isHelix(){return Hn.includes(this.sstruc)}isSheet(){return qn.includes(this.sstruc)}isTurn(){return Wn.includes(this.sstruc)&&this.isProtein()}isBonded(){return 0!==this.bondHash.countArray[this.index]}isRing(){return void 0!==this.residueType.getRings().atomRings[this.index-this.residueAtomOffset]}isAromatic(){return 1===this.aromatic}isPolarHydrogen(){let t=!1;return 1!==this.number||(t=!this.hasBondToElement(6)),t}isMetal(){return this.atomType.isMetal()}isNonmetal(){return this.atomType.isNonmetal()}isMetalloid(){return this.atomType.isMetalloid()}isHalogen(){return this.atomType.isHalogen()}isDiatomicNonmetal(){return this.atomType.isDiatomicNonmetal()}isPolyatomicNonmetal(){return this.atomType.isPolyatomicNonmetal()}isAlkaliMetal(){return this.atomType.isAlkaliMetal()}isAlkalineEarthMetal(){return this.atomType.isAlkalineEarthMetal()}isNobleGas(){return this.atomType.isNobleGas()}isTransitionMetal(){return this.atomType.isTransitionMetal()}isPostTransitionMetal(){return this.atomType.isPostTransitionMetal()}isLanthanide(){return this.atomType.isLanthanide()}isActinide(){return this.atomType.isActinide()}getDefaultValence(){return this.atomType.getDefaultValence()}getValenceList(){return this.atomType.getValenceList()}getOuterShellElectronCount(){return this.atomType.getOuterShellElectronCount()}distanceTo(t){const e=this.atomStore,i=t.atomStore,r=this.index,n=t.index,s=e.x[r]-i.x[n],o=e.y[r]-i.y[n],a=e.z[r]-i.z[n],c=s*s+o*o+a*a;return Math.sqrt(c)}connectedTo(t){const e=this.atomStore,i=t.atomStore,r=this.index,n=t.index;if(e.altloc&&i.altloc){const t=e.altloc[r],s=i.altloc[n];if(0!==t&&0!==s&&32!==t&&32!==s&&t!==s)return!1}const s=e.x[r]-i.x[n],o=e.y[r]-i.y[n],a=e.z[r]-i.z[n],c=s*s+o*o+a*a;if(c<48&&this.isCg())return!0;if(isNaN(c))return!1;const l=this.covalent+t.covalent,h=l+.3,u=l-.5;return cu*u}positionFromArray(t,e=0){return this.x=t[e+0],this.y=t[e+1],this.z=t[e+2],this}positionToArray(t=[],e=0){const i=this.index,r=this.atomStore;return t[e+0]=r.x[i],t[e+1]=r.y[i],t[e+2]=r.z[i],t}positionToVector3(t){return void 0===t&&(t=new e),t.x=this.x,t.y=this.y,t.z=this.z,t}positionFromVector3(t){return this.x=t.x,this.y=t.y,this.z=t.z,this}positionAdd(t){return this.x+=t.x,this.y+=t.y,this.z+=t.z,this}positionSub(t){return this.x-=t.x,this.y-=t.y,this.z-=t.z,this}getResidueBonds(t=!1){const e=this.residueAtomOffset,i=this.index-this.residueAtomOffset,r=this.residueType.getBonds(),n=r.atomIndices1,s=r.atomIndices2;let o,a,c,l;for(t||(l=[]),o=n.indexOf(i);-1!==o;){if(c=s[o]+e,!l)return c;l.push(c),o=n.indexOf(i,o+1)}for(a=s.indexOf(i);-1!==a;){if(c=n[a]+e,!l)return c;l.push(c),a=s.indexOf(i,a+1)}return l}qualifiedName(t=!1){var e="";return this.resname&&!t&&(e+="["+this.resname+"]"),void 0!==this.resno&&(e+=this.resno),this.inscode&&(e+="^"+this.inscode),this.chainname&&(e+=":"+this.chainname),this.atomname&&(e+="."+this.atomname),this.altloc&&(e+="%"+this.altloc),this.structure.modelStore.count>1&&(e+="/"+this.modelIndex),e}clone(){return new ka(this.structure,this.index)}toObject(){return{index:this.index,residueIndex:this.residueIndex,resname:this.resname,x:this.x,y:this.y,z:this.z,element:this.element,chainname:this.chainname,resno:this.resno,serial:this.serial,vdw:this.vdw,covalent:this.covalent,hetero:this.hetero,bfactor:this.bfactor,altloc:this.altloc,atomname:this.atomname,modelIndex:this.modelIndex}}}function Ma(t,e){const i=t[0]-e[0],r=t[1]-e[1],n=t[2]-e[2];return i*i+r*r+n*n}function Ta(t,e){return Math.sqrt(Ma(t,e))}const Da=new Float32Array(3);class Ba{constructor(t,e=!1){De&&ke.time("Kdtree build");const i=e?Ma:Ta,r=new Float32Array(3*t.atomCount),n=new Uint32Array(t.atomCount);let s=0;t.eachAtom((function(t){r[s+0]=t.x,r[s+1]=t.y,r[s+2]=t.z,n[s/3]=t.index,s+=3})),this.atomIndices=n,this.points=r,this.kdtree=new Ia(r,i),De&&ke.timeEnd("Kdtree build")}nearest(t,i,r){t instanceof e?t.toArray(Da):t instanceof ka&&t.positionToArray(Da);const n=this.kdtree.nearest(Da,i,r),s=this.kdtree.indices,o=this.kdtree.nodes,a=this.atomIndices,c=[];for(let t=0,e=n.length;t":"3/4-Z","?":"X-Y","@":"Y-X",A:"Z+1/3",B:"Z+2/3",C:"X+2/3",D:"Y+1/3",E:"-Y+2/3",F:"X-Y+1/3",G:"Y-X+2/3",H:"-X+1/3",I:"X+1/3",J:"Y+2/3",K:"-Y+1/3",L:"X-Y+2/3",M:"Y-X+1/3",N:"-X+2/3",O:"2/3+X",P:"1/3+Y",Q:"1/3+Z",R:"2/3-Y",S:"1/3+X-Y",T:"2/3+Y-X",U:"1/3-X",V:"2/3-X",W:"1/3-Y",X:"1/3-Z",Y:"2/3+Y",Z:"1/3+Y-X","[":"2/3+X-Y","]":"1/3+X","^":"2/3+Z",_:"2/3-Z","`":"5/6+Z",a:"1/6+Z",b:"5/6-Z",c:"1/6-Z",d:"Z+5/6",e:"Z+1/6",f:"Z+1/4",g:"+Y"},Ea={"P 1":" !#","P -1":" !#$%&","P 1 2 1":" !#$!&","P 1 21 1":" !#$'&","C 1 2 1":" !#$!&()#*)&","P 1 m 1":" !# %#","P 1 c 1":" !# %+","C 1 m 1":" !# %#()#(,#","C 1 c 1":" !# %+()#(,+","P 1 2/m 1":" !# %#$!&$%&","P 1 21/m 1":" !#$)&$%& ,#","C 1 2/m 1":" !# %#$!&$%&()#(,#*)&*,&","P 1 2/c 1":" !#$!-$%& %+","P 1 21/c 1":" !#$%&$)- ,+","C 1 2/c 1":" !#$!-$%& %+()#*)-*,&(,+","P 2 2 2":" !#$%#$!& %&","P 2 2 21":" !#$%+$!- %&","P 21 21 2":" !#$%#*)&(,&","P 21 21 21":" !#*%+$)-(,&","C 2 2 21":" !#$%+$!- %&()#*,+*)-(,&","C 2 2 2":" !#$%#$!& %&()#*,#*)&(,&","F 2 2 2":" !#$%#$!& %& )+$,+$)- ,-(!+*%+*!-(%-()#*,#*)&(,&","I 2 2 2":" !#$%# %&$!&.'/01/.120'2","I 21 21 21":" !#*%+$)-(,&()+$,#*!& %-","P m m 2":" !#$%# %#$!#","P m c 21":" !#$%+ %+$!#","P c c 2":" !#$%# %+$!+","P m a 2":" !#$%#(%#*!#","P c a 21":" !#$%+(%#*!+","P n c 2":" !#$%# ,+$)+","P m n 21":" !#*%+(%+$!#","P b a 2":" !#$%#(,#*)#","P n a 21":" !#$%+(,#*)+","P n n 2":" !#$%#(,+*)+","C m m 2":" !#$%# %#$!#()#*,#(,#*)#","C m c 21":" !#$%+ %+$!#()#*,+(,+*)#","C c c 2":" !#$%# %+$!+()#*,#(,+*)+","A m m 2":" !#$%# %#$!# )+$,+ ,+$)+","A b m 2":" !#$%# ,#$)# )+$,+ %+$!+","A m a 2":" !#$%#(%#*!# )+$,+(,+*)+","A b a 2":" !#$%#(,#*)# )+$,+(%+*!+","F m m 2":" !#$%# %#$!# )+$,+ ,+$)+(!+*%+(%+*!+()#*,#(,#*)#","F d d 2":" !#$%#345675 )+$,+3896:9(!+*%+;49<79()#*,#;85<:5","I m m 2":" !#$%# %#$!#()+*,+(,+*)+","I b a 2":" !#$%#(,#*)#()+*,+ %+$!+","I m a 2":" !#$%#(%#*!#()+*,+ ,+$)+","P 2/m 2/m 2/m":" !#$%#$!& %&$%& !& %#$!#","P 2/n 2/n 2/n":" !#$%#$!& %&*,-()-(,+*)+","P 2/c 2/c 2/m":" !#$%#$!- %-$%& !& %+$!+","P 2/b 2/a 2/n":" !#$%#$!& %&*,&()&(,#*)#","P 21/m 2/m 2/a":" !#*%#$!&(%&$%&(!& %#*!#","P 2/n 21/n 2/a":" !#*%#*)- ,-$%&(!&(,+$)+","P 2/m 2/n 21/a":" !#*%+*!- %&$%&(!-(%+$!#","P 21/c 2/c 2/a":" !#*%#$!-(%-$%&(!& %+*!+","P 21/b 21/a 2/m":" !#$%#*)&(,&$%& !&(,#*)#","P 21/c 21/c 2/n":" !#*,#$)-(%-$%&()& ,+*!+","P 2/b 21/c 21/m":" !#$%+$)- ,&$%& !- ,+$)#","P 21/n 21/n 2/m":" !#$%#*)-(,-$%& !&(,+*)+","P 21/m 21/m 2/n":" !#$%#*'&.,&*,&.'& %#$!#","P 21/b 2/c 21/n":" !#*,+$!-(,&$%&()- %+*)#","P 21/b 21/c 21/a":" !#*%+$)-(,&$%&(!- ,+*)#","P 21/n 21/m 21/a":" !#0%/$'&.12$%&.!2 1#0'/","C 2/m 2/c 21/m":" !#$%+$!- %&$%& !- %+$!#()#*,+*)-(,&*,&()-(,+*)#","C 2/m 2/c 21/a":" !#$,+$)- %&$%& )- ,+$!#()#*%+*!-(,&*,&(!-(%+*)#","C 2/m 2/m 2/m":" !#$%#$!& %&$%& !& %#$!#()#*,#*)&(,&*,&()&(,#*)#","C 2/c 2/c 2/m":" !#$%#$!- %-$%& !& %+$!+()#*,#*)-(,-*,&()&(,+*)+","C 2/m 2/m 2/a":" !#$,#$)& %&$%& )& ,#$!#()#*%#*!&(,&*,&(!&(%#*)#","C 2/c 2/c 2/a":" !#*,#$!&(,&$,-(!- ,+*!+()#$%#*)& %&*%- )-(%+$)+","F 2/m 2/m 2/m":" !#$%#$!& %&$%& !& %#$!# )+$,+$)- ,-$,- )- ,+$)+(!+*%+*!-(%-*%-(!-(%+*!+()#*,#*)&(,&*,&()&(,#*)#","F 2/d 2/d 2/d":" !#$%#$!& %&64=37=345675 )+$,+$)- ,-68>3:>3896:9(!+*%+*!-(%-<4>;7>;49<79()#*,#*)&(,&<8=;:=;85<:5","I 2/m 2/m 2/m":" !#$%#$!& %&$%& !& %#$!#()+*,+*)-(,-*,-()-(,+*)+","I 2/b 2/a 2/m":" !#$%#*)&(,&$%& !&(,#*)#()+*,+$!- %-*,-()- %+$!+","I 21/b 21/c 21/a":" !#*%+$)-(,&$%&(!- ,+*)#()+$,#*!& %-*,- )&(%#$!+","I 21/m 21/m 21/a":" !#$,#$)& %&$%& )& ,#$!#()+*%+*!-(,-*,-(!-(%+*)+","P 4":" !#$%#% #!$#","P 41":" !#$%+% 5!$9","P 42":" !#$%#% +!$+","P 43":" !#$%+% 9!$5","I 4":" !#$%#% #!$#()+*,+,(+)*+","I 41":" !#*,+%(5)$9()+$%#, 9!*5","P -4":" !#$%#!$&% &","I -4":" !#$%#!$&% &()+*,+)*-,(-","P 4/m":" !#$%#% #!$#$%& !&!$&% &","P 42/m":" !#$%#% +!$+$%& !&!$-% -","P 4/n":" !#$%#,(#)*#*,&()&!$&% &","P 42/n":" !#$%#,(+)*+*,-()-!$&% &","I 4/m":" !#$%#% #!$#$%& !&!$&% &()+*,+,(+)*+*,-()-)*-,(-","I 41/a":" !#*,+%(5)$9$,=(!>!$&,(-()+$%#, 9!*5*%> )=)*-% &","P 4 2 2":" !#$%#% #!$#$!& %&! &%$&","P 4 21 2":" !#$%#,(#)*#*)&(,&! &%$&","P 41 2 2":" !#$%+% 5!$9$!& %-! >%$=","P 41 21 2":" !#$%+,(5)*9*)=(,>! &%$-","P 42 2 2":" !#$%#% +!$+$!& %&! -%$-","P 42 21 2":" !#$%#,(+)*+*)-(,-! &%$&","P 43 2 2":" !#$%+% 9!$5$!& %-! =%$>","P 43 21 2":" !#$%+,(9)*5*)>(,=! &%$-","I 4 2 2":" !#$%#% #!$#$!& %&! &%$&()+*,+,(+)*+*)-(,-)(-,*-","I 41 2 2":" !#*,+%(5)$9*!> ,=)(-%$&()+$%#, 9!*5$)=(%>! &,*-","P 4 m m":" !#$%#% #!$# %#$!#%$#! #","P 4 b m":" !#$%#% #!$#(,#*)#,*#)(#","P 42 c m":" !#$%#% +!$+ %+$!+%$#! #","P 42 n m":" !#$%#,(+)*+(,+*)+%$#! #","P 4 c c":" !#$%#% #!$# %+$!+%$+! +","P 4 n c":" !#$%#% #!$#(,+*)+,*+)(+","P 42 m c":" !#$%#% +!$+ %#$!#%$+! +","P 42 b c":" !#$%#% +!$+(,#*)#,*+)(+","I 4 m m":" !#$%#% #!$# %#$!#%$#! #()+*,+,(+)*+(,+*)+,*+)(+","I 4 c m":" !#$%#% #!$# %+$!+%$+! +()+*,+,(+)*+(,#*)#,*#)(#","I 41 m d":" !#*,+%(5)$9 %#*)+%*5) 9()+$%#, 9!*5(,+$!#,$9!(5","I 41 c d":" !#*,+%(5)$9 %+*)#%*9) 5()+$%#, 9!*5(,#$!+,$5!(9","P -4 2 m":" !#$%#% &!$&$!& %&%$#! #","P -4 2 c":" !#$%#% &!$&$!- %-%$+! +","P -4 21 m":" !#$%#% &!$&*)&(,&,*#)(#","P -4 21 c":" !#$%#% &!$&*)-(,-,*+)(+","P -4 m 2":" !#$%#!$&% & %#$!#! &%$&","P -4 c 2":" !#$%#% &!$& %+$!+! -%$-","P -4 b 2":" !#$%#% &!$&(,#*)#)(&,*&","P -4 n 2":" !#$%#% &!$&(,+*)+)(-,*-","I -4 m 2":" !#$%#% &!$& %#$!#! &%$&()+*,+,(-)*-(,+*)+)(-,*-","I -4 c 2":" !#$%#% &!$& %+$!+! -%$-()+*,+,(-)*-(,#*)#)(&,*&","I -4 2 m":" !#$%#% &!$&$!& %&%$#! #()+*,+,(-)*-*)-(,-,*+)(+","I -4 2 d":" !#$%#% &!$&*!>(%>,$9) 9()+*,+,(-)*-$)= ,=%*5!(5","P 4/m 2/m 2/m":" !#$%#% #!$#$!& %&! &%$&$%& !&!$&% & %#$!#%$#! #","P 4/m 2/c 2/c":" !#$%#% #!$#$!- %-! -%$-$%& !&!$&% & %+$!+%$+! +","P 4/n 2/b 2/m":" !#$%#% #!$#$!& %&! &%$&*,&()&)*&,(&(,#*)#,*#)(#","P 4/n 2/n 2/c":" !#$%#% #!$#$!& %&! &%$&*,-()-)*-,(-(,+*)+,*+)(+","P 4/m 21/b 2/m":" !#$%#% #!$#*)&(,&)(&,*&$%& !&!$&% &(,#*)#,*#)(#","P 4/m 21/n 2/c":" !#$%#% #!$#*)-(,-)(-,*-$%& !&!$&% &(,+*)+,*+)(+","P 4/n 21/m 2/m":" !#$%#,(#)*#*)&(,&! &%$&*,&()&!$&% & %#$!#,*#)(#","P 4/n 2/c 2/c":" !#$%#,(#)*#*)-(,-! -%$-*,&()&!$&% & %+$!+,*+)(+","P 42/m 2/m 2/c":" !#$%#% +!$+$!& %&! -%$-$%& !&!$-% - %#$!#%$+! +","P 42/m 2/c 2/m":" !#$%#% +!$+$!- %-! &%$&$%& !&!$-% - %+$!+%$#! #","P 42/n 2/b 2/c":" !#$%#,(+)*+$!- %-)(&,*&*,-()-!$&% &(,#*)#%$+! +","P 42/n 2/n 2/m":" !#$%#,(+)*+$!& %&)(-,*-*,-()-!$&% &(,+*)+%$#! #","P 42/m 21/b 2/c":" !#$%#% +!$+*)&(,&)(-,*-$%& !&!$-% -(,#*)#,*+)(+","P 42/m 21/n 2/m":" !#$%#,./'*/*'-.,-! &%$&$%& !&'*-,.-.,/*'/%$#! #","P 42/n 21/m 2/c":" !#$%#,(+)*+*)-(,-! &%$&*,-()-!$&% & %#$!#,*+)(+","P 42/n 21/c 2/m":" !#$%#,(+)*+*)&(,&! -%$-*,-()-!$&% & %+$!+,*#)(#","I 4/m 2/m 2/m":" !#$%#% #!$#$!& %&! &%$&$%& !&!$&% & %#$!#%$#! #()+*,+,(+)*+*)-(,-)(-,*-*,-()-)*-,(-(,+*)+,*+)(+","I 4/m 2/c 2/m":" !#$%#% #!$#$!- %-! -%$-$%& !&!$&% & %+$!+%$+! +()+*,+,(+)*+*)&(,&)(&,*&*,-()-)*-,(-(,#*)#,*#)(#","I 41/a 2/m 2/d":" !#*,+%(5)$9*!> ,=)(-%$&$,=(!>!$&,(-(,+$!#,$9!(5()+$%#, 9!*5$)=(%>! &,*-*%> )=)*-% & %#*)+%*5) 9","I 41/a 2/c 2/d":" !#*,+%(5)$9*!= ,>)(&%$-$,=(!>!$&,(-(,#$!+,$5!(9()+$%#, 9!*5$)>(%=! -,*&*%> )=)*-% & %+*)#%*9) 5","P 3":" !#%?#@$#","P 31":" !#%?A@$B","P 32":" !#%?B@$A","H 3":" !#%?#@$#CDAEFAGHAIJBKLBMNB","R 3":" !## !!# ","P -3":" !#%?#@$#$%&!@&? &","H -3":" !#%?#@$#$%&!@&? &OPQRSQTUQVWXYZX[]X]Y^W[^ZV^UR_PT_SO_","R -3":" !## !!# $%&&$%%&$","P 3 1 2":" !#%?#@$#%$&@!& ?&","P 3 2 1":" !#%?#@$#! &?%&$@&","P 31 1 2":" !#%?Q@$^%$_@!X ?&","P 31 2 1":" !#%?A@$B! &?%_$@X","P 32 1 2":" !#%?^@$Q%$X@!_ ?&","P 32 2 1":" !#%?B@$A! &?%X$@_","H 3 2":" !#%?#@$#! &?%&$@&OPQRSQTUQY]X[WXVZX]Y^W[^ZV^PO_SR_UT_","R 3 2":" !## !!# %$&$&%&%$","P 3 m 1":" !#%?#@$#%$#@!# ?#","P 3 1 m":" !#%?#@$#! #?%#$@#","P 3 c 1":" !#%?#@$#%$+@!+ ?+","P 3 1 c":" !#%?#@$#! +?%+$@+","H 3 m":" !#%?#@$#%$#@!# ?#OPQRSQTUQRUQTPQOSQ]Y^W[^ZV^WV^ZY^][^","R 3 m":" !## !!# ! # #!#! ","H 3 c":" !#%?#@$#%$+@!+ ?+OPQRSQTUQRU`TP`OS`]Y^W[^ZV^WVaZYa][a","R 3 c":" !## !!# '././'/'.","P -3 1 2/m":" !#%?#@$#%$&@!& ?&$%&!@&? &! #?%#$@#","P -3 1 2/c":" !#%?#@$#%$-@!- ?-$%&!@&? &! +?%+$@+","P -3 2/m 1":" !#%?#@$#! &?%&$@&$%&!@&? &%$#@!# ?#","P -3 2/c 1":" !#%?#@$#! -?%-$@-$%&!@&? &%$+@!+ ?+","H -3 2/m":" !#%?#@$#! &?%&$@&$%&!@&? &%$#@!# ?#OPQRSQTUQY]X[WXVZXVWXYZX[]XRUQTPQOSQ]Y^W[^ZV^PO_SR_UT_UR_PT_SO_WV^ZY^][^","R -3 2/m":" !## !!# %$&$&%&%$$%&&$%%&$! # #!#! ","H -3 2/c":" !#%?#@$#! -?%-$@-$%&!@&? &%$+@!+ ?+OPQRSQTUQY]b[WbVZbVWXYZX[]XRU`TP`OS`]Y^W[^ZV^POcSRcUTcUR_PT_SO_WVaZYa][a","R -3 2/c":" !## !!# 102021210$%&&$%%&$'././'/'.","P 6":" !#%?#@$#$%#!@#? #","P 61":" !#%?A@$B$%/!@d? e","P 65":" !#%?B@$A$%/!@e? d","P 62":" !#%?^@$Q$%#!@^? Q","P 64":" !#%?Q@$^$%#!@Q? ^","P 63":" !#%?#@$#$%+!@+? +","P -6":" !#%?#@$# !&%?&@$&","P 6/m":" !#%?#@$#$%#!@#? #$%&!@&? & !&%?&@$&","P 63/m":" !#%?#@$#$%+!@+? +$%&!@&? & !-%?-@$-","P 6 2 2":" !#%?#@$#$%#!@#? #! &?%&$@&%$&@!& ?&","P 61 2 2":" !#%?Q@$^$%+!@`? a! X?%&$@_%$b@!- ?c","P 65 2 2":" !#%?^@$Q$%+!@a? `! _?%&$@X%$c@!- ?b","P 62 2 2":" !#%?^@$Q$%#!@^? Q! _?%&$@X%$_@!& ?X","P 64 2 2":" !#%?Q@$^$%#!@Q? ^! X?%&$@_%$X@!& ?_","P 63 2 2":" !#%?#@$#$%+!@+? +! &?%&$@&%$-@!- ?-","P 6 m m":" !#%?#@$#$%#!@#? #%$#@!# ?#! #?%#$@#","P 6 c c":" !#%?#@$#$%#!@#? #%$+@!+ ?+! +?%+$@+","P 63 c m":" !#%?#@$#$%+!@+? +%$+@!+ ?+! #?%#$@#","P 63 m c":" !#%?#@$#$%+!@+? +%$#@!# ?#! +?%+$@+","P -6 m 2":" !#%?#@$# !&%?&@$&%$#@!# ?#%$&@!& ?&","P -6 c 2":" !#%?#@$# !-%?-@$-%$+@!+ ?+%$&@!& ?&","P -6 2 m":" !#%?#@$# !&%?&@$&! &?%&$@&! #?%#$@#","P -6 2 c":" !#%?#@$# !-%?-@$-! &?%&$@&! +?%+$@+","P 6/m 2/m 2/m":" !#%?#@$#$%#!@#? #! &?%&$@&%$&@!& ?&$%&!@&? & !&@$&%?&%$#@!# ?#! #?%#$@#","P 6/m 2/c 2/c":" !#%?#@$#$%#!@#? #! -?%-$@-%$-@!- ?-$%&!@&? & !&@$&%?&%$+@!+ ?+! +?%+$@+","P 63/m 2/c 2/m":" !#%?#@$#$%+!@+? +! -?%-$@-%$&@!& ?&$%&!@&? & !-@$-%?-%$+@!+ ?+! #?%#$@#","P 63/m 2/m 2/c":" !#%?#@$#$%+!@+? +! &?%&$@&%$-@!- ?-$%&!@&? & !-@$-%?-%$#@!# ?#! +?%+$@+","P 2 3":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ","F 2 3":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-((!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- ","I 2 3":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-(","P 21 3":" !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(","I 21 3":" !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(()+$,#*!& %-+()#$,&*!- %)+(,#$!&*%- ","P 2/m -3":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& $%& !& %#$!#&$%& !# %#$!%&$!& %# !#$","P 2/n -3":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& *,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*","F 2/m -3":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& $%& !& %#$!#&$%& !# %#$!%&$!& %# !#$ )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-($,- )- ,+$)+&*,&()#(,#*)%-*!-(%+(!+*(!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(*%-(!-(%+*!+-$,- )+ ,+$),&*)&(,#()#*()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- *,&()&(,#*)#-*%-(!+(%+*!,-$)- ,+ )+$","F 2/d -3":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& 64=37=345675=64=375345674=67=3453756 )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-(68>3:>3896:9=<8=;:5;85<:4><7>;49;79<(!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(<4>;7>;49<79>68>3:93896:8=<:=;85;:5<()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- <8=;:=;8f<:f><4>;79;49<78>6:>3893:96","I 2/m -3":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& $%& !& %#$!#&$%& !# %#$!%&$!& %# !#$()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-(*,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*","P 21/a -3":" !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&($%&(!- ,+*)#&$%-(!+ ,#*)%&$!-(,+ )#*","I 21/a -3":" !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&($%&(!- ,+*)#&$%-(!+ ,#*)%&$!-(,+ )#*()+$,#*g& %-+()#$,&*!- %)+(,#$!&*%- *,- )&(%#$!+-*,& )#(%+$!,-*)& %#(!+$","P 4 3 2":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$","P 42 3 2":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,*","F 4 3 2":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$ )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-(!(-%*-!*+%(+ +,$+)$-, -)#)*#,(&)(&,*(!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&() -,$-)$+, +(#,*#)*&,(&)+!*+%(-!(-%*()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- )(&,*&)*#,(#(+%*+!*-%(-!+)$+, -) -,$","F 41 3 2":" !#$,+*)&(%-# !+$,&*)-(%!# ,+$)&*%-(:3>46=7<98;5;58<976=43>:97<58;>:3=46 )+$%#*!-(,&#()+*%&$!- ,!+(,#*)-$%& :;=4<>765839;94<5:6>83=79:6543>7;=8<(!+*,#$)- %&+ )#$%-*!&(,)#(%+*!&$,- 73=86>:<54;935469:<=8;>7576983=:;>4<()#*%+$!& ,-+(!#*,-$)& %)+ %#$!-*,&(7;>8<=:69435398657<>4;=:5:<94;=73>86","I 4 3 2":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-()(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,*","P 43 3 2":" !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(7;>46=:<5839398<5:6=4;>75:<983>7;=46","P 41 3 2":" !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(:3=8<>7694;5;54697<>83=:97654;=:3>8<","I 41 3 2":" !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(:3=8<>7694;5;54697<>83=:97654;=:3>8<()+$,#*!& %-+()#$,&*!- %)+(,#$!&*%- 7;>46=:<5839398<5:6=4;>75:<983>7;=46","P -4 3 m":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! #%$#!$&% & #!$#%$&! &%#! #%$&!$&% ","F -4 3 m":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! #%$#!$&% & #!$#%$&! &%#! #%$&!$&% )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-(!(+%*+!*-%(- +)$+,$-) -,#)(#,*&)*&,((!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&() +,$+)$-, -(#)*#,*&)(&,+!(+%*-!*-%(()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- )(#,*#)*&,(&(+!*+%*-!(-%+) +,$-)$-, ","I -4 3 m":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! #%$#!$&% & #!$#%$&! &%#! #%$&!$&% ()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-()(+,*+)*-,(-(+)*+,*-)(-,+)(+,*-)*-,(","P -4 3 n":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(+,*+)*-,(-(+)*+,*-)(-,+)(+,*-)*-,(","F -4 3 c":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(+,*+)*-,(-(+)*+,*-)(-,+)(+,*-)*-,( )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-() #,$#)$&, &(#!*#%*&!(&%+! +%$-!$-% (!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(!(#%*#!*&%(& +!$+%$-! -%#) #,$&)$&, ()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- ! +%$+!$-% - #)$#,$&) &,#!(#%*&!*&%(","I -4 3 d":" !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(7354<9:6>8;=357<946>:;=857394<>:6=8;()+$,#*!& %-+()#$,&*!- %)+(,#$!&*%- :;98657<=43>;9:658<=73>49:;586=7<>43","P 4/m -3 2/m":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$%$#! #% &!$&$&! &% #!$#%&% &!$#%$#! ","P 4/n -3 2/n":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$*,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*,*+)(+,(-)*-*-)(-,(+)*+,-,(-)*+,*+)(","P 42/m -3 2/n":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,*$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$,*+)(+,(-)*-*-)(-,(+)*+,-,(-)*+,*+)(","P 42/n -3 2/m":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,**,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*%$#! #% &!$&$&! &% #!$#%&% &!$#%$#! ","F 4/m -3 2/m":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$%$#! #% &!$&$&! &% #!$#%&% &!$#%$#! )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-(!(-%*-!*+%(+ +,$+)$-, -)#)*#,(&)(&,*$,- )- ,+$)+&*,&()#(,#*)%-*!-(%+(!+*%*+!(+%(-!*-$-) -, +)$+,&,(&)*#,*#)((!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&() -,$-)$+, +(#,*#)*&,(&)+!*+%(-!(-%**%-(!-(%+*!+-$,- )+ ,+$),&*)&(,#()#*,$+) +, -)$-*&)(&,(#)*#,-%(-!*+%*+!(()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- )(&,*&)*#,(#(+%*+!*-%(-!+)$+, -) -,$*,&()&(,#*)#-*%-(!+(%+*!,-$)- ,+ )+$,*#)(#,(&)*&*-!(-%(+!*+%-, -)$+,$+) ","F 4/m -3 2/c":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,*$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$,*+)(+,(-)*-*-)(-,(+)*+,-,(-)*+,*+)( )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-() &,$&)$#, #(#%*#!*&%(&!+!$+% -! -%$$,- )- ,+$)+&*,&()#(,#*)%-*!-(%+(!+*,$#) #, &)$&*&!(&%(#!*#%-% -!$+%$+! (!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(!(&%*&!*#%(# +%$+!$-% -!#)$#, &) &,$*%-(!-(%+*!+-$,- )+ ,+$),&*)&(,#()#*%*#!(#%(&!*&$-! -% +!$+%&, &)$#,$#) ()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- ! -%$-!$+% + #,$#)$&, &)#!*#%(&!(&%**,&()&(,#*)#-*%-(!+(%+*!,-$)- ,+ )+$%$+! +% -!$-$&) &, #)$#,&%(&!*#%*#!(","F 41/d -3 2/m":" !#$,+*)&(%-# !+$,&*)-(%!# ,+$)&*%-(:3>46=7<98;5;58<976=43>:97<58;>:3=4664=3:>;85<79=64>3:5;89<74=6:>385;79<,$+! #%(-)*&*&)(-% #!$+,-%(&)*+,$#! )+$%#*!-(,&#()+*%&$!- ,!+(,#*)-$%& :;=4<>765839;94<5:6>83=79:6543>7;=8<68>37=;49<:5=<8>;753496:4><:=;893756,*#!(+% &)$-*-!(&, +)$#%-, &!$+%*#)((!+*,#$)- %&+ )#$%-*!&(,)#(%+*!&$,- 73=86>:<54;935469:<=8;>7576983=:;>4<<4>;:=389675>68=379;45<:8=<7>;453:96%$#) +,(&!*-$&! -,(#)*+%&% -)$#,*+!(()#*%+$!& ,-+(!#*,-$)& %)+ %#$!-*,&(7;>8<=:69435398657<>4;=:5:<94;=73>86<8=;7>3456:9><4=;:9385678>67=349;:5<%*+)(#, -!$&$-) &%(+!*#,&,(-!*#%$+) ","F 41/d -3 2/c":" !#$,+*)&(%-# !+$,&*)-(%!# ,+$)&*%-(:3>46=7<98;5;58<976=43>:97<58;>:3=46<8>;7=3496:5><8=;793456:8><7=;493:56%*#)(+, &!$-$-! &,(+)*#%&, -!$#%*+)( )+$%#*!-(,&#()+*%&$!- ,!+(,#*)-$%& :;=4<>765839;94<5:6>83=79:6543>7;=8<<4=;:>385679>64=3:9;85<78=67>345;:9<%$+) #,(-!*&$&) -%(#!*+,&%(-)*#,$+! (!+*,#$)- %&+ )#$%-*!&(,)#(%+*!&$,- 73=86>:<54;935469:<=8;>7576983=:;>4<68=37>;45<:9=<4>;:5389674>6:=389;75<,*+!(#% -)$&*-)(&% +!$#,-,(&!*+%$#) ()#*%+$!& ,-+(!#*,-$)& %)+ %#$!-*,&(7;>8<=:69435398657<>4;=:5:<94;=73>8664>3:=;89<75=68>375;49<:4=<:>;853796,$#! +%(&)*-*&!(-, #)$+%-% &)$+,*#!(","I 4/m -3 2/m":" !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$%$#! #% &!$&$&! &% #!$#%&% &!$#%$#! ()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-()(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,**,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*,*+)(+,(-)*-*-)(-,(+)*+,-,(-)*+,*+)(","I 41/a -3 2/d":" !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(:3=8<>7694;5;54697<>83=:97654;=:3>8<$%&(!- ,+*)#&$%-(!+ ,#*)%&$!-(,+ )#*4<97358;=:6>6>:;=8357<94=8;>:694<573()+$,#*!& %-+()#$,&*!- %)+(,#$!&*%- 7;>46=:<5839398<5:6=4;>75:<983>7;=46*,- )&(%#$!+-*,& )#(%+$!,-*)& %#(!+$865:;943>7<=<=73>4;9:658>43=7<5869:;","P 1 1 2":" !#$%#","P 1 1 21":" !#$%+","B 1 1 2":" !#$%#(g+*%+","A 1 2 1":" !#$!& )+$)-","C 1 21 1":" !#$)&()#*!&","I 1 2 1":" !#$!&.'/0'2","I 1 21 1":" !#$)&.'/0!-","P 1 1 m":" !# !&","P 1 1 b":" !# )&","B 1 1 m":" !# !&(!+(!-","B 1 1 b":" !# )&(!+()-","P 1 1 2/m":" !# !&$%#$%&","P 1 1 21/m":" !#$%+$%& !-","B 1 1 2/m":" !# !&$%#$%&(!+(!-*%+*%-","P 1 1 2/b":" !#$,#$%& )&","P 1 1 21/b":" !#$%&$,+ )-","B 1 1 2/b":" !#$,#$%& )&(!+*,+*%-()-","P 21 2 2":" !#$!&(%&*%#","P 2 21 2":" !# ,&$)&$%#","P 21 21 2 (a)":" !#*,#.%&$'&","P 21 2 21":" !#$!&(%-*%+","P 2 21 21":" !# %&$)-$,+","C 2 2 21a)":" !#*%+(,&$)-()#$,+ %&*!-","C 2 2 2a":" !#*,#.%&$'&()#$%# ,&*!&","F 2 2 2a":" !#*,#.%&$'& '/*%/.12$!2.!/$,/ %20'2.'#$%# 1&0!&","I 2 2 2a":" !#*,#.%&$'&()+$%+*!- ,-","P 21/m 21/m 2/n a":" !#*,#$)&(%&$%&.'& ,#*!#","P 42 21 2a":" !#*,#%.+'$+$'&.%&! -,*-","I 2 3a":" !#*,#.%&$'&!# ,- '&$%/$# !-*!/$%&.%()+$%+ ,-*!-)+(%&(!-*,#*+()&$)#*,- ,"},$a=/^[1-9]$/;function Oa(t){let e="";return t.length>0&&(e=":"+pt(t).join(" OR :")),new me(e)}class Ra{constructor(t=""){this.name=t,this.partList=[]}get type(){return"Assembly"}addPart(t,e){const i=new La(t,e);return this.partList.push(i),i}getAtomCount(t){return this.partList.reduce(((e,i)=>e+i.getAtomCount(t)),0)}getResidueCount(t){return this.partList.reduce(((e,i)=>e+i.getResidueCount(t)),0)}getInstanceCount(){let t=0;return this.partList.forEach((function(e){t+=e.matrixList.length})),t}isIdentity(t){if(1!==this.partList.length)return!1;const e=this.partList[0];if(1!==e.matrixList.length)return!1;if(!(new i).equals(e.matrixList[0]))return!1;let r=[];return t.eachChain((function(t){r.push(t.chainname)})),r=pt(r),e.chainList.length===r.length}getBoundingBox(t){const e=new a;return this.partList.forEach((function(i){const r=i.getBoundingBox(t);e.expandByPoint(r.min),e.expandByPoint(r.max)})),e}getCenter(t){return this.getBoundingBox(t).getCenter(new e)}getSelection(){let t=[];return this.partList.forEach((function(e){t=t.concat(e.chainList)})),Oa(t)}}class La{constructor(t=[],e=[]){this.matrixList=t,this.chainList=e}get type(){return"AssemblyPart"}_getCount(t,e){let i=0;return t.eachChain((t=>{(0===this.chainList.length||this.chainList.includes(t.chainname))&&(i+=t[e])})),this.matrixList.length*i}getAtomCount(t){return this._getCount(t,"atomCount")}getResidueCount(t){return this._getCount(t,"residueCount")}getBoundingBox(t){const e=new a,i=new a,r=this.getSelection(),n=t.getBoundingBox(r);return this.matrixList.forEach((function(t){i.copy(n).applyMatrix4(t),e.expandByPoint(i.min),e.expandByPoint(i.max)})),e}getSelection(){return Oa(this.chainList)}getView(t){const e=this.getSelection();return e?t.getView(e):t}getInstanceList(){const t=[];for(let e=0,i=this.matrixList.length;e0&&this.addResidueType(this.ri-1),l.growIfFull(),l.resno[this.ri]=n,void 0!==o&&(l.sstruc[this.ri]=o.charCodeAt(0)),void 0!==a&&(l.inscode[this.ri]=a.charCodeAt(0)),l.atomOffset[this.ri]=this.ai,l.atomCount[this.ri]=0,l.count+=1,l.chainIndex[this.ri]=this.ci,h.residueCount[this.ci]+=1),c.count+=1,c.residueIndex[this.ai]=this.ri,l.atomCount[this.ri]+=1,this.currentModelindex=t,this.currentChainid=i,this.currentResname=r,this.currentResno=n,this.currentInscode=a,this.currentHetero=s}finalize(){this.previousResname=this.currentResname,this.previousHetero=this.currentHetero,this.ri>-1&&this.addResidueType(this.ri)}}function za(t,e){if(!e)return;De&&ke.time("assignSecondaryStructure");const i=[];t.eachModel((function(t){t.eachChain((function(t){i.push(t.chainname)}))}));const r=i.slice().sort(),n=[];r.forEach((function(t){n.push(i.indexOf(t))}));const s=e.helices.filter((function(t){return mt(r,t[0])>=0}));s.sort((function(t,e){const i=t[0],s=e[0],o=t[1],a=e[1];if(i===s)return o===a?0:o=0}));a.sort((function(t,e){const i=t[0],s=e[0];if(i===s)return 0;const o=mt(r,i),a=mt(r,s);return n[o]=t.residueCount)continue;o.index=s+n,a.index=s+n+e,c.index=o.traceAtomIndex,l.index=a.traceAtomIndex;const h=c.distanceTo(l);if(Math.abs(h-i[e-2])>r)return!1}return!0},i=function(e,i){return t(e,i,[5.45,5.18,6.37],2.1)},r=function(e,i){return t(e,i,[6.1,10.4,13],1.42)};return function(t){De&&ke.time("calculateSecondaryStructure"),t.eachPolymer((function(t){if(t.residueCount<4)return;if(t.isCg())!function(t){const i=t.residueStore,r=t.residueIndexStart,n=new Ca(t).position,s=new e,o=new e;for(let e=0,a=t.residueCount;e1&&n.bending[e]<20&&(i.sstruc[r+e]="h".charCodeAt(0),i.sstruc[r+e+1]="h".charCodeAt(0))}}(t);else{if(!t.isProtein())return;!function(t){const e=t.residueStore,n=t.residueIndexStart;for(let s=0,o=t.residueCount;s=e;)i=Math.floor(i/e),n+=Va[i%e],r+=1;return r>=5&&ke.warn("chainname overflow"),n}function Ga(t,e=!1){De&&ke.time("calculateChainnames");let i=!0;if(t.eachChain((function(t){t.chainname&&(i=!1)})),i){const i=t.modelStore,r=t.chainStore,n=t.residueStore,s=function(t,e,s,o){const a=r.count;for(let t=0;t{h.add(e),t.forEach((t=>{h.add(t)}))}))),t.eachResidue((function(t){if(!e&&l){const e=t.atomCount,n=t.atomOffset;if(e>500)return void ke.warn("more than 500 atoms, skip residue for auto-bonding",t.qualifiedName());if("auto"===i&&t.hetero)for(let e=t.atomOffset;e{d.forEach((i=>{e.push(t.clone().multiply(i))}))})),h.addPart(e)}else h.addPart(u);const m=new e,f=new Ra("SUPERCELL"),p=Array.prototype.concat.call(l(m.set(1,0,0)),l(m.set(0,1,0)),l(m.set(0,0,1)),l(m.set(-1,0,0)),l(m.set(0,-1,0)),l(m.set(0,0,-1)),l(m.set(1,1,0)),l(m.set(1,0,1)),l(m.set(0,1,1)),l(m.set(-1,-1,0)),l(m.set(-1,0,-1)),l(m.set(0,-1,-1)),l(m.set(1,-1,-1)),l(m.set(1,1,-1)),l(m.set(1,-1,1)),l(m.set(-1,1,1)),l(m.set(-1,-1,1)),l(m.set(-1,1,-1)),l(m.set(0,1,-1)),l(m.set(0,-1,1)),l(m.set(1,0,-1)),l(m.set(-1,0,1)),l(m.set(1,-1,0)),l(m.set(-1,1,0)),l(),l(m.set(1,1,1)),l(m.set(-1,-1,-1)));if(t.biomolDict.NCS){const t=[];p.forEach((function(e){d.forEach((function(i){t.push(e.clone().multiply(i))}))})),f.addPart(t)}else f.addPart(p);t.biomolDict.UNITCELL=h,t.biomolDict.SUPERCELL=f,De&&ke.timeEnd("buildUnitcellAssembly")}const Za=["H","C","O","N","S","P"],Qa=["NA","CL","FE"];function Ja(t){let e=t.toUpperCase(),i=0,r=0;for(let t=0;t0)break;++i}else r=t+1;(i>0||r=3&&-1!==Za.indexOf(e[0])?e[0]:""}function tc(t){const e=t.bondHash,i=e.countArray,r=e.offsetArray,n=e.indexArray,s=t.getBondProxy();t.eachResidue((function(t){const e=t.residueType;if(void 0!==e.bonds)return;var o=t.atomOffset,a=[],c=[],l=[],h={};const u=o+t.atomCount;t.eachAtom((function(t){const e=t.index,d=r[e];for(let t=0,r=i[e];t=u)continue;let i=s.atomIndex2;if(i=u)continue;if(e>i){const t=i;i=e,e=t}const r=e+"|"+i;void 0===h[r]&&(h[r]=!0,a.push(e-o),c.push(i-o),l.push(s.bondOrder))}})),e.bonds={atomIndices1:a,atomIndices2:c,bondOrders:l}}))}function ec(t,...e){De&&ke.time("concatStructures");const i=new Sc(t,""),r=new Na(i),n=i.atomStore,s=i.atomMap;n.addField("formalCharge",1,"int8"),n.addField("partialCharge",1,"float32");const o={};let a=0,c=0,l=0;e.forEach((t=>{t.eachAtom((t=>{n.growIfFull(),n.atomTypeId[a]=s.add(t.atomname,t.element),n.x[a]=t.x,n.y[a]=t.y,n.z[a]=t.z,n.serial[a]=t.serial,n.formalCharge[a]=t.formalCharge,n.partialCharge[a]=t.partialCharge,n.altloc[a]=t.altloc,n.occupancy[a]=t.occupancy,n.bfactor[a]=t.bfactor,r.addAtom(t.modelIndex+l,t.chainname,t.chainid,t.resname,t.resno,1===t.hetero,t.sstruc,t.inscode),o[t.index+c]=a,a+=1})),c+=t.atomStore.count,l+=t.modelStore.count}));const h=i.bondStore,u=i.getAtomProxy(),d=i.getAtomProxy();return c=0,e.forEach((t=>{t.eachBond((t=>{u.index=o[t.atomIndex1+c],d.index=o[t.atomIndex2+c],h.addBond(u,d,t.bondOrder)})),c+=t.atomStore.count})),r.finalize(),Ya(i,!0),Xa(i,!0),i.finalizeAtoms(),i.finalizeBonds(),tc(i),De&&ke.timeEnd("concatStructures"),i}const ic=[3,11,19,37,55,87],rc=[4,12,20,38,56,88],nc=[6,15,16,34],sc=[1,7,8,9,17,35,53],oc=[2,10,18,36,54,86],ac=[13,30,31,48,49,50,80,81,82,83,84,85,112],cc=[5,14,32,33,51,52,85],lc=[9,17,35,53,85];class hc{constructor(t,e,i){this.structure=t,this.atomname=e,i=i||Ja(e),this.element=i,this.number=Xn[i]||0,this.vdw=Yn[this.number]||2,this.covalent=Kn[this.number]||1.6}getDefaultValence(){const t=Zn[this.number];return t?t[0]:-1}getValenceList(){return Zn[this.number]||[]}getOuterShellElectronCount(){return Qn[this.number]||2}isMetal(){return this.isAlkaliMetal()||this.isAlkalineEarthMetal()||this.isLanthanide()||this.isActinide()||this.isTransitionMetal()||this.isPostTransitionMetal()}isNonmetal(){return this.isDiatomicNonmetal()||this.isPolyatomicNonmetal()||this.isNobleGas()}isMetalloid(){return cc.includes(this.number)}isHalogen(){return lc.includes(this.number)}isDiatomicNonmetal(){return sc.includes(this.number)}isPolyatomicNonmetal(){return nc.includes(this.number)}isAlkaliMetal(){return ic.includes(this.number)}isAlkalineEarthMetal(){return rc.includes(this.number)}isNobleGas(){return oc.includes(this.number)}isTransitionMetal(){const t=this.number;return t>=21&&t<=29||t>=39&&t<=47||t>=72&&t<=79||t>=104&&t<=108}isPostTransitionMetal(){return ac.includes(this.number)}isLanthanide(){return this.number>=57&&this.number<=71}isActinide(){return this.number>=89&&this.number<=103}}class uc{constructor(t){this.structure=t,this.dict={},this.list=[],this.structure=t}add(t,e){const i=function(t,e){return t+"|"+e}(t=t.toUpperCase(),e=e?e.toUpperCase():Ja(t));let r=this.dict[i];if(void 0===r){const n=new hc(this.structure,t,e);r=this.list.length,this.dict[i]=r,this.list.push(n)}return r}get(t){return this.list[t]}}class dc{constructor(t,e,i,r,n,s){this.structure=t,this.bondReferenceAtomIndices=[],this.resname=e,this.atomTypeIdList=i,this.hetero=r?1:0,this.chemCompType=n,this.bonds=s,this.atomCount=i.length,this.moleculeType=this.getMoleculeType(),this.backboneType=this.getBackboneType(0),this.backboneEndType=this.getBackboneType(-1),this.backboneStartType=this.getBackboneType(1),this.backboneIndexList=this.getBackboneIndexList();const o=ds[this.backboneType],a=ds[this.backboneStartType],c=ds[this.backboneEndType],l=this.getAtomIndexByName(o.trace);this.traceAtomIndex=rt(l,-1);const h=this.getAtomIndexByName(o.direction1);this.direction1AtomIndex=rt(h,-1);const u=this.getAtomIndexByName(o.direction2);this.direction2AtomIndex=rt(u,-1);const d=this.getAtomIndexByName(a.backboneStart);this.backboneStartAtomIndex=rt(d,-1);const m=this.getAtomIndexByName(c.backboneEnd);let f;this.backboneEndAtomIndex=rt(m,-1),f=ss.includes(e)?this.getAtomIndexByName("N1"):this.getAtomIndexByName("N3"),this.rungEndAtomIndex=rt(f,-1)}getBackboneIndexList(){const t=[];let e;switch(this.moleculeType){case 3:e=hs;break;case 4:case 5:e=us;break;default:return t}const i=this.structure.atomMap,r=this.atomTypeIdList;for(let n=0,s=this.atomCount;n500)De&&ke.warn("more than 500 atoms, skip residue for auto-bonding",t.qualifiedName());else if(n>50){const e=new Ba(t,!0),n=t.isCg()?1.2:2.3;for(let t=s;t=0||gc(t,e);this.rings={atomRings:t.atomRings,rings:t.rings}}isAromatic(t){return this.aromaticAtoms=this.getAromatic(t),1===this.aromaticAtoms[t.index-t.residueAtomOffset]}calculateAromatic(t){const e=this.aromaticAtoms=new Uint8Array(this.atomCount),i=this.getRings().rings,r=i.map((e=>function(t){if(t.some((t=>!mc.includes(t.number))))return!1;let e=0;const i=new lo(3,t.length),r=i.data;t.forEach((t=>{r[e+0]=t.x,r[e+1]=t.y,r[e+2]=t.z,e+=3}));return new ga(i).vecC.length()this.structure.getAtomProxy(e+t.atomOffset)))))),n=this.aromaticRings=[];i.forEach(((t,i)=>{r[i]&&(n.push(t),t.forEach((t=>e[t]=1)))}))}assignBondReferenceAtomIndices(){const t=this.getBondGraph(),e=this.getRings(),i=e.atomRings,r=e.rings,n=this.bonds,s=n.atomIndices1,o=n.atomIndices2,a=n.bondOrders,c=this.bondReferenceAtomIndices,l=n.atomIndices1.length;c.length=0;for(let e=0;e1)for(let i=0;i1)for(let i=0;i=0;t--)f[p++]=o[t];const g=t.rings.length;for(let e=0;e0?s[c]!==e&&s[e]!==c&&pc(t,e,c):(r[c]=1,n[a++]=c,s[c]=e)}}}const yc=4;class bc{constructor(t){this.structure=t,this.dict={},this.list=[]}add(t,e,i,r="",n){const s=function(t,e,i,r=""){return t+"|"+e.join(",")+"|"+(i?1:0)+"|"+r}(t=t.toUpperCase(),e,i,r);let o=this.dict[s];if(void 0===o){const a=new dc(this.structure,t,e,i,r,n);o=this.list.length,this.dict[s]=o,this.list.push(a)}return o}get(t){return this.list[t]}}class _c{constructor(t,i=0){this.structure=t,this.index=i,this.bondStore=t.bondStore,this._v12=new e,this._v13=new e,this._ap1=this.structure.getAtomProxy(),this._ap2=this.structure.getAtomProxy(),this._ap3=this.structure.getAtomProxy()}get atom1(){return this.structure.getAtomProxy(this.atomIndex1)}get atom2(){return this.structure.getAtomProxy(this.atomIndex2)}get atomIndex1(){return this.bondStore.atomIndex1[this.index]}set atomIndex1(t){this.bondStore.atomIndex1[this.index]=t}get atomIndex2(){return this.bondStore.atomIndex2[this.index]}set atomIndex2(t){this.bondStore.atomIndex2[this.index]=t}get bondOrder(){return this.bondStore.bondOrder[this.index]}set bondOrder(t){this.bondStore.bondOrder[this.index]=t}getOtherAtomIndex(t){return t===this.atomIndex1?this.atomIndex2:this.atomIndex1}getOtherAtom(t){return this.structure.getAtomProxy(this.getOtherAtomIndex(t.index))}getReferenceAtomIndex(){const t=this._ap1,e=this._ap2;if(t.index=this.atomIndex1,e.index=this.atomIndex2,t.residueIndex!==e.residueIndex)return;const i=t.index-t.residueAtomOffset,r=e.index-e.residueAtomOffset,n=t.residueType.getBondReferenceAtomIndex(i,r);if(void 0!==n)return n+t.residueAtomOffset;console.warn("No reference atom found",t.index,e.index)}calculateShiftDir(t=new e){const i=this._ap1,r=this._ap2,n=this._ap3,s=this._v12,o=this._v13;i.index=this.atomIndex1,r.index=this.atomIndex2;const a=this.getReferenceAtomIndex();s.subVectors(i,r).normalize(),void 0!==a?(n.index=a,o.subVectors(i,n)):o.copy(i),o.normalize();let c=s.dot(o);return 1-Math.abs(c)<1e-5&&(o.set(1,0,0),c=s.dot(o),1-Math.abs(c)<1e-5&&(o.set(0,1,0),c=s.dot(o))),t.copy(o.sub(s.multiplyScalar(c))).normalize()}qualifiedName(){return this.atomIndex1+"="+this.atomIndex2}clone(){return new _c(this.structure,this.index)}toObject(){return{atomIndex1:this.atomIndex1,atomIndex2:this.atomIndex2,bondOrder:this.bondOrder}}}class xc{constructor(t,e=0){this.structure=t,this.index=e,this.chainStore=t.chainStore,this.residueStore=t.residueStore,this.atomStore=t.atomStore,this.residueMap=t.residueMap,this.atomMap=t.atomMap}get entity(){return this.structure.entityList[this.entityIndex]}get entityIndex(){return this.chainStore.entityIndex[this.chainIndex]}get chain(){return this.structure.getChainProxy(this.chainIndex)}get chainIndex(){return this.residueStore.chainIndex[this.index]}set chainIndex(t){this.residueStore.chainIndex[this.index]=t}get atomOffset(){return this.residueStore.atomOffset[this.index]}set atomOffset(t){this.residueStore.atomOffset[this.index]=t}get atomCount(){return this.residueStore.atomCount[this.index]}set atomCount(t){this.residueStore.atomCount[this.index]=t}get atomEnd(){return this.atomOffset+this.atomCount-1}get modelIndex(){return this.chainStore.modelIndex[this.chainIndex]}get chainname(){return this.chainStore.getChainname(this.chainIndex)}get chainid(){return this.chainStore.getChainid(this.chainIndex)}get resno(){return this.residueStore.resno[this.index]}set resno(t){this.residueStore.resno[this.index]=t}get sstruc(){return this.residueStore.getSstruc(this.index)}set sstruc(t){this.residueStore.setSstruc(this.index,t)}get inscode(){return this.residueStore.getInscode(this.index)}set inscode(t){this.residueStore.setInscode(this.index,t)}get residueType(){return this.residueMap.get(this.residueStore.residueTypeId[this.index])}get resname(){return this.residueType.resname}get hetero(){return this.residueType.hetero}get moleculeType(){return this.residueType.moleculeType}get backboneType(){return this.residueType.backboneType}get backboneStartType(){return this.residueType.backboneStartType}get backboneEndType(){return this.residueType.backboneEndType}get traceAtomIndex(){return this.residueType.traceAtomIndex+this.atomOffset}get direction1AtomIndex(){return this.residueType.direction1AtomIndex+this.atomOffset}get direction2AtomIndex(){return this.residueType.direction2AtomIndex+this.atomOffset}get backboneStartAtomIndex(){return this.residueType.backboneStartAtomIndex+this.atomOffset}get backboneEndAtomIndex(){return this.residueType.backboneEndAtomIndex+this.atomOffset}get rungEndAtomIndex(){return this.residueType.rungEndAtomIndex+this.atomOffset}get x(){let t=0;for(let e=this.atomOffset;e<=this.atomEnd;++e)t+=this.atomStore.x[e];return t/this.atomCount}get y(){let t=0;for(let e=this.atomOffset;e<=this.atomEnd;++e)t+=this.atomStore.y[e];return t/this.atomCount}get z(){let t=0;for(let e=this.atomOffset;e<=this.atomEnd;++e)t+=this.atomStore.z[e];return t/this.atomCount}eachAtom(t,e){const i=this.atomCount,r=this.atomOffset,n=this.structure._ap,s=r+i;if(e&&e.atomOnlyTest){const i=e.atomOnlyTest;for(let e=r;e0)return this.entity.isPolymer();{const t=this.residueType.moleculeType;return 3===t||4===t||5===t}}isHetero(){return 1===this.residueType.hetero}isWater(){return 1===this.residueType.moleculeType}isIon(){return 2===this.residueType.moleculeType}isSaccharide(){return 6===this.residueType.moleculeType}isStandardAminoacid(){return this.residueType.isStandardAminoacid()}isStandardBase(){return this.residueType.isStandardBase()}isHelix(){return Hn.includes(this.sstruc)}isSheet(){return qn.includes(this.sstruc)}isTurn(){return Wn.includes(this.sstruc)&&this.isProtein()}getAtomType(t){return this.atomMap.get(this.atomStore.atomTypeId[t])}getResname1(){return es[this.resname.toUpperCase()]||"X"}getBackboneType(t){switch(t){case-1:return this.residueType.backboneStartType;case 1:return this.residueType.backboneEndType;default:return this.residueType.backboneType}}getAtomIndexByName(t){let e=this.residueType.getAtomIndexByName(t);return void 0!==e&&(e+=this.atomOffset),e}hasAtomWithName(t){return this.residueType.hasAtomWithName(t)}getAtomnameList(){console.warn("getAtomnameList - might be expensive");const t=this.atomCount,e=this.atomOffset,i=new Array(t);for(let r=0;r=e){const e=rt(t,this.structure.getResidueProxy());if(e.index=i,e.connectedTo(this))return e}else if(i===e-1){const i=this.chainStore.residueCount[this.chainIndex],r=rt(t,this.structure.getResidueProxy());if(r.index=e+i-1,r.connectedTo(this))return r}}getBonds(){return this.residueType.getBonds(this)}getRings(){return this.residueType.getRings()}getAromaticRings(){return this.residueType.getAromaticRings(this)}qualifiedName(t=!1){let e="";return this.resname&&!t&&(e+="["+this.resname+"]"),void 0!==this.resno&&(e+=this.resno),this.inscode&&(e+="^"+this.inscode),this.chain&&(e+=":"+this.chainname),e+="/"+this.modelIndex,e}clone(){return new xc(this.structure,this.index)}toObject(){return{index:this.index,chainIndex:this.chainIndex,atomOffset:this.atomOffset,atomCount:this.atomCount,resno:this.resno,resname:this.resname,sstruc:this.sstruc}}}class vc{constructor(t,e,i){this.structure=t,this.residueIndexStart=e,this.residueIndexEnd=i,this.chainStore=t.chainStore,this.residueStore=t.residueStore,this.atomStore=t.atomStore,this.residueCount=i-e+1;const r=this.structure.getResidueProxy(this.residueIndexStart),n=this.structure.getResidueProxy(this.residueIndexEnd);this.isPrevConnected=void 0!==r.getPreviousConnectedResidue();const s=n.getNextConnectedResidue();this.isNextConnected=void 0!==s,this.isNextNextConnected=void 0!==s&&void 0!==s.getNextConnectedResidue(),this.isCyclic=n.connectedTo(r),this.__residueProxy=this.structure.getResidueProxy()}get chainIndex(){return this.residueStore.chainIndex[this.residueIndexStart]}get modelIndex(){return this.chainStore.modelIndex[this.chainIndex]}get chainname(){return this.chainStore.getChainname(this.chainIndex)}isProtein(){return this.__residueProxy.index=this.residueIndexStart,this.__residueProxy.isProtein()}isCg(){return this.__residueProxy.index=this.residueIndexStart,this.__residueProxy.isCg()}isNucleic(){return this.__residueProxy.index=this.residueIndexStart,this.__residueProxy.isNucleic()}getMoleculeType(){return this.__residueProxy.index=this.residueIndexStart,this.__residueProxy.moleculeType}getBackboneType(t){return this.__residueProxy.index=this.residueIndexStart,this.__residueProxy.getBackboneType(t)}getAtomIndexByType(t,e){this.isCyclic?-1===t?t=this.residueCount-1:t===this.residueCount&&(t=0):(-1!==t||this.isPrevConnected||(t+=1),t!==this.residueCount||this.isNextNextConnected||(t-=1));const i=this.__residueProxy;let r;switch(i.index=this.residueIndexStart+t,e){case"trace":r=i.traceAtomIndex;break;case"direction1":r=i.direction1AtomIndex;break;case"direction2":r=i.direction2AtomIndex;break;default:r=i.getAtomIndexByName(e)}return r}eachAtom(t,e){this.eachResidue((function(i){i.eachAtom(t,e)}))}eachAtomN(t,e,i){const r=this.residueCount,n=new Array(t);for(let e=0;e1&&t(new vc(s,i,l.index)),i=r)):(o!==Nn&&l.index-i>1&&t(new vc(s,i,l.index)),i=r)}r-i>1&&this.structure.getResidueProxy(i).backboneEndType&&t(new vc(s,i,r))}qualifiedName(){return":"+this.chainname+"/"+this.modelIndex}clone(){return new wc(this.structure,this.index)}toObject(){return{index:this.index,residueOffset:this.residueOffset,residueCount:this.residueCount,chainname:this.chainname}}}class Ac{constructor(t,e=0){this.structure=t,this.index=e,this.modelStore=t.modelStore,this.chainStore=t.chainStore,this.residueStore=t.residueStore}get chainOffset(){return this.modelStore.chainOffset[this.index]}set chainOffset(t){this.modelStore.chainOffset[this.index]=t}get chainCount(){return this.modelStore.chainCount[this.index]}set chainCount(t){this.modelStore.chainCount[this.index]=t}get residueOffset(){return this.chainStore.residueOffset[this.chainOffset]}get atomOffset(){return this.residueStore.atomOffset[this.residueOffset]}get chainEnd(){return this.chainOffset+this.chainCount-1}get residueEnd(){return this.chainStore.residueOffset[this.chainEnd]+this.chainStore.residueCount[this.chainEnd]-1}get atomEnd(){return this.residueStore.atomOffset[this.residueEnd]+this.residueStore.atomCount[this.residueEnd]-1}get residueCount(){return 0===this.chainCount?0:this.residueEnd-this.residueOffset+1}get atomCount(){return 0===this.residueCount?0:this.atomEnd-this.atomOffset+1}eachAtom(t,e){this.eachChain((function(i){i.eachAtom(t,e)}),e)}eachResidue(t,e){this.eachChain((function(i){i.eachResidue(t,e)}),e)}eachPolymer(t,e){if(e&&e.chainOnlyTest){const i=e.chainOnlyTest;this.eachChain((function(r){i(r)&&r.eachPolymer(t,e)}))}else this.eachChain((function(i){i.eachPolymer(t,e)}))}eachChain(t,e){const i=this.chainCount,r=this.chainOffset,n=this.structure._cp,s=r+i;if(e&&e.test){const i=e.chainOnlyTest;if(i)for(let e=r;e{const i=3*e;a.index=t,l&&a.positionToArray(l,i),h&&s.atomColorToArray(a,h,i),u&&(u.array[e]=t),d&&(d[e]=n.atomRadius(a)),m&&(m[e]=t)})),o}getBondData(t){const i=Object.assign({},t);i.colorParams&&(i.colorParams.structure=this.getStructure());const r=i.what,n=rt(i.bondSet,this.bondSet),s=rt(i.multipleBond,"off"),o="off"!==s,a="offset"===s,c=rt(i.bondScale,.4),l=rt(i.bondSpacing,1);let h,u;const d={},m=this.getBondProxy();i.bondStore&&(m.bondStore=i.bondStore);const f=this.getAtomProxy(),p=this.getAtomProxy();let g;if(o){const t=m.bondStore.bondOrder;g=0,n.forEach((function(e){g+=t[e]}))}else g=n.getSize();r&&!r.position||(d.position1=new Float32Array(3*g),d.position2=new Float32Array(3*g)),r&&!r.color||!i.colorParams||(d.color=new Float32Array(3*g),d.color2=new Float32Array(3*g),u=Oe.getScheme(i.colorParams)),r&&!r.picking||(d.picking=new Ks(new Float32Array(g),this.getStructure(),i.bondStore)),(!r||r.radius||o&&r.position)&&(h=new ma(i.radiusParams)),r&&!r.radius||(d.radius=new Float32Array(g),i.radius2&&(d.radius2=new Float32Array(g)));const{position1:y,position2:b,color:_,color2:x,picking:v,radius:w,radius2:A}=d;let S,C,P,I,k,M,T=0;const D=new e,B=new e,F=new e;return n.forEach((t=>{if(C=3*T,m.index=t,f.index=m.atomIndex1,p.index=m.atomIndex2,I=m.bondOrder,y)if(o&&I>1){const t=h.atomRadius(f);M=t*c/(.5*I),m.calculateShiftDir(F),a?(k=2*l*t,F.multiplyScalar(k),F.negate(),B.subVectors(p,f).multiplyScalar(Math.max(.1,k/1.88)),f.positionToArray(y,C),p.positionToArray(b,C),I>=2&&(D.addVectors(f,F).add(B).toArray(y,C+3),D.addVectors(p,F).sub(B).toArray(b,C+3),I>=3&&(D.subVectors(f,F).add(B).toArray(y,C+6),D.subVectors(p,F).sub(B).toArray(b,C+6)))):(k=(l-c)*t,F.multiplyScalar(k),2===I?(D.addVectors(f,F).toArray(y,C),D.subVectors(f,F).toArray(y,C+3),D.addVectors(p,F).toArray(b,C),D.subVectors(p,F).toArray(b,C+3)):3===I?(f.positionToArray(y,C),D.addVectors(f,F).toArray(y,C+3),D.subVectors(f,F).toArray(y,C+6),p.positionToArray(b,C),D.addVectors(p,F).toArray(b,C+3),D.subVectors(p,F).toArray(b,C+6)):(f.positionToArray(y,C),p.positionToArray(b,C)))}else f.positionToArray(y,C),p.positionToArray(b,C);if(_&&x&&(u.bondColorToArray(m,1,_,C),u.bondColorToArray(m,0,x,C),o&&I>1))for(S=1;S1))for(S=1;S1))for(M=w[T]*c/(a?1:.5*I),S=a?1:0;S1))for(M=A[T]*c/(a?1:.5*I),S=a?1:0;S{const e=t.x,a=t.y,l=t.z;es&&(s=e),a>o&&(o=a),l>c&&(c=l)}),t),e.min.set(i,r,n),e.max.set(s,o,c),De&&ke.timeEnd("getBoundingBox"),e}getPrincipalAxes(t){De&&ke.time("getPrincipalAxes");let e=0;const i=new lo(3,this.atomCount),r=i.data;return this.eachAtom((t=>{r[e+0]=t.x,r[e+1]=t.y,r[e+2]=t.z,e+=3}),t),De&&ke.timeEnd("getPrincipalAxes"),new ga(i)}atomCenter(t){return t?this.getBoundingBox(t).getCenter(new e):this.center.clone()}hasCoords(){if(void 0===this._hasCoords){const t=this.atomStore;this._hasCoords=0!==Di(t.x)||0!==Ti(t.x)||0!==Di(t.y)||0!==Ti(t.y)||0!==Di(t.z)||0!==Ti(t.z)||t.count/this.modelStore.count==1}return this._hasCoords}getSequence(t){const e=[],i=this.getResidueProxy();return this.eachAtom((function(t){i.index=t.residueIndex,t.index===i.traceAtomIndex&&e.push(i.getResname1())}),t),e}getAtomIndices(t){if(t&&t.string){const e=[];return this.eachAtom((function(t){e.push(t.index)}),t),new Uint32Array(e)}{const t={what:{index:!0}};return this.getAtomData(t).index}}getChainnameCount(t){const e=new Set;return this.eachChain((function(t){t.residueCount&&e.add(t.chainname)}),t),e.size}updatePosition(t,e=!0){let i=0;this.eachAtom((function(e){e.positionFromArray(t,i),i+=3}),void 0),this._hasCoords=void 0,e&&this.refreshPosition()}refreshPosition(){this.getBoundingBox(void 0,this.boundingBox),this.boundingBox.getCenter(this.center),this.spatialHash=new Tn(this.atomStore,this.boundingBox),this.signals.refreshed.dispatch(this)}dispose(){this.frames&&(this.frames.length=0),this.boxes&&(this.boxes.length=0),this.bondStore.dispose(),this.backboneBondStore.dispose(),this.rungBondStore.dispose(),this.atomStore.dispose(),this.residueStore.dispose(),this.chainStore.dispose(),this.modelStore.dispose(),delete this.bondSet,delete this.atomSet}}const Cc=new a,Pc=[An,_n,Sn,wn,Cn,xn,bn,vn,In,Pn,kn,Mn],Ic={aspectRatio:1.5,sphereDetail:2,radialSegments:50,disableImpostor:!1,openEnded:!1,dashedCylinder:!1,labelParams:{},pointSize:2,sizeAttenuation:!1,useTexture:!0,linewidth:2};class kc{constructor(t="shape",e={}){this.boundingBox=new a,this.bufferList=[],this.meshCount=0,this._primitiveData={},this.name=t,this.parameters=nt(e,Ic),Pc.forEach((t=>{Object.keys(t.fields).forEach((e=>{this._primitiveData[t.getShapeKey(e)]=[]})),this._primitiveData[t.getShapeKey("name")]=[]}))}addBuffer(t){this.bufferList.push(t);const e=t.geometry;return e.boundingBox||e.computeBoundingBox(),this.boundingBox.union(e.boundingBox),this}addMesh(t,e,i,r,n){let s;t=St(t),e=St(e),Array.isArray(i)&&(i=bt(i,t.length)),r&&(r=St(r)),s=void 0===r||0==r.length?{position:t,color:e,index:i}:{position:t,color:e,index:i,normal:r};const o=new eo(this,Object.assign({serial:this.meshCount,name:n},s)),a=new Vo(Object.assign({picking:o},s));return this.bufferList.push(a),Cc.setFromArray(t),this.boundingBox.union(Cc),this.meshCount+=1,this}addSphere(t,e,i,r){return bn.objectToShape(this,{position:t,color:e,radius:i,name:r}),this}addEllipsoid(t,e,i,r,n,s){return Cn.objectToShape(this,{position:t,color:e,radius:i,majorAxis:r,minorAxis:n,name:s}),this}addTorus(t,e,i,r,n,s){return Pn.objectToShape(this,{position:t,color:e,radius:i,majorAxis:r,minorAxis:n,name:s}),this}addCylinder(t,e,i,r,n){return wn.objectToShape(this,{position1:t,position2:e,color:i,radius:r,name:n}),this}addCone(t,e,i,r,n){return Sn.objectToShape(this,{position1:t,position2:e,color:i,radius:r,name:n}),this}addArrow(t,e,i,r,n){return An.objectToShape(this,{position1:t,position2:e,color:i,radius:r,name:n}),this}addBox(t,e,i,r,n,s){return _n.objectToShape(this,{position:t,color:e,size:i,heightAxis:r,depthAxis:n,name:s}),this}addOctahedron(t,e,i,r,n,s){return xn.objectToShape(this,{position:t,color:e,size:i,heightAxis:r,depthAxis:n,name:s}),this}addTetrahedron(t,e,i,r,n,s){return vn.objectToShape(this,{position:t,color:e,size:i,heightAxis:r,depthAxis:n,name:s}),this}addText(t,e,i,r){return In.objectToShape(this,{position:t,color:e,size:i,text:r}),this}addPoint(t,e,i){return kn.objectToShape(this,{position:t,color:e,name:i}),this}addWideline(t,e,i,r,n){return this.parameters.linewidth=r,Mn.objectToShape(this,{position1:t,position2:e,color:i,name:n}),this}addLabel(t,e,i,r){return console.warn("Shape.addLabel is deprecated, use .addText instead"),this.addText(t,e,i,r)}getBufferList(){const t=[];return Pc.forEach((e=>{this._primitiveData[e.getShapeKey("color")].length&&t.push(e.bufferFromShape(this,this.parameters))})),this.bufferList.concat(t)}dispose(){this.bufferList.forEach((function(t){t.dispose()})),this.bufferList.length=0,Pc.forEach((t=>{Object.keys(t.fields).forEach((e=>{this._primitiveData[t.getShapeKey(e)].length=0})),this._primitiveData[t.getShapeKey("name")].length=0}))}get center(){return this._center||(this._center=this.boundingBox.getCenter(new e)),this._center}get type(){return"Shape"}}class Mc extends Nr{constructor(t,e,i){Array.isArray(t)||(t=[t]),super(t,e,i),this.type="buffer",this.parameters=Object.assign({},this.parameters,{colorScheme:null,colorScale:null,colorValue:null,colorDomain:null,colorMode:null}),this.buffer=t,this.init(i)}init(t){super.init(t),this.build()}create(){this.bufferList.push.apply(this.bufferList,this.buffer)}attach(t){this.bufferList.forEach((t=>{this.viewer.add(t),t.setParameters(this.getBufferParams())})),this.setVisibility(this.visible),t()}}const Tc=new i,Dc=new B;class Bc extends Vo{constructor(t,e={},i){super(function(t,e){const i=e.attributes.position.array,r=e.index?e.index.array:void 0,n=t.position.length/3,s=i.length/3,o=n*s,a=new Float32Array(3*o),c=new Float32Array(3*o),l=new Float32Array(3*o);let h;return r&&(h=bt(n*r.length,o)),{position:a,color:l,index:h,normal:c,primitiveId:t.primitiveId||Pi(n,s),picking:t.picking}}(t,i),e),this.updateNormals=!1;const r=i.attributes.position.array,n=i.attributes.normal.array,s=i.index?i.index.array:void 0;this.geoPosition=r,this.geoNormal=n,this.geoIndex=s,this.positionCount=t.position.length/3,this.geoPositionCount=r.length/3,this.transformedGeoPosition=new Float32Array(3*this.geoPositionCount),this.transformedGeoNormal=new Float32Array(3*this.geoPositionCount);const o=this.geometry.attributes;if(this.meshPosition=o.position.array,this.meshColor=o.color.array,this.meshNormal=o.normal.array,this.setAttributes(t),s){const t=this.geometry.getIndex();if(!t)return void ke.error("Index is null");this.meshIndex=t.array,this.makeIndex()}}setAttributes(t={},e=!1){const i=this.geometry.attributes;let r,n,s,o,a,c,l,h,u;const d=this.updateNormals;t.position&&(r=t.position,s=this.geoPosition,l=this.meshPosition,a=this.transformedGeoPosition,i.position.needsUpdate=!0,(d||e)&&(o=this.geoNormal,u=this.meshNormal,c=this.transformedGeoNormal,i.normal.needsUpdate=!0)),t.color&&(n=t.color,h=this.meshColor,i.color.needsUpdate=!0);const m=this.positionCount,f=this.geoPositionCount;for(let t=0;t 0.0 ){\ncameraPos = rayDirection * posT + rayOrigin;\ninterior = true;\nflag2 = true;\n}\n#else\nif( calcDepth( cameraPos ) <= 0.0 ){\ncameraPos = rayDirection * posT + rayOrigin;\ninterior = true;\n}\n#endif\ncameraNormal = normalize( cameraPos - cameraSpherePos );\ncameraNormal *= float(!interior) * 2.0 - 1.0;\nreturn !interior;\n}\nvoid main(void){\nbool flag = Impostor( cameraPos, cameraNormal );\n#ifdef NEAR_CLIP\nif( calcClip( cameraPos ) > 0.0 )\ndiscard;\n#endif\ngl_FragDepthEXT = calcDepth( cameraPos );\nif( !flag ){\n#ifdef NEAR_CLIP\nif( flag2 ){\ngl_FragDepthEXT = max( 0.0, calcDepth( vec3( - ( clipNear - 0.5 ) ) ) + ( 0.0000001 / vRadius ) );\n}else if( gl_FragDepthEXT >= 0.0 ){\ngl_FragDepthEXT = 0.0 + ( 0.0000001 / vRadius );\n}\n#else\nif( gl_FragDepthEXT >= 0.0 ){\ngl_FragDepthEXT = 0.0 + ( 0.0000001 / vRadius );\n}\n#endif\n}\nif (gl_FragDepthEXT < 0.0)\ndiscard;\nif (gl_FragDepthEXT > 1.0)\ndiscard;\n#ifdef PICKING\nif( opacity < 0.3 )\ndiscard;\ngl_FragColor = vec4( vPickingColor, objectId );\n#else\nvec3 vNormal = cameraNormal;\nvec3 vViewPosition = -cameraPos;\nvec4 diffuseColor = vec4( diffuse, opacity );\nReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\nvec3 totalEmissiveLight = emissive;\n#include color_fragment\n#include roughnessmap_fragment\n#include metalnessmap_fragment\n#include normal_fragment_begin\n#include lights_physical_fragment\n#include lights_fragment_begin\n#include lights_fragment_end\nvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveLight;\nif( interior ){\n#ifdef USE_INTERIOR_COLOR\noutgoingLight.xyz = interiorColor;\n#else\n#ifdef DIFFUSE_INTERIOR\noutgoingLight.xyz = vColor;\n#endif\n#endif\noutgoingLight.xyz *= 1.0 - interiorDarkening;\n}\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );\n#include premultiplied_alpha_fragment\n#include tonemapping_fragment\n#include colorspace_fragment\n#include fog_fragment\n#endif\n}");class Oc extends Uo{constructor(t,e,i={}){super(e,i),this.index=bt(this.indexSize,this.attributeSize),this.makeIndex(),this.initIndex(this.index),this.addAttributes({mapping:{type:t,value:null}}),this.setAttributes({primitiveId:Ci(this.size)})}get attributeSize(){return this.size*this.mappingSize}get indexSize(){return this.size*this.mappingIndicesSize}addAttributes(t){const e={};for(const i in t){const r=t[i];e[i]={type:r.type,value:null}}super.addAttributes(e)}getAttributeIndex(t){return 3*t*this.mappingSize}setAttributes(t){t&&!t.position&&t.position1&&t.position2&&(t.position=vi(t.position1,t.position2));const e=this.size,i=this.mappingSize,r=this.geometry.attributes;let n,s,o,a,c,l,h;for(const u in t)if("index"!==u&&"picking"!==u){s=t[u],n=r[u],o=n.itemSize,a=n.array;for(let t=0;t0&&this.parameters.alphaTest<=1&&(e.USE_ALPHATEST=1),e}setUniforms(t){t&&void 0!==t.edgeBleach&&(this.makeTexture(),t.map=this.tex),super.setUniforms(t)}dispose(){super.dispose(),this.tex&&this.tex.dispose()}}je.add("point",Hc);class qc extends Nr{constructor(t,e,i){super(t,e,i),this.type="dot",this.parameters=Object.assign({thresholdType:{type:"select",rebuild:!0,options:{value:"value",sigma:"sigma"}},thresholdMin:{type:"number",precision:3,max:1/0,min:-1/0,rebuild:!0},thresholdMax:{type:"number",precision:3,max:1/0,min:-1/0,rebuild:!0},thresholdOut:{type:"boolean",rebuild:!0},dotType:{type:"select",rebuild:!0,options:{"":"",sphere:"sphere",point:"point"}},radiusType:{type:"select",options:{"":"",value:"value","abs-value":"abs-value","value-min":"value-min",deviation:"deviation",size:"size"}},radius:{type:"number",precision:3,max:10,min:.001,property:"size"},scale:{type:"number",precision:3,max:10,min:.001},sphereDetail:!0,disableImpostor:!0,pointSize:{type:"number",precision:1,max:100,min:0,buffer:!0},sizeAttenuation:{type:"boolean",buffer:!0},sortParticles:{type:"boolean",rebuild:!0},useTexture:{type:"boolean",buffer:!0},alphaTest:{type:"range",step:.001,max:1,min:0,buffer:!0},forceTransparent:{type:"boolean",buffer:!0},edgeBleach:{type:"range",step:.001,max:1,min:0,buffer:!0}},this.parameters,{colorScheme:{type:"select",update:"color",options:{"":"",value:"value",uniform:"uniform",random:"random"}}}),t instanceof $o?(this.surface=void 0,this.volume=new ya(t)):(this.surface=t,this.volume=void 0),this.init(i)}init(t){var e=t||{};e.colorScheme=rt(e.colorScheme,"uniform"),e.colorValue=rt(e.colorValue,14540253),this.thresholdType=rt(e.thresholdType,"sigma"),this.thresholdMin=rt(e.thresholdMin,2),this.thresholdMax=rt(e.thresholdMax,1/0),this.thresholdOut=rt(e.thresholdOut,!1),this.dotType=rt(e.dotType,"point"),this.radius=rt(e.radius,.1),this.scale=rt(e.scale,1),this.pointSize=rt(e.pointSize,1),this.sizeAttenuation=rt(e.sizeAttenuation,!0),this.sortParticles=rt(e.sortParticles,!1),this.useTexture=rt(e.useTexture,!1),this.alphaTest=rt(e.alphaTest,.5),this.forceTransparent=rt(e.forceTransparent,!1),this.edgeBleach=rt(e.edgeBleach,0),super.init(e),this.build()}attach(t){this.bufferList.forEach((t=>{this.viewer.add(t)})),this.setVisibility(this.visible),t()}create(){var t={};if(this.volume){var e,i,r=this.volume;"sigma"===this.thresholdType?(e=r.getValueForSigma(this.thresholdMin),i=r.getValueForSigma(this.thresholdMax)):(e=this.thresholdMin,i=this.thresholdMax),r.setFilter(e,i,this.thresholdOut),Object.assign(t,{position:r.getDataPosition(),color:r.getDataColor(this.getColorParams())}),"sphere"===this.dotType&&Object.assign(t,{radius:r.getDataSize(this.radius,this.scale),picking:r.getDataPicking()})}else{var n=this.surface;Object.assign(t,{position:n.getPosition(),color:n.getColor(this.getColorParams())}),"sphere"===this.dotType&&Object.assign(t,{radius:n.getSize(this.radius,this.scale),picking:n.getPicking()})}"sphere"===this.dotType?this.dotBuffer=new Uc(t,this.getBufferParams({sphereDetail:this.sphereDetail,disableImpostor:this.disableImpostor,dullInterior:!1})):this.dotBuffer=new Hc(t,this.getBufferParams({pointSize:this.pointSize,sizeAttenuation:this.sizeAttenuation,sortParticles:this.sortParticles,useTexture:this.useTexture,alphaTest:this.alphaTest,forceTransparent:this.forceTransparent,edgeBleach:this.edgeBleach})),this.bufferList.push(this.dotBuffer)}update(t={}){if(0===this.bufferList.length)return;const e={};t.color&&(this.volume?Object.assign(e,{color:this.volume.getDataColor(this.getColorParams())}):Object.assign(e,{color:this.surface.getColor(this.getColorParams())})),"sphere"===this.dotType&&(t.radius||t.scale)&&(this.volume?Object.assign(e,{radius:this.volume.getDataSize(this.radius,this.scale)}):Object.assign(e,{radius:this.surface.getSize(this.radius,this.scale)})),this.dotBuffer.setAttributes(e)}setParameters(t,e={},i){return t&&void 0!==t.thresholdType&&this.volume instanceof $o&&("value"===this.thresholdType&&"sigma"===t.thresholdType?(this.thresholdMin=this.volume.getSigmaForValue(this.thresholdMin),this.thresholdMax=this.volume.getSigmaForValue(this.thresholdMax)):"sigma"===this.thresholdType&&"value"===t.thresholdType&&(this.thresholdMin=this.volume.getValueForSigma(this.thresholdMin),this.thresholdMax=this.volume.getValueForSigma(this.thresholdMax)),this.thresholdType=t.thresholdType),t&&void 0!==t.radiusType&&("radius"===t.radiusType?this.radius=.1:this.radius=parseFloat(t.radiusType),e.radius=!0,"sphere"!==this.dotType||Pe&&!this.disableImpostor||(i=!0)),t&&void 0!==t.radius&&(e.radius=!0,"sphere"!==this.dotType||Pe&&!this.disableImpostor||(i=!0)),t&&void 0!==t.scale&&(e.scale=!0,"sphere"!==this.dotType||Pe&&!this.disableImpostor||(i=!0)),super.setParameters(t,e,i),this}}ze.add("shader/Image.vert","uniform float clipRadius;\nuniform vec3 clipCenter;\nvarying vec2 vUv;\n#if defined( NEAR_CLIP ) || defined( RADIUS_CLIP ) || !defined( PICKING )\nvarying vec3 vViewPosition;\n#endif\n#if defined( RADIUS_CLIP )\nvarying vec3 vClipCenter;\n#endif\nvoid main() {\n#include begin_vertex\n#include project_vertex\nvUv = uv;\n#if defined( NEAR_CLIP ) || defined( RADIUS_CLIP ) || !defined( PICKING )\nvViewPosition = -mvPosition.xyz;\n#endif\n#if defined( RADIUS_CLIP )\nvClipCenter = -( modelViewMatrix * vec4( clipCenter, 1.0 ) ).xyz;\n#endif\n}"),ze.add("shader/Image.frag","uniform sampler2D map;\nuniform float opacity;\nuniform vec2 mapSize;\nuniform float clipNear;\nuniform float clipRadius;\nvarying vec2 vUv;\n#if defined( NEAR_CLIP ) || defined( RADIUS_CLIP ) || !defined( PICKING )\nvarying vec3 vViewPosition;\n#endif\n#if defined( RADIUS_CLIP )\nvarying vec3 vClipCenter;\n#endif\n#if defined( PICKING )\nuniform sampler2D pickingMap;\nuniform float objectId;\n#else\n#include fog_pars_fragment\n#endif\n#if defined( CUBIC_INTERPOLATION )\n#if defined( CATMULROM_FILTER ) || defined( MITCHELL_FILTER )\n#if defined( CATMULROM_FILTER )\nconst float B = 0.0;\nconst float C = 0.5;\n#elif defined( MITCHELL_FILTER )\nconst float B = 0.333;\nconst float C = 0.333;\n#endif\nfloat applyFilter( float x ){\nfloat f = x;\nif( f < 0.0 ){\nf = -f;\n}\nif( f < 1.0 ){\nreturn ( ( 12.0 - 9.0 * B - 6.0 * C ) * ( f * f * f ) +\n( -18.0 + 12.0 * B + 6.0 *C ) * ( f * f ) +\n( 6.0 - 2.0 * B ) ) / 6.0;\n}else if( f >= 1.0 && f < 2.0 ){\nreturn ( ( -B - 6.0 * C ) * ( f * f * f )\n+ ( 6.0 * B + 30.0 * C ) * ( f *f ) +\n( - ( 12.0 * B ) - 48.0 * C ) * f +\n8.0 * B + 24.0 * C ) / 6.0;\n}else{\nreturn 0.0;\n}\n}\n#elif defined( BSPLINE_FILTER )\nfloat applyFilter( float x ){\nfloat f = x;\nif( f < 0.0 ){\nf = -f;\n}\nif( f >= 0.0 && f <= 1.0 ){\nreturn ( 2.0 / 3.0 ) + ( 0.5 ) * ( f * f * f ) - ( f * f );\n}else if( f > 1.0 && f <= 2.0 ){\nreturn 1.0 / 6.0 * pow( ( 2.0 - f ), 3.0 );\n}\nreturn 1.0;\n}\n#else\nfloat applyFilter( float x ){\nreturn 1.0;\n}\n#endif\nvec4 biCubic( sampler2D tex, vec2 texCoord ){\nvec2 texelSize = 1.0 / mapSize;\ntexCoord -= texelSize / 2.0;\nvec4 nSum = vec4( 0.0 );\nfloat nDenom = 0.0;\nvec2 cell = fract( texCoord * mapSize );\nfor( float m = -1.0; m <= 2.0; ++m ){\nfor( float n = -1.0; n <= 2.0; ++n ){\nvec4 vecData = texture2D(\ntex, texCoord + texelSize * vec2( m, n )\n);\nfloat c = applyFilter( m - cell.x ) * applyFilter( -n + cell.y );\nnSum += vecData * c;\nnDenom += c;\n}\n}\nreturn nSum / nDenom;\n}\n#endif\nvoid main(){\n#include nearclip_fragment\n#include radiusclip_fragment\n#if defined( CUBIC_INTERPOLATION )\ngl_FragColor = biCubic( map, vUv );\n#else\ngl_FragColor = texture2D( map, vUv );\n#endif\n#if defined( PICKING )\nif( gl_FragColor.a < 0.3 )\ndiscard;\ngl_FragColor = vec4( texture2D( pickingMap, vUv ).xyz, objectId );\n#else\nif( gl_FragColor.a < 0.01 )\ndiscard;\ngl_FragColor.a *= opacity;\n#include fog_fragment\n#endif\n}");const Wc=new Uint16Array([0,1,2,1,3,2]),Xc=new Float32Array([0,1,0,0,1,1,1,0]),Yc=Object.assign({filter:"nearest",forceTransparent:!0},No),Kc=Object.assign({filter:{updateShader:!0,uniform:!0}},zo);class Zc extends Uo{constructor(e,i){super({position:e.position,index:Wc,picking:e.picking},i),this.parameterTypes=Kc,this.alwaysTransparent=!0,this.hasWireframe=!1,this.vertexShader="Image.vert",this.fragmentShader="Image.frag";const{imageData:r,width:n,height:s}=e,o=new V(r,n,s);o.flipY=!0,this.tex=o;const a=r.length,c=new Uint8Array(a);for(let t=0;t>16&255,c[t+1]=e>>8&255,c[t+2]=255&e}const l=new V(c,n,s);l.flipY=!0,l.minFilter=b,l.magFilter=b,this.pickingTex=l,this.addUniforms({map:{value:o},pickingMap:{value:l},mapSize:{value:new t(n,s)}}),this.geometry.setAttribute("uv",new M(Xc,2))}get defaultParameters(){return Yc}getDefines(t){const e=super.getDefines(t),i=this.parameters.filter;return i.startsWith("cubic")&&(e.CUBIC_INTERPOLATION=1,i.endsWith("bspline")?e.BSPLINE_FILTER=1:i.endsWith("catmulrom")?e.CATMULROM_FILTER=1:i.endsWith("mitchell")&&(e.MITCHELL_FILTER=1)),e}updateTexture(){const t=this.tex,e=this.parameters.filter;e.startsWith("cubic")?(t.minFilter=b,t.magFilter=b):"linear"===e?(t.minFilter=v,t.magFilter=v):(t.minFilter=b,t.magFilter=b),t.needsUpdate=!0,this.pickingTex.needsUpdate=!0}makeMaterial(){super.makeMaterial(),this.updateTexture();const t=this.material;t.uniforms.map.value=this.tex,t.blending=j,t.needsUpdate=!0;const e=this.wireframeMaterial;e.uniforms.map.value=this.tex,e.blending=j,e.needsUpdate=!0;const i=this.pickingMaterial;i.uniforms.map.value=this.tex,i.uniforms.pickingMap.value=this.pickingTex,i.blending=j,i.needsUpdate=!0}setUniforms(t){t&&void 0!==t.filter&&(this.updateTexture(),t.map=this.tex),super.setUniforms(t)}}class Qc{constructor(t,e){const i=e||{};this.dimension=rt(i.dimension,"x"),this.positionType=rt(i.positionType,"percent"),this.position=rt(i.position,30),this.thresholdType=rt(i.thresholdType,"sigma"),this.thresholdMin=rt(i.thresholdMin,-1/0),this.thresholdMax=rt(i.thresholdMax,1/0),this.normalize=rt(i.normalize,!1),this.volume=t}getPositionFromCoordinate(t){const i=this.dimension,r=this.volume,n=r.matrix,s=(new e).setFromMatrixPosition(n)[i],o=(new e).setFromMatrixScale(n)[i];let a;return a="x"===i?r.nx:"y"===i?r.ny:r.nz,Math.round(((t-s)/(a/100)+1)/o)}getData(t){t=t||{};const i=this.volume,r=i.data,n=i.matrix;let s;function o(t){return Math.round(t/100*(s-1))}function a(t,e,r,n){return 3*(r*i.ny*i.nx+e*i.nx+t)+n}s="coordinate"===this.positionType?this.getPositionFromCoordinate(this.position):this.position;const c=new Float32Array(12),l=new e;let h,u,d,m,f,p=0,g=0,y=0,b=i.nx,_=i.ny,x=i.nz;function v(t,e,i,r){l.set(t,e,i).applyMatrix4(n).toArray(c,r)}"x"===this.dimension?(d=o(i.nx),m=i.ny-1,f=i.nz-1,h=i.nz,u=i.ny,p=d,b=p+1,v(d,0,0,0),v(d,m,0,3),v(d,0,f,6),v(d,m,f,9)):"y"===this.dimension?(d=i.nx-1,m=o(i.ny),f=i.nz-1,h=i.nz,u=i.nx,g=m,_=g+1,v(0,m,0,0),v(d,m,0,3),v(0,m,f,6),v(d,m,f,9)):"z"===this.dimension&&(d=i.nx-1,m=i.ny-1,f=o(i.nz),h=i.nx,u=i.ny,y=f,x=y+1,v(0,0,f,0),v(0,m,f,3),v(d,0,f,6),v(d,m,f,9));let w=0,A=0;const S=new Uint8Array(h*u*4),C=new Float32Array(h*u);let P,I;"sigma"===this.thresholdType?(P=i.getValueForSigma(this.thresholdMin),I=i.getValueForSigma(this.thresholdMax)):(P=this.thresholdMin,I=this.thresholdMax);const k=Object.assign({},t.colorParams,{volume:i});this.normalize&&(k.domain=[0,1]);const M=Oe.getScheme(k),T=new Float32Array(3),D=M.getScale();let B,F=0,E=0;if(this.normalize){F=1/0,B=-1/0;for(let t=g;t<_;++t)for(let e=p;eB&&(B=n)}E=B-F}for(let t=g;t<_;++t)for(let e=p;eP&&s{this.viewer.add(t)})),this.setVisibility(this.visible),t()}create(){const t=new Qc(this.volume,{positionType:this.positionType,position:this.position,dimension:this.dimension,thresholdType:this.thresholdType,thresholdMin:this.thresholdMin,thresholdMax:this.thresholdMax,normalize:this.normalize}),e=new Zc(t.getData({colorParams:this.getColorParams()}),this.getBufferParams({filter:this.filter}));this.bufferList.push(e)}}function tl(t){ke.error(`makeRepresentation: representation type ${t} unknown`)}const el={name:"some element",status:""};class il{constructor(t,e={}){this.stage=t,this.signals={statusChanged:new tt,nameChanged:new tt,disposed:new tt},this.parameters=nt(e,this.defaultParameters),this.uuid=Tt()}get defaultParameters(){return el}get name(){return this.parameters.name}setStatus(t){return this.parameters.status=t,this.signals.statusChanged.dispatch(t),this}setName(t){return this.parameters.name=t,this.signals.nameChanged.dispatch(t),this}dispose(){this.signals.disposed.dispatch()}}const rl=Object.assign({visible:!0},el);class nl extends il{constructor(t,e,i={},r){super(t,Object.assign({name:e.type},i)),this.parent=r,this.signals=Object.assign({visibilityChanged:new tt,parametersChanged:new tt},this.signals),this.setRepresentation(e)}get defaultParameters(){return rl}get visible(){return this.parameters.visible}get type(){return"representation"}getType(){return this.repr.type}setRepresentation(t){this._disposeRepresentation(),this.repr=t,this.stage.tasks.listen(this.repr.tasks),this.updateVisibility()}_disposeRepresentation(){this.repr&&(this.stage.tasks.unlisten(this.repr.tasks),this.repr.dispose())}dispose(){this.parent&&this.parent.hasRepresentation(this)?this.parent.removeRepresentation(this):(this._disposeRepresentation(),this.signals.disposed.dispatch())}setVisibility(t){return this.parameters.visible=t,this.updateVisibility(),this.signals.visibilityChanged.dispatch(this.parameters.visible),this}getVisibility(){return this.parent?this.parent.parameters.visible&&this.parameters.visible:this.parameters.visible}toggleVisibility(){return this.setVisibility(!this.parameters.visible)}updateVisibility(){this.repr.setVisibility(this.getVisibility())}update(t){return this.repr.update(t),this}build(t){return this.repr.build(t),this}setSelection(t){const e=this.repr;return e.setSelection&&e.setSelection(t),this}setParameters(t){return this.repr.setParameters(t),this.signals.parametersChanged.dispatch(this.repr.getParameters()),this}getParameters(){return this.repr.getParameters()}setColor(t){return this.repr.setColor(t),this}}const sl=new i,ol=new e,al={name:"",status:"",visible:!0};class cl{constructor(t,n,s={}){this.stage=t,this.object=n,this.signals={representationAdded:new tt,representationRemoved:new tt,visibilityChanged:new tt,matrixChanged:new tt,statusChanged:new tt,nameChanged:new tt,disposed:new tt},this.reprList=[],this.annotationList=[],this.matrix=new i,this.position=new e,this.quaternion=new r,this.scale=new e(1,1,1),this.transform=new i,this.parameters=nt(s,this.defaultParameters),this.uuid=Tt(),this.viewer=t.viewer,this.controls=new ua(this)}get defaultParameters(){return al}get name(){return this.parameters.name}get status(){return this.parameters.status}get visible(){return this.parameters.visible}setPosition(t){return Array.isArray(t)?this.position.fromArray(t):this.position.copy(t),this.updateMatrix(),this}setRotation(t){if(Array.isArray(t))if(3===t.length){const e=(new G).fromArray(t);this.quaternion.setFromEuler(e)}else this.quaternion.fromArray(t);else t instanceof G?this.quaternion.setFromEuler(t):this.quaternion.copy(t);return this.updateMatrix(),this}setScale(t){return this.scale.set(t,t,t),this.updateMatrix(),this}setTransform(t){return this.transform.copy(t),this.updateMatrix(),this}updateMatrix(){const t=this.getCenterUntransformed(ol);this.matrix.makeTranslation(-t.x,-t.y,-t.z),sl.makeRotationFromQuaternion(this.quaternion),this.matrix.premultiply(sl),sl.makeScale(this.scale.x,this.scale.y,this.scale.z),this.matrix.premultiply(sl);const e=this.position;sl.makeTranslation(e.x+t.x,e.y+t.y,e.z+t.z),this.matrix.premultiply(sl),this.matrix.premultiply(this.transform),this.updateRepresentationMatrices(),this.stage.viewer.updateBoundingBox(),this.signals.matrixChanged.dispatch(this.matrix)}updateRepresentationMatrices(){this.reprList.forEach((t=>{t.setParameters({matrix:this.matrix})}))}addAnnotation(t,e,i){const r=new aa(this,t,e,i);return this.annotationList.push(r),r}eachAnnotation(t){this.annotationList.slice().forEach(t)}removeAnnotation(t){const e=this.annotationList.indexOf(t);-1!==e&&(this.annotationList.splice(e,1),t.dispose())}removeAllAnnotations(){this.eachAnnotation((t=>t.dispose())),this.annotationList.length=0}_addRepresentation(t,e,i,r=!1){const n=i||{},s=this.stage.getParameters();n.matrix=this.matrix.clone(),n.quality=n.quality||s.quality,n.disableImpostor=rt(n.disableImpostor,!s.impostor),n.useWorker=rt(n.useWorker,s.workerDefault),n.visible=rt(n.visible,!0);const o=Object.assign({},n,{visible:this.parameters.visible&&n.visible}),a=function(t,e,i,r){var n;if(De&&ke.time("makeRepresentation "+t),e instanceof Sc){if(!(n=Le.get(t)))return void tl(t)}else if(e instanceof Fo)if("surface"===t)n=Xo;else{if("dot"!==t)return void tl(t);n=qc}else if(e instanceof $o)if("surface"===t)n=Xo;else if("dot"===t)n=qc;else{if("slice"!==t)return void tl(t);n=Jc}else if(e instanceof kc)n=Mc,e=e.getBufferList();else{if("buffer"!==t)return void ke.error("makeRepresentation: object "+e+" unknown");n=Mc}const s=new n(e,i,r);return De&&ke.timeEnd("makeRepresentation "+t),s}(t,e,this.viewer,o),c=new nl(this.stage,a,n,this);return r||(this.reprList.push(c),this.signals.representationAdded.dispatch(c)),c}addBufferRepresentation(t,e){return this._addRepresentation.call(this,"buffer",t,e)}hasRepresentation(t){return-1!==this.reprList.indexOf(t)}eachRepresentation(t){this.reprList.slice().forEach(t)}removeRepresentation(t){const e=this.reprList.indexOf(t);-1!==e&&(this.reprList.splice(e,1),t.dispose(),this.signals.representationRemoved.dispatch(t))}updateRepresentations(t){this.reprList.forEach((e=>e.update(t))),this.stage.viewer.requestRender()}removeAllRepresentations(){this.eachRepresentation((t=>t.dispose()))}dispose(){this.removeAllAnnotations(),this.removeAllRepresentations(),this.reprList.length=0,this.signals.disposed.dispatch()}setVisibility(t){return this.parameters.visible=t,this.eachRepresentation((t=>t.updateVisibility())),this.eachAnnotation((t=>t.updateVisibility())),this.signals.visibilityChanged.dispatch(t),this}setStatus(t){return this.parameters.status=t,this.signals.statusChanged.dispatch(t),this}setName(t){return this.parameters.name=t,this.signals.nameChanged.dispatch(t),this}getBox(...t){return this.getBoxUntransformed(...t).clone().applyMatrix4(this.matrix)}getCenter(...t){return this.getCenterUntransformed(...t).clone().applyMatrix4(this.matrix)}getZoom(...t){return this.stage.getZoomForBox(this.getBox(...t))}getBoxUntransformed(...t){return new a}getCenterUntransformed(...t){return this.getBoxUntransformed().getCenter(new e)}autoView(t){this.stage.animationControls.zoomMove(this.getCenter(),this.getZoom(),rt(t,0))}}class ll{constructor(t=[]){this.list=t;const e=t.length;for(let i=0;i0?this.list[0]:void 0}forEach(t){return this.list.forEach(t),this}dispose(){return this.forEach((t=>t.dispose()))}}class hl extends ll{setParameters(t){return this.forEach((e=>e.setParameters(t)))}setVisibility(t){return this.forEach((e=>e.setVisibility(t)))}setSelection(t){return this.forEach((e=>e.setSelection(t)))}setColor(t){return this.forEach((e=>e.setColor(t)))}update(t){return this.forEach((e=>e.update(t)))}build(t){return this.forEach((e=>e.build(t)))}dispose(t){return this.forEach((t=>t.dispose()))}}const ul=Object.assign({defaultStep:1,defaultTimeout:50,defaultInterpolateType:"",defaultInterpolateStep:5,defaultMode:"loop",defaultDirection:"forward",initialFrame:0},el);class dl extends il{constructor(t,e,i={}){super(t,Object.assign({name:e.name},i)),this.trajectory=e,this.signals=Object.assign(this.signals,{frameChanged:new tt,playerChanged:new tt,countChanged:new tt,parametersChanged:new tt}),e.signals.frameChanged.add((t=>{this.signals.frameChanged.dispatch(t)})),e.signals.playerChanged.add((t=>{this.signals.playerChanged.dispatch(t)})),e.signals.countChanged.add((t=>{this.signals.countChanged.dispatch(t)})),void 0!==i.initialFrame&&this.setFrame(i.initialFrame)}get defaultParameters(){return ul}get type(){return"trajectory"}setFrame(t){this.trajectory.setFrame(t)}setParameters(t={}){this.trajectory.setParameters(t),this.signals.parametersChanged.dispatch(t)}dispose(){this.trajectory.dispose(),super.dispose()}}class ml{constructor(t,e){this.name=t,this.path=e,this.coordinates=[],this.boxes=[],this.times=[],this.timeOffset=0,this.deltaTime=1}get type(){return"Frames"}}class fl{constructor(t,e){let r,n;if(this.A=new lo(3,3),this.W=new lo(1,3),this.U=new lo(3,3),this.V=new lo(3,3),this.VH=new lo(3,3),this.R=new lo(3,3),this.tmp=new lo(3,3),this.c=new lo(3,3),t instanceof Sc)r=t.atomCount;else{if(!(t instanceof Float32Array))return;r=t.length/3}if(e instanceof Sc)n=e.atomCount;else{if(!(e instanceof Float32Array))return;n=e.length/3}const s=Math.min(r,n),o=new lo(3,s),a=new lo(3,s);this.coords1t=new lo(s,3),this.coords2t=new lo(s,3),this.transformationMatrix=new i,this.c.data.set([1,0,0,0,1,0,0,0,-1]),this.prepCoords(t,o,s,!1),this.prepCoords(e,a,s,!1),this._superpose(o,a)}_superpose(t,e){this.mean1=fo(t),this.mean2=fo(e),po(t,this.mean1),po(e,this.mean2),ho(this.coords1t,t),ho(this.coords2t,e),uo(this.A,this.coords2t,this.coords1t),xo(this.A,this.W,this.U,this.V),function(t,e){const i=t.data,r=e.data,n=i[4],s=i[8],o=i[5],a=i[7],c=i[0],l=c*n,h=c*o,u=i[3],d=i[1],m=u*d,f=i[2],p=u*f,g=i[6],y=g*d,b=g*f,_=1/(l*s-h*a-m*s+p*a+y*o-b*n);r[0]=(n*s-o*a)*_,r[1]=-(d*s-f*a)*_,r[2]=-(-d*o+f*n)*_,r[3]=-(u*s-o*g)*_,r[4]=(c*s-b)*_,r[5]=-(h-p)*_,r[6]=-(-u*a+n*g)*_,r[7]=-(c*a-y)*_,r[8]=(l-m)*_}(this.V,this.VH),mo(this.R,this.U,this.VH),function(t){const e=t.data;return e[0]*e[4]*e[8]-e[0]*e[5]*e[7]-e[3]*e[1]*e[8]+e[3]*e[2]*e[7]+e[6]*e[1]*e[5]-e[6]*e[2]*e[4]}(this.R)<0&&(De&&ke.log("R not a right handed system"),mo(this.tmp,this.c,this.VH),mo(this.R,this.U,this.tmp));const i=new lo(4,4),r=new lo(4,4),n=new lo(4,4),s=new lo(4,4),o=new lo(4,4),a=new lo(4,4),c=this.R.data,l=this.mean1,h=this.mean2;s.data.set([1,0,0,-l[0],0,1,0,-l[1],0,0,1,-l[2],0,0,0,1]),o.data.set([c[0],c[1],c[2],0,c[3],c[4],c[5],0,c[6],c[7],c[8],0,0,0,0,1]),a.data.set([1,0,0,h[0],0,1,0,h[1],0,0,1,h[2],0,0,0,1]),ho(r,s),uo(i,o,r),ho(n,i),uo(r,a,n),ho(i,r),this.transformationMatrix.elements=i.data}prepCoords(t,e,i,r){let n=0;const s=e.data;let o=3,a=3*i;if(r&&(a=4*i,o=4),t instanceof Sc)t.eachAtom((function(t){n{t!==this&&this.pause()}),this);const i=rt(t.frameCount,1);this.traj=t,this.parameters=nt(e,pl),this.parameters.end=Math.min(rt(e.end,i-1),i-1),this.parameters.step=rt(e.step,Math.ceil((i+1)/100)),this._currentFrame=this.parameters.start,this._direction="bounce"===this.parameters.direction?"forward":this.parameters.direction,t.signals.countChanged.add((t=>{this.parameters.end=Math.min(rt(this.parameters.end,t-1),t-1)}),this),this._animate=this._animate.bind(this)}get isRunning(){return this._run}setParameters(t={}){st(this.parameters,t),void 0!==t.direction&&"bounce"!==this.parameters.direction&&(this._direction=this.parameters.direction)}_animate(){if(!this._run)return;this._currentTime=window.performance.now();const t=this._currentTime-this._previousTime,e=this.parameters.interpolateType?this.parameters.interpolateStep:1,i=this.parameters.timeout/e,r=this.traj;if(r&&r.frameCount&&!r.inProgress&&t>=i)if(this.parameters.interpolateType)if(this._currentStep>this.parameters.interpolateStep&&(this._currentStep=1),1===this._currentStep&&(this._currentFrame=this._nextInterpolated()),r.hasFrame(this._currentFrame)){this._currentStep+=1;const t=this._currentStep/(this.parameters.interpolateStep+1),[e,i,n,s]=this._currentFrame;r.setFrameInterpolated(e,i,n,s,t,this.parameters.interpolateType),this._previousTime=this._currentTime}else r.loadFrame(this._currentFrame);else{const t=this._next();r.hasFrame(t)?(r.setFrame(t),this._previousTime=this._currentTime):r.loadFrame(t)}window.requestAnimationFrame(this._animate)}_next(){const t=this.parameters;let e;return e="forward"===this._direction?this.traj.currentFrame+t.step:this.traj.currentFrame-t.step,(e>t.end||e=t.end?i=t.start:"backward"===t.direction&&e<=t.start&&(i=t.end),this.traj.setFrame(i),this._run=!0,this._animate(),this.signals.startedRunning.dispatch()}}pause(){this._run=!1,this.signals.haltedRunning.dispatch()}stop(){this.pause(),this.traj.setFrame(this.parameters.start)}}class yl{constructor(t,e,i={}){this.signals={countChanged:new tt,frameChanged:new tt,playerChanged:new tt},this.frameCache={},this.loadQueue={},this.boxCache={},this.pathCache={},this.frameCacheSize=0,this._frameCount=0,this._currentFrame=-1,this._disposed=!1,this.deltaTime=rt(i.deltaTime,0),this.timeOffset=rt(i.timeOffset,0),this.centerPbc=rt(i.centerPbc,!1),this.removePbc=rt(i.removePbc,!1),this.removePeriodicity=rt(i.removePeriodicity,!1),this.superpose=rt(i.superpose,!1),this.name=t.replace(/^.*[\\/]/,""),this.trajPath=t,this.selection=new me(rt(i.sele,"backbone and not hydrogen")),this.selection.signals.stringChanged.add((()=>{this.selectionIndices=this.structure.getAtomIndices(this.selection),this._resetCache(),this._saveInitialCoords(),this.setFrame(this._currentFrame)}))}get frameCount(){return this._frameCount}get currentFrame(){return this._currentFrame}_init(t){this.setStructure(t),this._loadFrameCount(),this.setPlayer(new gl(this))}_loadFrameCount(){}setStructure(t){this.structure=t,this.atomCount=t.atomCount,this.backboneIndices=this._getIndices(new me("backbone and not hydrogen")),this._makeAtomIndices(),this._saveStructureCoords(),this.selectionIndices=this._getIndices(this.selection),this._resetCache(),this._saveInitialCoords(),this.setFrame(this._currentFrame)}_saveInitialCoords(){this.structure.hasCoords()?(this.initialCoords=new Float32Array(this.structureCoords),this._makeSuperposeCoords()):this.frameCache[0]?(this.initialCoords=new Float32Array(this.frameCache[0]),this._makeSuperposeCoords()):this.loadFrame(0,(()=>this._saveInitialCoords()))}_saveStructureCoords(){this.structureCoords=this.structure.getAtomData({what:{position:!0}}).position}setSelection(t){return this.selection.setString(t),this}_getIndices(t){let e=0;const i=t.test,r=[];return i&&this.structure.eachAtom((t=>{i(t)&&r.push(e),e+=1})),r}_makeSuperposeCoords(){const t=3*this.selectionIndices.length;this.coords1=new Float32Array(t),this.coords2=new Float32Array(t);const e=this.initialCoords,i=this.coords2;for(let r=0;r!!this.frameCache[t])):!!this.frameCache[t]}setFrame(t,e){return void 0===t||(this.inProgress=!0,-1===t||this.frameCache[t]?(this._updateStructure(t),e&&e()):this.loadFrame(t,(()=>{this._updateStructure(t),e&&e()}))),this}_interpolate(t,e,i,r,n,s){const o=this.frameCache;let a;a="spline"===s?function(t,e,i,r,n){const s=t.length,o=new Float32Array(s);for(let a=0;a{this._interpolate(t,e,i,r,n,s),o&&o()})):(this._interpolate(t,e,i,r,n,s),o&&o()),this}loadFrame(t,e){Array.isArray(t)?t.forEach((t=>{this.loadQueue[t]||this.frameCache[t]||(this.loadQueue[t]=!0,this._loadFrame(t,(()=>{delete this.loadQueue[t]})))})):this.loadQueue[t]||this.frameCache[t]||(this.loadQueue[t]=!0,this._loadFrame(t,(()=>{delete this.loadQueue[t],e&&e()})))}_loadFrame(t,e){ke.error("Trajectory._loadFrame not implemented",t,e)}_updateStructure(t){this._disposed?console.error("updateStructure: traj disposed"):(-1===t?this.structureCoords&&this.structure.updatePosition(this.structureCoords):this.structure.updatePosition(this.frameCache[t]),this.structure.trajectory={name:this.trajPath,frame:t},this._currentFrame=t,this.inProgress=!1,this.signals.frameChanged.dispatch(t))}_doSuperpose(t){const e=3*this.selectionIndices.length,i=this.coords1,r=this.coords2;for(let r=0;r0&&this.centerPbc){const t=[e[0],e[4],e[8]],r=function(t,e,i){return[xi(e,i[0],3,0,t),xi(e,i[1],3,1,t),xi(e,i[2],3,2,t)]}(this.backboneIndices,i,t);!function(t,e,i){if(0===i[0]||0===i[8]||0===i[4])return;const r=t.length,n=i[0],s=i[1],o=i[2],a=-e[0]+n+n/2,c=-e[1]+s+s/2,l=-e[2]+o+o/2;for(let e=0;e.5&&(t[n+r]-=e[3*r+r]*Math.round(s))}}(i,e,t)}this.removePbc&&function(t,e){if(0===e[0]||0===e[8]||0===e[4])return;const i=t.length;for(let r=3;r.9*e[3*i+i])if(n>0)for(let n=0;n<3;++n)t[r+n]-=e[3*i+n];else for(let n=0;n<3;++n)t[r+n]+=e[3*i+n]}}(i,e)}this.selectionIndices.length>0&&this.coords1&&this.superpose&&this._doSuperpose(i),this.frameCache[t]=i,this.boxCache[t]=e,this.frameCacheSize+=1}_setFrameCount(t){t!==this._frameCount&&(this._frameCount=t,this.signals.countChanged.dispatch(t))}dispose(){this._resetCache(),this._disposed=!0,this.player&&this.player.stop()}setPlayer(t){this.player=t,this.signals.playerChanged.dispatch(t)}getFrameTime(t){return this.timeOffset+t*this.deltaTime}}class bl extends yl{constructor(t,e,i){const r=i||{};r.timeOffset=rt(r.timeOffset,t.timeOffset),r.deltaTime=rt(r.deltaTime,t.deltaTime),super("",e,r),this.name=t.name,this.path=t.path,this.frames=t.coordinates,this.boxes=t.boxes,this._init(e)}get type(){return"frames"}_makeAtomIndices(){"StructureView"===this.structure.type?this.atomIndices=this.structure.getAtomIndices():this.atomIndices=void 0}_loadFrame(t,e){let i;const r=this.frames[t];if(this.atomIndices){const t=this.atomIndices,e=t.length;i=new Float32Array(3*e);for(let n=0;n{const n=i.response;if(!n)return void ke.error(`empty arrayBuffer for '${r}'`);const s=new Int32Array(n,0,1)[0],o=new Float32Array(n,8,9),a=new Float32Array(n,44);this._process(t,o,a,s),"function"==typeof e&&e()}),!1),i.send(n)}_loadFrameCount(){const t=new XMLHttpRequest,e=qe.getCountUrl(this.trajPath);t.open("GET",e,!0),t.addEventListener("load",(()=>{this._setFrameCount(parseInt(t.response))}),!1),t.send()}}class vl extends yl{constructor(t,e,i){super("",e,i),this.requestCallback=t,this._init(e)}get type(){return"callback"}_makeAtomIndices(){const t=[];if("StructureView"===this.structure.type){const e=this.structure.getAtomIndices(),i=e.length;let r=e[0],n=e[0];for(let s=1;s{this._process(t,i,r,n),"function"==typeof e&&e()}),t,this.atomIndices)}_loadFrameCount(){this.requestCallback((t=>this._setFrameCount(t)))}}Sc.prototype.getView=function(t){return new wl(this,t)};class wl extends Sc{constructor(t,i){super(),this.structure=t,this.selection=i,this.center=new e,this.boundingBox=new a,this._bp=this.getBondProxy(),this._ap=this.getAtomProxy(),this._rp=this.getResidueProxy(),this._cp=this.getChainProxy(),this.selection&&this.selection.signals.stringChanged.add(this.refresh,this),this.structure.signals.refreshed.add(this.refresh,this),this.refresh()}init(){}get type(){return"StructureView"}get name(){return this.structure.name}get path(){return this.structure.path}get title(){return this.structure.title}get id(){return this.structure.id}get data(){return this.structure.data}get atomSetDict(){return this.structure.atomSetDict}get biomolDict(){return this.structure.biomolDict}get entityList(){return this.structure.entityList}get unitcell(){return this.structure.unitcell}get frames(){return this.structure.frames}get boxes(){return this.structure.boxes}get validation(){return this.structure.validation}get bondStore(){return this.structure.bondStore}get backboneBondStore(){return this.structure.backboneBondStore}get rungBondStore(){return this.structure.rungBondStore}get atomStore(){return this.structure.atomStore}get residueStore(){return this.structure.residueStore}get chainStore(){return this.structure.chainStore}get modelStore(){return this.structure.modelStore}get atomMap(){return this.structure.atomMap}get residueMap(){return this.structure.residueMap}get bondHash(){return this.structure.bondHash}get spatialHash(){return this.structure.spatialHash}get _hasCoords(){return this.structure._hasCoords}set _hasCoords(t){this.structure._hasCoords=t}refresh(){De&&ke.time("StructureView.refresh"),this.atomSetCache={};const t=this.structure;if(this.selection.isAllSelection()&&t!==this&&t.atomSet&&t.bondSet){this.atomSet=t.atomSet.clone(),this.bondSet=t.bondSet.clone();for(let t in this.atomSetDict){const e=this.atomSetDict[t];this.atomSetCache["__"+t]=e.clone()}this.atomCount=t.atomCount,this.bondCount=t.bondCount,this.boundingBox.copy(t.boundingBox),this.center.copy(t.center)}else if(this.selection.isNoneSelection()&&t!==this&&t.atomSet&&t.bondSet){this.atomSet=new En(t.atomCount),this.bondSet=new En(t.bondCount);for(let e in this.atomSetDict)this.atomSetCache["__"+e]=new En(t.atomCount);this.atomCount=0,this.bondCount=0,this.boundingBox.makeEmpty(),this.center.set(0,0,0)}else{this.atomSet=this.getAtomSet(this.selection,!0),t.atomSet&&(this.atomSet=this.atomSet.intersection(t.atomSet)),this.bondSet=this.getBondSet();for(let t in this.atomSetDict){const e=this.atomSetDict[t];this.atomSetCache["__"+t]=e.makeIntersection(this.atomSet)}this.atomCount=this.atomSet.getSize(),this.bondCount=this.bondSet.getSize(),this.boundingBox=this.getBoundingBox(),this.center=this.boundingBox.getCenter(new e)}De&&ke.timeEnd("StructureView.refresh"),this.signals.refreshed.dispatch()}setSelection(t){this.selection=t,this.refresh()}getSelection(t){const e=[];t&&t.string&&e.push(t.string);const i=this.structure.getSelection();i&&i.string&&e.push(i.string),this.selection&&this.selection.string&&e.push(this.selection.string);let r="";return e.length>0&&(r=`( ${e.join(" ) AND ( ")} )`),new me(r)}getStructure(){return this.structure.getStructure()}eachBond(t,e){this.structure.eachBond(t,this.getSelection(e))}eachAtom(t,e){const i=this.getAtomProxy(),r=this.getAtomSet(e),n=this.atomStore.count;if(r.getSize()=this.V[i][r]?(e="S",this.score=this.S[i][r]):this.V[i][r]>=this.H[i][r]?(e="V",this.score=this.V[i][r]):(e="H",this.score=this.H[i][r]),De&&ke.log("Alignment: SCORE",this.score),De&&ke.log("Alignment: S, V, H",this.S[i][r],this.V[i][r],this.H[i][r]);i>0&&r>0;)"S"===e?this.S[i][r]===this.S[i-1][r-1]+t(i-1,r-1)?(this.ali1=this.seq1[i-1]+this.ali1,this.ali2=this.seq2[r-1]+this.ali2,--i,--r,e="S"):this.S[i][r]===this.V[i][r]?e="V":this.S[i][r]===this.H[i][r]?e="H":(--i,--r):"V"===e?this.V[i][r]===this.V[i-1][r]+this.gapExtensionPenalty?(this.ali1=this.seq1[i-1]+this.ali1,this.ali2="-"+this.ali2,--i,e="V"):this.V[i][r]===this.S[i-1][r]+this.gap(0)?(this.ali1=this.seq1[i-1]+this.ali1,this.ali2="-"+this.ali2,--i,e="S"):--i:"H"===e?this.H[i][r]===this.H[i][r-1]+this.gapExtensionPenalty?(this.ali1="-"+this.ali1,this.ali2=this.seq2[r-1]+this.ali2,--r,e="H"):this.H[i][r]===this.S[i][r-1]+this.gap(0)?(this.ali1="-"+this.ali1,this.ali2=this.seq2[r-1]+this.ali2,--r,e="S"):--r:ke.error("Alignment: no matrix");for(;i>0;)this.ali1=this.seq1[i-1]+this.ali1,this.ali2="-"+this.ali2,--i;for(;r>0;)this.ali1="-"+this.ali1,this.ali2=this.seq2[r-1]+this.ali2,--r;De&&ke.timeEnd("Alignment.trace"),De&&ke.log([this.ali1,this.ali2])}}function Il(t,e,i=!1,r="",n=""){let s,o,a,c,l;if(i){let i=t,h=e;r&&n&&(i=t.getView(new me(r)),h=e.getView(new me(n)));const u=i.getSequence(),d=h.getSequence(),m=new Pl(u.join(""),d.join(""));let f,p;m.calc(),m.trace(),s=0,o=0,a=m.ali1.length;const g=[],y=[];for(let t=0;tt[e]))}}}(),this.spacefillRepresentation=this.addRepresentation("spacefill",{sele:"none",opacity:Me.opacity,color:Me.color,disablePicking:!0,radiusType:"data"},!0),this.distanceRepresentation=this.addRepresentation("distance",Me,!0),this.angleRepresentation=this.addRepresentation("angle",Me,!0),this.dihedralRepresentation=this.addRepresentation("dihedral",Me,!0),this.measureRepresentations=new hl([this.spacefillRepresentation,this.distanceRepresentation,this.angleRepresentation,this.dihedralRepresentation]),this.setDefaultAssembly(this.parameters.defaultAssembly),this.structure.signals.refreshed.add((()=>{this.updateRepresentations({position:!0})}))}get defaultParameters(){return kl}get type(){return"structure"}initSelection(t){this.selection=new me(t),this.structureView=new wl(this.structure,this.selection),this.selection.signals.stringChanged.add((()=>{this.structureView.setSelection(this.selection),this.rebuildRepresentations(),this.rebuildTrajectories()}))}setSelection(t){return this.parameters.sele=t,this.selection.setString(t),this}setDefaultAssembly(t){if(void 0===this.structure.biomolDict[t]&&(t=""),this.parameters.defaultAssembly!==t){const e={defaultAssembly:t};this.reprList.forEach((t=>t.setParameters(e))),this.measureRepresentations.setParameters(e),this.parameters.defaultAssembly=t,this.signals.defaultAssemblyChanged.dispatch(t)}return this}rebuildRepresentations(){this.reprList.forEach((t=>{t.build()})),this.measureRepresentations.build()}rebuildTrajectories(){this.trajList.forEach((t=>{t.trajectory.setStructure(this.structureView)}))}updateRepresentations(t){super.updateRepresentations(t),this.measureRepresentations.update(t)}updateRepresentationMatrices(){super.updateRepresentationMatrices(),this.measureRepresentations.setParameters({matrix:this.matrix})}addRepresentation(t,e={},i=!1){e.defaultAssembly=this.parameters.defaultAssembly;const r=this._addRepresentation(t,this.structureView,e,i);return i||r.signals.parametersChanged.add((()=>this.measureUpdate())),r}addTrajectory(t="",e={}){const i=function(t,e,i){let r;return r=t&&t instanceof ml?new bl(t,e,i):!t&&e.frames?new _l(t,e,i):t&&"function"==typeof t?new vl(t,e,i):new xl(t,e,i),r}(t,this.structureView,e),r=new dl(this.stage,i,e);return this.trajList.push(r),this.signals.trajectoryAdded.dispatch(r),r}removeTrajectory(t){const e=this.trajList.indexOf(t);-1!==e&&this.trajList.splice(e,1),t.dispose(),this.signals.trajectoryRemoved.dispatch(t)}dispose(){this.trajList.slice().forEach((t=>t.dispose())),this.trajList.length=0,this.structure.dispose(),this.measureRepresentations.dispose(),super.dispose()}autoView(t,e){"number"==typeof t&&(e=t,t=""),this.stage.animationControls.zoomMove(this.getCenter(t),this.getZoom(t),rt(e,0))}getBoxUntransformed(t){let e;return e=t?this.structureView.getBoundingBox(new me(t)):this.structureView.boundingBox,e}getCenterUntransformed(t){return t&&"string"==typeof t?this.structure.atomCenter(new me(t)):this.structure.center}superpose(t,e,i,r){return Il(this.structureView,t.structureView,e,i,r),this.updateRepresentations({position:!0}),this}getMaxRepresentationRadius(t){let e=0;const i=this.structure.getAtomProxy(t);return this.eachRepresentation((t=>{if(t.getVisibility()){const r=t.repr;e=Math.max(r.getAtomRadius(i),e)}})),e}measurePick(t){const e=this.pickBuffer.count;if(this.lastPick===t.index&&e>=1){if(e>1){const t=this.pickBuffer.data,i=this.pickBuffer.data.sort();this.pickDict.has(i)?this.pickDict.del(i):this.pickDict.add(i,t),2===e?this.distanceRepresentation.setParameters({atomPair:this.pickDict.values.filter((t=>2===t.length))}):3===e?this.angleRepresentation.setParameters({atomTriple:this.pickDict.values.filter((t=>3===t.length))}):4===e&&this.dihedralRepresentation.setParameters({atomQuad:this.pickDict.values.filter((t=>4===t.length))})}this.pickBuffer.clear(),this.lastPick=void 0}else this.pickBuffer.has(t.index)||this.pickBuffer.push(t.index),this.lastPick=t.index;this.measureUpdate()}measureClear(){this.pickBuffer.clear(),this.lastPick=void 0,this.spacefillRepresentation.setSelection("none")}measureBuild(){const t=this.measureData();this.distanceRepresentation.setParameters({atomPair:t.distance}),this.angleRepresentation.setParameters({atomTriple:t.angle}),this.dihedralRepresentation.setParameters({atomQuad:t.dihedral})}measureUpdate(){const t=this.pickBuffer.data,e={};t.forEach((t=>{const i=Math.max(.1,this.getMaxRepresentationRadius(t));e[t]=i*(2.3-Et(.1,2,i))})),this.spacefillRepresentation.setSelection(t.length?"@"+t.join(","):"none"),t.length&&this.spacefillRepresentation.setParameters({radiusData:e})}measureData(){const t=this.pickDict.values;return{distance:t.filter((t=>2===t.length)),angle:t.filter((t=>3===t.length)),dihedral:t.filter((t=>4===t.length))}}removeAllMeasurements(t){const e=this.pickDict,i=e.values,r=function(t){i.filter((e=>e.length===t)).forEach((t=>e.del(t.slice().sort())))};(!t||1&t)&&r(2),(!t||2&t)&&r(3),(!t||4&t)&&r(4),this.measureBuild()}removeMeasurement(t){this.pickDict.del(t.slice().sort()),this.measureBuild()}addMeasurement(t){if(t.length<2||t.length>4)return;const e=t.slice().sort();this.pickDict.has(e)||this.pickDict.add(e,t),this.measureBuild()}}Ve.add("structure",Ml),Ve.add("structureview",Ml);class Tl extends cl{constructor(t,e,i={}){super(t,e,Object.assign({name:e.name},i)),this.surface=e}get type(){return"surface"}addRepresentation(t,e={}){return this._addRepresentation(t,this.surface,e)}getBoxUntransformed(){return this.surface.boundingBox}getCenterUntransformed(){return this.surface.center}dispose(){this.surface.dispose(),super.dispose()}}Ve.add("surface",Tl);class Dl extends cl{constructor(t,e,i={}){super(t,e,Object.assign({name:e.name},i)),this.volume=e}get type(){return"volume"}addRepresentation(t,e={}){return this._addRepresentation(t,this.volume,e)}getBoxUntransformed(){return this.volume.boundingBox}getCenterUntransformed(){return this.volume.center}dispose(){this.volume.dispose(),super.dispose()}}Ve.add("volume",Dl);class Bl extends ll{addRepresentation(t,e){return this.forEach((i=>i.addRepresentation(t,e)))}autoView(t){return this.forEach((e=>e.autoView(t)))}}function Fl(t,e){return t instanceof RegExp?null!==e.name.match(t):e.name===t}const El=new e,$l={impostor:!0,quality:"medium",workerDefault:!0,sampleLevel:0,backgroundColor:"black",rotateSpeed:2,zoomSpeed:1.2,panSpeed:1,clipNear:0,clipFar:100,clipDist:10,clipMode:"scene",clipScale:"relative",fogNear:50,fogFar:100,cameraFov:40,cameraEyeSep:.3,cameraType:"perspective",lightColor:14540253,lightIntensity:1.2,ambientColor:14540253,ambientIntensity:.3,hoverTimeout:0,tooltip:!0,mousePreset:"default"};class Ol{constructor(t,e={}){this.signals={parametersChanged:new tt,fullscreenChanged:new tt,componentAdded:new tt,componentRemoved:new tt,clicked:new tt,hovered:new tt},this.tasks=new ui,this.compList=[],this.defaultFileParams={},this.logList=[],this.viewer=new Qi(t),this.viewer.renderer&&(this.tooltip=document.createElement("div"),Object.assign(this.tooltip.style,{display:"none",position:"fixed",zIndex:"1000000",pointerEvents:"none",backgroundColor:"rgba( 0, 0, 0, 0.6 )",color:"lightgrey",padding:"8px",fontFamily:"sans-serif"}),this.viewer.container.appendChild(this.tooltip),this.mouseObserver=new rr(this.viewer.renderer.domElement),this.viewerControls=new Ir(this),this.trackballControls=new pr(this),this.pickingControls=new br(this),this.animationControls=new Rr(this),this.mouseControls=new Qo(this),this.keyControls=new ea(this),this.pickingBehavior=new ia(this),this.mouseBehavior=new ra(this),this.animationBehavior=new na(this),this.keyBehavior=new oa(this),this.spinAnimation=this.animationControls.spin([0,1,0],.005),this.spinAnimation.pause(!0),this.rockAnimation=this.animationControls.rock([0,1,0],.005),this.rockAnimation.pause(!0),this.parameters=nt(e,$l),this.setParameters(this.parameters),this.viewer.animate())}setParameters(t={}){st(this.parameters,t);const e=t,i=this.parameters,r=this.viewer,n=this.trackballControls;return void 0!==e.quality&&this.setQuality(i.quality),void 0!==e.impostor&&this.setImpostor(i.impostor),void 0!==e.rotateSpeed&&(n.rotateSpeed=i.rotateSpeed),void 0!==e.zoomSpeed&&(n.zoomSpeed=i.zoomSpeed),void 0!==e.panSpeed&&(n.panSpeed=i.panSpeed),void 0!==e.mousePreset&&this.mouseControls.preset(i.mousePreset),this.mouseObserver.setParameters({hoverTimeout:i.hoverTimeout}),r.setClip(i.clipNear,i.clipFar,i.clipDist,i.clipMode,i.clipScale),r.setFog(void 0,i.fogNear,i.fogFar),r.setCamera(i.cameraType,i.cameraFov,i.cameraEyeSep),r.setSampling(i.sampleLevel),r.setBackground(i.backgroundColor),r.setLight(i.lightColor,i.lightIntensity,i.ambientColor,i.ambientIntensity),this.signals.parametersChanged.dispatch(this.getParameters()),this}log(t){console.log("STAGE LOG",t),this.logList.push(t)}getParameters(){return Object.assign({},this.parameters)}defaultFileRepresentation(t){if(t instanceof Ml){let e,i,r;t.setSelection("/0");const n=t.structure;if(n.biomolDict.BU1){const s=n.biomolDict.BU1;e=s.getAtomCount(n),i=s.getResidueCount(n),r=s.getInstanceCount(),t.setDefaultAssembly("BU1")}else e=n.getModelProxy(0).atomCount,i=n.getModelProxy(0).residueCount,r=1;let s=e;Ae&&(s*=4);const o=n.atomStore.count/n.residueStore.count<2;o&&(s*=10);let a="chainname",c="RdYlBu",l=!1;if(1===n.getChainnameCount(new me("polymer and /0"))&&(a="residueindex",c="Spectral",l=!0),De&&console.log(s,e,r,o),i/r<4)t.addRepresentation("ball+stick",{colorScheme:"element",radiusScale:2,aspectRatio:1.5,bondScale:.3,bondSpacing:.75,quality:"auto"});else if(r>5&&s>15e3||s>7e5){let e=Math.min(2,Math.max(.1,6e3/(s/r)));o&&(e=Math.min(e,.5)),t.addRepresentation("surface",{colorScheme:a,colorScale:c,colorReverse:l,sele:"polymer",surfaceType:"av",probeRadius:1.4,scaleFactor:e,useWorker:!1})}else s>25e4?t.addRepresentation("backbone",{colorScheme:a,colorScale:c,colorReverse:l,lineOnly:!0}):s>1e5?t.addRepresentation("backbone",{colorScheme:a,colorScale:c,colorReverse:l,quality:"low",disableImpostor:!0,radiusScale:2}):s>8e4?t.addRepresentation("backbone",{colorScheme:a,colorScale:c,colorReverse:l,radiusScale:2}):(t.addRepresentation("cartoon",{colorScheme:a,colorScale:c,colorReverse:l,radiusScale:.7,aspectRatio:5,quality:"auto"}),s<5e4&&t.addRepresentation("base",{colorScheme:a,colorScale:c,colorReverse:l,quality:"auto"}),t.addRepresentation("ball+stick",{sele:"ligand",colorScheme:"element",radiusScale:2,aspectRatio:1.5,bondScale:.3,bondSpacing:.75,quality:"auto"}));t.structure.frames.length&&t.addTrajectory()}else(t instanceof Tl||t instanceof Dl)&&t.addRepresentation("surface");this.tasks.onZeroOnce(this.autoView,this)}loadFile(t,e={}){const i=Object.assign({},this.defaultFileParams,e),r=ii(t).name;this.tasks.increment(),this.log(`loading file '${r}'`);const n=rt(i.ext,ii(t).ext);let s;return s=Ne.isTrajectory(n)?Promise.reject(new Error(`loadFile: ext '${n}' is a trajectory and must be loaded into a structure component`)):ni(t,i),s.then((t=>{this.log(`loaded '${r}'`);const e=this.addComponentFromObject(t,i);return i.defaultRepresentation&&this.defaultFileRepresentation(e),this.tasks.decrement(),e}),(t=>{this.tasks.decrement();const e=`error loading file: '${t}'`;throw this.log(e),e}))}loadScript(t){const e=ii(t).name;return this.log(`loading script '${e}'`),ni(t).then((t=>{this.tasks.increment(),this.log(`running script '${e}'`),t.run(this).then((()=>{this.tasks.decrement(),this.log(`finished script '${e}'`)})),this.log(`called script '${e}'`)}),(t=>{this.tasks.decrement();const i=`errored script '${e}' "${t}"`;throw this.log(i),i}))}addComponent(t){t?(this.compList.push(t),this.signals.componentAdded.dispatch(t)):ke.warn("Stage.addComponent: no component given")}addComponentFromObject(t,e={}){const i=Ve.get(t.type);if(i){const r=new i(this,t,e);return this.addComponent(r),r}ke.warn("no component for object type",t.type)}removeComponent(t){const e=this.compList.indexOf(t);-1!==e&&(this.compList.splice(e,1),t.dispose(),this.signals.componentRemoved.dispatch(t))}removeAllComponents(){this.compList.slice().forEach((t=>this.removeComponent(t)))}handleResize(){this.viewer.handleResize()}setSize(t,e){const i=this.viewer.container;i!==document.body&&(void 0!==t&&(i.style.width=t),void 0!==e&&(i.style.height=e),this.handleResize())}toggleFullscreen(t){if(!(document.fullscreenEnabled||document.mozFullScreenEnabled||document.webkitFullscreenEnabled||document.msFullscreenEnabled))return void ke.log("fullscreen mode (currently) not possible");const e=this;function i(){return document.fullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement||document.msFullscreenElement}function r(){if(!i()&&e.lastFullscreenElement){const t=e.lastFullscreenElement;t.style.width=t.dataset.normalWidth||"",t.style.height=t.dataset.normalHeight||"",document.removeEventListener("fullscreenchange",r),document.removeEventListener("mozfullscreenchange",r),document.removeEventListener("webkitfullscreenchange",r),document.removeEventListener("MSFullscreenChange",r),e.handleResize(),e.signals.fullscreenChanged.dispatch(!1)}}t=t||this.viewer.container,this.lastFullscreenElement=t,i()?document.exitFullscreen?document.exitFullscreen():document.msExitFullscreen?document.msExitFullscreen():document.mozCancelFullScreen?document.mozCancelFullScreen():document.webkitExitFullscreen&&document.webkitExitFullscreen():(t.dataset.normalWidth=t.style.width||"",t.dataset.normalHeight=t.style.height||"",t.style.width=window.screen.width+"px",t.style.height=window.screen.height+"px",t.requestFullscreen?t.requestFullscreen():t.msRequestFullscreen?t.msRequestFullscreen():t.mozRequestFullScreen?t.mozRequestFullScreen():t.webkitRequestFullscreen&&t.webkitRequestFullscreen(),document.addEventListener("fullscreenchange",r),document.addEventListener("mozfullscreenchange",r),document.addEventListener("webkitfullscreenchange",r),document.addEventListener("MSFullscreenChange",r),this.handleResize(),this.signals.fullscreenChanged.dispatch(!0),setTimeout((function(){e.handleResize()}),100))}setSpin(t){t?(this.spinAnimation.resume(!0),this.rockAnimation.pause(!0)):this.spinAnimation.pause(!0)}setRock(t){t?(this.rockAnimation.resume(!0),this.spinAnimation.pause(!0)):this.rockAnimation.pause(!0)}toggleSpin(){this.setSpin(this.spinAnimation.paused)}toggleRock(){this.setRock(this.rockAnimation.paused)}getFocus(){const t=this.parameters;if("scene"!==t.clipMode)return 0;let e=t.clipNear;return"absolute"===t.clipScale&&(e=this.viewer.absoluteToRelative(e)),2*e}setFocus(t){if("scene"!==this.parameters.clipMode)return;let e,i,r,n;"relative"===this.parameters.clipScale?(e=Dt(t/2,0,49.9),i=100-e,r=50,n=function(t){return Dt(t,0,100)}(2*i-50)):(e=this.viewer.relativeToAbsolute(t/2),i=e,r=0,n=2*i),this.setParameters({clipNear:e,clipFar:i,fogNear:r,fogFar:n})}getZoomForBox(t){const e=t.getSize(El),i=Math.max(e.x,e.y,e.z),r=Math.min(e.x,e.y,e.z);let n=i+Math.sqrt(r);const s=It(this.viewer.perspectiveCamera.fov),o=this.viewer.width,a=this.viewer.height,c=a{this.tasks.onZeroOnce((()=>{this.tasks.increment(),this.viewer.makeImage(t).then((t=>{this.tasks.decrement(),e(t)})).catch((t=>{this.tasks.decrement(),i(t)}))}))}))}setImpostor(t){this.parameters.impostor=t;const e=["spacefill","ball+stick","licorice","hyperball","backbone","rocket","helixorient","contact","distance","dot"];this.eachRepresentation((function(i){if(!e.includes(i.getType()))return;const r=i.getParameters();r.disableImpostor=!t,i.build(r)}))}setQuality(t){this.parameters.quality=t;const e=["tube","cartoon","ribbon","trace","rope"],i=["spacefill","ball+stick","licorice","hyperball","backbone","rocket","helixorient","contact","distance","dot"];this.eachRepresentation((function(r){const n=r.getParameters();if(!e.includes(r.getType())){if(!i.includes(r.getType()))return;if(!n.disableImpostor)return void(r.repr.quality=t)}n.quality=t,r.build(n)}))}eachComponent(t,e){this.compList.slice().forEach((i=>{void 0!==e&&e!==i.type||t(i)}))}eachRepresentation(t,e){this.eachComponent((i=>{i.reprList.slice().forEach((r=>{void 0!==e&&e!==r.getType()||t(r,i)}))}))}getComponentsByName(t){const e=[];return this.eachComponent((i=>{(void 0===t||Fl(t,i))&&e.push(i)})),new Bl(e)}getComponentsByObject(t){const e=[];return this.eachComponent((i=>{i.object===t&&e.push(i)})),new Bl(e)}getRepresentationsByName(t){const e=[];return this.eachRepresentation(((i,r)=>{(void 0===t||Fl(t,i))&&e.push(i)})),new hl(e)}measureClear(){this.eachComponent((t=>t.measureClear()),"structure")}measureUpdate(){this.eachComponent((t=>t.measureUpdate()),"structure")}dispose(){this.tasks.dispose(),this.viewer.dispose(),this.mouseObserver.dispose()}}class Rl extends cl{constructor(t,e,i={}){super(t,e,Object.assign({name:e.name},i)),this.shape=e}get type(){return"shape"}addRepresentation(t,e={}){return this._addRepresentation(t,this.shape,e)}getBoxUntransformed(){return this.shape.boundingBox}getCenterUntransformed(){return this.shape.center}dispose(){this.shape.dispose(),super.dispose()}}function Ll(t,e,i,r){var n,s=arguments.length,o=s<3?e:null===r?r=Object.getOwnPropertyDescriptor(e,i):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(t,e,i,r);else for(var a=t.length-1;a>=0;a--)(n=t[a])&&(o=(s<3?n(o):s>3?n(e,i,o):n(e,i))||o);return s>3&&o&&Object.defineProperty(e,i,o),o}function Nl(t,e,i,r){return new(i||(i=Promise))((function(n,s){function o(t){try{c(r.next(t))}catch(t){s(t)}}function a(t){try{c(r.throw(t))}catch(t){s(t)}}function c(t){t.done?n(t.value):function(t){return t instanceof i?t:new i((function(e){e(t)}))}(t.value).then(o,a)}c((r=r.apply(t,e||[])).next())}))}Ve.add("shape",Rl),"function"==typeof SuppressedError&&SuppressedError;class zl extends Nt{constructor(t){super(t),t.scale||(this.parameters.scale="rainbow",this.parameters.reverse=rt(t.reverse,!0)),this.scalePerModel={},t.structure.eachModel((t=>{this.parameters.domain=[t.atomOffset,t.atomEnd],this.scalePerModel[t.index]=this.getScale()}))}atomColor(t){return this.scalePerModel[t.modelIndex](t.index)}}Ll([Lt],zl.prototype,"atomColor",null),Oe.add("atomindex",zl);class Ul extends Nt{constructor(t){if(super(t),t.scale||(this.parameters.scale="OrRd"),!t.domain){let e,i=1/0,r=-1/0;t.sele&&(e=new me(t.sele)),t.structure.eachAtom((function(t){const e=t.bfactor;i=Math.min(i,e),r=Math.max(r,e)}),e),this.parameters.domain=[i,r]}this.bfactorScale=this.getScale()}atomColor(t){return this.bfactorScale(t.bfactor)}}Ll([Lt],Ul.prototype,"atomColor",null),Oe.add("bfactor",Ul);class Vl extends Nt{constructor(t){super(t),this.chainidDictPerModel={},this.scalePerModel={},t.scale||(this.parameters.scale="Spectral"),t.structure.eachModel((t=>{let e=0;const i={};t.eachChain((function(t){void 0===i[t.chainid]&&(i[t.chainid]=e,e+=1)})),this.parameters.domain=[0,e-1],this.chainidDictPerModel[t.index]=i,this.scalePerModel[t.index]=this.getScale()}))}atomColor(t){const e=this.chainidDictPerModel[t.modelIndex];return this.scalePerModel[t.modelIndex](e[t.chainid])}}Ll([Lt],Vl.prototype,"atomColor",null),Oe.add("chainid",Vl);class jl extends Nt{constructor(t){super(t),this.scalePerModel={},t.scale||(this.parameters.scale="Spectral"),t.structure.eachModel((t=>{this.parameters.domain=[t.chainOffset,t.chainEnd],this.scalePerModel[t.index]=this.getScale()}))}atomColor(t){return this.scalePerModel[t.modelIndex](t.chainIndex)}}Ll([Lt],jl.prototype,"atomColor",null),Oe.add("chainindex",jl);class Gl extends Nt{constructor(t){super(t),this.chainnameDictPerModel={},this.scalePerModel={},t.scale||(this.parameters.scale="Spectral"),t.structure.eachModel((t=>{let e=0;const i={};t.eachChain((function(t){void 0===i[t.chainname]&&(i[t.chainname]=e,e+=1)})),this.parameters.domain=[0,e-1],this.chainnameDictPerModel[t.index]=i,this.scalePerModel[t.index]=this.getScale()}))}atomColor(t){const e=this.chainnameDictPerModel[t.modelIndex];return this.scalePerModel[t.modelIndex](e[t.chainname])}}Ll([Lt],Gl.prototype,"atomColor",null),Oe.add("chainname",Gl);class Hl extends Nt{constructor(t){super(t),this.rsrzDict={},this.rsccDict={},t.scale||(this.parameters.scale="RdYlBu"),this.rsrzScale=this.getScale({domain:[2,0]}),this.rsccScale=this.getScale({domain:[.678,1]});const e=t.structure.validation;e&&(this.rsrzDict=e.rsrzDict,this.rsccDict=e.rsccDict)}atomColor(t){let e=t.resno+"";t.inscode&&(e+="^"+t.inscode),t.chainname&&(e+=":"+t.chainname),e+="/"+t.modelIndex;const i=this.rsrzDict[e];if(void 0!==i)return this.rsrzScale(i);const r=this.rsccDict[e];return void 0!==r?this.rsccScale(r):9474192}}Ll([Lt],Hl.prototype,"atomColor",null),Oe.add("densityfit",Hl);const ql={ARG:{CD:.1,CZ:.5,NE:-.1},ASN:{CG:.55,OD1:-.55},ASP:{CB:-.16,CG:.36,OD1:-.6,OD2:-.6},CYS:{CB:.19,SG:-.19},GLN:{CD:.55,OE1:-.55},GLU:{CD:.36,CG:-.16,OE1:-.6,OE2:-.6},HIS:{CB:.1,CD2:.2,CE1:.45,CG:.15,ND1:.05,NE2:.05},LYS:{CE:.25,NZ:.75},MET:{CE:.06,CG:.06,SD:-.12},PTR:{C:.55,CA:.1,CZ:.25,N:-.35,O:-.55,O1P:-.85,O2P:-.85,O3P:-.85,OG1:-1.1,P:1.4},SEP:{C:.55,CA:.1,CB:.25,N:-.35,O:-.55,O1P:-.85,O2P:-.85,O3P:-.85,OG1:-1.1,P:1.4},SER:{CB:.25,OG:-.25},THR:{CB:.25,OG1:-.25},TPO:{C:.55,CA:.1,CB:.25,N:-.35,O:-.55,OG1:-1.1,O1P:-.85,O2P:-.85,O3P:-.85,P:1.4},TRP:{CD1:.06,CD2:.1,CE2:-.04,CE3:-.03,CG:-.03,NE1:-.06},TYR:{CZ:.25,OH:-.25},backbone:{C:.55,O:-.55,N:-.35,CA:.1}};class Wl extends Nt{constructor(t){super(t),this.delta=new e,this.hCharges=[],t.scale||(this.parameters.scale="rwb"),t.domain||(this.parameters.domain=[-50,50]),this.scale=this.getScale(),this.charges=new Float32Array(t.structure.atomCount);const i=[];t.structure.eachAtom((t=>{var r;if(this.charges[t.index]=(null!==(r=t).partialCharge?r.partialCharge:r.isProtein()&&(ql[r.resname]&&ql[r.resname][r.atomname]||ql.backbone[r.atomname])||0)*t.occupancy,"N"===t.atomname){if(t.bondCount>=3)return;if(t.bondToElementCount(1))return;const r=function(t,i=new e){let r=!1,n=!1,s=!1;return i.set(2*t.x,2*t.y,2*t.z),t.eachBondedAtom((function(t){if(!r)return"H"===t.atomname?(i.set(t.x,t.y,t.z),void(r=!0)):void(n||"CA"!==t.atomname?s||"C"!==t.atomname||(s=!0,i.sub(t)):(i.sub(t),n=!0))})),r?i:n&&s?(i.normalize(),i.multiplyScalar(1.04),i.add(t),i):void 0}(t);void 0!==r&&(i.push(r),this.hCharges.push(.25*t.occupancy))}}));const r=t.structure.getBoundingBox();r.expandByScalar(1.04),this.hStore=function(t){const e=t.length,i=new Float32Array(e),r=new Float32Array(e),n=new Float32Array(e);for(let e=0;e{const n=e[t];0!==n&&(r+=n/i)})),this.hHash.eachWithin(t.x,t.y,t.z,12,((t,e)=>{const n=i[t];0!==n&&(r+=n/e)})),this.scale(332*r)}}Ll([Lt],Wl.prototype,"positionColor",null),Oe.add("electrostatic",Wl);const Xl={H:16777215,HE:14286847,LI:13402367,BE:12779264,B:16758197,C:9474192,N:3166456,O:16715021,F:9494608,NE:11789301,NA:11230450,MG:9109248,AL:12560038,SI:1578e4,P:16744448,S:16777008,CL:2093087,AR:8442339,K:9388244,CA:4062976,SC:15132390,TI:12567239,V:10921643,CR:9083335,MN:10255047,FE:14706227,CO:15765664,NI:5296208,CU:13140019,ZN:8224944,GA:12750735,GE:6721423,AS:12419299,SE:16752896,BR:10889513,KR:6076625,RB:7351984,SR:65280,Y:9764863,ZR:9756896,NB:7586505,MO:5551541,TC:3907230,RU:2396047,RH:687500,PD:27013,AG:12632256,CD:16767375,IN:10909043,SN:6717568,SB:10380213,TE:13924864,I:9699476,XE:9699476,CS:5707663,BA:51456,LA:7394559,CE:16777159,PR:14286791,ND:13107143,PM:10747847,SM:9437127,EU:6422471,GD:4587463,TB:3211207,DY:2097095,HO:65436,ER:58997,TM:54354,YB:48952,LU:43812,HF:5096191,TA:5089023,W:2200790,RE:2522539,OS:2516630,IR:1528967,PT:13684960,AU:16765219,HG:12105936,TL:10900557,PB:5724513,BI:10375093,PO:11230208,AT:7688005,RN:4358806,FR:4325478,RA:32e3,AC:7384058,TH:47871,PA:41471,U:36863,NP:33023,PU:27647,AM:5528818,CM:7888099,BK:9064419,CF:10565332,ES:11739092,FM:11739066,MD:11734438,NO:12389767,LR:13041766,RF:13369433,DB:13697103,SG:14221381,BH:14680120,HS:15073326,MT:15400998,DS:16777215,RG:16777215,CN:16777215,UUT:16777215,FL:16777215,UUP:16777215,LV:16777215,UUH:16777215,D:16777152,T:16777120};class Yl extends Nt{constructor(t){t.value=rt(t.value,Xl.C),super(t)}atomColor(t){const e=t.element;return"C"===e?this.parameters.value:Xl[e]||16777215}}Ll([Lt],Yl.prototype,"atomColor",null),Oe.add("element",Yl);class Kl extends Nt{constructor(t){super(t),t.scale||(this.parameters.scale="Spectral"),t.domain||(this.parameters.domain=[0,t.structure.entityList.length-1]),this.entityindexScale=this.getScale()}atomColor(t){return this.entityindexScale(t.entityIndex)}}Ll([Lt],Kl.prototype,"atomColor",null),Oe.add("entityindex",Kl);class Zl extends Nt{atomColor(t){const e=t.entity;switch(e?e.entityType:void 0){case 1:return 8374655;case 2:return 16629894;case 3:return 12496596;case 4:return 3697840;default:return 16777113}}}Ll([Lt],Zl.prototype,"atomColor",null),Oe.add("entitytype",Zl);class Ql extends Nt{constructor(t){super(t),this.geoAtomDict={},this.geoDict={};const e=t.structure.validation;e&&(this.geoAtomDict=e.geoAtomDict,this.geoDict=e.geoDict)}atomColor(t){let e,i=t.resno+"";t.inscode&&(i+="^"+t.inscode),t.chainname&&(i+=":"+t.chainname),i+="/"+t.modelIndex;const r=this.geoAtomDict[i];if(void 0!==r){const i=r[t.atomname]||0;n=i,e=16843009*((n=(858993459&(n-=n>>1&1431655765))+(n>>2&858993459))+(n>>4)&252645135)>>24}else e=this.geoDict[i]||0;var n;return 0===e?2188972:1===e?16703627:2===e?16018755:e>=3?10813478:9474192}}Ll([Lt],Ql.prototype,"atomColor",null),Oe.add("geoquality",Ql);class Jl extends Nt{constructor(t){super(t),this.resHF={},t.scale||(this.parameters.scale="RdYlGn");for(const t in Jn)this.resHF[t]=Jn[t][0];if(this.defaultResidueHydrophobicity=ts[0],!t.domain){let t=1/0,e=-1/0;for(const i in this.resHF){const r=this.resHF[i];t=Math.min(t,r),e=Math.max(e,r)}this.parameters.domain=[t,0,e]}this.hfScale=this.getScale()}atomColor(t){return this.hfScale(this.resHF[t.resname]||this.defaultResidueHydrophobicity)}}Ll([Lt],Jl.prototype,"atomColor",null),Oe.add("hydrophobicity",Jl);class th extends Nt{constructor(t){super(t),t.scale||(this.parameters.scale="rainbow"),t.domain||(this.parameters.domain=[0,t.structure.modelStore.count]),this.modelindexScale=this.getScale()}atomColor(t){return this.modelindexScale(t.modelIndex)}}Ll([Lt],th.prototype,"atomColor",null),Oe.add("modelindex",th);class eh extends Nt{atomColor(t){switch(t.residueType.moleculeType){case 1:return 3697840;case 2:return 15729279;case 3:return 12496596;case 4:return 16629894;case 5:return 12540695;case 6:return 8374655;default:return 16777113}}}Ll([Lt],eh.prototype,"atomColor",null),Oe.add("moleculetype",eh);class ih extends Nt{constructor(t){super(t),t.scale||(this.parameters.scale="PuBu"),t.domain||(this.parameters.domain=[0,1]),this.occupancyScale=this.getScale()}atomColor(t){return this.occupancyScale(t.occupancy)}}Ll([Lt],ih.prototype,"atomColor",null),Oe.add("occupancy",ih);class rh extends Nt{constructor(t){super(t),t.scale||(this.parameters.scale="rwb"),t.domain||(this.parameters.domain=[-1,1]),this.partialchargeScale=this.getScale()}atomColor(t){return this.partialchargeScale(t.partialCharge||0)}}function nh(){return 16777215*Math.random()}Ll([Lt],rh.prototype,"atomColor",null),Oe.add("partialcharge",rh);class sh extends Nt{atomColor(){return nh()}volumeColor(){return nh()}positionColor(){return nh()}}Ll([Lt],sh.prototype,"atomColor",null),Ll([Lt],sh.prototype,"volumeColor",null),Ll([Lt],sh.prototype,"positionColor",null),Oe.add("random",sh);class oh extends Nt{constructor(t){super(t),this.rciDict={},t.scale||(this.parameters.scale="RdYlBu"),this.rciScale=this.getScale({domain:[.6,0]});const e=t.structure.validation;e&&(this.rciDict=e.rciDict)}atomColor(t){let e=`[${t.resname}]${t.resno}`;t.chainname&&(e+=":"+t.chainname);const i=this.rciDict[e];return void 0!==i?this.rciScale(i):9474192}}Ll([Lt],oh.prototype,"atomColor",null),Oe.add("randomcoilindex",oh);class ah extends Nt{constructor(t){super(t),this.scalePerChain={},t.scale||(this.parameters.scale="rainbow",this.parameters.reverse=rt(t.reverse,!0)),t.structure.eachChain((t=>{this.parameters.domain=[t.residueOffset,t.residueEnd],this.scalePerChain[t.index]=this.getScale()}))}atomColor(t){return this.scalePerChain[t.chainIndex](t.residueIndex)}}Ll([Lt],ah.prototype,"atomColor",null),Oe.add("residueindex",ah);const ch={ALA:9240460,ARG:124,ASN:16743536,ASP:10485826,CYS:16777072,GLN:16731212,GLU:6684672,GLY:16777215,HIS:7368959,ILE:19456,LEU:4546117,LYS:4671416,MET:12099650,PHE:5459026,PRO:5395026,SER:16740418,THR:12078080,TRP:5195264,TYR:9203788,VAL:16747775,ASX:16711935,GLX:16711935,ASH:16711935,GLH:16711935,A:14423100,G:3329330,I:10145074,X:8190976,C:16766720,T:4286945,U:4251856,D:35723,DA:14423100,DG:3329330,DI:10145074,DX:8190976,DC:16766720,DT:4286945,DU:4251856,DD:35723};class lh extends Nt{atomColor(t){return ch[t.resname]||16711935}}Ll([Lt],lh.prototype,"atomColor",null),Oe.add("resname",lh);const hh=16711808,uh=10485888,dh=6291584,mh=16762880,fh=6324479,ph=16777215,gh=11403518,yh=16580962,bh=10921722;class _h extends Nt{constructor(t){super(t),this.residueProxy=t.structure.getResidueProxy()}atomColor(t){const e=t.sstruc,i=this.residueProxy;return"h"===e?hh:"g"===e?uh:"i"===e?dh:"e"===e||"b"===e?mh:"t"===e?fh:(i.index=t.residueIndex,i.isDna()?gh:i.isRna()?yh:i.isSaccharide()?bh:i.isProtein()||"s"===e||"l"===e?ph:8421504)}}Ll([Lt],_h.prototype,"atomColor",null),Oe.add("sstruc",_h);class xh extends Nt{constructor(t){var e,i;super(t),t.scale||(this.parameters.scale="rwb"),this.atomData=null===(e=this.parameters.data)||void 0===e?void 0:e.atomData,this.bondData=null===(i=this.parameters.data)||void 0===i?void 0:i.bondData,this.scale=this.getScale(this.parameters)}atomColor(t){var e;const i=null===(e=this.atomData)||void 0===e?void 0:e[t.index];return void 0!==i?this.scale(i):this.parameters.value}bondColor(t,e){var i;const r=null===(i=this.bondData)||void 0===i?void 0:i[t.index];return void 0!==r?this.scale(r):this.atomProxy?(this.atomProxy.index=e?t.atomIndex1:t.atomIndex2,this.atomColor(this.atomProxy)):this.parameters.value}}Ll([Lt],xh.prototype,"atomColor",null),Ll([Lt],xh.prototype,"bondColor",null),Oe.add("structuredata",xh);class vh extends Nt{atomColor(){return this.parameters.value}bondColor(){return this.parameters.value}valueColor(){return this.parameters.value}volumeColor(){return this.parameters.value}}Ll([Lt],vh.prototype,"atomColor",null),Ll([Lt],vh.prototype,"bondColor",null),Ll([Lt],vh.prototype,"valueColor",null),Ll([Lt],vh.prototype,"volumeColor",null),Oe.add("uniform",vh);class wh extends Nt{constructor(t){super(t),this.valueScale=this.getScale()}volumeColor(t){return this.valueScale(this.parameters.volume.data[t])}}Ll([Lt],wh.prototype,"volumeColor",null),Oe.add("value",wh);class Ah extends Nt{constructor(t){super(t),this.vec=new e,this.valueScale=this.getScale()}positionColor(t){const e=this.parameters.volume;if(!e||!e.inverseMatrix)return this.parameters.value;const i=this.vec,r=e.data,n=e.nx,s=e.ny,o=n*s;i.copy(t),i.applyMatrix4(e.inverseMatrix);const a=Math.floor(i.x),c=Math.floor(i.y),l=Math.floor(i.z),h=(l*s+c)*n+a,u=h+1,d=h+n,m=h+o,f=d+1,p=m+1,g=d+o,y=g+1,b=r[h],_=r[u],x=r[d],v=r[m],w=r[f],A=r[p],S=r[g],C=r[y],P=i.x-a,I=i.y-c,k=i.z-l,M=Bt(b,_,P),T=Bt(v,A,P),D=Bt(x,w,P),B=Bt(S,C,P),F=Bt(M,D,I),E=Bt(T,B,I),$=Bt(F,E,k);return this.valueScale($)}}Ll([Lt],Ah.prototype,"positionColor",null),Oe.add("volume",Ah);class Sh extends Nr{constructor(t,e,i){const r=i||{};if(super(t,e,r),this.type="structure",this.parameters=Object.assign({radiusType:{type:"select",options:ma.types},radiusData:{type:"hidden"},radiusSize:{type:"number",precision:3,max:10,min:.001},radiusScale:{type:"number",precision:3,max:10,min:.001},assembly:null,defaultAssembly:{type:"hidden"}},this.parameters),this.selection=new me(r.sele),this.dataList=[],this.structure=t,this.structureView=this.structure.getView(this.selection),t.biomolDict){const e={default:"default","":t.unitcell?"AU":"FULL"};Object.keys(t.biomolDict).forEach((function(t){e[t]=t})),this.parameters.assembly={type:"select",options:e,rebuild:!0}}else this.parameters.assembly=null}get defaultScale(){return{vdw:1,covalent:1,bfactor:.01,sstruc:1}}init(t){const e=t||{};e.colorScheme=rt(e.colorScheme,"element"),this.setRadius(e.radius,e),this.radiusType=rt(e.radiusType,"vdw"),this.radiusData=rt(e.radiusData,{}),this.radiusSize=rt(e.radiusSize,1),this.radiusScale=rt(e.radiusScale,1),this.assembly=rt(e.assembly,"default"),this.defaultAssembly=rt(e.defaultAssembly,""),"auto"===e.quality&&(e.quality=this.getQuality()),super.init(e),this.selection.signals.stringChanged.add((()=>{this.build()})),this.build()}setRadius(t,e){const i=Object.keys(da);return"string"==typeof t&&i.includes(t.toLowerCase())?e.radiusType=t:void 0!==t&&(e.radiusType="size",e.radiusSize=t),this}getAssembly(){const t="default"===this.assembly?this.defaultAssembly:this.assembly;return this.structure.biomolDict[t]}getQuality(){let t;const e=this.structureView,i=this.getAssembly();t=i?i.getAtomCount(e):e.atomCount,Ae&&(t*=4);return e.atomStore.count/e.residueStore.count<2&&(t*=10),t<15e3?"high":t<8e4?"medium":"low"}create(){if(0===this.structureView.atomCount)return;if(!this.structureView.hasCoords())return void(this.needsBuild=!0);this.needsBuild=!1;const t=this.getAssembly();if(t)t.partList.forEach(((t,e)=>{const i=t.getView(this.structureView);if(0===i.atomCount)return;const r=this.createData(i,e);r&&(r.sview=i,r.instanceList=t.getInstanceList(),this.dataList.push(r))}));else{const t=this.createData(this.structureView,0);t&&(t.sview=this.structureView,this.dataList.push(t))}}update(t){!this.lazy||this.visible?this.needsBuild?this.build():this.dataList.forEach((e=>{e.bufferList.length>0&&this.updateData(t,e)}),this):Object.assign(this.lazyProps.what,t)}updateData(t,e){this.build()}getColorParams(){return Object.assign(Object.assign({},super.getColorParams()),{structure:this.structure})}getRadiusParams(t){return{type:this.radiusType,scale:this.radiusScale,size:this.radiusSize,data:this.radiusData}}getAtomParams(t,e){return Object.assign({what:t,colorParams:this.getColorParams(),radiusParams:this.getRadiusParams()},e)}getBondParams(t,e){return Object.assign({what:t,colorParams:this.getColorParams(),radiusParams:this.getRadiusParams()},e)}getAtomRadius(t){if(this.structureView.atomSet.isSet(t.index)){return new ma(this.getRadiusParams()).atomRadius(t)}return 0}setSelection(t,e){return this.selection.setString(t,e),this}setParameters(t,e={},i=!1){const r=t||{};return this.setRadius(r.radius,r),void 0===r.radiusType&&void 0===r.radiusData&&void 0===r.radiusSize&&void 0===r.radiusScale||(e.radius=!0,Pe&&!this.disableImpostor||(i=!0)),void 0!==r.defaultAssembly&&r.defaultAssembly!==this.defaultAssembly&&("default"===this.assembly&&void 0===r.assembly||"default"===r.assembly)&&(i=!0),super.setParameters(r,e,i),this}getParameters(){return Object.assign(super.getParameters(),{sele:this.selection?this.selection.string:void 0,defaultAssembly:this.defaultAssembly})}attach(t){const e=this.viewer,i=this.bufferList;this.dataList.forEach((function(t){t.bufferList.forEach((function(r){i.push(r),e.add(r,t.instanceList)}))})),this.setVisibility(this.visible),t()}clear(){this.dataList.length=0,super.clear()}dispose(){this.structureView.dispose(),super.dispose()}}class Ch extends Sh{constructor(t,e,i){super(t,e,i),this.n=0,this.parameters=Object.assign({labelVisible:{type:"boolean"},labelSize:{type:"number",precision:3,max:10,min:.001},labelColor:{type:"color"},labelFontFamily:{type:"select",options:{"sans-serif":"sans-serif",monospace:"monospace",serif:"serif"},buffer:"fontFamily"},labelFontStyle:{type:"select",options:{normal:"normal",italic:"italic"},buffer:"fontStyle"},labelFontWeight:{type:"select",options:{normal:"normal",bold:"bold"},buffer:"fontWeight"},labelsdf:{type:"boolean",buffer:"sdf"},labelXOffset:{type:"number",precision:1,max:20,min:-20,buffer:"xOffset"},labelYOffset:{type:"number",precision:1,max:20,min:-20,buffer:"yOffset"},labelZOffset:{type:"number",precision:1,max:20,min:-20,buffer:"zOffset"},labelAttachment:{type:"select",options:{"bottom-left":"bottom-left","bottom-center":"bottom-center","bottom-right":"bottom-right","middle-left":"middle-left","middle-center":"middle-center","middle-right":"middle-right","top-left":"top-left","top-center":"top-center","top-right":"top-right"},rebuild:!0},labelBorder:{type:"boolean",buffer:"showBorder"},labelBorderColor:{type:"color",buffer:"borderColor"},labelBorderWidth:{type:"number",precision:2,max:.3,min:0,buffer:"borderWidth"},labelBackground:{type:"boolean",rebuild:!0},labelBackgroundColor:{type:"color",buffer:"backgroundColor"},labelBackgroundMargin:{type:"number",precision:2,max:2,min:0,rebuild:!0},labelBackgroundOpacity:{type:"range",step:.01,max:1,min:0,buffer:"backgroundOpacity"},labelFixedSize:{type:"boolean",buffer:"fixedSize"},lineOpacity:{type:"range",min:0,max:1,step:.01},linewidth:{type:"integer",max:50,min:1,buffer:!0}},this.parameters,{flatShaded:null})}init(t){const e=t||{};this.labelVisible=rt(e.labelVisible,!0),this.labelSize=rt(e.labelSize,2),this.labelColor=rt(e.labelColor,16777215),this.labelFontFamily=rt(e.labelFontFamily,"sans-serif"),this.labelFontStyle=rt(e.labelFontstyle,"normal"),this.labelFontWeight=rt(e.labelFontWeight,"bold"),this.labelsdf=rt(e.labelsdf,"Chrome"===ve),this.labelXOffset=rt(e.labelXOffset,0),this.labelYOffset=rt(e.labelYOffset,0),this.labelZOffset=rt(e.labelZOffset,.5),this.labelAttachment=rt(e.labelAttachment,"bottom-left"),this.labelBorder=rt(e.labelBorder,!1),this.labelBorderColor=rt(e.labelBorderColor,"lightgrey"),this.labelBorderWidth=rt(e.labelBorderWidth,.15),this.labelBackground=rt(e.labelBackground,!1),this.labelBackgroundColor=rt(e.labelBackgroundColor,"lightgrey"),this.labelBackgroundMargin=rt(e.labelBackgroundMargin,.5),this.labelBackgroundOpacity=rt(e.labelBackgroundOpacity,1),this.labelFixedSize=rt(e.labelFixedSize,!1),this.lineOpacity=rt(e.lineOpacity,1),this.linewidth=rt(e.linewidth,2),super.init(e)}update(t){t.position?this.build():super.update(t)}updateData(t,e){const i={};if(t&&!t.labelSize||Object.assign(i,{size:Ai(this.n,this.labelSize)}),!t||t.labelColor){const t=new n(this.labelColor);Object.assign(i,{color:Si(this.n,t.r,t.g,t.b)})}this.textBuffer.setAttributes(i)}setParameters(t,e={},i=!1){return t&&t.labelSize&&(e.labelSize=!0),t&&(t.labelColor||0===t.labelColor)&&(e.labelColor=!0,i=!0),super.setParameters(t,e,i),t&&void 0!==t.opacity&&this.textBuffer.setParameters({opacity:1}),t&&void 0!==t.labelVisible&&this.setVisibility(this.visible),this}setVisibility(t,e){return super.setVisibility(t,!0),this.textBuffer&&this.textBuffer.setVisibility(this.labelVisible&&this.visible),e||this.viewer.requestRender(),this}getLabelBufferParams(t={}){return super.getBufferParams(Object.assign({fontFamily:this.labelFontFamily,fontStyle:this.labelFontStyle,fontWeight:this.labelFontWeight,sdf:this.labelsdf,xOffset:this.labelXOffset,yOffset:this.labelYOffset,zOffset:this.labelZOffset,attachment:this.labelAttachment,showBorder:this.labelBorder,borderColor:this.labelBorderColor,borderWidth:this.labelBorderWidth,showBackground:this.labelBackground,backgroundColor:this.labelBackgroundColor,backgroundMargin:this.labelBackgroundMargin,backgroundOpacity:this.labelBackgroundOpacity,fixedSize:this.labelFixedSize,disablePicking:!0,visible:this.labelVisible},t,{opacity:1}))}getAtomRadius(){return 0}}function Ph(t,e){const i=t.getAtomProxy(),r=new me,n=e.length;if(0===n)return new Float32Array(0);const s=e[0].length,o=t.getAtomSet(),a=new Float32Array(n*s*3);let c=0;return e.forEach((function(e){let n=!1;for(let l=0;l 1.0 ){\ngl_FragColor = vec4( backgroundColor, backgroundOpacity );\n}else{\nfloat sdf = texture2D( fontTexture, texCoord ).a;\nif( showBorder ) sdf += borderWidth;\nfloat a = smoothstep(padding - gamma, padding + gamma, sdf);\nif( a < 0.2 ) discard;\na *= opacity;\nvec3 outgoingLight = vColor;\nif( showBorder && sdf < ( padding + borderWidth ) ){\noutgoingLight = borderColor;\n}\ngl_FragColor = vec4( outgoingLight, a );\n}\n#if defined( PICKING )\nif( opacity < 0.3 )\ndiscard;\ngl_FragColor = vec4( vPickingColor, objectId );\n#else\n#include premultiplied_alpha_fragment\n#include tonemapping_fragment\n#include colorspace_fragment\n#include fog_fragment\n#endif\n}");const Th={};const Dh={font:"sans-serif",size:36,style:"normal",variant:"normal",weight:"normal",outline:3,width:1024,height:1024};class Bh{constructor(t={}){this.gamma=1,this.mapped={},this.scratchW=0,this.scratchH=0,this.currentX=0,this.currentY=0,this.cutoff=.25,this.parameters=nt(t,Dh);const e=this.parameters;this.radius=e.size/8,this.padding=e.size/3;const i=this.lineHeight=e.size+2*e.outline+Math.round(e.size/4),r=this.maxWidth=e.width/4,n=this.canvas=document.createElement("canvas");n.width=r,n.height=i;const s=this.context=this.canvas.getContext("2d",{willReadFrequently:!0});s.font=`${e.style} ${e.variant} ${e.weight} ${e.size}px ${e.font}`,s.fillStyle="black",s.textAlign="left",s.textBaseline="bottom",s.lineJoin="round",this.gridOuter=new Float64Array(i*r),this.gridInner=new Float64Array(i*r),this.f=new Float64Array(Math.max(i,r)),this.d=new Float64Array(Math.max(i,r)),this.z=new Float64Array(Math.max(i,r)+1),this.v=new Int16Array(Math.max(i,r)),this.data=new Uint8Array(e.width*e.height*4),this.canvas2=document.createElement("canvas"),this.canvas2.width=e.width,this.canvas2.height=e.height,this.context2=this.canvas2.getContext("2d"),this.placeholder=this.map(String.fromCharCode(65533));for(let t=32;t<=126;++t)this.map(String.fromCharCode(t));this.map(String.fromCharCode(176)),this.map(String.fromCharCode(8491)),this.texture=new H(this.canvas2),this.texture.flipY=!1,this.texture.needsUpdate=!0}map(t){const e=this.parameters;return void 0===this.mapped[t]&&(this.draw(t),this.currentX+this.scratchW>e.width&&(this.currentX=0,this.currentY+=this.scratchH),this.currentY+this.scratchH>e.height&&console.warn("canvas to small"),this.mapped[t]={x:this.currentX,y:this.currentY,w:this.scratchW,h:this.scratchH},this.context2.drawImage(this.canvas,0,0,this.scratchW,this.scratchH,this.currentX,this.currentY,this.scratchW,this.scratchH),this.currentX+=this.scratchW),this.mapped[t]}get(t){return this.mapped[t]||this.placeholder}draw(t){const e=this.parameters,i=this.lineHeight,r=e.outline,n=this.context,s=this.maxWidth,o=r,a=i-e.outline,c=n.measureText(t),l=Math.min(s,Math.ceil(c.width+2*o+1)),h=l*i;n.clearRect(0,0,l,i),n.fillText(t,o,a);const u=n.getImageData(0,0,l,i),d=u.data;for(let t=0;t= 0.0 ) {\ntrimSegment( start, end );\n} else if ( end.z < 0.0 && start.z >= 0.0 ) {\ntrimSegment( end, start );\n}\n}\nvec4 clipStart = projectionMatrix * start;\nvec4 clipEnd = projectionMatrix * end;\nvec2 ndcStart = clipStart.xy / clipStart.w;\nvec2 ndcEnd = clipEnd.xy / clipEnd.w;\nvec2 dir = ndcEnd - ndcStart;\ndir.x *= aspect;\ndir = normalize( dir );\nvec2 offset = vec2( dir.y, - dir.x );\ndir.x /= aspect;\noffset.x /= aspect;\nif ( mapping.x < 0.0 ) offset *= - 1.0;\noffset *= linewidth;\noffset /= resolution.y;\nvec4 clip = ( mapping.y < 0.5 ) ? clipStart : clipEnd;\noffset *= clip.w;\nclip.xy += offset;\ngl_Position = clip;\n#ifndef PICKING\nvViewPosition = ( projectionMatrixInverse * clip ).xyz;\n#endif\n#if defined( RADIUS_CLIP )\nvClipCenter = -( modelViewMatrix * vec4( clipCenter, 1.0 ) ).xyz;\n#endif\n#include nearclip_vertex\n}"),ze.add("shader/WideLine.frag","uniform vec3 diffuse;\nuniform float opacity;\nuniform float clipNear;\nuniform float clipRadius;\n#if defined( RADIUS_CLIP )\nvarying vec3 vClipCenter;\n#endif\n#ifdef PICKING\nuniform float objectId;\nvarying vec3 vPickingColor;\n#else\n#include common\n#include fog_pars_fragment\nvarying vec3 vViewPosition;\nvarying vec3 vColor;\nvarying vec3 vColor2;\nvarying float flag;\n#endif\nvoid main() {\n#include nearclip_fragment\n#include radiusclip_fragment\n#if defined( PICKING )\nif( opacity < 0.3 )\ndiscard;\ngl_FragColor = vec4( vPickingColor, objectId );\n#else\nvec3 outgoingLight = vec3( 0.0 );\nvec4 diffuseColor = vec4( diffuse, 1.0 );\nif ( flag < 0.0 ) {\ndiffuseColor.rgb *= vColor;\n} else {\ndiffuseColor.rgb *= vColor2;\n}\n#include alphatest_fragment\noutgoingLight = diffuseColor.rgb;\ngl_FragColor = vec4( outgoingLight, diffuseColor.a * opacity );\n#include premultiplied_alpha_fragment\n#include tonemapping_fragment\n#include colorspace_fragment\n#include fog_fragment\n#endif\n}");const Rh=Object.assign({linewidth:2},No),Lh=Object.assign({linewidth:{uniform:!0}},zo);class Nh extends Nc{constructor(e,r={}){super(e,r),this.parameterTypes=Lh,this.vertexShader="WideLine.vert",this.fragmentShader="WideLine.frag",!e.color2&&e.color&&(e.color2=e.color),this.addUniforms({linewidth:{value:this.parameters.linewidth},resolution:{value:new t},projectionMatrixInverse:{value:new i}}),this.addAttributes({position1:{type:"v3",value:null},position2:{type:"v3",value:null},color2:{type:"c",value:null}}),this.setAttributes(e),this.makeMapping()}get defaultParameters(){return Rh}setParameters(t){super.setParameters(t)}}je.add("wideline",Nh);class zh extends Ch{constructor(t,e,i){super(t,e,i),this.type="angle",this.parameters=Object.assign({atomTriple:{type:"hidden",rebuild:!0},vectorVisible:{type:"boolean",default:!0},arcVisible:{type:"boolean",default:!0},sectorVisible:{type:"boolean",default:!0}},this.parameters),this.init(i)}init(t){const e=t||{};e.side=rt(e.side,"double"),e.opacity=rt(e.opacity,.5),this.atomTriple=rt(e.atomTriple,[]),this.arcVisible=rt(e.arcVisible,!0),this.sectorVisible=rt(e.sectorVisible,!0),this.vectorVisible=rt(e.vectorVisible,!0),super.init(e)}createData(t){if(!t.atomCount||!this.atomTriple.length)return;const e=function(t,e){return function(t){const e=[],i=t.length/9;for(let r=0;r radius2) {\ndiscard;\n}\n#ifdef CAP\nsurface_point = front_point;\n_normal = axis;\n#else\nsurface_point = ray_target + ( (-a1 - sqrt(d)) / a2 ) * ray_direction;\ndNV = dot(-axis, ray_direction);\nnear = dot(axis, end) / dNV;\nnew_point2 = ray_direction * near + ray_origin;\nif (dot(new_point2 - end, new_point2-base) < radius2) {\ndiscard;\n}\ninterior = true;\n#endif\n}\nif( end_cap_test > 0.0 )\n{\nfloat dNV;\nfloat near;\nvec3 end_point;\nif ( ortho == 1.0 ) {\nend_point = ray_target;\n} else {\ndNV = dot(axis, ray_direction);\nif (dNV < 0.0) {\ndiscard;\n}\nnear = dot(axis, end) / dNV;\nend_point = ray_direction * near + ray_origin;\n}\nif( dot(end_point - end, end_point-base) > radius2 ) {\ndiscard;\n}\n#ifdef CAP\nsurface_point = end_point;\n_normal = axis;\n#else\nsurface_point = ray_target + ( (-a1 - sqrt(d)) / a2 ) * ray_direction;\ndNV = dot(-axis, ray_direction);\nnear = dot(-axis, (base)) / dNV;\nnew_point2 = ray_direction * near + ray_origin;\nif (dot(new_point2 - base, new_point2-base) < radius2) {\ndiscard;\n}\ninterior = true;\n#endif\n}\ngl_FragDepthEXT = calcDepth( surface_point );\n#ifdef NEAR_CLIP\nif( calcClip( surface_point ) > 0.0 ){\ndist = (-a1 - sqrt(d)) / a2;\nsurface_point = ray_target + dist * ray_direction;\nif( calcClip( surface_point ) > 0.0 ) {\ndiscard;\n}\ninterior = true;\ngl_FragDepthEXT = calcDepth( surface_point );\nif( gl_FragDepthEXT >= 0.0 ){\ngl_FragDepthEXT = max( 0.0, calcDepth( vec3( - ( clipNear - 0.5 ) ) ) + ( 0.0000001 / vRadius ) );\n}\n}else if( gl_FragDepthEXT <= 0.0 ){\ndist = (-a1 - sqrt(d)) / a2;\nsurface_point = ray_target + dist * ray_direction;\ninterior = true;\ngl_FragDepthEXT = calcDepth( surface_point );\nif( gl_FragDepthEXT >= 0.0 ){\ngl_FragDepthEXT = 0.0 + ( 0.0000001 / vRadius );\n}\n}\n#else\nif( gl_FragDepthEXT <= 0.0 ){\ndist = (-a1 - sqrt(d)) / a2;\nsurface_point = ray_target + dist * ray_direction;\ninterior = true;\ngl_FragDepthEXT = calcDepth( surface_point );\nif( gl_FragDepthEXT >= 0.0 ){\ngl_FragDepthEXT = 0.0 + ( 0.0000001 / vRadius );\n}\n}\n#endif\nif (gl_FragDepthEXT < 0.0) {\ndiscard;\n}\nif (gl_FragDepthEXT > 1.0) {\ndiscard;\n}\n#ifdef PICKING\nif( opacity < 0.3 )\ndiscard;\ngl_FragColor = vec4( vPickingColor, objectId );\n#else\nvec3 vViewPosition = -surface_point;\nvec3 vNormal = _normal;\nvec3 vColor;\nif( distSq3( surface_point, end ) < distSq3( surface_point, base ) ){\nif( b < 0.0 ){\nvColor = vColor1;\n}else{\nvColor = vColor2;\n}\n}else{\nif( b > 0.0 ){\nvColor = vColor1;\n}else{\nvColor = vColor2;\n}\n}\nvec4 diffuseColor = vec4( diffuse, opacity );\nReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\nvec3 totalEmissiveLight = emissive;\n#include color_fragment\n#include roughnessmap_fragment\n#include metalnessmap_fragment\nvec3 normal = normalize( vNormal );\nvec3 nonPerturbedNormal = normal;\n#include lights_physical_fragment\n#include lights_fragment_begin\n#include lights_fragment_end\nvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveLight;\nif( interior ){\n#ifdef USE_INTERIOR_COLOR\noutgoingLight.xyz = interiorColor;\n#else\n#ifdef DIFFUSE_INTERIOR\noutgoingLight.xyz = vColor;\n#endif\n#endif\noutgoingLight.xyz *= 1.0 - interiorDarkening;\n}\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );\n#include premultiplied_alpha_fragment\n#include tonemapping_fragment\n#include colorspace_fragment\n#include fog_fragment\n#endif\n}");const Xh=new Float32Array([-1,1,-1,-1,-1,-1,1,1,-1,1,1,1,1,-1,-1,1,-1,1]),Yh=new Uint16Array([0,1,2,1,4,2,2,4,3,4,5,3]);class Kh extends Oc{constructor(t,e={}){super("v3",t,e)}get mapping(){return Xh}get mappingIndices(){return Yh}get mappingIndicesSize(){return 12}get mappingSize(){return 6}get mappingItemSize(){return 3}}const Zh=Object.assign({openEnded:!1},No),Qh=Object.assign({openEnded:{updateShader:!0}},zo);class Jh extends Kh{constructor(t,e={}){super(t,e),this.parameterTypes=Qh,this.isImpostor=!0,this.vertexShader="CylinderImpostor.vert",this.fragmentShader="CylinderImpostor.frag",this.addUniforms({modelViewMatrixInverse:{value:new i},ortho:{value:0}}),this.addAttributes({position1:{type:"v3",value:null},position2:{type:"v3",value:null},color2:{type:"c",value:null},radius:{type:"f",value:null}}),this.setAttributes(t),this.makeMapping()}get defaultParameters(){return Zh}getDefines(t){const e=Kh.prototype.getDefines.call(this,t);return this.parameters.openEnded||(e.CAP=1),e}}Object.assign({disableImpostor:!1},Hh,Zh);const tu=class{constructor(t,e={}){return!t.color2&&t.color&&(t.color2=t.color),!Pe||e&&e.disableImpostor?new Wh(t,e):new Jh(t,e)}};je.add("cylinder",tu);class eu extends Sh{constructor(t,e,i){super(t,e,i),this.type="axes",this.parameters=Object.assign({radiusSize:{type:"number",precision:3,max:10,min:.001},sphereDetail:!0,radialSegments:!0,disableImpostor:!0,showAxes:{type:"boolean",rebuild:!0},showBox:{type:"boolean",rebuild:!0}},this.parameters,{assembly:null}),this.init(i)}init(t){const e=t||{};e.radiusSize=rt(e.radiusSize,.5),e.colorValue=rt(e.colorValue,"lightgreen"),e.useInteriorColor=rt(e.useInteriorColor,!0),this.showAxes=rt(e.showAxes,!0),this.showBox=rt(e.showBox,!1),super.init(e)}getPrincipalAxes(){let t;const e=this.getAssembly();return e&&(t=e.partList[0].getSelection()),this.structureView.getPrincipalAxes(t)}getAxesData(t){const i=this.getPrincipalAxes(),r=new n(this.colorValue);let s=0,o=0;this.showAxes&&(s+=6,o+=3),this.showBox&&(s+=8,o+=12);const a=new Float32Array(3*s),c=Si(s,r.r,r.g,r.b),l=Ai(s,this.radiusSize),h=new Float32Array(3*o),u=new Float32Array(3*o),d=Si(o,r.r,r.g,r.b),m=Ai(o,this.radiusSize);let f=0;if(this.showAxes){const t=function(t,e){t.toArray(a,2*f),e.toArray(a,2*f+3),t.toArray(h,f),e.toArray(u,f),f+=3};t(i.begA,i.endA),t(i.begB,i.endB),t(i.begC,i.endC)}if(this.showBox){const r=new e,{d1a:n,d2a:s,d3a:o,d1b:c,d2b:l,d3b:d}=i.getProjectedScaleForAtoms(t);let m=2*f;const p=function(t,e,n){r.copy(i.center).addScaledVector(i.normVecA,t).addScaledVector(i.normVecB,e).addScaledVector(i.normVecC,n),r.toArray(a,m),m+=3};p(n,s,o),p(n,s,d),p(n,l,d),p(n,l,o),p(c,l,d),p(c,l,o),p(c,s,o),p(c,s,d);let g=f;const y=function(t,e){r.fromArray(a,2*f+3*t).toArray(h,g),r.fromArray(a,2*f+3*e).toArray(u,g),g+=3};y(0,1),y(0,3),y(0,6),y(1,2),y(1,7),y(2,3),y(2,4),y(3,5),y(4,5),y(4,7),y(5,6),y(6,7)}const p=new Ys(i);return{vertex:{position:a,color:c,radius:l,picking:p},edge:{position1:h,position2:u,color:d,color2:d,radius:m,picking:p}}}create(){const t=this.getAxesData(this.structureView);this.sphereBuffer=new Uc(t.vertex,this.getBufferParams({sphereDetail:this.sphereDetail,disableImpostor:this.disableImpostor,dullInterior:!0})),this.cylinderBuffer=new tu(t.edge,this.getBufferParams({openEnded:!0,radialSegments:this.radialSegments,disableImpostor:this.disableImpostor,dullInterior:!0})),this.dataList.push({sview:this.structureView,bufferList:[this.sphereBuffer,this.cylinderBuffer]})}createData(t){}updateData(t,e){const i=this.getAxesData(e.sview),r={},n={};t&&!t.position||(Object.assign(r,{position:i.vertex.position}),Object.assign(n,{position1:i.edge.position1,position2:i.edge.position2})),t&&!t.color||(Object.assign(r,{color:i.vertex.color}),Object.assign(n,{color:i.edge.color,color2:i.edge.color})),t&&!t.radius||(Object.assign(r,{radius:i.vertex.radius}),Object.assign(n,{radius:i.edge.radius})),this.sphereBuffer.setAttributes(r),this.cylinderBuffer.setAttributes(n)}}Le.add("axes",eu);class iu extends Sh{constructor(t,e,i){super(t,e,i),this.type="ball+stick",this.parameters=Object.assign({sphereDetail:!0,radialSegments:!0,openEnded:!0,disableImpostor:!0,aspectRatio:{type:"number",precision:1,max:10,min:1},lineOnly:{type:"boolean",rebuild:!0},cylinderOnly:{type:"boolean",rebuild:!0},multipleBond:{type:"select",rebuild:!0,options:{off:"off",symmetric:"symmetric",offset:"offset"}},bondScale:{type:"number",precision:2,max:1,min:.01},bondSpacing:{type:"number",precision:2,max:2,min:.5},linewidth:{type:"integer",max:50,min:1,buffer:!0}},this.parameters),this.init(i)}init(t){var e=t||{};e.radiusType=rt(e.radiusType,"size"),e.radiusSize=rt(e.radiusSize,.15),e.useInteriorColor=rt(e.useInteriorColor,!0),this.aspectRatio=rt(e.aspectRatio,2),this.lineOnly=rt(e.lineOnly,!1),this.cylinderOnly=rt(e.cylinderOnly,!1),this.multipleBond=rt(e.multipleBond,"off"),this.bondSpacing=rt(e.bondSpacing,1),this.bondScale=rt(e.bondScale,.4),this.linewidth=rt(e.linewidth,2),super.init(e)}getAtomRadius(t){return this.aspectRatio*super.getAtomRadius(t)}getAtomParams(t,e){var i=super.getAtomParams(t,e);return i.radiusParams.scale*=this.aspectRatio,i}getAtomData(t,e,i){return t.getAtomData(this.getAtomParams(e,i))}getBondParams(t,e){return e=Object.assign({multipleBond:this.multipleBond,bondSpacing:this.bondSpacing,bondScale:this.bondScale},e),super.getBondParams(t,e)}getBondData(t,e,i){return t.getBondData(this.getBondParams(e,i))}createData(t){const e=[];if(this.lineOnly)this.lineBuffer=new Nh(this.getBondData(t,{position:!0,color:!0,picking:!0}),this.getBufferParams({linewidth:this.linewidth})),e.push(this.lineBuffer);else{const i=new tu(this.getBondData(t),this.getBufferParams({openEnded:this.openEnded,radialSegments:this.radialSegments,disableImpostor:this.disableImpostor,dullInterior:!0}));if(e.push(i),!this.cylinderOnly){const i=new Uc(this.getAtomData(t),this.getBufferParams({sphereDetail:this.sphereDetail,disableImpostor:this.disableImpostor,dullInterior:!0}));e.push(i)}}return{bufferList:e}}updateData(t,e){"off"!==this.multipleBond&&t&&t.radius&&(t.position=!0);const i=this.getBondData(e.sview,t);if(this.lineOnly){const r={};t&&!t.position||Object.assign(r,{position1:i.position1,position2:i.position2}),t&&!t.color||Object.assign(r,{color:i.color,color2:i.color2}),e.bufferList[0].setAttributes(r)}else{var r={};if(t&&!t.position||Object.assign(r,{position1:i.position1,position2:i.position2}),t&&!t.color||Object.assign(r,{color:i.color,color2:i.color2}),t&&!t.radius||Object.assign(r,{radius:i.radius}),e.bufferList[0].setAttributes(r),!this.cylinderOnly){var n=this.getAtomData(e.sview,t),s={};t&&!t.position||Object.assign(s,{position:n.position}),t&&!t.color||Object.assign(s,{color:n.color}),t&&!t.radius||Object.assign(s,{radius:n.radius}),e.bufferList[1].setAttributes(s)}}}setParameters(t={}){let e=!1;const i={};return(t.aspectRatio||t.bondSpacing||t.bondScale)&&(Object.assign(i,{radius:!0}),Pe&&!this.disableImpostor||(e=!0)),super.setParameters(t,i,e),this}}Le.add("ball+stick",iu);class ru extends iu{constructor(t,e,i){super(t,e,i),this.type="backbone",this.parameters=Object.assign({},this.parameters,{multipleBond:null,bondSpacing:null}),this.init(i)}init(t){var e=t||{};e.aspectRatio=rt(e.aspectRatio,1),e.radiusSize=rt(e.radiusSize,.25),super.init(e)}getAtomRadius(t){return t.isTrace()?super.getAtomRadius(t):0}getAtomData(t,e,i){return t.getBackboneAtomData(this.getAtomParams(e,i))}getBondData(t,e,i){return t.getBackboneBondData(this.getBondParams(e,i))}}Le.add("backbone",ru);class nu extends iu{constructor(t,e,i){super(t,e,i),this.type="base",this.parameters=Object.assign({},this.parameters,{multipleBond:null,bondSpacing:null})}init(t){let e=t||{};e.aspectRatio=rt(e.aspectRatio,1),e.radiusSize=rt(e.radiusSize,.3),super.init(e)}getAtomData(t,e,i){return t.getRungAtomData(this.getAtomParams(e,i))}getBondData(t,e,i){let r=this.getBondParams(e,i);return Object.assign(r.colorParams,{rung:!0}),t.getRungBondData(r)}}Le.add("base",nu);class su{constructor(t,i){this.m=t,this.tension=i,this.dt=1/this.m,this.delta=1e-4,this.vec1=new e,this.vec2=new e,this.vDir=new e,this.vTan=new e,this.vNorm=new e,this.vBin=new e,this.m2=Math.ceil(this.m/2)}interpolateToArr(t,e,i,r,n,s,o){s[o+0]=Ft(t.x,e.x,i.x,r.x,n,this.tension),s[o+1]=Ft(t.y,e.y,i.y,r.y,n,this.tension),s[o+2]=Ft(t.z,e.z,i.z,r.z,n,this.tension)}interpolateToVec(t,e,i,r,n,s){s.x=Ft(t.x,e.x,i.x,r.x,n,this.tension),s.y=Ft(t.y,e.y,i.y,r.y,n,this.tension),s.z=Ft(t.z,e.z,i.z,r.z,n,this.tension)}interpolatePosition(t,e,i,r,n,s){for(var o=0;o1&&(l=1),this.interpolateToVec(t,e,i,r,c,this.vec1),this.interpolateToVec(t,e,i,r,l,this.vec2),this.vec2.sub(this.vec1).normalize(),this.vec2.toArray(n,h)}}vectorSubdivide(t,e,i,r,n){let s,o=e.next(),a=e.next(),c=e.next();const l=e.size,h=l-1;let u=r||0;for(let r=0;r0&&e{if(t.residueCount<4)return;i.push(t);const r=this.getSpline(t),n=this.getAspectRatio(t),s=r.getSubdividedPosition(),o=r.getSubdividedOrientation(),a=r.getSubdividedColor(this.getColorParams()),c=r.getSubdividedPicking(),l=r.getSubdividedSize(this.getRadiusParams());e.push(new hu(Object.assign({},s,o,a,c,l),this.getBufferParams({radialSegments:this.radialSegments,aspectRatio:n,capped:this.capped})))}),t.getSelection()),{bufferList:e,polymerList:i}}updateData(t,e){De&&ke.time(this.type+" repr update"),t=t||{};for(var i=0,r=e.polymerList.length;i0;Zr(w,b,A);const n=Kr(w,x)<0;if(sn(w,x,Kr(x,_)),Zr(S,_,w),sn(w,x,Kr(x,v)),Zr(C,v,w),0===rn(S)||0===rn(C))continue;on(S,S),on(C,C);const B=s[T]=dn(S,C);a[T]=(_i*B).toFixed(1)+String.fromCharCode(176),Yr(k,S,x),on(k,k),Kr(k,C)<0&&un(k,k),Ih(w,A,S,k,B/2),tn(w,o,3*T);const F=Math.ceil(B/i),E=F+(e.extendLine?4:2),$=e.extendLine?36:0,O=new Float32Array(3*E),R=new Float32Array(3*E),L=new Float32Array(9*F),N=new Float32Array($);c[T]=O,l[T]=R,h[T]=L,u[T]=N,e.extendLine&&(r?(Zr(w,p,y),on(w,w),sn(P,w,1/Kr(S,w)),Qr(P,P,y)):(sn(P,_,1/Kr(S,_)),Qr(P,P,g)),n?(Zr(w,b,g),on(w,w),sn(I,w,1/Kr(C,w)),Qr(I,I,g)):(sn(I,v,1/Kr(C,v)),Qr(I,I,y))),Qr(M,A,S);let z=0;e.extendLine?(tn(p,O,z),tn(P,R,z),z+=3,tn(P,O,z),tn(M,R,z),z+=3,tn(P,N,0),tn(M,N,3),tn(r?y:g,N,6),tn(r?y:g,N,9),tn(M,N,12),tn(A,N,15)):(tn(A,O,z),tn(M,R,z),z+=3);const U=function(t,e){const i=9*e;tn(A,L,i),tn(M,L,i+3),tn(M,O,z),Ih(M,A,S,k,t),tn(M,L,i+6),tn(M,R,z),z+=3};let V=0;for(let t=i;t{const e=fu(i,t);Object.assign(t,e)})),e.side=rt(e.side,"double"),e.opacity=rt(e.opacity,.5),e.radiusType=rt(e.radiusType,"size"),e.radiusSize=rt(e.radiusSize,.15),super.init(e)}getHistogramBinBorderBufferParameters(){return this.getBufferParams({linewidth:this.histogramBinBorderWidth,visible:this.histogramBinBorderVisible,opacity:this.histogramBinBorderOpacity})}getBondArrowsBufferParameters(){return this.getBufferParams({linewidth:this.bondArrowWidth,visible:this.bondArrowVisible,opacity:this.bondArrowOpacity})}getOpaqueMiddleDiscBufferParameters(){return this.getBufferParams({visible:this.opaqueMiddleDiscVisible,opacity:this.opaqueMiddleDiscOpacity})}getHistogramBufferParameters(){return this.getBufferParams({visible:!0,opacity:this.histogramOpacity,side:"double"})}createData(t){if(!t.atomCount||!this.histogramsData.length)return;this.histogramsData.forEach((e=>e.atomPositions=Ph(t,[e.atomQuad])));const e=this.scaleBinToSectorArea?function(t){return Math.sqrt(t)}:function(t){return t};function i(t){const e=t.map((t=>t.length)),i=new Float32Array(Bi(e));let r=0;for(let e=0;et.startPoints))),position2:i(t.map((t=>t.endPoints))),color:i(t.map((t=>t.startColors))),color2:i(t.map((t=>t.endColors)))},e)}function n(t,e){return new Vo({position:i(t.map((t=>t.triangles))),color:i(t.map((t=>t.triangleColors)))},e)}this.histogramsData.forEach((t=>t.histogram360Scaled=t.histogram360.map(e)));const s=[];for(let t=0;t=3&&(e=yu(i)),void 0!==e&&s.push(e)}return this.frontHistogramBinBordersBuffer=r(s.map((t=>t.frontHistogramBinBorders)),this.getHistogramBinBorderBufferParameters()),this.backHistogramBinBordersBuffer=r(s.map((t=>t.backHistogramBinBorders)),this.getHistogramBinBorderBufferParameters()),this.adjacentBondArrowsBuffer=r(s.map((t=>t.adjacentBondArrows)),this.getBondArrowsBufferParameters()),this.distantBondArrowsBuffer=r(s.map((t=>t.distantBondArrows)),this.getBondArrowsBufferParameters()),this.opaqueMiddleDiscBuffer=n(s.map((t=>t.opaqueMiddleDisc)),this.getOpaqueMiddleDiscBufferParameters()),this.frontHistogramBuffer=n(s.map((t=>t.frontHistogram)),this.getHistogramBufferParameters()),this.backHistogramBuffer=n(s.map((t=>t.backHistogram)),this.getHistogramBufferParameters()),{bufferList:[].concat(this.frontHistogramBinBordersBuffer,this.backHistogramBinBordersBuffer,this.adjacentBondArrowsBuffer,this.distantBondArrowsBuffer,this.opaqueMiddleDiscBuffer,this.frontHistogramBuffer,this.backHistogramBuffer)}}setParameters(t){return super.setParameters(t,{},!1),t&&void 0!==t.histogramBinBorderVisible&&this.setVisibility(this.visible),this}setVisibility(t,e){return super.setVisibility(t,!0),this.frontHistogramBinBordersBuffer&&this.frontHistogramBinBordersBuffer.setVisibility(this.histogramBinBorderVisible),this.backHistogramBinBordersBuffer&&this.backHistogramBinBordersBuffer.setVisibility(this.histogramBinBorderVisible),e||this.viewer.requestRender(),this}}function yu(t){const e=t.atomPositions,i=t.histogram360Scaled,r=i.length<=180?360:2*i.length,n={triangles:new Float32Array(3*r*3),triangleColors:pu(t.opaqueMiddleDiscColor,3*r)},s={triangles:new Float32Array(3*i.length*3),triangleColors:pu(t.frontHistogramColor,3*i.length)},o={triangles:new Float32Array(3*i.length*3),triangleColors:pu(t.backHistogramColor,3*i.length)},a={startPoints:new Float32Array(3*i.length),endPoints:new Float32Array(3*i.length),startColors:pu(t.histogramBinBorderColor,i.length),endColors:pu(t.histogramBinBorderColor,i.length)},c={startPoints:new Float32Array(3*i.length),endPoints:new Float32Array(3*i.length),startColors:pu(t.histogramBinBorderColor,i.length),endColors:pu(t.histogramBinBorderColor,i.length)},l={startPoints:new Float32Array(6),endPoints:new Float32Array(6),startColors:pu(t.adjacentBondArrowColor,i.length),endColors:pu(t.adjacentBondArrowColor,i.length)},h={startPoints:new Float32Array(6),endPoints:new Float32Array(6),startColors:pu(t.distantBondArrowColor,i.length),endColors:pu(t.distantBondArrowColor,i.length)},u=Xr(),d=Xr(),m=Xr(),f=Xr(),p=Xr(),g=Xr(),y=Xr(),b=Xr(),_=Xr(),x=Xr(),v=Xr(),w=Xr(),A=Xr(),S=Xr(),C=Xr(),P=Xr(),I=[u,d,m,f];for(let t=0;t{let d=e[0],m=e[1];if("number"==typeof d&&Number.isInteger(d)&&"number"==typeof m&&Number.isInteger(m)){if(!u.get(d)||!u.get(m))return void(h+=1);c.index=d,l.index=m}else{s.setString(d),o.setString(m);var f=t.getAtomIndices(s),p=t.getAtomIndices(o);if(!f.length||!p.length)return void(h+=1);c.index=f[0],l.index=p[0]}a.addBond(c,l,1),i-=h;var g=c.distanceTo(l);switch(this.labelUnit){case"angstrom":r[i]=g.toFixed(2)+" "+String.fromCharCode(8491);break;case"nm":r[i]=(g/10).toFixed(2)+" nm";break;default:r[i]=g.toFixed(2)}var y=3*i;n[y+0]=(c.x+l.x)/2,n[y+1]=(c.y+l.y)/2,n[y+2]=(c.z+l.z)/2})),h>0&&(i-=h,n=n.subarray(0,3*i));var d=new En(a.count,!0);return{text:r,position:n,bondSet:d,bondStore:a}}getBondData(t,e,i){const r=t.getBondData(this.getBondParams(e,i));return r.picking&&(r.picking=new Js(r.picking.array,r.picking.structure,i.bondStore)),r}createData(t){if(!t.atomCount||!this.atomPair.length)return;const e=this.atomPair.length,i=new n(this.labelColor),r=this.getDistanceData(t,this.atomPair);this.textBuffer=new Oh({position:r.position,size:Ai(e,this.labelSize),color:Si(e,i.r,i.g,i.b),text:r.text},this.getLabelBufferParams());const s={bondSet:r.bondSet,bondStore:r.bondStore},o=this.getBondData(t,{position:!0,color:!0,picking:!0,radius:this.useCylinder},s);return this.useCylinder?this.distanceBuffer=new tu(o,this.getBufferParams({openEnded:this.openEnded,radialSegments:this.radialSegments,disableImpostor:this.disableImpostor,dullInterior:!0})):this.distanceBuffer=new Nh(fn(o),this.getBufferParams({linewidth:this.linewidth,visible:this.lineVisible,opacity:this.lineOpacity})),{bondSet:r.bondSet,bondStore:r.bondStore,position:r.position,bufferList:[this.textBuffer,this.distanceBuffer]}}updateData(t,e){super.updateData(t,e);const i={bondSet:e.bondSet,bondStore:e.bondStore},r=this.getBondData(e.sview,t,i),n={};t&&!t.color||Object.assign(n,{color:r.color,color2:r.color2}),t&&!t.radius||Object.assign(n,{radius:r.radius}),this.distanceBuffer.setAttributes(n)}setParameters(t){return super.setParameters(t,{},!1),this.useCylinder||(t&&t.lineOpacity&&this.distanceBuffer.setParameters({opacity:t.lineOpacity}),t&&void 0!==t.opacity&&this.distanceBuffer.setParameters({opacity:this.lineOpacity}),t&&t.linewidth&&this.distanceBuffer.setParameters({linewidth:t.linewidth})),this}}function _u(t){return 2*(t.position.length/3)*3}Le.add("distance",bu);const xu=Object.assign({scale:1,color:"grey"},No);class vu extends Uo{constructor(t,e={}){super({position:new Float32Array(_u(t)),color:new Float32Array(_u(t))},e),this.isLine=!0,this.vertexShader="Line.vert",this.fragmentShader="Line.frag";const i=new n(this.parameters.color),r=this.geometry.attributes;Si(_u(t)/3,i.r,i.g,i.b,r.color.array),this.setAttributes(t)}get defaultParameters(){return xu}setAttributes(t={}){const e=this.geometry.attributes;let i,r,n;t.position&&t.vector&&(i=t.position,r=t.vector,n=e.position.array,e.position.needsUpdate=!0);const s=this.size/2,o=this.parameters.scale;if(i&&r)for(let t=0;t{if(t.residueCount<4)return;i.push(t);const r=new Sa(t),n=r.getPosition(),s=r.getColor(this.getColorParams()),o=r.getSize(this.getRadiusParams()),a=r.getPicking();e.push(new Uc({position:n.center,color:s.color,radius:o.size,picking:a.picking},this.getBufferParams({sphereDetail:this.sphereDetail,disableImpostor:this.disableImpostor,dullInterior:!0})),new vu({position:n.center,vector:n.axis},this.getBufferParams({color:"skyblue",scale:1})),new vu({position:n.center,vector:n.resdir},this.getBufferParams({color:"lightgreen",scale:1})))}),t.getSelection()),{bufferList:e,polymerList:i}}updateData(t,e){De&&ke.time(this.type+" repr update"),t=t||{};for(let i=0,r=e.polymerList.length;i radius2) {\nspaceposition.y = mapping.y * 1.5 * radius1;\nspaceposition.x = mapping.x * 1.5 * radius1;\n} else {\nspaceposition.y = mapping.y * 1.5 * radius2;\nspaceposition.x = mapping.x * 1.5 * radius2;\n}\nspaceposition.w = 1.0;\nvec4 e3 = vec4( 1.0 );\nvec3 e1, e1_temp, e2, e2_temp;\ne3.xyz = normalize(position_atom1-position_atom2);\nif (e3.z == 0.0) { e3.z = 0.0000000000001;}\nif ( (position_atom1.x - position_atom2.x) == 0.0) { position_atom1.x += 0.001;}\nif ( (position_atom1.y - position_atom2.y) == 0.0) { position_atom1.y += 0.001;}\nif ( (position_atom1.z - position_atom2.z) == 0.0) { position_atom1.z += 0.001;}\nvec4 focus = vec4( 1.0 );\nfocus.x = ( position_atom1.x*position_atom1.x - position_atom2.x*position_atom2.x +\n( radius2*radius2 - radius1*radius1 )*e3.x*e3.x/shrink )/(2.0*(position_atom1.x - position_atom2.x));\nfocus.y = ( position_atom1.y*position_atom1.y - position_atom2.y*position_atom2.y +\n( radius2*radius2 - radius1*radius1 )*e3.y*e3.y/shrink )/(2.0*(position_atom1.y - position_atom2.y));\nfocus.z = ( position_atom1.z*position_atom1.z - position_atom2.z*position_atom2.z +\n( radius2*radius2 - radius1*radius1 )*e3.z*e3.z/shrink )/(2.0*(position_atom1.z - position_atom2.z));\ne1.x = 1.0;\ne1.y = 1.0;\ne1.z = ( (e3.x*focus.x + e3.y*focus.y + e3.z*focus.z) - e1.x*e3.x - e1.y*e3.y)/e3.z;\ne1_temp = e1 - focus.xyz;\ne1 = normalize(e1_temp);\ne2_temp = e1.yzx * e3.zxy - e1.zxy * e3.yzx;\ne2 = normalize(e2_temp);\nmat3 R= mat3( e1.xyz, e2.xyz, e3.xyz );\nvertex_position.xyz = R * spaceposition.xyz;\nvertex_position.w = 1.0;\nvertex_position.x += (position_atom1.x+position_atom2.x) / 2.0;\nvertex_position.y += (position_atom1.y+position_atom2.y) / 2.0;\nvertex_position.z += (position_atom1.z+position_atom2.z) / 2.0;\ngl_Position = modelViewProjectionMatrix * vertex_position;\nvec4 i_near, i_far;\nvec4 near = gl_Position;\nnear.z = 0.0 ;\nnear = modelViewProjectionMatrixInverse * near;\ni_near = near;\nvec4 far = gl_Position;\nfar.z = far.w ;\ni_far = modelViewProjectionMatrixInverse * far;\nprime1 = vec4( position_atom1 - (position_atom1 - focus.xyz)*shrink, 1.0 );\nprime2 = vec4( position_atom2 - (position_atom2 - focus.xyz)*shrink, 1.0 );\nfloat Rsquare = (radius1*radius1/shrink) - (\n(position_atom1.x - focus.x)*(position_atom1.x - focus.x) +\n(position_atom1.y - focus.y)*(position_atom1.y - focus.y) +\n(position_atom1.z - focus.z)*(position_atom1.z - focus.z)\n);\nfocus.w = Rsquare;\nmatrix_near = mat4( i_near, i_far, focus, e3 );\ngl_Position.z = 1.0;\n}"),ze.add("shader/HyperballStickImpostor.frag","#define STANDARD\n#define IMPOSTOR\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 interiorColor;\nuniform float interiorDarkening;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\nuniform float clipNear;\nuniform float shrink;\nuniform mat4 modelViewMatrix;\nuniform mat4 modelViewProjectionMatrix;\nuniform mat4 modelViewMatrixInverseTranspose;\nuniform mat4 projectionMatrix;\nvarying mat4 matrix_near;\nvarying vec4 prime1;\nvarying vec4 prime2;\nvarying float vRadius;\nvarying float vRadius2;\n#ifdef PICKING\nuniform float objectId;\nvarying vec3 vPickingColor;\n#else\nvarying vec3 vColor1;\nvarying vec3 vColor2;\n#include common\n#include fog_pars_fragment\n#include bsdfs\n#include lights_pars_begin\n#include lights_physical_pars_fragment\n#endif\nbool interior = false;\nfloat calcClip( vec4 cameraPos ){\nreturn dot( cameraPos, vec4( 0.0, 0.0, 1.0, clipNear - 0.5 ) );\n}\nfloat calcClip( vec3 cameraPos ){\nreturn calcClip( vec4( cameraPos, 1.0 ) );\n}\nfloat calcDepth( in vec3 cameraPos ){\nvec2 clipZW = cameraPos.z * projectionMatrix[2].zw + projectionMatrix[3].zw;\nreturn 0.5 + 0.5 * clipZW.x / clipZW.y;\n}\nstruct Ray {\nvec3 origin ;\nvec3 direction ;\n};\nbool cutoff_plane (vec3 M, vec3 cutoff, vec3 x3){\nfloat a = x3.x;\nfloat b = x3.y;\nfloat c = x3.z;\nfloat d = -x3.x*cutoff.x-x3.y*cutoff.y-x3.z*cutoff.z;\nfloat l = a*M.x+b*M.y+c*M.z+d;\nif (l<0.0) {return true;}\nelse{return false;}\n}\nvec3 isect_surf(Ray r, mat4 matrix_coef){\nvec4 direction = vec4(r.direction, 0.0);\nvec4 origin = vec4(r.origin, 1.0);\nfloat a = dot(direction,(matrix_coef*direction));\nfloat b = dot(origin,(matrix_coef*direction));\nfloat c = dot(origin,(matrix_coef*origin));\nfloat delta =b*b-a*c;\ngl_FragColor.a = 1.0;\nif (delta<0.0){\ndiscard;\n}\nfloat t1 =(-b-sqrt(delta))/a;\nreturn r.origin+t1*r.direction;\n}\nvec3 isect_surf2(Ray r, mat4 matrix_coef){\nvec4 direction = vec4(r.direction, 0.0);\nvec4 origin = vec4(r.origin, 1.0);\nfloat a = dot(direction,(matrix_coef*direction));\nfloat b = dot(origin,(matrix_coef*direction));\nfloat c = dot(origin,(matrix_coef*origin));\nfloat delta =b*b-a*c;\ngl_FragColor.a = 1.0;\nif (delta<0.0){\ndiscard;\n}\nfloat t2 =(-b+sqrt(delta))/a;\nreturn r.origin+t2*r.direction;\n}\nRay primary_ray(vec4 near1, vec4 far1){\nvec3 near=near1.xyz/near1.w;\nvec3 far=far1.xyz/far1.w;\nreturn Ray(near,far-near);\n}\nfloat update_z_buffer(vec3 M, mat4 ModelViewP){\nfloat depth1;\nvec4 Ms=(ModelViewP*vec4(M,1.0));\nreturn depth1=(1.0+Ms.z/Ms.w)/2.0;\n}\nvoid main(){\nfloat radius = max( vRadius, vRadius2 );\nvec4 i_near, i_far, focus;\nvec3 e3, e1, e1_temp, e2;\ni_near = vec4(matrix_near[0][0],matrix_near[0][1],matrix_near[0][2],matrix_near[0][3]);\ni_far = vec4(matrix_near[1][0],matrix_near[1][1],matrix_near[1][2],matrix_near[1][3]);\nfocus = vec4(matrix_near[2][0],matrix_near[2][1],matrix_near[2][2],matrix_near[2][3]);\ne3 = vec3(matrix_near[3][0],matrix_near[3][1],matrix_near[3][2]);\ne1.x = 1.0;\ne1.y = 1.0;\ne1.z = ( (e3.x*focus.x + e3.y*focus.y + e3.z*focus.z) - e1.x*e3.x - e1.y*e3.y)/e3.z;\ne1_temp = e1 - focus.xyz;\ne1 = normalize(e1_temp);\ne2 = normalize(cross(e1,e3));\nvec4 equation = focus;\nfloat shrinkfactor = shrink;\nfloat t1 = -1.0/(1.0-shrinkfactor);\nfloat t2 = 1.0/(shrinkfactor);\nvec4 colonne1, colonne2, colonne3, colonne4;\nmat4 mat;\nvec3 equation1 = vec3(t2,t2,t1);\nfloat A1 = - e1.x*equation.x - e1.y*equation.y - e1.z*equation.z;\nfloat A2 = - e2.x*equation.x - e2.y*equation.y - e2.z*equation.z;\nfloat A3 = - e3.x*equation.x - e3.y*equation.y - e3.z*equation.z;\nfloat A11 = equation1.x*e1.x*e1.x + equation1.y*e2.x*e2.x + equation1.z*e3.x*e3.x;\nfloat A21 = equation1.x*e1.x*e1.y + equation1.y*e2.x*e2.y + equation1.z*e3.x*e3.y;\nfloat A31 = equation1.x*e1.x*e1.z + equation1.y*e2.x*e2.z + equation1.z*e3.x*e3.z;\nfloat A41 = equation1.x*e1.x*A1 + equation1.y*e2.x*A2 + equation1.z*e3.x*A3;\nfloat A22 = equation1.x*e1.y*e1.y + equation1.y*e2.y*e2.y + equation1.z*e3.y*e3.y;\nfloat A32 = equation1.x*e1.y*e1.z + equation1.y*e2.y*e2.z + equation1.z*e3.y*e3.z;\nfloat A42 = equation1.x*e1.y*A1 + equation1.y*e2.y*A2 + equation1.z*e3.y*A3;\nfloat A33 = equation1.x*e1.z*e1.z + equation1.y*e2.z*e2.z + equation1.z*e3.z*e3.z;\nfloat A43 = equation1.x*e1.z*A1 + equation1.y*e2.z*A2 + equation1.z*e3.z*A3;\nfloat A44 = equation1.x*A1*A1 + equation1.y*A2*A2 + equation1.z*A3*A3 - equation.w;\ncolonne1 = vec4(A11,A21,A31,A41);\ncolonne2 = vec4(A21,A22,A32,A42);\ncolonne3 = vec4(A31,A32,A33,A43);\ncolonne4 = vec4(A41,A42,A43,A44);\nmat = mat4(colonne1,colonne2,colonne3,colonne4);\nRay ray = primary_ray(i_near,i_far) ;\nvec3 M;\nM = isect_surf(ray, mat);\nif (cutoff_plane(M, prime1.xyz, -e3) || cutoff_plane(M, prime2.xyz, e3)){ discard; }\nvec4 M1 = vec4(M,1.0);\nvec4 M2 = mat*M1;\nvec3 _normal = ( modelViewMatrixInverseTranspose * M2 ).xyz;\ngl_FragDepthEXT = update_z_buffer(M, modelViewProjectionMatrix) ;\n#ifdef NEAR_CLIP\nif( calcClip( modelViewMatrix * vec4( M, 1.0 ) ) > 0.0 ){\nM = isect_surf2(ray, mat);\nif( calcClip( modelViewMatrix * vec4( M, 1.0 ) ) > 0.0 )\ndiscard;\ninterior = true;\ngl_FragDepthEXT = update_z_buffer(M, modelViewProjectionMatrix) ;\nif( gl_FragDepthEXT >= 0.0 ){\ngl_FragDepthEXT = max( 0.0, calcDepth( vec3( - ( clipNear - 0.5 ) ) ) + ( 0.0000001 / radius ) );\n}\n}else if( gl_FragDepthEXT <= 0.0 ){\nM = isect_surf2(ray, mat);\ninterior = true;\ngl_FragDepthEXT = update_z_buffer(M, modelViewProjectionMatrix);\nif( gl_FragDepthEXT >= 0.0 ){\ngl_FragDepthEXT = 0.0 + ( 0.0000001 / radius );\n}\n}\n#else\nif( gl_FragDepthEXT <= 0.0 ){\nM = isect_surf2(ray, mat);\ninterior = true;\ngl_FragDepthEXT = update_z_buffer(M, modelViewProjectionMatrix) ;\nif( gl_FragDepthEXT >= 0.0 ){\ngl_FragDepthEXT = 0.0 + ( 0.0000001 / radius );\n}\n}\n#endif\nif (cutoff_plane(M, prime1.xyz, -e3) || cutoff_plane(M, prime2.xyz, e3)){ discard; }\nif (gl_FragDepthEXT < 0.0)\ndiscard;\nif (gl_FragDepthEXT > 1.0)\ndiscard;\nfloat distance_ratio = ((M.x-prime2.x)*e3.x + (M.y-prime2.y)*e3.y +(M.z-prime2.z)*e3.z) /\ndistance(prime2.xyz,prime1.xyz);\n#ifdef PICKING\nif( opacity < 0.3 )\ndiscard;\ngl_FragColor = vec4( vPickingColor, objectId );\n#else\nvec3 vViewPosition = -( modelViewMatrix * vec4( M, 1.0 ) ).xyz;\nvec3 vNormal = _normal;\nvec3 vColor;\nif( distance_ratio>0.5 ){\nvColor = vColor1;\n}else{\nvColor = vColor2;\n}\nvec4 diffuseColor = vec4( diffuse, opacity );\nReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\nvec3 totalEmissiveLight = emissive;\n#include color_fragment\n#include roughnessmap_fragment\n#include metalnessmap_fragment\nvec3 normal = normalize( vNormal );\nvec3 nonPerturbedNormal = normal;\n#include lights_physical_fragment\n#include lights_fragment_begin\n#include lights_fragment_end\nvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveLight;\nif( interior ){\n#ifdef USE_INTERIOR_COLOR\noutgoingLight.xyz = interiorColor;\n#else\n#ifdef DIFFUSE_INTERIOR\noutgoingLight.xyz = vColor;\n#endif\n#endif\noutgoingLight.xyz *= 1.0 - interiorDarkening;\n}\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );\n#include premultiplied_alpha_fragment\n#include tonemapping_fragment\n#include colorspace_fragment\n#include fog_fragment\n#endif\n}");const Su=new Float32Array([-1,-1,-1,1,-1,-1,1,-1,1,-1,-1,1,-1,1,-1,1,1,-1,1,1,1,-1,1,1]),Cu=new Uint16Array([0,1,2,0,2,3,1,5,6,1,6,2,4,6,5,4,7,6,0,7,4,0,3,7,0,5,1,0,4,5,3,2,6,3,6,7]);class Pu extends Oc{constructor(t,e={}){super("v3",t,e)}get mapping(){return Su}get mappingIndices(){return Cu}get mappingIndicesSize(){return 36}get mappingSize(){return 8}get mappingItemSize(){return 3}}const Iu=Object.assign({shrink:.14},No),ku=Object.assign({shrink:{uniform:!0}},zo);class Mu extends Pu{constructor(t,e={}){super(t,e),this.parameterTypes=ku,this.isImpostor=!0,this.vertexShader="HyperballStickImpostor.vert",this.fragmentShader="HyperballStickImpostor.frag",this.addUniforms({modelViewProjectionMatrix:{value:new i},modelViewProjectionMatrixInverse:{value:new i},modelViewMatrixInverseTranspose:{value:new i},shrink:{value:this.parameters.shrink}}),this.addAttributes({position1:{type:"v3",value:null},position2:{type:"v3",value:null},color2:{type:"c",value:null},radius:{type:"f",value:null},radius2:{type:"f",value:null}}),this.setAttributes(t),this.makeMapping()}get defaultParameters(){return Iu}}Object.assign({disableImpostor:!1},Hh,Iu);const Tu=class{constructor(t,e={}){return!Pe||e&&e.disableImpostor?(t.radius=function(t,e){const i=t.length,r=new Float32Array(i);for(let n=0;na.push(r.atomLabel(t)))))}else if("residue"===this.labelGrouping){e&&!e.position||(c=[]),e&&!e.color||(h=[]),e&&!e.radius||(l=[]),e&&!e.text||(a=[]),i.colorParams&&(i.colorParams.structure=t.getStructure());const u=Oe.getScheme(i.colorParams),d=new ma(i.radiusParams),m=t.getAtomProxy();let f=0;t.eachResidue((t=>{const i=3*f;t.isProtein()||t.isNucleic()?(m.index=t.traceAtomIndex,e&&!e.position||m.positionToArray(c,i)):(m.index=t.atomOffset,e&&!e.position||t.positionToArray(c,i)),e&&!e.color||u.atomColorToArray(m,h,i),e&&!e.radius||(l[f]=d.atomRadius(m)),e&&!e.text||a.push(r.atomLabel(m)),++f})),e&&!e.position||(n=new Float32Array(c)),e&&!e.color||(o=new Float32Array(h)),e&&!e.radius||(s=new Float32Array(l))}return{position:n,size:s,color:o,text:a}}createData(t){return{bufferList:[new Oh(this.getTextData(t,{position:!0,color:!0,radius:!0,text:!0}),this.getBufferParams({fontFamily:this.fontFamily,fontStyle:this.fontStyle,fontWeight:this.fontWeight,xOffset:this.xOffset,yOffset:this.yOffset,zOffset:this.zOffset,attachment:this.attachment,showBorder:this.showBorder,borderColor:this.borderColor,borderWidth:this.borderWidth,showBackground:this.showBackground,backgroundColor:this.backgroundColor,backgroundMargin:this.backgroundMargin,backgroundOpacity:this.backgroundOpacity,fixedSize:this.fixedSize}))]}}updateData(t,e){e.bufferList[0].setAttributes(this.getTextData(e.sview,t))}getAtomRadius(){return 0}}function Eu(t){const e=t.getAtomSet(),i=t.getBondSet(),r=t.getBondProxy();return i.forEach((function(t){r.index=t,e.clear(r.atomIndex1),e.clear(r.atomIndex2)})),e}Le.add("label",Fu);class $u extends Sh{constructor(t,e,i){super(t,e,i),this.type="line",this.parameters=Object.assign({multipleBond:{type:"select",rebuild:!0,options:{off:"off",symmetric:"symmetric",offset:"offset"}},bondSpacing:{type:"number",precision:2,max:2,min:.5},linewidth:{type:"integer",max:50,min:1,buffer:!0},lines:{type:"boolean",rebuild:!0},crosses:{type:"select",rebuild:!0,options:{off:"off",lone:"lone",all:"all"}},crossSize:{type:"number",precision:2,max:2,min:.1}},this.parameters,{flatShaded:null,side:null,wireframe:null,roughness:null,metalness:null}),this.init(i)}init(t){var e=t||{};this.multipleBond=rt(e.multipleBond,"off"),this.bondSpacing=rt(e.bondSpacing,1),this.linewidth=rt(e.linewidth,2),this.lines=rt(e.lines,!0),this.crosses=rt(e.crosses,"lone"),this.crossSize=rt(e.crossSize,.4),super.init(e)}getAtomRadius(t){return.1}getBondParams(t,e){return e=Object.assign({multipleBond:this.multipleBond,bondSpacing:this.bondSpacing,radiusParams:{type:"size",size:.1,scale:1}},e),super.getBondParams(t,e)}_crossData(t,e){if(t&&!t.position&&!t.color)return;const i={};"lone"===this.crosses&&Object.assign(i,{atomSet:Eu(e)});const r=e.getAtomData(this.getAtomParams(t,i)),n={},s=r.position,o=r.color,a=r.picking,c=(s||o).length,l=3*c;let h=new Float32Array(0),u=new Float32Array(0),d=new Float32Array(0),m=new Float32Array(0),f=0,p=new Float32Array(0);t&&!t.position||(h=n.position1=new Float32Array(l),u=n.position2=new Float32Array(l),f=this.crossSize/2),t&&!t.color||(d=n.color=new Float32Array(l),m=n.color2=new Float32Array(l)),t&&!t.picking||(p=new Float32Array(3*r.picking.array.length));for(let e=0;el?d[p]=-1:(c=Math.sqrt(l-a),d[p]=Math.floor(c)),++p;f[g]=u,m[g]=d}}function k(i){var r,n,s,a,u,p,b,x,v,w,S,C,P,I,k,M,T,D,B=3*i,F=i;r=Math.floor(.5+o*(t[B]+d[0])),n=Math.floor(.5+o*(t[B+1]+d[1])),s=Math.floor(.5+o*(t[B+2]+d[2]));var E,$=e[F],O=m[$],R=0,L=l*h,N=f[$];for(w=0;w=c||I>=l||k>=h)){var z=P*L+I*h+k;if(g)if(y[z]&A){if(y[z]&A){var U=_[z];U!==B&&b*b+x*x+v*v<(a=r+b-Math.floor(.5+o*(t[U]+d[0])))*a+(u=n+x-Math.floor(.5+o*(t[U+1]+d[1])))*u+(p=s+v-Math.floor(.5+o*(t[U+2]+d[2])))*p&&(_[z]=i)}}else y[z]|=A,_[z]=i;else y[z]|=A}R++}}function M(e){var i,r;for(console.time("EDTSurface fillvoxels"),i=0,r=y.length;i=c||A>=l||C>=h)){var L=w*R+A*h+C;if(y[L]&S){if(g){var N=_[L];b*b+x*x+v*v<(a=Math.floor(.5+o*(t[N]+d[0])))*a+(u=Math.floor(.5+o*(t[N+1]+d[1])))*u+(p=Math.floor(.5+o*(t[N+2]+d[2])))*p&&(_[L]=i)}}else y[L]|=S,g&&(_[L]=i)}$++}}function D(){var t,e,i,r;console.time("EDTSurface fastdistancemap");var n,s=Ou(c,l,h,Uint16Array,3),o=l*h,u=p*p,d=0;for(t=0;t0);var w,P=a*a,I=new Uint16Array(3);for(t=0;t=P)||(y[n]|=C,g&&y[n]&S&&(s.toArray(t,e,i,I),w=I[0]*o+I[1]*h+I[2],_[n]=_[w])));console.timeEnd("EDTSurface fastdistancemap")}function B(t,e,i,r){var n,s,o,a,u,d,m,f,p,g,_,x,v=new Uint16Array(3),w=0;if(0===i)return w;var I=-1,k=-1,M=-1,T=l*h;for(m=0,p=i;m-1&&k-1&&M-1&&(y[_=I*T+h*k+M]&A&&!(y[_]&S)?(e.fromArray(I,k,M,v),g=(a=I-v[0])*a+(u=k-v[1])*u+(d=M-v[2])*d,b[_]=g,y[_]|=S,y[_]|=C,r[w]=I,r[w+1]=k,r[w+2]=M,w+=3):y[_]&A&&y[_]&S&&(g=(a=I-v[0])*a+(u=k-v[1])*u+(d=M-v[2])*d)-1&&k-1&&M-1&&(y[_=I*T+h*k+M]&A&&!(y[_]&S)?(e.fromArray(I,k,M,v),g=(a=I-v[0])*a+(u=k-v[1])*u+(d=M-v[2])*d,b[_]=g,y[_]|=S,y[_]|=C,r[w]=I,r[w+1]=k,r[w+2]=M,w+=3):y[_]&A&&y[_]&S&&(g=(a=I-v[0])*a+(u=k-v[1])*u+(d=M-v[2])*d)-1&&k-1&&M-1&&(y[_=I*T+h*k+M]&A&&!(y[_]&S)?(e.fromArray(I,k,M,v),g=(a=I-v[0])*a+(u=k-v[1])*u+(d=M-v[2])*d,b[_]=g,y[_]|=S,y[_]|=C,r[w]=I,r[w+1]=k,r[w+2]=M,w+=3):y[_]&A&&y[_]&S&&(g=(a=I-v[0])*a+(u=k-v[1])*u+(d=M-v[2])*d)-1&&o-1&&u-1&&aT&&(T=E)}return{neighbourListLength:27*T+1,withinRadii:function(n,s,o,a,u){for(var d=0,m=f(n,c),p=f(s,l),g=f(o,h),y=Math.max(0,m-1),v=Math.max(0,p-1),A=Math.max(0,g-1),S=Math.min(b,m+2),C=Math.min(_,p+2),M=Math.min(x,g+2),T=y;Td&&(d=h[t]);!function(){const t=Bo(c,l,d,f,0);f=t.scaleFactor,y=t.dim,b=t.matrix,F=Math.max(5,2+Math.floor(m*f)),_=Ai(y[0]*y[1]*y[2],-1001),x=new Int32Array(_.length),v=new Float32Array(y[0]),w=new Float32Array(y[1]),A=new Float32Array(y[2]),$(v,c[0],1/f),$(w,c[1],1/f),$(A,c[2],1/f)}(),function(){var t=0,e=2*Math.PI/g;C=new Float32Array(g),S=new Float32Array(g);for(var i=0;i=0;){if(s!==r&&s!==n&&R(s,t,e,i))return k=s,s;s=I[++o]}return k=-1,-1}function R(e,i,r,n){var s=3*e,o=u[e],a=t[s]-i,c=t[s+1]-r,l=t[s+2]-n;return a*a+c*c+l*l0&&d=0;)t{e(this._makeSurface(t.data.sd,i))}),(t=>{console.warn("MolecularSurface.getSurfaceWorker error - trying without worker",t),this.worker.terminate(),this.worker=void 0;const r=this.getSurface(i);e(r)}))}else{const t=this.getSurface(i);e(t)}}dispose(){this.worker&&this.worker.terminate()}}class Uu extends Sh{constructor(t,e,i){super(t,e,i),this.type="surface",this.parameters=Object.assign({surfaceType:{type:"select",rebuild:!0,options:{vws:"vws",sas:"sas",ms:"ms",ses:"ses",av:"av"}},probeRadius:{type:"number",precision:1,max:20,min:0,rebuild:!0},smooth:{type:"integer",precision:1,max:10,min:0,rebuild:!0},scaleFactor:{type:"number",precision:1,max:5,min:0,rebuild:!0},cutoff:{type:"number",precision:2,max:50,min:0,rebuild:!0},contour:{type:"boolean",rebuild:!0},background:{type:"boolean",rebuild:!0},opaqueBack:{type:"boolean",buffer:!0},filterSele:{type:"text",rebuild:!0},colorVolume:{type:"hidden"},useWorker:{type:"boolean",rebuild:!0}},this.parameters,{radius:null,scale:null}),this.__infoList=[],this.structure.signals.refreshed.add((()=>{this.__forceNewMolsurf=!0})),this.toBePrepared=!0,this.init(i)}init(t){const e=t||{};e.colorScheme=rt(e.colorScheme,"uniform"),e.colorValue=rt(e.colorValue,14540253),e.disablePicking=rt(e.disablePicking,!0),this.surfaceType=rt(e.surfaceType,"ms"),this.probeRadius=rt(e.probeRadius,1.4),this.smooth=rt(e.smooth,2),this.scaleFactor=rt(e.scaleFactor,2),this.cutoff=rt(e.cutoff,0),this.contour=rt(e.contour,!1),this.background=rt(e.background,!1),this.opaqueBack=rt(e.opaqueBack,!0),this.filterSele=rt(e.filterSele,""),this.colorVolume=rt(e.colorVolume,void 0),this.useWorker=rt(e.useWorker,!0),super.init(t)}prepareData(t,i,r){let n=this.__infoList[i];if(n||(n={},this.__infoList[i]=n),n.molsurf&&n.sele===t.selection.string)r(i);else{if(this.filterSele){const n=t.structure.getView(new me(this.filterSele)),s=n.boundingBox.getSize(new e),o=Math.max(s.x,s.y,s.z),a=t.getAtomSetWithinPoint(n.center,o/2+6);if(0===(t=t.getView(new me(t.getAtomSetWithinSelection(a,3).toSeleString()))).atomCount)return void r(i)}n.sele=t.selection.string,n.molsurf=new zu(t);const s=this.getSurfaceParams(),o=t=>{n.surface=t,r(i)};this.useWorker?n.molsurf.getSurfaceWorker(s,o):o(n.molsurf.getSurface(s))}}prepare(t){if((this.__forceNewMolsurf||this.__sele!==this.selection.string||this.__surfaceParams!==JSON.stringify(this.getSurfaceParams()))&&(this.__infoList.forEach((t=>{t&&t.molsurf&&t.molsurf.dispose()})),this.__infoList.length=0),0===this.structureView.atomCount)return void t();const e=()=>{this.__sele=this.selection.string,this.__surfaceParams=JSON.stringify(this.getSurfaceParams()),this.__forceNewMolsurf=!1,t()},i="default"===this.assembly?this.defaultAssembly:this.assembly,r=this.structure.biomolDict[i];r?r.partList.forEach(((t,i)=>{const n=t.getView(this.structureView);this.prepareData(n,i,(t=>{t===r.partList.length-1&&e()}))})):this.prepareData(this.structureView,0,e)}createData(t,e){const i=this.__infoList[e],r=i.surface;if(!r)return;const n={position:r.getPosition(),color:r.getColor(this.getColorParams()),index:r.getFilteredIndex(this.filterSele,t)},s=[];if(r.contour){const t=new Wo(n,this.getBufferParams({wireframe:!1}));s.push(t)}else{Object.assign(n,{normal:r.getNormal(),picking:r.getPicking(t.getStructure())});const e=new jo(n,this.getBufferParams({background:this.background,opaqueBack:this.opaqueBack,dullInterior:!1}));if("double"==this.getBufferParams().side){const t=new qo(e);s.push(t)}else s.push(e)}return{bufferList:s,info:i}}updateData(t,e){const i={};if(t.position||t.radius)return this.__forceNewMolsurf=!0,void this.build();t.color&&(i.color=e.info.surface.getColor(this.getColorParams())),t.index&&(i.index=e.info.surface.getFilteredIndex(this.filterSele,e.sview)),e.bufferList[0].setAttributes(i)}setParameters(t,e={},i){return t&&t.filterSele&&(e.index=!0),t&&void 0!==t.colorVolume&&(e.color=!0),t&&t.wireframe&&(t.contour||void 0===t.contour&&this.contour)&&(t.wireframe=!1),super.setParameters(t,e,i),this}getSurfaceParams(t={}){return Object.assign({type:this.surfaceType,probeRadius:this.probeRadius,scaleFactor:this.scaleFactor,smooth:this.smooth&&!this.contour,cutoff:this.cutoff,contour:this.contour,useWorker:this.useWorker,radiusParams:this.getRadiusParams()},t)}getColorParams(){const t=super.getColorParams();return t.volume=this.colorVolume,t}getAtomRadius(){return 0}clear(){super.clear()}dispose(){this.__infoList.forEach((t=>{t&&t.molsurf&&t.molsurf.dispose()})),this.__infoList.length=0,super.dispose()}}Le.add("surface",Uu);class Vu extends Sh{constructor(t,e,i){super(t,e,i),this.type="point",this.parameters=Object.assign({pointSize:{type:"number",precision:1,max:100,min:0,buffer:!0},sizeAttenuation:{type:"boolean",buffer:!0},sortParticles:{type:"boolean",rebuild:!0},useTexture:{type:"boolean",buffer:!0},alphaTest:{type:"range",step:.001,max:1,min:0,buffer:!0},forceTransparent:{type:"boolean",buffer:!0},edgeBleach:{type:"range",step:.001,max:1,min:0,buffer:!0}},this.parameters,{flatShaded:null,wireframe:null,linewidth:null,side:null,roughness:null,metalness:null}),this.init(i)}init(t){var e=t||{};this.pointSize=rt(e.pointSize,1),this.sizeAttenuation=rt(e.sizeAttenuation,!0),this.sortParticles=rt(e.sortParticles,!1),this.useTexture=rt(e.useTexture,!1),this.alphaTest=rt(e.alphaTest,.5),this.forceTransparent=rt(e.forceTransparent,!1),this.edgeBleach=rt(e.edgeBleach,0),super.init(e)}createData(t){var e=t.getAtomData(this.getAtomParams({position:!0,color:!0,picking:!0}));return{bufferList:[new Hc(e,this.getBufferParams({pointSize:this.pointSize,sizeAttenuation:this.sizeAttenuation,sortParticles:this.sortParticles,useTexture:this.useTexture,alphaTest:this.alphaTest,forceTransparent:this.forceTransparent,edgeBleach:this.edgeBleach}))]}}updateData(t,e){var i=e.sview.getAtomData(this.getAtomParams(t)),r={};t&&!t.position||Object.assign(r,{position:i.position}),t&&!t.color||Object.assign(r,{color:i.color}),e.bufferList[0].setAttributes(r)}getAtomRadius(){return.1}}Le.add("point",Vu),ze.add("shader/Ribbon.vert","#define STANDARD\nuniform float clipNear;\nuniform vec3 clipCenter;\n#if defined( NEAR_CLIP ) || defined( RADIUS_CLIP ) || !defined( PICKING )\nvarying vec3 vViewPosition;\n#endif\n#if defined( RADIUS_CLIP )\nvarying vec3 vClipCenter;\n#endif\nattribute vec3 dir;\nattribute float size;\n#ifdef PICKING\n#include unpack_color\nattribute float primitiveId;\nvarying vec3 vPickingColor;\n#else\n#include color_pars_vertex\n#ifndef FLAT_SHADED\nvarying vec3 vNormal;\n#endif\n#endif\n#include common\nvoid main(void){\n#ifdef PICKING\nvPickingColor = unpackColor( primitiveId );\n#else\n#include color_vertex\n#include beginnormal_vertex\n#include defaultnormal_vertex\n#ifndef FLAT_SHADED\nvNormal = normalize( transformedNormal );\n#endif\n#endif\n#include begin_vertex\ntransformed += normalize( dir ) * size;\n#include project_vertex\n#if defined( NEAR_CLIP ) || defined( RADIUS_CLIP ) || !defined( PICKING )\nvViewPosition = -mvPosition.xyz;\n#endif\n#if defined( RADIUS_CLIP )\nvClipCenter = -( modelViewMatrix * vec4( clipCenter, 1.0 ) ).xyz;\n#endif\n#include nearclip_vertex\n}");const ju=new Uint16Array([0,1,2,1,3,2]);function Gu(t){return 3*(4*(t.position.length/3-1))}class Hu extends Vo{constructor(t,e={}){super({position:new Float32Array(Gu(t)),color:new Float32Array(Gu(t)),index:bt(Gu(t),Gu(t)/3),normal:new Float32Array(Gu(t)),picking:t.picking},e),this.vertexShader="Ribbon.vert";const i=t.position.length/3-1,r=4*i,n=3*r;this.addAttributes({dir:{type:"v3",value:new Float32Array(n)}}),this.addAttributes({size:{type:"f",value:new Float32Array(r)}}),t.primitiveId=Ci(i),this.setAttributes(t),this.makeIndex()}setAttributes(t={}){const e=this.size/4,i=this.geometry.attributes;let r,n,s,o,a,c,l,h,u,d,m,f,p,g,y,b,_,x,v;t.position&&(r=t.position,l=i.position.array,i.position.needsUpdate=!0),t.normal&&(n=t.normal,h=i.normal.array,i.normal.needsUpdate=!0),t.size&&(s=t.size,u=i.size.array,i.size.needsUpdate=!0),t.dir&&(o=t.dir,d=i.dir.array,i.dir.needsUpdate=!0),t.color&&(a=t.color,m=i.color.array,i.color.needsUpdate=!0),t.primitiveId&&(c=t.primitiveId,f=i.primitiveId.array,i.primitiveId.needsUpdate=!0);let w=s?s[0]:null;for(p=0;p{if(!(t.residueCount<4)){i.push(t);var r=new ou(t,this.getSplineParams()),n=r.getSubdividedPosition(),s=r.getSubdividedOrientation(),o=r.getSubdividedColor(this.getColorParams()),a=r.getSubdividedPicking(),c=r.getSubdividedSize(this.getRadiusParams());e.push(new Hu({position:n.position,normal:s.binormal,dir:s.normal,color:o.color,size:c.size,picking:a.picking},this.getBufferParams()))}}),t.getSelection()),{bufferList:e,polymerList:i}}updateData(t,e){t=t||{};var i=0,r=e.polymerList.length;for(i=0;i{if(t.residueCount<4||t.isNucleic())return;const n=new Ca(t),s=n.getAxis(this.localAngle,this.centerDist,this.ssBorder,this.getColorParams(),this.getRadiusParams());e+=s.size.length,i.push(s),r.push(n)}),t.getSelection());const n={begin:new Float32Array(3*e),end:new Float32Array(3*e),size:new Float32Array(e),color:new Float32Array(3*e),picking:{}};let s=new Float32Array(e),o=0;i.forEach((function(t){n.begin.set(t.begin,3*o),n.end.set(t.end,3*o),n.size.set(t.size,o),n.color.set(t.color,3*o),s.set(t.picking.array,o),o+=t.size.length})),e&&(n.picking=new Xs(s,t.getStructure()));return{bufferList:[new tu({position1:n.begin,position2:n.end,color:n.color,color2:n.color,radius:n.size,picking:n.picking},this.getBufferParams({openEnded:this.openEnded,radialSegments:this.radialSegments,disableImpostor:this.disableImpostor,dullInterior:!0}))],axisList:i,helixbundleList:r,axisData:n}}updateData(t,e){if((t=t||{}).position)this.build();else{var i={};if(t.color||t.radius){var r=0;e.helixbundleList.forEach((i=>{var n=i.getAxis(this.localAngle,this.centerDist,this.ssBorder,this.getColorParams(),this.getRadiusParams());t.color&&e.axisData.color.set(n.color,3*r),(t.radius||t.scale)&&e.axisData.size.set(n.size,r),r+=n.size.length})),t.color&&Object.assign(i,{color:e.axisData.color,color2:e.axisData.color}),(t.radius||t.scale)&&Object.assign(i,{radius:e.axisData.size})}e.bufferList[0].setAttributes(i)}}}Le.add("rocket",Wu);class Xu extends uu{constructor(t,e,i){super(t,e,i),this.type="rope",this.parameters=Object.assign({smooth:{type:"integer",max:15,min:0,rebuild:!0}},this.parameters,{aspectRatio:null,smoothSheet:null})}init(t){var e=t||{};e.aspectRatio=1,e.tension=rt(e.tension,.5),e.radiusScale=rt(e.radiusScale,5),e.smoothSheet=!1,this.smooth=rt(e.smooth,2),super.init(e)}getSpline(t){var e=new Sa(t);return new ou(t,this.getSplineParams({directional:!1,positionIterator:e.getCenterIterator(this.smooth)}))}}Le.add("rope",Xu);class Yu extends Sh{constructor(t,e,i){super(t,e,i),this.type="spacefill",this.parameters=Object.assign({sphereDetail:!0,disableImpostor:!0},this.parameters),this.init(i)}init(t){var e=t||{};e.useInteriorColor=rt(e.useInteriorColor,!0),super.init(e)}createData(t){return{bufferList:[new Uc(t.getAtomData(this.getAtomParams()),this.getBufferParams({sphereDetail:this.sphereDetail,dullInterior:!0,disableImpostor:this.disableImpostor}))]}}updateData(t,e){var i=e.sview.getAtomData(this.getAtomParams(t)),r={};t&&!t.position||Object.assign(r,{position:i.position}),t&&!t.color||Object.assign(r,{color:i.color}),t&&!t.radius||Object.assign(r,{radius:i.radius}),e.bufferList[0].setAttributes(r)}}function Ku(t){return 3*(t.position.length/3-1)*2}Le.add("spacefill",Yu);class Zu extends Uo{constructor(t,e={}){super({position:new Float32Array(Ku(t)),color:new Float32Array(Ku(t))},e),this.isLine=!0,this.vertexShader="Line.vert",this.fragmentShader="Line.frag",this.setAttributes(t)}setAttributes(t){let e,i,r,n;const s=this.geometry.attributes;if(t.position&&(e=t.position,r=s.position.array,s.position.needsUpdate=!0),t.color&&(i=t.color,n=s.color.array,s.color.needsUpdate=!0),!e&&!i)return void ke.warn("TraceBuffer.prototype.setAttributes no data");let o,a;const c=this.size-1;for(let t=0;t{if(!(t.residueCount<4)){i.push(t);var r=new ou(t,this.getSplineParams()),n=r.getSubdividedPosition(),s=r.getSubdividedColor(this.getColorParams());e.push(new Zu(Object.assign({},n,s),this.getBufferParams()))}}),t.getSelection()),{bufferList:e,polymerList:i}}updateData(t,e){t=t||{};var i=0,r=e.polymerList.length;for(i=0;i{t.boundingBox||t.computeBoundingBox(),this.boundingBox.union(t.boundingBox)}))}}const ld=Object.assign({aspectRatio:1.5,radialSegments:50,openEnded:!1,disableImpostor:!1},No);class hd{constructor(t,e={}){this.group=new d,this.wireframeGroup=new d,this.pickingGroup=new d,this.visible=!0,this.parameters=nt(e,this.defaultParameters),this.splitPosition=new Float32Array(t.position1.length),this.cylinderRadius=new Float32Array(t.radius.length);const r=this.makeAttributes(t),n={radialSegments:this.parameters.radialSegments,openEnded:this.parameters.openEnded,disableImpostor:this.parameters.disableImpostor};this.cylinderBuffer=new tu(r.cylinder,n),this.coneBuffer=new ad(r.cone,n),this.geometry=new cd([this.cylinderBuffer.geometry,this.coneBuffer.geometry]),this.matrix=rt(e.matrix,new i),this.picking=t.picking}get defaultParameters(){return ld}set matrix(t){Uo.prototype.setMatrix.call(this,t)}get matrix(){return this.group.matrix.clone()}get pickable(){return!!this.picking}makeAttributes(t={}){const i=this.splitPosition,r=this.cylinderRadius,n=this.parameters.aspectRatio;let s,o;const a={},c={};if(t.radius){for(s=0,o=r.length;s0&&(s=1/Math.sqrt(s),t[0]=e[0]*s,t[1]=e[1]*s,t[2]=e[2]*s),t}function u(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]}function d(t,e,i){const r=e[0],n=e[1],s=e[2],o=i[0],a=i[1],c=i[2];return t[0]=n*c-s*a,t[1]=s*o-r*c,t[2]=r*a-n*o,t}t.zero=e,t.clone=function(t){const i=e();return i[0]=t[0],i[1]=t[1],i[2]=t[2],i},t.isFinite=function(t){return Xd(t[0])&&Xd(t[1])&&Xd(t[2])},t.hasNaN=function(t){return isNaN(t[0])||isNaN(t[1])||isNaN(t[2])},t.setNaN=function(t){return t[0]=NaN,t[1]=NaN,t[2]=NaN,t},t.fromObj=function(t){return i(t.x,t.y,t.z)},t.toObj=function(t){return{x:t[0],y:t[1],z:t[2]}},t.fromArray=function(t,e,i){return t[0]=e[i+0],t[1]=e[i+1],t[2]=e[i+2],t},t.toArray=function(t,e,i){return e[i+0]=t[0],e[i+1]=t[1],e[i+2]=t[2],e},t.create=i,t.ofArray=function(t){const i=e();return i[0]=t[0],i[1]=t[1],i[2]=t[2],i},t.set=function(t,e,i,r){return t[0]=e,t[1]=i,t[2]=r,t},t.copy=r,t.add=n,t.sub=s,t.mul=function(t,e,i){return t[0]=e[0]*i[0],t[1]=e[1]*i[1],t[2]=e[2]*i[2],t},t.div=function(t,e,i){return t[0]=e[0]/i[0],t[1]=e[1]/i[1],t[2]=e[2]/i[2],t},t.scale=o,t.scaleAndAdd=a,t.scaleAndSub=function(t,e,i,r){return t[0]=e[0]-i[0]*r,t[1]=e[1]-i[1]*r,t[2]=e[2]-i[2]*r,t},t.addScalar=function(t,e,i){return t[0]=e[0]+i,t[1]=e[1]+i,t[2]=e[2]+i,t},t.subScalar=function(t,e,i){return t[0]=e[0]-i,t[1]=e[1]-i,t[2]=e[2]-i,t},t.round=function(t,e){return t[0]=Math.round(e[0]),t[1]=Math.round(e[1]),t[2]=Math.round(e[2]),t},t.ceil=function(t,e){return t[0]=Math.ceil(e[0]),t[1]=Math.ceil(e[1]),t[2]=Math.ceil(e[2]),t},t.floor=function(t,e){return t[0]=Math.floor(e[0]),t[1]=Math.floor(e[1]),t[2]=Math.floor(e[2]),t},t.trunc=function(t,e){return t[0]=Math.trunc(e[0]),t[1]=Math.trunc(e[1]),t[2]=Math.trunc(e[2]),t},t.abs=function(t,e){return t[0]=Math.abs(e[0]),t[1]=Math.abs(e[1]),t[2]=Math.abs(e[2]),t},t.min=function(t,e,i){return t[0]=Math.min(e[0],i[0]),t[1]=Math.min(e[1],i[1]),t[2]=Math.min(e[2],i[2]),t},t.max=function(t,e,i){return t[0]=Math.max(e[0],i[0]),t[1]=Math.max(e[1],i[1]),t[2]=Math.max(e[2],i[2]),t},t.clamp=function(t,e,i,r){return t[0]=Math.max(i[0],Math.min(r[0],e[0])),t[1]=Math.max(i[1],Math.min(r[1],e[1])),t[2]=Math.max(i[2],Math.min(r[2],e[2])),t},t.distance=function(t,e){const i=e[0]-t[0],r=e[1]-t[1],n=e[2]-t[2];return Math.sqrt(i*i+r*r+n*n)},t.squaredDistance=function(t,e){const i=e[0]-t[0],r=e[1]-t[1],n=e[2]-t[2];return i*i+r*r+n*n},t.magnitude=function(t){const e=t[0],i=t[1],r=t[2];return Math.sqrt(e*e+i*i+r*r)},t.squaredMagnitude=c,t.setMagnitude=function(t,e,i){return o(t,h(t,e),i)},t.negate=l,t.inverse=function(t,e){return t[0]=1/e[0],t[1]=1/e[1],t[2]=1/e[2],t},t.normalize=h,t.dot=u,t.cross=d,t.lerp=function(t,e,i,r){const n=e[0],s=e[1],o=e[2];return t[0]=n+r*(i[0]-n),t[1]=s+r*(i[1]-s),t[2]=o+r*(i[2]-o),t};const m=e();function f(t,e){const i=Math.sqrt(c(t)*c(e));if(0===i)return Math.PI/2;const r=u(t,e)/i;return Math.acos(Hd(r,-1,1))}t.slerp=function(t,e,i,r){const s=Hd(u(e,i),-1,1),c=Math.acos(s)*r;return a(m,i,e,-s),h(m,m),n(t,o(t,e,Math.cos(c)),o(m,m,Math.sin(c)))},t.hermite=function(t,e,i,r,n,s){const o=s*s,a=o*(2*s-3)+1,c=o*(s-2)+s,l=o*(s-1),h=o*(3-2*s);return t[0]=e[0]*a+i[0]*c+r[0]*l+n[0]*h,t[1]=e[1]*a+i[1]*c+r[1]*l+n[1]*h,t[2]=e[2]*a+i[2]*c+r[2]*l+n[2]*h,t},t.bezier=function(t,e,i,r,n,s){const o=1-s,a=o*o,c=s*s,l=a*o,h=3*s*a,u=3*c*o,d=c*s;return t[0]=e[0]*l+i[0]*h+r[0]*u+n[0]*d,t[1]=e[1]*l+i[1]*h+r[1]*u+n[1]*d,t[2]=e[2]*l+i[2]*h+r[2]*u+n[2]*d,t},t.quadraticBezier=function(t,e,i,r,n){return t[0]=Wd(e[0],i[0],r[0],n),t[1]=Wd(e[1],i[1],r[1],n),t[2]=Wd(e[2],i[2],r[2],n),t},t.spline=function(t,e,i,r,n,s,o){return t[0]=qd(e[0],i[0],r[0],n[0],s,o),t[1]=qd(e[1],i[1],r[1],n[1],s,o),t[2]=qd(e[2],i[2],r[2],n[2],s,o),t},t.random=function(t,e){const i=2*Math.random()*Math.PI,r=2*Math.random()-1,n=Math.sqrt(1-r*r)*e;return t[0]=Math.cos(i)*n,t[1]=Math.sin(i)*n,t[2]=r*e,t},t.transformMat4=function(t,e,i){const r=e[0],n=e[1],s=e[2],o=1/(i[3]*r+i[7]*n+i[11]*s+i[15]||1);return t[0]=(i[0]*r+i[4]*n+i[8]*s+i[12])*o,t[1]=(i[1]*r+i[5]*n+i[9]*s+i[13])*o,t[2]=(i[2]*r+i[6]*n+i[10]*s+i[14])*o,t},t.transformDirection=function(t,e,i){const r=e[0],n=e[1],s=e[2];return t[0]=i[0]*r+i[4]*n+i[8]*s,t[1]=i[1]*r+i[5]*n+i[9]*s,t[2]=i[2]*r+i[6]*n+i[10]*s,h(t,t)},t.transformMat4Offset=function(t,e,i,r,n,s){const o=e[0+n],a=e[1+n],c=e[2+n],l=1/(i[3+s]*o+i[7+s]*a+i[11+s]*c+i[15+s]||1);return t[0+r]=(i[0+s]*o+i[4+s]*a+i[8+s]*c+i[12+s])*l,t[1+r]=(i[1+s]*o+i[5+s]*a+i[9+s]*c+i[13+s])*l,t[2+r]=(i[2+s]*o+i[6+s]*a+i[10+s]*c+i[14+s])*l,t},t.transformDirectionOffset=function(t,e,i,r,n,s){const o=e[0+n],a=e[1+n],c=e[2+n];t[0+r]=i[0+s]*o+i[4+s]*a+i[8+s]*c,t[1+r]=i[1+s]*o+i[5+s]*a+i[9+s]*c,t[2+r]=i[2+s]*o+i[6+s]*a+i[10+s]*c;const l=Math.hypot(t[0+r],t[1+r],t[2+r]);return l>0&&(t[0+r]/=l,t[1+r]/=l,t[2+r]/=l),t},t.transformMat3=function(t,e,i){const r=e[0],n=e[1],s=e[2];return t[0]=r*i[0]+n*i[3]+s*i[6],t[1]=r*i[1]+n*i[4]+s*i[7],t[2]=r*i[2]+n*i[5]+s*i[8],t},t.transformQuat=function(t,e,i){const r=e[0],n=e[1],s=e[2],o=i[0],a=i[1],c=i[2],l=i[3],h=l*r+a*s-c*n,u=l*n+c*r-o*s,d=l*s+o*n-a*r,m=-o*r-a*n-c*s;return t[0]=h*l+m*-o+u*-c-d*-a,t[1]=u*l+m*-a+d*-o-h*-c,t[2]=d*l+m*-c+h*-a-u*-o,t},t.angle=f;const p=e(),g=e(),y=e(),b=e(),_=e(),x=e(),v=e();t.dihedralAngle=function(t,e,i,r){s(p,t,e),s(g,i,e),s(y,e,i),s(b,r,i),d(_,p,g),d(x,y,b);const n=f(_,x);return d(v,_,x),u(g,v)>0?n:-n},t.directionFromSpherical=function(e,i,r,n){return t.set(e,n*Math.cos(r)*Math.sin(i),n*Math.sin(r)*Math.sin(i),n*Math.cos(i))},t.exactEquals=function(t,e){return t[0]===e[0]&&t[1]===e[1]&&t[2]===e[2]},t.equals=function(t,e){const i=t[0],r=t[1],n=t[2],s=e[0],o=e[1],a=e[2];return Math.abs(i-s)<=jd*Math.max(1,Math.abs(i),Math.abs(s))&&Math.abs(r-o)<=jd*Math.max(1,Math.abs(r),Math.abs(o))&&Math.abs(n-a)<=jd*Math.max(1,Math.abs(n),Math.abs(a))};const w=e();t.makeRotation=function(e,i,r){const n=f(i,r);if(Math.abs(n)<1e-4)return Qd.setIdentity(e);if(Math.abs(n-Math.PI)0?r(t,e):l(t,r(t,e)),t};const P=e(),I=e();t.triangleNormal=function(t,e,i,r){return s(P,i,e),s(I,r,e),h(t,d(t,P,I))},t.toString=function(t,e){return`[${t[0].toPrecision(e)} ${t[1].toPrecision(e)} ${t[2].toPrecision(e)}]`},t.origin=i(0,0,0),t.unit=i(1,1,1),t.negUnit=i(-1,-1,-1),t.unitX=i(1,0,0),t.unitY=i(0,1,0),t.unitZ=i(0,0,1),t.negUnitX=i(-1,0,0),t.negUnitY=i(0,-1,0),t.negUnitZ=i(0,0,-1)}(Yd||(Yd={}));const Kd=Math.PI/180;function Zd(t){return t*Kd}function Qd(){return Qd.zero()}function Jd(){return Jd.zero()}function tm(){return tm.zero()}function em(){return em.zero()}function im(t){throw new Error("unreachable")}function rm(){return rm.zero()}var nm,sm,om,am;function cm(t,e,i){let r=e,n=0,s=1;for(45===t.charCodeAt(r)?(s=-1,++r):43===t.charCodeAt(r)&&++r;r9||e<0)return s*n|0;n=10*n+e|0}return s*n}function lm(t,e,i,r){return 43===e.charCodeAt(i)&&i++,t*Math.pow(10,cm(e,i,r))}function hm(t,e,i){let r=e,n=1,s=0,o=0,a=1;for(45===t.charCodeAt(r)?(n=-1,++r):43===t.charCodeAt(r)&&++r;r=0&&e<10)){if(-2===e){for(++r;r=0&&e<10))return 53===e||21===e?lm(n*(s+o/a),t,r+1,i):n*(s+o/a);o=10*o+e,a*=10,++r}return n*(s+o/a)}if(53===e||21===e)return lm(n*s,t,r+1,i);break}s=10*s+e,++r}return n*s}function um(t,e,i,r){return{schema:i,__array:void 0,isDefined:0===r,rowCount:e,value:e=>t,valueKind:t=>r,toArray:i=>{const{array:r}=Nd(e,i);for(let e=0,i=r.length;e!0}}function dm({value:t,valueKind:e,areValuesEqual:i,rowCount:r,schema:n}){return{schema:n,__array:void 0,isDefined:!0,rowCount:r,value:t,valueKind:e||(t=>0),toArray:e=>{const{array:i,start:n}=Nd(r,e);for(let e=0,r=i.length;et(e)===t(i))}}function mm({array:t,schema:e,valueKind:i}){const r=t.length,n=e.T,s="str"===e.valueType?"lowercase"===e.transform?e=>{const i=t[e];return"string"==typeof i?i.toLowerCase():`${null!=i?i:n}`.toLowerCase()}:"uppercase"===e.transform?e=>{const i=t[e];return"string"==typeof i?i.toUpperCase():`${null!=i?i:n}`.toUpperCase()}:e=>{const i=t[e];return"string"==typeof i?i:`${null!=i?i:n}`}:e=>t[e],o=Ud(t);return{schema:e,__array:t,isDefined:!0,rowCount:r,value:s,valueKind:i||(t=>0),toArray:"str"===e.valueType?"lowercase"===e.transform?e=>{const{start:i,end:s}=Ld(r,e),o=new(e&&void 0!==e.array?e.array:t.constructor)(s-i);for(let e=0,r=s-i;e{const{start:i,end:s}=Ld(r,e),o=new(e&&void 0!==e.array?e.array:t.constructor)(s-i);for(let e=0,r=s-i;e{const{start:i,end:s}=Ld(r,e),o=new(e&&void 0!==e.array?e.array:t.constructor)(s-i);for(let e=0,r=s-i;eVd(t,e):e=>{const{start:i,end:n}=Ld(r,e);if(0===i&&n===t.length)return t;const s=new(e&&void 0!==e.array?e.array:t.constructor)(n-i);for(let e=0,r=n-i;et[e]===t[i]}}function fm(t,e,i){return t.isDefined?0===e&&i===t.rowCount?t:t.__array&&Ud(t.__array)?function(t,e,i){const r=Vd(t.__array,{start:e,end:i}),n=t.valueKind;return mm({array:r,schema:t.schema,valueKind:t=>n(e+t)})}(t,e,i):function(t,e,i){const r=t.value,n=t.valueKind,s=t.areValuesEqual,o=0===e?r:t=>r(t+e),a=i-e;return{schema:t.schema,__array:void 0,isDefined:t.isDefined,rowCount:a,value:o,valueKind:0===e?n:t=>n(t+e),toArray:t=>{const{array:i}=Nd(a,t);for(let t=0,n=i.length;ts(t+e,i+e)}}(t,e,i):sm.Undefined(i-e,t.schema)}function pm(t,e,i){return 0===t.rowCount||i&&function(t,e){if(t.length!==e)return!1;for(let e=0,i=t.length;en(e[t])})}(t,e):function(t,e){const i=t.value,r=t.valueKind,n=t.areValuesEqual,s=t=>i(e[t]),o=e.length;return{schema:t.schema,__array:void 0,isDefined:t.isDefined,rowCount:o,value:s,valueKind:t=>r(e[t]),toArray:t=>{const{array:r}=Nd(o,t);for(let t=0,n=r.length;tn(e[t],e[i])}}(t,e)}function gm(t,e,i){return t[e]-t[i]}function ym(t,e,i){const r=t[e];t[e]=t[i],t[i]=r}function bm(t,e,i,r){const n=i+r>>1;return e(t,i,r)>0?e(t,i,n)>0?e(t,n,r)>0?n:r:i:e(t,r,n)>0?e(t,n,i)>0?n:i:r}function _m(t,e,i){const{cmp:r,swap:n,data:s,parts:o}=t;let a=e+1,c=i;for(n(s,e,bm(s,r,e,i));r(s,c,e)>0;)--c;for(let t=e+1;t<=c;t++){const i=r(s,t,e);if(i>0){for(n(s,t,c),--c;r(s,c,e)>0;)--c;t--}else 0===i&&(n(s,t,a),a++)}for(let t=e;t=r&&e(t,n,n+1)>0;)i(t,n,n+1),n-=1}}function vm(t,e,i){const{parts:r}=t;for(;eo;)--s;for(let e=i+1;e<=s;e++){const i=t[e];if(i>o){for(ym(t,e,s),--s;t[s]>o;)--s;e--}else i===o&&(ym(t,e,n),++n)}for(let e=i;e=e&&t[n]>i;)t[n+1]=t[n],n-=1;t[n+1]=i}}function Sm(t,e,i,r){for(;ii)return!1;return!0}function a(t,e,i,r){t[4*i+e]=r}function c(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4],t[5]=e[5],t[6]=e[6],t[7]=e[7],t[8]=e[8],t[9]=e[9],t[10]=e[10],t[11]=e[11],t[12]=e[12],t[13]=e[13],t[14]=e[14],t[15]=e[15],t}function l(t,e){const i=e[0]+e[5]+e[10];let r=0;return i>0?(r=2*Math.sqrt(i+1),t[3]=.25*r,t[0]=(e[6]-e[9])/r,t[1]=(e[8]-e[2])/r,t[2]=(e[1]-e[4])/r):e[0]>e[5]&&e[0]>e[10]?(r=2*Math.sqrt(1+e[0]-e[5]-e[10]),t[3]=(e[6]-e[9])/r,t[0]=.25*r,t[1]=(e[1]+e[4])/r,t[2]=(e[8]+e[2])/r):e[5]>e[10]?(r=2*Math.sqrt(1+e[5]-e[0]-e[10]),t[3]=(e[8]-e[2])/r,t[0]=(e[1]+e[4])/r,t[1]=.25*r,t[2]=(e[6]+e[9])/r):(r=2*Math.sqrt(1+e[10]-e[0]-e[5]),t[3]=(e[1]-e[4])/r,t[0]=(e[8]+e[2])/r,t[1]=(e[6]+e[9])/r,t[2]=.25*r),t}function h(t,e){const i=e[0],r=e[1],n=e[2],s=e[3],o=e[4],a=e[5],c=e[6],l=e[7],h=e[8],u=e[9],d=e[10],m=e[11],f=e[12],p=e[13],g=e[14],y=e[15],b=i*a-r*o,_=i*c-n*o,x=i*l-s*o,v=r*c-n*a,w=r*l-s*a,A=n*l-s*c,S=h*p-u*f,C=h*g-d*f,P=h*y-m*f,I=u*g-d*p,k=u*y-m*p,M=d*y-m*g;let T=b*M-_*k+x*I+v*P-w*C+A*S;return!!T&&(T=1/T,t[0]=(a*M-c*k+l*I)*T,t[1]=(n*k-r*M-s*I)*T,t[2]=(p*A-g*w+y*v)*T,t[3]=(d*w-u*A-m*v)*T,t[4]=(c*P-o*M-l*C)*T,t[5]=(i*M-n*P+s*C)*T,t[6]=(g*x-f*A-y*_)*T,t[7]=(h*A-d*x+m*_)*T,t[8]=(o*k-a*P+l*S)*T,t[9]=(r*P-i*k-s*S)*T,t[10]=(f*w-p*x+y*b)*T,t[11]=(u*x-h*w-m*b)*T,t[12]=(a*C-o*I-c*S)*T,t[13]=(i*I-r*C+n*S)*T,t[14]=(p*_-f*v-g*b)*T,t[15]=(h*v-u*_+d*b)*T,!0)}function u(t,e,i){const r=e[0],n=e[1],s=e[2],o=e[3],a=e[4],c=e[5],l=e[6],h=e[7],u=e[8],d=e[9],m=e[10],f=e[11],p=e[12],g=e[13],y=e[14],b=e[15];let _=i[0],x=i[1],v=i[2],w=i[3];return t[0]=_*r+x*a+v*u+w*p,t[1]=_*n+x*c+v*d+w*g,t[2]=_*s+x*l+v*m+w*y,t[3]=_*o+x*h+v*f+w*b,_=i[4],x=i[5],v=i[6],w=i[7],t[4]=_*r+x*a+v*u+w*p,t[5]=_*n+x*c+v*d+w*g,t[6]=_*s+x*l+v*m+w*y,t[7]=_*o+x*h+v*f+w*b,_=i[8],x=i[9],v=i[10],w=i[11],t[8]=_*r+x*a+v*u+w*p,t[9]=_*n+x*c+v*d+w*g,t[10]=_*s+x*l+v*m+w*y,t[11]=_*o+x*h+v*f+w*b,_=i[12],x=i[13],v=i[14],w=i[15],t[12]=_*r+x*a+v*u+w*p,t[13]=_*n+x*c+v*d+w*g,t[14]=_*s+x*l+v*m+w*y,t[15]=_*o+x*h+v*f+w*b,t}function d(t,e,i){let n=i[0],s=i[1],o=i[2],a=Math.sqrt(n*n+s*s+o*o);if(Math.abs(a)0&&(m=1/Math.sqrt(m),h*=m,u*=m,d*=m);let f=c*d-l*u,p=l*h-a*d,g=a*u-c*h;return m=f*f+p*p+g*g,m>0&&(m=1/Math.sqrt(m),f*=m,p*=m,g*=m),t[0]=f,t[1]=p,t[2]=g,t[3]=0,t[4]=u*g-d*p,t[5]=d*f-h*g,t[6]=h*p-u*f,t[7]=0,t[8]=h,t[9]=u,t[10]=d,t[11]=0,t[12]=n,t[13]=s,t[14]=o,t[15]=1,t},t.fromPermutation=function(t,e){n(t);for(let i=0;i<4;i++){a(t,i,e[i],1)}return t},t.getMaxScaleOnAxis=function(t){const e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],i=t[4]*t[4]+t[5]*t[5]+t[6]*t[6],r=t[8]*t[8]+t[9]*t[9]+t[10]*t[10];return Math.sqrt(Math.max(e,i,r))};const g=[1,0,0],y=[0,1,0],b=[0,0,1];t.rotX90=d(e(),Zd(90),g),t.rotX180=d(e(),Zd(180),g),t.rotY90=d(e(),Zd(90),y),t.rotY180=d(e(),Zd(180),y),t.rotY270=d(e(),Zd(270),y),t.rotZ90=d(e(),Zd(90),b),t.rotZ180=d(e(),Zd(180),b),t.rotXY90=u(e(),t.rotX90,t.rotY90),t.rotZY90=u(e(),t.rotZ90,t.rotY90),t.rotZYZ90=u(e(),t.rotZY90,t.rotZ90),t.rotZ90X180=u(e(),t.rotZ90,t.rotX180),t.rotY90Z180=u(e(),t.rotY90,t.rotZ180),t.id=i()}(Qd||(Qd={})),function(t){function e(){const t=[.1,0,0,0,0,0,0,0,0];return t[0]=0,t}function i(){const t=e();return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t}function r(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[4],t[4]=e[5],t[5]=e[6],t[6]=e[8],t[7]=e[9],t[8]=e[10],t}t.zero=e,t.identity=i,t.setIdentity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},t.toArray=function(t,e,i){return e[i+0]=t[0],e[i+1]=t[1],e[i+2]=t[2],e[i+3]=t[3],e[i+4]=t[4],e[i+5]=t[5],e[i+6]=t[6],e[i+7]=t[7],e[i+8]=t[8],e},t.fromArray=function(t,e,i){return t[0]=e[i+0],t[1]=e[i+1],t[2]=e[i+2],t[3]=e[i+3],t[4]=e[i+4],t[5]=e[i+5],t[6]=e[i+6],t[7]=e[i+7],t[8]=e[i+8],t},t.fromColumns=function(t,e,i,r){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=i[0],t[4]=i[1],t[5]=i[2],t[6]=r[0],t[7]=r[1],t[8]=r[2],t},t.fromMat4=r;const n=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];t.fromEuler=function(t,e,i){return Qd.fromEuler(n,e,i),r(t,n)},t.create=function(t,i,r,n,s,o,a,c,l){const h=e();return h[0]=t,h[1]=i,h[2]=r,h[3]=n,h[4]=s,h[5]=o,h[6]=a,h[7]=c,h[8]=l,h};const s=i();function o(t,e,i){for(let r=0;r<9;r++)if(Math.abs(t[r]-e[r])>i)return!1;return!0}function a(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t[4]=e[4],t[5]=e[5],t[6]=e[6],t[7]=e[7],t[8]=e[8],t}function c(t,e){if(t===e){const i=e[1],r=e[2],n=e[5];t[1]=e[3],t[2]=e[6],t[3]=i,t[5]=e[7],t[6]=r,t[7]=n}else t[0]=e[0],t[1]=e[3],t[2]=e[6],t[3]=e[1],t[4]=e[4],t[5]=e[7],t[6]=e[2],t[7]=e[5],t[8]=e[8];return t}function l(t,e){const i=e[0],r=e[1],n=e[2],s=e[3],o=e[4],a=e[5],c=e[6],l=e[7],h=e[8],u=h*o-a*l,d=-h*s+a*c,m=l*s-o*c;let f=i*u+r*d+n*m;return f?(f=1/f,t[0]=u*f,t[1]=(-h*r+n*l)*f,t[2]=(a*r-n*o)*f,t[3]=d*f,t[4]=(h*i-n*c)*f,t[5]=(-a*i+n*s)*f,t[6]=m*f,t[7]=(-l*i+r*c)*f,t[8]=(o*i-r*s)*f,t):(console.warn("non-invertible matrix.",e),t)}function h(t){const e=t[0],i=t[1],r=t[2],n=t[3],s=t[4],o=t[5],a=t[6],c=t[7],l=t[8];return e*(l*s-o*c)+i*(-l*n+o*a)+r*(c*n-s*a)}function u(t){return t[0]+t[4]+t[8]}function d(t,e,i){return t[0]=e[0]-i[0],t[1]=e[1]-i[1],t[2]=e[2]-i[2],t[3]=e[3]-i[3],t[4]=e[4]-i[4],t[5]=e[5]-i[5],t[6]=e[6]-i[6],t[7]=e[7]-i[7],t[8]=e[8]-i[8],t}function m(t,e,i){return t[0]=e[0]*i,t[1]=e[1]*i,t[2]=e[2]*i,t[3]=e[3]*i,t[4]=e[4]*i,t[5]=e[5]*i,t[6]=e[6]*i,t[7]=e[7]*i,t[8]=e[8]*i,t}t.isIdentity=function(t,e){return o(t,s,void 0===e?jd:e)},t.hasNaN=function(t){for(let e=0;e<9;e++)if(isNaN(t[e]))return!0;return!1},t.clone=function(t){return a(e(),t)},t.areEqual=o,t.setValue=function(t,e,i,r){t[3*i+e]=r},t.getValue=function(t,e,i){return t[3*i+e]},t.copy=a,t.transpose=c,t.invert=l,t.symmtricFromUpper=function(t,e){return t===e?(t[3]=e[1],t[6]=e[2],t[7]=e[5]):(t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[1],t[4]=e[4],t[5]=e[5],t[6]=e[2],t[7]=e[5],t[8]=e[8]),t},t.symmtricFromLower=function(t,e){return t===e?(t[1]=e[3],t[2]=e[6],t[5]=e[7]):(t[0]=e[0],t[1]=e[3],t[2]=e[6],t[3]=e[3],t[4]=e[4],t[5]=e[7],t[6]=e[6],t[7]=e[7],t[8]=e[8]),t},t.determinant=h,t.trace=u,t.sub=d,t.add=function(t,e,i){return t[0]=e[0]+i[0],t[1]=e[1]+i[1],t[2]=e[2]+i[2],t[3]=e[3]+i[3],t[4]=e[4]+i[4],t[5]=e[5]+i[5],t[6]=e[6]+i[6],t[7]=e[7]+i[7],t[8]=e[8]+i[8],t},t.mul=function(t,e,i){const r=e[0],n=e[1],s=e[2],o=e[3],a=e[4],c=e[5],l=e[6],h=e[7],u=e[8],d=i[0],m=i[1],f=i[2],p=i[3],g=i[4],y=i[5],b=i[6],_=i[7],x=i[8];return t[0]=d*r+m*o+f*l,t[1]=d*n+m*a+f*h,t[2]=d*s+m*c+f*u,t[3]=p*r+g*o+y*l,t[4]=p*n+g*a+y*h,t[5]=p*s+g*c+y*u,t[6]=b*r+_*o+x*l,t[7]=b*n+_*a+x*h,t[8]=b*s+_*c+x*u,t},t.subScalar=function(t,e,i){return t[0]=e[0]-i,t[1]=e[1]-i,t[2]=e[2]-i,t[3]=e[3]-i,t[4]=e[4]-i,t[5]=e[5]-i,t[6]=e[6]-i,t[7]=e[7]-i,t[8]=e[8]-i,t},t.addScalar=function(t,e,i){return t[0]=e[0]+i,t[1]=e[1]+i,t[2]=e[2]+i,t[3]=e[3]+i,t[4]=e[4]+i,t[5]=e[5]+i,t[6]=e[6]+i,t[7]=e[7]+i,t[8]=e[8]+i,t},t.mulScalar=m;const f=Math.PI/3,p=e();t.symmetricEigenvalues=function(e,i){const r=i[1]*i[1]+i[2]*i[2]+i[5]*i[5];if(0===r)e[0]=i[0],e[1]=i[4],e[2]=i[8];else{const n=u(i)/3,s=i[0]-n,o=i[4]-n,a=i[8]-n,c=s*s+o*o+a*a+2*r,l=Math.sqrt(c/6);m(p,t.Identity,n),d(p,i,p),m(p,p,1/l);const g=h(p)/2,y=g<=-1?f:g>=1?0:Math.acos(g)/3;e[0]=n+2*l*Math.cos(y),e[2]=n+2*l*Math.cos(y+2*f),e[1]=3*n-e[0]-e[2]}return e};const g=[.1,0,0],y=[.1,0,0],b=[.1,0,0],_=[.1,0,0],x=[.1,0,0],v=[.1,0,0];t.eigenvector=function(t,e,i){Yd.set(g,e[0]-i,e[1],e[2]),Yd.set(y,e[1],e[4]-i,e[5]),Yd.set(b,e[2],e[5],e[8]-i),Yd.cross(_,g,y),Yd.cross(x,g,b),Yd.cross(v,y,b);const r=Yd.dot(_,_),n=Yd.dot(x,x),s=Yd.dot(v,v);let o=r,a=0;return n>o&&(o=n,a=1),s>o&&(a=2),0===a?Yd.scale(t,_,1/Math.sqrt(r)):1===a?Yd.scale(t,x,1/Math.sqrt(n)):Yd.scale(t,v,1/Math.sqrt(s)),t},t.directionTransform=function(t,e){return r(t,e),l(t,t),c(t,t),t},t.Identity=i(),t.innerProduct=function(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]+t[3]*e[3]+t[4]*e[4]+t[5]*e[5]+t[6]*e[6]+t[7]*e[7]+t[8]*e[8]}}(Jd||(Jd={})),function(t){function e(){const t=[.1,0];return t[0]=0,t}t.zero=e,t.clone=function(t){const i=e();return i[0]=t[0],i[1]=t[1],i},t.create=function(t,i){const r=e();return r[0]=t,r[1]=i,r},t.hasNaN=function(t){return isNaN(t[0])||isNaN(t[1])},t.toArray=function(t,e,i){return e[i+0]=t[0],e[i+1]=t[1],e},t.fromArray=function(t,e,i){return t[0]=e[i+0],t[1]=e[i+1],t},t.copy=function(t,e){return t[0]=e[0],t[1]=e[1],t},t.set=function(t,e,i){return t[0]=e,t[1]=i,t},t.add=function(t,e,i){return t[0]=e[0]+i[0],t[1]=e[1]+i[1],t},t.sub=function(t,e,i){return t[0]=e[0]-i[0],t[1]=e[1]-i[1],t},t.mul=function(t,e,i){return t[0]=e[0]*i[0],t[1]=e[1]*i[1],t},t.div=function(t,e,i){return t[0]=e[0]/i[0],t[1]=e[1]/i[1],t},t.scale=function(t,e,i){return t[0]=e[0]*i,t[1]=e[1]*i,t},t.round=function(t,e){return t[0]=Math.round(e[0]),t[1]=Math.round(e[1]),t},t.ceil=function(t,e){return t[0]=Math.ceil(e[0]),t[1]=Math.ceil(e[1]),t},t.floor=function(t,e){return t[0]=Math.floor(e[0]),t[1]=Math.floor(e[1]),t},t.distance=function(t,e){const i=e[0]-t[0],r=e[1]-t[1];return Math.sqrt(i*i+r*r)},t.squaredDistance=function(t,e){const i=e[0]-t[0],r=e[1]-t[1];return i*i+r*r},t.magnitude=function(t){const e=t[0],i=t[1];return Math.sqrt(e*e+i*i)},t.squaredMagnitude=function(t){const e=t[0],i=t[1];return e*e+i*i},t.inverse=function(t,e){return t[0]=1/e[0],t[1]=1/e[1],t},t.areEqual=function(t,e){return t[0]===e[0]&&t[1]===e[1]},t.toString=function(t,e){return`[${t[0].toPrecision(e)} ${t[1].toPrecision(e)}}]`}}(tm||(tm={})),function(t){function e(){const t=[.1,0,0,0];return t[0]=0,t}function i(t,e){return t[0]=e.center[0],t[1]=e.center[1],t[2]=e.center[2],t[3]=e.radius,t}t.zero=e,t.clone=function(t){const i=e();return i[0]=t[0],i[1]=t[1],i[2]=t[2],i[3]=t[3],i},t.create=function(t,i,r,n){const s=e();return s[0]=t,s[1]=i,s[2]=r,s[3]=n,s},t.fromSphere=i,t.ofSphere=function(t){return i(e(),t)},t.hasNaN=function(t){return isNaN(t[0])||isNaN(t[1])||isNaN(t[2])||isNaN(t[3])},t.toArray=function(t,e,i){return e[i+0]=t[0],e[i+1]=t[1],e[i+2]=t[2],e[i+3]=t[3],e},t.fromArray=function(t,e,i){return t[0]=e[i+0],t[1]=e[i+1],t[2]=e[i+2],t[3]=e[i+3],t},t.toVec3Array=function(t,e,i){e[i+0]=t[0],e[i+1]=t[1],e[i+2]=t[2]},t.fromVec3Array=function(t,e,i){return t[0]=e[i+0],t[1]=e[i+1],t[2]=e[i+2],t[3]=0,t},t.copy=function(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t},t.set=function(t,e,i,r,n){return t[0]=e,t[1]=i,t[2]=r,t[3]=n,t},t.add=function(t,e,i){return t[0]=e[0]+i[0],t[1]=e[1]+i[1],t[2]=e[2]+i[2],t[3]=e[3]+i[3],t},t.distance=function(t,e){const i=e[0]-t[0],r=e[1]-t[1],n=e[2]-t[2],s=e[3]-t[3];return Math.sqrt(i*i+r*r+n*n+s*s)},t.scale=function(t,e,i){return t[0]=e[0]*i,t[1]=e[1]*i,t[2]=e[2]*i,t[4]=e[4]*i,t},t.round=function(t,e){return t[0]=Math.round(e[0]),t[1]=Math.round(e[1]),t[2]=Math.round(e[2]),t[3]=Math.round(e[3]),t},t.ceil=function(t,e){return t[0]=Math.ceil(e[0]),t[1]=Math.ceil(e[1]),t[2]=Math.ceil(e[2]),t[3]=Math.ceil(e[3]),t},t.floor=function(t,e){return t[0]=Math.floor(e[0]),t[1]=Math.floor(e[1]),t[2]=Math.floor(e[2]),t[3]=Math.floor(e[3]),t},t.squaredDistance=function(t,e){const i=e[0]-t[0],r=e[1]-t[1],n=e[2]-t[2],s=e[3]-t[3];return i*i+r*r+n*n+s*s},t.norm=function(t){const e=t[0],i=t[1],r=t[2],n=t[3];return Math.sqrt(e*e+i*i+r*r+n*n)},t.squaredNorm=function(t){const e=t[0],i=t[1],r=t[2],n=t[3];return e*e+i*i+r*r+n*n},t.transformMat4=function(t,e,i){const r=e[0],n=e[1],s=e[2],o=e[3];return t[0]=i[0]*r+i[4]*n+i[8]*s+i[12]*o,t[1]=i[1]*r+i[5]*n+i[9]*s+i[13]*o,t[2]=i[2]*r+i[6]*n+i[10]*s+i[14]*o,t[3]=i[3]*r+i[7]*n+i[11]*s+i[15]*o,t},t.dot=function(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]+t[3]*e[3]},t.inverse=function(t,e){return t[0]=1/e[0],t[1]=1/e[1],t[2]=1/e[2],t[3]=1/e[3],t},t.exactEquals=function(t,e){return t[0]===e[0]&&t[1]===e[1]&&t[2]===e[2]&&t[3]===e[3]},t.equals=function(t,e){const i=t[0],r=t[1],n=t[2],s=t[3],o=e[0],a=e[1],c=e[2],l=e[3];return Math.abs(i-o)<=jd*Math.max(1,Math.abs(i),Math.abs(o))&&Math.abs(r-a)<=jd*Math.max(1,Math.abs(r),Math.abs(a))&&Math.abs(n-c)<=jd*Math.max(1,Math.abs(n),Math.abs(c))&&Math.abs(s-l)<=jd*Math.max(1,Math.abs(s),Math.abs(l))},t.toString=function(t,e){return`[${t[0].toPrecision(e)} ${t[1].toPrecision(e)} ${t[2].toPrecision(e)} ${t[3].toPrecision(e)}]`}}(em||(em={})),function(t){function e(){const t=[.1,0,0,0];return t[0]=0,t}function i(){const t=e();return t[3]=1,t}function r(t,e,i){i*=.5;const r=Math.sin(i);return t[0]=r*e[0],t[1]=r*e[1],t[2]=r*e[2],t[3]=Math.cos(i),t}function n(t,e,i,r){const n=e[0],s=e[1],o=e[2],a=e[3];let c,l,h,u,d,m=i[0],f=i[1],p=i[2],g=i[3];return l=n*m+s*f+o*p+a*g,l<0&&(l=-l,m=-m,f=-f,p=-p,g=-g),1-l>1e-6?(c=Math.acos(l),h=Math.sin(c),u=Math.sin((1-r)*c)/h,d=Math.sin(r*c)/h):(u=1-r,d=r),t[0]=u*n+d*m,t[1]=u*s+d*f,t[2]=u*o+d*p,t[3]=u*a+d*g,t}function s(t,e){const i=e[0]+e[4]+e[8];let r;if(i>0)r=Math.sqrt(i+1),t[3]=.5*r,r=.5/r,t[0]=(e[5]-e[7])*r,t[1]=(e[6]-e[2])*r,t[2]=(e[1]-e[3])*r;else{let i=0;e[4]>e[0]&&(i=1),e[8]>e[3*i+i]&&(i=2);const n=(i+1)%3,s=(i+2)%3;r=Math.sqrt(e[3*i+i]-e[3*n+n]-e[3*s+s]+1),t[i]=.5*r,r=.5/r,t[3]=(e[3*n+s]-e[3*s+n])*r,t[n]=(e[3*n+i]+e[3*i+n])*r,t[s]=(e[3*s+i]+e[3*i+s])*r}return t}t.zero=e,t.identity=i,t.setIdentity=function(t){t[0]=0,t[1]=0,t[2]=0,t[3]=1},t.hasNaN=function(t){return isNaN(t[0])||isNaN(t[1])||isNaN(t[2])||isNaN(t[3])},t.create=function(t,e,r,n){const s=i();return s[0]=t,s[1]=e,s[2]=r,s[3]=n,s},t.setAxisAngle=r,t.getAxisAngle=function(t,e){const i=2*Math.acos(e[3]),r=Math.sin(i/2);return 0!==r?(t[0]=e[0]/r,t[1]=e[1]/r,t[2]=e[2]/r):(t[0]=1,t[1]=0,t[2]=0),i},t.multiply=function(t,e,i){const r=e[0],n=e[1],s=e[2],o=e[3],a=i[0],c=i[1],l=i[2],h=i[3];return t[0]=r*h+o*a+n*l-s*c,t[1]=n*h+o*c+s*a-r*l,t[2]=s*h+o*l+r*c-n*a,t[3]=o*h-r*a-n*c-s*l,t},t.rotateX=function(t,e,i){i*=.5;const r=e[0],n=e[1],s=e[2],o=e[3],a=Math.sin(i),c=Math.cos(i);return t[0]=r*c+o*a,t[1]=n*c+s*a,t[2]=s*c-n*a,t[3]=o*c-r*a,t},t.rotateY=function(t,e,i){i*=.5;const r=e[0],n=e[1],s=e[2],o=e[3],a=Math.sin(i),c=Math.cos(i);return t[0]=r*c-s*a,t[1]=n*c+o*a,t[2]=s*c+r*a,t[3]=o*c-n*a,t},t.rotateZ=function(t,e,i){i*=.5;const r=e[0],n=e[1],s=e[2],o=e[3],a=Math.sin(i),c=Math.cos(i);return t[0]=r*c+n*a,t[1]=n*c-r*a,t[2]=s*c+o*a,t[3]=o*c-s*a,t},t.calculateW=function(t,e){const i=e[0],r=e[1],n=e[2];return t[0]=i,t[1]=r,t[2]=n,t[3]=Math.sqrt(Math.abs(1-i*i-r*r-n*n)),t},t.slerp=n,t.invert=function(t,e){const i=e[0],r=e[1],n=e[2],s=e[3],o=i*i+r*r+n*n+s*s,a=o?1/o:0;return t[0]=-i*a,t[1]=-r*a,t[2]=-n*a,t[3]=s*a,t},t.conjugate=function(t,e){return t[0]=-e[0],t[1]=-e[1],t[2]=-e[2],t[3]=e[3],t},t.dot=function(t,e){return t[0]*e[0]+t[1]*e[1]+t[2]*e[2]+t[3]*e[3]},t.fromMat3=s,t.fromEuler=function(t,e,i){const[r,n,s]=e,o=Math.cos(r/2),a=Math.cos(n/2),c=Math.cos(s/2),l=Math.sin(r/2),h=Math.sin(n/2),u=Math.sin(s/2);switch(i){case"XYZ":t[0]=l*a*c+o*h*u,t[1]=o*h*c-l*a*u,t[2]=o*a*u+l*h*c,t[3]=o*a*c-l*h*u;break;case"YXZ":t[0]=l*a*c+o*h*u,t[1]=o*h*c-l*a*u,t[2]=o*a*u-l*h*c,t[3]=o*a*c+l*h*u;break;case"ZXY":t[0]=l*a*c-o*h*u,t[1]=o*h*c+l*a*u,t[2]=o*a*u+l*h*c,t[3]=o*a*c-l*h*u;break;case"ZYX":t[0]=l*a*c-o*h*u,t[1]=o*h*c+l*a*u,t[2]=o*a*u-l*h*c,t[3]=o*a*c+l*h*u;break;case"YZX":t[0]=l*a*c+o*h*u,t[1]=o*h*c+l*a*u,t[2]=o*a*u-l*h*c,t[3]=o*a*c-l*h*u;break;case"XZY":t[0]=l*a*c-o*h*u,t[1]=o*h*c-l*a*u,t[2]=o*a*u+l*h*c,t[3]=o*a*c+l*h*u;break;default:im()}return t};const o=[0,0,0];function a(t,e){const i=e[0],r=e[1],n=e[2],s=e[3];let o=i*i+r*r+n*n+s*s;return o>0&&(o=1/Math.sqrt(o),t[0]=i*o,t[1]=r*o,t[2]=n*o,t[3]=s*o),t}t.fromUnitVec3=function(t,e,i){let r=Yd.dot(e,i)+1;return rMath.abs(e[2])?Yd.set(o,-e[1],e[0],0):Yd.set(o,0,-e[2],e[1])):Yd.cross(o,e,i),t[0]=o[0],t[1]=o[1],t[2]=o[2],t[3]=r,a(t,t),t},t.clone=function(t){const i=e();return i[0]=t[0],i[1]=t[1],i[2]=t[2],i[3]=t[3],i},t.toArray=function(t,e,i){return e[i+0]=t[0],e[i+1]=t[1],e[i+2]=t[2],e[i+3]=t[3],e},t.fromArray=function(t,e,i){return t[0]=e[i+0],t[1]=e[i+1],t[2]=e[i+2],t[3]=e[i+3],t},t.copy=function(t,e){return t[0]=e[0],t[1]=e[1],t[2]=e[2],t[3]=e[3],t},t.set=function(t,e,i,r,n){return t[0]=e,t[1]=i,t[2]=r,t[3]=n,t},t.exactEquals=function(t,e){return t[0]===e[0]&&t[1]===e[1]&&t[2]===e[2]&&t[3]===e[3]},t.equals=function(t,e){const i=t[0],r=t[1],n=t[2],s=t[3],o=e[0],a=e[1],c=e[2],l=e[3];return Math.abs(i-o)<=jd*Math.max(1,Math.abs(i),Math.abs(o))&&Math.abs(r-a)<=jd*Math.max(1,Math.abs(r),Math.abs(a))&&Math.abs(n-c)<=jd*Math.max(1,Math.abs(n),Math.abs(c))&&Math.abs(s-l)<=jd*Math.max(1,Math.abs(s),Math.abs(l))},t.add=function(t,e,i){return t[0]=e[0]+i[0],t[1]=e[1]+i[1],t[2]=e[2]+i[2],t[3]=e[3]+i[3],t},t.normalize=a;const c=[0,0,0],l=[1,0,0],h=[0,1,0];t.rotationTo=function(t,e,i){const n=Yd.dot(e,i);return n<-.999999?(Yd.cross(c,l,e),Yd.magnitude(c)<1e-6&&Yd.cross(c,h,e),Yd.normalize(c,c),r(t,c,Math.PI),t):n>.999999?(t[0]=0,t[1]=0,t[2]=0,t[3]=1,t):(Yd.cross(c,e,i),t[0]=c[0],t[1]=c[1],t[2]=c[2],t[3]=1+n,a(t,t))};const u=e(),d=e();t.sqlerp=function(t,e,i,r,s,o){return n(u,e,s,o),n(d,i,r,o),n(t,u,d,2*o*(1-o)),t};const m=[0,0,0,0,0,0,0,0,0];t.setAxes=function(t,e,i,r){return m[0]=i[0],m[3]=i[1],m[6]=i[2],m[1]=r[0],m[4]=r[1],m[7]=r[2],m[2]=-e[0],m[5]=-e[1],m[8]=-e[2],a(t,s(t,m))},t.toString=function(t,e){return`[${t[0].toPrecision(e)} ${t[1].toPrecision(e)} ${t[2].toPrecision(e)} ${t[3].toPrecision(e)}]`},t.Identity=i()}(rm||(rm={})),function(t){function e(t,e,n){const s=function(t,e,i){const r=[];for(let t=0;tt[e],set:(t,e,i)=>t[e]=i,add:(t,e,i)=>t[e]+=i,dataOffset:t=>t,getCoords:(t,e)=>(e[0]=t,e)};case 2:if(0===i[0]&&1===i[1]){const t=e[0];return{get:(e,i,r)=>e[r*t+i],set:(e,i,r,n)=>e[r*t+i]=n,add:(e,i,r,n)=>e[r*t+i]+=n,dataOffset:(e,i)=>i*t+e,getCoords:(e,i)=>(i[0]=e%t,i[1]=Math.floor(e/t),i)}}if(1===i[0]&&0===i[1]){const t=e[1];return{get:(e,i,r)=>e[i*t+r],set:(e,i,r,n)=>e[i*t+r]=n,add:(e,i,r,n)=>e[i*t+r]+=n,dataOffset:(e,i)=>e*t+i,getCoords:(e,i)=>(i[0]=Math.floor(e/t),i[1]=e%t,i)}}throw new Error("bad axis order");case 3:if(0===i[0]&&1===i[1]&&2===i[2]){const t=e[0],i=e[1],r=t*i;return{get:(e,i,n,s)=>e[i+n*t+s*r],set:(e,i,n,s,o)=>e[i+n*t+s*r]=o,add:(e,i,n,s,o)=>e[i+n*t+s*r]+=o,dataOffset:(e,i,n)=>e+i*t+n*r,getCoords:(e,r)=>{const n=Math.floor(e/t);return r[0]=e%t,r[1]=n%i,r[2]=Math.floor(n/i),r}}}if(0===i[0]&&2===i[1]&&1===i[2]){const t=e[0],i=e[2],r=t*i;return{get:(e,i,n,s)=>e[i+s*t+n*r],set:(e,i,n,s,o)=>e[i+s*t+n*r]=o,add:(e,i,n,s,o)=>e[i+s*t+n*r]+=o,dataOffset:(e,i,n)=>e+n*t+i*r,getCoords:(e,r)=>{const n=Math.floor(e/t);return r[0]=e%t,r[1]=Math.floor(n/i),r[2]=n%i,r}}}if(1===i[0]&&0===i[1]&&2===i[2]){const t=e[1],i=e[0],r=t*i;return{get:(e,i,n,s)=>e[n+i*t+s*r],set:(e,i,n,s,o)=>e[n+i*t+s*r]=o,add:(e,i,n,s,o)=>e[n+i*t+s*r]+=o,dataOffset:(e,i,n)=>i+e*t+n*r,getCoords:(e,r)=>{const n=Math.floor(e/t);return r[0]=n%i,r[1]=e%t,r[2]=Math.floor(n/i),r}}}if(1===i[0]&&2===i[1]&&0===i[2]){const t=e[1],i=e[2],r=t*i;return{get:(e,i,n,s)=>e[n+s*t+i*r],set:(e,i,n,s,o)=>e[n+s*t+i*r]=o,add:(e,i,n,s,o)=>e[n+s*t+i*r]+=o,dataOffset:(e,i,n)=>i+n*t+e*r,getCoords:(e,r)=>{const n=Math.floor(e/t);return r[0]=Math.floor(n/i),r[1]=e%t,r[2]=n%i,r}}}if(2===i[0]&&0===i[1]&&1===i[2]){const t=e[2],i=e[0],r=t*i;return{get:(e,i,n,s)=>e[s+i*t+n*r],set:(e,i,n,s,o)=>e[s+i*t+n*r]=o,add:(e,i,n,s,o)=>e[s+i*t+n*r]+=o,dataOffset:(e,i,n)=>n+e*t+i*r,getCoords:(e,r)=>{const n=Math.floor(e/t);return r[0]=n%i,r[1]=Math.floor(n/i),r[2]=e%t,r}}}if(2===i[0]&&1===i[1]&&0===i[2]){const t=e[2],i=e[1],r=t*i;return{get:(e,i,n,s)=>e[s+n*t+i*r],set:(e,i,n,s,o)=>e[s+n*t+i*r]=o,add:(e,i,n,s,o)=>e[s+n*t+i*r]+=o,dataOffset:(e,i,n)=>n+i*t+e*r,getCoords:(e,r)=>{const n=Math.floor(e/t);return r[0]=Math.floor(n/i),r[1]=n%i,r[2]=e%t,r}}}throw new Error("bad axis order");default:return{get:(e,...i)=>e[n(t,i)],set:(e,...i)=>e[n(t,i)]=i[i.length-1],add:(e,...i)=>e[n(t,i)]+=i[i.length-1],dataOffset:(...e)=>n(t,e),getCoords:(e,i)=>function(t,e,i){const{dimensions:r,axisOrderFastToSlow:n}=t,s=r.length;let o=e;for(let t=0;tnew(e||t.defaultCtor)(i)}function n(t,e){const{accessDimensions:i,axisOrderFastToSlow:r}=t,n=i.length-1;let s=i[n]*e[r[n]];for(let t=n-1;t>=0;t--)s=(s+e[r[t]])*i[t];return s}function s(t,e){const i=[];for(let r=0;rs(t,e)},t.convertToCanonicalAxisIndicesSlowToFast=function(t){const e=new Int32Array(t.length);for(let i=0;is(t,e)}}(nm||(nm={})),function(t){let e;function i(t,e){return um(e.T,t,e,1)}function r(t){return dm(t)}!function(t){function e(e,i=t.float){return{"@type":"tensor",T:e.create(),space:e,valueType:"tensor",baseType:i}}t.str={"@type":"str",T:"",valueType:"str"},t.ustr={"@type":"str",T:"",valueType:"str",transform:"uppercase"},t.lstr={"@type":"str",T:"",valueType:"str",transform:"lowercase"},t.int={"@type":"int",T:0,valueType:"int"},t.coord={"@type":"coord",T:0,valueType:"float"},t.float={"@type":"float",T:0,valueType:"float"},t.Str=function(t){var e;return{"@type":"str",T:null!==(e=null==t?void 0:t.defaultValue)&&void 0!==e?e:"",transform:null==t?void 0:t.transform,valueType:"str"}},t.Int=function(t=0){return{"@type":"int",T:t,valueType:"int"}},t.Float=function(t=0){return{"@type":"float",T:t,valueType:"float"}},t.Tensor=e,t.Vector=function(i,r=t.float){return e(nm.Vector(i,"int"===r["@type"]?Int32Array:Float64Array),r)},t.Matrix=function(i,r,n=t.float){return e(nm.ColumnMajorMatrix(i,r,"int"===n["@type"]?Int32Array:Float64Array),n)},t.Aliased=function(t){return t},t.List=function(t,e,i=[]){return{"@type":"list",T:i,separator:t,itemParse:e,valueType:"list"}}}(e=t.Schema||(t.Schema={})),t.is=function(t){return!!t&&!!t.schema&&!!t.value},t.ValueKind={Present:0,NotPresent:1,Unknown:2},t.Undefined=i,t.ofConst=function(t,e,i){return um(t,e,i,0)},t.ofLambda=r,t.range=function(t,i){return r({value:e=>e+t,rowCount:Math.max(i-t+1,0),schema:e.int})},t.ofArray=function(t){return mm(t)},t.ofIntArray=function(t){return mm({array:t,schema:e.int})},t.ofFloatArray=function(t){return mm({array:t,schema:e.float})},t.ofStringArray=function(t){return mm({array:t,schema:e.str})},t.ofStringAliasArray=function(t){return mm({array:t,schema:e.Aliased(e.str)})},t.ofStringListArray=function(t,i=","){return mm({array:t,schema:e.List(i,(t=>t))})},t.ofIntTokens=function(t){const{count:i,data:r,indices:n}=t;return dm({value:t=>cm(r,n[2*t],n[2*t+1])||0,rowCount:i,schema:e.int})},t.ofFloatTokens=function(t){const{count:i,data:r,indices:n}=t;return dm({value:t=>hm(r,n[2*t],n[2*t+1])||0,rowCount:i,schema:e.float})},t.ofStringTokens=function(t){const{count:i,data:r,indices:n}=t;return dm({value:t=>{const e=r.substring(n[2*t],n[2*t+1]);return"."===e||"?"===e?"":e},rowCount:i,schema:e.str})},t.window=function(t,e,i){return fm(t,e,i)},t.view=function(t,e,i=!0){return pm(t,e,i)},t.createFirstIndexMap=function(t){return function(t){const e=new Map;for(let i=0,r=t.rowCount;ie.has(t)?e.get(t):-1}(t)},t.mapToArray=function(t,e,i){return function(t,e,i){const r=new i(t.rowCount);for(let i=0,n=t.rowCount;i0&&(t.chunks[t.chunks.length]=t.current.length===t.offset?t.current.join(""):t.current.slice(0,t.offset).join("")),t.chunks.join("")):t.current.length===t.offset?t.current.join(""):t.current.splice(0,t.offset).join("")},t.getSize=function(t){let e=0;for(const i of t.chunks)e+=i.length;for(let i=0;i0&&(t.current.length===t.offset?t.chunks[t.chunks.length]=t.current.join(""):t.chunks[t.chunks.length]=t.current.slice(0,t.offset).join(""),t.offset=0),t.chunks};const e=[];function i(t,i){i>0&&r(t,e[i])}function r(t,e){t.offset===t.capacity&&(t.chunks[t.chunks.length]=t.current.join(""),t.offset=0),t.current[t.offset++]=e}!function(){let t="";for(let i=0;i<512;i++)e[i]=t,t+=" "}(),t.newline=function(t){r(t,"\n")},t.whitespace=i,t.whitespace1=function(t){r(t," ")},t.write=function(t,e){e&&(t.offset===t.capacity&&(t.chunks[t.chunks.length]=t.current.join(""),t.offset=0),t.current[t.offset++]=e)},t.writeSafe=r,t.writePadLeft=function(t,e,n){if(!e)return void i(t,n);i(t,n-e.length),r(t,e)},t.writePadRight=function(t,e,n){if(!e)return void i(t,n);const s=n-e.length;r(t,e),i(t,s)},t.writeInteger=function(t,e){r(t,""+e)},t.writeIntegerAndSpace=function(t,e){r(t,e+" ")},t.writeIntegerPadLeft=function(t,e,n){const s=""+e;i(t,n-s.length),r(t,s)},t.writeIntegerPadRight=function(t,e,n){const s=""+e,o=n-s.length;r(t,s),i(t,o)},t.writeFloat=function(t,e,i){r(t,""+Math.round(i*e)/i)},t.writeFloatPadLeft=function(t,e,n,s){const o=""+Math.round(n*e)/n;i(t,s-o.length),r(t,o)},t.writeFloatPadRight=function(t,e,n,s){const o=""+Math.round(n*e)/n,a=s-o.length;r(t,o),i(t,a)}}(am||(am={}));const Pm=function(){if("undefined"!=typeof window&&window.performance){const t=window.performance;return()=>t.now()}return"undefined"!=typeof process&&"undefined"!==process.hrtime&&"function"==typeof process.hrtime?()=>{const t=process.hrtime();return 1e3*t[0]+t[1]/1e6}:Date.now?()=>Date.now():()=>+new Date}();var Im,km,Mm;function Tm(t,e){return t-e}function Dm(t=0,e=Number.MAX_SAFE_INTEGER){let i=t;return()=>{const t=i;return i=(i+1)%e,t}}!function(t){const e="undefined"!=typeof btoa?btoa:t=>Buffer.from(t).toString("base64"),i=[];t.create22=function(){let t=+new Date+Pm();for(let e=0;e<16;e++)i[e]=String.fromCharCode((t+255*Math.random())%255|0),t=Math.floor(t/255);return e(i.join("")).replace(/\+/g,"-").replace(/\//g,"_").substr(0,22)},t.createv4=function(){let t=+new Date+Pm();return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(function(e){const i=(t+16*Math.random())%16|0;return t=Math.floor(t/16),("x"===e?i:3&i|8).toString(16)}))},t.is=function(t){return"string"==typeof t}}(Im||(Im={})),function(t){class e{has(t){return!1}forEach(t,e){return e}constructor(){this.size=0}}class i{has(t){return t===this.idx}forEach(t,e){return t(this.idx,e),e}constructor(t){this.idx=t,this.size=1}}class r{has(t){return tt[e++]=i)),function(t){Array.prototype.sort.call(t,Tm)}(t),this._flat=t,this._flat}forEach(t,e){return this._forEach(t,e),e}constructor(t){this.set=t,this._flat=void 0,this.size=t.size}}function o(t){return new s(t)}function a(t,e){return new r(t,e)}t.always=function(t){return new n(t)},t.never=new e,t.ofSet=o,t.singleton=function(t){return new i(t)},t.ofUniqueIndices=function(t){const o=t.length;if(0===o)return new e;if(1===o)return new i(t[0]);let a=0;for(const e of t)e>a&&(a=e);if(o===a)return new n(o);if(o/a<1/12){const e=new Set;for(const i of t)e.add(i);return new s(e)}const c=new Int8Array(a+1);for(const e of t)c[e]=1;return new r(c,t.length)},t.ofMask=a,t.hasAny=function(t,e){for(const i of e)if(t.has(i))return!0;return!1},t.complement=function(t,e){let i=0,r=0;if(e.forEach((e=>{t.has(e)||(i++,e>r&&(r=e))})),i/r<1/12){const i=new Set;return e.forEach((e=>{t.has(e)||i.add(e)})),o(i)}{const n=new Uint8Array(r+1);return e.forEach((e=>{t.has(e)||(n[e]=1)})),a(n,i)}}}(km||(km={})),function(t){t.create=function(t){return{ref:t}},t.set=function(t,e){return t.ref=e,t}}(Mm||(Mm={}));const Bm=Dm(0,2147483647);var Fm,Em,$m,Om,Rm;function Lm(t){const{data:e,indices:i}=t;return function(t,r){const n=i[2*t],s=i[2*r],o=i[2*t+1]-n;if(o!==i[2*r+1]-s)return!1;for(let t=0;tr[t]}}!function(t){t.create=function(t,e){return{id:Bm(),version:0,value:t,metadata:e}},t.withValue=function(t,e){return{id:t.id,version:t.version+1,value:e,metadata:t.metadata}}}(Fm||(Fm={})),function(t){function e(t,e){return Mm.set(t,Fm.withValue(t.ref,e))}t.create=function(t,e){return Mm.create(Fm.create(t,e))},t.update=e,t.set=function(t,e){return Mm.set(t,e)},t.updateIfChanged=function(t,i){return t.ref.value!==i?e(t,i):t}}(Em||(Em={})),function(t){function e(t,e,i){const r=Object.create(null),n=Object.keys(e);r._rowCount=i.length,r._columns=n,r._schema=e;for(const e of n)r[e]=sm.view(t[e],i);return r}function i(t,e){const i=Object.create(null),{_columns:r}=t;for(let n=0;ne[t][s],valueKind:t=>void 0===e[t][s]?1:0});return i},t.ofArrays=function(t,e){var i;const r=Object.create(null),n=Object.keys(t);r._rowCount=0,r._columns=n,r._schema=t;for(const s of n)void 0!==e[s]?(r[s]=sm.ofArray({array:e[s],schema:t[s]}),r._rowCount=null===(i=e[s])||void 0===i?void 0:i.length):r[s]=sm.Undefined(r._rowCount,t[s]);return r},t.view=e,t.pick=function(t,i,r){const n=[];for(let e=0,i=t._rowCount;ee(i,r)));let r=!0;for(let t=0,e=i.length;t0?e[i[0]].rowCount:0,name:t,fieldNames:i,getField:t=>e[t]}}t.empty=function(t){return{rowCount:0,name:t,fieldNames:[],getField(t){}}},t.ofFields=e,t.ofTable=function(t,i){const r={};for(const t of i._columns)r[t]=Rm.ofColumn(i[t]);return e(t,r)}}(Um||(Um={})),function(t){function e(t){const e=t.length,i=e=>{const i=t[e];return i&&"."!==i&&"?"!==i?i:""},r=e=>{const i=t[e];return cm(i,0,i.length)||0},n=e=>{const i=t[e];return hm(i,0,i.length)||0};return{__array:void 0,binaryEncoding:void 0,isDefined:!0,rowCount:e,str:i,int:r,float:n,valueKind:e=>{const i=t[e],r=i.length;if(r>1)return 0;if(0===r)return 1;const n=i.charCodeAt(0);return 46===n?1:63===n?2:0},areValuesEqual:(e,i)=>t[e]===t[i],toStringArray:r=>r?zd(e,i,r):t,toIntArray:t=>zd(e,r,t),toFloatArray:t=>zd(e,n,t)}}function i(t){const{rowCount:e,valueKind:i,areValuesEqual:r,isDefined:n}=t;let s,o,a;switch(t.schema.valueType){case"float":case"int":s=e=>""+t.value(e),o=t.value,a=t.value;break;case"str":s=t.value,o=e=>{const i=t.value(e);return cm(i,0,i.length)||0},a=e=>{const i=t.value(e);return hm(i,0,i.length)||0};break;case"list":const{separator:e}=t.schema;s=i=>t.value(i).join(e),o=t=>NaN,a=t=>NaN;break;default:throw new Error(`unsupported valueType '${t.schema.valueType}'`)}return{__array:void 0,binaryEncoding:void 0,isDefined:n,rowCount:e,str:s,int:o,float:a,valueKind:i,areValuesEqual:r,toStringArray:t=>zd(e,s,t),toIntArray:t=>zd(e,o,t),toFloatArray:t=>zd(e,a,t)}}t.ofString=function(t){return e([t])},t.ofStrings=e,t.ofNumbers=function(t){const e=t.length,i=e=>""+t[e],r=e=>t[e],n=i=>!i||i.array&&t instanceof i.array?t:zd(e,r,i);return{__array:void 0,binaryEncoding:void 0,isDefined:!0,rowCount:e,str:i,int:r,float:r,valueKind:t=>0,areValuesEqual:(e,i)=>t[e]===t[i],toStringArray:t=>zd(e,i,t),toIntArray:n,toFloatArray:n}},t.ofTokens=function(t){const{data:e,indices:i,count:r}=t,n=t=>{const r=e.substring(i[2*t],i[2*t+1]);return"."===r||"?"===r?"":r},s=t=>cm(e,i[2*t],i[2*t+1])||0,o=t=>hm(e,i[2*t],i[2*t+1])||0;return{__array:void 0,binaryEncoding:void 0,isDefined:!0,rowCount:r,str:n,int:s,float:o,valueKind:t=>{const r=i[2*t],n=i[2*t+1]-r;if(n>1)return 0;if(0===n)return 1;const s=e.charCodeAt(r);return 46===s?1:63===s?2:0},areValuesEqual:Lm(t),toStringArray:t=>zd(r,n,t),toIntArray:t=>zd(r,s,t),toFloatArray:t=>zd(r,o,t)}},t.ofColumn=i,t.ofUndefined=function(t,e){return i(sm.Undefined(t,e))}}(Rm||(Rm={}));const Vm="undefined"!=typeof setImmediate?"undefined"!=typeof window?{setImmediate:(t,...e)=>window.setImmediate(t,...e),clearImmediate:t=>window.clearImmediate(t)}:{setImmediate:setImmediate,clearImmediate:clearImmediate}:function(){const t=function(){const t="undefined"!=typeof window&&window,e="undefined"!=typeof self&&"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope&&self,i="undefined"!=typeof global&&global;return t||i||e}(),e={},i="undefined"!=typeof document?document:void 0;let r,n=1;function s(t){delete e[t]}function o(t){const i=e[t];s(t),function(t){const e=t.callback,i=t.args;switch(i.length){case 0:e();break;case 1:e(i[0]);break;case 2:e(i[0],i[1]);break;case 3:e(i[0],i[1],i[2]);break;default:e.apply(void 0,i)}}(i)}return"undefined"!=typeof process&&"[object process]"==={}.toString.call(process)?r=function(t){process.nextTick((function(){o(t)}))}:function(){if(t&&t.postMessage&&!t.importScripts){let e=!0;const i=t.onmessage;return t.onmessage=function(){e=!1},t.postMessage("","*"),t.onmessage=i,e}}()?function(){const e="setImmediate$"+Math.random()+"$",i=function(i){i.source===t&&"string"==typeof i.data&&0===i.data.indexOf(e)&&o(+i.data.slice(e.length))};window.addEventListener?window.addEventListener("message",i,!1):window.attachEvent("onmessage",i),r=function(t){window.postMessage(e+t,"*")}}():"undefined"!=typeof MessageChannel?function(){const t=new MessageChannel;t.port1.onmessage=function(t){o(t.data)},r=function(e){t.port2.postMessage(e)}}():i&&"onreadystatechange"in i.createElement("script")?function(){const t=i.documentElement;r=function(e){let r=i.createElement("script");r.onreadystatechange=function(){o(e),r.onreadystatechange=null,t.removeChild(r),r=null},t.appendChild(r)}}():r=function(t){setTimeout(o,0,t)},{setImmediate:function(t,...i){"function"!=typeof t&&(t=new Function(""+t));const s={callback:t,args:i};return e[n]=s,r(n),n++},clearImmediate:s}}();function jm(t){Vm.setImmediate(t)}const Gm={setImmediate:Vm.setImmediate,clearImmediate:Vm.clearImmediate,immediatePromise:()=>new Promise(jm),delay:(t,e=void 0)=>new Promise((i=>setTimeout(i,t,e)))};!function(){try{return"production"===process.env.NODE_ENV}catch(t){return!1}}(),function(){try{const t=process.env.DEBUG;return"*"===t||"molstar"===t}catch(t){return!1}}();const Hm="undefined"!=typeof performance&&!!performance.mark&&performance.measure&&!1;var qm;function Wm(t,e,i=250){const r=function(t,e,i){const r={abortRequested:!1,treeAborted:!1,reason:""};return{updateRateMs:i,lastNotified:Pm(),observer:e,abortToken:r,taskId:t.id,root:{progress:Xm(t),children:[]},tryAbort:Ym(r)}}(t,e,i);return Qm(t,new rf(r,r.root))}function Xm(t){return{taskId:t.id,taskName:t.name,message:"",startedTime:0,canAbort:!0,isIndeterminate:!0,current:0,max:0}}function Ym(t){return e=>{t.abortRequested=!0,t.reason=e||t.reason}}function Km(t){return{progress:{...t.progress},children:t.children.map(Km)}}function Zm(t){return t.progress.canAbort&&t.children.every(Zm)}async function Qm(t,e){qm.markStart(t),e.node.progress.startedTime=Pm();try{const i=await t.f(e);return qm.markEnd(t),qm.measure(t),e.info.abortToken.abortRequested&&Jm(e.info),i}catch(i){throw sf.isAbort(i)&&(e.isAborted=!0,e.node.children.length>0&&await new Promise((t=>{e.onChildrenFinished=t})),t.onAbort&&t.onAbort()),i}}function Jm(t){throw t.abortToken.treeAborted||(t.abortToken.treeAborted=!0,tf(t.root),ef(t,Pm())),sf.Aborted(t.abortToken.reason)}function tf(t){const e=t.progress;e.isIndeterminate=!0,e.canAbort=!1,e.message="Aborting...";for(const e of t.children)tf(e)}function ef(t,e){t.lastNotified=e;const i=function(t){return{root:Km(t.root),canAbort:Zm(t.root),requestAbort:t.tryAbort}}(t);t.observer(i)}!function(t){function e(t){return`startTask${t.id}`}function i(t){return`endTask${t.id}`}t.markStart=function(t){Hm&&performance.mark(e(t))},t.markEnd=function(t){Hm&&performance.mark(i(t))},t.measure=function(t){Hm&&performance.measure(`✳️ ${t.name}`,e(t),i(t))}}(qm||(qm={}));class rf{checkAborted(){this.info.abortToken.abortRequested&&(this.isAborted=!0,Jm(this.info))}get shouldUpdate(){return this.checkAborted(),Pm()-this.lastUpdatedTime>this.info.updateRateMs}updateProgress(t){if(this.checkAborted(),!t)return;const e=this.node.progress;"string"==typeof t?(e.message=t,e.isIndeterminate=!0):(void 0!==t.canAbort&&(e.canAbort=t.canAbort),void 0!==t.message&&(e.message=t.message),void 0!==t.current&&(e.current=t.current),void 0!==t.max&&(e.max=t.max),e.isIndeterminate=void 0===e.current||void 0===e.max,void 0!==t.isIndeterminate&&(e.isIndeterminate=t.isIndeterminate))}update(t,e){if(this.lastUpdatedTime=Pm(),this.updateProgress(t),!e)return ef(this.info,this.lastUpdatedTime),this.checkAborted(),Gm.immediatePromise()}async runChild(t,e){this.updateProgress(e);const i={progress:Xm(t),children:[]},r=this.node.children;r.push(i);const n=new rf(this.info,i);try{return await Qm(t,n)}catch(t){if(sf.isAbort(t)&&this.isAborted)return;throw t}finally{const t=r.indexOf(i);if(t>=0){for(let e=t,i=r.length-1;e0;){o+=l;const e=Pm()-c;h+=e,a+=e,t.shouldUpdate&&(await n(t,i,o),s=Math.round(h*o/a)+1,c=Pm(),h=0)}return t.shouldUpdate&&await n(t,i,o),i}function df(t){return{data:t,position:0,length:t.length,lineNumber:1,tokenStart:0,tokenEnd:0}}function mf(t){for(;t.position=t.length)return void(t.tokenType=6);t.tokenStart=t.position,t.tokenEnd=t.position,t.isEscaped=!1;const i=t.data.charCodeAt(t.position);switch(i){case 35:!function(t){for(;t.position=5&&95===t.data.charCodeAt(t.tokenStart+4)?!function(t){let e=t.data.charCodeAt(t.tokenStart);return!(68!==e&&100!==e||(e=t.data.charCodeAt(t.tokenStart+1),65!==e&&97!==e||(e=t.data.charCodeAt(t.tokenStart+2),84!==e&&116!==e||(e=t.data.charCodeAt(t.tokenStart+3),65!==e&&97!==e))))}(t)?!function(t){let e=t.data.charCodeAt(t.tokenStart);return!(83!==e&&115!==e||(e=t.data.charCodeAt(t.tokenStart+1),65!==e&&97!==e||(e=t.data.charCodeAt(t.tokenStart+2),86!==e&&118!==e||(e=t.data.charCodeAt(t.tokenStart+3),69!==e&&101!==e))))}(t)?!function(t){if(t.tokenEnd-t.tokenStart!=5)return!1;let e=t.data.charCodeAt(t.tokenStart);return!(76!==e&&108!==e||(e=t.data.charCodeAt(t.tokenStart+1),79!==e&&111!==e||(e=t.data.charCodeAt(t.tokenStart+2),79!==e&&111!==e||(e=t.data.charCodeAt(t.tokenStart+3),80!==e&&112!==e))))}(t)?t.tokenType=3:t.tokenType=2:t.tokenType=1:t.tokenType=0:t.tokenType=3}}function xf(t){for(_f(t);5===t.tokenType;)_f(t)}function vf(){return{categoryNames:[],categoryData:Object.create(null)}}function wf(t,e){const i=Object.create(null);for(const r of t){const t=e[r];i[r]=Um(t.name,t.rowCount,t.fieldNames,t.fields)}return i}function Af(t,e,i){return zm(t.categoryNames,wf(t.categoryNames,t.categoryData),e,i)}function Sf(t,e){return zm(t.categoryNames,wf(t.categoryNames,t.categoryData),e)}function Cf(t,e,i,r,n){if(e in t.categoryData){const i=t.categoryData[e];i.fieldNames.push(...r),Object.assign(i.fields,n)}else t.categoryData[e]={name:e,rowCount:i,fieldNames:r,fields:n},t.categoryNames.push(e)}function Pf(t,e){const i=t.tokenStart,r=gf(t),n=yf(t,r),s=Object.create(null),o=[];let a=!0;for(;a;){if(4!==t.tokenType||!pf(t,i,r)){a=!1;break}const e=bf(t).substring(n.length+1);if(xf(t),3!==t.tokenType)return{hasError:!0,errorLine:t.lineNumber,errorMessage:"Expected value."};s[e]=Rm.ofTokens({data:t.data,indices:[t.tokenStart,t.tokenEnd],count:1}),o[o.length]=e,xf(t)}return Cf(e,n.substr(1),1,o,s),{hasError:!1,errorLine:0,errorMessage:""}}function If(t,e){const{tokenizer:i,tokens:r,fieldCount:n}=e;let s=e.tokenCount,o=0;for(;3===i.tokenType&&o0&&i.push(Af(s,n,o)),n=t.substring(r.tokenStart+5,r.tokenEnd),s=vf(),o=[],xf(r)}else if(1===e){if(r.tokenEnd-r.tokenStart==5)a.categoryNames.length>0&&(o[o.length]=Sf(a,l)),r.inSaveFrame=!1;else{if(r.inSaveFrame)return Tf(r.lineNumber,"Save frames cannot be nested.");r.inSaveFrame=!0,l=t.substring(r.tokenStart+5,r.tokenEnd),a=vf()}xf(r)}else if(2===e){const t=await Mf(r,r.inSaveFrame?a:s);if(t.hasError)return Tf(t.errorLine,t.errorMessage)}else{if(4!==e)return console.log(r.tokenType,df.getTokenString(r)),Tf(r.lineNumber,"Unexpected token. Expected data_, loop_, or data name.");{const t=Pf(r,r.inSaveFrame?a:s);if(t.hasError)return Tf(t.errorLine,t.errorMessage)}}}return r.inSaveFrame?Tf(r.lineNumber,`Unfinished save frame (${c.header}).`):((s.categoryNames.length>0||o.length>0)&&i.push(Af(s,n,o)),function(t){return lf.success(t)}(Nm(i)))}function Bf(t){return sf.create("Parse CIF",(async e=>await Df(t,e)))}!function(t){class e{run(t,e=250){return t?Wm(this,t,e):this.f(nf)}runAsChild(t,e){return t.isSynchronous?this.f(nf):function(t,e,i){return t.runChild(e,i)}(t,this,e)}runInContext(t){return t.isSynchronous?this.f(nf):function(t,e){return Qm(e,t)}(t,this)}constructor(t,e,i){this.name=t,this.f=e,this.onAbort=i,this.id=n()}}function i(t){const e=t;return!!t&&"number"==typeof e.id&&"string"==typeof e.name&&!!e.run}function r(t,i,r){return new e(t,i,r)}t.is=i,t.isAbort=function(t){return!!t&&!!t.isAborted},t.Aborted=function(t){return{isAborted:!0,reason:t,toString:()=>"Aborted"+(t?": "+t:"")}},t.create=r,t.constant=function(t,e){return r(t,(async t=>e))},t.empty=function(){return r("",(async t=>{}))},t.fail=function(t,e){return r(t,(async t=>{throw new Error(e)}))},t.resolveInContext=function(t,e){return i(t)?e?t.runInContext(e):t.run():t};const n=Dm(0,1073741823)}(sf||(sf={})),function(t){t.Synchronous=nf}(of||(of={})),function(t){function e(t,i=""){const r=t.progress;if(!t.children.length)return r.isIndeterminate?`${i}${r.taskName}: ${r.message}`:`${i}${r.taskName}: [${r.current}/${r.max}] ${r.message}`;const n=i+" |_ ",s=t.children.map((t=>e(t,n)));return r.isIndeterminate?`${i}${r.taskName}: ${r.message}\n${s.join("\n")}`:`${i}${r.taskName}: [${r.current}/${r.max}] ${r.message}\n${s.join("\n")}`}t.format=function(t){return e(t.root)}}(af||(af={})),function(t){function e(t){return t.data.substring(t.tokenStart,t.tokenEnd)}function i(t){const{data:e}=t;for(;t.position=n;)o=r.charCodeAt(--s);return t.tokenStart=n,t.tokenEnd=s+1,t.position=i,t}t.getTokenString=e,t.reset=function(t){t.position=0,t.lineNumber=1,t.tokenStart=0,t.tokenEnd=0},t.eatLine=i,t.markStart=function(t){t.tokenStart=t.position},t.markLine=r,t.readLine=function(t){return r(t),e(t)},t.readLineTrim=function(t){r(t);const i=t.position;return s(t,t.tokenStart,t.tokenEnd),t.position=i,e(t)},t.markLines=function(t,e){const i=cf.create(t.data,2*e);return n(t,e,i),i},t.readLines=function(e,i){const r=[];for(let n=0;n{const r=Math.min(e-o,t);return n(i,r,s),o+=r,r}),((t,e)=>t.update({message:"Parsing...",current:e.position,max:e.length}))),s},t.readAllLines=function(e){const i=t(e),n=cf.create(i.data,Math.max(e.length/80,2));for(;r(i);)cf.add(n,i.tokenStart,i.tokenEnd);return n},t.readAllLinesAsync=async function(e,i,n=1e5){const s=t(e),o=cf.create(s.data,Math.max(e.length/80,2));return await uf(i,n,s,((t,e)=>(function(t,e,i){let n=0;for(let s=0;st.update({message:"Parsing...",current:e.position,max:e.length}))),o},t.eatValue=function(t){for(;t.positionr.indicesLenMinus2&&function(t){const e=new Uint32Array(1.61*t.indices.length|0);e.set(t.indices),t.indices=e,t.indicesLenMinus2=e.length-2|0}(r),r.indices[r.offset++]=e,r.indices[r.offset++]=i,t.count++}t.add=e,t.addToken=function(t,i){e(t,i.tokenStart,i.tokenEnd)},t.addUnchecked=function(t,e,i){t.indices[t.offset++]=e,t.indices[t.offset++]=i,t.count++},t.create=function(t,e){return{data:t,indicesLenMinus2:(e=Math.max(10,e))-2|0,count:0,offset:0,indices:new Uint32Array(e)}}}(cf||(cf={})),function(t){t.error=function(t,i=-1){return new e(t,i)},t.success=function(t,e=[]){return new i(t,e)};class e{toString(){return this.line>=0?`[Line ${this.line}] ${this.message}`:this.message}constructor(t,e){this.message=t,this.line=e,this.isError=!0}}t.Error=e;class i{constructor(t,e){this.result=t,this.warnings=e,this.isError=!1}}t.Success=i}(lf||(lf={})),function(t){var e,i;(e=t.IntDataType||(t.IntDataType={}))[e.Int8=1]="Int8",e[e.Int16=2]="Int16",e[e.Int32=3]="Int32",e[e.Uint8=4]="Uint8",e[e.Uint16=5]="Uint16",e[e.Uint32=6]="Uint32",(i=t.FloatDataType||(t.FloatDataType={}))[i.Float32=32]="Float32",i[i.Float64=33]="Float64",t.getDataType=function(e){let i;return i=e instanceof Int8Array?t.IntDataType.Int8:e instanceof Int16Array?t.IntDataType.Int16:e instanceof Int32Array?t.IntDataType.Int32:e instanceof Uint8Array?t.IntDataType.Uint8:e instanceof Uint16Array?t.IntDataType.Uint16:e instanceof Uint32Array?t.IntDataType.Uint32:e instanceof Float32Array?t.FloatDataType.Float32:e instanceof Float64Array?t.FloatDataType.Float64:t.IntDataType.Int32,i},t.isSignedIntegerDataType=function(t){if(t instanceof Int8Array||t instanceof Int16Array||t instanceof Int32Array)return!0;for(let e=0,i=t.length;e=0;i--)e=$f(e,t.encoding[i]);return e}function $f(t,e){switch(e.kind){case"ByteArray":switch(e.type){case hf.IntDataType.Uint8:return t;case hf.IntDataType.Int8:return function(t){return new Int8Array(t.buffer,t.byteOffset)}(t);case hf.IntDataType.Int16:return function(t){return Lf(t,2,Int16Array)}(t);case hf.IntDataType.Uint16:return function(t){return Lf(t,2,Uint16Array)}(t);case hf.IntDataType.Int32:return function(t){return Lf(t,4,Int32Array)}(t);case hf.IntDataType.Uint32:return function(t){return Lf(t,4,Uint32Array)}(t);case hf.FloatDataType.Float32:return function(t){return Lf(t,4,Float32Array)}(t);case hf.FloatDataType.Float64:return function(t){return Lf(t,8,Float64Array)}(t);default:im(e.type)}case"FixedPoint":return function(t,e){const i=t.length,r=Rf(e.srcType,i),n=1/e.factor;for(let e=0;e=t.currentSize)o.set(c,a);else for(let t=0,e=c.length;t=t.currentSize&&e(t);const o=t.currentChunk,a=t.currentIndex;return o[a]=i,o[a+1]=r,o[a+2]=n,o[a+3]=s,t.currentIndex+=4,t.elementCount++},t.add3=function(t,i,r,n){t.currentIndex>=t.currentSize&&e(t);const s=t.currentChunk,o=t.currentIndex;return s[o]=i,s[o+1]=r,s[o+2]=n,t.currentIndex+=3,t.elementCount++},t.add2=function(t,i,r){t.currentIndex>=t.currentSize&&e(t);const n=t.currentChunk,s=t.currentIndex;return n[s]=i,n[s+1]=r,t.currentIndex+=2,t.elementCount++},t.add=function(t,i){return t.currentIndex>=t.currentSize&&e(t),t.currentChunk[t.currentIndex]=i,t.currentIndex+=1,t.elementCount++},t.addRepeat=function(t,i,r){for(let n=0;n=t.currentSize&&e(t),t.currentChunk[t.currentIndex++]=r,t.elementCount++;return t.elementCount},t.addMany=function(t,i){const{elementSize:r}=t;for(let n=0,s=i.length;n=t.currentSize&&e(t);const{currentChunk:s}=t;for(let e=0;e=0?Math.ceil((t+1)/e):Math.ceil((t+1)/(-e-1))}function i({limit8:t,limit16:i},r,n){r.pack8+=e(n,t),r.pack16+=e(n,i),r.count+=1}function r(t,i){t.pack8+=e(i,127),t.pack16+=e(i,32767),t.count+=1}function n(t){return 4*t.count<2*t.pack16?{length:4*t.count,elem:4}:2*t.pack16t.length-e.length)),i}t.getSize=l,t.classify=function(t){if(t.length<2)return jf.by(jf.byteArray);switch(l(t)[0].kind){case"pack":return jf.by(jf.integerPacking);case"rle":return jf.by(jf.runLength).and(jf.integerPacking);case"delta":return jf.by(jf.delta).and(jf.integerPacking);case"delta-rle":return jf.by(jf.delta).and(jf.runLength).and(jf.integerPacking);default:im()}}}(zf||(zf={})),function(t){t.classify=function(t){const{mantissaDigits:e,integerDigits:i}=function(t,e,i){let r=1,n=0;for(let s=0,o=t.length;s=0){const n=Gf(t[s],e,i);n<0?r=-1:n>r&&(r=n)}const o=Math.abs(t[s]);if(o>i){const t=Math.floor(Math.log10(Math.abs(o)))+1;t>n&&(n=t)}}return{mantissaDigits:r,integerDigits:n}}(t,4,1e-6);if(e<0||e+i>10)return jf.by(jf.byteArray);if(0===e)return zf.classify(t);const r=function(t){let e=1;for(let i=0;i=0?s/e|0:s/i|0}return r+=t.length,r}t.byteArray=r,t.fixedPoint=function(t){return e=>function(t,e){const i=hf.getDataType(t),r=new Int32Array(t.length);for(let i=0,n=t.length;ifunction(t,e,i,r,n){const s=hf.getDataType(t);if(!t.length)return{encodings:[{kind:"IntervalQuantization",min:e,max:i,numSteps:r,srcType:s}],data:new Int32Array(0)};if(i=i?r-1:0|Math.round((s-e)/o)}return{encodings:[{kind:"IntervalQuantization",min:e,max:i,numSteps:r,srcType:s}],data:a}}(n,t,e,i,r)},t.runLength=function(t){let e=hf.getDataType(t);if(void 0===e&&(t=new Int32Array(t),e=hf.IntDataType.Int32),!t.length)return{encodings:[{kind:"RunLength",srcType:e,srcSize:0}],data:new Int32Array(0)};let i=2;for(let e=1,r=t.length;e=0)for(;r>=i;)o[a]=i,++a,r-=i;else for(;r<=n;)o[a]=n,++a,r-=n;o[a]=r,++a}const c=r(o);return{encodings:[{kind:"IntegerPacking",byteCount:e.bytesPerElement,isUnsigned:!e.isSigned,srcSize:s},c.encodings[0]],data:c.data}}(t,e)},t.stringArray=function(t){const e=Object.create(null),i=[],r=new Int32Array(t.length),n=Nf.create(Int32Array,1,Math.min(1024,t.length<32?t.length+1:Math.round(t.length/8)+1));Nf.add(n,0);let s=0,o=0;for(const a of t){if(null==a){r[o++]=-1;continue}let t=e[a];void 0===t&&(s+=a.length,t=i.length,i[t]=a,e[a]=t,Nf.add(n,s)),r[o++]=t}const a=Nf.compact(n),c=Hf(a).encode(a),l=Hf(r).encode(r);return{encodings:[{kind:"StringArray",dataEncoding:l.encoding,stringData:i.join(""),offsetEncoding:c.encoding,offsets:c.data}],data:l.data}}}(jf||(jf={}));const Wf=function(){const t=[];for(let e=0;e<1024;e++)t[e]=String.fromCharCode(e);return t}();function Xf(t){throw new Error(t)}const Yf="undefined"!=typeof TextDecoder?new TextDecoder:void 0;function Kf(t,e,i){if(Yf){const r=e||i!==t.length?t.subarray(e,e+i):t;return Yf.decode(r)}return function(t,e,i){const r=Wf;let n,s=0;const o=[];for(let a=e,c=e+i;a0&&(n[n.length]=o.slice(0,s).join("")),n.join("")):o.slice(0,s).join("")}(t,e,i)}function Zf(t,e){const i={};for(let r=0;rt.name)),getField(t){const r=e[t];if(r)return i[t]||(i[t]=function(t){const e=t.mask?Ef(t.mask):void 0,i=Ef(t.data),r=Ud(i),n=r?e?t=>0===e[t]?""+i[t]:"":t=>""+i[t]:e?t=>0===e[t]?i[t]:"":t=>i[t],s=r?t=>i[t]:t=>{const e=i[t];return cm(e,0,e.length)},o=r?t=>i[t]:t=>{const e=i[t];return hm(e,0,e.length)},a=e?t=>e[t]:t=>0,c=i.length;return{__array:i,binaryEncoding:t.data.encoding,isDefined:!0,rowCount:c,str:n,int:s,float:o,valueKind:a,areValuesEqual:(t,e)=>i[t]===i[e],toStringArray:t=>zd(c,n,t),toIntArray:r?t=>Vd(i,t):t=>zd(c,s,t),toFloatArray:r?t=>Vd(i,t):t=>zd(c,o,t)}}(r)),i[t]}}}function rp(t){return sf.create("Parse BinaryCIF",(async e=>{const i=[0,3];try{const e=ep({buffer:r=t,offset:0,dataView:new DataView(r.buffer)});if(!function(t,e){for(let i=0;i<2;i++)if(t[i]>e[i])return!1;return!0}(i,e.version.match(/(\d)\.(\d)\.\d/).slice(1).map((t=>+t))))return lf.error(`Unsupported format version. Current ${e.version}, required ${i.join(".")}.`);const n=Nm(e.dataBlocks.map((t=>{const e=Object.create(null);for(const i of t.categories)e[i.name.substr(1)]=ip(i);return zm(t.categories.map((t=>t.name.substr(1))),e,t.header)})));return lf.success(n)}catch(t){return lf.error(""+t)}var r}))}var np;function sp(t,e,i){return function(t,e,i){const r=Object.create(null);for(const n of Object.keys(t))r[n]=dp(n,t[n],e,i);return Om.ofTables(e.header,t,r)}(t,e,i)}function op(t){switch(t.valueType){case"str":return(e,i,r)=>function(t,e,i,r){return{schema:t,__array:e.__array,isDefined:e.isDefined,rowCount:e.rowCount,value:"lowercase"===t.transform?t=>i(t).toLowerCase():"uppercase"===t.transform?t=>i(t).toUpperCase():i,valueKind:e.valueKind,areValuesEqual:e.areValuesEqual,toArray:"lowercase"===t.transform?t=>Array.from(r(t)).map((t=>t.toLowerCase())):"uppercase"===t.transform?t=>Array.from(r(t)).map((t=>t.toUpperCase())):r}}(t,e,e.str,e.toStringArray);case"int":return(e,i,r)=>ap(t,e,e.int,e.toIntArray);case"float":return(e,i,r)=>ap(t,e,e.float,e.toFloatArray);case"list":throw new Error("Use createListColumn instead.");case"tensor":throw new Error("Use createTensorColumn instead.")}}function ap(t,e,i,r){return{schema:t,__array:e.__array,isDefined:e.isDefined,rowCount:e.rowCount,value:i,valueKind:e.valueKind,areValuesEqual:e.areValuesEqual,toArray:r}}function cp(t,e,i){const r=t.separator,n=t.itemParse,s=e.getField(i),o=s?t=>s.str(t).split(r).map((t=>n(t.trim()))).filter((t=>!!t)):t=>[];return{schema:t,__array:void 0,isDefined:!!s,rowCount:e.rowCount,value:o,valueKind:s?s.valueKind:()=>1,areValuesEqual:(t,e)=>function(t,e){const i=t.length;if(i!==e.length)return!1;for(let r=0;rzd(e.rowCount,o,t)}}function lp(t,e,i){const r=t.space,n=e.fieldNames.includes(`${i}[0]`)||e.fieldNames.includes(`${i}[0][0]`)||e.fieldNames.includes(`${i}[0][0][0]`),s=n?0:1,o=e.fieldNames.includes(`${i}_1`)||e.fieldNames.includes(`${i}_11`)||e.fieldNames.includes(`${i}_111`)?"underscore":"brackets",a=function(t,e,i,r){const n=i?0:1;switch(e){case 1:return"brackets"===r?e=>`${t}[${e+n}]`:e=>`${t}_${e+n}`;case 2:return"brackets"===r?(e,i)=>`${t}[${e+n}][${i+n}]`:(e,i)=>`${t}_${e+n}${i+n}`;case 3:return"brackets"===r?(e,i,r)=>`${t}[${e+n}][${i+n}][${r+n}]`:(e,i,r)=>`${t}_${e+n}${i+n}${r+n}`;default:throw new Error("Tensors with rank > 3 or rank 0 are currently not supported.")}}(i,r.rank,n,o),c=e.getField(a(s,s,s))||sm.Undefined(e.rowCount,t),l=t=>function(t,e,i,r){const n=e.create();if(1===e.rank){const s=e.dimensions[0];for(let o=0;o 3 or rank 0 are currently not supported.");{const s=e.dimensions[0],o=e.dimensions[1],a=e.dimensions[2];for(let c=0;cnm.areEqualExact(l(t),l(e)),toArray:t=>zd(e.rowCount,l,t)}}!function(t){function e(t){return t.replace(".","_").replace(/\[/,"_").replace(/(\[|\])/g,"")}t.canonical=e,t.equal=function(t,i){return e(t)===e(i)},t.create=function(t,i,r=!1){const n=`${t}${i?`.${i}`:""}`;return r?e(n):n}}(np||(np={}));class hp{constructor(t,e,i){this._isDefined=i;const r=Object.keys(e);this._rowCount=t.rowCount,this._columns=r,this._schema=e;const n=Object.create(null);for(const i of r)Object.defineProperty(this,i,{get:function(){if(n[i])return n[i];const r=e[i];if("list"===r.valueType)n[i]=cp(r,t,i);else if("tensor"===r.valueType)n[i]=lp(r,t,i);else{const e=op(r),s=t.getField(i);n[i]=s?e(s,t,i):sm.Undefined(t.rowCount,r)}return n[i]},enumerable:!0,configurable:!1})}}function up(t,e,i,r){const n=np.create(e,t),s=np.canonical(n);if(s in i)return i[s];if(r&&n in r)for(const t of r[n]){const e=np.canonical(t);if(e in i)return i[e]}}function dp(t,e,i,r){let n=i.categories[t];if(r){const s=function(t){const e=Object.create(null);for(const i of Object.keys(t.categories))for(const r of t.categories[i].fieldNames)e[np.create(i,r,!0)]=t.categories[i].getField(r);return e}(i),o=Object.create(null),a=[];let c=0;for(const i of Object.keys(e)){const e=up(i,t,s,r);e&&(o[i]=e,a.push(i),c=e.rowCount)}n={rowCount:c,name:t,fieldNames:[...a],getField:t=>o[t]}}return new hp(n||Um.empty(t),e,!!n)}var mp=sm.Schema;const fp=mp.str,pp=mp.int,gp=mp.float,yp=mp.coord,bp=mp.Aliased,_p=mp.Matrix,xp=mp.Vector,vp=mp.lstr,wp=mp.List,Ap={atom_site:{auth_asym_id:fp,auth_atom_id:fp,auth_comp_id:fp,auth_seq_id:pp,B_iso_or_equiv:gp,Cartn_x:yp,Cartn_y:yp,Cartn_z:yp,group_PDB:bp(fp),id:pp,label_alt_id:fp,label_asym_id:fp,label_atom_id:fp,label_comp_id:fp,label_entity_id:fp,label_seq_id:pp,occupancy:gp,type_symbol:fp,pdbx_PDB_ins_code:fp,pdbx_PDB_model_num:pp,pdbx_formal_charge:pp,pdbx_label_index:pp,pdbx_sifts_xref_db_name:fp,pdbx_sifts_xref_db_acc:fp,pdbx_sifts_xref_db_num:fp,pdbx_sifts_xref_db_res:fp,ihm_model_id:pp},atom_site_anisotrop:{id:pp,type_symbol:fp,U:_p(3,3),U_esd:_p(3,3),pdbx_auth_seq_id:fp,pdbx_auth_asym_id:fp,pdbx_auth_atom_id:fp,pdbx_auth_comp_id:fp,pdbx_label_seq_id:pp,pdbx_label_alt_id:fp,pdbx_label_asym_id:fp,pdbx_label_atom_id:fp,pdbx_label_comp_id:fp,pdbx_PDB_ins_code:fp},atom_sites:{entry_id:fp,fract_transf_matrix:_p(3,3),fract_transf_vector:xp(3)},audit_author:{name:fp,pdbx_ordinal:pp,identifier_ORCID:fp},audit_conform:{dict_location:fp,dict_name:fp,dict_version:fp},cell:{angle_alpha:gp,angle_beta:gp,angle_gamma:gp,entry_id:fp,length_a:gp,length_b:gp,length_c:gp,Z_PDB:pp,pdbx_unique_axis:fp},chem_comp:{formula:fp,formula_weight:gp,id:fp,mon_nstd_flag:bp(vp),name:fp,type:bp(vp),pdbx_synonyms:wp(";",(t=>t))},chem_comp_bond:{atom_id_1:fp,atom_id_2:fp,comp_id:fp,value_order:bp(vp),pdbx_ordinal:pp,pdbx_stereo_config:bp(vp),pdbx_aromatic_flag:bp(vp)},citation:{book_publisher:fp,country:fp,id:fp,journal_abbrev:fp,journal_id_ASTM:fp,journal_id_CSD:fp,journal_id_ISSN:fp,journal_volume:fp,page_first:fp,page_last:fp,title:fp,year:pp,pdbx_database_id_DOI:fp,pdbx_database_id_PubMed:pp},citation_author:{citation_id:fp,name:fp,ordinal:pp},database_2:{database_id:bp(vp),database_code:fp},entity:{details:fp,formula_weight:gp,id:fp,src_method:bp(vp),type:bp(vp),pdbx_description:wp(",",(t=>t)),pdbx_number_of_molecules:pp,pdbx_mutation:fp,pdbx_fragment:fp,pdbx_ec:wp(",",(t=>t))},entity_poly:{entity_id:fp,nstd_linkage:bp(vp),nstd_monomer:bp(vp),type:bp(fp),pdbx_strand_id:wp(",",(t=>t)),pdbx_seq_one_letter_code:fp,pdbx_seq_one_letter_code_can:fp,pdbx_target_identifier:fp},entity_poly_seq:{entity_id:fp,hetero:bp(vp),mon_id:fp,num:pp},entry:{id:fp},exptl:{entry_id:fp,method:bp(fp)},software:{classification:fp,date:fp,description:fp,name:fp,type:bp(vp),version:fp,pdbx_ordinal:pp},struct:{entry_id:fp,title:fp,pdbx_descriptor:fp},struct_asym:{details:fp,entity_id:fp,id:fp,pdbx_modified:fp,pdbx_blank_PDB_chainid_flag:bp(fp)},struct_conf:{beg_label_asym_id:fp,beg_label_comp_id:fp,beg_label_seq_id:pp,beg_auth_asym_id:fp,beg_auth_comp_id:fp,beg_auth_seq_id:pp,conf_type_id:bp(vp),details:fp,end_label_asym_id:fp,end_label_comp_id:fp,end_label_seq_id:pp,end_auth_asym_id:fp,end_auth_comp_id:fp,end_auth_seq_id:pp,id:fp,pdbx_beg_PDB_ins_code:fp,pdbx_end_PDB_ins_code:fp,pdbx_PDB_helix_class:fp,pdbx_PDB_helix_length:pp,pdbx_PDB_helix_id:fp},struct_conn:{conn_type_id:bp(vp),details:fp,id:fp,ptnr1_label_asym_id:fp,ptnr1_label_atom_id:fp,ptnr1_label_comp_id:fp,ptnr1_label_seq_id:pp,ptnr1_auth_asym_id:fp,ptnr1_auth_comp_id:fp,ptnr1_auth_seq_id:pp,ptnr1_symmetry:fp,ptnr2_label_asym_id:fp,ptnr2_label_atom_id:fp,ptnr2_label_comp_id:fp,ptnr2_label_seq_id:pp,ptnr2_auth_asym_id:fp,ptnr2_auth_comp_id:fp,ptnr2_auth_seq_id:pp,ptnr2_symmetry:fp,pdbx_ptnr1_PDB_ins_code:fp,pdbx_ptnr1_label_alt_id:fp,pdbx_ptnr1_standard_comp_id:fp,pdbx_ptnr2_PDB_ins_code:fp,pdbx_ptnr2_label_alt_id:fp,pdbx_ptnr3_PDB_ins_code:fp,pdbx_ptnr3_label_alt_id:fp,pdbx_ptnr3_label_asym_id:fp,pdbx_ptnr3_label_atom_id:fp,pdbx_ptnr3_label_comp_id:fp,pdbx_ptnr3_label_seq_id:pp,pdbx_PDB_id:fp,pdbx_dist_value:gp,pdbx_value_order:bp(vp)},struct_conn_type:{criteria:fp,id:bp(vp),reference:fp},struct_keywords:{entry_id:fp,text:wp(",",(t=>t)),pdbx_keywords:fp},struct_ncs_oper:{code:bp(fp),details:fp,id:pp,matrix:_p(3,3),vector:xp(3)},struct_sheet_range:{beg_label_asym_id:fp,beg_label_comp_id:fp,beg_label_seq_id:pp,end_label_asym_id:fp,end_label_comp_id:fp,end_label_seq_id:pp,beg_auth_asym_id:fp,beg_auth_comp_id:fp,beg_auth_seq_id:pp,end_auth_asym_id:fp,end_auth_comp_id:fp,end_auth_seq_id:pp,id:fp,sheet_id:fp,pdbx_beg_PDB_ins_code:fp,pdbx_end_PDB_ins_code:fp},struct_site:{details:fp,id:fp,pdbx_num_residues:pp,pdbx_evidence_code:fp,pdbx_auth_asym_id:fp,pdbx_auth_comp_id:fp,pdbx_auth_seq_id:fp,pdbx_auth_ins_code:fp},struct_site_gen:{details:fp,id:fp,label_alt_id:fp,label_asym_id:fp,label_atom_id:fp,label_comp_id:fp,label_seq_id:pp,auth_asym_id:fp,auth_comp_id:fp,auth_seq_id:fp,site_id:fp,symmetry:fp,pdbx_auth_ins_code:fp,pdbx_num_res:pp},symmetry:{entry_id:fp,cell_setting:bp(vp),Int_Tables_number:pp,space_group_name_Hall:fp,"space_group_name_H-M":fp},pdbx_database_status:{status_code:bp(fp),status_code_sf:bp(fp),status_code_mr:bp(fp),entry_id:fp,recvd_initial_deposition_date:fp,SG_entry:bp(vp),deposit_site:bp(fp),process_site:bp(fp),status_code_cs:bp(fp),methods_development_category:bp(fp),pdb_format_compatible:bp(vp)},pdbx_nonpoly_scheme:{asym_id:fp,entity_id:fp,mon_id:fp,pdb_strand_id:fp,ndb_seq_num:fp,pdb_seq_num:fp,auth_seq_num:fp,pdb_mon_id:fp,auth_mon_id:fp,pdb_ins_code:fp},pdbx_database_related:{db_name:fp,details:fp,db_id:fp,content_type:bp(fp)},pdbx_entity_nonpoly:{entity_id:fp,comp_id:fp,name:fp},pdbx_chem_comp_synonyms:{name:fp,comp_id:fp,provenance:bp(fp)},pdbx_chem_comp_identifier:{comp_id:fp,identifier:fp,type:bp(fp),program:fp,program_version:fp},pdbx_unobs_or_zero_occ_residues:{id:pp,polymer_flag:bp(vp),occupancy_flag:bp(pp),PDB_model_num:pp,auth_asym_id:fp,auth_comp_id:fp,auth_seq_id:fp,PDB_ins_code:fp,label_asym_id:fp,label_comp_id:fp,label_seq_id:pp},pdbx_struct_mod_residue:{id:pp,auth_asym_id:fp,auth_comp_id:fp,auth_seq_id:pp,PDB_ins_code:fp,label_asym_id:fp,label_comp_id:fp,label_seq_id:pp,parent_comp_id:fp,details:fp},pdbx_struct_oper_list:{id:fp,type:bp(fp),name:fp,symmetry_operation:fp,matrix:_p(3,3),vector:xp(3)},pdbx_struct_assembly:{method_details:fp,oligomeric_details:fp,oligomeric_count:pp,details:fp,id:fp},pdbx_struct_assembly_gen:{asym_id_list:wp(",",(t=>t)),assembly_id:fp,oper_expression:fp},pdbx_reference_entity_list:{prd_id:fp,ref_entity_id:fp,type:bp(vp),details:fp,component_id:pp},pdbx_reference_entity_link:{link_id:pp,prd_id:fp,details:fp,ref_entity_id_1:fp,ref_entity_id_2:fp,entity_seq_num_1:pp,entity_seq_num_2:pp,comp_id_1:fp,comp_id_2:fp,atom_id_1:fp,atom_id_2:fp,value_order:bp(vp),component_1:pp,component_2:pp,link_class:bp(fp)},pdbx_reference_entity_poly_link:{link_id:pp,prd_id:fp,ref_entity_id:fp,component_id:pp,entity_seq_num_1:pp,entity_seq_num_2:pp,comp_id_1:fp,comp_id_2:fp,atom_id_1:fp,atom_id_2:fp,value_order:bp(vp)},pdbx_molecule:{prd_id:fp,instance_id:pp,asym_id:fp},pdbx_molecule_features:{prd_id:fp,class:bp(vp),type:bp(vp),name:fp,details:fp},entity_src_nat:{entity_id:fp,pdbx_organism_scientific:fp,pdbx_plasmid_name:fp,pdbx_src_id:pp,pdbx_beg_seq_num:pp,pdbx_end_seq_num:pp},entity_src_gen:{entity_id:fp,pdbx_gene_src_gene:wp(",",(t=>t)),pdbx_gene_src_scientific_name:fp,plasmid_name:fp,pdbx_src_id:pp,pdbx_beg_seq_num:pp,pdbx_end_seq_num:pp},pdbx_entity_src_syn:{organism_scientific:fp,entity_id:fp,pdbx_src_id:pp,pdbx_beg_seq_num:pp,pdbx_end_seq_num:pp},pdbx_entity_branch_descriptor:{entity_id:fp,descriptor:fp,type:bp(vp),program:fp,program_version:fp,ordinal:pp},pdbx_entity_instance_feature:{details:fp,feature_type:bp(fp),auth_asym_id:fp,asym_id:fp,auth_seq_num:fp,seq_num:pp,comp_id:fp,auth_comp_id:fp,ordinal:pp},pdbx_entity_branch_list:{entity_id:fp,hetero:bp(vp),comp_id:fp,num:pp},pdbx_entity_branch_link:{link_id:pp,details:fp,entity_id:fp,entity_branch_list_num_1:pp,entity_branch_list_num_2:pp,comp_id_1:fp,comp_id_2:fp,atom_id_1:fp,leaving_atom_id_1:fp,atom_stereo_config_1:bp(vp),atom_id_2:fp,leaving_atom_id_2:fp,atom_stereo_config_2:bp(vp),value_order:bp(vp)},pdbx_entity_branch:{entity_id:fp,type:bp(fp)},pdbx_branch_scheme:{entity_id:fp,hetero:bp(vp),asym_id:fp,mon_id:fp,num:pp,pdb_asym_id:fp,pdb_seq_num:fp,pdb_mon_id:fp,auth_asym_id:fp,auth_seq_num:fp,auth_mon_id:fp},pdbx_chem_comp_related:{comp_id:fp,related_comp_id:fp,relationship_type:bp(fp),details:fp},ihm_starting_model_details:{starting_model_id:fp,entity_id:fp,entity_description:fp,asym_id:fp,entity_poly_segment_id:pp,starting_model_source:bp(fp),starting_model_auth_asym_id:fp,starting_model_sequence_offset:pp,dataset_list_id:pp},ihm_starting_comparative_models:{id:pp,starting_model_id:fp,starting_model_auth_asym_id:fp,starting_model_seq_id_begin:pp,starting_model_seq_id_end:pp,template_auth_asym_id:fp,template_seq_id_begin:pp,template_seq_id_end:pp,template_sequence_identity:gp,template_sequence_identity_denominator:bp(pp),template_dataset_list_id:pp,alignment_file_id:pp},ihm_starting_model_seq_dif:{id:pp,entity_id:fp,asym_id:fp,seq_id:pp,comp_id:fp,starting_model_id:fp,db_asym_id:fp,db_seq_id:pp,db_comp_id:fp,details:fp},ihm_model_representation:{id:pp,name:fp,details:fp},ihm_model_representation_details:{id:pp,representation_id:pp,entity_poly_segment_id:pp,entity_id:fp,entity_description:fp,entity_asym_id:fp,model_object_primitive:bp(fp),starting_model_id:fp,model_mode:bp(fp),model_granularity:bp(fp),model_object_count:pp},ihm_struct_assembly_details:{id:pp,assembly_id:pp,parent_assembly_id:pp,entity_description:fp,entity_id:fp,asym_id:fp,entity_poly_segment_id:pp},ihm_struct_assembly:{id:pp,name:fp,description:fp},ihm_modeling_protocol:{id:pp,num_steps:pp,protocol_name:fp},ihm_modeling_protocol_details:{id:pp,protocol_id:pp,step_id:pp,struct_assembly_id:pp,dataset_group_id:pp,struct_assembly_description:fp,step_name:fp,step_method:fp,num_models_begin:pp,num_models_end:pp,multi_scale_flag:bp(vp),multi_state_flag:bp(vp),ordered_flag:bp(vp),script_file_id:pp,software_id:pp},ihm_multi_state_modeling:{state_id:pp,state_group_id:pp,population_fraction:gp,population_fraction_sd:gp,state_type:fp,state_name:fp,experiment_type:bp(fp),details:fp},ihm_modeling_post_process:{id:pp,protocol_id:pp,analysis_id:pp,step_id:pp,type:bp(fp),feature:bp(fp),num_models_begin:pp,num_models_end:pp},ihm_ensemble_info:{ensemble_id:pp,ensemble_name:fp,post_process_id:pp,model_group_id:pp,ensemble_clustering_method:bp(fp),ensemble_clustering_feature:bp(fp),num_ensemble_models:pp,num_ensemble_models_deposited:pp,ensemble_precision_value:gp,ensemble_file_id:pp},ihm_model_list:{model_id:pp,model_name:fp,assembly_id:pp,protocol_id:pp,representation_id:pp},ihm_model_group:{id:pp,name:fp,details:fp},ihm_model_group_link:{model_id:pp,group_id:pp},ihm_model_representative:{id:pp,model_group_id:pp,model_id:pp,selection_criteria:bp(fp)},ihm_dataset_list:{id:pp,data_type:bp(fp),database_hosted:bp(vp)},ihm_dataset_group:{id:pp,name:fp,application:bp(fp),details:fp},ihm_dataset_group_link:{dataset_list_id:pp,group_id:pp},ihm_related_datasets:{dataset_list_id_derived:pp,dataset_list_id_primary:pp},ihm_dataset_related_db_reference:{id:pp,dataset_list_id:pp,db_name:bp(fp),accession_code:fp,version:fp,details:fp},ihm_external_reference_info:{reference_id:pp,reference_provider:fp,reference_type:bp(fp),reference:fp,refers_to:bp(fp),associated_url:fp},ihm_external_files:{id:pp,reference_id:pp,file_path:fp,content_type:bp(fp),file_size_bytes:gp,details:fp},ihm_dataset_external_reference:{id:pp,dataset_list_id:pp,file_id:pp},ihm_localization_density_files:{id:pp,file_id:pp,ensemble_id:pp,entity_id:fp,entity_poly_segment_id:pp,asym_id:fp},ihm_predicted_contact_restraint:{id:pp,group_id:pp,entity_id_1:fp,entity_id_2:fp,asym_id_1:fp,asym_id_2:fp,comp_id_1:fp,comp_id_2:fp,seq_id_1:pp,seq_id_2:pp,rep_atom_1:bp(fp),rep_atom_2:bp(fp),distance_lower_limit:gp,distance_upper_limit:gp,probability:gp,restraint_type:bp(fp),model_granularity:bp(fp),dataset_list_id:pp,software_id:pp},ihm_cross_link_list:{id:pp,group_id:pp,entity_description_1:fp,entity_description_2:fp,entity_id_1:fp,entity_id_2:fp,comp_id_1:fp,comp_id_2:fp,seq_id_1:pp,seq_id_2:pp,linker_type:bp(fp),dataset_list_id:pp},ihm_cross_link_restraint:{id:pp,group_id:pp,entity_id_1:fp,entity_id_2:fp,asym_id_1:fp,asym_id_2:fp,comp_id_1:fp,comp_id_2:fp,seq_id_1:pp,seq_id_2:pp,atom_id_1:fp,atom_id_2:fp,restraint_type:bp(fp),conditional_crosslink_flag:bp(fp),model_granularity:bp(fp),distance_threshold:gp,psi:gp,sigma_1:gp,sigma_2:gp},ihm_cross_link_result_parameters:{id:pp,restraint_id:pp,model_id:pp,psi:gp,sigma_1:gp,sigma_2:gp},ihm_2dem_class_average_restraint:{id:pp,dataset_list_id:pp,number_raw_micrographs:pp,pixel_size_width:gp,pixel_size_height:gp,image_resolution:gp,image_segment_flag:bp(vp),number_of_projections:pp,struct_assembly_id:pp,details:fp},ihm_2dem_class_average_fitting:{id:pp,restraint_id:pp,model_id:pp,cross_correlation_coefficient:gp,rot_matrix:_p(3,3),tr_vector:xp(3)},ihm_3dem_restraint:{id:pp,dataset_list_id:pp,model_id:pp,struct_assembly_id:pp,fitting_method:fp,number_of_gaussians:pp,cross_correlation_coefficient:gp},ihm_sas_restraint:{id:pp,dataset_list_id:pp,model_id:pp,struct_assembly_id:pp,profile_segment_flag:bp(vp),fitting_atom_type:fp,fitting_method:fp,fitting_state:bp(fp),radius_of_gyration:gp,chi_value:gp,details:fp},ihm_starting_model_coord:{ordinal_id:pp,starting_model_id:fp,group_PDB:bp(fp),id:pp,type_symbol:fp,entity_id:fp,atom_id:fp,comp_id:fp,seq_id:pp,asym_id:fp,Cartn_x:gp,Cartn_y:gp,Cartn_z:gp,B_iso_or_equiv:gp},ihm_sphere_obj_site:{id:pp,entity_id:fp,seq_id_begin:pp,seq_id_end:pp,asym_id:fp,Cartn_x:gp,Cartn_y:gp,Cartn_z:gp,object_radius:gp,rmsf:gp,model_id:pp},ihm_gaussian_obj_site:{id:pp,entity_id:fp,seq_id_begin:pp,seq_id_end:pp,asym_id:fp,mean_Cartn_x:gp,mean_Cartn_y:gp,mean_Cartn_z:gp,weight:gp,covariance_matrix:_p(3,3),model_id:pp},ihm_gaussian_obj_ensemble:{id:pp,entity_id:fp,seq_id_begin:pp,seq_id_end:pp,asym_id:fp,mean_Cartn_x:gp,mean_Cartn_y:gp,mean_Cartn_z:gp,weight:gp,covariance_matrix:_p(3,3),ensemble_id:pp},ihm_feature_list:{feature_id:pp,feature_type:bp(fp),entity_type:bp(fp)},ihm_poly_residue_feature:{ordinal_id:pp,feature_id:pp,entity_id:fp,asym_id:fp,comp_id_begin:fp,comp_id_end:fp,seq_id_begin:pp,seq_id_end:pp},ihm_derived_distance_restraint:{id:pp,group_id:pp,feature_id_1:pp,feature_id_2:pp,group_conditionality:bp(fp),random_exclusion_fraction:gp,distance_upper_limit:gp,restraint_type:bp(fp),dataset_list_id:pp},ma_model_list:{ordinal_id:pp,model_id:pp,model_group_id:pp,model_name:fp,model_group_name:fp,model_type:bp(fp),data_id:pp},ma_target_entity:{entity_id:fp,data_id:pp,origin:bp(fp)},ma_target_entity_instance:{asym_id:fp,entity_id:fp,details:fp},ma_target_ref_db_details:{target_entity_id:fp,db_name:bp(fp),db_code:fp,db_accession:fp,seq_db_isoform:fp,seq_db_align_begin:fp,seq_db_align_end:fp,ncbi_taxonomy_id:fp,organism_scientific:fp},ma_data:{id:pp,content_type:bp(fp),content_type_other_details:fp,name:fp},ma_software_group:{ordinal_id:pp,group_id:pp,software_id:pp},ma_qa_metric:{id:pp,name:fp,type:bp(fp),mode:bp(fp),software_group_id:pp},ma_qa_metric_global:{ordinal_id:pp,model_id:pp,metric_id:pp,metric_value:gp},ma_qa_metric_local:{ordinal_id:pp,model_id:pp,label_asym_id:fp,label_seq_id:pp,label_comp_id:fp,metric_id:pp,metric_value:gp}};var Sp=sm.Schema;const Cp=Sp.str,Pp=Sp.float,Ip=Sp.List,kp=Sp.lstr,Mp=Sp.Aliased,Tp=Sp.int,Dp=Sp.coord,Bp={chem_comp:{formula:Cp,formula_weight:Pp,id:Cp,mon_nstd_parent_comp_id:Ip(",",(t=>t)),name:Cp,one_letter_code:Cp,three_letter_code:Cp,type:Mp(kp),pdbx_synonyms:Ip(";",(t=>t)),pdbx_type:Cp,pdbx_ambiguous_flag:Cp,pdbx_replaced_by:Cp,pdbx_replaces:Cp,pdbx_formal_charge:Tp,pdbx_model_coordinates_details:Cp,pdbx_model_coordinates_db_code:Cp,pdbx_ideal_coordinates_details:Cp,pdbx_ideal_coordinates_missing_flag:Mp(kp),pdbx_model_coordinates_missing_flag:Mp(kp),pdbx_initial_date:Cp,pdbx_modified_date:Cp,pdbx_release_status:Mp(Cp),pdbx_processing_site:Mp(Cp)},chem_comp_atom:{alt_atom_id:Cp,atom_id:Cp,charge:Tp,model_Cartn_x:Dp,model_Cartn_y:Dp,model_Cartn_z:Dp,comp_id:Cp,type_symbol:Cp,pdbx_align:Tp,pdbx_ordinal:Tp,pdbx_model_Cartn_x_ideal:Dp,pdbx_model_Cartn_y_ideal:Dp,pdbx_model_Cartn_z_ideal:Dp,pdbx_stereo_config:Mp(kp),pdbx_aromatic_flag:Mp(kp),pdbx_leaving_atom_flag:Mp(kp)},chem_comp_bond:{atom_id_1:Cp,atom_id_2:Cp,comp_id:Cp,value_order:Mp(kp),pdbx_ordinal:Tp,pdbx_stereo_config:Mp(kp),pdbx_aromatic_flag:Mp(kp)},pdbx_chem_comp_descriptor:{comp_id:Cp,descriptor:Cp,type:Mp(kp),program:Cp,program_version:Cp},pdbx_chem_comp_identifier:{comp_id:Cp,identifier:Cp,type:Mp(Cp),program:Cp,program_version:Cp}};var Fp=sm.Schema;const Ep=Fp.str,$p=Fp.float,Op=Fp.lstr,Rp=Fp.Aliased,Lp=Fp.int,Np={pdbx_reference_molecule:{prd_id:Ep,formula_weight:$p,formula:Ep,type:Rp(Op),type_evidence_code:Ep,class:Rp(Op),class_evidence_code:Ep,name:Ep,represent_as:Rp(Op),chem_comp_id:Ep,compound_details:Ep,description:Ep,representative_PDB_id_code:Ep,release_status:Rp(Op),replaces:Ep,replaced_by:Ep},pdbx_reference_entity_list:{prd_id:Ep,ref_entity_id:Ep,type:Rp(Op),details:Ep,component_id:Lp},pdbx_reference_entity_nonpoly:{prd_id:Ep,ref_entity_id:Ep,name:Ep,chem_comp_id:Ep},pdbx_reference_entity_link:{link_id:Lp,prd_id:Ep,details:Ep,ref_entity_id_1:Ep,ref_entity_id_2:Ep,entity_seq_num_1:Lp,entity_seq_num_2:Lp,comp_id_1:Ep,comp_id_2:Ep,atom_id_1:Ep,atom_id_2:Ep,value_order:Rp(Op),component_1:Lp,component_2:Lp,link_class:Rp(Ep)},pdbx_reference_entity_poly_link:{link_id:Lp,prd_id:Ep,ref_entity_id:Ep,component_id:Lp,entity_seq_num_1:Lp,entity_seq_num_2:Lp,comp_id_1:Ep,comp_id_2:Ep,atom_id_1:Ep,atom_id_2:Ep,value_order:Rp(Op)},pdbx_reference_entity_poly:{prd_id:Ep,ref_entity_id:Ep,type:Rp(Ep),db_code:Ep,db_name:Ep},pdbx_reference_entity_poly_seq:{prd_id:Ep,ref_entity_id:Ep,mon_id:Ep,parent_mon_id:Ep,num:Lp,observed:Rp(Op),hetero:Rp(Op)},pdbx_reference_entity_sequence:{prd_id:Ep,ref_entity_id:Ep,type:Rp(Ep),NRP_flag:Rp(Ep),one_letter_codes:Ep},pdbx_reference_entity_src_nat:{prd_id:Ep,ref_entity_id:Ep,ordinal:Lp,organism_scientific:Ep,taxid:Ep,db_code:Ep,db_name:Ep},pdbx_prd_audit:{prd_id:Ep,date:Ep,processing_site:Rp(Ep),action_type:Rp(Ep)}};var zp=sm.Schema;const Up=zp.str,Vp={datablock:{id:Up,description:Up},dictionary:{title:Up,datablock_id:Up,version:Up},dictionary_history:{version:Up,update:Up,revision:Up},sub_category:{id:Up,description:Up},category_group_list:{id:Up,parent_id:Up,description:Up},item_type_list:{code:Up,primitive_code:Up,construct:Up,detail:Up},item_units_list:{code:Up,detail:Up},item_units_conversion:{from_code:Up,to_code:Up,operator:Up,factor:zp.float}};var jp=sm.Schema;const Gp=jp.str,Hp=jp.int,qp=jp.float,Wp=jp.Aliased,Xp=jp.Vector;Wp(Gp),Wp(Gp),Wp(Gp),Wp(Gp),Xp(3),Xp(3);const Yp={volume_data_3d_info:{name:Gp,axis_order:Xp(3,Hp),origin:Xp(3),dimensions:Xp(3),sample_rate:Hp,sample_count:Xp(3,Hp),spacegroup_number:Hp,spacegroup_cell_size:Xp(3),spacegroup_cell_angles:Xp(3),mean_source:qp,mean_sampled:qp,sigma_source:qp,sigma_sampled:qp,min_source:qp,min_sampled:qp,max_source:qp,max_sampled:qp},volume_data_3d:{values:qp}};var Kp=sm.Schema;const Zp=Kp.float,Qp=Kp.int,Jp=Kp.str,tg={cell:{angle_alpha:Zp,angle_beta:Zp,angle_gamma:Zp,formula_units_z:Qp,length_a:Zp,length_b:Zp,length_c:Zp,volume:Zp},chemical:{melting_point:Zp,name_common:Jp,name_systematic:Jp},chemical_formula:{moiety:Jp,sum:Jp,weight:Zp},space_group:{crystal_system:Jp,it_number:Qp,"name_h-m_full":Jp},space_group_symop:{operation_xyz:Jp},geom_bond:{atom_site_label_1:Jp,atom_site_label_2:Jp,distance:Zp,publ_flag:Jp,site_symmetry_1:Jp,site_symmetry_2:Jp,valence:Zp},audit:{block_doi:Jp},database_code:{cod:Jp,csd:Jp,depnum_ccdc_archive:Jp,depnum_ccdc_fiz:Jp,icsd:Jp,mdf:Jp,nbs:Jp},atom_site:{adp_type:Jp,calc_flag:Jp,disorder_assembly:Jp,disorder_group:Jp,fract_x:Zp,fract_y:Zp,fract_z:Zp,label:Jp,occupancy:Zp,refinement_flags:Jp,site_symmetry_multiplicity:Qp,type_symbol:Jp,u_iso_or_equiv:Zp},atom_site_aniso:{label:Jp,u_11:Zp,u:(0,Kp.Matrix)(3,3),u_12:Zp,u_13:Zp,u_22:Zp,u_23:Zp,u_33:Zp},atom_type:{description:Jp,symbol:Jp},atom_type_scat:{dispersion_imag:Zp,dispersion_real:Zp,source:Jp}},eg={"cell.formula_units_z":["cell_formula_units_Z"],"space_group.it_number":["space_group_IT_number","symmetry_Int_Tables_number"],"space_group.name_h-m_full":["symmetry_space_group_name_H-M"],"space_group_symop.operation_xyz":["symmetry_equiv_pos_as_xyz"],"geom_bond.atom_site_label_1":["geom_bond_atom_site_id_1"],"geom_bond.atom_site_label_2":["geom_bond_atom_site_id_2"],"geom_bond.distance":["geom_bond_dist"],"audit.block_doi":["audit_block_DOI"],"database_code.cod":["database_code_COD"],"database_code.csd":["database_code_CSD"],"database_code.depnum_ccdc_archive":["database_code_depnum_CCDC_archive"],"database_code.depnum_ccdc_fiz":["database_code_depnum_CCDC_fiz"],"database_code.icsd":["database_code_ICSD"],"database_code.mdf":["database_code_MDF"],"database_code.nbs":["database_code_NBS"],"atom_site.adp_type":["atom_site_ADP_type","atom_site_thermal_displace_type"],"atom_site.label":["atom_site_id"],"atom_site.site_symmetry_multiplicity":["atom_site_symmetry_multiplicity"],"atom_site.u_iso_or_equiv":["atom_site_U_iso_or_equiv"],"atom_site_aniso.label":["atom_site_anisotrop_id"],"atom_site_aniso.u_11":["atom_site_aniso_U_11","atom_site_anisotrop_U_11"],"atom_site_aniso.u_12":["atom_site_aniso_U_12","atom_site_anisotrop_U_12"],"atom_site_aniso.u_13":["atom_site_aniso_U_13","atom_site_anisotrop_U_13"],"atom_site_aniso.u_22":["atom_site_aniso_U_22","atom_site_anisotrop_U_22"],"atom_site_aniso.u_23":["atom_site_aniso_U_23","atom_site_anisotrop_U_23"],"atom_site_aniso.u_33":["atom_site_aniso_U_33","atom_site_anisotrop_U_33"]};const ig=sm.Schema.int,rg={volume_data_3d_info:Yp.volume_data_3d_info,segmentation_data_table:{set_id:ig,segment_id:ig},segmentation_data_3d:{values:ig}},ng={parse:t=>"string"==typeof t?Bf(t):rp(t),parseText:Bf,parseBinary:rp,toDatabaseCollection:function(t,e,i){const r={};for(const n of e.blocks)r[n.header]=sp(t,n,i);return r},toDatabase:sp,schema:{mmCIF:t=>sp(Ap,t),CCD:t=>sp(Bp,t),BIRD:t=>sp(Np,t),dic:t=>sp(Vp,t),cifCore:t=>sp(tg,t,eg),densityServer:t=>sp(Yp,t),segmentation:t=>sp(rg,t)}};class sg{constructor(t,e){var i=e||{};this.streamer=t,this.name=rt(i.name,""),this.path=rt(i.path,"")}get type(){return""}get __objName(){return""}get isBinary(){return!1}get isJson(){return!1}get isXml(){return!1}parse(){return this.streamer.read().then((()=>Nl(this,void 0,void 0,(function*(){return yield this._beforeParse(),yield this._parse(),yield this._afterParse(),this[this.__objName]}))))}_parse(){}_beforeParse(){}_afterParse(){De&&ke.log(this[this.__objName])}}class og extends sg{constructor(t,e){var i=e||{};super(t,i),this.firstModelOnly=rt(i.firstModelOnly,!1),this.asTrajectory=rt(i.asTrajectory,!1),this.cAlphaOnly=rt(i.cAlphaOnly,!1),this.structure=new Sc(this.name,this.path),this.structureBuilder=new Na(this.structure)}get type(){return"structure"}get __objName(){return"structure"}}class ag{constructor(t,e,i="",r,n=[]){this.structure=t,this.index=e,this.description=i,this.entityType=function(t){switch(t=t.toLowerCase()){case"polymer":return 1;case"non-polymer":return 2;case"macrolide":return 3;case"water":return 4;default:return 0}}(r||""),this.chainIndexList=n,n.forEach((function(i){t.chainStore.entityIndex[i]=e}))}get type(){return function(t){switch(t){case 1:return"polymer";case 2:return"non-polymer";case 3:return"macrolide";case 4:return"water";default:return}}(this.entityType)}getEntityType(){return this.entityType}isPolymer(){return 1===this.entityType}isNonPolymer(){return 2===this.entityType}isMacrolide(){return 3===this.entityType}isWater(){return 4===this.entityType}eachChain(t){const e=this.structure.getChainProxy();this.chainIndexList.forEach((function(i){e.index=i,t(e)}))}}const cg={a:1,b:1,c:1,alpha:90,beta:90,gamma:90,spacegroup:"P 1"};class lg{constructor(t=cg){this.cartToFrac=new i,this.fracToCart=new i,this.a=t.a,this.b=t.b,this.c=t.c,this.alpha=t.alpha,this.beta=t.beta,this.gamma=t.gamma,this.spacegroup=t.spacegroup;const e=It(this.alpha),r=It(this.beta),n=It(this.gamma),s=Math.cos(e),o=Math.cos(r),a=Math.cos(n),c=Math.sin(r),l=Math.sin(n);if(this.volume=this.a*this.b*this.c*Math.sqrt(1-s*s-o*o-a*a+2*s*o*a),void 0===t.cartToFrac){const t=this.a*this.b*l/this.volume,e=(o*a-s)/(c*l);this.fracToCart.set(this.a,0,0,0,this.b*a,this.b*l,0,0,this.c*o,-this.c*c*e,1/t,0,0,0,0,1).transpose(),this.cartToFrac.copy(this.fracToCart).invert()}else this.cartToFrac.copy(t.cartToFrac),this.fracToCart.copy(this.cartToFrac).invert()}getPosition(t){const i=new Float32Array(24);if(t.unitcell){const r=t.unitcell,n=t.center.clone().applyMatrix4(r.cartToFrac).floor(),s=new e;let o=0;const a=function(t,e,a){s.set(t,e,a).add(n).applyMatrix4(r.fracToCart).toArray(i,o),o+=3};a(0,0,0),a(1,0,0),a(0,1,0),a(0,0,1),a(1,1,0),a(1,0,1),a(0,1,1),a(1,1,1)}return i}getCenter(t){return function(t,i=new e){const r=t.length;for(let e=0;e0)continue;let e,i,r,n,a,g=0;if(s){if(n=S.split(mg),g=10===n.length?1:0,B=n[2],f&&"CA"!==B)continue;e=parseFloat(n[6-g]),i=parseFloat(n[7-g]),r=parseFloat(n[8-g])}else{if(B=S.substr(12,4).trim(),f&&"CA"!==B)continue;e=parseFloat(S.substr(30,8)),i=parseFloat(S.substr(38,8)),r=parseFloat(S.substr(46,8))}if(m){const t=3*b;if(y[t+0]=e,y[t+1]=i,y[t+2]=r,b+=1,_)continue}s?(P=parseInt(n[1]),a="",F="H"===S[0],I=g?"":n[4],k=parseInt(n[5-g]),D="",M=n[3],$="",T=1):(P=parseInt(S.substr(6,5),h),l&&99999===P&&(h=16),F="H"===S[0],I=S[21].trim(),k=parseInt(S.substr(22,4),u),l&&9999===k&&(u=16),D=S[26].trim(),M=S.substr(17,4).trim()||"MOL",E=parseFloat(S.substr(60,6)),$=S[16].trim(),T=parseFloat(S.substr(54,6)),t||(o?(a=S.substr(76,3).trim(),a in ms&&(a=ms[a])):(a=S.substr(76,2).trim(),I||(I=S.substr(72,4).trim())),O=parseInt((S.substr(79,1)+S.substr(78,1)).trim()))),ut.growIfFull(),ut.atomTypeId[ft]=ht.add(B,a),ut.x[ft]=e,ut.y[ft]=i,ut.z[ft]=r,ut.serial[ft]=P,ut.altloc[ft]=$.charCodeAt(0),ut.occupancy[ft]=isNaN(T)?0:T,s?(ut.partialCharge[ft]=parseFloat(n[9-g]),ut.radius[ft]=parseFloat(n[10-g])):(ut.bfactor[ft]=isNaN(E)?0:E,o&&(ut.partialCharge[ft]=parseFloat(S.substr(70,6))),isFinite(O)&&(ut.formalCharge||ut.addField("formalCharge",1,"int8"),ut.formalCharge[ft]=O));const x=fg(k,I,D);!F||K[x]||ug.includes(M)?tt||et===I||(Q+=1,J=Q.toString()):et===I&&rt===M&&(as.includes(M)||it===k&&nt===D)||(Q+=1,J=Q.toString(),it=k,rt=M,nt=D),c.addAtom(pt,I,J,M,k,F,void 0,D),j[P]=ft,ft+=1,tt=!1,et=I}else if("CONECT"===C){const t=j[parseInt(S.substr(6,5))],e=[11,16,21,26],i={};if(void 0===t)continue;for(let r=0;r<4;++r){let n=parseInt(S.substr(e[r],5));if(!Number.isNaN(n)&&(n=j[n],void 0!==n))if(t{var i;return[null===(i=n.get(t))||void 0===i?void 0:i.atomname,e]}))),o=[],a=[],c=[];let l,h;for(let t=0;t{var b;const _=c.getField(f),x=c.getField(p),v=c.getField(g),w=y*o;for(let c=0;cc*c)return a.growIfFull(),a.atomTypeId[w]=a.atomTypeId[t],a.x[w]=_.x,a.y[w]=_.y,a.z[w]=_.z,a.occupancy[w]=a.occupancy[t],a.serial[w]=w,a.altloc[w]="A".charCodeAt(0),n.addAtom(0,"","","HET",1,!0),void(w+=1)}}}))}}(B,A,S),S.finalize(),A.finalizeAtoms(),Ha(A),A.finalizeBonds();else{const e={},T={},D=A.atomMap,F=A.atomStore,E=B.categories.atom_site;let $=E.rowCount;const O=E.getField("pdbx_PDB_model_num");if(!(null===(t=null==O?void 0:O.areValuesEqual(0,$-1))||void 0===t||t)&&(P||C)){const t=O.int(0);for(let e=0;e<$;e++)if(O.int(e)>t){$=e;break}}A.chemCompMap=new gg(A);const R=B.categories.chem_comp;let L=R.getField("id");const N=R.getField("type");for(let t=0;t{const r=t.getField(e);return r?r.toFloatArray({array:Float32Array,start:0,end:i}):new Float32Array(i)};F.resize($),F.x=z(E,"Cartn_x",$),F.y=z(E,"Cartn_y",$),F.z=z(E,"Cartn_z",$),F.serial=E.getField("id").toIntArray({start:0,end:$}),F.bfactor=z(E,"B_iso_or_equiv",$),F.occupancy=z(E,"occupancy",$);const U=E.getField("label_alt_id");(null==U?void 0:U.isDefined)&&(F.altloc=Uint8Array.from(U.toStringArray(),(t=>t.charCodeAt(0))));const V=E.getField("label_atom_id"),j=E.getField("type_symbol");L=E.getField("label_comp_id");const G=null!==(r=E.getField("auth_seq_id"))&&void 0!==r?r:E.getField("label_seq_id"),H=E.getField("pdbx_PDB_ins_code"),q=E.getField("auth_asym_id"),W=E.getField("label_asym_id"),X=E.getField("group_PDB"),Y=E.getField("label_entity_id");for(let t=0;t<$;t++){const i=null!==(n=null==O?void 0:O.int(t))&&void 0!==n?n:1,r=null!==(s=null==q?void 0:q.str(t))&&void 0!==s?s:"",u=null!==(o=null==W?void 0:W.str(t))&&void 0!==o?o:"",d=null!==(a=null==L?void 0:L.str(t))&&void 0!==a?a:"",m=null!==(c=null==G?void 0:G.int(t))&&void 0!==c?c:0,f="H"===(null==X?void 0:X.str(t)[0]),p=null!==(l=null==H?void 0:H.str(t))&&void 0!==l?l:"",g=null!==(h=null==Y?void 0:Y.int(t))&&void 0!==h?h:1;F.atomTypeId[t]=D.add((null==V?void 0:V.str(t))||"",null==j?void 0:j.str(t)),S.addAtom(i-1,r,u,d,m,f,void 0,p),e[u]=r,T[g]||(T[g]=new Set),T[g].add(A.chainStore.count-1)}if(P){const t=E.rowCount/$|0,e=E.getField("Cartn_x"),i=E.getField("Cartn_y"),r=E.getField("Cartn_z");for(let n=0;n0){const[t,e]=h.split("(").filter((t=>!!t)),r=o(t),s=o(e);Object.keys(r).forEach((function(t){Object.keys(s).forEach((function(e){const o=new i;o.multiplyMatrices(r[t],s[e]),n[t+"x"+e]=o}))}))}else n=o(h);const u=[];for(let t in n)u.push(n[t]);let d=""+e;/^(0|[1-9][0-9]*)$/.test(d)&&(d="BU"+d);const m=l.str(t).split(",").map((t=>r[t]));void 0===s[d]&&(s[d]=new Ra(d)),s[d].addPart(u,m)}}if(t.struct_ncs_oper){const e=t.struct_ncs_oper,r="NCS";s[r]=new Ra(r);const n=s[r].addPart(),o=e.getField("code"),a=e.getField("matrix[1][1]"),c=e.getField("matrix[1][2]"),l=e.getField("matrix[1][3]"),h=e.getField("matrix[2][1]"),u=e.getField("matrix[2][2]"),d=e.getField("matrix[2][3]"),m=e.getField("matrix[3][1]"),f=e.getField("matrix[3][2]"),p=e.getField("matrix[3][3]"),g=e.getField("vector[1]"),y=e.getField("vector[2]"),b=e.getField("vector[3]");for(let t=0;ts&&([n,s]=[s,n],[P,T]=[T,P]),0!==n&&0!==s)for(let i=0;ib)continue}u=I.substr(5,5).trim(),d=parseInt(I.substr(0,5)),m=parseInt(I.substr(15,5)),x.growIfFull(),x.atomTypeId[v]=_.add(h),x.x[v]=T,x.y[v]=D,x.z[v]=B,x.serial[v]=m,r.addAtom(w,"","",u,d,!1,"l"),v+=1}}}(0,i.length,i)})),r.finalize(),i.finalizeAtoms(),Ga(i),Ha(i),i.finalizeBonds(),Ua(i),De&&ke.timeEnd("GroParser._parse "+this.name)}});var wg=["mmtfVersion","mmtfProducer","unitCell","spaceGroup","structureId","title","depositionDate","releaseDate","experimentalMethods","resolution","rFree","rWork","bioAssemblyList","ncsOperatorList","entityList","groupList","numBonds","numAtoms","numGroups","numChains","numModels","groupsPerChain","chainsPerModel"].concat(["xCoordList","yCoordList","zCoordList","groupIdList","groupTypeList","chainIdList","bFactorList","atomIdList","altLocList","occupancyList","secStructList","insCodeList","sequenceIndexList","chainNameList","bondAtomList","bondOrderList"]);function Ag(t,e,i){return e?new t(e.buffer,e.byteOffset,e.byteLength/(i||1)):void 0}function Sg(t){return Ag(DataView,t)}function Cg(t){return Ag(Int8Array,t)}function Pg(t){return Ag(Int32Array,t,4)}function Ig(t,e){var i=t.length/2;e||(e=new Int16Array(i));for(var r=0,n=0;rs&&++a;e=new Int32Array(a)}for(i=0,r=0;in){for(var s=[],o=0;o0&&(o.biomolDict[t]=e)}const E=a.unitCell;E&&Array.isArray(E)&&E[0]?o.unitcell=new lg({a:E[0],b:E[1],c:E[2],alpha:E[3],beta:E[4],gamma:E[5],spacegroup:a.spaceGroup}):o.unitcell=void 0,Ya(o,!0),Xa(o,!0),o.finalizeAtoms(),o.finalizeBonds(),Ka(o),De&&ke.timeEnd("MmtfParser._parse "+this.name)}});const Ng=/\s+/,zg={1:1,2:2,3:3,am:1,ar:1,du:1,un:1,nc:0};Ne.add("mol2",class extends og{get type(){return"mol2"}_parse(){De&&ke.time("Mol2Parser._parse "+this.name);const t=this.structure,e=this.structureBuilder,i=this.firstModelOnly,r=this.asTrajectory,n=t.frames;let s,o,a=!1;const c=t.atomMap,l=t.atomStore;l.resize(Math.round(this.streamer.data.length/60)),l.addField("partialCharge",1,"float32");let h=0,u=0,d=0,m=-1,f=0,p=0;const g=t.getAtomProxy(),y=t.getAtomProxy();this.streamer.eachChunkOfLines((function(b){!function(b,_,x){for(let v=b;v<_;++v){const b=x[v].trim();if(""!==b&&"#"!==b[0])if("@"===b[0])"@MOLECULE"===b?(p=1,u=0,++m):"@ATOM"===b?(p=2,d=l.count,r&&(o=0,s=new Float32Array(3*f),n.push(s),m>0&&(a=!0))):p="@BOND"===b?3:0;else if(1===p){if(0===u)t.title=b,t.id=b;else if(1===u){const t=b.split(Ng);f=parseInt(t[0])}++u}else if(2===p){const t=b.split(Ng);if(i&&m>0)continue;const n=parseFloat(t[2]),u=parseFloat(t[3]),d=parseFloat(t[4]);if(r){const t=3*o;if(s[t+0]=n,s[t+1]=u,s[t+2]=d,o+=1,a)continue}const f=t[0],p=t[1],g=t[5].split(".")[0],y=t[6]?parseInt(t[6]):1,_=t[7]?t[7]:"",x=t[8]?parseFloat(t[8]):0;l.growIfFull(),l.atomTypeId[h]=c.add(p,g),l.x[h]=n,l.y[h]=u,l.z[h]=d,l.serial[h]=+f,l.partialCharge[h]=x,e.addAtom(m,"","",_,y,!0),h+=1}else if(3===p){if(i&&m>0)continue;if(r&&m>0)continue;const e=b.split(Ng);g.index=parseInt(e[1])-1+d,y.index=parseInt(e[2])-1+d;const n=zg[e[3]];t.bondStore.addBond(g,y,n)}}}(0,b.length,b)})),e.finalize(),t.finalizeAtoms(),Ga(t),Xa(t,!0),Ya(t,!0),t.finalizeBonds(),tc(t),Ua(t),De&&ke.timeEnd("Mol2Parser._parse "+this.name)}});Ne.add("pdbqt",class extends pg{get type(){return"pdbqt"}});Ne.add("pqr",class extends pg{get type(){return"pqr"}});const Ug=/> +<(.+)>/;class Vg extends og{get type(){return"sdf"}_parse(){De&&ke.time("SdfParser._parse "+this.name);const t=this.structure,e=this.structureBuilder,i=this.firstModelOnly,r=this.asTrajectory,n=this.streamer.peekLines(2);t.id=n[0].trim(),t.title=n[1].trim();const s=t.frames;let o,a,c=!1;const l=t.atomMap,h=t.atomStore;h.resize(Math.round(this.streamer.data.length/50)),h.addField("formalCharge",1,"int8");const u=t.getAtomProxy(),d=t.getAtomProxy();let m=0,f=0,p=0,g=0;const y=[];let b,_,x,v,w,A,S,C,P,I,k,M,T,D,B=!1,F={};t.extraData.sdf=y;let E=!1,$=!1,O=!1,R=[],L=[];const N=new Map;this.streamer.eachChunkOfLines((function(n){!function(n,z,U){for(let V=n;V-1,E?N.clear():(_=parseInt(n.substr(0,3)),x=parseInt(n.substr(3,3)),v=4,w=v+_,A=w,S=A+x,r&&(a=0,o=new Float32Array(3*_),s.push(o),p>0&&(c=!0)));else if(E&&"COUNTS"===R[0])_=parseInt(R[1]),r&&(a=0,o=new Float32Array(3*_),s.push(o),p>0&&(c=!0));else if(E&&2==R.length)"ATOM"===R[1]?"BEGIN"===R[0]?$=!0:"END"===R[0]&&($=!1):"BOND"===R[1]&&("BEGIN"===R[0]?O=!0:"END"===R[0]&&(O=!1));else if($||!E&&f>=v&&f0)continue;let t=0;if(E){if(C=parseFloat(R[2]),P=parseFloat(R[3]),I=parseFloat(R[4]),M=R[1],T=parseInt(R[0]),N.set(T,m),k=M+T,R.length>6){let e=R.slice(6).find((t=>0===t.indexOf("CHG=")));e&&(t=parseInt(e.substring(4)))}}else C=parseFloat(n.substr(0,10)),P=parseFloat(n.substr(10,10)),I=parseFloat(n.substr(20,10)),M=n.substr(31,3).trim(),k=M+(m-g+1);if(r){const t=3*a;if(o[t+0]=C,o[t+1]=P,o[t+2]=I,a+=1,c)continue}h.growIfFull(),h.atomTypeId[m]=l.add(k,M),h.x[m]=C,h.y[m]=P,h.z[m]=I,h.serial[m]=E?T:m,h.formalCharge[m]=t,e.addAtom(p,"","","HET",1,!0),m+=1}else if(O||!E&&f>=A&&f0)continue;if(r&&p>0)continue;E?(u.index=N.get(parseInt(R[2])),d.index=N.get(parseInt(R[3])),D=parseInt(R[1])):(u.index=parseInt(n.substr(0,3))-1+g,d.index=parseInt(n.substr(3,3))-1+g,D=parseInt(n.substr(6,3))),t.bondStore.addBond(u,d,D)}else if("M CHG"===n.substr(0,6)){const t=parseInt(n.substr(6,3));for(let e=0,i=10;e"===n.charAt(0)&&(b=n.match(Ug))?(B=b[1],F[B]=[]):!1!==B&&n&&F[B].push(n);++f}}}(0,n.length,n)})),e.finalize(),t.finalizeAtoms(),t.finalizeBonds(),tc(t),De&&ke.timeEnd("SdfParser._parse "+this.name)}_postProcess(){tc(this.structure)}}Ne.add("sdf",Vg),Ne.add("sd",Vg),Ne.add("mol",Vg);function jg(t,e,i){return parseInt(t.substr(e,i).trim())}class Gg extends og{get type(){return"prmtop"}_parse(){De&&ke.time("PrmtopParser._parse "+this.name);const t=this.structure,e=this.structureBuilder,i=t.atomMap,r=t.atomStore;r.addField("partialCharge",1,"float32"),r.addField("radius",1,"float32");const n=[],s={},o=["NATOM","NTYPES","NBONH","MBONA","NTHETH","MTHETA","NPHIH","MPHIA","NHPARM","NPARM","NNB","NRES","NBONA","NTHETA","NPHIA","NUMBND","NUMANG","NPTRA","NATYP","NPHB","IFPERT","NBPER","NGPER","NDPER","MBPER","MGPER","MDPER","IFBOX","NMXRS","IFCAP","NUMEXTRA","NCOPY"];let a,c,l,h,u;o.forEach((t=>{s[t]=0}));let d,m,f,p,g,y=new Uint8Array(0);this.streamer.eachChunkOfLines((function(t){!function(t,e,i){for(let b=t;b0)return void ke.error("dcd format with fixed atoms unsupported, aborting");const f=s.NATOM,p=4*f;for(let i=0,a=s.NSET;i=1&&(i.timeOffset=(s.ISTART-1)*i.deltaTime),De&&ke.timeEnd("DcdParser._parse "+this.name)}});const Jg={BYTE:1,CHAR:2,SHORT:3,INT:4,FLOAT:5,DOUBLE:6};function ty(t){switch(Number(t)){case Jg.BYTE:return"byte";case Jg.CHAR:return"char";case Jg.SHORT:return"short";case Jg.INT:return"int";case Jg.FLOAT:return"float";case Jg.DOUBLE:return"double";default:return"undefined"}}function ey(t){switch(Number(t)){case Jg.BYTE:case Jg.CHAR:return 1;case Jg.SHORT:return 2;case Jg.INT:case Jg.FLOAT:return 4;case Jg.DOUBLE:return 8;default:return-1}}function iy(t){switch(String(t)){case"byte":return Jg.BYTE;case"char":return Jg.CHAR;case"short":return Jg.SHORT;case"int":return Jg.INT;case"float":return Jg.FLOAT;case"double":return Jg.DOUBLE;default:return-1}}function ry(t,e){if(1!==t){const i=new Array(t);for(let r=0;r6,"non valid type "+h);const u=t.readUint32();let d=t.readUint32();2===i&&(Kg(d>0,"offsets larger than 4GB not supported"),d=t.readUint32()),c[0]===e&&(s+=u),n[r]={name:o,dimensions:c,attributes:l,type:ty(h),size:u,offset:d,record:c[0]===e}}}return{variables:n,recordStep:s}}(t,r.recordId,e);return i.variables=n.variables,i.recordDimension.recordStep=n.recordStep,i}function hy(t){let e;const i=t.readUint32();if(i===sy)return Kg(t.readUint32()!==sy,"wrong empty tag for list of attributes"),[];{Kg(i!==cy,"wrong tag for list of attributes");const r=t.readUint32();e=new Array(r);for(let i=0;i6,"non valid type "+n);const s=t.readUint32(),o=ny(t,n,s);Zg(t),e[i]={name:r,type:ty(n),value:o}}}return e}class uy{constructor(t){const e=new li(t);e.setBigEndian(),Kg("CDF"!==e.readChars(3),"should start with CDF");const i=e.readByte();Kg(i>2,"unknown version"),this.header=ly(e,i),this.buffer=e}get version(){return 1===this.header.version?"classic format":"64-bit offset format"}get recordDimension(){return this.header.recordDimension}get dimensions(){return this.header.dimensions}get globalAttributes(){return this.header.globalAttributes}get variables(){return this.header.variables}hasDataVariable(t){return-1!==this.header.variables.findIndex((function(e){return e.name===t}))}getDataVariable(t){let e;return e="string"==typeof t?this.header.variables.find((function(e){return e.name===t})):t,Kg(void 0===e,"variable not found"),this.buffer.seek(e.offset),e.record?function(t,e,i){const r=iy(e.type),n=e.size?e.size/ey(r):1,s=i.length,o=new Array(s),a=i.recordStep;for(let e=0;e=1&&(e.timeOffset=n[0]),n.length>=2&&(e.deltaTime=n[1]-n[0]),De&&ke.timeEnd("NctrajParser._parse "+this.name)}}Ne.add("nctraj",dy),Ne.add("ncdf",dy),Ne.add("nc",dy);Ne.add("trr",class extends Yg{get type(){return"trr"}get isBinary(){return!0}_parse(){De&&ke.time("TrrParser._parse "+this.name);const t=_t(this.streamer.data),e=new DataView(t),i=this.frames,r=i.coordinates,n=i.boxes,s=i.times;let o=0;for(;;){o+=8;const i=e.getInt32(o);o+=4,o+=i;const a=e.getInt32(o+8),c=e.getInt32(o+12),l=e.getInt32(o+16),h=e.getInt32(o+28),u=e.getInt32(o+32),d=e.getInt32(o+36),m=e.getInt32(o+40);o+=52;const f=a/9,p=3*m;if(8===f?s.push(e.getFloat64(o)):s.push(e.getFloat32(o)),o+=2*f,a){const t=new Float32Array(9);if(8===f)for(let i=0;i<9;++i)t[i]=10*e.getFloat64(o),o+=8;else for(let i=0;i<9;++i)t[i]=10*e.getFloat32(o),o+=4;n.push(t)}if(o+=c,o+=l,h){let i;if(8===f){i=new Float32Array(p);for(let t=0;t>8&65280|i>>24&255}i=new Float32Array(t,o,p);for(let t=0;t=t.byteLength)break}s.length>=1&&(i.timeOffset=s[0]),s.length>=2&&(i.deltaTime=s[1]-s[0]),De&&ke.timeEnd("TrrParser._parse "+this.name)}});const my=new Uint32Array([0,0,0,0,0,0,0,0,0,8,10,12,16,20,25,32,40,50,64,80,101,128,161,203,256,322,406,512,645,812,1024,1290,1625,2048,2580,3250,4096,5060,6501,8192,10321,13003,16384,20642,26007,32768,41285,52015,65536,82570,104031,131072,165140,208063,262144,330280,416127,524287,660561,832255,1048576,1321122,1664510,2097152,2642245,3329021,4194304,5284491,6658042,8388607,10568983,13316085,16777216]);function fy(t){let e=1,i=0;for(;t>=e&&i<32;)i++,e<<=1;return i}const py=new Uint8Array(32);function gy(t,e){let i=1,r=0;py[0]=1;for(let r=0;r>=8;for(;0!==n;)py[t++]=255&n,n>>=8;i=t}let n=1;for(i--;py[i]>=n;)r++,n*=2;return r+8*i}function yy(t,e,i,r){const n=(1<=8;)o=o<<8|e[a++],c|=o>>s<0&&(s>s&(1<8;)by[a++]=yy(t,e,8,o),r-=8;r>0&&(by[a++]=yy(t,e,r,o));for(let t=i-1;t>0;t--){let e=0;for(let i=a-1;i>=0;i--){e=e<<8|by[i];const r=e/n[t]|0;by[i]=r,e-=r*n[t]}s[t]=e}s[0]=by[0]|by[1]<<8|by[2]<<16|by[3]<<24}Ne.add("xtc",class extends Yg{get type(){return"xtc"}get isBinary(){return!0}_parse(){De&&ke.time("XtcParser._parse "+this.name);const t=_t(this.streamer.data),e=new DataView(t),i=this.frames,r=i.coordinates,n=i.boxes,s=i.times,o=new Int32Array(6),a=new Int32Array(3),c=new Int32Array(3),l=new Uint32Array(3),h=new Float32Array(3),u=new Float32Array(3);let d=0;const m=new Int32Array(3),f=new Uint32Array(m.buffer);for(;;){let i;const p=e.getInt32(d+4);d+=12;const g=3*p;s.push(e.getFloat32(d)),d+=4;const y=new Float32Array(9);for(let t=0;t<9;++t)y[t]=10*e.getFloat32(d),d+=4;if(n.push(y),p<=9){i=new Float32Array(p);for(let t=0;t16777215?(c[0]=fy(a[0]),c[1]=fy(a[1]),c[2]=fy(a[2]),p=0):p=gy(3,a);let y=e.getInt32(d);d+=4;let b=y-1;b=9>b?9:b;let _=my[b]/2|0,x=my[y]/2|0;l[0]=l[1]=l[2]=my[y];let v=4*Math.ceil(e.getInt32(d)/4);d+=4;const w=1/s;let A=0,S=0;const C=new Uint8Array(t,d);for(h[0]=h[1]=h[2]=0;S0){h[0]=h[1]=h[2]=0;for(let t=0;t9?my[y-1]/2|0:0):t>0&&(_=x,x=my[y]/2|0),l[0]=l[1]=l[2]=my[y],0===l[0]||0===l[1]||0===l[2])return void console.error("(xdrfile error) Undefined error.")}d+=v}for(let t=0;t=t.byteLength)break}s.length>=1&&(i.timeOffset=s[0]),s.length>=2&&(i.deltaTime=s[1]-s[0]),De&&ke.timeEnd("XtcParser._parse "+this.name)}});class xy extends sg{constructor(t,e){const i=e||{};super(t,i),this.volume=new $o(this.name,this.path),this.voxelSize=rt(i.voxelSize,1)}get type(){return"volume"}get __objName(){return"volume"}_afterParse(){this.volume.setMatrix(this.getMatrix()),super._afterParse()}getMatrix(){return new i}}const vy=/\s+/,wy=/-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?/g,Ay=.529177210859;class Sy extends xy{get type(){return"cube"}_parse(){De&&ke.time("CubeParser._parse "+this.name);const t=this.volume,i=this.streamer.peekLines(6),r={},n=Ay*this.voxelSize;function s(t,e){var r=i[t].trim().split(vy)[e];return parseFloat(r)}r.atomCount=Math.abs(s(2,0)),r.originX=s(2,1)*Ay,r.originY=s(2,2)*Ay,r.originZ=s(2,3)*Ay,r.NVX=s(3,0),r.NVY=s(4,0),r.NVZ=s(5,0),r.basisX=new e(s(3,1),s(3,2),s(3,3)).multiplyScalar(n),r.basisY=new e(s(4,1),s(4,2),s(4,3)).multiplyScalar(n),r.basisZ=new e(s(5,1),s(5,2),s(5,3)).multiplyScalar(n);const o=new Float32Array(r.NVX*r.NVY*r.NVZ);let a=0,c=0;const l=s(2,0)>0?0:1;this.streamer.eachChunkOfLines((function(t){!function(t,e,i){for(let n=t;n=r.atomCount+6+l){const e=t.match(wy);for(let t=0,i=e.length;t>8&255}e.xStart=s[0],e.yStart=s[1],e.zStart=s[2],e.xExtent=s[3],e.yExtent=s[4],e.zExtent=s[5],e.xRate=s[6],e.yRate=s[7],e.zRate=s[8];const t=1/s[17],n=t*this.voxelSize;e.xlen=s[9]*n,e.ylen=s[10]*n,e.zlen=s[11]*n,e.alpha=s[12]*t,e.beta=s[13]*t,e.gamma=s[14]*t,i=s[15]/100,r=s[16],e.gamma=s[14]*t}t.header=e,De&&ke.log(e,i,r);const c=new Float32Array(e.xExtent*e.yExtent*e.zExtent);let l=512;const h=Math.ceil(e.xExtent/8),u=Math.ceil(e.yExtent/8),d=Math.ceil(e.zExtent/8);for(var m=0;mn){const t=i[r].trim();if(""!==t){const e=t.split(Py);for(let t=0,i=e.length;t=n&&(f-n)%d!=0&&m=0?i-1:i+e/3)},parseNormalIndex:function(t,e){var i=parseInt(t,10);return 3*(i>=0?i-1:i+e/3)},addVertex:function(t,e,i){var r=this.vertices,n=this.object.geometry.vertices;n.push(r[t+0]),n.push(r[t+1]),n.push(r[t+2]),n.push(r[e+0]),n.push(r[e+1]),n.push(r[e+2]),n.push(r[i+0]),n.push(r[i+1]),n.push(r[i+2])},addVertexLine:function(t){var e=this.vertices,i=this.object.geometry.vertices;i.push(e[t+0]),i.push(e[t+1]),i.push(e[t+2])},addNormal:function(t,e,i){var r=this.normals,n=this.object.geometry.normals;n.push(r[t+0]),n.push(r[t+1]),n.push(r[t+2]),n.push(r[e+0]),n.push(r[e+1]),n.push(r[e+2]),n.push(r[i+0]),n.push(r[i+1]),n.push(r[i+2])},addFace:function(t,e,i,r,n,s,o,a){var c,l=this.vertices.length,h=this.parseVertexIndex(t,l),u=this.parseVertexIndex(e,l),d=this.parseVertexIndex(i,l);if(void 0===r?this.addVertex(h,u,d):(c=this.parseVertexIndex(r,l),this.addVertex(h,u,c),this.addVertex(u,d,c)),void 0!==n){var m=this.normals.length;h=this.parseNormalIndex(n,m),u=n===s?h:this.parseNormalIndex(s,m),d=n===o?h:this.parseNormalIndex(o,m),void 0===r?this.addNormal(h,u,d):(c=this.parseNormalIndex(a,m),this.addNormal(h,u,c),this.addNormal(u,d,c))}},addLineGeometry:function(t){this.object.geometry.type="Line";for(var e=this.vertices.length,i=0,r=t.length;i0?_.setAttribute("normal",new M(new Float32Array(b.normals),3)):_.computeVertexNormals(),y.push(_)}}return y}};Ne.add("obj",class extends Gy{get type(){return"obj"}getLoader(){return new Hy}});Ne.add("csv",class extends sg{constructor(t,e){const i=e||{};super(t,i),this.delimiter=rt(i.delimiter,","),this.comment=rt(i.comment,"#"),this.columnNames=rt(i.columnNames,!1),this.table={name:this.name,path:this.path,columnNames:[],data:[]}}get type(){return"csv"}get __objName(){return"table"}_parse(){const t=this.table.data,e=new RegExp("\\s*"+this.delimiter+"\\s*");let i=0;this.streamer.eachChunkOfLines((r=>{const n=r.length;for(let s=0;s/g,""),{declaration:e(),root:i()};function e(){if(!n(/^<\?xml\s*/))return;const t={attributes:{}};for(;!s()&&!o("?>");){const e=r();if(!e)return t;t.attributes[e.name]=e.value}return n(/\?>\s*/),t}function i(){const t=n(Xy);if(!t)return;const e={name:t[1],attributes:{},children:[]};for(;!(s()||o(">")||o("?>")||o("/>"));){const t=r();if(!t)return e;e.attributes[t.name]=t.value}if(n(/^\s*\/>\s*/))return e;let a;for(n(/\??>\s*/),e.content=function(){const t=n(Yy);return t?t[1]:""}();a=i();)e.children.push(a);return n(/^<\/[\w-:.]+>\s*/),e}function r(){const t=n(Ky);var e;if(t)return{name:t[1],value:(e=t[2],e.replace(Wy,""))}}function n(e){const i=t.match(e);if(i)return t=t.slice(i[0].length),i}function s(){return 0===t.length}function o(e){return 0===t.indexOf(e)}}class Qy extends sg{constructor(t,e){const i=e||{};super(t,i),this.useDomParser=rt(i.useDomParser,!1),this.xml={name:this.name,path:this.path,data:{}}}get type(){return"xml"}get __objName(){return"xml"}get isXml(){return!0}__xmlParser(t){return Zy(t)}__domParser(t){return(new window.DOMParser).parseFromString(t,"text/xml")}_parse(){De&&ke.time("XmlParser._parse "+this.name),this.useDomParser?this.streamer.data instanceof Document?this.xml.data=this.streamer.data:this.xml.data=this.__domParser(this.streamer.asText()):this.xml.data=this.__xmlParser(this.streamer.asText()),De&&ke.timeEnd("XmlParser._parse "+this.name)}}function Jy(t,e){const i=t.getNamedItem(e);return null!==i?i.value:""}function tb(t,e,i=!1){const r=Jy(t,"icode").trim(),n=Jy(t,"chain").trim(),s=Jy(t,"altcode");let o=Jy(t,"resnum");return r&&(o+="^"+r),n&&(o+=":"+n),e&&(o+="."+e),i&&s.trim()&&(o+="%"+s),o+="/"+(parseInt(Jy(t,"model"))-1),o}function eb(t){const e=Jy(t,"chain").trim();let i=`[${Jy(t,"rescode")}]${Jy(t,"resnum")}`;return e&&(i+=`:${e}`),i}function ib(t,e,i){void 0===t[e]?t[e]=i:t[e]|=i}function rb(t,e){return null!==t&&t.value===e}function nb(t,e,i){let r=0;const n=e.getElementsByTagName("clash");for(let e=0,i=n.length;e0&&(r+=1);e.getElementsByTagName("bond-outlier").length>0&&(r+=1);return e.getElementsByTagName("plane-outlier").length>0&&(r+=1),rb(i.getNamedItem("rota"),"OUTLIER")&&(r+=1),rb(i.getNamedItem("rama"),"OUTLIER")&&(r+=1),rb(i.getNamedItem("RNApucker"),"outlier")&&(r+=1),r}Ne.add("xml",Qy);class sb{constructor(t,e){this.name=t,this.path=e,this.rsrzDict={},this.rsccDict={},this.rciDict={},this.clashDict={},this.clashArray=[],this.geoDict={},this.geoAtomDict={},this.atomDict={},this.clashSele="NONE"}get type(){return"validation"}fromXml(t){De&&ke.time("Validation.fromXml");const e=this.rsrzDict,i=this.rsccDict,r=this.rciDict,n=this.clashDict,s=this.clashArray,o=this.geoDict,a=this.geoAtomDict,c=this.atomDict,l=t.getElementsByTagName("Entry");if(1===l.length){const t=l[0].getElementsByTagName("chemical_shift_list");if(1===t.length){const e=t[0].getElementsByTagName("random_coil_index");for(let t=0,i=e.length;t0&&(o[r]=t)}else{const t=e.getElementsByTagName("clash"),i=e.getElementsByTagName("mog-bond-outlier"),s=e.getElementsByTagName("mog-angle-outlier");if(i.length>0||s.length>0||t.length>0){const e={};a[r]=e;for(let i=0,r=t.length;i>>16&65535,o=0;0!==i;){i-=o=i>2e3?2e3:i;do{s=s+(n=n+e[r++]|0)|0}while(--o);n%=65521,s%=65521}return n|s<<16}Ne.add("validation",class extends Qy{constructor(t,e){super(t,e||{}),this.useDomParser=!0,this.validation=new sb(this.name,this.path)}get __objName(){return"validation"}get isXml(){return!0}_parse(){super._parse(),De&&ke.time("ValidationParser._parse "+this.name),this.validation.fromXml(this.xml.data),De&&ke.timeEnd("ValidationParser._parse "+this.name)}});var lb=function(){for(var t,e=[],i=0;i<256;i++){t=i;for(var r=0;r<8;r++)t=1&t?3988292384^t>>>1:t>>>1;e[i]=t}return e}();function hb(t,e,i,r){var n=lb,s=r+i;t^=-1;for(var o=r;o>>8^n[255&(t^e[o])];return~t}var ub=30,db=12;function mb(t,e){var i,r,n,s,o,a,c,l,h,u,d,m,f,p,g,y,b,_,x,v,w,A,S,C,P;i=t.state,r=t.next_in,C=t.input,n=r+(t.avail_in-5),s=t.next_out,P=t.output,o=s-(e-t.avail_out),a=s+(t.avail_out-257),c=i.dmax,l=i.wsize,h=i.whave,u=i.wnext,d=i.window,m=i.hold,f=i.bits,p=i.lencode,g=i.distcode,y=(1<>>=x=_>>>24,f-=x,0===(x=_>>>16&255))P[s++]=65535&_;else{if(!(16&x)){if(64&x){if(32&x){i.mode=db;break t}t.msg="invalid literal/length code",i.mode=ub;break t}_=p[(65535&_)+(m&(1<>>=x,f-=x),f<15&&(m+=C[r++]<>>=x=_>>>24,f-=x,16&(x=_>>>16&255)){if(w=65535&_,f<(x&=15)&&(m+=C[r++]<c){t.msg="invalid distance too far back",i.mode=ub;break t}if(m>>>=x,f-=x,w>(x=s-o)){if((x=w-x)>h&&i.sane){t.msg="invalid distance too far back",i.mode=ub;break t}if(A=0,S=d,0===u){if(A+=l-x,x2;)P[s++]=S[A++],P[s++]=S[A++],P[s++]=S[A++],v-=3;v&&(P[s++]=S[A++],v>1&&(P[s++]=S[A++]))}else{A=s-w;do{P[s++]=P[A++],P[s++]=P[A++],P[s++]=P[A++],v-=3}while(v>2);v&&(P[s++]=P[A++],v>1&&(P[s++]=P[A++]))}break}if(64&x){t.msg="invalid distance code",i.mode=ub;break t}_=g[(65535&_)+(m&(1<>3,m&=(1<<(f-=v<<3))-1,t.next_in=r,t.next_out=s,t.avail_in=r=1&&0===T[v];v--);if(w>v&&(w=v),0===v)return n[s++]=20971520,n[s++]=20971520,a.bits=1,0;for(x=1;x0&&(t===yb||1!==v))return-1;for(D[1]=0,b=1;bpb||t===_b&&P>gb)return 1;for(;;){f=b-S,o[_]m?(p=B[F+o[_]],g=k[M+o[_]]):(p=96,g=0),c=1<>S)+(l-=c)]=f<<24|p<<16|g}while(0!==l);for(c=1<>=1;if(0!==c?(I&=c-1,I+=c):I=0,_++,0==--T[b]){if(b===v)break;b=e[i+o[_]]}if(b>w&&(I&u)!==h){for(0===S&&(S=w),d+=x,C=1<<(A=b-S);A+Spb||t===_b&&P>gb)return 1;n[h=I&u]=w<<24|A<<16|d-s}}return 0!==I&&(n[d+I]=b-S<<24|64<<16),a.bits=w,0}var Cb=1,Pb=2,Ib=0,kb=-2,Mb=1,Tb=12,Db=30,Bb=852,Fb=592;function Eb(t){return(t>>>24&255)+(t>>>8&65280)+((65280&t)<<8)+((255&t)<<24)}function $b(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new Uint16Array(320),this.work=new Uint16Array(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function Ob(t){var e;return t&&t.state?((e=t.state).wsize=0,e.whave=0,e.wnext=0,function(t){var e;return t&&t.state?(e=t.state,t.total_in=t.total_out=e.total=0,t.msg="",e.wrap&&(t.adler=1&e.wrap),e.mode=Mb,e.last=0,e.havedict=0,e.dmax=32768,e.head=null,e.hold=0,e.bits=0,e.lencode=e.lendyn=new Int32Array(Bb),e.distcode=e.distdyn=new Int32Array(Fb),e.sane=1,e.back=-1,Ib):kb}(t)):kb}function Rb(t,e){var i,r;return t?(r=new $b,t.state=r,r.window=null,i=function(t,e){var i,r;return t&&t.state?(r=t.state,e<0?(i=0,e=-e):(i=1+(e>>4),e<48&&(e&=15)),e&&(e<8||e>15)?kb:(null!==r.window&&r.wbits!==e&&(r.window=null),r.wrap=i,r.wbits=e,Ob(t))):kb}(t,e),i!==Ib&&(t.state=null),i):kb}var Lb,Nb,zb=!0;function Ub(t){if(zb){var e;for(Lb=new Int32Array(512),Nb=new Int32Array(32),e=0;e<144;)t.lens[e++]=8;for(;e<256;)t.lens[e++]=9;for(;e<280;)t.lens[e++]=7;for(;e<288;)t.lens[e++]=8;for(Sb(Cb,t.lens,0,288,Lb,0,t.work,{bits:9}),e=0;e<32;)t.lens[e++]=5;Sb(Pb,t.lens,0,32,Nb,0,t.work,{bits:5}),zb=!1}t.lencode=Lb,t.lenbits=9,t.distcode=Nb,t.distbits=5}function Vb(t,e,i,r){var n,s=t.state;return null===s.window&&(s.wsize=1<=s.wsize?(ab(s.window,e,i-s.wsize,s.wsize,0),s.wnext=0,s.whave=s.wsize):((n=s.wsize-s.wnext)>r&&(n=r),ab(s.window,e,i-r,n,s.wnext),(r-=n)?(ab(s.window,e,i-r,r,0),s.wnext=r,s.whave=s.wsize):(s.wnext+=n,s.wnext===s.wsize&&(s.wnext=0),s.whave>>8&255,i.check=hb(i.check,I,2,0),l=0,h=0,i.mode=2;break}if(i.flags=0,i.head&&(i.head.done=!1),!(1&i.wrap)||(((255&l)<<8)+(l>>8))%31){t.msg="incorrect header check",i.mode=Db;break}if(8!=(15&l)){t.msg="unknown compression method",i.mode=Db;break}if(h-=4,w=8+(15&(l>>>=4)),0===i.wbits)i.wbits=w;else if(w>i.wbits){t.msg="invalid window size",i.mode=Db;break}i.dmax=1<>8&1),512&i.flags&&(I[0]=255&l,I[1]=l>>>8&255,i.check=hb(i.check,I,2,0)),l=0,h=0,i.mode=3;case 3:for(;h<32;){if(0===a)break t;a--,l+=r[s++]<>>8&255,I[2]=l>>>16&255,I[3]=l>>>24&255,i.check=hb(i.check,I,4,0)),l=0,h=0,i.mode=4;case 4:for(;h<16;){if(0===a)break t;a--,l+=r[s++]<>8),512&i.flags&&(I[0]=255&l,I[1]=l>>>8&255,i.check=hb(i.check,I,2,0)),l=0,h=0,i.mode=5;case 5:if(1024&i.flags){for(;h<16;){if(0===a)break t;a--,l+=r[s++]<>>8&255,i.check=hb(i.check,I,2,0)),l=0,h=0}else i.head&&(i.head.extra=null);i.mode=6;case 6:if(1024&i.flags&&((m=i.length)>a&&(m=a),m&&(i.head&&(w=i.head.extra_len-i.length,i.head.extra||(i.head.extra=new Array(i.head.extra_len)),ab(i.head.extra,r,s,m,w)),512&i.flags&&(i.check=hb(i.check,r,m,s)),a-=m,s+=m,i.length-=m),i.length))break t;i.length=0,i.mode=7;case 7:if(2048&i.flags){if(0===a)break t;m=0;do{w=r[s+m++],i.head&&w&&i.length<65536&&(i.head.name+=String.fromCharCode(w))}while(w&&m>9&1,i.head.done=!0),t.adler=i.check=0,i.mode=Tb;break;case 10:for(;h<32;){if(0===a)break t;a--,l+=r[s++]<>>=7&h,h-=7&h,i.mode=27;break}for(;h<3;){if(0===a)break t;a--,l+=r[s++]<>>=1)){case 0:i.mode=14;break;case 1:if(Ub(i),i.mode=20,6===e){l>>>=2,h-=2;break t}break;case 2:i.mode=17;break;case 3:t.msg="invalid block type",i.mode=Db}l>>>=2,h-=2;break;case 14:for(l>>>=7&h,h-=7&h;h<32;){if(0===a)break t;a--,l+=r[s++]<>>16^65535)){t.msg="invalid stored block lengths",i.mode=Db;break}if(i.length=65535&l,l=0,h=0,i.mode=15,6===e)break t;case 15:i.mode=16;case 16:if(m=i.length){if(m>a&&(m=a),m>c&&(m=c),0===m)break t;ab(n,r,s,m,o),a-=m,s+=m,c-=m,o+=m,i.length-=m;break}i.mode=Tb;break;case 17:for(;h<14;){if(0===a)break t;a--,l+=r[s++]<>>=5,h-=5,i.ndist=1+(31&l),l>>>=5,h-=5,i.ncode=4+(15&l),l>>>=4,h-=4,i.nlen>286||i.ndist>30){t.msg="too many length or distance symbols",i.mode=Db;break}i.have=0,i.mode=18;case 18:for(;i.have>>=3,h-=3}for(;i.have<19;)i.lens[k[i.have++]]=0;if(i.lencode=i.lendyn,i.lenbits=7,S={bits:i.lenbits},A=Sb(0,i.lens,0,19,i.lencode,0,i.work,S),i.lenbits=S.bits,A){t.msg="invalid code lengths set",i.mode=Db;break}i.have=0,i.mode=19;case 19:for(;i.have>>16&255,b=65535&P,!((g=P>>>24)<=h);){if(0===a)break t;a--,l+=r[s++]<>>=g,h-=g,i.lens[i.have++]=b;else{if(16===b){for(C=g+2;h>>=g,h-=g,0===i.have){t.msg="invalid bit length repeat",i.mode=Db;break}w=i.lens[i.have-1],m=3+(3&l),l>>>=2,h-=2}else if(17===b){for(C=g+3;h>>=g)),l>>>=3,h-=3}else{for(C=g+7;h>>=g)),l>>>=7,h-=7}if(i.have+m>i.nlen+i.ndist){t.msg="invalid bit length repeat",i.mode=Db;break}for(;m--;)i.lens[i.have++]=w}}if(i.mode===Db)break;if(0===i.lens[256]){t.msg="invalid code -- missing end-of-block",i.mode=Db;break}if(i.lenbits=9,S={bits:i.lenbits},A=Sb(Cb,i.lens,0,i.nlen,i.lencode,0,i.work,S),i.lenbits=S.bits,A){t.msg="invalid literal/lengths set",i.mode=Db;break}if(i.distbits=6,i.distcode=i.distdyn,S={bits:i.distbits},A=Sb(Pb,i.lens,i.nlen,i.ndist,i.distcode,0,i.work,S),i.distbits=S.bits,A){t.msg="invalid distances set",i.mode=Db;break}if(i.mode=20,6===e)break t;case 20:i.mode=21;case 21:if(a>=6&&c>=258){t.next_out=o,t.avail_out=c,t.next_in=s,t.avail_in=a,i.hold=l,i.bits=h,mb(t,d),o=t.next_out,n=t.output,c=t.avail_out,s=t.next_in,r=t.input,a=t.avail_in,l=i.hold,h=i.bits,i.mode===Tb&&(i.back=-1);break}for(i.back=0;y=(P=i.lencode[l&(1<>>16&255,b=65535&P,!((g=P>>>24)<=h);){if(0===a)break t;a--,l+=r[s++]<>_)])>>>16&255,b=65535&P,!(_+(g=P>>>24)<=h);){if(0===a)break t;a--,l+=r[s++]<>>=_,h-=_,i.back+=_}if(l>>>=g,h-=g,i.back+=g,i.length=b,0===y){i.mode=26;break}if(32&y){i.back=-1,i.mode=Tb;break}if(64&y){t.msg="invalid literal/length code",i.mode=Db;break}i.extra=15&y,i.mode=22;case 22:if(i.extra){for(C=i.extra;h>>=i.extra,h-=i.extra,i.back+=i.extra}i.was=i.length,i.mode=23;case 23:for(;y=(P=i.distcode[l&(1<>>16&255,b=65535&P,!((g=P>>>24)<=h);){if(0===a)break t;a--,l+=r[s++]<>_)])>>>16&255,b=65535&P,!(_+(g=P>>>24)<=h);){if(0===a)break t;a--,l+=r[s++]<>>=_,h-=_,i.back+=_}if(l>>>=g,h-=g,i.back+=g,64&y){t.msg="invalid distance code",i.mode=Db;break}i.offset=b,i.extra=15&y,i.mode=24;case 24:if(i.extra){for(C=i.extra;h>>=i.extra,h-=i.extra,i.back+=i.extra}if(i.offset>i.dmax){t.msg="invalid distance too far back",i.mode=Db;break}i.mode=25;case 25:if(0===c)break t;if(m=d-c,i.offset>m){if((m=i.offset-m)>i.whave&&i.sane){t.msg="invalid distance too far back",i.mode=Db;break}m>i.wnext?(m-=i.wnext,f=i.wsize-m):f=i.wnext-m,m>i.length&&(m=i.length),p=i.window}else p=n,f=o-i.offset,m=i.length;m>c&&(m=c),c-=m,i.length-=m;do{n[o++]=p[f++]}while(--m);0===i.length&&(i.mode=21);break;case 26:if(0===c)break t;n[o++]=i.length,c--,i.mode=21;break;case 27:if(i.wrap){for(;h<32;){if(0===a)break t;a--,l|=r[s++]<=252?6:Xb>=248?5:Xb>=240?4:Xb>=224?3:Xb>=192?2:1;function Yb(t){var e,i,r,n,s,o=t.length,a=0;for(n=0;n>>6,e[s++]=128|63&i):i<65536?(e[s++]=224|i>>>12,e[s++]=128|i>>>6&63,e[s++]=128|63&i):(e[s++]=240|i>>>18,e[s++]=128|i>>>12&63,e[s++]=128|i>>>6&63,e[s++]=128|63&i);return e}function Kb(t,e){var i,r,n,s,o=e||t.length,a=new Array(2*o);for(r=0,i=0;i4)a[r++]=65533,i+=s-1;else{for(n&=2===s?31:3===s?15:7;s>1&&i1?a[r++]=65533:n<65536?a[r++]=n:(n-=65536,a[r++]=55296|n>>10&1023,a[r++]=56320|1023&n)}return function(t,e){if(e<65537&&(t.subarray&&qb||!t.subarray&&Hb))return String.fromCharCode.apply(null,ob(t,e));for(var i="",r=0;rt.length&&(e=t.length),i=e-1;i>=0&&128==(192&t[i]);)i--;return i<0||0===i?e:i+Wb[t[i]]>e?i:e}Wb[254]=Wb[254]=1;var Qb=0,Jb={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"};function t_(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}function e_(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}var i_=Object.prototype.toString;function r_(t){if(!(this instanceof r_))return new r_(t);this.options=function(t){for(var e=Array.prototype.slice.call(arguments,1);e.length;){var i=e.shift();if(i){if("object"!=typeof i)throw new TypeError(i+"must be non-object");for(var r in i)i.hasOwnProperty(r)&&(t[r]=i[r])}}return t}({chunkSize:16384,windowBits:0,to:""},t||{});var e=this.options;e.raw&&e.windowBits>=0&&e.windowBits<16&&(e.windowBits=-e.windowBits,0===e.windowBits&&(e.windowBits=-15)),!(e.windowBits>=0&&e.windowBits<16)||t&&t.windowBits||(e.windowBits+=32),e.windowBits>15&&e.windowBits<48&&(15&e.windowBits||(e.windowBits|=15)),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new t_,this.strm.avail_out=0;var i,r,n,s=Rb(this.strm,e.windowBits);if(s!==Qb)throw new Error(Jb[s]);this.header=new e_,i=this.strm,r=this.header,i&&i.state&&2&(n=i.state).wrap&&(n.head=r,r.done=!1)}r_.prototype.push=function(t,e){var i,r,n,s,o,a,c=this.strm,l=this.options.chunkSize,h=this.options.dictionary,u=!1;if(this.ended)return!1;r=e===~~e?e:!0===e?4:0,"string"==typeof t?c.input=function(t){for(var e=new Uint8Array(t.length),i=0,r=e.length;i0||0===c.avail_out)&&1!==i);return 1===i&&(r=4),4===r?(i=function(t){if(!t||!t.state)return kb;var e=t.state;return e.window&&(e.window=null),t.state=null,Ib}(this.strm),this.onEnd(i),this.ended=!0,i===Qb):2!==r||(this.onEnd(Qb),c.avail_out=0,!0)},r_.prototype.onData=function(t){this.chunks.push(t)},r_.prototype.onEnd=function(t){t===Qb&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=function(t){var e,i,r,n,s,o;for(r=0,e=0,i=t.length;e-1?e.name:e.name.substring(0,4);let r;return!["pdb","cif"].includes(e.ext)||!1!==e.compressed&&"gz"!==e.compressed?"mmtf"===e.ext?(ke.warn("MMTF files distribution is discontinued by RCSB PDB as of July 2, 2024.\n Consider using bcif format instead. See https://www.rcsb.org/news/65a1af31c76ca3abcc925d0c for the deprecation notice"),r=e.base.endsWith(".bb")?a_+i:o_+i):"bcif"!==e.ext||!1!==e.compressed&&"gz"!==e.compressed?e.ext?(ke.warn("unsupported ext",e.ext),r=c_+i+".bcif.gz"):(ke.warn('mmCif files available from RCSB PDB lack connectivity information.\n Consider using PDBe as the data provider for using "Updated mmCif files" that contain residues connectivity records.'),r=c_+i+".bcif.gz"):r=c_+e.path:r="//files.rcsb.org/download/"+e.path,at()+r}getExt(t){const e=ii(t).ext;return e||"mmtf"}});const l_="//www.ebi.ac.uk/pdbe/entry-files/download/";Re.add("pdbe",new class extends n_{getUrl(t){const e=ii(t);let i,r=e.name.indexOf("_")>-1?e.name:e.name.substring(0,4);switch(e.ext){case"cif":i=l_+r+"_updated.cif";break;case"pdb":case"ent":r.startsWith("pdb")||(r="pdb"+r),i=l_+r+".ent";break;case"bcif":i=l_+e.path;break;case"":i=l_+r+".bcif";break;default:ke.warn("unsupported ext",e.ext),i=l_+r+".bcif"}return"https://"+i}getExt(t){const e=ii(t).ext;return e||"mmtf"}});const h_="//pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/",u_="/SDF?record_type=3d";Re.add("pubchem",new class extends n_{getUrl(t){const e=ii(t),i=e.name;let r;return e.ext&&"sdf"!==e.ext?(ke.warn("unsupported ext",e.ext),r=h_+i+u_):r=h_+i+u_,at()+r}getExt(t){const e=ii(t).ext;return e||"sdf"}});class d_ extends n_{getUrl(t){return t}getExt(t){return ii(t).ext}}Re.add("ftp",new d_),Re.add("http",new d_),Re.add("https",new d_);const m_="//alphafold.ebi.ac.uk/files/AF-",f_="-F1-model_v4.pdb";Re.add("alphafold",new class extends n_{getUrl(t){const e=ii(t),i=e.name;let r;return e.ext&&"pdb"!==e.ext?(ke.warn("unsupported AF ext",e.ext),r=m_+i+f_):r=m_+i+f_,"https://"+r}getExt(t){const e=ii(t).ext;return e||"pdb"}});const p_=/^((http|https|ftp):)*\/\//;class g_ extends n_{constructor(t=""){super(),this.baseUrl=t}getUrl(t){const e=ii(t);let i=this.baseUrl+e.path;return p_.test(this.baseUrl)||(i=function(t){const e=window.location,i=e.pathname,r=i.substring(0,i.lastIndexOf("/")+1);return e.origin+r+t}(i)),i}getExt(t){return ii(t).ext}}class y_ extends n_{constructor(t=""){super(),this.baseUrl=t}getListing(t=""){let e=`${this.baseUrl}dir/${t}`;return"/"!==e[e.length-1]&&(e+="/"),ni(e,{ext:"json"}).then((e=>({path:t,data:e.data})))}getUrl(t){const e=ii(t);return`${this.baseUrl}file/${e.path}${e.query}`}getCountUrl(t){const e=ii(t);return`${this.baseUrl}traj/numframes/${e.path}${e.query}`}getFrameUrl(t,e){const i=ii(t);return`${this.baseUrl}traj/frame/${e}/${i.path}${i.query}`}getFrameParams(t,e){return`atomIndices=${e.join(";")}`}getPathUrl(t,e){const i=ii(t);return`${this.baseUrl}traj/path/${e}/${i.path}${i.query}`}getExt(t){return ii(t).ext}}function b_(t,e){return{type:"integer",max:t,min:e}}function __(t,e,i){return{type:"number",precision:t,max:e,min:i}}function x_(t,e,i){return{type:"range",step:t,max:e,min:i}}function v_(...t){return{type:"select",options:t.reduce(((t,e)=>Object.assign(Object.assign({},t),{[e]:e})),{})}}const w_={backgroundColor:{type:"color"},quality:v_("auto","low","medium","high"),sampleLevel:x_(1,5,-1),impostor:{type:"boolean"},workerDefault:{type:"boolean"},rotateSpeed:__(1,10,0),zoomSpeed:__(1,10,0),panSpeed:__(1,10,0),clipNear:x_(1,100,0),clipFar:x_(1,100,0),clipDist:b_(200,0),clipMode:v_("scene","camera"),clipScale:v_("relative","absolute"),fogNear:x_(1,100,0),fogFar:x_(1,100,0),cameraType:v_("perspective","orthographic","stereo"),cameraEyeSep:__(3,1,.01),cameraFov:x_(1,120,15),lightColor:{type:"color"},lightIntensity:__(2,10,0),ambientColor:{type:"color"},ambientIntensity:__(2,10,0),hoverTimeout:b_(1e4,-1),tooltip:{type:"boolean"},mousePreset:v_(...Object.keys(Ko))};const A_="2.3.0";export{zh as AngleRepresentation,hd as ArrowBuffer,Ra as Assembly,eu as AxesRepresentation,ru as BackboneRepresentation,iu as BallAndStickRepresentation,nu as BaseRepresentation,pd as BoxBuffer,Mc as BufferRepresentation,uu as CartoonRepresentation,ll as Collection,Nt as Colormaker,Oe as ColormakerRegistry,cl as Component,Bl as ComponentCollection,ad as ConeBuffer,du as ContactRepresentation,ui as Counter,tu as CylinderBuffer,Re as DatasourceRegistry,De as Debug,Ue as DecompressorRegistry,gu as DihedralHistogramRepresentation,mu as DihedralRepresentation,bu as DistanceRepresentation,vd as EllipsoidBuffer,ml as Frames,wu as HelixorientRepresentation,Du as HyperballRepresentation,Ba as Kdtree,Jo as KeyActions,Fu as LabelRepresentation,Ji as LeftMouseButton,Au as LicoriceRepresentation,$u as LineRepresentation,He as ListingDatasource,y_ as MdsrvDatasource,Me as MeasurementDefaultParams,Vo as MeshBuffer,tr as MiddleMouseButton,zu as MolecularSurface,Uu as MolecularSurfaceRepresentation,Yo as MouseActions,Pd as OctahedronBuffer,Ne as ParserRegistry,oi as PdbWriter,yr as PickingProxy,Hc as PointBuffer,Vu as PointRepresentation,Lr as Queue,hl as RepresentationCollection,nl as RepresentationElement,Le as RepresentationRegistry,qu as RibbonRepresentation,er as RightMouseButton,Wu as RocketRepresentation,Xu as RopeRepresentation,Ee as ScriptExtensions,ai as SdfWriter,me as Selection,kc as Shape,Rl as ShapeComponent,Yu as SpacefillRepresentation,Tn as SpatialHash,Uc as SphereBuffer,Ol as Stage,g_ as StaticDatasource,hi as StlWriter,Sc as Structure,Ml as StructureComponent,kl as StructureComponentDefaultParameters,Sh as StructureRepresentation,fl as Superposition,Tl as SurfaceComponent,Dd as TetrahedronBuffer,Oh as TextBuffer,Rd as TorusBuffer,Qu as TraceRepresentation,qe as TrajectoryDatasource,gl as TrajectoryPlayer,Ju as TubeRepresentation,w_ as UIStageParameters,td as UnitcellRepresentation,ed as ValidationRepresentation,A_ as Version,Qi as Viewer,$o as Volume,Dl as VolumeComponent,Nh as WidelineBuffer,ni as autoLoad,ec as concatStructures,ht as download,ot as flatten,ri as getDataInfo,ii as getFileInfo,it as getQuery,Ja as guessElement,Fe as setDebug,We as setListingDatasource,Te as setMeasurementDefaultParams,Xe as setTrajectoryDatasource,Il as superpose,ut as throttle,pt as uniqueArray}; //# sourceMappingURL=ngl.esm.js.map diff --git a/dist/ngl.esm.js.map b/dist/ngl.esm.js.map index 1358a9a84..b13526970 100644 --- a/dist/ngl.esm.js.map +++ b/dist/ngl.esm.js.map @@ -1 +1 @@ -{"version":3,"file":"ngl.esm.js","sources":["../src/utils.ts","../src/utils/registry.ts","../src/math/math-utils.ts","../src/color/colormaker.ts","../src/selection/selection-constants.ts","../src/selection/selection-test.ts","../src/selection/selection.ts","../src/selection/selection-parser.ts","../src/color/selection-colormaker.ts","../src/color/colormaker-registry.ts","../src/worker/worker-utils.ts","../src/globals.ts","../src/worker/worker-registry.ts","../src/parser/parser-registry.ts","../src/streamer/streamer.ts","../src/streamer/file-streamer.ts","../src/streamer/network-streamer.ts","../src/loader/loader.ts","../src/loader/parser-loader.ts","../src/script.ts","../src/loader/script-loader.ts","../src/loader/loader-utils.ts","../src/writer/writer.ts","../src/writer/pdb-writer.ts","../src/writer/sdf-writer.ts","../src/utils/io-buffer.ts","../src/writer/stl-writer.ts","../src/utils/counter.ts","../src/viewer/stats.ts","../src/shader/shader-utils.ts","../src/viewer/viewer-constants.ts","../src/viewer/tiled-renderer.ts","../src/math/math-constants.ts","../src/math/array-utils.ts","../src/viewer/viewer-utils.ts","../src/viewer/gl-utils.ts","../src/viewer/viewer.ts","../src/constants.ts","../src/stage/mouse-observer.ts","../src/controls/trackball-controls.ts","../src/controls/picking-proxy.ts","../src/controls/picking-controls.ts","../src/controls/viewer-controls.ts","../src/animation/animation.ts","../src/controls/animation-controls.ts","../src/utils/queue.ts","../src/representation/representation.ts","../src/worker/worker.ts","../src/worker/worker-pool.ts","../src/math/vector-utils.ts","../src/geometry/dash.ts","../src/geometry/primitive.ts","../src/geometry/spatial-hash.ts","../src/store/store.ts","../src/store/contact-store.ts","../src/utils/bitarray.ts","../src/utils/adjacency-list.ts","../src/chemistry/interactions/features.ts","../src/structure/structure-constants.ts","../src/chemistry/geometry.ts","../src/chemistry/valence-model.ts","../src/structure/data.ts","../src/chemistry/functional-groups.ts","../src/chemistry/interactions/charged.ts","../src/chemistry/interactions/hydrogen-bonds.ts","../src/chemistry/interactions/metal-binding.ts","../src/chemistry/interactions/halogen-bonds.ts","../src/chemistry/interactions/refine-contacts.ts","../src/chemistry/interactions/contact.ts","../src/chemistry/interactions/hydrophobic.ts","../src/utils/picker.ts","../src/surface/marching-cubes.ts","../src/math/matrix-utils.ts","../src/surface/surface-utils.ts","../src/surface/surface.ts","../src/surface/volume.ts","../src/buffer/buffer.ts","../src/buffer/mesh-buffer.ts","../src/buffer/surface-buffer.ts","../src/buffer/doublesided-buffer.ts","../src/buffer/contour-buffer.ts","../src/representation/surface-representation.ts","../src/controls/mouse-actions.ts","../src/controls/mouse-controls.ts","../src/controls/key-actions.ts","../src/controls/key-controls.ts","../src/stage/picking-behavior.ts","../src/stage/mouse-behavior.ts","../src/stage/animation-behavior.ts","../src/stage/key-behavior.ts","../src/component/annotation.ts","../src/controls/component-controls.ts","../src/utils/radius-factory.ts","../src/math/principal-axes.ts","../src/surface/filtered-volume.ts","../src/store/bond-hash.ts","../src/store/bond-store.ts","../src/store/atom-store.ts","../src/store/residue-store.ts","../src/store/chain-store.ts","../src/store/model-store.ts","../src/geometry/helixorient.ts","../src/geometry/helixbundle.ts","../src/utils/binary-heap.ts","../src/utils/kdtree.ts","../src/proxy/atom-proxy.ts","../src/geometry/kdtree.ts","../src/symmetry/symmetry-constants.ts","../src/symmetry/symmetry-utils.ts","../src/symmetry/assembly.ts","../src/structure/structure-builder.ts","../src/structure/structure-utils.ts","../src/store/atom-type.ts","../src/store/atom-map.ts","../src/store/residue-type.ts","../src/store/residue-map.ts","../src/proxy/bond-proxy.ts","../src/proxy/residue-proxy.ts","../src/proxy/polymer.ts","../src/proxy/chain-proxy.ts","../src/proxy/model-proxy.ts","../src/structure/structure.ts","../src/geometry/shape.ts","../src/representation/buffer-representation.ts","../src/buffer/geometry-buffer.ts","../src/buffer/spheregeometry-buffer.ts","../src/buffer/mapped-buffer.ts","../src/buffer/mappedquad-buffer.ts","../src/buffer/sphereimpostor-buffer.ts","../src/buffer/sphere-buffer.ts","../src/buffer/point-buffer.ts","../src/representation/dot-representation.ts","../src/buffer/image-buffer.ts","../src/surface/volume-slice.ts","../src/representation/slice-representation.ts","../src/representation/representation-utils.ts","../src/component/element.ts","../src/component/representation-element.ts","../src/component/component.ts","../src/component/collection.ts","../src/component/representation-collection.ts","../src/component/trajectory-element.ts","../src/trajectory/frames.ts","../src/align/superposition.ts","../src/trajectory/trajectory-player.ts","../src/trajectory/trajectory.ts","../src/trajectory/frames-trajectory.ts","../src/trajectory/structure-trajectory.ts","../src/trajectory/remote-trajectory.ts","../src/trajectory/callback-trajectory.ts","../src/structure/structure-view.ts","../src/align/alignment.ts","../src/align/align-utils.ts","../src/component/structure-component.ts","../src/trajectory/trajectory-utils.ts","../src/component/surface-component.ts","../src/component/volume-component.ts","../src/component/component-collection.ts","../src/stage/stage.ts","../src/component/shape-component.ts","../node_modules/tslib/tslib.es6.js","../src/color/atomindex-colormaker.ts","../src/color/bfactor-colormaker.ts","../src/color/chainid-colormaker.ts","../src/color/chainindex-colormaker.ts","../src/color/chainname-colormaker.ts","../src/color/densityfit-colormaker.ts","../src/color/electrostatic-colormaker.ts","../src/color/element-colormaker.ts","../src/color/entityindex-colormaker.ts","../src/color/entitytype-colormaker.ts","../src/color/geoquality-colormaker.ts","../src/color/hydrophobicity-colormaker.ts","../src/color/modelindex-colormaker.ts","../src/color/moleculetype-colormaker.ts","../src/color/occupancy-colormaker.ts","../src/color/partialcharge-colormaker.ts","../src/color/random-colormaker.ts","../src/color/randomcoilindex-colormaker.ts","../src/color/residueindex-colormaker.ts","../src/color/resname-colormaker.ts","../src/color/sstruc-colormaker.ts","../src/color/structuredata-colormaker.ts","../src/color/uniform-colormaker.ts","../src/color/value-colormaker.ts","../src/color/volume-colormaker.ts","../src/representation/structure-representation.ts","../src/representation/measurement-representation.ts","../src/utils/edt.ts","../src/buffer/text-buffer.ts","../src/buffer/wideline-buffer.ts","../src/representation/angle-representation.ts","../src/buffer/cylindergeometry-buffer.ts","../src/buffer/mappedalignedbox-buffer.ts","../src/buffer/cylinderimpostor-buffer.ts","../src/buffer/cylinder-buffer.ts","../src/representation/axes-representation.ts","../src/representation/ballandstick-representation.ts","../src/representation/backbone-representation.ts","../src/representation/base-representation.ts","../src/geometry/spline.ts","../src/buffer/tubemesh-buffer.ts","../src/representation/cartoon-representation.ts","../src/representation/contact-representation.ts","../src/representation/dihedral-representation.ts","../src/representation/dihedral-histogram-representation.ts","../src/representation/distance-representation.ts","../src/buffer/vector-buffer.ts","../src/representation/helixorient-representation.ts","../src/representation/licorice-representation.ts","../src/buffer/mappedbox-buffer.ts","../src/buffer/hyperballstickimpostor-buffer.ts","../src/buffer/hyperballstick-buffer.ts","../src/representation/hyperball-representation.ts","../src/utils/label-factory.ts","../src/representation/label-representation.ts","../src/representation/line-representation.ts","../src/geometry/grid.ts","../src/surface/edt-surface.ts","../src/surface/av-surface.ts","../src/surface/molecular-surface.ts","../src/representation/molecularsurface-representation.ts","../src/representation/point-representation.ts","../src/buffer/ribbon-buffer.ts","../src/representation/ribbon-representation.ts","../src/representation/rocket-representation.ts","../src/representation/rope-representation.ts","../src/representation/spacefill-representation.ts","../src/buffer/trace-buffer.ts","../src/representation/trace-representation.ts","../src/representation/tube-representation.ts","../src/representation/unitcell-representation.ts","../src/representation/validation-representation.ts","../src/buffer/cone-buffer.ts","../src/viewer/geometry-group.ts","../src/buffer/arrow-buffer.ts","../src/buffer/box-buffer.ts","../src/buffer/ellipsoid-buffer.ts","../src/buffer/octahedron-buffer.ts","../src/buffer/tetrahedron-buffer.ts","../src/buffer/torus-buffer.ts","../src/parser/parser.ts","../src/parser/structure-parser.ts","../src/structure/entity.ts","../src/symmetry/unitcell.ts","../src/parser/pdb-parser.ts","../src/parser/cif-parser.ts","../src/parser/gro-parser.ts","../lib/mmtf.es6.js","../src/parser/mmtf-parser.ts","../src/parser/mol2-parser.ts","../src/parser/pdbqt-parser.ts","../src/parser/pqr-parser.ts","../src/parser/sdf-parser.ts","../src/parser/prmtop-parser.ts","../src/parser/psf-parser.ts","../src/parser/top-parser.ts","../src/parser/trajectory-parser.ts","../src/utils/netcdf-reader.ts","../src/parser/dcd-parser.ts","../src/parser/nctraj-parser.ts","../src/parser/trr-parser.ts","../src/parser/xtc-parser.ts","../src/parser/volume-parser.ts","../src/parser/cube-parser.ts","../src/parser/dsn6-parser.ts","../src/parser/dx-parser.ts","../src/parser/dxbin-parser.ts","../src/parser/mrc-parser.ts","../src/parser/xplor-parser.ts","../src/parser/kin-parser.ts","../src/parser/surface-parser.ts","../src/parser/obj-parser.ts","../src/parser/ply-parser.ts","../src/parser/csv-parser.ts","../src/parser/json-parser.ts","../src/parser/msgpack-parser.ts","../src/parser/netcdf-parser.ts","../src/parser/text-parser.ts","../src/utils/parse-xml.ts","../src/parser/xml-parser.ts","../src/structure/validation.ts","../lib/pako_inflate.es6.js","../src/parser/validation-parser.ts","../src/utils/gzip-decompressor.ts","../src/datasource/datasource.ts","../src/datasource/rcsb-datasource.ts","../src/datasource/pubchem-datasource.ts","../src/datasource/passthrough-datasource.ts","../src/datasource/alphafold-datasource.ts","../src/datasource/static-datasource.ts","../src/datasource/mdsrv-datasource.ts","../src/ui/parameters.ts","../src/version.ts"],"sourcesContent":["/**\n * @file Utils\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector2, Vector3, Matrix4, Quaternion } from 'three'\n\nexport function getQuery (id: string) {\n if (typeof window === 'undefined') return undefined\n\n const a = new RegExp(`${id}=([^&#=]*)`)\n const m = a.exec(window.location.search)\n\n if (m) {\n return decodeURIComponent(m[1])\n } else {\n return undefined\n }\n}\n\nexport function boolean (value: any) {\n if (!value) {\n return false\n }\n\n if (typeof value === 'string') {\n return /^1|true|t|yes|y$/i.test(value)\n }\n\n return true\n}\n\nexport function defaults (value: any, defaultValue: any) {\n return value !== undefined ? value : defaultValue\n}\n\nexport function createParams (params: {[k in keyof T]?: any}, defaultParams: T) {\n const o: any = Object.assign({}, params)\n for (const k in defaultParams) {\n const value = params[k]\n if (value === undefined) o[k] = defaultParams[k]\n }\n return o as T\n}\n\nexport function updateParams (params: T, newParams: {[k in keyof T]?: any}) {\n for (const k in newParams) {\n const value = newParams[k]\n if (value !== undefined) params[k] = value\n }\n return params as T\n}\n\nexport function pick (object: { [index: string]: any }) {\n const properties = [].slice.call(arguments, 1)\n return properties.reduce((a: { [index: string]: any }, e: any) => {\n a[ e ] = object[ e ]\n return a\n }, {})\n}\n\nexport function flatten (array: any[], ret: any[]) {\n ret = defaults(ret, [])\n for (let i = 0; i < array.length; i++) {\n if (Array.isArray(array[i])) {\n flatten(array[i], ret)\n } else {\n ret.push(array[i])\n }\n }\n return ret\n}\n\nexport function getProtocol () {\n const protocol = window.location.protocol\n return protocol.match(/http(s)?:/gi) === null ? 'http:' : protocol\n}\n\nexport function getBrowser () {\n if (typeof window === 'undefined') return false\n\n const ua = window.navigator.userAgent\n\n if (/Opera|OPR/.test(ua)) {\n return 'Opera'\n } else if (/Chrome/i.test(ua)) {\n return 'Chrome'\n } else if (/Firefox/i.test(ua)) {\n return 'Firefox'\n } else if (/Mobile(\\/.*)? Safari/i.test(ua)) {\n return 'Mobile Safari'\n } else if (/MSIE/i.test(ua)) {\n return 'Internet Explorer'\n } else if (/Safari/i.test(ua)) {\n return 'Safari'\n }\n\n return false\n}\n\nexport function getAbsolutePath (relativePath: string) {\n const loc = window.location\n const pn = loc.pathname\n const basePath = pn.substring(0, pn.lastIndexOf('/') + 1)\n\n return loc.origin + basePath + relativePath\n}\n\nexport function deepCopy (src: any) {\n if (typeof src !== 'object') {\n return src\n }\n\n const dst: { [index: string]: any } = Array.isArray(src) ? [] : {}\n\n for (let key in src) {\n dst[ key ] = deepCopy(src[ key ])\n }\n\n return dst\n}\n\nexport function deepEqual(a: any, b: any) {\n // from https://github.com/epoberezkin/fast-deep-equal MIT\n if (a === b) return true;\n\n const arrA = Array.isArray(a)\n const arrB = Array.isArray(b)\n\n if (arrA && arrB) {\n if (a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) {\n if (!deepEqual(a[i], b[i])) return false\n }\n return true\n }\n\n if (arrA !== arrB) return false\n\n if (a && b && typeof a === 'object' && typeof b === 'object') {\n const keys = Object.keys(a)\n if (keys.length !== Object.keys(b).length) return false;\n\n const dateA = a instanceof Date\n const dateB = b instanceof Date\n if (dateA && dateB) return a.getTime() === b.getTime()\n if (dateA !== dateB) return false\n\n const regexpA = a instanceof RegExp\n const regexpB = b instanceof RegExp\n if (regexpA && regexpB) return a.toString() === b.toString()\n if (regexpA !== regexpB) return false\n\n for (let i = 0; i < keys.length; i++) {\n if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false\n }\n\n for (let i = 0; i < keys.length; i++) {\n if(!deepEqual(a[keys[i]], b[keys[i]])) return false\n }\n\n return true\n }\n\n return false\n}\n\nfunction openUrl (url: string) {\n const opened = window.open(url, '_blank')\n if (!opened) {\n window.location.href = url\n }\n}\n\nexport function download (data: Blob|string, downloadName = 'download') {\n // using ideas from https://github.com/eligrey/FileSaver.js/blob/master/FileSaver.js\n\n if (!data) return\n\n const isSafari = getBrowser() === 'Safari'\n const isChromeIos = /CriOS\\/[\\d]+/.test(window.navigator.userAgent)\n\n const a = document.createElement('a')\n\n function open (str: string) {\n openUrl(isChromeIos ? str : str.replace(/^data:[^;]*;/, 'data:attachment/file;'))\n }\n\n if (typeof navigator !== 'undefined' && (navigator as any).msSaveOrOpenBlob) {\n // native saveAs in IE 10+\n (navigator as any).msSaveOrOpenBlob(data, downloadName)\n } else if ((isSafari || isChromeIos) && FileReader) {\n if (data instanceof Blob) {\n // no downloading of blob urls in Safari\n var reader = new FileReader()\n reader.onloadend = function () {\n open(reader.result as string)\n }\n reader.readAsDataURL(data)\n } else {\n open(data)\n }\n } else {\n let objectUrlCreated = false\n if (data instanceof Blob) {\n data = URL.createObjectURL(data)\n objectUrlCreated = true\n }\n\n if ('download' in a) {\n // download link available\n a.style.display = 'hidden'\n document.body.appendChild(a)\n a.href = data\n a.download = downloadName\n a.target = '_blank'\n a.click()\n document.body.removeChild(a)\n } else {\n openUrl(data)\n }\n\n if (objectUrlCreated) {\n window.URL.revokeObjectURL(data)\n }\n }\n}\n\nexport function submit (url: string, data: FormData, callback: Function, onerror: Function) {\n const xhr = new XMLHttpRequest()\n xhr.open('POST', url)\n\n xhr.addEventListener('load', function () {\n if (xhr.status === 200 || xhr.status === 304) {\n callback(xhr.response)\n } else {\n if (typeof onerror === 'function') {\n onerror(xhr.status)\n }\n }\n }, false)\n\n xhr.send(data)\n}\n\ninterface HTMLInputEvent extends Event {\n target: HTMLInputElement & EventTarget\n}\n\nexport function open (callback: Function, extensionList = ['*']) {\n const fileInput = document.createElement('input')\n fileInput.type = 'file'\n fileInput.multiple = true\n fileInput.style.display = 'hidden'\n document.body.appendChild(fileInput)\n fileInput.accept = '.' + extensionList.join(',.')\n fileInput.addEventListener('change', function (e: HTMLInputEvent) {\n callback(e.target.files)\n }, false)\n\n fileInput.click()\n}\n\nexport function throttle (func: Function, wait: number, options: { leading?: boolean, trailing?: boolean }) {\n // from http://underscorejs.org/docs/underscore.html\n\n let context: any\n let args: any\n let result: any\n let timeout: any = null\n let previous = 0\n\n if (!options) options = {}\n\n function later () {\n previous = options.leading === false ? 0 : Date.now()\n timeout = null\n result = func.apply(context, args)\n if (!timeout) context = args = null\n }\n\n return function throttle (this: any) {\n var now = Date.now()\n if (!previous && options.leading === false) previous = now\n var remaining = wait - (now - previous)\n context = this\n args = arguments\n if (remaining <= 0 || remaining > wait) {\n if (timeout) {\n clearTimeout(timeout)\n timeout = null\n }\n previous = now\n result = func.apply(context, args)\n if (!timeout) context = args = null\n } else if (!timeout && options.trailing !== false) {\n timeout = setTimeout(later, remaining)\n }\n\n return result\n }\n}\n\nexport function lexicographicCompare (elm1: T, elm2: T) {\n if (elm1 < elm2) return -1\n if (elm1 > elm2) return 1\n return 0\n}\n\n/**\n * Does a binary search to get the index of an element in the input array\n * @function\n * @example\n * var array = [ 1, 2, 3, 4, 5, 6 ];\n * var element = 4;\n * binarySearchIndexOf( array, element ); // returns 3\n *\n * @param {Array} array - sorted array\n * @param {Anything} element - element to search for in the array\n * @param {Function} [compareFunction] - compare function\n * @return {Number} the index of the element or -1 if not in the array\n */\nexport function binarySearchIndexOf (array: T[], element: T, compareFunction = lexicographicCompare) {\n let low = 0\n let high = array.length - 1\n while (low <= high) {\n const mid = (low + high) >> 1\n const cmp = compareFunction(element, array[ mid ])\n if (cmp > 0) {\n low = mid + 1\n } else if (cmp < 0) {\n high = mid - 1\n } else {\n return mid\n }\n }\n return -low - 1\n}\n\nexport function binarySearchForLeftRange (array: number[], leftRange: number) {\n let high = array.length - 1\n if (array[ high ] < leftRange) return -1\n let low = 0\n while (low <= high) {\n const mid = (low + high) >> 1\n if (array[ mid ] >= leftRange) {\n high = mid - 1\n } else {\n low = mid + 1\n }\n }\n return high + 1\n}\n\nexport function binarySearchForRightRange (array: number[], rightRange: number) {\n if (array[ 0 ] > rightRange) return -1\n let low = 0\n let high = array.length - 1\n while (low <= high) {\n const mid = (low + high) >> 1\n if (array[ mid ] > rightRange) {\n high = mid - 1\n } else {\n low = mid + 1\n }\n }\n return low - 1\n}\n\nexport function rangeInSortedArray (array: number[], min: number, max: number) {\n const indexLeft = binarySearchForLeftRange(array, min)\n const indexRight = binarySearchForRightRange(array, max)\n if (indexLeft === -1 || indexRight === -1 || indexLeft > indexRight) {\n return 0\n } else {\n return indexRight - indexLeft + 1\n }\n}\n\nexport function dataURItoImage (dataURI: string) {\n const img = document.createElement('img')\n img.src = dataURI\n return img\n}\n\nexport function uniqueArray (array: any[]) {\n return array.sort().filter(function (value, index, sorted) {\n return (index === 0) || (value !== sorted[ index - 1 ])\n })\n}\n\n// String/arraybuffer conversion\n\nexport function uint8ToString (u8a: Uint8Array) {\n const chunkSize = 0x7000\n\n if (u8a.length > chunkSize) {\n const c = []\n\n for (let i = 0; i < u8a.length; i += chunkSize) {\n c.push(String.fromCharCode.apply(\n null, u8a.subarray(i, i + chunkSize)\n ))\n }\n\n return c.join('')\n } else {\n return String.fromCharCode.apply(null, u8a)\n }\n}\n\nexport function uint8ToLines (u8a: Uint8Array, chunkSize = 1024 * 1024 * 10, newline = '\\n') {\n let partialLine = ''\n let lines: string[] = []\n\n for (let i = 0; i < u8a.length; i += chunkSize) {\n const str = uint8ToString(u8a.subarray(i, i + chunkSize))\n const idx = str.lastIndexOf(newline)\n\n if (idx === -1) {\n partialLine += str\n } else {\n const str2 = partialLine + str.substr(0, idx)\n lines = lines.concat(str2.split(newline))\n\n if (idx === str.length - newline.length) {\n partialLine = ''\n } else {\n partialLine = str.substr(idx + newline.length)\n }\n }\n }\n\n if (partialLine !== '') {\n lines.push(partialLine)\n }\n\n return lines\n}\n\nexport type TypedArrayString = 'int8'|'int16'|'int32'|'uint8'|'uint16'|'uint32'|'float32'\nexport function getTypedArray (arrayType: TypedArrayString, arraySize: number) {\n switch (arrayType) {\n case 'int8':\n return new Int8Array(arraySize)\n case 'int16':\n return new Int16Array(arraySize)\n case 'int32':\n return new Int32Array(arraySize)\n case 'uint8':\n return new Uint8Array(arraySize)\n case 'uint16':\n return new Uint16Array(arraySize)\n case 'uint32':\n return new Uint32Array(arraySize)\n case 'float32':\n return new Float32Array(arraySize)\n default:\n throw new Error('arrayType unknown: ' + arrayType)\n }\n}\n\nexport function getUintArray (sizeOrArray: any, maxUint: number) { // TODO\n const TypedArray = maxUint > 65535 ? Uint32Array : Uint16Array\n return new TypedArray(sizeOrArray)\n}\n\nexport function ensureArray (value: any) {\n return Array.isArray(value) ? value : [value]\n}\n\nexport function ensureBuffer (a: any) { // TODO\n return (a.buffer && a.buffer instanceof ArrayBuffer) ? a.buffer : a\n}\n\nfunction _ensureClassFromArg (arg: any, constructor: { new (arg: any): any }) {\n return arg instanceof constructor ? arg : new constructor(arg)\n}\n\nfunction _ensureClassFromArray (array: any, constructor: { new (): any }) {\n if (array === undefined) {\n array = new constructor()\n } else if (Array.isArray(array)) {\n array = new constructor().fromArray(array)\n }\n return array\n}\n\nexport function ensureVector2 (v?: number[]|Vector2) {\n return _ensureClassFromArray(v, Vector2)\n}\n\nexport function ensureVector3 (v?: number[]|Vector3) {\n return _ensureClassFromArray(v, Vector3)\n}\n\nexport function ensureMatrix4 (m?: number[]|Matrix4) {\n return _ensureClassFromArray(m, Matrix4)\n}\n\nexport function ensureQuaternion (q?: number[]|Quaternion) {\n return _ensureClassFromArray(q, Quaternion)\n}\n\nexport function ensureFloat32Array (a?: number[]|Float32Array) {\n return _ensureClassFromArg(a, Float32Array)\n}\n\nexport interface RingBuffer {\n has: (value: T) => boolean\n get: (value: number) => T\n push: (value: T) => void\n count: number\n data: T[]\n clear: () => void\n}\n\nexport function createRingBuffer (length: number): RingBuffer {\n let pointer = 0\n let count = 0\n const buffer: T[] = []\n\n return {\n has: function (value: any) { return buffer.indexOf(value) !== -1 },\n get: function (idx: number) { return buffer[idx] },\n push: function (item: any) {\n buffer[pointer] = item\n pointer = (length + pointer + 1) % length\n ++count\n },\n get count () { return count },\n get data () { return buffer.slice(0, Math.min(count, length)) },\n clear: function () {\n count = 0\n pointer = 0\n buffer.length = 0\n }\n }\n}\n\nexport interface SimpleDict {\n has: (k: K) => boolean\n add: (k: K, v: V) => void\n del: (k: K) => void\n values: V[]\n}\n\nexport function createSimpleDict (): SimpleDict {\n const set: { [k: string]: V } = {}\n\n return {\n has: function (k: K) { return set[JSON.stringify(k)] !== undefined },\n add: function (k: K, v: V) { set[JSON.stringify(k)] = v },\n del: function (k: K) { delete set[JSON.stringify(k)] },\n get values () { return Object.keys(set).map(k => set[k]) }\n }\n}\n\nexport interface SimpleSet {\n has: (value: T) => boolean\n add: (value: T) => void\n del: (value: T) => void\n list: T[]\n}\n\nexport function createSimpleSet (): SimpleSet {\n const set: { [k: string]: T } = {}\n\n return {\n has: function (v: T) { return set[JSON.stringify(v)] !== undefined },\n add: function (v: T) { set[JSON.stringify(v)] = v },\n del: function (v: T) { delete set[JSON.stringify(v)] },\n get list () { return Object.keys(set).map(k => set[k]) },\n }\n}\n","/**\n * @file Registry\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\n\nfunction toLowerCaseString (value: string) {\n return defaults(value, '').toString().toLowerCase()\n}\n\nexport default class Registry {\n name: string\n private _dict: {[k: string]: any}\n\n constructor (name: string) {\n this.name = name\n this._dict = {}\n }\n\n add (key: string, value: any) {\n this._dict[ toLowerCaseString(key) ] = value\n }\n\n get (key: string) {\n return this._dict[ toLowerCaseString(key) ]\n }\n\n get names () {\n return Object.keys(this._dict)\n }\n}","/**\n * @file Math Utils\n * @author Alexander Rose \n * @private\n */\n\nexport function degToRad (deg: number) {\n return deg * 0.01745 // deg * Math.PI / 180\n}\n\nexport function radToDeg (rad: number) {\n return rad * 57.29578 // rad * 180 / Math.PI\n}\n\n// http://www.broofa.com/Tools/Math.uuid.htm\nconst chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')\nconst uuid = new Array(36)\n\nexport function generateUUID () {\n let rnd = 0\n let r\n\n for (let i = 0; i < 36; i++) {\n if (i === 8 || i === 13 || i === 18 || i === 23) {\n uuid[ i ] = '-'\n } else if (i === 14) {\n uuid[ i ] = '4'\n } else {\n if (rnd <= 0x02) rnd = 0x2000000 + (Math.random() * 0x1000000) | 0\n r = rnd & 0xf\n rnd = rnd >> 4\n uuid[ i ] = chars[ (i === 19) ? (r & 0x3) | 0x8 : r ]\n }\n }\n\n return uuid.join('')\n}\n\nexport function countSetBits (i: number) {\n i = i - ((i >> 1) & 0x55555555)\n i = (i & 0x33333333) + ((i >> 2) & 0x33333333)\n return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24\n}\n\nexport function normalize (value: number, min: number, max: number) {\n return (value - min) / (max - min)\n}\n\nexport function clamp (value: number, min: number, max: number) {\n return Math.max(min, Math.min(max, value))\n}\n\nexport function pclamp (value: number) {\n return clamp(value, 0, 100)\n}\n\nexport function saturate (value: number) {\n return clamp(value, 0, 1)\n}\n\nexport function lerp (start: number, stop: number, alpha: number) {\n return start + (stop - start) * alpha\n}\n\nexport function spline (p0: number, p1: number, p2: number, p3: number, t: number, tension: number) {\n const v0 = (p2 - p0) * tension\n const v1 = (p3 - p1) * tension\n const t2 = t * t\n const t3 = t * t2\n return (2 * p1 - 2 * p2 + v0 + v1) * t3 +\n (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 +\n v0 * t + p1\n}\n\nexport function smoothstep (min: number, max: number, x: number) {\n x = saturate(normalize(x, min, max))\n return x * x * (3 - 2 * x)\n}\n\nexport function smootherstep (min: number, max: number, x: number) {\n x = saturate(normalize(x, min, max))\n return x * x * x * (x * (x * 6 - 15) + 10)\n}\n\nexport function smootheststep (min: number, max: number, x: number) {\n x = saturate(normalize(x, min, max))\n return (\n -20 * Math.pow(x, 7) +\n 70 * Math.pow(x, 6) -\n 84 * Math.pow(x, 5) +\n 35 * Math.pow(x, 4)\n )\n}\n\nexport function almostIdentity (value: number, start: number, stop: number) {\n if (value > start) return value\n const a = 2 * stop - start\n const b = 2 * start - 3 * stop\n const t = value / start\n return (a * t + b) * t * t + stop\n}","/**\n * @file Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Color } from 'three'\nimport * as chroma from 'chroma-js'\n\nimport { createParams } from '../utils'\nimport { NumberArray } from '../types'\nimport Structure from '../structure/structure'\nimport Surface from '../surface/surface'\nimport Volume from '../surface/volume'\nimport AtomProxy from '../proxy/atom-proxy'\nimport BondProxy from '../proxy/bond-proxy'\n\nexport type ColorMode = 'rgb'|'hsv'|'hsl'|'hsi'|'lab'|'hcl'\nexport type ColorSpace = 'sRGB' | 'linear'\n\n/**\n * Internal color space for all colors (global).\n * Colors are always specified as sRGB; if this is set to\n * 'linear' then colors get linearized when used internally\n * as vertex or texture colors.\n * @see setColorSpace/getColorSpace.\n */\nvar colorSpace: ColorSpace = 'sRGB' // default: don't linearize\n\n/** Set the global internal color space for colormakers */\nexport function setColorSpace(space: ColorSpace) {\n colorSpace = space\n}\n\n/** Get the global internal color space for colormakers */\nexport function getColorSpace() {\n return colorSpace\n}\n\nexport const ScaleDefaultParameters = {\n scale: 'uniform' as string|string[],\n mode: 'hcl' as ColorMode,\n domain: [ 0, 1 ] as number[],\n value: 0xFFFFFF,\n reverse: false,\n}\nexport type ScaleParameters = typeof ScaleDefaultParameters\n\nexport interface ColorData {\n atomData?: number[],\n bondData?: number[]\n}\n\nexport interface ColormakerParameters extends ScaleParameters {\n structure?: Structure\n volume?: Volume\n surface?: Surface\n data?: ColorData\n}\n\nexport type StuctureColormakerParams = { structure: Structure } & Partial\nexport type VolumeColormakerParams = { volume: Volume } & Partial\nexport type ColormakerScale = (v: number) => number\nexport type ColormakerConstructor = new (...p: ConstructorParameters) => Colormaker\n\nconst tmpColor = new Color()\n\n/** Decorator for optionally linearizing a numeric color */\ntype colorFuncType = (value: any, fromTo?: boolean) => number // decorator applies to functions with this shape\nexport function manageColor\n (_target: Object,\n _name: string | symbol,\n descriptor: TypedPropertyDescriptor): PropertyDescriptor {\n const originalMethod = descriptor.value\n const linearize: colorFuncType = function (this: T, value: any, fromTo?: boolean) {\n let result = originalMethod!.bind(this, value, fromTo)()\n if (colorSpace == 'linear') {\n tmpColor.set(result)\n tmpColor.convertSRGBToLinear()\n return tmpColor.getHex()\n } else {\n return result\n }\n }\n descriptor.value = linearize\n return descriptor\n }\n\n/**\n * Class for making colors.\n * @interface\n */\nabstract class Colormaker {\n parameters: ColormakerParameters\n atomProxy?: AtomProxy\n\n /**\n * Create a colormaker instance\n * @param {ColormakerParameters} params - colormaker parameter\n */\n constructor (params: Partial = {}) {\n this.parameters = createParams(params, ScaleDefaultParameters)\n\n if (typeof this.parameters.value === 'string') {\n this.parameters.value = tmpColor.set(this.parameters.value).getHex()\n }\n\n if (this.parameters.structure) {\n this.atomProxy = this.parameters.structure.getAtomProxy()\n }\n }\n\n getScale (params: Partial = {}) {\n const p = createParams(params, this.parameters)\n\n if (p.scale === 'rainbow') {\n p.scale = [ 'red', 'orange', 'yellow', 'green', 'blue' ]\n } else if (p.scale === 'rwb') {\n p.scale = [ 'red', 'white', 'blue' ]\n }\n\n if (p.reverse) {\n p.domain = p.domain.slice().reverse()\n }\n return chroma\n .scale(p.scale as any) // TODO\n .mode(p.mode)\n .domain(p.domain)\n .out('num' as any) // returns RGB color as numeric (not string \"#ffffff\")\n }\n\n /**\n * save a color to an array\n * @param {Integer} color - hex color value\n * @param {Array|TypedArray} array - destination\n * @param {Integer} offset - index into the array\n * @return {Array} the destination array\n */\n colorToArray (color: number, array: NumberArray = [], offset = 0) {\n array[ offset ] = (color >> 16 & 255) / 255\n array[ offset + 1 ] = (color >> 8 & 255) / 255\n array[ offset + 2 ] = (color & 255) / 255\n\n return array\n }\n\n atomColor? (atom: AtomProxy): number\n\n /**\n * save an atom color to an array\n * @param {AtomProxy} atom - atom to get color for\n * @param {Array|TypedArray} array - destination\n * @param {Integer} offset - index into the array\n * @return {Array} the destination array\n */\n atomColorToArray (atom: AtomProxy, array: NumberArray, offset: number) {\n return this.colorToArray(\n this.atomColor ? this.atomColor(atom) : 0x000000, array, offset\n )\n }\n\n /**\n * return the color for an bond\n * @param {BondProxy} bond - bond to get color for\n * @param {Boolean} fromTo - whether to use the first or second atom of the bond\n * @return {Integer} hex bond color\n */\n bondColor (bond: BondProxy, fromTo: boolean) {\n if (this.atomProxy && this.atomColor) {\n this.atomProxy.index = fromTo ? bond.atomIndex1 : bond.atomIndex2\n return this.atomColor(this.atomProxy)\n } else {\n return 0x000000\n }\n }\n\n /**\n * safe a bond color to an array\n * @param {BondProxy} bond - bond to get color for\n * @param {Boolean} fromTo - whether to use the first or second atom of the bond\n * @param {Array|TypedArray} array - destination\n * @param {Integer} offset - index into the array\n * @return {Array} the destination array\n */\n bondColorToArray (bond: BondProxy, fromTo: boolean, array: NumberArray, offset: number) {\n return this.colorToArray(\n this.bondColor(bond, fromTo), array, offset\n )\n }\n\n volumeColor? (index: number): number\n\n /**\n * safe a volume cell color to an array\n * @param {Integer} index - volume cell index\n * @param {Array|TypedArray} array - destination\n * @param {Integer} offset - index into the array\n * @return {Array} the destination array\n */\n volumeColorToArray (index: number, array: NumberArray, offset: number) {\n return this.colorToArray(\n this.volumeColor ? this.volumeColor(index) : 0x000000, array, offset\n )\n }\n\n positionColor? (position: Vector3): number\n\n /**\n * safe a color for coordinates in space to an array\n * @param {Vector3} coords - xyz coordinates\n * @param {Array|TypedArray} array - destination\n * @param {Integer} offset - index into the array\n * @return {Array} the destination array\n */\n positionColorToArray (coords: Vector3, array: NumberArray, offset: number) {\n return this.colorToArray(\n this.positionColor ? this.positionColor(coords) : 0x000000, array, offset\n )\n }\n}\n\nexport default Colormaker\n","/**\n * @file Selection Constants\n * @author Alexander Rose \n * @private\n */\n\nexport enum kwd {\n PROTEIN = 1,\n NUCLEIC = 2,\n RNA = 3,\n DNA = 4,\n POLYMER = 5,\n WATER = 6,\n HELIX = 7,\n SHEET = 8,\n TURN = 9,\n BACKBONE = 10,\n SIDECHAIN = 11,\n ALL = 12,\n HETERO = 13,\n ION = 14,\n SACCHARIDE = 15,\n SUGAR = 15,\n BONDED = 16,\n RING = 17,\n AROMATICRING = 18,\n METAL = 19,\n POLARH = 20,\n NONE = 21\n}\n\nexport const SelectAllKeyword = [ '*', '', 'ALL' ]\nexport const SelectNoneKeyword = [ 'NONE' ]\n\nexport const AtomOnlyKeywords = [\n kwd.BACKBONE, kwd.SIDECHAIN, kwd.BONDED, kwd.RING, kwd.AROMATICRING, kwd.METAL, kwd.POLARH\n]\n\nexport const ChainKeywords = [\n kwd.POLYMER, kwd.WATER\n]\n\nexport const SmallResname = [ 'ALA', 'GLY', 'SER' ]\nexport const NucleophilicResname = [ 'CYS', 'SER', 'THR' ]\nexport const HydrophobicResname = [ 'ALA', 'ILE', 'LEU', 'MET', 'PHE', 'PRO', 'TRP', 'VAL' ]\nexport const AromaticResname = [ 'PHE', 'TRP', 'TYR', 'HIS' ]\nexport const AmideResname = [ 'ASN', 'GLN' ]\nexport const AcidicResname = [ 'ASP', 'GLU' ]\nexport const BasicResname = [ 'ARG', 'HIS', 'LYS' ]\nexport const ChargedResname = [ 'ARG', 'ASP', 'GLU', 'HIS', 'LYS' ]\nexport const PolarResname = [ 'ASN', 'ARG', 'ASP', 'CYS', 'GLY', 'GLN', 'GLU', 'HIS', 'LYS', 'SER', 'THR', 'TYR' ]\nexport const NonpolarResname = [ 'ALA', 'ILE', 'LEU', 'MET', 'PHE', 'PRO', 'TRP', 'VAL' ]\nexport const CyclicResname = [ 'HIS', 'PHE', 'PRO', 'TRP', 'TYR' ]\nexport const AliphaticResname = [ 'ALA', 'GLY', 'ILE', 'LEU', 'VAL' ]\n","/**\n * @file Selection Test\n * @author Alexander Rose \n * @private\n */\n\nimport { binarySearchIndexOf, rangeInSortedArray } from '../utils'\nimport { kwd, AtomOnlyKeywords, ChainKeywords } from './selection-constants'\n\nimport AtomProxy from '../proxy/atom-proxy'\nimport ResidueProxy from '../proxy/residue-proxy'\nimport ChainProxy from '../proxy/chain-proxy'\nimport ModelProxy from '../proxy/model-proxy'\n\nexport type ProxyEntity = AtomProxy|ResidueProxy|ChainProxy|ModelProxy\ntype TestEntityFn = (e: ProxyEntity, s: SelectionRule) => boolean|-1\ntype FilterFn = (s: SelectionRule) => boolean\nexport type SelectionTest = false|((e: ProxyEntity) => boolean|-1)\n\nexport type SelectionOperator = 'AND'|'OR'\nexport interface SelectionRule {\n keyword?: any\n atomname?: string\n element?: string\n atomindex?: number[]\n altloc?: string\n inscode?: string\n resname?: string|string[]\n sstruc?: string\n resno?: number|[number, number]\n chainname?: string\n model?: number\n\n error?: string\n rules?: SelectionRule[]\n negate?: boolean\n operator?: SelectionOperator\n}\n\nfunction atomTestFn (a: AtomProxy, s: SelectionRule) {\n // returning -1 means the rule is not applicable\n if (s.atomname === undefined && s.element === undefined &&\n s.altloc === undefined && s.atomindex === undefined &&\n s.keyword === undefined && s.inscode === undefined &&\n s.resname === undefined && s.sstruc === undefined &&\n s.resno === undefined && s.chainname === undefined &&\n s.model === undefined\n ) return -1\n\n if (s.keyword !== undefined) {\n if (s.keyword === kwd.BACKBONE && !a.isBackbone()) return false\n if (s.keyword === kwd.SIDECHAIN && !a.isSidechain()) return false\n if (s.keyword === kwd.BONDED && !a.isBonded()) return false\n if (s.keyword === kwd.RING && !a.isRing()) return false\n if (s.keyword === kwd.AROMATICRING && !a.isAromatic()) return false\n\n if (s.keyword === kwd.HETERO && !a.isHetero()) return false\n if (s.keyword === kwd.PROTEIN && !a.isProtein()) return false\n if (s.keyword === kwd.NUCLEIC && !a.isNucleic()) return false\n if (s.keyword === kwd.RNA && !a.isRna()) return false\n if (s.keyword === kwd.DNA && !a.isDna()) return false\n if (s.keyword === kwd.POLYMER && !a.isPolymer()) return false\n if (s.keyword === kwd.WATER && !a.isWater()) return false\n if (s.keyword === kwd.HELIX && !a.isHelix()) return false\n if (s.keyword === kwd.SHEET && !a.isSheet()) return false\n if (s.keyword === kwd.TURN && !a.isTurn()) return false\n if (s.keyword === kwd.ION && !a.isIon()) return false\n if (s.keyword === kwd.SACCHARIDE && !a.isSaccharide()) return false\n if (s.keyword === kwd.METAL && !a.isMetal()) return false\n if (s.keyword === kwd.POLARH && !a.isPolarHydrogen()) return false\n }\n\n if (s.atomname !== undefined && s.atomname !== a.atomname) return false\n if (s.element !== undefined && s.element !== a.element) return false\n if (s.altloc !== undefined && s.altloc !== a.altloc) return false\n\n if (s.atomindex !== undefined &&\n binarySearchIndexOf(s.atomindex, a.index) < 0\n ) return false\n\n if (s.resname !== undefined) {\n if (Array.isArray(s.resname)) {\n if (!s.resname.includes(a.resname)) return false\n } else {\n if (s.resname !== a.resname) return false\n }\n }\n if (s.sstruc !== undefined && s.sstruc !== a.sstruc) return false\n if (s.resno !== undefined) {\n if (Array.isArray(s.resno) && s.resno.length === 2) {\n if (s.resno[0] > a.resno || s.resno[1] < a.resno) return false\n } else {\n if (s.resno !== a.resno) return false\n }\n }\n if (s.inscode !== undefined && s.inscode !== a.inscode) return false\n\n if (s.chainname !== undefined && s.chainname !== a.chainname) return false\n if (s.model !== undefined && s.model !== a.modelIndex) return false\n\n return true\n}\n\nfunction residueTestFn (r: ResidueProxy, s: SelectionRule) {\n // returning -1 means the rule is not applicable\n if (s.resname === undefined && s.resno === undefined && s.inscode === undefined &&\n s.sstruc === undefined && s.model === undefined && s.chainname === undefined &&\n s.atomindex === undefined &&\n (s.keyword === undefined || AtomOnlyKeywords.includes(s.keyword))\n ) return -1\n\n if (s.keyword !== undefined) {\n if (s.keyword === kwd.HETERO && !r.isHetero()) return false\n if (s.keyword === kwd.PROTEIN && !r.isProtein()) return false\n if (s.keyword === kwd.NUCLEIC && !r.isNucleic()) return false\n if (s.keyword === kwd.RNA && !r.isRna()) return false\n if (s.keyword === kwd.DNA && !r.isDna()) return false\n if (s.keyword === kwd.POLYMER && !r.isPolymer()) return false\n if (s.keyword === kwd.WATER && !r.isWater()) return false\n if (s.keyword === kwd.HELIX && !r.isHelix()) return false\n if (s.keyword === kwd.SHEET && !r.isSheet()) return false\n if (s.keyword === kwd.TURN && !r.isTurn()) return false\n if (s.keyword === kwd.ION && !r.isIon()) return false\n if (s.keyword === kwd.SACCHARIDE && !r.isSaccharide()) return false\n }\n\n if (s.atomindex !== undefined &&\n rangeInSortedArray(s.atomindex, r.atomOffset, r.atomEnd) === 0\n ) return false\n\n if (s.resname !== undefined) {\n if (Array.isArray(s.resname)) {\n if (!s.resname.includes(r.resname)) return false\n } else {\n if (s.resname !== r.resname) return false\n }\n }\n if (s.sstruc !== undefined && s.sstruc !== r.sstruc) return false\n if (s.resno !== undefined) {\n if (Array.isArray(s.resno) && s.resno.length === 2) {\n if (s.resno[0] > r.resno || s.resno[1] < r.resno) return false\n } else {\n if (s.resno !== r.resno) return false\n }\n }\n if (s.inscode !== undefined && s.inscode !== r.inscode) return false\n\n if (s.chainname !== undefined && s.chainname !== r.chainname) return false\n if (s.model !== undefined && s.model !== r.modelIndex) return false\n\n return true\n}\n\nfunction chainTestFn (c: ChainProxy, s: SelectionRule) {\n // returning -1 means the rule is not applicable\n if (s.chainname === undefined && s.model === undefined && s.atomindex === undefined &&\n (s.keyword === undefined || !ChainKeywords.includes(s.keyword) || !c.entity)\n ) return -1\n\n if (s.keyword !== undefined) {\n if (s.keyword === kwd.POLYMER && !c.entity.isPolymer()) return false\n if (s.keyword === kwd.WATER && !c.entity.isWater()) return false\n }\n\n if (s.atomindex !== undefined &&\n rangeInSortedArray(s.atomindex, c.atomOffset, c.atomEnd) === 0\n ) return false\n\n if (s.chainname !== undefined && s.chainname !== c.chainname) return false\n\n if (s.model !== undefined && s.model !== c.modelIndex) return false\n\n return true\n}\n\nfunction modelTestFn (m: ModelProxy, s: SelectionRule) {\n // returning -1 means the rule is not applicable\n if (s.model === undefined && s.atomindex === undefined) return -1\n\n if (s.atomindex !== undefined &&\n rangeInSortedArray(s.atomindex, m.atomOffset, m.atomEnd) === 0\n ) return false\n\n if (s.model !== undefined && s.model !== m.index) return false\n\n return true\n}\n\nfunction makeTest (selection: SelectionRule|null, fn: TestEntityFn) {\n if (selection === null) return false\n if (selection.error) return false\n if (!selection.rules || selection.rules.length === 0) return false\n\n const n = selection.rules.length\n\n const t = !selection.negate\n const f = !!selection.negate\n\n const subTests: SelectionTest[] = []\n for (let i = 0; i < n; ++i) {\n const s = selection.rules[ i ]\n if (s.hasOwnProperty('operator')) {\n subTests[ i ] = makeTest(s, fn) as SelectionTest // TODO\n }\n }\n\n // ( x and y ) can short circuit on false\n // ( x or y ) can short circuit on true\n // not ( x and y )\n\n return function test (entity: ProxyEntity) {\n const and = selection.operator === 'AND'\n let na = false\n\n for (let i = 0; i < n; ++i) {\n const s = selection.rules![ i ] // TODO\n let ret\n\n if (s.hasOwnProperty('operator')) {\n const test = subTests[ i ]\n if (test !== false) {\n ret = test(entity)\n } else {\n ret = -1\n }\n\n if (ret === -1) {\n na = true\n continue\n } else if (ret === true) {\n if (and) { continue } else { return t }\n } else {\n if (and) { return f } else { continue }\n }\n } else {\n if (s.keyword === kwd.ALL) {\n if (and) { continue } else { return t }\n } else if (s.keyword === kwd.NONE) {\n if (and) { continue } else { return f }\n }\n\n ret = fn(entity, s)\n\n // console.log( entity.qualifiedName(), ret, s, selection.negate, \"t\", t, \"f\", f )\n\n if (ret === -1) {\n na = true\n continue\n } else if (ret === true) {\n if (and) { continue } else { return t }\n } else {\n if (and) { return f } else { continue }\n }\n }\n }\n\n if (na) {\n return -1\n } else {\n if (and) { return t } else { return f }\n }\n } as SelectionTest\n}\n\nfunction filter (selection: SelectionRule, fn: FilterFn) {\n if (selection.error) return selection\n if (!selection.rules || selection.rules.length === 0) return selection\n\n const n = selection.rules.length\n\n const filtered: SelectionRule = {\n operator: selection.operator,\n rules: []\n }\n if (selection.hasOwnProperty('negate')) {\n filtered.negate = selection.negate\n }\n\n for (let i = 0; i < n; ++i) {\n const s = selection.rules[ i ]\n if (s.hasOwnProperty('operator')) {\n const fs = filter(s, fn)\n if (fs !== null) filtered.rules!.push(fs) // TODO\n } else if (!fn(s)) {\n filtered.rules!.push(s) // TODO\n }\n }\n\n if (filtered.rules!.length > 0) { // TODO\n // TODO maybe the filtered rules could be returned\n // in some case, but the way how tests are applied\n // e.g. when traversing a structure would also need\n // to change\n return selection\n // return filtered;\n } else {\n return null\n }\n}\n\nfunction makeAtomTest (selection: SelectionRule, atomOnly = false) {\n let filteredSelection: SelectionRule|null = selection\n if (atomOnly) {\n filteredSelection = filter(selection, function (s) {\n if (s.keyword !== undefined && !AtomOnlyKeywords.includes(s.keyword)) return true\n if (s.model !== undefined) return true\n if (s.chainname !== undefined) return true\n if (s.resname !== undefined) return true\n if (s.resno !== undefined) return true\n if (s.sstruc !== undefined) return true\n return false\n })\n }\n return makeTest(filteredSelection, atomTestFn)\n}\n\nfunction makeResidueTest (selection: SelectionRule, residueOnly = false) {\n let filteredSelection: SelectionRule|null = selection\n if (residueOnly) {\n filteredSelection = filter(selection, function (s) {\n if (s.keyword !== undefined && AtomOnlyKeywords.includes(s.keyword)) return true\n if (s.model !== undefined) return true\n if (s.chainname !== undefined) return true\n if (s.atomname !== undefined) return true\n if (s.element !== undefined) return true\n if (s.altloc !== undefined) return true\n return false\n })\n }\n return makeTest(filteredSelection, residueTestFn)\n}\n\nfunction makeChainTest (selection: SelectionRule, chainOnly = false) {\n let filteredSelection: SelectionRule|null = selection\n if (chainOnly) {\n filteredSelection = filter(selection, function (s) {\n if (s.keyword !== undefined && !ChainKeywords.includes(s.keyword)) return true\n // if( s.model!==undefined ) return true;\n if (s.resname !== undefined) return true\n if (s.resno !== undefined) return true\n if (s.atomname !== undefined) return true\n if (s.element !== undefined) return true\n if (s.altloc !== undefined) return true\n if (s.sstruc !== undefined) return true\n if (s.inscode !== undefined) return true\n return false\n })\n }\n return makeTest(filteredSelection, chainTestFn)\n}\n\nfunction makeModelTest (selection: SelectionRule, modelOnly = false) {\n let filteredSelection: SelectionRule|null = selection\n if (modelOnly) {\n filteredSelection = filter(selection, function (s) {\n if (s.keyword !== undefined) return true\n if (s.chainname !== undefined) return true\n if (s.resname !== undefined) return true\n if (s.resno !== undefined) return true\n if (s.atomname !== undefined) return true\n if (s.element !== undefined) return true\n if (s.altloc !== undefined) return true\n if (s.sstruc !== undefined) return true\n if (s.inscode !== undefined) return true\n return false\n })\n }\n return makeTest(filteredSelection, modelTestFn)\n}\n\nexport {\n makeAtomTest,\n makeResidueTest,\n makeChainTest,\n makeModelTest\n}\n","/**\n * @file Selection\n * @author Alexander Rose \n * @private\n */\n\nimport { Signal } from 'signals'\n\nimport { parseSele } from './selection-parser'\nimport {\n SelectionTest, SelectionRule,\n makeAtomTest, makeResidueTest, makeChainTest, makeModelTest\n} from './selection-test'\nimport { SelectAllKeyword, SelectNoneKeyword } from './selection-constants'\n\nexport type SelectionSignals = {\n stringChanged: Signal\n}\n\n/**\n * Selection\n */\nclass Selection {\n signals: SelectionSignals\n string: string\n selection: SelectionRule\n\n test: SelectionTest\n residueTest: SelectionTest\n chainTest: SelectionTest\n modelTest: SelectionTest\n\n atomOnlyTest: SelectionTest\n residueOnlyTest: SelectionTest\n chainOnlyTest: SelectionTest\n modelOnlyTest: SelectionTest\n\n /**\n * Create Selection\n * @param {String} string - selection string, see {@tutorial selection-language}\n */\n constructor (string?: string) {\n this.signals = {\n stringChanged: new Signal()\n }\n\n this.setString(string)\n }\n\n get type () { return 'selection' }\n\n setString (string?: string, silent?: boolean) {\n if (string === undefined) string = this.string || ''\n if (string === this.string) return\n\n try {\n this.selection = parseSele(string)\n } catch (e) {\n // Log.error( e.stack );\n this.selection = { 'error': e.message }\n }\n const selection = this.selection\n\n this.string = string\n\n this.test = makeAtomTest(selection)\n this.residueTest = makeResidueTest(selection)\n this.chainTest = makeChainTest(selection)\n this.modelTest = makeModelTest(selection)\n\n this.atomOnlyTest = makeAtomTest(selection, true)\n this.residueOnlyTest = makeResidueTest(selection, true)\n this.chainOnlyTest = makeChainTest(selection, true)\n this.modelOnlyTest = makeModelTest(selection, true)\n\n if (!silent) {\n this.signals.stringChanged.dispatch(this.string)\n }\n }\n\n isAllSelection () {\n return SelectAllKeyword.includes(this.string.toUpperCase())\n }\n\n isNoneSelection () {\n return SelectNoneKeyword.includes(this.string.toUpperCase())\n }\n}\n\nexport default Selection\n","/**\n * @file Selection Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { SelectionRule, SelectionOperator } from './selection-test'\nimport {\n kwd, SelectAllKeyword,\n SmallResname, NucleophilicResname, HydrophobicResname, AromaticResname,\n AmideResname, AcidicResname, BasicResname, ChargedResname,\n PolarResname, NonpolarResname, CyclicResname, AliphaticResname\n} from './selection-constants'\n\nfunction parseSele (string: string) {\n let retSelection: SelectionRule = {\n operator: undefined,\n rules: []\n }\n\n if (!string) {\n return retSelection\n }\n\n let selection = retSelection\n let newSelection: SelectionRule\n let oldSelection: SelectionRule\n const selectionStack: SelectionRule[] = []\n\n string = string.replace(/\\(/g, ' ( ').replace(/\\)/g, ' ) ').trim()\n if (string.charAt(0) === '(' && string.substr(-1) === ')') {\n string = string.slice(1, -1).trim()\n }\n const chunks = string.split(/\\s+/)\n\n // Log.log( string, chunks )\n\n const createNewContext = (operator?: SelectionOperator) => {\n newSelection = {\n operator,\n rules: []\n }\n if (selection === undefined) {\n selection = newSelection\n retSelection = newSelection\n } else {\n selection.rules!.push(newSelection)\n selectionStack.push(selection)\n selection = newSelection\n }\n }\n\n const getPrevContext = function (operator?: SelectionOperator) {\n oldSelection = selection\n selection = selectionStack.pop()!\n if (selection === undefined) {\n createNewContext(operator)\n pushRule(oldSelection)\n }\n }\n\n const pushRule = function (rule: SelectionRule) {\n selection.rules!.push(rule)\n }\n\n let not: false|0|1|2 = false\n\n for (let i = 0; i < chunks.length; ++i) {\n const c = chunks[ i ]\n const cu = c.toUpperCase()\n\n // handle parens\n\n if (c === '(') {\n // Log.log( \"(\" );\n not = false\n createNewContext()\n continue\n } else if (c === ')') {\n // Log.log( \")\" );\n getPrevContext()\n if (selection.negate) {\n getPrevContext()\n }\n continue\n }\n\n // leave 'not' context\n\n if (not > 0) {\n if (cu === 'NOT') {\n not = 1\n } else if (not === 1) {\n not = 2\n } else if (not === 2) {\n not = false\n getPrevContext()\n } else {\n throw new Error(\"something went wrong with 'not'\")\n }\n }\n\n // handle logic operators\n\n if (cu === 'AND') {\n // Log.log( \"AND\" );\n if (selection.operator === 'OR') {\n const lastRule = selection.rules!.pop()!\n createNewContext('AND')\n pushRule(lastRule)\n } else {\n selection.operator = 'AND'\n }\n continue\n } else if (cu === 'OR') {\n // Log.log( \"OR\" );\n if (selection.operator === 'AND') {\n getPrevContext('OR')\n } else {\n selection.operator = 'OR'\n }\n continue\n } else if (c.toUpperCase() === 'NOT') {\n // Log.log( \"NOT\", j );\n not = 1\n createNewContext()\n selection.negate = true\n continue\n } else {\n // Log.log( \"chunk\", c, j, selection );\n }\n\n // handle keyword attributes\n\n // ensure `cu` is not a number before testing if it is in the\n // kwd enum dictionary which includes the enum numbers as well...\n if (+cu !== +cu) {\n const keyword = (kwd as any)[ cu ]\n if (keyword !== undefined) {\n pushRule({ keyword })\n continue\n }\n }\n\n if (cu === 'HYDROGEN') {\n pushRule({\n operator: 'OR',\n rules: [\n { element: 'H' },\n { element: 'D' }\n ]\n })\n continue\n }\n\n if (cu === 'SMALL') {\n pushRule({ resname: SmallResname })\n continue\n }\n\n if (cu === 'NUCLEOPHILIC') {\n pushRule({ resname: NucleophilicResname })\n continue\n }\n\n if (cu === 'HYDROPHOBIC') {\n pushRule({ resname: HydrophobicResname })\n continue\n }\n\n if (cu === 'AROMATIC') {\n pushRule({ resname: AromaticResname })\n continue\n }\n\n if (cu === 'AMIDE') {\n pushRule({ resname: AmideResname })\n continue\n }\n\n if (cu === 'ACIDIC') {\n pushRule({ resname: AcidicResname })\n continue\n }\n\n if (cu === 'BASIC') {\n pushRule({ resname: BasicResname })\n continue\n }\n\n if (cu === 'CHARGED') {\n pushRule({ resname: ChargedResname })\n continue\n }\n\n if (cu === 'POLAR') {\n pushRule({ resname: PolarResname })\n continue\n }\n\n if (cu === 'NONPOLAR') {\n pushRule({ resname: NonpolarResname })\n continue\n }\n\n if (cu === 'CYCLIC') {\n pushRule({ resname: CyclicResname })\n continue\n }\n\n if (cu === 'ALIPHATIC') {\n pushRule({ resname: AliphaticResname })\n continue\n }\n\n if (cu === 'SIDECHAINATTACHED') {\n pushRule({\n operator: 'OR',\n rules: [\n { keyword: kwd.SIDECHAIN },\n {\n operator: 'AND',\n negate: false,\n rules: [\n { keyword: kwd.PROTEIN },\n {\n operator: 'OR',\n negate: false,\n rules: [\n { atomname: 'CA' },\n { atomname: 'BB' }\n ]\n }\n ]\n },\n {\n operator: 'AND',\n negate: false,\n rules: [\n { resname: 'PRO' },\n { atomname: 'N' }\n ]\n },\n {\n operator: 'AND',\n negate: false,\n rules: [\n { keyword: kwd.NUCLEIC },\n {\n operator: 'OR',\n negate: true,\n rules: [\n { atomname: 'P' },\n { atomname: 'OP1' },\n { atomname: 'OP2' },\n { atomname: \"O3'\" },\n { atomname: 'O3*' },\n { atomname: \"HO3'\"},\n { atomname: \"O5'\" },\n { atomname: 'O5*' },\n { atomname: \"HO5'\"},\n { atomname: \"C5'\" },\n { atomname: 'C5*' },\n { atomname: \"H5'\" },\n { atomname: \"H5''\"}\n ]\n }\n ]\n }\n ]\n })\n continue\n }\n\n if (cu === 'APOLARH') {\n pushRule({\n operator: 'AND',\n negate: false,\n rules: [\n { element: 'H' },\n {\n negate: true,\n operator: undefined,\n rules: [\n { keyword: kwd.POLARH }\n ]\n }\n ]\n })\n continue\n }\n\n if (cu === 'LIGAND') {\n pushRule({\n operator: 'AND',\n rules: [\n {\n operator: 'OR',\n rules: [\n {\n operator: 'AND',\n rules: [\n { keyword: kwd.HETERO },\n {\n negate: true,\n operator: undefined,\n rules: [\n { keyword: kwd.POLYMER }\n ]\n }\n ]\n },\n {\n negate: true,\n operator: undefined,\n rules: [\n { keyword: kwd.POLYMER }\n ]\n }\n ]\n },\n {\n negate: true,\n operator: undefined,\n rules: [\n {\n operator: 'OR',\n rules: [\n { keyword: kwd.WATER },\n { keyword: kwd.ION }\n ]\n }\n ]\n }\n ]\n })\n continue\n }\n\n if (SelectAllKeyword.indexOf(cu) !== -1) {\n pushRule({ keyword: kwd.ALL })\n continue\n }\n\n // handle atom expressions\n\n if (c.charAt(0) === '@') {\n const indexList = c.substr(1).split(',').map(x => parseInt(x))\n indexList.sort(function (a, b) { return a - b })\n pushRule({ atomindex: indexList })\n continue\n }\n\n if (c.charAt(0) === '#') {\n console.error('# for element selection deprecated, use _')\n pushRule({ element: cu.substr(1) })\n continue\n }\n if (c.charAt(0) === '_') {\n pushRule({ element: cu.substr(1) })\n continue\n }\n\n if (c[0] === '[' && c[c.length - 1] === ']') {\n const resnameList = cu.substr(1, c.length - 2).split(',')\n const resname = resnameList.length > 1 ? resnameList : resnameList[ 0 ]\n pushRule({ resname: resname })\n continue\n } else if (\n (c.length >= 1 && c.length <= 4) &&\n c[0] !== '^' && c[0] !== ':' && c[0] !== '.' && c[0] !== '%' && c[0] !== '/' &&\n isNaN(parseInt(c))\n ) {\n pushRule({ resname: cu })\n continue\n }\n\n // there must be only one constraint per rule\n // otherwise a test quickly becomes not applicable\n // e.g. chainTest for chainname when resno is present too\n\n const sele: SelectionRule = {\n operator: 'AND',\n rules: []\n }\n\n const model = c.split('/')\n if (model.length > 1 && model[1]) {\n if (isNaN(parseInt(model[1]))) {\n throw new Error('model must be an integer')\n }\n sele.rules!.push({\n model: parseInt(model[1])\n })\n }\n\n const altloc = model[0].split('%')\n if (altloc.length > 1) {\n sele.rules!.push({\n altloc: altloc[1]\n })\n }\n\n const atomname = altloc[0].split('.')\n if (atomname.length > 1 && atomname[1]) {\n if (atomname[1].length > 4) {\n throw new Error('atomname must be one to four characters')\n }\n sele.rules!.push({\n atomname: atomname[1].substring(0, 4).toUpperCase()\n })\n }\n\n const chain = atomname[0].split(':')\n if (chain.length > 1 && chain[1]) {\n sele.rules!.push({\n chainname: chain[1]\n })\n }\n\n const inscode = chain[0].split('^')\n if (inscode.length > 1) {\n sele.rules!.push({\n inscode: inscode[1]\n })\n }\n\n if (inscode[0]) {\n let negate, negate2\n if (inscode[0][0] === '-') {\n inscode[0] = inscode[0].substr(1)\n negate = true\n }\n if (inscode[0].includes('--')) {\n inscode[0] = inscode[0].replace('--', '-')\n negate2 = true\n }\n let resi = inscode[0].split('-')\n if (resi.length === 1) {\n let resiSingle = parseInt(resi[0])\n if (isNaN(resiSingle)) {\n throw new Error('resi must be an integer')\n }\n if (negate) resiSingle *= -1\n sele.rules!.push({\n resno: resiSingle\n })\n } else if (resi.length === 2) {\n const resiRange = resi.map(x => parseInt(x))\n if (negate) resiRange[0] *= -1\n if (negate2) resiRange[1] *= -1\n sele.rules!.push({\n resno: [resiRange[0], resiRange[1]]\n })\n } else {\n throw new Error(\"resi range must contain one '-'\")\n }\n }\n\n // round up\n\n if (sele.rules!.length === 1) {\n pushRule(sele.rules![ 0 ])\n } else if (sele.rules!.length > 1) {\n pushRule(sele)\n } else {\n throw new Error('empty selection chunk')\n }\n }\n\n // cleanup\n\n if (\n retSelection.operator === undefined &&\n retSelection.rules!.length === 1 &&\n retSelection.rules![ 0 ].hasOwnProperty('operator')\n ) {\n retSelection = retSelection.rules![ 0 ]\n }\n\n return retSelection\n}\n\nexport {\n parseSele\n}\n","/**\n * @file Selection Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { Color } from 'three'\n\nimport { ColormakerRegistry } from '../globals'\nimport Selection from '../selection/selection'\nimport Colormaker, { ColormakerParameters } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport Structure from '../structure/structure'\n\nexport type SelectionSchemeData = [ string, string, ColormakerParameters|undefined ]\n\n/**\n * Color based on {@link Selection}\n */\nclass SelectionColormaker extends Colormaker {\n colormakerList: any[] = [] // TODO\n selectionList: Selection[] = []\n\n constructor (params: { structure: Structure, dataList: SelectionSchemeData[] } & Partial) {\n super(params)\n\n const dataList = params.dataList || []\n\n dataList.forEach((data: SelectionSchemeData) => {\n const [ scheme, sele, params = {} ] = data\n\n if (ColormakerRegistry.hasScheme(scheme)) {\n Object.assign(params, {\n scheme: scheme,\n structure: this.parameters.structure\n })\n } else {\n Object.assign(params, {\n scheme: 'uniform',\n value: new Color(scheme).getHex()\n })\n }\n\n this.colormakerList.push(ColormakerRegistry.getScheme(params as { scheme: string } & ColormakerParameters))\n this.selectionList.push(new Selection(sele))\n })\n }\n\n // NOT NEEDED @manageColor\n atomColor (a: AtomProxy) {\n for (let i = 0, n = this.selectionList.length; i < n; ++i) {\n const test = this.selectionList[ i ].test\n if (test && test(a)) {\n return this.colormakerList[ i ].atomColor(a)\n }\n }\n\n return 0xFFFFFF\n }\n}\n\nexport default SelectionColormaker\n","/**\n * @file Colormaker Registry\n * @author Alexander Rose \n * @private\n */\n\nimport { generateUUID } from '../math/math-utils'\nimport Colormaker, { ColormakerConstructor, ColormakerParameters } from './colormaker'\nimport SelectionColormaker, { SelectionSchemeData } from './selection-colormaker'\nimport Structure from '../structure/structure'\n\ntype ColormakerDefinitionFunction = ((this: Colormaker, param?: ColormakerParameters) => void)\n\nconst ColormakerScales = {\n '': '',\n\n // Sequential\n OrRd: '[S] Orange-Red',\n PuBu: '[S] Purple-Blue',\n BuPu: '[S] Blue-Purple',\n Oranges: '[S] Oranges',\n BuGn: '[S] Blue-Green',\n YlOrBr: '[S] Yellow-Orange-Brown',\n YlGn: '[S] Yellow-Green',\n Reds: '[S] Reds',\n RdPu: '[S] Red-Purple',\n Greens: '[S] Greens',\n YlGnBu: '[S] Yellow-Green-Blue',\n Purples: '[S] Purples',\n GnBu: '[S] Green-Blue',\n Greys: '[S] Greys',\n YlOrRd: '[S] Yellow-Orange-Red',\n PuRd: '[S] Purple-Red',\n Blues: '[S] Blues',\n PuBuGn: '[S] Purple-Blue-Green',\n\n // Diverging\n Viridis: '[D] Viridis',\n Spectral: '[D] Spectral',\n RdYlGn: '[D] Red-Yellow-Green',\n RdBu: '[D] Red-Blue',\n PiYG: '[D] Pink-Yellowgreen',\n PRGn: '[D] Purplered-Green',\n RdYlBu: '[D] Red-Yellow-Blue',\n BrBG: '[D] Brown-Bluegreen',\n RdGy: '[D] Red-Grey',\n PuOr: '[D] Purple-Orange',\n\n // Qualitative\n Set1: '[Q] Set1',\n Set2: '[Q] Set2',\n Set3: '[Q] Set3',\n Dark2: '[Q] Dark2',\n Paired: '[Q] Paired',\n Pastel1: '[Q] Pastel1',\n Pastel2: '[Q] Pastel2',\n Accent: '[Q] Accent',\n\n // Other\n rainbow: '[?] Rainbow',\n rwb: '[?] Red-White-Blue'\n}\n\nconst ColormakerModes = {\n '': '',\n\n rgb: 'Red Green Blue',\n hsv: 'Hue Saturation Value',\n hsl: 'Hue Saturation Lightness',\n hsi: 'Hue Saturation Intensity',\n lab: 'CIE L*a*b*',\n hcl: 'Hue Chroma Lightness'\n}\n\n/**\n * Class for registering {@link Colormaker}s. Generally use the\n * global {@link src/globals.js~ColormakerRegistry} instance.\n */\nclass ColormakerRegistry {\n schemes: { [k: string]: ColormakerConstructor }\n userSchemes: { [k: string]: ColormakerConstructor }\n\n constructor () {\n this.schemes = {}\n this.userSchemes = {}\n }\n\n getScheme (params: Partial<{ scheme: string } & ColormakerParameters>) {\n const p = params || {}\n const id = (p.scheme || '').toLowerCase()\n\n let SchemeClass: ColormakerConstructor\n\n if (id in this.schemes) {\n SchemeClass = this.schemes[ id ]\n } else if (id in this.userSchemes) {\n SchemeClass = this.userSchemes[ id ]\n } else {\n //@ts-expect-error abstract class used as a constructor\n SchemeClass = Colormaker\n }\n\n return new SchemeClass(params)\n }\n\n /**\n * Get an description of available schemes as an\n * object with id-label as key-value pairs\n * @return {Object} available schemes\n */\n getSchemes () {\n const types: { [k: string]: string } = {}\n\n Object.keys(this.schemes).forEach(function (k) {\n types[ k ] = k\n })\n\n Object.keys(this.userSchemes).forEach(function (k) {\n types[ k ] = k.split('|')[ 1 ]\n })\n\n return types\n }\n\n /**\n * Get an description of available scales as an\n * object with id-label as key-value pairs\n * @return {Object} available scales\n */\n getScales () {\n return ColormakerScales\n }\n\n getModes () {\n return ColormakerModes\n }\n\n /**\n * Add a scheme with a hardcoded id\n * @param {String} id - the id\n * @param {Colormaker} scheme - the colormaker\n * @return {undefined}\n */\n add (id: string, scheme: ColormakerConstructor) {\n id = id.toLowerCase()\n this.schemes[ id ] = scheme\n }\n\n /**\n * Register a custom scheme\n *\n * @example\n * // Create a class with a `atomColor` method that returns a hex color.\n * var schemeId = NGL.ColormakerRegistry.addScheme( function( params ){\n * this.atomColor = function( atom ){\n * if( atom.serial < 1000 ){\n * return 0x0000FF; // blue\n * }else if( atom.serial > 2000 ){\n * return 0xFF0000; // red\n * }else{\n * return 0x00FF00; // green\n * }\n * };\n * } );\n *\n * stage.loadFile( \"rcsb://3dqb.pdb\" ).then( function( o ){\n * o.addRepresentation( \"cartoon\", { color: schemeId } ); // pass schemeId here\n * o.autoView();\n * } );\n *\n * @param {Function|Colormaker} scheme - constructor or {@link Colormaker} instance\n * @param {String} label - scheme label\n * @return {String} id to refer to the registered scheme\n */\n addScheme (scheme: ColormakerConstructor|ColormakerDefinitionFunction, label?: string) {\n if (!(isColormakerSubClass(scheme))) {\n scheme = this._createScheme(scheme)\n }\n\n return this._addUserScheme(scheme, label)\n }\n\n /**\n * Add a user-defined scheme\n * @param {Colormaker} scheme - the user-defined scheme\n * @param {String} [label] - scheme label\n * @return {String} id to refer to the registered scheme\n */\n _addUserScheme (scheme: ColormakerConstructor, label?: string) {\n label = label || ''\n const id = `${generateUUID()}|${label}`.toLowerCase()\n this.userSchemes[ id ] = scheme\n\n return id\n }\n\n /**\n * Remove the scheme with the given id\n * @param {String} id - scheme to remove\n * @return {undefined}\n */\n removeScheme (id: string) {\n id = id.toLowerCase()\n delete this.userSchemes[ id ]\n }\n\n _createScheme (constructor: ColormakerDefinitionFunction): ColormakerConstructor {\n class _Colormaker extends Colormaker {\n constructor (params: ColormakerParameters) {\n super(params)\n constructor.call(this, params)\n }\n }\n return _Colormaker\n }\n\n /**\n * Create and a selection-based coloring scheme. Supply a list with pairs\n * of colorname and selection for coloring by selections. Use the last\n * entry as a default (catch all) coloring definition.\n *\n * @example\n * var schemeId = NGL.ColormakerRegistry.addSelectionScheme( [\n * [ \"red\", \"64-74 or 134-154 or 222-254 or 310-310 or 322-326\" ],\n * [ \"green\", \"311-322\" ],\n * [ \"yellow\", \"40-63 or 75-95 or 112-133 or 155-173 or 202-221 or 255-277 or 289-309\" ],\n * [ \"blue\", \"1-39 or 96-112 or 174-201 or 278-288\" ],\n * [ \"white\", \"*\" ]\n * ], \"Transmembrane 3dqb\" );\n *\n * stage.loadFile( \"rcsb://3dqb.pdb\" ).then( function( o ){\n * o.addRepresentation( \"cartoon\", { color: schemeId } ); // pass schemeId here\n * o.autoView();\n * } );\n *\n * @param {Array} dataList - cloror-selection pairs\n * @param {String} label - scheme name\n * @return {String} id to refer to the registered scheme\n */\n addSelectionScheme (dataList: SelectionSchemeData[], label?: string) {\n class MySelectionColormaker extends SelectionColormaker {\n constructor (params: { structure: Structure } & ColormakerParameters) {\n super(Object.assign({ dataList }, params))\n }\n }\n\n return this._addUserScheme(MySelectionColormaker, label)\n }\n\n /**\n * Check if a scheme with the given id exists\n * @param {String} id - the id to check\n * @return {Boolean} flag indicating if the scheme exists\n */\n hasScheme (id: string) {\n id = id.toLowerCase()\n return id in this.schemes || id in this.userSchemes\n }\n}\n\nfunction isColormakerSubClass (\n scheme: ColormakerConstructor|((this: Colormaker, param?: ColormakerParameters) => void)\n): scheme is ColormakerConstructor {\n return (scheme instanceof Colormaker)\n}\n\nexport default ColormakerRegistry\n","/**\n * @file Worker Utils\n * @author Alexander Rose \n * @private\n */\n\nimport { uniqueArray } from '../utils'\n\nexport type FunctionWithDeps = { __deps?: Function[] } & Function\nexport interface WorkerEvent {\n data: {\n __name: string\n __postId: string\n }\n}\n\nfunction getWorkerDeps (vars: FunctionWithDeps[]) {\n const deps = vars\n vars.forEach(function (sym) {\n if (sym.__deps) {\n Array.prototype.push.apply(deps, getWorkerDeps(sym.__deps))\n }\n })\n return deps\n}\n\nfunction makeWorkerString (vars: any) {\n const deps = uniqueArray(getWorkerDeps(vars))\n return deps.map(function (sym) {\n return sym.toString()\n }).join('\\n\\n\\n')\n}\n\nfunction onmessage (e: WorkerEvent) {\n const name = e.data.__name\n const postId = e.data.__postId\n\n /* global self */\n if (name === undefined) {\n console.error('message __name undefined')\n } else if ((self as any).func === undefined) {\n console.error('worker func undefined', name)\n } else {\n const callback = function (aMessage: any, transferList: any[]) {\n aMessage = aMessage || {}\n if (postId !== undefined) aMessage.__postId = postId\n\n try {\n (self as any).postMessage(aMessage, transferList)\n } catch (error) {\n console.error('self.postMessage:', error);\n (self as any).postMessage(aMessage)\n }\n };\n (self as any).func(e, callback)\n }\n}\n\nexport function makeWorkerBlob (func: Function, deps: Function[]) {\n let str = \"'use strict';\\n\\n\" + makeWorkerString(deps)\n str += '\\n\\n\\nself.func = ' + func.toString() + ';'\n str += '\\n\\n\\nself.onmessage = ' + onmessage.toString() + ';'\n // console.log(str);\n return new Blob([ str ], { type: 'application/javascript' })\n}\n","/**\n * @file Globals\n * @author Alexander Rose \n * @private\n */\n\nimport { getBrowser, getQuery, boolean } from './utils'\nimport Registry from './utils/registry'\nimport _ColormakerRegistry from './color/colormaker-registry'\nimport _ParserRegistry from './parser/parser-registry'\nimport _WorkerRegistry from './worker/worker-registry'\nimport { MeasurementRepresentationParameters } from './representation/measurement-representation';\n\n/**\n * The browser name: \"Opera\", \"Chrome\", \"Firefox\", \"Mobile Safari\",\n * \"Internet Explorer\", \"Safari\" or false.\n */\nexport const Browser = getBrowser()\n\n/**\n * Flag indicating support for the 'passive' option for event handler\n */\nexport let SupportsPassiveEventHandler = false\ntry {\n // Test via a getter in the options object to see if the passive property is accessed\n const opts = Object.defineProperty({}, 'passive', {\n get: function () {\n SupportsPassiveEventHandler = true\n }\n })\n window.addEventListener('test', e => {}, opts)\n} catch (e) {}\n\n/**\n * Flag indicating a mobile browser\n */\nexport const Mobile = typeof window !== 'undefined' ? typeof window.orientation !== 'undefined' : false\n\nexport let SupportsReadPixelsFloat = false\nexport function setSupportsReadPixelsFloat (value: boolean) {\n SupportsReadPixelsFloat = value\n}\n\n/**\n * Flag indicating support for the `EXT_frag_depth` WebGL extension\n * (Always present in WebGL2)\n */\nexport let ExtensionFragDepth = false\nexport function setExtensionFragDepth (value: boolean) {\n ExtensionFragDepth = value\n}\n\nexport const Log = {\n log: Function.prototype.bind.call(console.log, console),\n info: Function.prototype.bind.call(console.info, console),\n warn: Function.prototype.bind.call(console.warn, console),\n error: Function.prototype.bind.call(console.error, console),\n time: Function.prototype.bind.call(console.time, console),\n timeEnd: Function.prototype.bind.call(console.timeEnd, console)\n}\n\nexport let MeasurementDefaultParams: Partial = {\n color: 'green',\n labelColor: 0x808080,\n labelAttachment: 'bottom-center',\n labelSize: 0.7,\n labelZOffset: 0.5,\n labelYOffset: 0.1,\n labelBorder: true,\n labelBorderColor: 0xd3d3d3,\n labelBorderWidth: 0.25,\n lineOpacity: 0.8,\n linewidth: 5.0,\n opacity: 0.6,\n\n labelUnit: 'angstrom',\n arcVisible: true,\n planeVisible: false\n}\nexport function setMeasurementDefaultParams (params = {}) {\n Object.assign(MeasurementDefaultParams, params)\n}\n\nexport let Debug = boolean(getQuery('debug'))\nexport function setDebug (value: boolean) {\n Debug = value\n}\n\nexport const WebglErrorMessage = '

Your browser/graphics card does not seem to support WebGL.

Find out how to get it here.

'\n\n/**\n * List of file extensions to be recognized as scripts\n */\nexport const ScriptExtensions = [ 'ngl', 'js' ]\n\nexport const WorkerRegistry = new _WorkerRegistry()\nexport const ColormakerRegistry = new _ColormakerRegistry()\nexport const DatasourceRegistry = new Registry('datasource')\nexport const RepresentationRegistry = new Registry('representatation')\nexport const ParserRegistry = new _ParserRegistry()\nexport const ShaderRegistry = new Registry('shader')\nexport const DecompressorRegistry = new Registry('decompressor')\nexport const ComponentRegistry = new Registry('component')\nexport const BufferRegistry = new Registry('buffer')\nexport const PickerRegistry = new Registry('picker')\n\nexport let ListingDatasource: any\nexport function setListingDatasource (value: any) {\n ListingDatasource = value\n}\n\nexport let TrajectoryDatasource: any // TODO should accept mdsrvDatasource\nexport function setTrajectoryDatasource (value: any) {\n TrajectoryDatasource = value\n}\n","/**\n * @file Worker Registry\n * @author Alexander Rose \n * @private\n */\n\nimport { makeWorkerBlob } from './worker-utils'\n\nclass WorkerRegistry {\n activeWorkerCount = 0\n\n private _funcDict: { [k: string]: Function } = {}\n private _depsDict: { [k: string]: Function[] } = {}\n private _blobDict: { [k: string]: Blob } = {}\n\n add (name: string, func: Function, deps: Function[]) {\n this._funcDict[ name ] = func\n this._depsDict[ name ] = deps\n }\n\n get (name: string) {\n if (!this._blobDict[ name ]) {\n this._blobDict[ name ] = makeWorkerBlob(\n this._funcDict[ name ], this._depsDict[ name ]\n )\n }\n return this._blobDict[ name ]\n }\n}\n\nexport default WorkerRegistry\n","/**\n * @file Parser Registry\n * @author Alexander Rose \n * @private\n */\n\nimport Registry from '../utils/registry'\n\nclass ParserRegistry extends Registry {\n constructor () {\n super('parser')\n }\n\n __hasObjName (key: string, objName: string) {\n const parser = this.get(key)\n return parser && parser.prototype.__objName === objName\n }\n\n isTrajectory (key: string) {\n return this.__hasObjName(key, 'frames')\n }\n\n isStructure (key: string) {\n return this.__hasObjName(key, 'structure')\n }\n\n isVolume (key: string) {\n return this.__hasObjName(key, 'volume')\n }\n\n isSurface (key: string) {\n return this.__hasObjName(key, 'surface')\n }\n\n isBinary (key: string) {\n const parser = this.get(key)\n return parser && parser.prototype.isBinary\n }\n\n isXml (key: string) {\n const parser = this.get(key)\n return parser && parser.prototype.isXml\n }\n\n isJson (key: string) {\n const parser = this.get(key)\n return parser && parser.prototype.isJson\n }\n\n getTrajectoryExtensions () {\n return this.names.filter(name => this.isTrajectory(name))\n }\n\n getStructureExtensions () {\n return this.names.filter(name => this.isStructure(name))\n }\n\n getVolumeExtensions () {\n return this.names.filter(name => this.isVolume(name))\n }\n\n getSurfaceExtensions () {\n return this.names.filter(name => this.isSurface(name))\n }\n}\n\nexport default ParserRegistry\n","/**\n * @file Streamer\n * @author Alexander Rose \n * @private\n */\n\nimport { DecompressorRegistry } from '../globals'\nimport { uint8ToString, defaults } from '../utils'\n\nexport interface StreamerParams {\n compressed?: string|false\n binary?: boolean\n json?: boolean\n xml?: boolean\n}\n\nabstract class Streamer {\n src: any\n data: any\n\n compressed: string|false\n binary: boolean\n json: boolean\n xml: boolean\n\n chunkSize = 1024 * 1024 * 10\n newline = '\\n'\n\n protected __pointer = 0\n protected __partialLine = ''\n\n constructor (src: any, params: StreamerParams = {}) {\n this.compressed = defaults(params.compressed, false)\n this.binary = defaults(params.binary, false)\n this.json = defaults(params.json, false)\n this.xml = defaults(params.xml, false)\n\n this.src = src\n }\n\n isBinary () {\n return this.binary || this.compressed\n }\n\n read () {\n return this._read().then(data => {\n const decompressFn = this.compressed ? DecompressorRegistry.get(this.compressed) : undefined\n\n if (this.compressed && decompressFn) {\n this.data = decompressFn(data)\n } else {\n if ((this.binary || this.compressed) && data instanceof ArrayBuffer) {\n data = new Uint8Array(data)\n }\n this.data = data\n }\n\n return this.data\n })\n }\n\n protected abstract _read (): Promise\n\n protected _chunk (start: number, end: number) {\n end = Math.min(this.data.length, end)\n\n if (start === 0 && this.data.length === end) {\n return this.data\n } else {\n if (this.isBinary()) {\n return this.data.subarray(start, end)\n } else {\n return this.data.substring(start, end)\n }\n }\n }\n\n chunk (start: number) {\n const end = start + this.chunkSize\n\n return this._chunk(start, end)\n }\n\n peekLines (m: number) {\n const data = this.data\n const n = data.length\n\n // FIXME does not work for multi-char newline\n const newline = this.isBinary() ? this.newline.charCodeAt(0) : this.newline\n\n let i\n let count = 0\n for (i = 0; i < n; ++i) {\n if (data[ i ] === newline) ++count\n if (count === m) break\n }\n\n const chunk = this._chunk(0, i + 1)\n const d = this.chunkToLines(chunk, '', i > n)\n\n return d.lines\n }\n\n chunkCount () {\n return Math.floor(this.data.length / this.chunkSize) + 1\n }\n\n asText () {\n return this.isBinary() ? uint8ToString(this.data) : this.data\n }\n\n chunkToLines (chunk: string|Uint8Array, partialLine: string, isLast: boolean) {\n const newline = this.newline\n\n if (!this.isBinary() && chunk.length === this.data.length) {\n return {\n lines: (chunk as string).split(newline),\n partialLine: ''\n }\n }\n\n let lines: string[] = []\n const str = this.isBinary() ? uint8ToString(chunk as Uint8Array) : chunk\n const idx = str.lastIndexOf(newline)\n\n if (idx === -1) {\n partialLine += str\n } else {\n const str2 = partialLine + str.substr(0, idx)\n lines = lines.concat(str2.split(newline))\n\n if (idx === str.length - newline.length) {\n partialLine = ''\n } else {\n partialLine = str.substr(idx + newline.length)\n }\n }\n\n if (isLast && partialLine !== '') {\n lines.push(partialLine)\n }\n\n return {\n lines: lines,\n partialLine: partialLine\n }\n }\n\n nextChunk () {\n const start = this.__pointer\n\n if (start > this.data.length) {\n return undefined\n }\n\n this.__pointer += this.chunkSize\n return this.chunk(start)\n }\n\n nextChunkOfLines () {\n const chunk = this.nextChunk()\n\n if (chunk === undefined) {\n return undefined\n }\n\n const isLast = this.__pointer > this.data.length\n const d = this.chunkToLines(chunk, this.__partialLine, isLast)\n\n this.__partialLine = d.partialLine\n\n return d.lines\n }\n\n eachChunk (callback: (chunk: string|Uint8Array, chunkNo: number, chunkCount: number) => void) {\n const chunkSize = this.chunkSize\n const n = this.data.length\n const chunkCount = this.chunkCount()\n\n for (let i = 0; i < n; i += chunkSize) {\n const chunk = this.chunk(i)\n const chunkNo = Math.round(i / chunkSize)\n\n callback(chunk, chunkNo, chunkCount)\n }\n }\n\n eachChunkOfLines (callback: (chunk: string[], chunkNo: number, chunkCount: number) => void) {\n this.eachChunk((chunk, chunkNo, chunkCount) => {\n const isLast = chunkNo === chunkCount + 1\n const d = this.chunkToLines(chunk, this.__partialLine, isLast)\n\n this.__partialLine = d.partialLine\n\n callback(d.lines, chunkNo, chunkCount)\n })\n }\n\n dispose () {\n delete this.src\n }\n}\n\nexport default Streamer\n","/**\n * @file File Streamer\n * @author Alexander Rose \n * @private\n */\n\nimport Streamer from './streamer'\n\ninterface FileReaderEventTarget extends EventTarget {\n result:string | ArrayBuffer | null\n}\n\ninterface FileReaderEvent extends ProgressEvent {\n target: FileReaderEventTarget | null;\n}\n\nclass FileStreamer extends Streamer {\n _read () {\n return new Promise((resolve, reject) => {\n const file = this.src\n const reader = new FileReader()\n\n reader.onload = (event: FileReaderEvent) => {\n if(event.target) resolve(event.target.result)\n }\n\n // if (typeof this.onprogress === 'function') {\n // reader.onprogress = event => this.onprogress(event)\n // }\n\n reader.onerror = event => reject(event)\n\n if (this.binary || this.compressed) {\n reader.readAsArrayBuffer(file)\n } else {\n reader.readAsText(file)\n }\n })\n }\n}\n\nexport default FileStreamer\n","/**\n * @file Network Streamer\n * @author Alexander Rose \n * @private\n */\n\nimport Streamer from './streamer'\n\nclass NetworkStreamer extends Streamer {\n _read () {\n return new Promise((resolve, reject) => {\n const url = this.src\n const xhr = new XMLHttpRequest()\n\n xhr.open('GET', url, true)\n\n xhr.addEventListener('load', () => {\n if (xhr.status === 200 || xhr.status === 304 ||\n // when requesting from local file system\n // the status in Google Chrome/Chromium is 0\n xhr.status === 0\n ) {\n try {\n resolve(xhr.response)\n } catch (e) {\n reject(e)\n }\n } else {\n reject(xhr.statusText)\n }\n }, false)\n\n // if (typeof this.onprogress === 'function') {\n // xhr.addEventListener('progress', event => this.onprogress(event), false);\n // }\n\n xhr.addEventListener('error', event => reject('network error'), false)\n\n if (this.isBinary()) {\n xhr.responseType = 'arraybuffer'\n } else if (this.json) {\n xhr.responseType = 'json'\n } else if (this.xml) {\n xhr.responseType = 'document'\n } else {\n xhr.responseType = 'text'\n }\n // xhr.crossOrigin = true;\n\n xhr.send()\n })\n }\n}\n\nexport default NetworkStreamer\n","/**\n * @file Loader\n * @author Alexander Rose \n * @private\n */\n\nimport { ParserRegistry } from '../globals'\nimport { createParams } from '../utils'\nimport FileStreamer from '../streamer/file-streamer'\nimport NetworkStreamer from '../streamer/network-streamer'\nimport { LoaderParameters, LoaderInput } from './loader-utils'\n\n/**\n * Loader parameter object.\n * @typedef {Object} LoaderParameters - loader parameters\n * @property {String} ext - file extension, determines file type\n * @property {Boolean} compressed - flag data as compressed\n * @property {Boolean} binary - flag data as binary\n * @property {String} name - set data name\n */\n\n/**\n * Loader base class\n */\nabstract class Loader {\n parameters: LoaderParameters\n streamer: FileStreamer | NetworkStreamer\n\n /**\n * Construct a loader object\n * @param {String|File|Blob} src - data source, string is interpreted as an URL\n * @param {LoaderParameters} params - parameters object\n */\n constructor (src: LoaderInput, params: Partial = {}) {\n this.parameters = createParams(params, {\n ext: '',\n compressed: false,\n binary: ParserRegistry.isBinary(params.ext || ''),\n name: '',\n\n dir: '',\n path: '',\n protocol: ''\n } as LoaderParameters)\n\n const streamerParams = {\n compressed: this.parameters.compressed as string|false,\n binary: this.parameters.binary,\n json: ParserRegistry.isJson(this.parameters.ext),\n xml: ParserRegistry.isXml(this.parameters.ext)\n }\n\n if ((typeof File !== 'undefined' && src instanceof File) ||\n (typeof Blob !== 'undefined' && src instanceof Blob)\n ) {\n this.streamer = new FileStreamer(src, streamerParams)\n } else {\n this.streamer = new NetworkStreamer(src, streamerParams)\n }\n }\n\n /**\n * Load data\n * @abstract\n * @return {Promise} resolves to the loaded data {@link Object}\n */\n abstract load (): Promise\n}\n\nexport default Loader\n","/**\n * @file Parser Loader\n * @author Alexander Rose \n * @private\n */\n\nimport { ParserRegistry } from '../globals'\nimport type { InferBondsOptions } from '../structure/structure-utils'\nimport Loader from './loader'\nimport { LoaderParameters, LoaderInput } from './loader-utils'\n\nexport interface ParserParams {\n voxelSize?: number\n firstModelOnly?: boolean\n asTrajectory?: boolean\n cAlphaOnly?: boolean\n name?: string\n path?: string\n delimiter?: string\n comment?: string\n columnNames?: string\n inferBonds?: InferBondsOptions\n}\n\n/**\n * Parser loader class\n * @extends Loader\n */\nclass ParserLoader extends Loader {\n parserParams: ParserParams\n\n constructor (src: LoaderInput, params: Partial & ParserParams = {}) {\n super(src, params)\n this.parserParams = {\n voxelSize: params.voxelSize,\n firstModelOnly: params.firstModelOnly,\n asTrajectory: params.asTrajectory,\n cAlphaOnly: params.cAlphaOnly,\n delimiter: params.delimiter,\n comment: params.comment,\n columnNames: params.columnNames,\n inferBonds: params.inferBonds,\n name: this.parameters.name,\n path: this.parameters.path\n }\n }\n\n /**\n * Load parsed object\n * @return {Promise} resolves to the loaded & parsed {@link Structure},\n * {@link Volume}, {@link Surface} or data object\n */\n load () {\n var ParserClass = ParserRegistry.get(this.parameters.ext)\n var parser = new ParserClass(this.streamer, this.parserParams)\n\n return parser.parse()\n }\n}\n\nexport default ParserLoader\n","/**\n * @file Script\n * @author Alexander Rose \n * @private\n */\n\nimport { Signal } from 'signals'\n\nimport { Log } from './globals'\nimport Stage from './stage/stage'\n\nexport interface ScriptSignals {\n elementAdded: Signal\n elementRemoved: Signal\n nameChanged: Signal\n}\n\n/**\n * Script class\n */\nclass Script {\n readonly signals: ScriptSignals = {\n elementAdded: new Signal(),\n elementRemoved: new Signal(),\n nameChanged: new Signal()\n }\n\n readonly dir: string\n readonly fn: Function\n\n readonly type = 'Script'\n\n /**\n * Create a script instance\n * @param {String} functionBody - the function source\n * @param {String} name - name of the script\n * @param {String} path - path of the script\n */\n constructor (functionBody: string, readonly name: string, readonly path: string) {\n this.dir = path.substring(0, path.lastIndexOf('/') + 1)\n\n try {\n /* eslint-disable no-new-func */\n this.fn = new Function('stage', '__name', '__path', '__dir', functionBody)\n } catch (e) {\n Log.error('Script compilation failed', e)\n this.fn = function () {}\n }\n }\n\n /**\n * Execute the script\n * @param {Stage} stage - the stage context\n * @return {Promise} - resolve when script finished running\n */\n run (stage: Stage): Promise {\n return new Promise((resolve, reject) => {\n try {\n this.fn.apply(null, [ stage, this.name, this.path, this.dir ])\n resolve()\n } catch (e) {\n Log.error('Script.fn', e)\n reject(e)\n }\n })\n }\n}\n\nexport default Script\n","/**\n * @file Script Loader\n * @author Alexander Rose \n * @private\n */\n\nimport Loader from './loader'\nimport Script from '../script'\n\n/**\n * Script loader class\n * @extends Loader\n */\nclass ScriptLoader extends Loader {\n /**\n * Load script\n * @return {Promise} resolves to the loaded {@link Script}\n */\n load () {\n return this.streamer.read().then(() => {\n return new Script(\n this.streamer.asText(), this.parameters.name, this.parameters.path\n )\n })\n }\n}\n\nexport default ScriptLoader\n","/**\n * @file Loader Utils\n * @author Alexander Rose \n * @private\n */\n\nimport {\n DatasourceRegistry, DecompressorRegistry, ParserRegistry, ScriptExtensions\n} from '../globals'\nimport ParserLoader, { ParserParams } from './parser-loader'\nimport ScriptLoader from './script-loader'\n\nexport interface LoaderParameters {\n ext: string // file extension, determines file type\n compressed: string|false // flag data as compressed\n binary: boolean // flag data as binary\n name: string // set data name\n\n dir: string\n path: string\n protocol: string\n}\n\nexport type LoaderInput = File|Blob|string\n\nexport function getFileInfo (file: LoaderInput) {\n const compressedExtList = DecompressorRegistry.names\n\n let path: string\n let compressed: string|false\n let protocol = ''\n\n if (file instanceof File) {\n path = file.name\n } else if (file instanceof Blob) {\n path = ''\n } else {\n path = file\n }\n const queryIndex = path.lastIndexOf('?')\n const query = queryIndex !== -1 ? path.substring(queryIndex) : ''\n path = path.substring(0, queryIndex === -1 ? path.length : queryIndex)\n\n const name = path.replace(/^.*[\\\\/]/, '')\n let base = name.substring(0, name.lastIndexOf('.'))\n\n const nameSplit = name.split('.')\n let ext = nameSplit.length > 1 ? (nameSplit.pop() || '').toLowerCase() : ''\n\n const protocolMatch = path.match(/^(.+):\\/\\/(.+)$/)\n if (protocolMatch) {\n protocol = protocolMatch[ 1 ].toLowerCase()\n path = protocolMatch[ 2 ] || ''\n }\n\n const dir = path.substring(0, path.lastIndexOf('/') + 1)\n\n if (compressedExtList.includes(ext)) {\n compressed = ext\n const n = path.length - ext.length - 1\n ext = (path.substr(0, n).split('.').pop() || '').toLowerCase()\n const m = base.length - ext.length - 1\n base = base.substr(0, m)\n } else {\n compressed = false\n }\n\n return { path, name, ext, base, dir, compressed, protocol, query, 'src': file }\n}\n\nexport function getDataInfo (src: LoaderInput) {\n let info = getFileInfo(src)\n const datasource = DatasourceRegistry.get(info.protocol)\n if (datasource) {\n info = getFileInfo(datasource.getUrl(info.src))\n if (!info.ext && datasource.getExt) {\n info.ext = datasource.getExt(src)\n }\n }\n return info\n}\n\n/**\n * Load a file\n *\n * @example\n * // load from URL\n * NGL.autoLoad( \"http://files.rcsb.org/download/5IOS.cif\" );\n *\n * @example\n * // load binary data in CCP4 format via a Blob\n * var binaryBlob = new Blob( [ ccp4Data ], { type: 'application/octet-binary'} );\n * NGL.autoLoad( binaryBlob, { ext: \"ccp4\" } );\n *\n * @example\n * // load string data in PDB format via a Blob\n * var stringBlob = new Blob( [ pdbData ], { type: 'text/plain'} );\n * NGL.autoLoad( stringBlob, { ext: \"pdb\" } );\n *\n * @example\n * // load a File object\n * NGL.autoLoad( file );\n *\n * @param {String|File|Blob} file - either a URL or an object containing the file data\n * @param {LoaderParameters} params - loading parameters\n * @return {Promise} Promise resolves to the loaded data\n */\nexport function autoLoad (file: LoaderInput, params: Partial = {}) {\n const p = Object.assign(getDataInfo(file), params)\n\n let loader\n if (ParserRegistry.names.includes(p.ext)) {\n loader = new ParserLoader(p.src, p)\n } else if (ScriptExtensions.includes(p.ext)) {\n loader = new ScriptLoader(p.src, p)\n }\n\n if (loader) {\n return loader.load()\n } else {\n return Promise.reject(new Error(`autoLoad: ext '${p.ext}' unknown`))\n }\n}\n","/**\n * @file Writer\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults, download } from '../utils'\n\n/**\n * Base class for writers\n * @interface\n */\nabstract class Writer {\n readonly mimeType: string\n readonly defaultName: string\n readonly defaultExt: string\n\n /**\n * @abstract\n * @return {Anything} the data to be written\n */\n abstract getData (): any\n\n /**\n * Get a blob with the written data\n * @return {Blob} the blob\n */\n getBlob () {\n return new Blob([ this.getData() ], { type: this.mimeType })\n }\n\n /**\n * Trigger a download of the\n * @param {[type]} name [description]\n * @param {[type]} ext [description]\n * @return {[type]} [description]\n */\n download (name?: string, ext?: string) {\n name = defaults(name, this.defaultName)\n ext = defaults(ext, this.defaultExt)\n\n download(this.getBlob(), `${name}.${ext}`)\n }\n}\n\nexport default Writer","/**\n * @file Pdb Writer\n * @author Alexander Rose \n * @private\n */\n\nimport { sprintf } from 'sprintf-js'\n\nimport Writer from './writer'\nimport { defaults, ensureArray } from '../utils'\nimport Structure from '../structure/structure'\nimport AtomProxy from '../proxy/atom-proxy'\n\n// http://www.wwpdb.org/documentation/file-format\n\n// Sample PDB line, the coords X,Y,Z are fields 5,6,7 on each line.\n// ATOM 1 N ARG 1 29.292 13.212 -12.751 1.00 33.78 1BPT 108\n\nconst AtomFormat =\n 'ATOM %5d %-4s %3s %1s%4d %8.3f%8.3f%8.3f%6.2f%6.2f %4s%2s%1s%1s'\n\nconst HetatmFormat =\n 'HETATM%5d %-4s %3s %1s%4d %8.3f%8.3f%8.3f%6.2f%6.2f %4s%2s%1s%1s'\n\nexport interface PdbWriterParams {\n renumberSerial: boolean\n remarks: string[]\n}\n\n/**\n * Create a PDB file from a Structure object\n */\nexport default class PdbWriter extends Writer {\n readonly mimeType = 'text/plain'\n readonly defaultName = 'structure'\n readonly defaultExt = 'pdb'\n\n renumberSerial: boolean\n remarks: string[]\n\n structure: Structure\n private _records: string[]\n\n /**\n * @param {Structure} structure - the structure object\n * @param {Object} params - parameters]\n */\n constructor (structure: Structure, params?: PdbWriterParams) {\n super()\n\n const p = Object.assign({}, params)\n\n this.renumberSerial = defaults(p.renumberSerial, true)\n this.remarks = ensureArray(defaults(p.remarks, []))\n\n this.structure = structure\n this._records = []\n }\n\n private _writeRecords () {\n this._records.length = 0\n\n this._writeTitle()\n this._writeRemarks()\n this._writeAtoms()\n }\n\n private _writeTitle () {\n // FIXME multiline if title line longer than 80 chars\n this._records.push(sprintf('TITLE %-74s', this.structure.name))\n }\n\n private _writeRemarks () {\n this.remarks.forEach(str => {\n this._records.push(sprintf('REMARK %-73s', str))\n })\n\n if (this.structure.trajectory) {\n this._records.push(sprintf(\n 'REMARK %-73s',\n \"Trajectory '\" + this.structure.trajectory.name + \"'\"\n ))\n this._records.push(sprintf(\n 'REMARK %-73s',\n `Frame ${(this.structure.trajectory as any).frame}` // TODO\n ))\n }\n }\n\n private _writeAtoms () {\n let ia = 1\n let im = 1\n let charge = \" \"\n let chargeSign = \" \"\n const hasModels = this.structure.modelStore.count > 1\n\n this.structure.eachModel(m => {\n if (hasModels) this._records.push(sprintf('MODEL %4d%-66s', im++, ''))\n\n m.eachAtom((a: AtomProxy) => {\n const formatString = a.hetero ? HetatmFormat : AtomFormat\n const serial = this.renumberSerial ? ia : a.serial\n\n // Formal PDB spec\n // Alignment of one-letter atom name such as C starts at column 14,\n // while two-letter atom name such as FE starts at column 13.\n\n // This, however, leaves Calcium and C-alpha ambiguous\n // The convention (from earlier versions of the spec, see 1992, and also: \n // https://www.cgl.ucsf.edu/chimera/docs/UsersGuide/tutorials/pdbintro.html#misalignment)\n // is that element is right-justified in 13-14, modifiers are left justified in columns 15-16\n // A single-character element symmbol should not appear in column 13 unless the atom name has four characters\n let atomname = a.atomname\n\n if (atomname.length === 1) {\n // Simple case\n atomname = ' ' + atomname\n } else if (atomname.length < 4) {\n // 2 or 3-letter name, if element symbol is single char and matches name, add a space\n if (a.element.length === 1 && atomname[0] === a.element) {\n atomname = ' ' + atomname\n }\n }\n\n if (a.formalCharge) { // Skip nulls and zeros\n charge = Math.abs(a.formalCharge).toPrecision(1)\n chargeSign = (a.formalCharge > 0) ? \"+\" : \"-\"\n } else {\n charge = \" \"\n chargeSign = \" \"\n }\n\n this._records.push(sprintf(\n formatString,\n\n serial,\n atomname,\n a.resname,\n defaults(a.chainname, ' '),\n a.resno,\n a.x, a.y, a.z,\n defaults(a.occupancy, 1.0),\n defaults(a.bfactor, 0.0),\n '', // segid\n defaults(a.element, ''),\n charge,\n chargeSign\n ))\n ia += 1\n }, this.structure.getSelection())\n\n if (hasModels) this._records.push(sprintf('%-80s', 'ENDMDL'))\n })\n\n this._records.push(sprintf('%-80s', 'END'))\n }\n\n getString () {\n console.warn('PdbWriter.getString() is deprecated, use .getData instead')\n return this.getData()\n }\n\n /**\n * Get string containing the PDB file data\n * @return {String} PDB file\n */\n getData () {\n this._writeRecords()\n return this._records.join('\\n')\n }\n}\n","/**\n * Writer class for sdf/mol files.\n */\n\nimport { sprintf } from 'sprintf-js'\n\nimport Writer from './writer'\nimport Structure from '../structure/structure'\nimport AtomProxy from '../proxy/atom-proxy'\nimport BondProxy from '../proxy/bond-proxy'\n\n// Hard-coded chiral as false as we don't specify it any atoms\nconst CountFormat = '%3i%3i 0 0 0 0 0 0 0 0999 V2000'\nconst AtomLine = '%10.4f%10.4f%10.4f %-3s 0%3i 0 0 0'\nconst BondFormat = '%3i%3i%3i 0 0 0'\n\nclass SdfWriter extends Writer {\n readonly mimeType = 'text/plain'\n readonly defaultName = 'structure'\n readonly defaultExt = 'sdf'\n\n structure: Structure\n private _records: string[]\n\n /**\n * @param {Structure} structure - structure to write\n * @param {Object} params - parameters\n */\n constructor (structure: Structure) {\n super()\n\n this.structure = structure\n // Follow the pdb-writer example:\n this._records = []\n }\n\n get idString () {\n return this.structure.id\n }\n\n get titleString () {\n return ' ' + this.structure.title\n }\n\n get countsString () {\n return sprintf(\n CountFormat,\n this.structure.atomCount,\n this.structure.bondCount\n )\n }\n\n get chargeLines () {\n const pairs: [number, number][] = []\n this.structure.eachAtom(ap => {\n if (ap.formalCharge != null && ap.formalCharge !== 0) {\n pairs.push([ap.index, ap.formalCharge])\n }\n })\n const lines = []\n for (let i = 0; i < pairs.length; i += 8) {\n const nCharges = Math.min(8, pairs.length - i)\n let s = sprintf('M CHG%3i', nCharges)\n for (let j = i; j < i + nCharges; j++) {\n s += sprintf(' %3i %3i', pairs[j][0] + 1, pairs[j][1])\n }\n lines.push(s)\n }\n return lines\n }\n\n formatAtom (ap: AtomProxy) {\n let charge = 0\n if (ap.formalCharge != null && ap.formalCharge !== 0) {\n charge = 4 - ap.formalCharge\n }\n const line = sprintf(\n AtomLine, ap.x, ap.y, ap.z, ap.element, charge\n )\n if (line.length !== 48) { throw new Error('Incompatible atom for sdf format') }\n\n return line\n }\n\n formatBond (bp: BondProxy) {\n return sprintf(\n BondFormat,\n bp.atomIndex1 + 1,\n bp.atomIndex2 + 1,\n bp.bondOrder)\n }\n\n _writeRecords () {\n this._records.length = 0\n this._writeHeader()\n this._writeCTab()\n this._writeFooter()\n }\n\n _writeHeader () {\n this._records.push(this.idString, this.titleString, '')\n }\n\n _writeCTab () {\n this._records.push(this.countsString)\n this.structure.eachAtom(ap => {\n this._records.push(this.formatAtom(ap))\n })\n this.structure.eachBond(bp => {\n this._records.push(this.formatBond(bp))\n })\n this.chargeLines.forEach(line => {\n this._records.push(line)\n })\n this._records.push('M END')\n }\n\n _writeFooter () {\n this._records.push('$$$$')\n }\n\n getData () {\n this._writeRecords()\n return this._records.join('\\n')\n }\n}\n\nexport default SdfWriter\n","/**\n * @file IO Buffer\n * @author Alexander Rose \n * @private\n *\n * Adapted and converted to TypeScript from https://github.com/image-js/iobuffer\n * MIT License, Copyright (c) 2015 Michaël Zasso\n */\n\nimport { TypedArray } from '../types'\n\nconst defaultByteLength = 1024 * 8\nconst charArray: string[] = []\n\nexport interface IOBufferParameters {\n offset?: number // Ignore the first n bytes of the ArrayBuffer\n}\n\n/**\n * Class for writing and reading binary data\n */\nclass IOBuffer {\n private _lastWrittenByte: number\n private _mark = 0\n private _marks: number[] = []\n private _data: DataView\n\n offset = 0 // The current offset of the buffer's pointer\n littleEndian = true\n buffer: ArrayBuffer // Reference to the internal ArrayBuffer object\n length: number // Byte length of the internal ArrayBuffer\n byteLength: number // Byte length of the internal ArrayBuffer\n byteOffset: number // Byte offset of the internal ArrayBuffer\n\n /**\n * If it's a number, it will initialize the buffer with the number as\n * the buffer's length. If it's undefined, it will initialize the buffer\n * with a default length of 8 Kb. If its an ArrayBuffer, a TypedArray,\n * it will create a view over the underlying ArrayBuffer.\n */\n constructor (data: number|ArrayBuffer|TypedArray, params: IOBufferParameters = {}) {\n let dataIsGiven = false\n if (data === undefined) {\n data = defaultByteLength\n }\n if (typeof data === 'number') {\n data = new ArrayBuffer(data)\n } else {\n dataIsGiven = true\n }\n\n const offset = params.offset ? params.offset >>> 0 : 0\n let byteLength = data.byteLength - offset\n let dvOffset = offset\n if (!(data instanceof ArrayBuffer)) {\n if (data.byteLength !== data.buffer.byteLength) {\n dvOffset = data.byteOffset + offset\n }\n data = data.buffer\n }\n if (dataIsGiven) {\n this._lastWrittenByte = byteLength\n } else {\n this._lastWrittenByte = 0\n }\n\n this.buffer = data\n this.length = byteLength\n this.byteLength = byteLength\n this.byteOffset = dvOffset\n\n this._data = new DataView(this.buffer, dvOffset, byteLength)\n }\n\n /**\n * Checks if the memory allocated to the buffer is sufficient to store more bytes after the offset\n * @param {number} [byteLength=1] The needed memory in bytes\n * @return {boolean} Returns true if there is sufficient space and false otherwise\n */\n available (byteLength: number) {\n if (byteLength === undefined) byteLength = 1\n return (this.offset + byteLength) <= this.length\n }\n\n /**\n * Check if little-endian mode is used for reading and writing multi-byte values\n * @return {boolean} Returns true if little-endian mode is used, false otherwise\n */\n isLittleEndian () {\n return this.littleEndian\n }\n\n /**\n * Set little-endian mode for reading and writing multi-byte values\n * @return {IOBuffer}\n */\n setLittleEndian () {\n this.littleEndian = true\n return this\n }\n\n /**\n * Check if big-endian mode is used for reading and writing multi-byte values\n * @return {boolean} Returns true if big-endian mode is used, false otherwise\n */\n isBigEndian () {\n return !this.littleEndian\n }\n\n /**\n * Switches to big-endian mode for reading and writing multi-byte values\n * @return {IOBuffer}\n */\n setBigEndian () {\n this.littleEndian = false\n return this\n }\n\n /**\n * Move the pointer n bytes forward\n * @param {number} n\n * @return {IOBuffer}\n */\n skip (n: number) {\n if (n === undefined) n = 1\n this.offset += n\n return this\n }\n\n /**\n * Move the pointer to the given offset\n * @param {number} offset\n * @return {IOBuffer}\n */\n seek (offset: number) {\n this.offset = offset\n return this\n }\n\n /**\n * Store the current pointer offset.\n * @see {@link IOBuffer#reset}\n * @return {IOBuffer}\n */\n mark () {\n this._mark = this.offset\n return this\n }\n\n /**\n * Move the pointer back to the last pointer offset set by mark\n * @see {@link IOBuffer#mark}\n * @return {IOBuffer}\n */\n reset () {\n this.offset = this._mark\n return this\n }\n\n /**\n * Push the current pointer offset to the mark stack\n * @see {@link IOBuffer#popMark}\n * @return {IOBuffer}\n */\n pushMark () {\n this._marks.push(this.offset)\n return this\n }\n\n /**\n * Pop the last pointer offset from the mark stack, and set the current pointer offset to the popped value\n * @see {@link IOBuffer#pushMark}\n * @return {IOBuffer}\n */\n popMark () {\n const offset = this._marks.pop()\n if (offset === undefined) throw new Error('Mark stack empty')\n this.seek(offset)\n return this\n }\n\n /**\n * Move the pointer offset back to 0\n * @return {IOBuffer}\n */\n rewind () {\n this.offset = 0\n return this\n }\n\n /**\n * Make sure the buffer has sufficient memory to write a given byteLength at the current pointer offset\n * If the buffer's memory is insufficient, this method will create a new buffer (a copy) with a length\n * that is twice (byteLength + current offset)\n * @param {number} [byteLength = 1]\n * @return {IOBuffer}\n */\n ensureAvailable (byteLength: number) {\n if (byteLength === undefined) byteLength = 1\n if (!this.available(byteLength)) {\n const lengthNeeded = this.offset + byteLength\n const newLength = lengthNeeded * 2\n const newArray = new Uint8Array(newLength)\n newArray.set(new Uint8Array(this.buffer))\n this.buffer = newArray.buffer\n this.length = this.byteLength = newLength\n this._data = new DataView(this.buffer)\n }\n return this\n }\n\n /**\n * Read a byte and return false if the byte's value is 0, or true otherwise\n * Moves pointer forward\n * @return {boolean}\n */\n readBoolean () {\n return this.readUint8() !== 0\n }\n\n /**\n * Read a signed 8-bit integer and move pointer forward\n * @return {number}\n */\n readInt8 () {\n return this._data.getInt8(this.offset++)\n }\n\n /**\n * Read an unsigned 8-bit integer and move pointer forward\n * @return {number}\n */\n readUint8 () {\n return this._data.getUint8(this.offset++)\n }\n\n /**\n * Alias for {@link IOBuffer#readUint8}\n * @return {number}\n */\n readByte () {\n return this.readUint8()\n }\n\n /**\n * Read n bytes and move pointer forward.\n * @param {number} n\n * @return {Uint8Array}\n */\n readBytes (n: number) {\n if (n === undefined) n = 1\n var bytes = new Uint8Array(n)\n for (var i = 0; i < n; i++) {\n bytes[i] = this.readByte()\n }\n return bytes\n }\n\n /**\n * Read a 16-bit signed integer and move pointer forward\n * @return {number}\n */\n readInt16 () {\n var value = this._data.getInt16(this.offset, this.littleEndian)\n this.offset += 2\n return value\n }\n\n /**\n * Read a 16-bit unsigned integer and move pointer forward\n * @return {number}\n */\n readUint16 () {\n var value = this._data.getUint16(this.offset, this.littleEndian)\n this.offset += 2\n return value\n }\n\n /**\n * Read a 32-bit signed integer and move pointer forward\n * @return {number}\n */\n readInt32 () {\n var value = this._data.getInt32(this.offset, this.littleEndian)\n this.offset += 4\n return value\n }\n\n /**\n * Read a 32-bit unsigned integer and move pointer forward\n * @return {number}\n */\n readUint32 () {\n var value = this._data.getUint32(this.offset, this.littleEndian)\n this.offset += 4\n return value\n }\n\n /**\n * Read a 32-bit floating number and move pointer forward\n * @return {number}\n */\n readFloat32 () {\n var value = this._data.getFloat32(this.offset, this.littleEndian)\n this.offset += 4\n return value\n }\n\n /**\n * Read a 64-bit floating number and move pointer forward\n * @return {number}\n */\n readFloat64 () {\n var value = this._data.getFloat64(this.offset, this.littleEndian)\n this.offset += 8\n return value\n }\n\n /**\n * Read 1-byte ascii character and move pointer forward\n * @return {string}\n */\n readChar () {\n return String.fromCharCode(this.readInt8())\n }\n\n /**\n * Read n 1-byte ascii characters and move pointer forward\n * @param {number} n\n * @return {string}\n */\n readChars (n = 1) {\n charArray.length = n\n for (var i = 0; i < n; i++) {\n charArray[i] = this.readChar()\n }\n return charArray.join('')\n }\n\n /**\n * Write 0xff if the passed value is truthy, 0x00 otherwise\n * @param {any} value\n * @return {IOBuffer}\n */\n writeBoolean (value = false) {\n this.writeUint8(value ? 0xff : 0x00)\n return this\n }\n\n /**\n * Write value as an 8-bit signed integer\n * @param {number} value\n * @return {IOBuffer}\n */\n writeInt8 (value: number) {\n this.ensureAvailable(1)\n this._data.setInt8(this.offset++, value)\n this._updateLastWrittenByte()\n return this\n }\n\n /**\n * Write value as a 8-bit unsigned integer\n * @param {number} value\n * @return {IOBuffer}\n */\n writeUint8 (value: number) {\n this.ensureAvailable(1)\n this._data.setUint8(this.offset++, value)\n this._updateLastWrittenByte()\n return this\n }\n\n /**\n * An alias for {@link IOBuffer#writeUint8}\n * @param {number} value\n * @return {IOBuffer}\n */\n writeByte (value: number) {\n return this.writeUint8(value)\n }\n\n /**\n * Write bytes\n * @param {Array|Uint8Array} bytes\n * @return {IOBuffer}\n */\n writeBytes (bytes: number[]|Uint8Array) {\n this.ensureAvailable(bytes.length)\n for (var i = 0; i < bytes.length; i++) {\n this._data.setUint8(this.offset++, bytes[i])\n }\n this._updateLastWrittenByte()\n return this\n }\n\n /**\n * Write value as an 16-bit signed integer\n * @param {number} value\n * @return {IOBuffer}\n */\n writeInt16 (value: number) {\n this.ensureAvailable(2)\n this._data.setInt16(this.offset, value, this.littleEndian)\n this.offset += 2\n this._updateLastWrittenByte()\n return this\n }\n\n /**\n * Write value as a 16-bit unsigned integer\n * @param {number} value\n * @return {IOBuffer}\n */\n writeUint16 (value: number) {\n this.ensureAvailable(2)\n this._data.setUint16(this.offset, value, this.littleEndian)\n this.offset += 2\n this._updateLastWrittenByte()\n return this\n }\n\n /**\n * Write a 32-bit signed integer at the current pointer offset\n * @param {number} value\n * @return {IOBuffer}\n */\n writeInt32 (value: number) {\n this.ensureAvailable(4)\n this._data.setInt32(this.offset, value, this.littleEndian)\n this.offset += 4\n this._updateLastWrittenByte()\n return this\n }\n\n /**\n * Write a 32-bit unsigned integer at the current pointer offset\n * @param {number} value - The value to set\n * @return {IOBuffer}\n */\n writeUint32 (value: number) {\n this.ensureAvailable(4)\n this._data.setUint32(this.offset, value, this.littleEndian)\n this.offset += 4\n this._updateLastWrittenByte()\n return this\n }\n\n /**\n * Write a 32-bit floating number at the current pointer offset\n * @param {number} value - The value to set\n * @return {IOBuffer}\n */\n writeFloat32 (value: number) {\n this.ensureAvailable(4)\n this._data.setFloat32(this.offset, value, this.littleEndian)\n this.offset += 4\n this._updateLastWrittenByte()\n return this\n }\n\n /**\n * Write a 64-bit floating number at the current pointer offset\n * @param {number} value\n * @return {IOBuffer}\n */\n writeFloat64 (value: number) {\n this.ensureAvailable(8)\n this._data.setFloat64(this.offset, value, this.littleEndian)\n this.offset += 8\n this._updateLastWrittenByte()\n return this\n }\n\n /**\n * Write the charCode of the passed string's first character to the current pointer offset\n * @param {string} str - The character to set\n * @return {IOBuffer}\n */\n writeChar (str: string) {\n return this.writeUint8(str.charCodeAt(0))\n }\n\n /**\n * Write the charCodes of the passed string's characters to the current pointer offset\n * @param {string} str\n * @return {IOBuffer}\n */\n writeChars (str: string) {\n for (var i = 0; i < str.length; i++) {\n this.writeUint8(str.charCodeAt(i))\n }\n return this\n }\n\n /**\n * Export a Uint8Array view of the internal buffer.\n * The view starts at the byte offset and its length\n * is calculated to stop at the last written byte or the original length.\n * @return {Uint8Array}\n */\n toArray () {\n return new Uint8Array(this.buffer, this.byteOffset, this._lastWrittenByte)\n }\n\n /**\n * Update the last written byte offset\n * @private\n */\n _updateLastWrittenByte () {\n if (this.offset > this._lastWrittenByte) {\n this._lastWrittenByte = this.offset\n }\n }\n}\n\nexport default IOBuffer\n","/**\n * @file STL Writer\n * @author Paul Pillot \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport Writer from './writer'\nimport IOBuffer from '../utils/io-buffer'\nimport Surface from '../surface/surface'\n\n// https://en.wikipedia.org/wiki/STL_(file_format)#ASCII_STL\n\n/**\n * Create an STL File from a surface Object (e.g. for 3D printing)\n *\n * @example\n * molsurf = new MolecularSurface(structure)\n * surf = molsurf.getSurface({type: 'av', probeRadius: 1.4})\n * stl = new StlWriter(surf)\n * stl.download('myFileName')\n */\nexport default class StlWriter extends Writer {\n readonly mimeType = 'application/vnd.ms-pki.stl'\n readonly defaultName = 'surface'\n readonly defaultExt = 'stl'\n\n surface: any // TODO\n\n /**\n * @param {Surface} surface - the surface to write out\n */\n constructor (surface: Surface) {\n super()\n\n this.surface = surface\n }\n\n /*\n * Get STL Binary data\n *\n * Adapted from: https://github.com/mrdoob/three.js/blob/master/examples/js/exporters/STLBinaryExporter.js\n * see https://en.wikipedia.org/wiki/STL_(file_format)#Binary_STL for the file format description\n *\n * @return {DataView} the data\n */\n getData () {\n const triangles = this.surface.index.length / 3\n const bufferLength = triangles * 2 + triangles * 3 * 4 * 4 + 80 + 4\n const output = new IOBuffer(bufferLength)\n\n output.skip(80) // skip header\n output.writeUint32(triangles)\n\n const vector = new Vector3()\n const vectorNorm1 = new Vector3()\n const vectorNorm2 = new Vector3()\n const vectorNorm3 = new Vector3()\n\n // traversing vertices\n for (let i = 0; i < triangles; i++) {\n const indices = [\n this.surface.index[i * 3],\n this.surface.index[i * 3 + 1],\n this.surface.index[i * 3 + 2]\n ]\n\n vectorNorm1.fromArray(this.surface.normal, indices[0] * 3)\n vectorNorm2.fromArray(this.surface.normal, indices[1] * 3)\n vectorNorm3.fromArray(this.surface.normal, indices[2] * 3)\n\n vector.addVectors(vectorNorm1, vectorNorm2).add(vectorNorm3).normalize()\n\n output.writeFloat32(vector.x)\n output.writeFloat32(vector.y)\n output.writeFloat32(vector.z)\n\n for (let j = 0; j < 3; j++) {\n vector.fromArray(this.surface.position, indices[j] * 3)\n\n output.writeFloat32(vector.x) // vertices\n output.writeFloat32(vector.y)\n output.writeFloat32(vector.z)\n }\n\n output.writeUint16(0) // attribute byte count\n }\n\n return new DataView(output.buffer)\n }\n}","/**\n * @file Counter\n * @author Alexander Rose \n * @private\n */\n\nimport { Log } from '../globals'\n\nimport * as signalsWrapper from 'signals'\n\n/**\n * {@link Signal}, dispatched when the `count` changes\n * @example\n * counter.signals.countChanged.add( function( delta ){ ... } );\n * @event Counter#countChanged\n * @type {Integer}\n */\n\nexport interface CounterSignals {\n countChanged: signalsWrapper.Signal\n}\n\n/**\n * Counter class for keeping track of counts\n */\nclass Counter {\n count = 0\n\n signals: CounterSignals = {\n countChanged: new signalsWrapper.Signal()\n }\n\n /**\n * Set the `count` to zero\n * @return {undefined}\n */\n clear () {\n this.change(-this.count)\n }\n\n /**\n * Change the `count`\n * @fires Counter#countChanged\n * @param {Integer} delta - count change\n * @return {undefined}\n */\n change (delta: number) {\n this.count += delta\n this.signals.countChanged.dispatch(delta, this.count)\n\n if (this.count < 0) {\n Log.warn('Counter.count below zero', this.count)\n }\n }\n\n /**\n * Increments the `count` by one.\n * @return {undefined}\n */\n increment () {\n this.change(1)\n }\n\n /**\n * Decrements the `count` by one.\n * @return {undefined}\n */\n decrement () {\n this.change(-1)\n }\n\n /**\n * Listen to another counter object and change this `count` by the\n * same amount\n * @param {Counter} counter - the counter object to listen to\n * @return {undefined}\n */\n listen (counter: Counter) {\n this.change(counter.count)\n counter.signals.countChanged.add(this.change, this)\n }\n\n /**\n * Stop listening to the other counter object\n * @param {Counter} counter - the counter object to stop listening to\n * @return {undefined}\n */\n unlisten (counter: Counter) {\n const countChanged = counter.signals.countChanged\n if (countChanged.has(this.change, this)) {\n countChanged.remove(this.change, this)\n }\n }\n\n /**\n * Invole the callback function once, when the `count` becomes zero\n * @param {Function} callback - the callback function\n * @param {Object} context - the context for the callback function\n * @return {undefined}\n */\n onZeroOnce (callback: () => void, context?: any) {\n if (this.count === 0) {\n callback.call(context)\n } else {\n const fn = () => {\n if (this.count === 0) {\n this.signals.countChanged.remove(fn, this)\n callback.call(context)\n }\n }\n this.signals.countChanged.add(fn, this)\n }\n }\n\n dispose () {\n this.clear()\n this.signals.countChanged.dispose()\n }\n}\n\nexport default Counter\n","/**\n * @file Stats\n * @author Alexander Rose \n * @private\n */\n\nimport * as signalsWrapper from 'signals'\n\nexport default class Stats {\n signals = {\n updated: new signalsWrapper.Signal()\n }\n\n maxDuration = -Infinity\n minDuration = Infinity\n avgDuration = 14\n lastDuration = Infinity\n\n prevFpsTime = 0\n lastFps = Infinity\n lastFrames = 1\n frames = 0\n count = 0\n\n startTime: number\n currentTime: number\n\n constructor () {\n this.begin()\n }\n\n update () {\n this.startTime = this.end()\n this.currentTime = this.startTime\n this.signals.updated.dispatch()\n }\n\n begin () {\n this.startTime = window.performance.now()\n this.lastFrames = this.frames\n }\n\n end () {\n const time = window.performance.now()\n\n this.count += 1\n this.frames += 1\n\n this.lastDuration = time - this.startTime\n this.minDuration = Math.min(this.minDuration, this.lastDuration)\n this.maxDuration = Math.max(this.maxDuration, this.lastDuration)\n this.avgDuration -= this.avgDuration / 30\n this.avgDuration += this.lastDuration / 30\n\n if (time > this.prevFpsTime + 1000) {\n this.lastFps = this.frames\n this.prevFpsTime = time\n this.frames = 0\n }\n\n return time\n }\n}","/**\n * @file Shader Utils\n * @author Alexander Rose \n * @private\n */\n\nimport { ShaderChunk } from 'three'\n\nimport './chunk/fog_fragment.glsl'\nimport './chunk/interior_fragment.glsl'\nimport './chunk/matrix_scale.glsl'\nimport './chunk/nearclip_vertex.glsl'\nimport './chunk/nearclip_fragment.glsl'\nimport './chunk/opaque_back_fragment.glsl'\nimport './chunk/radiusclip_vertex.glsl'\nimport './chunk/radiusclip_fragment.glsl'\nimport './chunk/unpack_color.glsl'\n\nimport { ShaderRegistry } from '../globals'\n\nexport type ShaderDefine = (\n 'NEAR_CLIP'|'RADIUS_CLIP'|'PICKING'|'NOLIGHT'|'FLAT_SHADED'|'OPAQUE_BACK'|\n 'DIFFUSE_INTERIOR'|'USE_INTERIOR_COLOR'|\n 'USE_SIZEATTENUATION'|'USE_MAP'|'ALPHATEST'|'SDF'|'FIXED_SIZE'|\n 'CUBIC_INTERPOLATION'|'BSPLINE_FILTER'|'CATMULROM_FILTER'|'MITCHELL_FILTER'\n)\nexport type ShaderDefines = {\n [k in ShaderDefine]?: number|string\n}\n\nfunction getDefines (defines: ShaderDefines) {\n if (defines === undefined) return ''\n\n const lines = []\n\n for (const name in defines) {\n const value = defines[ name as keyof ShaderDefines ]\n\n if (!value) continue\n\n lines.push(`#define ${name} ${value}`)\n }\n\n return lines.join('\\n') + '\\n'\n}\n\nconst reInclude = /^(?!\\/\\/)\\s*#include\\s+(\\S+)/gmi\nconst shaderCache: { [k: string]: string } = {}\n\nexport function getShader (name: string, defines: ShaderDefines = {}) {\n let hash = name + '|'\n for (const key in defines) {\n hash += key + ':' + defines[ key as keyof ShaderDefines ]\n }\n\n if (!shaderCache[ hash ]) {\n const definesText = getDefines(defines)\n\n let shaderText = ShaderRegistry.get(`shader/${name}`) as string\n if (!shaderText) {\n throw new Error(`empty shader, '${name}'`)\n }\n shaderText = shaderText.replace(reInclude, function (match, p1) {\n const path = `shader/chunk/${p1}.glsl`\n const chunk = ShaderRegistry.get(path) || ShaderChunk[ p1 ]\n if (!chunk) {\n throw new Error(`empty chunk, '${p1}'`)\n }\n return chunk\n })\n\n shaderCache[ hash ] = definesText + shaderText\n }\n\n return shaderCache[ hash ]\n}\n","/**\n * @file Viewer Constants\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug } from '../globals'\n\nif (typeof WebGLRenderingContext !== 'undefined') {\n const wrcp = WebGLRenderingContext.prototype\n\n // wrap WebGL debug function used by three.js and\n // ignore calls to them when the debug flag is not set\n\n const _getShaderParameter = wrcp.getShaderParameter\n wrcp.getShaderParameter = function getShaderParameter (this: WebGLRenderingContext) {\n if (Debug) {\n return _getShaderParameter.apply(this, arguments)\n } else {\n return true\n }\n }\n\n const _getShaderInfoLog = wrcp.getShaderInfoLog\n wrcp.getShaderInfoLog = function getShaderInfoLog (this: WebGLRenderingContext) {\n if (Debug) {\n return _getShaderInfoLog.apply(this, arguments)\n } else {\n return ''\n }\n }\n\n const _getProgramParameter = wrcp.getProgramParameter\n wrcp.getProgramParameter = function getProgramParameter (this: WebGLRenderingContext, program, pname) {\n if (Debug || pname !== wrcp.LINK_STATUS) {\n return _getProgramParameter.apply(this, arguments)\n } else {\n return true\n }\n }\n\n const _getProgramInfoLog = wrcp.getProgramInfoLog\n wrcp.getProgramInfoLog = function getProgramInfoLog (this: WebGLRenderingContext) {\n if (Debug) {\n return _getProgramInfoLog.apply(this, arguments)\n } else {\n return ''\n }\n }\n}\n\nexport const JitterVectors = [\n [\n [ 0, 0 ]\n ],\n [\n [ 4, 4 ], [ -4, -4 ]\n ],\n [\n [ -2, -6 ], [ 6, -2 ], [ -6, 2 ], [ 2, 6 ]\n ],\n [\n [ 1, -3 ], [ -1, 3 ], [ 5, 1 ], [ -3, -5 ],\n [ -5, 5 ], [ -7, -1 ], [ 3, 7 ], [ 7, -7 ]\n ],\n [\n [ 1, 1 ], [ -1, -3 ], [ -3, 2 ], [ 4, -1 ],\n [ -5, -2 ], [ 2, 5 ], [ 5, 3 ], [ 3, -5 ],\n [ -2, 6 ], [ 0, -7 ], [ -4, -6 ], [ -6, 4 ],\n [ -8, 0 ], [ 7, -4 ], [ 6, 7 ], [ -7, -8 ]\n ],\n [\n [ -4, -7 ], [ -7, -5 ], [ -3, -5 ], [ -5, -4 ],\n [ -1, -4 ], [ -2, -2 ], [ -6, -1 ], [ -4, 0 ],\n [ -7, 1 ], [ -1, 2 ], [ -6, 3 ], [ -3, 3 ],\n [ -7, 6 ], [ -3, 6 ], [ -5, 7 ], [ -1, 7 ],\n [ 5, -7 ], [ 1, -6 ], [ 6, -5 ], [ 4, -4 ],\n [ 2, -3 ], [ 7, -2 ], [ 1, -1 ], [ 4, -1 ],\n [ 2, 1 ], [ 6, 2 ], [ 0, 4 ], [ 4, 4 ],\n [ 2, 5 ], [ 7, 5 ], [ 5, 6 ], [ 3, 7 ]\n ]\n]\n\nJitterVectors.forEach(offsetList => {\n offsetList.forEach(offset => {\n // 0.0625 = 1 / 16\n offset[ 0 ] *= 0.0625\n offset[ 1 ] *= 0.0625\n })\n})\n","/**\n * @file Tiled Renderer\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport { Camera, WebGLRenderer } from 'three'\nimport Viewer from './viewer'\n\nexport interface TiledRendererParams {\n factor?: number\n antialias?: boolean\n onProgress?: Function\n onFinish?: Function\n}\n\nclass TiledRenderer {\n canvas = document.createElement('canvas')\n\n private _width: number\n private _height: number\n private _n: number\n private _factor: number\n private _antialias: boolean\n private _viewerSampleLevel: number\n\n private _viewer: Viewer\n private _onProgress?: Function\n private _onFinish?: Function\n private _ctx: CanvasRenderingContext2D\n\n constructor(renderer: WebGLRenderer, camera: Camera, viewer: Viewer, params: TiledRendererParams) {\n this._viewer = viewer\n\n this._factor = defaults(params.factor, 2)\n this._antialias = defaults(params.antialias, false)\n\n this._onProgress = params.onProgress\n this._onFinish = params.onFinish\n\n if (this._antialias) this._factor *= 2\n this._n = this._factor * this._factor\n\n // canvas\n\n this._width = this._viewer.width\n this._height = this._viewer.height\n\n if (this._antialias) {\n this.canvas.width = this._width * this._factor / 2\n this.canvas.height = this._height * this._factor / 2\n } else {\n this.canvas.width = this._width * this._factor\n this.canvas.height = this._height * this._factor\n }\n\n this._ctx = this.canvas.getContext('2d')!\n\n this._viewerSampleLevel = viewer.sampleLevel\n this._viewer.setSampling(-1)\n }\n\n private _renderTile (i: number) {\n const viewer = this._viewer\n const width = this._width\n const height = this._height\n const factor = this._factor\n\n const x = i % factor\n const y = Math.floor(i / factor)\n\n const offsetX = x * width\n const offsetY = y * height\n\n viewer.camera.setViewOffset(\n width * factor,\n height * factor,\n offsetX,\n offsetY,\n width,\n height\n )\n\n viewer.render()\n\n if (this._antialias) {\n const w = Math.round((offsetX + width) / 2) - Math.round (offsetX / 2);\n const h = Math.round((offsetY + height) / 2) - Math.round (offsetY / 2);\n this._ctx.drawImage(\n viewer.renderer.domElement,\n Math.round(offsetX / 2),\n Math.round(offsetY / 2),\n w,\n h\n )\n } else {\n this._ctx.drawImage(\n viewer.renderer.domElement,\n Math.floor(offsetX),\n Math.floor(offsetY),\n Math.ceil(width),\n Math.ceil(height)\n )\n }\n\n if (typeof this._onProgress === 'function') {\n this._onProgress(i + 1, this._n, false)\n }\n }\n\n private _finalize () {\n this._viewer.setSampling(this._viewerSampleLevel)\n this._viewer.camera.view = null! // TODO\n\n if (typeof this._onFinish === 'function') {\n this._onFinish(this._n + 1, this._n, false)\n }\n }\n\n render () {\n for (let i = 0; i <= this._n; ++i) {\n if (i === this._n) {\n this._finalize()\n } else {\n this._renderTile(i)\n }\n }\n }\n\n renderAsync () {\n let count = 0\n const n = this._n\n\n const fn = () => {\n if (count === n) {\n this._finalize()\n } else {\n this._renderTile(count)\n }\n count += 1\n }\n\n for (let i = 0; i <= n; ++i) {\n setTimeout(fn, 0)\n }\n }\n}\n\nexport default TiledRenderer\n","/**\n * @file Math Constants\n * @author Alexander Rose \n * @private\n */\n\nexport const EPS = 0.0000001\nexport const TwoPI = 2 * Math.PI\n\nexport const DEG2RAD = Math.PI / 180\nexport const RAD2DEG = 180 / Math.PI\n","/**\n * @file Array Utils\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { NumberArray } from '../types'\nimport { TwoPI } from './math-constants'\n\nexport function circularMean (array: NumberArray, max: number, stride = 1, offset = 0, indices?: NumberArray) {\n // http://en.wikipedia.org/wiki/Center_of_mass#Systems_with_periodic_boundary_conditions\n\n // Bai, Linge; Breen, David (2008). Calculating Center of Mass in an Unbounded 2D Environment. Journal of Graphics, GPU, and Game Tools 13 (4): 53–60.\n\n // http://stackoverflow.com/questions/18166507/using-fft-to-find-the-center-of-mass-under-periodic-boundary-conditions\n\n const n = indices ? indices.length : array.length / stride\n\n let cosMean = 0\n let sinMean = 0\n\n if (indices) {\n for (let i = 0; i < n; ++i) {\n const c = (array[ indices[ i ] * stride + offset ] + max) % max\n const angle = (c / max) * TwoPI - Math.PI\n\n cosMean += Math.cos(angle)\n sinMean += Math.sin(angle)\n }\n } else {\n for (let i = offset; i < n; i += stride) {\n const c = (array[ i ] + max) % max\n const angle = (c / max) * TwoPI - Math.PI\n\n cosMean += Math.cos(angle)\n sinMean += Math.sin(angle)\n }\n }\n\n cosMean /= n\n sinMean /= n\n\n const meanAngle = Math.atan2(sinMean, cosMean)\n const mean = (meanAngle + Math.PI) / TwoPI * max\n\n return mean\n}\n\nexport function calculateCenterArray (array1: NumberArray, array2: NumberArray, center?: T, offset = 0): T {\n const n = array1.length\n const c = center || new Float32Array(n)\n\n for (let i = 0; i < n; i += 3) {\n c[ offset + i + 0 ] = (array1[ i + 0 ] + array2[ i + 0 ]) / 2.0\n c[ offset + i + 1 ] = (array1[ i + 1 ] + array2[ i + 1 ]) / 2.0\n c[ offset + i + 2 ] = (array1[ i + 2 ] + array2[ i + 2 ]) / 2.0\n }\n\n return c as T\n}\n\nexport function calculateDirectionArray (array1: NumberArray, array2: NumberArray) {\n const n = array1.length\n const direction = new Float32Array(n)\n\n for (let i = 0; i < n; i += 3) {\n direction[ i + 0 ] = array2[ i + 0 ] - array1[ i + 0 ]\n direction[ i + 1 ] = array2[ i + 1 ] - array1[ i + 1 ]\n direction[ i + 2 ] = array2[ i + 2 ] - array1[ i + 2 ]\n }\n\n return direction\n}\n\nexport function uniformArray (n: number, a: number, optionalTarget?: T): T {\n const array = optionalTarget || new Float32Array(n)\n\n for (let i = 0; i < n; ++i) {\n array[ i ] = a\n }\n\n return array as T\n}\n\nexport function uniformArray3 (n: number, a: number, b: number, c: number, optionalTarget?: NumberArray) {\n const array = optionalTarget || new Float32Array(n * 3)\n\n for (let i = 0; i < n; ++i) {\n const j = i * 3\n\n array[ j + 0 ] = a\n array[ j + 1 ] = b\n array[ j + 2 ] = c\n }\n\n return array\n}\n\nexport function centerArray3 (array: NumberArray, center = new Vector3()) {\n const n = array.length\n\n for (let i = 0; i < n; i += 3) {\n center.x += array[ i ]\n center.y += array[ i + 1 ]\n center.z += array[ i + 2 ]\n }\n\n center.divideScalar(n / 3)\n\n return center\n}\n\nexport function serialArray (n: number) {\n const array = new Float32Array(n)\n\n for (let i = 0; i < n; ++i) {\n array[ i ] = i\n }\n\n return array\n}\n\nexport function serialBlockArray (n: number, b: number, offset = 0, optionalTarget?: NumberArray) {\n const array = optionalTarget || new Float32Array(n * b)\n\n for (let i = 0; i < n; ++i) {\n const k = offset + i * b\n\n for (let j = 0; j < b; ++j) {\n array[ k + j ] = i\n }\n }\n\n return array\n}\n\nexport function randomColorArray (n: number) {\n const array = new Float32Array(n * 3)\n\n for (let i = 0; i < n; ++i) {\n const j = i * 3\n\n array[ j + 0 ] = Math.random()\n array[ j + 1 ] = Math.random()\n array[ j + 2 ] = Math.random()\n }\n\n return array\n}\n\nexport function replicateArrayEntries (array: NumberArray, m: number) {\n const n = array.length\n const repArr = new Float32Array(n * m)\n\n for (let i = 0; i < n; ++i) {\n const k = i * m\n const a = array[ i ]\n\n for (let j = 0; j < m; ++j) {\n repArr[ k + j ] = a\n }\n }\n\n return repArr\n}\n\nexport function replicateArray3Entries (array: NumberArray, m: number) {\n const n = array.length / 3\n const repArr = new Float32Array(n * m * 3)\n\n for (let i = 0; i < n; ++i) {\n const v = i * 3\n const k = i * m * 3\n\n const a = array[ v + 0 ]\n const b = array[ v + 1 ]\n const c = array[ v + 2 ]\n\n for (let j = 0; j < m; ++j) {\n const l = k + j * 3\n\n repArr[ l + 0 ] = a\n repArr[ l + 1 ] = b\n repArr[ l + 2 ] = c\n }\n }\n\n return repArr\n}\n\nexport function calculateMeanArray (array1: NumberArray, array2: NumberArray) {\n const n = array1.length\n const mean = new Float32Array(n)\n\n for (let i = 0; i < n; i++) {\n mean[ i ] = (array1[ i ] + array2[ i ]) / 2.0\n }\n\n return mean\n}\n\nexport function calculateMinArray (array1: NumberArray, array2: NumberArray) {\n const n = array1.length\n const min = new Float32Array(n)\n\n for (let i = 0; i < n; i++) {\n min[ i ] = Math.min(array1[ i ], array2[ i ])\n }\n\n return min\n}\n\nexport function copyArray (src: T, dst: T, srcOffset: number, dstOffset: number, length: number) {\n for (let i = 0; i < length; ++i) {\n dst[ dstOffset + i ] = src[ srcOffset + i ]\n }\n}\n\nexport function copyWithin (array: NumberArray|any[], srcOffset: number, dstOffset: number, length: number) {\n copyArray(array, array, srcOffset, dstOffset, length)\n}\n\nconst swap = new Float32Array(4)\nconst temp = new Float32Array(4)\n/**\n * quicksortIP\n * @function\n * @author Roman Bolzern , 2013\n * @author I4DS http://www.fhnw.ch/i4ds, 2013\n * @license MIT License \n * @description\n * In-place quicksort for typed arrays (e.g. for Float32Array)\n * provides fast sorting\n * useful e.g. for a custom shader and/or BufferGeometry\n * Complexity: http://bigocheatsheet.com/ see Quicksort\n *\n * @example\n * points: [x, y, z, x, y, z, x, y, z, ...]\n * eleSize: 3 //because of (x, y, z)\n * orderElement: 0 //order according to x\n *\n * @param {TypedArray} arr - array to be sorted\n * @param {Integer} eleSize - element size\n * @param {Integer} orderElement - index of element used for sorting, < eleSize\n * @param {Integer} [begin] - start index for range to be sorted\n * @param {Integer} [end] - end index for range to be sorted\n * @return {TypedArray} the input array\n */\nexport function quicksortIP (arr: NumberArray, eleSize: number, orderElement: number, begin = 0, end?: number) {\n end = (end || (arr.length / eleSize)) - 1\n\n const stack = []\n let sp = -1\n let left = begin\n let right = end\n let tmp = 0.0\n let x = 0\n let y = 0\n\n const swapF = function (a: number, b: number) {\n a *= eleSize; b *= eleSize\n for (y = 0; y < eleSize; y++) {\n tmp = arr[ a + y ]\n arr[ a + y ] = arr[ b + y ]\n arr[ b + y ] = tmp\n }\n }\n\n let i, j\n\n while (true) {\n if (right - left <= 25) {\n for (j = left + 1; j <= right; j++) {\n for (x = 0; x < eleSize; x++) {\n swap[ x ] = arr[ j * eleSize + x ]\n }\n\n i = j - 1\n\n while (i >= left && arr[ i * eleSize + orderElement ] > swap[ orderElement ]) {\n for (x = 0; x < eleSize; x++) {\n arr[ (i + 1) * eleSize + x ] = arr[ i * eleSize + x ]\n }\n i--\n }\n\n for (x = 0; x < eleSize; x++) {\n arr[ (i + 1) * eleSize + x ] = swap[ x ]\n }\n }\n\n if (sp === -1) break\n\n right = stack[ sp-- ] // ?\n left = stack[ sp-- ]\n } else {\n const median = (left + right) >> 1\n\n i = left + 1\n j = right\n\n swapF(median, i)\n\n if (arr[ left * eleSize + orderElement ] > arr[ right * eleSize + orderElement ]) {\n swapF(left, right)\n }\n\n if (arr[ i * eleSize + orderElement ] > arr[ right * eleSize + orderElement ]) {\n swapF(i, right)\n }\n\n if (arr[ left * eleSize + orderElement ] > arr[ i * eleSize + orderElement ]) {\n swapF(left, i)\n }\n\n for (x = 0; x < eleSize; x++) {\n temp[ x ] = arr[ i * eleSize + x ]\n }\n\n while (true) {\n do i++; while (arr[ i * eleSize + orderElement ] < temp[ orderElement ])\n do j--; while (arr[ j * eleSize + orderElement ] > temp[ orderElement ])\n if (j < i) break\n swapF(i, j)\n }\n\n for (x = 0; x < eleSize; x++) {\n arr[ (left + 1) * eleSize + x ] = arr[ j * eleSize + x ]\n arr[ j * eleSize + x ] = temp[ x ]\n }\n\n if (right - i + 1 >= j - left) {\n stack[ ++sp ] = i\n stack[ ++sp ] = right\n right = j - 1\n } else {\n stack[ ++sp ] = left\n stack[ ++sp ] = j - 1\n left = i\n }\n }\n }\n\n return arr\n}\n\nexport function quicksortCmp (arr: NumberArray|T[], cmp?: (a: number|T, b: number|T) => number, begin = 0, end?: number) {\n cmp = cmp || function cmp (a, b) {\n if (a > b) return 1\n if (a < b) return -1\n return 0\n }\n end = (end || arr.length) - 1\n\n const stack = []\n let sp = -1\n let left = begin\n let right = end\n let tmp: number|T\n\n function swap (a: number, b: number) {\n const tmp2 = arr[ a ]\n arr[ a ] = arr[ b ]\n arr[ b ] = tmp2\n }\n\n let i, j\n\n while (true) {\n if (right - left <= 25) {\n for (let k = left + 1; k <= right; ++k) {\n tmp = arr[ k ]\n i = k - 1\n\n while (i >= left && cmp(arr[ i ], tmp) > 0) {\n arr[ i + 1 ] = arr[ i ]\n --i\n }\n\n arr[ i + 1 ] = tmp\n }\n\n if (sp === -1) break\n\n right = stack[ sp-- ] // ?\n left = stack[ sp-- ]\n } else {\n const median = (left + right) >> 1\n\n i = left + 1\n j = right\n\n swap(median, i)\n\n if (cmp(arr[ left ], arr[ right ]) > 0) {\n swap(left, right)\n }\n\n if (cmp(arr[ i ], arr[ right ]) > 0) {\n swap(i, right)\n }\n\n if (cmp(arr[ left ], arr[ i ]) > 0) {\n swap(left, i)\n }\n\n tmp = arr[ i ]\n\n while (true) {\n do i++; while (cmp(arr[ i ], tmp) < 0)\n do j--; while (cmp(arr[ j ], tmp) > 0)\n if (j < i) break\n swap(i, j)\n }\n\n arr[ left + 1 ] = arr[ j ]\n arr[ j ] = tmp\n\n if (right - i + 1 >= j - left) {\n stack[ ++sp ] = i\n stack[ ++sp ] = right\n right = j - 1\n } else {\n stack[ ++sp ] = left\n stack[ ++sp ] = j - 1\n left = i\n }\n }\n }\n\n return arr\n}\n\nexport function quickselectCmp (arr: NumberArray|T[], n: number, cmp?: (a: number|T, b: number|T) => number, left = 0, right?: number) {\n cmp = cmp || function cmp (a, b) {\n if (a > b) return 1\n if (a < b) return -1\n return 0\n }\n right = (right || arr.length) - 1\n\n let pivotIndex, pivotValue, storeIndex\n\n function swap (a: number, b: number) {\n const tmp = arr[ a ]\n arr[ a ] = arr[ b ]\n arr[ b ] = tmp\n }\n\n while (true) {\n if (left === right) {\n return arr[ left ]\n }\n pivotIndex = (left + right) >> 1\n pivotValue = arr[ pivotIndex ]\n swap(pivotIndex, right)\n storeIndex = left\n for (let i = left; i < right; ++i) {\n if (cmp(arr[ i ], pivotValue) < 0) {\n swap(storeIndex, i)\n ++storeIndex\n }\n }\n swap(right, storeIndex)\n pivotIndex = storeIndex\n if (n === pivotIndex) {\n return arr[ n ]\n } else if (n < pivotIndex) {\n right = pivotIndex - 1\n } else {\n left = pivotIndex + 1\n }\n }\n}\n\nexport function arrayMax (array: NumberArray) {\n let max = -Infinity\n for (let i = 0, il = array.length; i < il; ++i) {\n if (array[ i ] > max) max = array[ i ]\n }\n return max\n}\n\nexport function arrayMin (array: NumberArray) {\n let min = Infinity\n for (let i = 0, il = array.length; i < il; ++i) {\n if (array[ i ] < min) min = array[ i ]\n }\n return min\n}\n\nexport function arraySum (array: NumberArray, stride = 1, offset = 0) {\n const n = array.length\n let sum = 0\n for (let i = offset; i < n; i += stride) {\n sum += array[ i ]\n }\n return sum\n}\n\nexport function arrayMean (array: NumberArray, stride = 1, offset = 0) {\n return arraySum(array, stride, offset) / (array.length / stride)\n}\n\nexport function arrayRms (array: NumberArray) {\n const n = array.length\n let sumSq = 0\n for (let i = 0; i < n; ++i) {\n const di = array[ i ]\n sumSq += di * di\n }\n return Math.sqrt(sumSq / n)\n}\n\nexport function arraySorted (array: NumberArray) {\n for (let i = 1, il = array.length; i < il; ++i) {\n if (array[ i - 1 ] > array[ i ]) return false\n }\n return true\n}\n\nexport function arraySortedCmp (array: NumberArray|T[], cmp: (a: number|T, b: number|T) => number) {\n for (let i = 1, il = array.length; i < il; ++i) {\n if (cmp(array[ i - 1 ], array[ i ]) > 0) return false\n }\n return true\n}\n","/**\n * @file Viewer Utils\n * @author Alexander Rose \n * @private\n */\n\nimport {\n Vector2, Vector3, Matrix4, Points, Scene, Camera,\n Object3D, WebGLRenderer\n} from 'three'\n\nimport { createParams } from '../utils'\nimport TiledRenderer from './tiled-renderer'\nimport { quicksortCmp } from '../math/array-utils'\nimport Viewer from './viewer'\n\nfunction _trimCanvas (canvas: HTMLCanvasElement, r: number, g: number, b: number, a: number) {\n const canvasHeight = canvas.height\n const canvasWidth = canvas.width\n\n const ctx = canvas.getContext('2d')!\n const pixels = ctx.getImageData(0, 0, canvasWidth, canvasHeight).data\n\n let x, y, doBreak, off\n\n doBreak = false\n for (y = 0; y < canvasHeight; y++) {\n for (x = 0; x < canvasWidth; x++) {\n off = (y * canvasWidth + x) * 4\n if (pixels[ off ] !== r || pixels[ off + 1 ] !== g ||\n pixels[ off + 2 ] !== b || pixels[ off + 3 ] !== a\n ) {\n doBreak = true\n break\n }\n }\n if (doBreak) {\n break\n }\n }\n const topY = y\n\n doBreak = false\n for (x = 0; x < canvasWidth; x++) {\n for (y = 0; y < canvasHeight; y++) {\n off = (y * canvasWidth + x) * 4\n if (pixels[ off ] !== r || pixels[ off + 1 ] !== g ||\n pixels[ off + 2 ] !== b || pixels[ off + 3 ] !== a\n ) {\n doBreak = true\n break\n }\n }\n if (doBreak) {\n break\n }\n }\n const topX = x\n\n doBreak = false\n for (y = canvasHeight - 1; y >= 0; y--) {\n for (x = canvasWidth - 1; x >= 0; x--) {\n off = (y * canvasWidth + x) * 4\n if (pixels[ off ] !== r || pixels[ off + 1 ] !== g ||\n pixels[ off + 2 ] !== b || pixels[ off + 3 ] !== a\n ) {\n doBreak = true\n break\n }\n }\n if (doBreak) {\n break\n }\n }\n const bottomY = y\n\n doBreak = false\n for (x = canvasWidth - 1; x >= 0; x--) {\n for (y = canvasHeight - 1; y >= 0; y--) {\n off = (y * canvasWidth + x) * 4\n if (pixels[ off ] !== r || pixels[ off + 1 ] !== g ||\n pixels[ off + 2 ] !== b || pixels[ off + 3 ] !== a\n ) {\n doBreak = true\n break\n }\n }\n if (doBreak) {\n break\n }\n }\n const bottomX = x\n\n const trimedCanvas = document.createElement('canvas')\n trimedCanvas.width = bottomX - topX\n trimedCanvas.height = bottomY - topY\n\n const trimedCtx = trimedCanvas.getContext('2d')!\n trimedCtx.drawImage(\n canvas,\n topX, topY,\n trimedCanvas.width, trimedCanvas.height,\n 0, 0,\n trimedCanvas.width, trimedCanvas.height\n )\n\n return trimedCanvas\n}\n\n/**\n * Image parameter object.\n * @typedef {Object} ImageParameters - image generation parameters\n * @property {Boolean} trim - trim the image\n * @property {Integer} factor - scaling factor to apply to the viewer canvas\n * @property {Boolean} antialias - antialias the image\n * @property {Boolean} transparent - transparent image background\n */\n\nexport const ImageDefaultParameters = {\n trim: false,\n factor: 1,\n antialias: false,\n transparent: false,\n onProgress: undefined as Function|undefined\n}\nexport type ImageParameters = typeof ImageDefaultParameters\n\n/**\n * Make image from what is shown in a viewer canvas\n * @param {Viewer} viewer - the viewer\n * @param {ImageParameters} params - parameters object\n * @return {Promise} A Promise object that resolves to an image {@link Blob}.\n */\nexport function makeImage (viewer: Viewer, params: Partial = {}) {\n const {trim, factor, antialias, transparent} = createParams(params, ImageDefaultParameters)\n\n const renderer = viewer.renderer\n const camera = viewer.camera\n\n const originalClearAlpha = renderer.getClearAlpha()\n const backgroundColor = renderer.getClearColor()\n\n function setLineWidthAndPixelSize (invert = false) {\n let _factor = factor\n if (antialias) _factor *= 2\n if (invert) _factor = 1 / _factor\n viewer.scene.traverse(function (o: any) { // TODO\n const m = o.material\n if (m && m.linewidth) {\n m.linewidth *= _factor\n }\n if (m && m.uniforms && m.uniforms.size) {\n if (m.uniforms.size.__seen === undefined) {\n m.uniforms.size.value *= _factor\n m.uniforms.size.__seen = true\n }\n }\n if (m && m.uniforms && m.uniforms.linewidth) {\n if (m.uniforms.linewidth.__seen === undefined) {\n m.uniforms.linewidth.value *= _factor\n m.uniforms.linewidth.__seen = true\n }\n }\n })\n viewer.scene.traverse(function (o: any) { // TODO\n const m = o.material\n if (m && m.uniforms && m.uniforms.size) {\n delete m.uniforms.size.__seen\n }\n if (m && m.uniforms && m.uniforms.linewidth) {\n delete m.uniforms.linewidth.__seen\n }\n })\n }\n\n function trimCanvas (canvas: HTMLCanvasElement) {\n if (trim) {\n const bg = backgroundColor\n const r = transparent ? 0 : bg.r * 255\n const g = transparent ? 0 : bg.g * 255\n const b = transparent ? 0 : bg.b * 255\n const a = transparent ? 0 : 255\n return _trimCanvas(canvas, r, g, b, a)\n } else {\n return canvas\n }\n }\n\n function onProgress (i: number, n: number, finished: boolean) {\n if (typeof params.onProgress === 'function') {\n params.onProgress(i, n, finished)\n }\n }\n\n return new Promise(function (resolve, reject) {\n const tiledRenderer = new TiledRenderer(\n renderer, camera, viewer,\n { factor, antialias, onProgress, onFinish }\n )\n\n renderer.setClearAlpha(transparent ? 0 : 1)\n setLineWidthAndPixelSize()\n tiledRenderer.renderAsync()\n\n function onFinish (i: number, n: number) {\n const canvas = trimCanvas(tiledRenderer.canvas)\n canvas.toBlob(\n function (blob) {\n renderer.setClearAlpha(originalClearAlpha)\n setLineWidthAndPixelSize(true)\n viewer.requestRender()\n onProgress(n, n, true)\n if (blob) {\n resolve(blob)\n } else {\n reject('error creating image')\n }\n },\n 'image/png'\n )\n }\n })\n}\n\nconst vertex = new Vector3()\nconst matrix = new Matrix4()\nconst modelViewProjectionMatrix = new Matrix4()\n\nexport function sortProjectedPosition (scene: Scene, camera: Camera) {\n // console.time( \"sort\" );\n\n scene.traverseVisible(function (o) {\n if (!(o instanceof Points) || !o.userData.buffer.parameters.sortParticles) {\n return\n }\n\n const attributes = (o.geometry as any).attributes // TODO\n const n = attributes.position.count\n\n if (n === 0) return\n\n matrix.multiplyMatrices(\n camera.matrixWorldInverse, o.matrixWorld\n )\n modelViewProjectionMatrix.multiplyMatrices(\n camera.projectionMatrix, matrix\n )\n\n let sortData, sortArray, zArray: Float32Array, cmpFn\n\n if (!o.userData.sortData) {\n zArray = new Float32Array(n)\n sortArray = new Uint32Array(n)\n cmpFn = function (ai: number, bi: number) {\n const a = zArray[ ai ]\n const b = zArray[ bi ]\n if (a > b) return 1\n if (a < b) return -1\n return 0\n }\n\n sortData = {\n __zArray: zArray,\n __sortArray: sortArray,\n __cmpFn: cmpFn\n }\n\n o.userData.sortData = sortData\n } else {\n sortData = o.userData.sortData\n zArray = sortData.__zArray\n sortArray = sortData.__sortArray\n cmpFn = sortData.__cmpFn\n }\n\n for (let i = 0; i < n; ++i) {\n vertex.fromArray(attributes.position.array, i * 3)\n vertex.applyMatrix4(modelViewProjectionMatrix)\n\n // negate, so that sorting order is reversed\n zArray[ i ] = -vertex.z\n sortArray[ i ] = i\n }\n\n quicksortCmp(sortArray, cmpFn)\n\n let index, indexSrc, indexDst, tmpTab\n\n for (let name in attributes) {\n const attr = attributes[ name ]\n const array = attr.array\n const itemSize = attr.itemSize\n\n if (!sortData[ name ]) {\n sortData[ name ] = new Float32Array(itemSize * n)\n }\n\n tmpTab = sortData[ name ]\n sortData[ name ] = array\n\n for (let i = 0; i < n; ++i) {\n index = sortArray[ i ]\n\n for (let j = 0; j < itemSize; ++j) {\n indexSrc = index * itemSize + j\n indexDst = i * itemSize + j\n tmpTab[ indexDst ] = array[ indexSrc ]\n }\n }\n\n attributes[ name ].array = tmpTab\n attributes[ name ].needsUpdate = true\n }\n })\n\n // console.timeEnd( \"sort\" );\n}\n\nconst resolution = new Vector2()\nconst projectionMatrixInverse = new Matrix4()\nconst projectionMatrixTranspose = new Matrix4()\n\nexport function updateMaterialUniforms (group: Object3D, camera: Camera, renderer: WebGLRenderer, cDist: number, bRadius: number) {\n let size = new Vector2()\n renderer.getSize(size)\n const canvasHeight = size.height\n const pixelRatio = renderer.getPixelRatio()\n const ortho = camera.type === 'OrthographicCamera'\n\n resolution.set(size.width, size.height)\n projectionMatrixInverse.getInverse(camera.projectionMatrix)\n projectionMatrixTranspose.copy(camera.projectionMatrix).transpose()\n\n group.traverse(function (o: any) {\n const m = o.material\n if (!m) return\n\n const u = m.uniforms\n if (!u) return\n\n if (m.clipNear) {\n const nearFactor = (50 - m.clipNear) / 50\n const nearClip = cDist - (bRadius * nearFactor)\n u.clipNear.value = nearClip\n }\n\n if (u.canvasHeight) {\n u.canvasHeight.value = canvasHeight\n }\n\n if (u.resolution) {\n u.resolution.value.copy(resolution)\n }\n\n if (u.pixelRatio) {\n u.pixelRatio.value = pixelRatio\n }\n\n if (u.projectionMatrixInverse) {\n u.projectionMatrixInverse.value.copy(projectionMatrixInverse)\n }\n\n if (u.projectionMatrixTranspose) {\n u.projectionMatrixTranspose.value.copy(projectionMatrixTranspose)\n }\n\n if (u.ortho) {\n u.ortho.value = ortho\n }\n })\n}\n\nexport function updateCameraUniforms (group: Object3D, camera: Camera) {\n projectionMatrixInverse.getInverse(camera.projectionMatrix)\n projectionMatrixTranspose.copy(camera.projectionMatrix).transpose()\n\n group.traverse(function (o: any) {\n const m = o.material\n if (!m) return\n\n const u = m.uniforms\n if (!u) return\n\n if (u.projectionMatrixInverse) {\n u.projectionMatrixInverse.value.copy(projectionMatrixInverse)\n }\n\n if (u.projectionMatrixTranspose) {\n u.projectionMatrixTranspose.value.copy(projectionMatrixTranspose)\n }\n })\n}\n","/**\n * @file Viewer\n * @author Alexander Rose \n * @private\n */\n\n// adapted from https://webglfundamentals.org/webgl/resources/webgl-utils.js\n// Copyright 2012, Gregg Tavares. Modified BSD License\n\nexport function createProgram(gl: WebGLRenderingContext, shaders: WebGLShader[], attribs?: string[], locations?: number[]) {\n const program = gl.createProgram()\n if (!program) {\n console.log(`error creating WebGL program`)\n return\n }\n shaders.forEach(shader => gl.attachShader(program, shader))\n if (attribs) {\n attribs.forEach((attrib, i) => {\n gl.bindAttribLocation(program, locations ? locations[i] : i, attrib)\n })\n }\n gl.linkProgram(program);\n\n // Check the link status\n const linked = gl.getProgramParameter(program, gl.LINK_STATUS)\n if (!linked) {\n console.log(`error linking program: ${gl.getProgramInfoLog(program)}`)\n gl.deleteProgram(program)\n return null\n }\n return program\n}\n\nexport function loadShader(gl: WebGLRenderingContext, shaderSource: string, shaderType: number) {\n const shader = gl.createShader(shaderType)\n if (!shader) {\n console.log(`error creating WebGL shader ${shaderType}`)\n return // can't create shader\n }\n gl.shaderSource(shader, shaderSource)\n gl.compileShader(shader)\n\n // Check the compile status\n const compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS)\n if (!compiled) {\n console.log(`error compiling shader ${shader}: ${gl.getShaderInfoLog(shader)}`)\n gl.deleteShader(shader)\n return null\n }\n\n return shader\n}\n\n//\n\nexport function getErrorDescription(gl: WebGLRenderingContext, error: number) {\n switch (error) {\n case gl.NO_ERROR: return 'no error'\n case gl.INVALID_ENUM: return 'invalid enum'\n case gl.INVALID_VALUE: return 'invalid value'\n case gl.INVALID_OPERATION: return 'invalid operation'\n case gl.INVALID_FRAMEBUFFER_OPERATION: return 'invalid framebuffer operation'\n case gl.OUT_OF_MEMORY: return 'out of memory'\n case gl.CONTEXT_LOST_WEBGL: return 'context lost'\n }\n return 'unknown error'\n}\n\nexport function getExtension (gl: WebGLRenderingContext, name: string) {\n const ext = gl.getExtension(name)\n if (!ext) console.log(`extension '${name}' not available`)\n return ext\n}\n\nconst TextureTestVertShader = `\nattribute vec4 a_position;\n\nvoid main() {\n gl_Position = a_position;\n}`\n\nconst TextureTestFragShader = `\nprecision mediump float;\nuniform vec4 u_color;\nuniform sampler2D u_texture;\n\nvoid main() {\n gl_FragColor = texture2D(u_texture, vec2(0.5, 0.5)) * u_color;\n}`\n\nconst TextureTestTexCoords = new Float32Array([\n -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0\n])\n\nexport function testTextureSupport (type: number) {\n // adapted from\n // https://stackoverflow.com/questions/28827511/webgl-ios-render-to-floating-point-texture\n\n // Get A WebGL context\n const canvas = document.createElement('canvas')\n canvas.width = 16\n canvas.height = 16\n canvas.style.width = 16 + 'px'\n canvas.style.height = 16 + 'px'\n const gl = canvas.getContext(\"webgl\") || canvas.getContext(\"experimental-webgl\");\n if (!gl) {\n console.log(`error creating webgl context for ${type}`)\n return false\n }\n if (!(gl instanceof WebGLRenderingContext)) {\n console.log(`Got unexpected type for WebGL rendering context`)\n return false\n }\n\n getExtension(gl, 'OES_texture_float')\n getExtension(gl, 'OES_texture_half_float')\n getExtension(gl, 'WEBGL_color_buffer_float')\n\n // setup shaders\n const vertShader = loadShader(gl, TextureTestVertShader, gl.VERTEX_SHADER)\n const fragShader = loadShader(gl, TextureTestFragShader, gl.FRAGMENT_SHADER)\n if (!vertShader || !fragShader) return false\n\n // setup program\n const program = createProgram(gl, [ vertShader, fragShader ])\n if (!program) {\n console.log(`error creating WebGL program`)\n return false\n }\n gl.useProgram(program);\n\n // look up where the vertex data needs to go.\n const positionLocation = gl.getAttribLocation(program, \"a_position\");\n const colorLoc = gl.getUniformLocation(program, \"u_color\");\n if (!colorLoc) {\n console.log(`error getting 'u_color' uniform location`)\n return false\n }\n\n // provide texture coordinates for the rectangle.\n const positionBuffer = gl.createBuffer()\n gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)\n gl.bufferData(gl.ARRAY_BUFFER, TextureTestTexCoords, gl.STATIC_DRAW)\n gl.enableVertexAttribArray(positionLocation)\n gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0)\n\n const whiteTex = gl.createTexture()\n const whiteData = new Uint8Array([255, 255, 255, 255])\n gl.bindTexture(gl.TEXTURE_2D, whiteTex)\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, whiteData)\n\n const tex = gl.createTexture()\n gl.bindTexture(gl.TEXTURE_2D, tex)\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, type, null)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)\n\n const fb = gl.createFramebuffer()\n gl.bindFramebuffer(gl.FRAMEBUFFER, fb)\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0)\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER)\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n console.log(`error creating framebuffer for ${type}`)\n return false\n }\n\n // Draw the rectangle.\n gl.bindTexture(gl.TEXTURE_2D, whiteTex)\n gl.uniform4fv(colorLoc, [0, 10, 20, 1])\n gl.drawArrays(gl.TRIANGLES, 0, 6)\n\n gl.bindTexture(gl.TEXTURE_2D, tex)\n gl.bindFramebuffer(gl.FRAMEBUFFER, null)\n gl.clearColor(1, 0, 0, 1)\n gl.clear(gl.COLOR_BUFFER_BIT)\n gl.uniform4fv(colorLoc, [0, 1/10, 1/20, 1])\n gl.drawArrays(gl.TRIANGLES, 0, 6)\n\n // Check if rendered correctly\n const pixel = new Uint8Array(4)\n gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel)\n if (pixel[0] !== 0 || pixel[1] < 248 || pixel[2] < 248 || pixel[3] < 254) {\n console.log(`not able to actually render to ${type} texture`)\n return false\n }\n\n // Check reading from float texture\n if (type === gl.FLOAT) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, fb)\n const floatPixel = new Float32Array(4)\n gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, floatPixel)\n const error = gl.getError()\n if (error) {\n console.log(`error reading pixels as float: '${getErrorDescription(gl, error)}'`)\n return false\n }\n }\n\n return true\n}\n","/**\n * @file Viewer\n * @author Alexander Rose \n * @private\n */\n\nimport { Signal } from 'signals'\nimport {\n PerspectiveCamera, OrthographicCamera, StereoCamera,\n Vector2, Box3, Vector3, Matrix4, Color,\n WebGLRenderer, WebGLRenderTarget,\n NearestFilter, LinearFilter, AdditiveBlending,\n RGBAFormat, FloatType, /*HalfFloatType, */UnsignedByteType,\n ShaderMaterial,\n PlaneGeometry, Geometry,\n Scene, Mesh, Group, Object3D, Uniform,\n Fog, SpotLight, AmbientLight,\n BufferGeometry, BufferAttribute,\n LineSegments,\n LinearEncoding, sRGBEncoding, TextureEncoding\n} from 'three'\nimport '../shader/BasicLine.vert'\nimport '../shader/BasicLine.frag'\nimport '../shader/Quad.vert'\nimport '../shader/Quad.frag'\n\nimport {\n Debug, Log, WebglErrorMessage, Browser,\n setExtensionFragDepth, SupportsReadPixelsFloat, setSupportsReadPixelsFloat\n} from '../globals'\nimport { degToRad } from '../math/math-utils'\nimport Stats from './stats'\nimport { getShader } from '../shader/shader-utils'\nimport { setColorSpace } from '../color/colormaker'\nimport { JitterVectors } from './viewer-constants'\nimport {\n makeImage, ImageParameters,\n sortProjectedPosition, updateMaterialUniforms, updateCameraUniforms\n} from './viewer-utils'\nimport { testTextureSupport } from './gl-utils'\n\nimport Buffer from '../buffer/buffer'\n\nconst pixelBufferFloat = new Float32Array(4 * 25)\nconst pixelBufferUint = new Uint8Array(4 * 25)\n\n// When picking, we read a 25 pixel (5x5) array (readRenderTargetPixels)\n// We read the pixels in the order below to find what was picked.\n// This starts at the center and tries successively further points.\n// (Many points will be at equal distance to the center, their order\n// is arbitrary).\nconst pixelOrder = [12,7,13,17,11,6,8,18,16,2,14,22,10,1,3,9,19,23,21,15,5,0,4,24,20]\n\n\nconst tmpMatrix = new Matrix4()\n\nfunction onBeforeRender (this: Object3D, renderer: WebGLRenderer, scene: Scene, camera: PerspectiveCamera|OrthographicCamera, geometry: Geometry, material: ShaderMaterial/*, group */) {\n const u = material.uniforms\n const updateList = []\n\n if (!u) return // See #908 - some materials may not have uniforms, ignore these\n\n if (u.objectId) {\n u.objectId.value = SupportsReadPixelsFloat ? this.id : this.id / 255\n updateList.push('objectId')\n }\n\n if (u.modelViewMatrixInverse || u.modelViewMatrixInverseTranspose ||\n u.modelViewProjectionMatrix || u.modelViewProjectionMatrixInverse\n ) {\n this.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, this.matrixWorld)\n }\n\n if (u.modelViewMatrixInverse) {\n u.modelViewMatrixInverse.value.getInverse(this.modelViewMatrix)\n updateList.push('modelViewMatrixInverse')\n }\n\n if (u.modelViewMatrixInverseTranspose) {\n if (u.modelViewMatrixInverse) {\n u.modelViewMatrixInverseTranspose.value.copy(\n u.modelViewMatrixInverse.value\n ).transpose()\n } else {\n u.modelViewMatrixInverseTranspose.value\n .getInverse(this.modelViewMatrix)\n .transpose()\n }\n updateList.push('modelViewMatrixInverseTranspose')\n }\n\n if (u.modelViewProjectionMatrix) {\n u.modelViewProjectionMatrix.value.multiplyMatrices(\n camera.projectionMatrix, this.modelViewMatrix\n )\n updateList.push('modelViewProjectionMatrix')\n }\n\n if (u.modelViewProjectionMatrixInverse) {\n if (u.modelViewProjectionMatrix) {\n tmpMatrix.copy(\n u.modelViewProjectionMatrix.value\n )\n u.modelViewProjectionMatrixInverse.value.getInverse(\n tmpMatrix\n )\n } else {\n tmpMatrix.multiplyMatrices(\n camera.projectionMatrix, this.modelViewMatrix\n )\n u.modelViewProjectionMatrixInverse.value.getInverse(\n tmpMatrix\n )\n }\n updateList.push('modelViewProjectionMatrixInverse')\n }\n\n if (updateList.length) {\n const materialProperties = renderer.properties.get(material)\n\n if (materialProperties.program) {\n const gl = renderer.getContext()\n const p = materialProperties.program\n gl.useProgram(p.program)\n const pu = p.getUniforms()\n\n updateList.forEach(function (name) {\n pu.setValue(gl, name, u[ name ].value)\n })\n }\n }\n}\n\nexport type CameraType = 'perspective'|'orthographic'|'stereo'\nexport type ColorWorkflow = 'linear' | 'sRGB'\n\nexport interface ViewerSignals {\n ticked: Signal,\n rendered: Signal\n}\n\nexport interface ViewerParameters {\n fogColor: Color\n fogNear: number\n fogFar: number\n\n backgroundColor: Color\n\n cameraType: CameraType\n cameraFov: number\n cameraEyeSep: number\n cameraZ: number\n\n clipNear: number\n clipFar: number\n clipDist: number\n clipMode: string // \"scene\" or \"camera\"\n clipScale: string // \"relative\" or \"absolute\"\n\n lightColor: Color\n lightIntensity: number\n ambientColor: Color\n ambientIntensity: number\n\n sampleLevel: number\n\n rendererEncoding: TextureEncoding // default is three.LinearEncoding; three.sRGBEncoding gives more correct results\n}\n\nexport interface BufferInstance {\n matrix: Matrix4\n}\n\n/**\n * Viewer class\n * @class\n * @param {String|Element} [idOrElement] - dom id or element\n */\nexport default class Viewer {\n signals: ViewerSignals\n\n container: HTMLElement\n wrapper: HTMLElement\n\n private rendering: boolean\n private renderPending: boolean\n private lastRenderedPicking: boolean\n private isStill: boolean\n private frameRequest: number\n\n sampleLevel: number\n private cDist: number\n private bRadius: number\n\n private parameters: ViewerParameters\n stats: Stats\n\n perspectiveCamera: PerspectiveCamera\n private orthographicCamera: OrthographicCamera\n private stereoCamera: StereoCamera\n camera: PerspectiveCamera|OrthographicCamera\n\n width: number\n height: number\n\n scene: Scene\n private spotLight: SpotLight\n private ambientLight: AmbientLight\n rotationGroup: Group\n translationGroup: Group\n private modelGroup: Group\n private pickingGroup: Group\n private backgroundGroup: Group\n private helperGroup: Group\n\n renderer: WebGLRenderer\n private supportsHalfFloat: boolean\n\n private pickingTarget: WebGLRenderTarget\n private sampleTarget: WebGLRenderTarget\n private holdTarget: WebGLRenderTarget\n\n private compositeUniforms: {\n tForeground: Uniform\n scale: Uniform\n }\n private compositeMaterial: ShaderMaterial\n private compositeCamera: OrthographicCamera\n private compositeScene: Scene\n\n private boundingBoxMesh: LineSegments\n boundingBox = new Box3()\n private boundingBoxSize = new Vector3()\n private boundingBoxLength = 0\n\n private info = {\n memory: {\n programs: 0,\n geometries: 0,\n textures: 0\n },\n render: {\n calls: 0,\n vertices: 0,\n faces: 0,\n points: 0\n }\n }\n\n private distVector = new Vector3()\n\n constructor (idOrElement: string|HTMLElement) {\n this.signals = {\n ticked: new Signal(),\n rendered: new Signal()\n }\n\n if (typeof idOrElement === 'string') {\n const elm = document.getElementById(idOrElement)\n if (elm === null) {\n this.container = document.createElement('div')\n }else {\n this.container = elm\n }\n } else if (idOrElement instanceof HTMLElement) {\n this.container = idOrElement\n } else {\n this.container = document.createElement('div')\n }\n\n if (this.container === document.body) {\n this.width = window.innerWidth || 1\n this.height = window.innerHeight || 1\n } else {\n const box = this.container.getBoundingClientRect()\n this.width = box.width || 1\n this.height = box.height || 1\n this.container.style.overflow = 'hidden'\n }\n\n this.wrapper = document.createElement('div')\n this.wrapper.style.position = 'relative'\n this.container.appendChild(this.wrapper)\n\n this._initParams()\n this._initStats()\n this._initCamera()\n this._initScene()\n\n if (this._initRenderer() === false) {\n Log.error('Viewer: could not initialize renderer')\n return\n }\n\n this._initHelper()\n\n // fog & background\n this.setBackground()\n this.setFog()\n\n this.animate = this.animate.bind(this)\n }\n\n private _initParams () {\n this.parameters = {\n fogColor: new Color(0x000000),\n fogNear: 50,\n fogFar: 100,\n\n backgroundColor: new Color(0x000000),\n\n cameraType: 'perspective',\n cameraFov: 40,\n cameraEyeSep: 0.3,\n cameraZ: -80, // FIXME initial value should be automatically determined\n\n clipNear: 0,\n clipFar: 100,\n clipDist: 10,\n clipMode: 'scene',\n clipScale: 'relative',\n\n lightColor: new Color(0xdddddd),\n lightIntensity: 1.0,\n ambientColor: new Color(0xdddddd),\n ambientIntensity: 0.2,\n\n sampleLevel: 0,\n\n // output encoding: use sRGB for a linear internal workflow, linear for traditional sRGB workflow.\n rendererEncoding: LinearEncoding,\n }\n }\n\n private _initCamera () {\n const lookAt = new Vector3(0, 0, 0)\n const {width, height} = this\n\n this.perspectiveCamera = new PerspectiveCamera(\n this.parameters.cameraFov, width / height\n )\n this.perspectiveCamera.position.z = this.parameters.cameraZ\n this.perspectiveCamera.lookAt(lookAt)\n\n this.orthographicCamera = new OrthographicCamera(\n width / -2, width / 2, height / 2, height / -2\n )\n this.orthographicCamera.position.z = this.parameters.cameraZ\n this.orthographicCamera.lookAt(lookAt)\n\n this.stereoCamera = new StereoCamera()\n this.stereoCamera.aspect = 0.5\n this.stereoCamera.eyeSep = this.parameters.cameraEyeSep\n\n const cameraType = this.parameters.cameraType\n if (cameraType === 'orthographic') {\n this.camera = this.orthographicCamera\n } else if(cameraType === 'perspective' || cameraType === 'stereo') {\n this.camera = this.perspectiveCamera\n } else {\n throw new Error(`Unknown cameraType '${cameraType}'`)\n }\n this.camera.updateProjectionMatrix()\n }\n\n private _initStats () {\n this.stats = new Stats()\n }\n\n private _initScene () {\n if (!this.scene) {\n this.scene = new Scene()\n this.scene.name = 'scene'\n }\n\n this.rotationGroup = new Group()\n this.rotationGroup.name = 'rotationGroup'\n this.scene.add(this.rotationGroup)\n\n this.translationGroup = new Group()\n this.translationGroup.name = 'translationGroup'\n this.rotationGroup.add(this.translationGroup)\n\n this.modelGroup = new Group()\n this.modelGroup.name = 'modelGroup'\n this.translationGroup.add(this.modelGroup)\n\n this.pickingGroup = new Group()\n this.pickingGroup.name = 'pickingGroup'\n this.translationGroup.add(this.pickingGroup)\n\n this.backgroundGroup = new Group()\n this.backgroundGroup.name = 'backgroundGroup'\n this.translationGroup.add(this.backgroundGroup)\n\n this.helperGroup = new Group()\n this.helperGroup.name = 'helperGroup'\n this.translationGroup.add(this.helperGroup)\n\n // fog\n\n this.scene.fog = new Fog(this.parameters.fogColor.getHex())\n\n // light\n\n this.spotLight = new SpotLight(\n this.parameters.lightColor.getHex(), this.parameters.lightIntensity\n )\n this.scene.add(this.spotLight)\n\n this.ambientLight = new AmbientLight(\n this.parameters.ambientColor.getHex(), this.parameters.ambientIntensity\n )\n this.scene.add(this.ambientLight)\n }\n\n private _initRenderer () {\n const dpr = window.devicePixelRatio\n const {width, height} = this\n\n try {\n this.renderer = new WebGLRenderer({\n preserveDrawingBuffer: true,\n alpha: true,\n antialias: true\n })\n } catch (e) {\n this.wrapper.innerHTML = WebglErrorMessage\n return false\n }\n this.renderer.setPixelRatio(dpr)\n this.renderer.setSize(width, height)\n this.renderer.autoClear = false\n this.renderer.sortObjects = true\n this.renderer.outputEncoding = this.parameters.rendererEncoding\n\n const gl = this.renderer.getContext()\n // console.log(gl.getContextAttributes().antialias)\n // console.log(gl.getParameter(gl.SAMPLES))\n\n // For WebGL1, extensions must be explicitly enabled.\n // The following are builtin to WebGL2 (and don't appear as\n // extensions)\n // EXT_frag_depth, OES_element_index_uint, OES_texture_float\n // OES_texture_half_float\n\n // The WEBGL_color_buffer_float extension is replaced by\n // EXT_color_buffer_float\n\n // If not webgl2 context, explicitly check for these\n if (!this.renderer.capabilities.isWebGL2) {\n setExtensionFragDepth(this.renderer.extensions.get('EXT_frag_depth'))\n this.renderer.extensions.get('OES_element_index_uint')\n\n setSupportsReadPixelsFloat(\n (this.renderer.extensions.get('OES_texture_float') &&\n this.renderer.extensions.get('WEBGL_color_buffer_float')) ||\n (this.renderer.extensions.get('OES_texture_float') &&\n testTextureSupport(gl.FLOAT))\n )\n // picking texture\n\n this.renderer.extensions.get('OES_texture_float')\n\n this.supportsHalfFloat = (\n this.renderer.extensions.get('OES_texture_half_float') &&\n testTextureSupport(0x8D61)\n )\n\n } else {\n setExtensionFragDepth(true)\n setSupportsReadPixelsFloat(\n this.renderer.extensions.get('EXT_color_buffer_float')\n )\n this.supportsHalfFloat = true\n }\n\n this.wrapper.appendChild(this.renderer.domElement)\n\n const dprWidth = width * dpr\n const dprHeight = height * dpr\n\n\n if (Debug) {\n console.log(JSON.stringify({\n 'Browser': Browser,\n 'OES_texture_float': !!this.renderer.extensions.get('OES_texture_float'),\n 'OES_texture_half_float': !!this.renderer.extensions.get('OES_texture_half_float'),\n 'WEBGL_color_buffer_float': !!this.renderer.extensions.get('WEBGL_color_buffer_float'),\n 'testTextureSupport Float': testTextureSupport(gl.FLOAT),\n 'testTextureSupport HalfFloat': testTextureSupport(0x8D61),\n 'this.supportsHalfFloat': this.supportsHalfFloat,\n 'SupportsReadPixelsFloat': SupportsReadPixelsFloat\n }, null, 2))\n }\n\n this.pickingTarget = new WebGLRenderTarget(\n dprWidth, dprHeight,\n {\n minFilter: NearestFilter,\n magFilter: NearestFilter,\n stencilBuffer: false,\n format: RGBAFormat,\n type: SupportsReadPixelsFloat ? FloatType : UnsignedByteType\n }\n )\n this.pickingTarget.texture.generateMipmaps = false\n this.pickingTarget.texture.encoding = this.parameters.rendererEncoding\n\n // workaround to reset the gl state after using testTextureSupport\n // fixes some bug where nothing is rendered to the canvas\n // when animations are started on page load\n this.renderer.setRenderTarget(this.pickingTarget)\n this.renderer.clear()\n this.renderer.setRenderTarget(null!)\n\n // ssaa textures\n\n this.sampleTarget = new WebGLRenderTarget(\n dprWidth, dprHeight,\n {\n minFilter: LinearFilter,\n magFilter: LinearFilter,\n format: RGBAFormat\n }\n )\n this.sampleTarget.texture.encoding = this.parameters.rendererEncoding\n\n this.holdTarget = new WebGLRenderTarget(\n dprWidth, dprHeight,\n {\n minFilter: NearestFilter,\n magFilter: NearestFilter,\n format: RGBAFormat,\n type: UnsignedByteType\n // using HalfFloatType or FloatType does not work on some Chrome 61 installations\n // type: this.supportsHalfFloat ? HalfFloatType : (\n // SupportsReadPixelsFloat ? FloatType : UnsignedByteType\n // )\n }\n )\n this.holdTarget.texture.encoding = this.parameters.rendererEncoding\n\n this.compositeUniforms = {\n 'tForeground': new Uniform(this.sampleTarget.texture),\n 'scale': new Uniform(1.0)\n }\n\n this.compositeMaterial = new ShaderMaterial({\n uniforms: this.compositeUniforms,\n vertexShader: getShader('Quad.vert'),\n fragmentShader: getShader('Quad.frag'),\n premultipliedAlpha: true,\n transparent: true,\n blending: AdditiveBlending,\n depthTest: false,\n depthWrite: false\n })\n\n this.compositeCamera = new OrthographicCamera(-1, 1, 1, -1, 0, 1)\n this.compositeScene = new Scene()\n this.compositeScene.name = 'compositeScene'\n this.compositeScene.add(new Mesh(\n new PlaneGeometry(2, 2), this.compositeMaterial\n ))\n }\n\n private _initHelper () {\n const indices = new Uint16Array([\n 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6,\n 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7\n ])\n const positions = new Float32Array(8 * 3)\n\n const bbGeometry = new BufferGeometry()\n bbGeometry.setIndex(new BufferAttribute(indices, 1))\n bbGeometry.setAttribute('position', new BufferAttribute(positions, 3))\n const bbMaterial = new ShaderMaterial({\n uniforms: { 'uColor': { value: new Color('skyblue') } },\n vertexShader: getShader('BasicLine.vert'),\n fragmentShader: getShader('BasicLine.frag')\n })\n\n this.boundingBoxMesh = new LineSegments(bbGeometry, bbMaterial)\n this.helperGroup.add(this.boundingBoxMesh)\n }\n\n updateHelper () {\n const position = ((this.boundingBoxMesh.geometry as BufferGeometry).attributes as any).position // TODO\n const array = position.array\n const {min, max} = this.boundingBox\n\n array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z\n array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z\n array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z\n array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z\n array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z\n array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z\n array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z\n array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z\n\n position.needsUpdate = true\n\n if (!this.boundingBox.isEmpty()) {\n this.boundingBoxMesh.geometry.computeBoundingSphere()\n }\n }\n\n /** Distance from origin (lookAt point) */\n get cameraDistance(): number {\n return Math.abs(this.camera.position.z)\n }\n\n /** Set distance from origin (lookAt point); along the -z axis */\n set cameraDistance(d: number) {\n this.camera.position.z = -d\n }\n\n add (buffer: Buffer, instanceList?: BufferInstance[]) {\n // Log.time( \"Viewer.add\" );\n\n if (instanceList) {\n instanceList.forEach(instance => this.addBuffer(buffer, instance))\n } else {\n this.addBuffer(buffer)\n }\n\n buffer.group.name = 'meshGroup'\n buffer.wireframeGroup.name = 'wireframeGroup'\n if (buffer.parameters.background) {\n this.backgroundGroup.add(buffer.group)\n this.backgroundGroup.add(buffer.wireframeGroup)\n } else {\n this.modelGroup.add(buffer.group)\n this.modelGroup.add(buffer.wireframeGroup)\n }\n\n if (buffer.pickable) {\n this.pickingGroup.add(buffer.pickingGroup)\n }\n\n if (Debug) this.updateHelper()\n\n // Log.timeEnd( \"Viewer.add\" );\n }\n\n addBuffer (buffer: Buffer, instance?: BufferInstance) {\n // Log.time( \"Viewer.addBuffer\" );\n\n function setUserData (object: Object3D) {\n if (object instanceof Group) {\n object.children.forEach(setUserData)\n } else {\n object.userData.buffer = buffer\n object.userData.instance = instance\n object.onBeforeRender = onBeforeRender\n }\n }\n\n const mesh = buffer.getMesh()\n if (instance) {\n mesh.applyMatrix4(instance.matrix)\n }\n setUserData(mesh)\n buffer.group.add(mesh)\n\n const wireframeMesh = buffer.getWireframeMesh()\n if (instance) {\n // wireframeMesh.applyMatrix( instance.matrix );\n wireframeMesh.matrix.copy(mesh.matrix)\n wireframeMesh.position.copy(mesh.position)\n wireframeMesh.quaternion.copy(mesh.quaternion)\n wireframeMesh.scale.copy(mesh.scale)\n }\n setUserData(wireframeMesh)\n buffer.wireframeGroup.add(wireframeMesh)\n\n if (buffer.pickable) {\n const pickingMesh = buffer.getPickingMesh()\n if (instance) {\n // pickingMesh.applyMatrix( instance.matrix );\n pickingMesh.matrix.copy(mesh.matrix)\n pickingMesh.position.copy(mesh.position)\n pickingMesh.quaternion.copy(mesh.quaternion)\n pickingMesh.scale.copy(mesh.scale)\n }\n setUserData(pickingMesh)\n buffer.pickingGroup.add(pickingMesh)\n }\n\n if (instance) {\n this._updateBoundingBox(buffer.geometry, buffer.matrix, instance.matrix)\n } else {\n this._updateBoundingBox(buffer.geometry, buffer.matrix)\n }\n\n // Log.timeEnd( \"Viewer.addBuffer\" );\n }\n\n remove (buffer: Buffer) {\n this.translationGroup.children.forEach(function (group) {\n group.remove(buffer.group)\n group.remove(buffer.wireframeGroup)\n })\n\n if (buffer.pickable) {\n this.pickingGroup.remove(buffer.pickingGroup)\n }\n\n this.updateBoundingBox()\n if (Debug) this.updateHelper()\n\n // this.requestRender();\n }\n\n private _updateBoundingBox (geometry?: BufferGeometry, matrix?: Matrix4, instanceMatrix?: Matrix4) {\n const boundingBox = this.boundingBox\n\n function updateGeometry (geometry: BufferGeometry, matrix?: Matrix4, instanceMatrix?: Matrix4) {\n if (geometry.boundingBox == null) {\n geometry.computeBoundingBox()\n }\n\n const geoBoundingBox = (geometry.boundingBox as Box3).clone()\n\n if (matrix) {\n geoBoundingBox.applyMatrix4(matrix)\n }\n if (instanceMatrix) {\n geoBoundingBox.applyMatrix4(instanceMatrix)\n }\n\n if (geoBoundingBox.min.equals(geoBoundingBox.max)) {\n // mainly to give a single impostor geometry some volume\n // as it is only expanded in the shader on the GPU\n geoBoundingBox.expandByScalar(5)\n }\n\n boundingBox.union(geoBoundingBox)\n }\n\n function updateNode (node: Mesh) {\n if (node.geometry !== undefined) {\n let matrix, instanceMatrix\n if (node.userData.buffer) {\n matrix = node.userData.buffer.matrix\n }\n if (node.userData.instance) {\n instanceMatrix = node.userData.instance.matrix\n }\n updateGeometry(node.geometry as BufferGeometry, matrix, instanceMatrix) // TODO\n }\n }\n\n if (geometry) {\n updateGeometry(geometry, matrix, instanceMatrix)\n } else {\n boundingBox.makeEmpty()\n this.modelGroup.traverse(updateNode)\n this.backgroundGroup.traverse(updateNode)\n }\n\n boundingBox.getSize(this.boundingBoxSize)\n this.boundingBoxLength = this.boundingBoxSize.length()\n }\n\n updateBoundingBox () {\n this._updateBoundingBox()\n if (Debug) this.updateHelper()\n }\n\n getPickingPixels () {\n const {width, height} = this\n\n const n = width * height * 4\n const imgBuffer = SupportsReadPixelsFloat ? new Float32Array(n) : new Uint8Array(n)\n\n this.render(true)\n this.renderer.readRenderTargetPixels(\n this.pickingTarget, 0, 0, width, height, imgBuffer\n )\n\n return imgBuffer\n }\n\n getImage (picking: boolean) {\n return new Promise(resolve => {\n if (picking) {\n const {width, height} = this\n const n = width * height * 4\n let imgBuffer = this.getPickingPixels()\n\n if (SupportsReadPixelsFloat) {\n const imgBuffer2 = new Uint8Array(n)\n for (let i = 0; i < n; ++i) {\n imgBuffer2[ i ] = Math.round(imgBuffer[ i ] * 255)\n }\n imgBuffer = imgBuffer2\n }\n\n const canvas = document.createElement('canvas')\n canvas.width = width\n canvas.height = height\n const ctx = canvas.getContext('2d')! // TODO\n const imgData = ctx.getImageData(0, 0, width, height)\n imgData.data.set(imgBuffer as any) // TODO\n ctx.putImageData(imgData, 0, 0)\n canvas.toBlob(resolve as any, 'image/png') // TODO\n } else {\n this.renderer.domElement.toBlob(resolve as any, 'image/png') // TODO\n }\n })\n }\n\n makeImage (params: Partial = {}) {\n return makeImage(this, params)\n }\n\n setLight (color: Color|number|string, intensity: number, ambientColor: Color|number|string, ambientIntensity: number) {\n const p = this.parameters\n\n if (color !== undefined) p.lightColor.set(color as string) // TODO\n if (intensity !== undefined) p.lightIntensity = intensity\n if (ambientColor !== undefined) p.ambientColor.set(ambientColor as string) // TODO\n if (ambientIntensity !== undefined) p.ambientIntensity = ambientIntensity\n\n this.requestRender()\n }\n\n setFog (color?: Color|number|string, near?: number, far?: number) {\n const p = this.parameters\n\n if (color !== undefined) p.fogColor.set(color as string) // TODO\n if (near !== undefined) p.fogNear = near\n if (far !== undefined) p.fogFar = far\n\n this.requestRender()\n }\n\n setBackground (color?: Color|number|string) {\n const p = this.parameters\n\n if (color) p.backgroundColor.set(color as string) // TODO\n\n this.setFog(p.backgroundColor)\n this.renderer.setClearColor(p.backgroundColor, 0)\n this.renderer.domElement.style.backgroundColor = p.backgroundColor.getStyle()\n\n this.requestRender()\n }\n\n setSampling (level: number) {\n if (level !== undefined) {\n this.parameters.sampleLevel = level\n this.sampleLevel = level\n }\n\n this.requestRender()\n }\n\n /**\n * Set the output color encoding, i.e. how the renderer translates\n * colorspaces as it renders to the screen.\n\n * The default is LinearEncoding, because the internals of NGL are\n * already sRGB so no translation is needed to show sRGB colors.\n * Set to sRGBEncoding to create a linear workflow, and also call\n * `setColorEncoding(LinearEncoding)` to linearize colors on input.\n * @see setColorEncoding\n */\n private setOutputEncoding (encoding: TextureEncoding) {\n this.parameters.rendererEncoding = encoding\n this.renderer.outputEncoding = encoding\n this.pickingTarget.texture.encoding = encoding\n this.sampleTarget.texture.encoding = encoding\n this.holdTarget.texture.encoding = encoding\n }\n\n /**\n * Set the internal color workflow, linear or sRGB.\n * sRGB, the default, is more \"vibrant\" at the cost of accuracy.\n * Linear gives more accurate results, especially for transparent objects.\n * In all cases, the output is always sRGB; this just affects how colors are computed internally.\n * Call this just after creating the viewer, before loading any models.\n */\n setColorWorkflow (encoding: ColorWorkflow) {\n if (encoding != 'linear' && encoding != 'sRGB')\n throw new Error(`setColorWorkflow: invalid color workflow ${encoding}`)\n setColorSpace(encoding == 'linear' ? 'linear' : 'sRGB')\n this.setOutputEncoding(encoding == 'linear' ? sRGBEncoding : LinearEncoding)\n // Note: this doesn't rebuild models, so existing geometry will have\n // the old color encoding.\n this.requestRender()\n }\n\n setCamera (type: CameraType, fov?: number, eyeSep?: number) {\n const p = this.parameters\n\n if (type) p.cameraType = type\n if (fov) p.cameraFov = fov\n if (eyeSep) p.cameraEyeSep = eyeSep\n\n if (p.cameraType === 'orthographic') {\n if (this.camera !== this.orthographicCamera) {\n this.camera = this.orthographicCamera\n this.camera.position.copy(this.perspectiveCamera.position)\n this.camera.up.copy(this.perspectiveCamera.up)\n this.updateZoom()\n }\n } else if (p.cameraType === 'perspective' || p.cameraType === 'stereo') {\n if (this.camera !== this.perspectiveCamera) {\n this.camera = this.perspectiveCamera\n this.camera.position.copy(this.orthographicCamera.position)\n this.camera.up.copy(this.orthographicCamera.up)\n }\n } else {\n throw new Error(`Unknown cameraType '${p.cameraType}'`)\n }\n\n this.perspectiveCamera.fov = p.cameraFov\n this.stereoCamera.eyeSep = p.cameraEyeSep\n this.camera.updateProjectionMatrix()\n\n this.requestRender()\n }\n\n setClip (near: number, far: number, dist: number, clipMode?: string, clipScale?: string) {\n const p = this.parameters\n\n if (near !== undefined) p.clipNear = near\n if (far !== undefined) p.clipFar = far\n if (dist !== undefined) p.clipDist = dist\n if (clipMode !== undefined) p.clipMode = clipMode\n if (clipScale !== undefined) p.clipScale = clipScale\n\n this.requestRender()\n }\n\n setSize (width: number, height: number) {\n this.width = width || 1\n this.height = height || 1\n\n this.perspectiveCamera.aspect = this.width / this.height\n this.orthographicCamera.left = -this.width / 2\n this.orthographicCamera.right = this.width / 2\n this.orthographicCamera.top = this.height / 2\n this.orthographicCamera.bottom = -this.height / 2\n this.camera.updateProjectionMatrix()\n\n const dpr = window.devicePixelRatio\n\n this.renderer.setPixelRatio(dpr)\n this.renderer.setSize(width, height)\n\n const dprWidth = this.width * dpr\n const dprHeight = this.height * dpr\n\n this.pickingTarget.setSize(dprWidth, dprHeight)\n this.sampleTarget.setSize(dprWidth, dprHeight)\n this.holdTarget.setSize(dprWidth, dprHeight)\n\n this.requestRender()\n }\n\n handleResize () {\n if (this.container === document.body) {\n this.setSize(window.innerWidth, window.innerHeight)\n } else {\n const box = this.container.getBoundingClientRect()\n this.setSize(box.width, box.height)\n }\n }\n\n updateInfo (reset?: boolean) {\n const { memory, render } = this.info\n\n if (reset) {\n memory.programs = 0\n memory.geometries = 0\n memory.textures = 0\n\n render.calls = 0\n render.vertices = 0\n render.points = 0\n } else {\n const rInfo = this.renderer.info\n const rMemory = rInfo.memory\n const rRender = rInfo.render\n\n memory.geometries = rMemory.geometries\n memory.textures = rMemory.textures\n\n render.calls += rRender.calls\n render.faces += rRender.triangles\n render.points += rRender.points\n }\n }\n\n animate () {\n this.signals.ticked.dispatch(this.stats)\n const delta = window.performance.now() - this.stats.startTime\n\n if (delta > 500 && !this.isStill && this.sampleLevel < 3 && this.sampleLevel !== -1) {\n const currentSampleLevel = this.sampleLevel\n this.sampleLevel = 3\n this.renderPending = true\n this.render()\n this.isStill = true\n this.sampleLevel = currentSampleLevel\n if (Debug) Log.log('rendered still frame')\n }\n\n this.frameRequest = window.requestAnimationFrame(this.animate)\n }\n\n pick (x: number, y: number) {\n if (this.parameters.cameraType === 'stereo') {\n // TODO picking broken for stereo camera\n return {\n 'pid': 0,\n 'instance': undefined,\n 'picker': undefined\n }\n }\n\n x *= window.devicePixelRatio\n y *= window.devicePixelRatio\n\n x = Math.max(x - 2, 0)\n y = Math.max(y - 2, 0)\n\n let pid = 0, instance, picker\n const pixelBuffer = SupportsReadPixelsFloat ? pixelBufferFloat : pixelBufferUint\n\n this.render(true)\n this.renderer.readRenderTargetPixels(\n this.pickingTarget, x, y, 5, 5, pixelBuffer\n )\n\n for (let i = 0; i < pixelOrder.length; i++) {\n\n const offset = pixelOrder[i] * 4\n\n const oid = Math.round(pixelBuffer[ offset + 3 ])\n const object = this.pickingGroup.getObjectById(oid)\n if (object) {\n instance = object.userData.instance\n picker = object.userData.buffer.picking\n } else {\n continue\n }\n\n if (SupportsReadPixelsFloat) {\n pid =\n ((Math.round(pixelBuffer[offset] * 255) << 16) & 0xFF0000) |\n ((Math.round(pixelBuffer[offset + 1] * 255) << 8) & 0x00FF00) |\n ((Math.round(pixelBuffer[offset + 2] * 255)) & 0x0000FF)\n } else {\n pid =\n (pixelBuffer[offset] << 16) |\n (pixelBuffer[offset + 1] << 8) |\n (pixelBuffer[offset + 2])\n }\n }\n // if( Debug ){\n // const rgba = Array.apply( [], pixelBuffer );\n // Log.log( pixelBuffer );\n // Log.log(\n // \"picked color\",\n // rgba.map( c => { return c.toPrecision( 2 ) } )\n // );\n // Log.log( \"picked pid\", pid );\n // Log.log( \"picked oid\", oid );\n // Log.log( \"picked object\", object );\n // Log.log( \"picked instance\", instance );\n // Log.log( \"picked position\", x, y );\n // Log.log( \"devicePixelRatio\", window.devicePixelRatio );\n // }\n\n return { pid, instance, picker }\n }\n\n requestRender () {\n if (this.renderPending) {\n // Log.info(\"there is still a 'render' call pending\")\n return\n }\n\n // start gathering stats anew after inactivity\n if (window.performance.now() - this.stats.startTime > 22) {\n this.stats.begin()\n this.isStill = false\n }\n\n this.renderPending = true\n\n window.requestAnimationFrame(() => {\n this.render()\n this.stats.update()\n })\n }\n\n updateZoom () {\n const fov = degToRad(this.perspectiveCamera.fov)\n const height = 2 * Math.tan(fov / 2) * this.cameraDistance\n this.orthographicCamera.zoom = this.height / height\n }\n\n /**\n * Convert an absolute clip value to a relative one using bRadius.\n *\n * 0.0 -> 50.0\n * bRadius -> 0.0\n */\n absoluteToRelative (d: number) :number {\n return 50 * (1 - d / this.bRadius)\n }\n\n /**\n * Convert a relative clip value to an absolute one using bRadius\n *\n * 0.0 -> bRadius\n * 50.0 -> 0.0\n */\n relativeToAbsolute (d: number) : number {\n return this.bRadius * (1 - d / 50)\n }\n\n /**\n * Intepret clipMode, clipScale and set the camera and fog clipping.\n * Also ensures bRadius and cDist are valid\n */\n private __updateClipping () {\n const p = this.parameters\n\n // bRadius must always be updated for material-based clipping\n // and for focus calculations\n this.bRadius = Math.max(10, this.boundingBoxLength * 0.5)\n\n // FL: Removed below, but leaving commented as I don't understand intention\n // this.bRadius += this.boundingBox.getCenter(this.distVector).length()\n\n if (!isFinite(this.bRadius)) {\n this.bRadius = 50\n }\n\n this.camera.getWorldPosition(this.distVector)\n this.cDist = this.distVector.length()\n if (!this.cDist) {\n // recover from a broken (NaN) camera position\n this.cameraDistance = Math.abs(p.cameraZ)\n this.cDist = Math.abs(p.cameraZ)\n }\n\n // fog\n const fog = this.scene.fog as Fog\n fog.color.set(p.fogColor)\n\n if (p.clipMode === 'camera') {\n // Always interpret clipScale as absolute for clipMode camera\n\n this.camera.near = p.clipNear\n this.camera.far = p.clipFar\n fog.near = p.fogNear\n fog.far = p.fogFar\n\n } else {\n // scene mode\n\n if (p.clipScale === 'absolute') {\n // absolute scene mode; offset clip planes from scene center\n // (note: positive values move near plane towards camera and rear plane away)\n\n this.camera.near = this.cDist - p.clipNear\n this.camera.far = this.cDist + p.clipFar\n fog.near = this.cDist - p.fogNear\n fog.far = this.cDist + p.fogFar\n\n } else {\n // relative scene mode (default): convert pecentages to Angstroms\n\n const nearFactor = (50 - p.clipNear) / 50\n const farFactor = -(50 - p.clipFar) / 50\n this.camera.near = this.cDist - (this.bRadius * nearFactor)\n this.camera.far = this.cDist + (this.bRadius * farFactor)\n\n const fogNearFactor = (50 - p.fogNear) / 50\n const fogFarFactor = -(50 - p.fogFar) / 50\n fog.near = this.cDist - (this.bRadius * fogNearFactor)\n fog.far = this.cDist + (this.bRadius * fogFarFactor)\n }\n }\n\n if (p.clipMode !== 'camera') {\n\n if (this.camera.type === 'PerspectiveCamera') {\n\n this.camera.near = Math.max(0.1, p.clipDist, this.camera.near)\n this.camera.far = Math.max(1, this.camera.far)\n fog.near = Math.max(0.1, fog.near)\n fog.far = Math.max(1, fog.far)\n } else if (this.camera.type === 'OrthographicCamera') {\n\n if (p.clipDist > 0) {\n this.camera.near = Math.max(p.clipDist, this.camera.near)\n }\n }\n }\n }\n\n private __updateCamera () {\n const camera = this.camera\n camera.updateMatrix()\n camera.updateMatrixWorld(true)\n camera.updateProjectionMatrix()\n\n updateMaterialUniforms(this.scene, camera, this.renderer, this.cDist, this.bRadius)\n sortProjectedPosition(this.scene, camera)\n }\n\n private __setVisibility (model: boolean, picking: boolean, background: boolean, helper: boolean) {\n this.modelGroup.visible = model\n this.pickingGroup.visible = picking\n this.backgroundGroup.visible = background\n this.helperGroup.visible = helper\n }\n\n private __updateLights () {\n this.spotLight.color.set(this.parameters.lightColor)\n this.spotLight.intensity = this.parameters.lightIntensity\n\n this.distVector.copy(this.camera.position).setLength(this.boundingBoxLength * 100)\n this.spotLight.position.copy(this.camera.position).add(this.distVector)\n\n this.ambientLight.color.set(this.parameters.ambientColor)\n this.ambientLight.intensity = this.parameters.ambientIntensity\n }\n\n private __renderPickingGroup (camera: PerspectiveCamera|OrthographicCamera) {\n this.renderer.setRenderTarget(this.pickingTarget || null)\n this.renderer.clear()\n this.__setVisibility(false, true, false, false)\n this.renderer.render(this.scene, camera)\n // back to standard render target\n this.renderer.setRenderTarget(null)\n this.updateInfo()\n\n // if (Debug) {\n // this.__setVisibility(false, true, false, true);\n\n // this.renderer.clear();\n // this.renderer.render(this.scene, camera);\n // }\n }\n\n private __renderModelGroup (camera: PerspectiveCamera|OrthographicCamera, renderTarget?: WebGLRenderTarget) {\n this.renderer.setRenderTarget(renderTarget || null)\n this.renderer.clear()\n this.__setVisibility(false, false, true, false)\n this.renderer.render(this.scene, camera)\n this.renderer.clear(false, true, true)\n this.updateInfo()\n\n this.__setVisibility(true, false, false, Debug)\n this.renderer.render(this.scene, camera)\n this.renderer.setRenderTarget(null) // set back to default canvas\n this.updateInfo()\n }\n\n private __renderSuperSample (camera: PerspectiveCamera|OrthographicCamera, renderTarget?: WebGLRenderTarget) {\n // based on the Supersample Anti-Aliasing Render Pass\n // contributed to three.js by bhouston / http://clara.io/\n //\n // This manual approach to SSAA re-renders the scene ones for\n // each sample with camera jitter and accumulates the results.\n // References: https://en.wikipedia.org/wiki/Supersampling\n const offsetList = JitterVectors[ Math.max(0, Math.min(this.sampleLevel, 5)) ]\n\n const baseSampleWeight = 1.0 / offsetList.length\n const roundingRange = 1 / 32\n\n this.compositeUniforms.tForeground.value = this.sampleTarget.texture\n\n let width = this.sampleTarget.width\n const height = this.sampleTarget.height\n if (this.parameters.cameraType === 'stereo') {\n width /= 2\n }\n\n // render the scene multiple times, each slightly jitter offset\n // from the last and accumulate the results.\n for (let i = 0; i < offsetList.length; ++i) {\n const offset = offsetList[ i ]\n camera.setViewOffset(\n width, height, offset[ 0 ], offset[ 1 ], width, height\n )\n camera.updateProjectionMatrix()\n updateCameraUniforms(this.scene, camera)\n\n let sampleWeight = baseSampleWeight\n // the theory is that equal weights for each sample lead to an\n // accumulation of rounding errors.\n // The following equation varies the sampleWeight per sample\n // so that it is uniformly distributed across a range of values\n // whose rounding errors cancel each other out.\n const uniformCenteredDistribution = -0.5 + (i + 0.5) / offsetList.length\n sampleWeight += roundingRange * uniformCenteredDistribution\n this.compositeUniforms.scale.value = sampleWeight\n\n this.__renderModelGroup(camera, this.sampleTarget)\n this.renderer.setRenderTarget(this.holdTarget)\n if (i === 0) {\n this.renderer.clear()\n }\n\n this.renderer.render(this.compositeScene, this.compositeCamera)\n }\n\n this.compositeUniforms.scale.value = 1.0\n this.compositeUniforms.tForeground.value = this.holdTarget.texture\n\n camera.clearViewOffset()\n this.renderer.setRenderTarget(renderTarget || null)\n this.renderer.clear()\n this.renderer.render(this.compositeScene, this.compositeCamera)\n }\n\n private __renderStereo (picking = false, _renderTarget?: WebGLRenderTarget) {\n const stereoCamera = this.stereoCamera\n stereoCamera.update(this.perspectiveCamera);\n\n const renderer = this.renderer\n let size = new Vector2()\n renderer.getSize(size)\n\n renderer.setScissorTest(true)\n\n renderer.setScissor(0, 0, size.width / 2, size.height)\n renderer.setViewport(0, 0, size.width / 2, size.height)\n updateCameraUniforms(this.scene, stereoCamera.cameraL)\n this.__render(picking, stereoCamera.cameraL)\n\n renderer.setScissor(size.width / 2, 0, size.width / 2, size.height)\n renderer.setViewport(size.width / 2, 0, size.width / 2, size.height)\n updateCameraUniforms(this.scene, stereoCamera.cameraR)\n this.__render(picking, stereoCamera.cameraR)\n\n renderer.setScissorTest(false)\n renderer.setViewport(0, 0, size.width, size.height)\n }\n\n private __render(picking = false, camera: PerspectiveCamera|OrthographicCamera, renderTarget?: WebGLRenderTarget) {\n if (picking) {\n if (!this.lastRenderedPicking) this.__renderPickingGroup(camera)\n } else if (this.sampleLevel > 0 && this.parameters.cameraType !== 'stereo') {\n // TODO super sample broken for stereo camera\n this.__renderSuperSample(camera, renderTarget)\n } else {\n this.__renderModelGroup(camera, renderTarget)\n }\n }\n\n render (picking = false, renderTarget?: WebGLRenderTarget) {\n if (this.rendering) {\n Log.warn(\"'tried to call 'render' from within 'render'\")\n return\n }\n\n // Log.time('Viewer.render')\n\n this.rendering = true\n\n try {\n this.__updateClipping()\n this.__updateCamera()\n this.__updateLights()\n this.updateInfo(true)\n\n // render\n if (this.parameters.cameraType === 'stereo') {\n this.__renderStereo(picking, renderTarget)\n } else {\n this.__render(picking, this.camera, renderTarget)\n }\n this.lastRenderedPicking = picking\n } finally {\n this.rendering = false\n this.renderPending = false\n }\n this.signals.rendered.dispatch()\n\n // Log.timeEnd('Viewer.render')\n // Log.log(this.info.memory, this.info.render)\n }\n\n clear () {\n Log.log('scene cleared')\n this.scene.remove(this.rotationGroup)\n this._initScene()\n this.renderer.clear()\n }\n\n dispose () {\n this.renderer.dispose()\n window.cancelAnimationFrame(this.frameRequest)\n }\n}\n","/**\n * @file Constants\n * @author Alexander Rose \n * @private\n */\n\nexport const LeftMouseButton = 1\nexport const MiddleMouseButton = 2\nexport const RightMouseButton = 3\n","/**\n * @file Mouse Observer\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector2 } from 'three'\nimport { Signal } from 'signals'\n\nimport { LeftMouseButton, RightMouseButton } from '../constants'\nimport { defaults } from '../utils'\nimport Viewer from '../viewer/viewer'\nimport MouseControls from '../controls/mouse-controls'\n\ntype Optional = Pick, K> & Omit;\n\n/**\n * @example\n * mouseObserver.signals.scrolled.add( function( delta ){ ... } );\n *\n * @typedef {Object} MouseSignals\n * @property {Signal} moved - on move: deltaX, deltaY\n * @property {Signal} scrolled - on scroll: delta\n * @property {Signal} dragged - on drag: deltaX, deltaY\n * @property {Signal} dropped - on drop\n * @property {Signal} clicked - on click\n * @property {Signal} hovered - on hover\n */\n\nfunction getTouchDistance (event: TouchEvent) {\n const dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX\n const dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY\n return Math.sqrt(dx * dx + dy * dy)\n}\n\nfunction getMouseButtons (event: MouseEvent) {\n if (typeof event === 'object') {\n if ('buttons' in event) {\n return event.buttons\n } else if ('which' in event as any) {\n const b = (event as any).which\n if (b === 2) {\n return 4\n } else if (b === 3) {\n return 2\n } else if (b > 0) {\n return 1 << (b - 1)\n }\n } else if ('button' in event as any) {\n const b = (event as any).button\n if (b === 1) {\n return 4\n } else if (b === 2) {\n return 2\n } else if (b >= 0) {\n return 1 << b\n }\n }\n }\n return 0\n}\n\nexport interface MouseSignals {\n moved: Signal // on move: deltaX, deltaY\n scrolled: Signal // on scroll: delta\n dragged: Signal // on drag: deltaX, deltaY\n dropped: Signal // on drop\n clicked: Signal // on click\n hovered: Signal // on hover\n doubleClicked: Signal\n}\n\nexport interface MouseParams {\n hoverTimeout?: number\n handleScroll?:boolean\n doubleClickSpeed?: number\n}\n\n/**\n * Mouse observer\n *\n * @example\n * // listen to mouse moving (and touch-moving) events\n * mouseObserver.moved.moved.add( function( deltaX, deltaY ){ ... } );\n *\n * @example\n * // listen to scrolling (and pinching) events\n * mouseObserver.signals.scrolled.add( function( delta ){ ... } );\n *\n * @example\n * // listen to dragging (and touch-dragging) events\n * mouseObserver.signals.dragged.add( function( deltaX, deltaY ){ ... } );\n *\n * @example\n * // listen to clicking (and tapping) events\n * mouseObserver.signals.clicked.add( function(){ ... } );\n *\n * @example\n * // listen to double clicking (and double tapping) events\n * mouseObserver.signals.doubleClicked.add( function(){ ... } );\n *\n * @example\n * // listen to hovering events\n * mouseObserver.signals.hovered.add( function(){ ... } );\n */\nclass MouseObserver {\n signals: MouseSignals = {\n moved: new Signal(),\n scrolled: new Signal(),\n dragged: new Signal(),\n dropped: new Signal(),\n clicked: new Signal(),\n hovered: new Signal(),\n doubleClicked: new Signal()\n }\n\n hoverTimeout: number\n handleScroll:boolean\n doubleClickSpeed: number\n\n viewer: Viewer\n mouse: MouseObserver\n controls: MouseControls\n\n position = new Vector2() // Position on page\n prevPosition = new Vector2() // Previous position on page\n down = new Vector2() // Position on page when clicked\n canvasPosition = new Vector2() // Position on dom element\n prevClickCP = new Vector2()\n\n moving = false // Flag indicating if the mouse is moving\n hovering = true // Flag indicating if the mouse is hovering\n scrolled = false // Flag indicating if there was a scolling event since the last mouse move\n lastMoved = Infinity // Timestamp of last mouse move\n which? = 0 // 0: No button; 1: Left button; 2: Middle button; 3: Right button\n buttons? = 0 // 0: No button; 1: Left button; 2: Right button; 4: Middle button\n pressed? = false // Flag indicating if the mouse is pressed down\n altKey = false // Flag indicating if the alt key is pressed\n ctrlKey = false // Flag indicating if the ctrl key is pressed\n metaKey = false // Flag indicating if the meta key is pressed\n shiftKey = false // Flag indicating if the shift key is pressed\n\n doubleClickPending: boolean\n lastClicked: number\n overElement: boolean\n lastTouchDistance: number\n private frameRequest: number\n\n /**\n * @param {Element} domElement - the dom element to observe mouse events in\n * @param {Object} params - parameters object\n * @param {Integer} params.hoverTimeout - timeout in ms until the {@link MouseSignals.hovered}\n * signal is fired, set to -1 to ignore hovering\n * @param {Boolean} params.handleScroll - whether or not to handle scroll events\n * @param {Integer} params.doubleClickSpeed - max time in ms to trigger double click\n */\n constructor (readonly domElement: HTMLCanvasElement, params: MouseParams = {}) {\n this.domElement.style.touchAction = 'none'\n\n this.hoverTimeout = defaults(params.hoverTimeout, 50)\n this.handleScroll = defaults(params.handleScroll, true)\n this.doubleClickSpeed = defaults(params.doubleClickSpeed, 500)\n\n this._listen = this._listen.bind(this)\n this._onMousewheel = this._onMousewheel.bind(this)\n this._onMousemove = this._onMousemove.bind(this)\n this._onMousedown = this._onMousedown.bind(this)\n this._onMouseup = this._onMouseup.bind(this)\n this._onContextmenu = this._onContextmenu.bind(this)\n this._onTouchstart = this._onTouchstart.bind(this)\n this._onTouchend = this._onTouchend.bind(this)\n this._onTouchmove = this._onTouchmove.bind(this)\n\n this._listen()\n\n const opt = { passive: false } // treat as 'passive' so preventDefault can be called\n document.addEventListener('mousewheel', this._onMousewheel, opt)\n document.addEventListener('wheel', this._onMousewheel, opt)\n document.addEventListener('MozMousePixelScroll', this._onMousewheel, opt)\n document.addEventListener('mousemove', this._onMousemove, opt)\n document.addEventListener('mousedown', this._onMousedown, opt)\n document.addEventListener('mouseup', this._onMouseup, opt)\n document.addEventListener('contextmenu', this._onContextmenu, opt)\n document.addEventListener('touchstart', this._onTouchstart, opt)\n document.addEventListener('touchend', this._onTouchend, opt)\n document.addEventListener('touchmove', this._onTouchmove, opt)\n }\n\n get key () {\n let key = 0\n if (this.altKey) key += 1\n if (this.ctrlKey) key += 2\n if (this.metaKey) key += 4\n if (this.shiftKey) key += 8\n return key\n }\n\n setParameters (params: MouseParams = {}) {\n this.hoverTimeout = defaults(params.hoverTimeout, this.hoverTimeout)\n }\n\n /**\n * listen to mouse actions\n * @emits {MouseSignals.clicked} when clicked\n * @emits {MouseSignals.hovered} when hovered\n * @return {undefined}\n */\n _listen () {\n const now = window.performance.now()\n const cp = this.canvasPosition\n if (this.doubleClickPending && now - this.lastClicked > this.doubleClickSpeed) {\n this.doubleClickPending = false\n }\n if (now - this.lastMoved > this.hoverTimeout) {\n this.moving = false\n }\n if (this.scrolled || (!this.moving && !this.hovering)) {\n this.scrolled = false\n if (this.hoverTimeout !== -1 && this.overElement) {\n this.hovering = true\n this.signals.hovered.dispatch(cp.x, cp.y)\n }\n }\n this.frameRequest = window.requestAnimationFrame(this._listen)\n }\n\n /**\n * handle mouse scroll\n * @emits {MouseSignals.scrolled} when scrolled\n * @param {Event} event - mouse event\n * @return {undefined}\n */\n _onMousewheel(event: Optional & { wheelDelta?: number, wheelDeltaY?: number }) {\n if (event.target !== this.domElement || !this.handleScroll) {\n return\n }\n event.preventDefault()\n this._setKeys(event as any)\n\n let delta = 0\n // This has to be written in a particular way to handle old browsers that\n // all send events with different properties set in different ways.\n if ('deltaY' in event && 'deltaMode' in event &&\n event.deltaY !== undefined && event.deltaMode !== undefined) {\n // all modern browsers, using WheelEvent; deltaY + down (toward user)\n if (event.deltaMode === WheelEvent.DOM_DELTA_PIXEL)\n // everything except Firefox: normally 100 per wheel click\n delta = -event.deltaY * (2.5 / 100.0)\n else if (event.deltaMode === WheelEvent.DOM_DELTA_LINE)\n // Firefox in line mode, normally 3 per wheel click\n delta = -event.deltaY * (2.5 / 3.0)\n else // page mode: 1 per wheel click\n delta = -event.deltaY * 2.5\n } else if ('deltaY' in event && !('detail' in event)) {\n // Old Firefox or IE 11: deltaY but no deltaMode; treat as pixels\n delta = -event.deltaY * (2.5 / 100.0)\n } else if (event.wheelDelta !== undefined) {\n delta = -event.wheelDelta * (2.5 / 100)\n } else if (event.wheelDeltaY !== undefined) {\n delta = -event.wheelDeltaY * (2.5 / 100)\n } else if (event.detail !== undefined){\n // Old Firefox, MouseWheelEvent\n delta = -event.detail / 3\n }\n this.signals.scrolled.dispatch(delta)\n\n setTimeout(() => {\n this.scrolled = true\n }, this.hoverTimeout)\n }\n\n /**\n * handle mouse move\n * @emits {MouseSignals.moved} when moved\n * @emits {MouseSignals.dragged} when dragged\n * @param {Event} event - mouse event\n * @return {undefined}\n */\n _onMousemove (event: MouseEvent) {\n if (event.target === this.domElement) {\n event.preventDefault()\n this.overElement = true\n } else {\n this.overElement = false\n }\n this._setKeys(event)\n this.moving = true\n this.hovering = false\n this.lastMoved = window.performance.now()\n this.prevPosition.copy(this.position)\n this.position.set(event.clientX, event.clientY)\n this._setCanvasPosition(event)\n const dx = this.prevPosition.x - this.position.x\n const dy = this.prevPosition.y - this.position.y\n this.signals.moved.dispatch(dx, dy)\n if (this.pressed) {\n this.signals.dragged.dispatch(dx, dy)\n }\n }\n\n _onMousedown (event: MouseEvent) {\n if (event.target !== this.domElement) {\n return\n }\n event.preventDefault()\n this._setKeys(event)\n this.moving = false\n this.hovering = false\n this.down.set(event.clientX, event.clientY)\n this.position.set(event.clientX, event.clientY)\n this.which = event.which\n this.buttons = getMouseButtons(event)\n this.pressed = true\n this._setCanvasPosition(event)\n }\n\n /**\n * handle mouse up\n * @emits {MouseSignals.doubleClicked} when double clicked\n * @emits {MouseSignals.dropped} when dropped\n * @param {Event} event - mouse event\n * @return {undefined}\n */\n _onMouseup (event: MouseEvent) {\n if (event.target === this.domElement) {\n event.preventDefault()\n }\n this._setKeys(event)\n const cp = this.canvasPosition\n if (this._distance() < 4) {\n this.lastClicked = window.performance.now()\n if (this.doubleClickPending && this.prevClickCP.distanceTo(cp) < 4) {\n this.signals.doubleClicked.dispatch(cp.x, cp.y)\n this.doubleClickPending = false\n }\n this.signals.clicked.dispatch(cp.x, cp.y)\n this.doubleClickPending = true\n this.prevClickCP.copy(cp)\n }\n this.which = undefined\n this.buttons = undefined\n this.pressed = undefined\n // if (this._distance() > 3 || event.which === RightMouseButton) {\n // this.signals.dropped.dispatch();\n // }\n }\n\n _onContextmenu (event: MouseEvent) {\n if (event.target === this.domElement) {\n event.preventDefault()\n }\n }\n\n _onTouchstart (event: TouchEvent) {\n if (event.target !== this.domElement) {\n return\n }\n event.preventDefault()\n this.pressed = true\n switch (event.touches.length) {\n case 1: {\n this.moving = false\n this.hovering = false\n this.down.set(\n event.touches[ 0 ].pageX,\n event.touches[ 0 ].pageY\n )\n this.position.set(\n event.touches[ 0 ].pageX,\n event.touches[ 0 ].pageY\n )\n this._setCanvasPosition(event.touches[ 0 ])\n break\n }\n\n case 2: {\n this.down.set(\n (event.touches[ 0 ].pageX + event.touches[ 1 ].pageX) / 2,\n (event.touches[ 0 ].pageY + event.touches[ 1 ].pageY) / 2\n )\n this.position.set(\n (event.touches[ 0 ].pageX + event.touches[ 1 ].pageX) / 2,\n (event.touches[ 0 ].pageY + event.touches[ 1 ].pageY) / 2\n )\n this.lastTouchDistance = getTouchDistance(event)\n }\n }\n }\n\n _onTouchend (event: TouchEvent) {\n if (event.target === this.domElement) {\n event.preventDefault()\n }\n this.which = undefined\n this.buttons = undefined\n this.pressed = undefined\n }\n\n _onTouchmove (event: TouchEvent) {\n if (event.target === this.domElement) {\n event.preventDefault()\n this.overElement = true\n } else {\n this.overElement = false\n }\n switch (event.touches.length) {\n case 1: {\n this._setKeys(event)\n this.which = LeftMouseButton\n this.buttons = 1\n this.moving = true\n this.hovering = false\n this.lastMoved = window.performance.now()\n this.prevPosition.copy(this.position)\n this.position.set(\n event.touches[ 0 ].pageX,\n event.touches[ 0 ].pageY\n )\n this._setCanvasPosition(event.touches[ 0 ])\n const dx = this.prevPosition.x - this.position.x\n const dy = this.prevPosition.y - this.position.y\n this.signals.moved.dispatch(dx, dy)\n if (this.pressed) {\n this.signals.dragged.dispatch(dx, dy)\n }\n break\n }\n\n case 2: {\n const touchDistance = getTouchDistance(event)\n const delta = touchDistance - this.lastTouchDistance\n this.lastTouchDistance = touchDistance\n this.prevPosition.copy(this.position)\n this.position.set(\n (event.touches[ 0 ].pageX + event.touches[ 1 ].pageX) / 2,\n (event.touches[ 0 ].pageY + event.touches[ 1 ].pageY) / 2\n )\n if (Math.abs(delta) > 2 && this.handleScroll &&\n this.position.distanceTo(this.prevPosition) < 2\n ) {\n this.which = 0\n this.buttons = 0\n this.signals.scrolled.dispatch(delta / 2)\n } else {\n this.which = RightMouseButton\n this.buttons = 2\n const dx = this.prevPosition.x - this.position.x\n const dy = this.prevPosition.y - this.position.y\n this.signals.moved.dispatch(dx, dy)\n if (this.pressed) {\n this.signals.dragged.dispatch(dx, dy)\n }\n }\n }\n }\n }\n\n _distance () {\n return this.position.distanceTo(this.down)\n }\n\n _setCanvasPosition (event: any) { // TODO\n const box = this.domElement.getBoundingClientRect()\n let offsetX, offsetY;\n if ('clientX' in event && 'clientY' in event) {\n offsetX = event.clientX - box.left\n offsetY = event.clientY - box.top\n } else {\n offsetX = event.offsetX\n offsetY = event.offsetY\n }\n this.canvasPosition.set(offsetX, box.height - offsetY)\n }\n\n _setKeys (event: MouseEvent|TouchEvent) {\n this.altKey = event.altKey\n this.ctrlKey = event.ctrlKey\n this.metaKey = event.metaKey\n this.shiftKey = event.shiftKey\n }\n\n dispose () {\n document.removeEventListener('mousewheel', this._onMousewheel)\n document.removeEventListener('wheel', this._onMousewheel)\n document.removeEventListener('MozMousePixelScroll', this._onMousewheel)\n document.removeEventListener('mousemove', this._onMousemove)\n document.removeEventListener('mousedown', this._onMousedown)\n document.removeEventListener('mouseup', this._onMouseup)\n document.removeEventListener('contextmenu', this._onContextmenu)\n document.removeEventListener('touchstart', this._onTouchstart)\n document.removeEventListener('touchend', this._onTouchend)\n document.removeEventListener('touchmove', this._onTouchmove)\n window.cancelAnimationFrame(this.frameRequest)\n }\n}\n\nexport default MouseObserver\n","/**\n * @file Trackball Controls\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Matrix4, Quaternion } from 'three'\n\nimport { defaults } from '../utils'\nimport Stage from '../stage/stage'\nimport MouseObserver from '../stage/mouse-observer'\nimport Viewer from '../viewer/viewer'\nimport ViewerControls from './viewer-controls'\nimport AtomProxy from '../proxy/atom-proxy';\nimport Component from '../component/component';\n\nconst tmpRotateXMatrix = new Matrix4()\nconst tmpRotateYMatrix = new Matrix4()\nconst tmpRotateZMatrix = new Matrix4()\nconst tmpRotateMatrix = new Matrix4()\nconst tmpRotateCameraMatrix = new Matrix4()\nconst tmpRotateVector = new Vector3()\nconst tmpRotateQuaternion = new Quaternion()\nconst tmpRotateQuaternion2 = new Quaternion()\nconst tmpPanMatrix = new Matrix4()\nconst tmpPanVector = new Vector3()\nconst tmpAtomVector = new Vector3()\n\nexport interface TrackballControlsParams {\n rotateSpeed?: number\n zoomSpeed?: number\n panSpeed?: number\n}\n\n/**\n * Trackball controls\n */\nclass TrackballControls {\n viewer: Viewer\n mouse: MouseObserver\n controls: ViewerControls\n\n rotateSpeed: number\n zoomSpeed: number\n panSpeed: number\n\n constructor (readonly stage: Stage, params: TrackballControlsParams = {}) {\n this.rotateSpeed = defaults(params.rotateSpeed, 2.0)\n this.zoomSpeed = defaults(params.zoomSpeed, 1.2)\n this.panSpeed = defaults(params.panSpeed, 1.0)\n\n this.viewer = stage.viewer\n this.mouse = stage.mouseObserver\n this.controls = stage.viewerControls\n }\n\n get component (): Component|undefined {\n return this.stage.transformComponent\n }\n\n get atom (): AtomProxy|undefined {\n return this.stage.transformAtom\n }\n\n private _setPanVector (x: number, y: number, z = 0) {\n const scaleFactor = this.controls.getCanvasScaleFactor(z)\n tmpPanVector.set(x, y, 0)\n tmpPanVector.multiplyScalar(this.panSpeed * scaleFactor)\n }\n\n private _getRotateXY (x: number, y: number) {\n return [\n this.rotateSpeed * -x * 0.01,\n this.rotateSpeed * y * 0.01\n ]\n }\n\n private _getCameraRotation(m: Matrix4) {\n m.extractRotation(this.viewer.camera.matrixWorld)\n m.multiply(tmpRotateYMatrix.makeRotationY(Math.PI))\n\n return m\n }\n\n private _transformPanVector () {\n if (!this.component) return\n\n // Adjust for component and scene rotation\n tmpPanMatrix.extractRotation(this.component.transform)\n tmpPanMatrix.premultiply(this.viewer.rotationGroup.matrix)\n tmpPanMatrix.getInverse(tmpPanMatrix)\n\n // Adjust for camera rotation\n tmpPanMatrix.multiply(this._getCameraRotation(tmpRotateMatrix))\n\n tmpPanVector.applyMatrix4(tmpPanMatrix)\n }\n\n zoom (delta: number) {\n this.controls.zoom(this.zoomSpeed * delta * 0.02)\n }\n\n pan (x: number, y: number) {\n this._setPanVector(x, y)\n\n // Adjust for scene rotation\n tmpPanMatrix.getInverse(this.viewer.rotationGroup.matrix)\n\n // Adjust for camera rotation\n tmpPanMatrix.multiply(this._getCameraRotation(tmpRotateMatrix))\n\n tmpPanVector.applyMatrix4(tmpPanMatrix)\n this.controls.translate(tmpPanVector)\n }\n\n panComponent (x: number, y: number) {\n if (!this.component) return\n\n this._setPanVector(x, y)\n this._transformPanVector()\n\n this.component.position.add(tmpPanVector)\n this.component.updateMatrix()\n }\n\n panAtom (x: number, y: number) {\n if (!this.atom || !this.component) return\n\n this.atom.positionToVector3(tmpAtomVector)\n tmpAtomVector.add(this.viewer.translationGroup.position)\n tmpAtomVector.applyMatrix4(this.viewer.rotationGroup.matrix)\n\n this._setPanVector(x, y, tmpAtomVector.z)\n this._transformPanVector()\n\n this.atom.positionAdd(tmpPanVector)\n this.component.updateRepresentations({ 'position': true })\n }\n\n rotate (x: number, y: number) {\n const [ dx, dy ] = this._getRotateXY(x, y)\n\n // rotate around screen X then screen Y\n this._getCameraRotation(tmpRotateMatrix)\n tmpRotateVector.set(1, 0, 0) // X axis\n tmpRotateVector.applyMatrix4(tmpRotateMatrix) // screen X\n tmpRotateQuaternion.setFromAxisAngle(tmpRotateVector, dy)\n\n tmpRotateVector.set(0, 1, 0) // Y axis\n tmpRotateVector.applyMatrix4(tmpRotateMatrix) // screen Y\n tmpRotateQuaternion2.setFromAxisAngle(tmpRotateVector, dx)\n\n tmpRotateQuaternion.multiply(tmpRotateQuaternion2)\n tmpRotateMatrix.makeRotationFromQuaternion(tmpRotateQuaternion)\n this.controls.applyMatrix(tmpRotateMatrix)\n }\n\n zRotate (x: number, y: number) {\n const dz = this.rotateSpeed * ((-x + y) / -2) * 0.01\n\n tmpRotateZMatrix.makeRotationZ(dz)\n this.controls.applyMatrix(tmpRotateZMatrix)\n }\n\n rotateComponent (x: number, y: number) {\n if (!this.component) return\n\n const [ dx, dy ] = this._getRotateXY(x, y)\n\n this._getCameraRotation(tmpRotateCameraMatrix)\n\n tmpRotateMatrix.extractRotation(this.component.transform)\n tmpRotateMatrix.premultiply(this.viewer.rotationGroup.matrix)\n tmpRotateMatrix.getInverse(tmpRotateMatrix)\n tmpRotateMatrix.premultiply(tmpRotateCameraMatrix)\n\n tmpRotateVector.set(1, 0, 0)\n tmpRotateVector.applyMatrix4(tmpRotateMatrix)\n tmpRotateXMatrix.makeRotationAxis(tmpRotateVector, dy)\n\n tmpRotateVector.set(0, 1, 0)\n tmpRotateVector.applyMatrix4(tmpRotateMatrix)\n tmpRotateYMatrix.makeRotationAxis(tmpRotateVector, dx)\n\n tmpRotateXMatrix.multiply(tmpRotateYMatrix)\n tmpRotateQuaternion.setFromRotationMatrix(tmpRotateXMatrix)\n this.component.quaternion.premultiply(tmpRotateQuaternion)\n this.component.quaternion.normalize()\n this.component.updateMatrix()\n }\n}\n\nexport default TrackballControls\n","/**\n * @file Picking Proxy\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Matrix4, Vector2 } from 'three'\n\nimport Stage from '../stage/stage'\nimport StructureComponent from '../component/structure-component'\nimport MouseObserver from '../stage/mouse-observer'\nimport { Picker } from '../utils/picker'\nimport ViewerControls from './viewer-controls'\nimport Shape from '../geometry/shape'\nimport Structure from '../structure/structure'\nimport BondProxy from '../proxy/bond-proxy'\nimport AtomProxy from '../proxy/atom-proxy'\nimport Surface from '../surface/surface'\nimport Volume from '../surface/volume'\nimport Unitcell from '../symmetry/unitcell'\nimport Component from '../component/component';\n\nconst tmpVec = new Vector3()\n\nexport interface ShapePrimitive {\n name: string\n shape: Shape\n}\n\nfunction closer (x: Vector3, a: Vector3, b: Vector3) {\n return x.distanceTo(a) < x.distanceTo(b)\n}\n\n/**\n * Picking data object.\n * @typedef {Object} PickingData - picking data\n * @property {Number} [pid] - picking id\n * @property {Object} [instance] - instance data\n * @property {Integer} instance.id - instance id\n * @property {String|Integer} instance.name - instance name\n * @property {Matrix4} instance.matrix - transformation matrix of the instance\n * @property {Picker} [picker] - picker object\n */\n\nexport interface InstanceData {\n id: number\n name: number|string\n matrix: Matrix4\n}\n\nexport interface PickingData {\n pid: number\n instance: InstanceData\n picker: Picker\n}\n\n/**\n * Picking proxy class.\n */\nclass PickingProxy {\n pid: number\n picker: Picker\n instance: InstanceData\n controls: ViewerControls\n mouse: MouseObserver\n\n /**\n * Create picking proxy object\n * @param {PickingData} pickingData - picking data\n * @param {Stage} stage - stage object\n */\n constructor (pickingData: PickingData, readonly stage: Stage) {\n this.pid = pickingData.pid\n this.picker = pickingData.picker\n\n /**\n * @type {Object}\n */\n this.instance = pickingData.instance\n\n /**\n * @type {Stage}\n */\n this.stage = stage\n /**\n * @type {ViewerControls}\n */\n this.controls = stage.viewerControls\n /**\n * @type {MouseObserver}\n */\n this.mouse = stage.mouseObserver\n }\n\n /**\n * Kind of the picked data\n * @type {String}\n */\n get type () { return this.picker.type }\n\n /**\n * If the `alt` key was pressed\n * @type {Boolean}\n */\n get altKey () { return this.mouse.altKey }\n /**\n * If the `ctrl` key was pressed\n * @type {Boolean}\n */\n get ctrlKey () { return this.mouse.ctrlKey }\n /**\n * If the `meta` key was pressed\n * @type {Boolean}\n */\n get metaKey () { return this.mouse.metaKey }\n /**\n * If the `shift` key was pressed\n * @type {Boolean}\n */\n get shiftKey () { return this.mouse.shiftKey }\n\n /**\n * Position of the mouse on the canvas\n * @type {Vector2}\n */\n get canvasPosition (): Vector2 { return this.mouse.canvasPosition }\n\n /**\n * The component the picked data is part of\n * @type {Component}\n */\n get component (): Component {\n return this.stage.getComponentsByObject(this.picker.data as any).list[ 0 ] // TODO\n }\n\n /**\n * The picked object data\n * @type {Object}\n */\n get object () {\n return this.picker.getObject(this.pid)\n }\n\n /**\n * The 3d position in the scene of the picked object\n * @type {Vector3}\n */\n get position () {\n return this.picker.getPosition(this.pid, this.instance, this.component)\n }\n\n /**\n * The atom of a picked bond that is closest to the mouse\n * @type {AtomProxy}\n */\n get closestBondAtom (): AtomProxy|undefined {\n if (this.type !== 'bond' || !this.bond) return undefined\n\n const bond = this.bond\n const controls = this.controls\n const cp = this.canvasPosition\n\n const v1 = bond.atom1.positionToVector3()\n const v2 = bond.atom2.positionToVector3()\n\n v1.applyMatrix4(this.component.matrix)\n v2.applyMatrix4(this.component.matrix)\n\n const acp1 = controls.getPositionOnCanvas(v1)\n const acp2 = controls.getPositionOnCanvas(v2)\n\n return closer(cp as any, acp1, acp2) ? bond.atom1 : bond.atom2\n }\n\n /**\n * Close-by atom\n * @type {AtomProxy}\n */\n get closeAtom (): AtomProxy|undefined {\n const cp = this.canvasPosition\n const ca = this.closestBondAtom\n if (!ca) return undefined\n\n const v = ca.positionToVector3().applyMatrix4(this.component.matrix)\n\n const acp = this.controls.getPositionOnCanvas(v)\n\n ca.positionToVector3(tmpVec)\n if (this.instance) tmpVec.applyMatrix4(this.instance.matrix)\n tmpVec.applyMatrix4(this.component.matrix)\n const viewer = this.controls.viewer\n tmpVec.add(viewer.translationGroup.position)\n tmpVec.applyMatrix4(viewer.rotationGroup.matrix)\n\n const scaleFactor = this.controls.getCanvasScaleFactor(tmpVec.z)\n const sc = this.component as StructureComponent\n const radius = sc.getMaxRepresentationRadius(ca.index)\n //console.log(scaleFactor, cp.distanceTo(acp), radius/scaleFactor, radius)\n\n if (cp.distanceTo(acp) <= radius/scaleFactor) {\n return ca\n } else {\n return undefined\n }\n }\n\n /**\n * @type {Object}\n */\n get arrow () { return this._objectIfType('arrow') as ShapePrimitive }\n /**\n * @type {AtomProxy}\n */\n get atom () { return this._objectIfType('atom') as AtomProxy }\n /**\n * @type {Object}\n */\n get axes () { return this._objectIfType('axes') }\n /**\n * @type {BondProxy}\n */\n get bond () { return this._objectIfType('bond') as BondProxy }\n /**\n * @type {Object}\n */\n get box () { return this._objectIfType('box') as ShapePrimitive }\n /**\n * @type {Object}\n */\n get cone () { return this._objectIfType('cone') as ShapePrimitive }\n /**\n * @type {Object}\n */\n get clash () { return this._objectIfType('clash') as { clash: { sele1: string, sele2: string } } }\n /**\n * @type {BondProxy}\n */\n get contact () { return this._objectIfType('contact') as { type: string, atom1: AtomProxy, atom2: AtomProxy } }\n /**\n * @type {Object}\n */\n get cylinder () { return this._objectIfType('cylinder') as ShapePrimitive }\n /**\n * @type {BondProxy}\n */\n get distance () { return this._objectIfType('distance') as BondProxy }\n /**\n * @type {Object}\n */\n get ellipsoid () { return this._objectIfType('ellipsoid') as ShapePrimitive }\n /**\n * @type {Object}\n */\n get octahedron () { return this._objectIfType('octahedron') as ShapePrimitive }\n /**\n * @type {Object}\n */\n get point () { return this._objectIfType('point') as ShapePrimitive }\n /**\n * @type {Object}\n */\n get mesh () { return this._objectIfType('mesh') as { name: string, shape: Shape, serial: number } }\n /**\n * @type {Object}\n */\n get slice () { return this._objectIfType('slice') as { volume: Volume, value: number } }\n /**\n * @type {Object}\n */\n get sphere () { return this._objectIfType('sphere') as ShapePrimitive }\n /**\n * @type {Object}\n */\n get tetrahedron () { return this._objectIfType('tetrahedron') as ShapePrimitive }\n /**\n * @type {Object}\n */\n get torus () { return this._objectIfType('torus') as ShapePrimitive }\n /**\n * @type {Object}\n */\n get surface () { return this._objectIfType('surface') as { surface: Surface, index: number } }\n /**\n * @type {Object}\n */\n get unitcell () { return this._objectIfType('unitcell') as { unitcell: Unitcell, structure: Structure } }\n /**\n * @type {Object}\n */\n get unknown () { return this._objectIfType('unknown') }\n /**\n * @type {Object}\n */\n get volume () { return this._objectIfType('volume') as { volume: Volume, value: number } }\n /**\n * @type {Object}\n */\n get wideline () { return this._objectIfType('wideline') as ShapePrimitive }\n\n _objectIfType (type: string) {\n return this.type === type ? this.object : undefined\n }\n\n getLabel () {\n const atom = this.atom || this.closeAtom\n let msg = 'nothing'\n if (this.arrow) {\n msg = this.arrow.name\n } else if (atom) {\n msg = `atom: ${atom.qualifiedName()} (${atom.structure.name})`\n } else if (this.axes) {\n msg = 'axes'\n } else if (this.bond) {\n msg = `bond: ${this.bond.atom1.qualifiedName()} - ${this.bond.atom2.qualifiedName()} (${this.bond.structure.name})`\n } else if (this.box) {\n msg = this.box.name\n } else if (this.cone) {\n msg = this.cone.name\n } else if (this.clash) {\n msg = `clash: ${this.clash.clash.sele1} - ${this.clash.clash.sele2}`\n } else if (this.contact) {\n msg = `${this.contact.type}: ${this.contact.atom1.qualifiedName()} - ${this.contact.atom2.qualifiedName()} (${this.contact.atom1.structure.name})`\n } else if (this.cylinder) {\n msg = this.cylinder.name\n } else if (this.distance) {\n msg = `distance: ${this.distance.atom1.qualifiedName()} - ${this.distance.atom2.qualifiedName()} (${this.distance.structure.name})`\n } else if (this.ellipsoid) {\n msg = this.ellipsoid.name\n } else if (this.octahedron) {\n msg = this.octahedron.name\n } else if (this.point) {\n msg = this.point.name\n } else if (this.mesh) {\n msg = `mesh: ${this.mesh.name || this.mesh.serial} (${this.mesh.shape.name})`\n } else if (this.slice) {\n msg = `slice: ${this.slice.value.toPrecision(3)} (${this.slice.volume.name})`\n } else if (this.sphere) {\n msg = this.sphere.name\n } else if (this.surface) {\n msg = `surface: ${this.surface.surface.name}`\n } else if (this.tetrahedron) {\n msg = this.tetrahedron.name\n } else if (this.torus) {\n msg = this.torus.name\n } else if (this.unitcell) {\n msg = `unitcell: ${this.unitcell.unitcell.spacegroup} (${this.unitcell.structure.name})`\n } else if (this.unknown) {\n msg = 'unknown'\n } else if (this.volume) {\n msg = `volume: ${this.volume.value.toPrecision(3)} (${this.volume.volume.name})`\n } else if (this.wideline) {\n msg = this.wideline.name\n }\n return msg\n }\n}\n\nexport default PickingProxy\n","/**\n * @file Picking Controls\n * @author Alexander Rose \n * @private\n */\n\nimport PickingProxy from './picking-proxy'\nimport Stage from '../stage/stage'\nimport Viewer from '../viewer/viewer'\n\n/**\n * Picking controls\n */\nclass PickingControls {\n viewer: Viewer\n\n constructor (readonly stage: Stage) {\n this.viewer = stage.viewer\n }\n\n /**\n * get picking data\n * @param {Number} x - canvas x coordinate\n * @param {Number} y - canvas y coordinate\n * @return {PickingProxy|undefined} picking proxy\n */\n pick (x: number, y: number) {\n const pickingData = this.viewer.pick(x, y)\n\n if (pickingData.picker &&\n pickingData.picker.type !== 'ignore' &&\n pickingData.pid !== undefined\n ) {\n const pickerArray = pickingData.picker.array\n if (pickerArray && pickingData.pid >= pickerArray.length) {\n console.error('pid >= picker.array.length')\n } else {\n return new PickingProxy(pickingData, this.stage)\n }\n }\n }\n}\n\nexport default PickingControls\n","/**\n * @file Viewer Controls\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector2, Vector3, Matrix4, Quaternion, OrthographicCamera } from 'three'\nimport * as signalsWrapper from 'signals'\n\nimport {\n ensureVector2, ensureVector3, ensureMatrix4, ensureQuaternion\n} from '../utils'\nimport { degToRad } from '../math/math-utils'\nimport Stage from '../stage/stage'\nimport Viewer from '../viewer/viewer'\n\n/**\n * Orientation matrix, a 4x4 transformation matrix with rotation part\n * used for scene rotation, scale part for scene camera distance and\n * position part for scene translation\n * @typedef {Matrix4} OrientationMatrix - orientation matrix\n */\n\nconst tmpQ = new Quaternion()\nconst tmpP = new Vector3()\nconst tmpS = new Vector3()\n\nconst tmpCanvasVector = new Vector3()\nconst tmpScaleVector = new Vector3()\nconst tmpRotateMatrix = new Matrix4()\nconst tmpRotateVector = new Vector3()\nconst tmpAlignMatrix = new Matrix4()\n\n/**\n * Viewer controls\n */\nclass ViewerControls {\n signals = {\n changed: new signalsWrapper.Signal()\n }\n\n viewer: Viewer\n\n /**\n * @param {Stage} stage - the stage object\n */\n constructor (readonly stage: Stage) {\n this.viewer = stage.viewer\n }\n\n /**\n * scene center position\n * @type {Vector3}\n */\n get position () {\n return this.viewer.translationGroup.position\n }\n\n /**\n * scene rotation\n * @type {Quaternion}\n */\n get rotation () {\n return this.viewer.rotationGroup.quaternion\n }\n\n /**\n * Trigger render and emit changed event\n * @emits {ViewerControls.signals.changed}\n * @return {undefined}\n */\n changed () {\n this.viewer.requestRender()\n this.signals.changed.dispatch()\n }\n\n getPositionOnCanvas (position: Vector3, optionalTarget?: Vector2) {\n const canvasPosition = ensureVector2(optionalTarget)\n const viewer = this.viewer\n\n tmpCanvasVector.copy(position)\n .add(viewer.translationGroup.position)\n .applyMatrix4(viewer.rotationGroup.matrix)\n .project(viewer.camera)\n\n return canvasPosition.set(\n (tmpCanvasVector.x + 1) * viewer.width / 2,\n (tmpCanvasVector.y + 1) * viewer.height / 2\n )\n }\n\n getCanvasScaleFactor (z = 0) {\n const camera = this.viewer.camera\n if (camera instanceof OrthographicCamera) {\n return 1 / camera.zoom\n } else {\n z = Math.abs(z)\n z += this.getCameraDistance()\n const fov = degToRad(camera.fov)\n const unitHeight = 2.0 * z * Math.tan(fov / 2)\n return unitHeight / this.viewer.height\n }\n }\n\n /**\n * get scene orientation\n * @param {Matrix4} optionalTarget - pre-allocated target matrix\n * @return {OrientationMatrix} scene orientation\n */\n getOrientation (optionalTarget?: Matrix4) {\n const m = ensureMatrix4(optionalTarget)\n\n m.copy(this.viewer.rotationGroup.matrix)\n const z = this.getCameraDistance()\n m.scale(tmpScaleVector.set(z, z, z))\n m.setPosition(this.viewer.translationGroup.position)\n\n return m\n }\n\n /**\n * set scene orientation\n * @param {OrientationMatrix|Array} orientation - scene orientation\n * @return {undefined}\n */\n orient (orientation?: Matrix4) {\n ensureMatrix4(orientation).decompose(tmpP, tmpQ, tmpS)\n\n const v = this.viewer\n v.rotationGroup.setRotationFromQuaternion(tmpQ)\n v.translationGroup.position.copy(tmpP)\n v.cameraDistance = tmpS.z\n v.updateZoom()\n this.changed()\n }\n\n /**\n * translate scene\n * @param {Vector3|Array} vector - translation vector\n * @return {undefined}\n */\n translate (vector: Vector3|number[]) {\n this.viewer.translationGroup.position\n .add(ensureVector3(vector))\n this.changed()\n }\n\n /**\n * center scene\n * @param {Vector3|Array} position - center position\n * @return {undefined}\n */\n center (position: Vector3|number[]) {\n this.viewer.translationGroup.position\n .copy(ensureVector3(position)).negate()\n this.changed()\n }\n\n /**\n * \"zoom\" scene by moving camera closer to origin\n * @param {Number} delta - zoom change\n * @return {undefined}\n */\n zoom (delta: number) {\n this.distance(this.getCameraDistance() * (1 - delta))\n }\n\n /**\n * get camera distance\n */\n getCameraDistance(): number {\n return this.viewer.cameraDistance\n }\n\n /**\n * camera distance\n * @param {Number} z - distance\n * @return {undefined}\n */\n distance (distance: number) {\n // Math.abs because distance used to be \"z\", normally negative.\n // Math.max to prevent us from getting _too_ close.\n this.viewer.cameraDistance = Math.max(Math.abs(distance), 0.2)\n this.viewer.updateZoom()\n this.changed()\n }\n\n /**\n * spin scene on axis\n * @param {Vector3|Array} axis - rotation axis\n * @param {Number} angle - amount to spin\n * @return {undefined}\n */\n spin (axis: Vector3|number[], angle: number) {\n tmpRotateMatrix.getInverse(this.viewer.rotationGroup.matrix)\n tmpRotateVector\n .copy(ensureVector3(axis)).applyMatrix4(tmpRotateMatrix)\n\n this.viewer.rotationGroup.rotateOnAxis(tmpRotateVector, angle)\n this.changed()\n }\n\n /**\n * rotate scene\n * @param {Quaternion|Array} quaternion - rotation quaternion\n * @return {undefined}\n */\n rotate (quaternion: Quaternion|number[]) {\n this.viewer.rotationGroup\n .setRotationFromQuaternion(ensureQuaternion(quaternion))\n this.changed()\n }\n\n /**\n * align scene to basis matrix\n * @param {Matrix4|Array} basis - basis matrix\n * @return {undefined}\n */\n align (basis: Matrix4|number[]) {\n tmpAlignMatrix.getInverse(ensureMatrix4(basis))\n\n this.viewer.rotationGroup.setRotationFromMatrix(tmpAlignMatrix)\n this.changed()\n }\n\n /**\n * apply rotation matrix to scene\n * @param {Matrix4|Array} matrix - rotation matrix\n * @return {undefined}\n */\n applyMatrix (matrix: Matrix4|number[]) {\n this.viewer.rotationGroup.applyMatrix4(ensureMatrix4(matrix))\n this.changed()\n }\n}\n\nexport default ViewerControls\n","/**\n * @file Animation\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Quaternion } from 'three'\n\nimport { defaults, ensureVector3, ensureQuaternion } from '../utils'\nimport { lerp, smoothstep } from '../math/math-utils'\nimport ViewerControls from '../controls/viewer-controls'\nimport Stats from '../viewer/stats'\n\n/**\n * Animation. Base animation class.\n * @interface\n */\nabstract class Animation {\n duration: number\n controls: ViewerControls\n\n alpha: number\n startTime: number\n\n pausedTime = -1\n elapsedDuration = 0\n pausedDuration = 0\n ignoreGlobalToggle = false\n\n private _paused = false\n private _resolveList: Function[] = []\n private _hold: boolean\n\n constructor (duration: number|undefined, controls: ViewerControls, ...args: any[]) {\n this.duration = defaults(duration, 1000)\n this.controls = controls\n\n this.startTime = window.performance.now()\n\n this._init(...args)\n }\n\n /**\n * True when animation has finished\n */\n get done () {\n return this.alpha === 1\n }\n\n /**\n * True when animation is paused\n */\n get paused () {\n return this._paused\n }\n\n /**\n * init animation\n */\n abstract _init (...args: any[]): void\n\n /**\n * called on every tick\n */\n abstract _tick (stats?: Stats): void\n\n tick (stats: Stats) {\n if (this._paused) return\n\n this.elapsedDuration = stats.currentTime - this.startTime - this.pausedDuration\n\n if (this.duration === 0) {\n this.alpha = 1\n } else {\n this.alpha = smoothstep(0, 1, this.elapsedDuration / this.duration)\n }\n\n this._tick(stats)\n\n if (this.done) {\n this._resolveList.forEach(resolve => resolve())\n }\n\n return this.done\n }\n\n /**\n * Pause animation\n * @param {boolean} [hold] - put animation on a hold which\n * must be release before it can be resumed\n */\n pause (hold?: boolean) {\n if (hold) this._hold = true\n\n if (this.pausedTime === -1) {\n this.pausedTime = window.performance.now()\n }\n this._paused = true\n }\n\n /**\n * Resume animation\n * @param {Boolean} [releaseHold] - release a hold on the animation\n */\n resume (releaseHold?: boolean) {\n if (!releaseHold && this._hold) return\n\n this.pausedDuration += window.performance.now() - this.pausedTime\n this._paused = false\n this._hold = false\n this.pausedTime = -1\n }\n\n /**\n * Toggle animation\n */\n toggle () {\n if (this._paused) {\n this.resume()\n } else {\n this.pause()\n }\n }\n\n /**\n * Promise-like interface\n */\n then (callback: Function) {\n let p: Promise\n\n if (this.done) {\n p = Promise.resolve()\n } else {\n p = new Promise(resolve => this._resolveList.push(resolve))\n }\n\n return p.then(callback as any)\n }\n}\n\nexport default Animation\n\n/**\n * Spin animation. Spin around an axis.\n */\nexport class SpinAnimation extends Animation {\n axis: Vector3\n angle: number\n\n constructor (duration: number|undefined, controls: ViewerControls, ...args: any[]) {\n super(defaults(duration, Infinity), controls, ...args)\n }\n\n _init (axis: number[]|Vector3, angle: number) {\n if (Array.isArray(axis)) {\n this.axis = new Vector3().fromArray(axis)\n } else {\n this.axis = defaults(axis, new Vector3(0, 1, 0))\n }\n this.angle = defaults(angle, 0.01)\n }\n\n _tick (stats: Stats) {\n if (!this.axis || !this.angle) return\n\n this.controls.spin(\n this.axis, this.angle * stats.lastDuration / 16\n )\n }\n}\n\n/**\n * Rock animation. Rock around an axis.\n */\nexport class RockAnimation extends Animation {\n axis: Vector3\n angleStep: number\n angleEnd: number\n angleSum = 0\n direction = 1\n\n constructor (duration: number|undefined, controls: ViewerControls, ...args: any[]) {\n super(defaults(duration, Infinity), controls, ...args)\n }\n\n _init (axis: number[]|Vector3, angleStep: number, angleEnd: number) {\n if (Array.isArray(axis)) {\n this.axis = new Vector3().fromArray(axis)\n } else {\n this.axis = defaults(axis, new Vector3(0, 1, 0))\n }\n this.angleStep = defaults(angleStep, 0.01)\n this.angleEnd = defaults(angleEnd, 0.2)\n }\n\n _tick (stats: Stats) {\n if (!this.axis || !this.angleStep || !this.angleEnd) return\n\n const alpha = smoothstep(\n 0, 1, Math.abs(this.angleSum) / this.angleEnd\n )\n const angle = this.angleStep * this.direction * (1.1 - alpha)\n\n this.controls.spin(\n this.axis, angle * stats.lastDuration / 16\n )\n\n this.angleSum += this.angleStep\n\n if (this.angleSum >= this.angleEnd) {\n this.direction *= -1\n this.angleSum = -this.angleEnd\n }\n }\n}\n\n/**\n * Move animation. Move from one position to another.\n */\nexport class MoveAnimation extends Animation {\n moveFrom: Vector3\n moveTo: Vector3\n\n _init (moveFrom: number[]|Vector3, moveTo: number[]|Vector3) {\n this.moveFrom = ensureVector3(defaults(moveFrom, new Vector3()))\n this.moveTo = ensureVector3(defaults(moveTo, new Vector3()))\n }\n\n _tick (/* stats */) {\n this.controls.position.lerpVectors(\n this.moveFrom, this.moveTo, this.alpha\n ).negate()\n this.controls.changed()\n }\n}\n\n/**\n * Zoom animation. Gradually change the zoom level.\n */\nexport class ZoomAnimation extends Animation {\n zoomFrom: number\n zoomTo: number\n\n _init (zoomFrom: number, zoomTo: number) {\n this.zoomFrom = zoomFrom\n this.zoomTo = zoomTo\n }\n\n _tick () {\n this.controls.distance(lerp(this.zoomFrom, this.zoomTo, this.alpha))\n }\n}\n\n/**\n * Rotate animation. Rotate from one orientation to another.\n */\nexport class RotateAnimation extends Animation {\n rotateFrom: Quaternion\n rotateTo: Quaternion\n\n private _currentRotation = new Quaternion()\n\n _init (rotateFrom: number[]|Quaternion, rotateTo: number[]|Quaternion) {\n this.rotateFrom = ensureQuaternion(rotateFrom)\n this.rotateTo = ensureQuaternion(rotateTo)\n\n this._currentRotation = new Quaternion()\n }\n\n _tick () {\n this._currentRotation\n .copy(this.rotateFrom)\n .slerp(this.rotateTo, this.alpha)\n\n this.controls.rotate(this._currentRotation)\n }\n}\n\n/**\n * Value animation. Call callback with interpolated value.\n */\nexport class ValueAnimation extends Animation {\n valueFrom: number\n valueTo: number\n callback: Function\n\n _init (valueFrom: number, valueTo: number, callback: Function) {\n this.valueFrom = valueFrom\n this.valueTo = valueTo\n\n this.callback = callback\n }\n\n _tick (/* stats */) {\n this.callback(lerp(this.valueFrom, this.valueTo, this.alpha))\n }\n}\n\n/**\n * Timeout animation. Call callback after duration.\n */\nexport class TimeoutAnimation extends Animation {\n callback: Function\n\n _init (callback: Function) {\n this.callback = callback\n }\n\n _tick () {\n if (this.alpha === 1) this.callback()\n }\n}\n\n/**\n * Animation list.\n */\nexport class AnimationList {\n _list: Animation[]\n _resolveList: Function[] = []\n\n constructor (list: Animation[] = []) {\n this._list = list\n }\n\n /**\n * True when all animations have finished\n */\n get done () {\n return this._list.every(animation => {\n return animation.done\n })\n }\n\n /**\n * Promise-like interface\n */\n then (callback: Function) {\n let p: Promise\n\n if (this.done) {\n p = Promise.resolve()\n } else {\n p = new Promise(resolve => {\n this._resolveList.push(resolve)\n this._list.forEach(animation => {\n animation.then(() => {\n this._resolveList.forEach(callback => {\n callback()\n })\n this._resolveList.length = 0\n })\n })\n })\n }\n\n return p.then(callback as any)\n }\n}\n","/**\n * @file Animation Controls\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Quaternion, Matrix4 } from 'three'\n\nimport { ensureMatrix4 } from '../utils'\nimport Animation, {\n SpinAnimation, RockAnimation, MoveAnimation, ZoomAnimation,\n RotateAnimation, ValueAnimation, TimeoutAnimation, AnimationList\n} from '../animation/animation'\nimport Stage from '../stage/stage'\nimport Component from '../component/component'\nimport Viewer from '../viewer/viewer'\nimport Stats from '../viewer/stats'\nimport ViewerControls from './viewer-controls'\n\n/**\n * Animation controls\n */\nclass AnimationControls {\n viewer: Viewer\n controls: ViewerControls\n\n animationList: Animation[] = []\n finishedList: Animation[] = []\n\n /**\n * Create animation controls\n * @param {Stage} stage - the stage object\n */\n constructor (readonly stage: Stage) {\n this.viewer = stage.viewer\n this.controls = stage.viewerControls\n }\n\n /**\n * True when all animations are paused\n * @type {Boolean}\n */\n get paused () {\n return this.animationList.every((animation: Animation) => animation.paused)\n }\n\n /**\n * Add an animation\n */\n add (animation: Animation) {\n if (animation.duration === 0) {\n animation.tick(this.viewer.stats)\n } else {\n this.animationList.push(animation)\n }\n\n return animation\n }\n\n /**\n * Remove an animation\n */\n remove (animation: Animation) {\n const list = this.animationList\n const index = list.indexOf(animation)\n\n if (index > -1) {\n list.splice(index, 1)\n }\n }\n\n /**\n * Run all animations\n */\n run (stats: Stats) {\n const finishedList = this.finishedList\n const animationList = this.animationList\n\n const n = animationList.length\n for (let i = 0; i < n; ++i) {\n const animation = animationList[ i ]\n // tick returns true when finished\n if (animation.tick(stats)) {\n finishedList.push(animation)\n }\n }\n\n const m = finishedList.length\n if (m) {\n for (let j = 0; j < m; ++j) {\n this.remove(finishedList[ j ])\n }\n finishedList.length = 0\n }\n }\n\n /**\n * Add a spin animation\n * @param {Vector3} axis - axis to spin around\n * @param {Number} angle - amount to spin per frame, radians\n * @param {Number} duration - animation time in milliseconds\n * @return {SpinAnimation} the animation\n */\n spin (axis: Vector3|number[], angle?: number, duration?: number) {\n return this.add(\n new SpinAnimation(duration, this.controls, axis, angle)\n )\n }\n\n /**\n * Add a rock animation\n * @param {Vector3} axis - axis to rock around\n * @param {Number} angle - amount to spin per frame, radians\n * @param {Number} end - maximum extend of motion, radians\n * @param {Number} duration - animation time in milliseconds\n * @return {SpinAnimation} the animation\n */\n rock (axis: Vector3|number[], angle?: number, end?: number, duration?: number) {\n return this.add(\n new RockAnimation(duration, this.controls, axis, angle, end)\n )\n }\n\n /**\n * Add a rotate animation\n * @param {Quaternion} rotateTo - target rotation\n * @param {Number} duration - animation time in milliseconds\n * @return {RotateAnimation} the animation\n */\n rotate (rotateTo: Quaternion|number[], duration?: number) {\n const rotateFrom = this.viewer.rotationGroup.quaternion.clone()\n\n return this.add(\n new RotateAnimation(duration, this.controls, rotateFrom, rotateTo)\n )\n }\n\n /**\n * Add a move animation\n * @param {Vector3} moveTo - target position\n * @param {Number} duration - animation time in milliseconds\n * @return {MoveAnimation} the animation\n */\n move (moveTo: Vector3|number[], duration?: number) {\n const moveFrom = this.controls.position.clone().negate()\n\n return this.add(\n new MoveAnimation(duration, this.controls, moveFrom, moveTo)\n )\n }\n\n /**\n * Add a zoom animation\n * @param {Number} zoomTo - target distance\n * @param {Number} duration - animation time in milliseconds\n * @return {ZoomAnimation} the animation\n */\n zoom (zoomTo: number, duration?: number) {\n const zoomFrom = this.viewer.camera.position.z\n\n return this.add(\n new ZoomAnimation(duration, this.controls, zoomFrom, zoomTo)\n )\n }\n\n /**\n * Add a zoom and a move animation\n * @param {Vector3} moveTo - target position\n * @param {Number} zoomTo - target distance\n * @param {Number} duration - animation time in milliseconds\n * @return {Array} the animations\n */\n zoomMove (moveTo: Vector3, zoomTo: number, duration?: number) {\n return new AnimationList([\n this.move(moveTo, duration),\n this.zoom(zoomTo, duration)\n ])\n }\n\n /**\n * Add an orient animation\n * @param {OrientationMatrix|Array} orientTo - target orientation\n * @param {Number} duration - animation time in milliseconds\n * @return {Array} the animations\n */\n orient (orientTo: Matrix4|number[], duration?: number) {\n const p = new Vector3()\n const q = new Quaternion()\n const s = new Vector3()\n\n ensureMatrix4(orientTo).decompose(p, q, s)\n\n return new AnimationList([\n this.move(p.negate(), duration),\n this.rotate(q, duration),\n this.zoom(-s.x, duration)\n ])\n }\n\n /**\n * Add a value animation\n * @param {Number} valueFrom - start value\n * @param {Number} valueTo - target value\n * @param {Function} callback - called on every tick\n * @param {Number} duration - animation time in milliseconds\n * @return {ValueAnimation} the animation\n */\n value (valueFrom: number, valueTo: number, callback: Function, duration?: number) {\n return this.add(\n new ValueAnimation(duration, this.controls, valueFrom, valueTo, callback)\n )\n }\n\n /**\n * Add a timeout animation\n * @param {Function} callback - called after duration\n * @param {Number} duration - timeout in milliseconds\n * @return {TimeoutAnimation} the animation\n */\n timeout (callback: Function, duration?: number) {\n return this.add(\n new TimeoutAnimation(duration, this.controls, callback)\n )\n }\n\n /**\n * Add a component spin animation\n * @param {Component} component - object to move\n * @param {Vector3} axis - axis to spin around\n * @param {Number} angle - amount to spin per frame, radians\n * @param {Number} duration - animation time in milliseconds\n * @return {SpinAnimation} the animation\n */\n spinComponent (component: Component, axis?: Vector3|number[], angle?: number, duration?: number) {\n return this.add(\n // TODO\n new SpinAnimation(duration, component.controls as any, axis, angle)\n )\n }\n\n /**\n * Add a component rock animation\n * @param {Component} component - object to move\n * @param {Vector3} axis - axis to rock around\n * @param {Number} angle - amount to spin per frame, radians\n * @param {Number} end - maximum extend of motion, radians\n * @param {Number} duration - animation time in milliseconds\n * @return {SpinAnimation} the animation\n */\n rockComponent (component: Component, axis: Vector3|number[], angle?: number, end?: number, duration?: number) {\n return this.add(\n // TODO\n new RockAnimation(duration, component.controls as any, axis, angle, end)\n )\n }\n\n /**\n * Add a component move animation\n * @param {Component} component - object to move\n * @param {Vector3} moveTo - target position\n * @param {Number} duration - animation time in milliseconds\n * @return {MoveAnimation} the animation\n */\n moveComponent (component: Component, moveTo: Vector3|number[], duration?: number) {\n const moveFrom = component.controls.position.clone().negate()\n\n return this.add(\n // TODO\n new MoveAnimation(duration, component.controls as any, moveFrom, moveTo)\n )\n }\n\n /**\n * Pause all animations\n * @return {undefined}\n */\n pause () {\n this.animationList.forEach(animation => animation.pause())\n }\n\n /**\n * Resume all animations\n * @return {undefined}\n */\n resume () {\n this.animationList.forEach(animation => animation.resume())\n }\n\n /**\n * Toggle all animations\n * @return {undefined}\n */\n toggle () {\n if (this.paused) {\n this.resume()\n } else {\n this.pause()\n }\n }\n\n /**\n * Clear all animations\n * @return {undefined}\n */\n clear () {\n this.animationList.length = 0\n }\n\n dispose () {\n this.clear()\n }\n}\n\nexport default AnimationControls\n","/**\n * @file Queue\n * @author Alexander Rose \n * @private\n */\n\nclass Queue {\n queue: T[] = []\n pending = false\n\n constructor(readonly fn: Function, argList?: T[]) {\n this.next = this.next.bind(this)\n\n if (argList) {\n for (let i = 0, il = argList.length; i < il; ++i) {\n this.queue.push(argList[ i ])\n }\n this.next()\n }\n }\n\n private run (arg: any) {\n this.fn(arg, this.next)\n }\n\n private next () {\n const arg = this.queue.shift()\n if (arg !== undefined) {\n this.pending = true\n setTimeout(() => this.run(arg))\n } else {\n this.pending = false\n }\n }\n\n push (arg: T) {\n this.queue.push(arg)\n if (!this.pending) this.next()\n }\n\n kill () {\n this.queue.length = 0\n }\n\n length () {\n return this.queue.length\n }\n}\n\nexport default Queue\n","/**\n * @file Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { Color, Vector3, Matrix4 } from 'three'\n\nimport { Debug, Log, ColormakerRegistry, ExtensionFragDepth } from '../globals'\nimport { defaults } from '../utils'\nimport Queue from '../utils/queue'\nimport Counter from '../utils/counter'\nimport Viewer from '../viewer/viewer'\nimport { BufferParameters, BufferSide, default as Buffer } from '../buffer/buffer';\nimport { ColorData, ColormakerParameters, ColorMode } from '../color/colormaker';\nimport { GenericColor } from '../types'\n\nexport interface RepresentationParameters {\n name: string\n lazy: boolean,\n clipNear: number,\n clipRadius: number,\n clipCenter: Vector3,\n flatShaded: boolean,\n opacity: number,\n depthWrite: boolean,\n side: BufferSide,\n wireframe: boolean,\n colorData: ColorData,\n colorScheme: string,\n colorScale: string | number[],\n colorReverse: boolean,\n colorValue: GenericColor,\n colorDomain: number[],\n colorMode: ColorMode,\n colorSpace: 'sRGB' | 'linear',\n roughness: number,\n metalness: number,\n diffuse: GenericColor,\n diffuseInterior: boolean,\n useInteriorColor: boolean,\n interiorColor: GenericColor,\n interiorDarkening: number,\n disablePicking: boolean,\n matrix: Matrix4\n quality: string,\n visible: boolean,\n color: GenericColor,\n sphereDetail: number,\n radialSegments: number,\n openEnded: boolean\n disableImpostor: boolean\n [key: string]: any//boolean | number | undefined | Color | string | Vector3 | Matrix4 | number[]\n}\n/**\n * Representation parameter object.\n * @typedef {Object} RepresentationParameters - representation parameters\n * @property {Boolean} [lazy] - only build & update the representation when visible\n * otherwise defer changes until set visible again\n * @property {Integer} [clipNear] - position of camera near/front clipping plane\n * in percent of scene bounding box\n * @property {Integer} [clipRadius] - radius of clipping sphere\n * @property {Vector3} [clipCenter] - position of for spherical clipping\n * @property {Boolean} [flatShaded] - render flat shaded\n * @property {Float} [opacity] - translucency: 1 is fully opaque, 0 is fully transparent\n * @property {Boolean} [depthWrite] - depth write\n * @property {String} [side] - which triangle sides to render, \"front\" front-side,\n * \"back\" back-side, \"double\" front- and back-side\n * @property {Boolean} [wireframe] - render as wireframe\n * @property {ColorData} [colorData] - atom or bond indexed data for coloring\n * @property {String} [colorScheme] - color scheme\n * @property {String} [colorScale] - color scale, either a string for a\n * predefined scale or an array of\n * colors to be used as the scale\n * @property {Boolean} [colorReverse] - reverse color scale\n * @property {Color} [colorValue] - color value\n * @property {Integer[]} [colorDomain] - scale value range\n * @property {Integer} colorDomain.0 - min value\n * @property {Integer} colorDomain.1 - max value\n * @property {String} [colorMode] - color mode, one of rgb, hsv, hsl, hsi, lab, hcl\n * @property {Float} [roughness] - how rough the material is, between 0 and 1\n * @property {Float} [metalness] - how metallic the material is, between 0 and 1\n * @property {Color} [diffuse] - diffuse color for lighting\n * @property {Boolean} [diffuseInterior] - diffuse interior, i.e. ignore normal\n * @property {Boolean} [useInteriorColor] - use interior color\n * @property {Color} [interiorColor] - interior color\n * @property {Float} [interiorDarkening] - interior darkening: 0 no darking, 1 fully darkened\n * @property {Boolean} [disablePicking] - disable picking\n */\n\n/**\n * Representation object\n * @interface\n * @param {Object} object - the object to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {RepresentationParameters} [params] - representation parameters\n */\nclass Representation {\n parameters: any\n type: string\n viewer: Viewer\n tasks: Counter\n private queue: Queue\n bufferList: Buffer[]\n\n lazy: boolean\n lazyProps: { build: boolean, bufferParams: BufferParameters | {}, what: {}}\n protected name: string\n protected clipNear: number\n protected clipRadius: number\n protected clipCenter: Vector3\n protected flatShaded: boolean\n protected opacity: number\n protected depthWrite: boolean\n protected side: BufferSide\n protected wireframe: boolean\n protected colorData: ColorData\n protected colorScheme: string\n protected colorScale: string | string[]\n protected colorReverse: boolean\n protected colorValue: number\n protected colorDomain: number[]\n protected colorMode: ColorMode\n protected roughness: number\n protected metalness: number\n protected diffuse: GenericColor\n protected diffuseInterior?: boolean\n protected useInteriorColor?: boolean\n protected interiorColor: GenericColor\n protected interiorDarkening: number\n protected disablePicking: boolean\n protected sphereDetail: number\n protected radialSegments: number\n protected openEnded: boolean\n protected disableImpostor: boolean\n protected disposed: boolean\n\n protected matrix: Matrix4\n\n private quality: string\n visible: boolean\n\n protected manualAttach: ()=> any\n\n protected toBePrepared: boolean\n\n [key: string]: any\n\n constructor (object: any, viewer: Viewer, params: Partial) {\n // eslint-disable-next-line no-unused-vars\n // const p = params || {}\n\n this.type = ''\n\n this.parameters = {\n\n lazy: {\n type: 'boolean'\n },\n\n clipNear: {\n type: 'range', step: 1, max: 100, min: 0, buffer: true\n },\n clipRadius: {\n type: 'number', precision: 1, max: 1000, min: 0, buffer: true\n },\n clipCenter: {\n type: 'vector3', precision: 1, buffer: true\n },\n flatShaded: {\n type: 'boolean', buffer: true\n },\n opacity: {\n type: 'range', step: 0.01, max: 1, min: 0, buffer: true\n },\n depthWrite: {\n type: 'boolean', buffer: true\n },\n side: {\n type: 'select',\n buffer: true,\n options: { front: 'front', back: 'back', double: 'double' }\n },\n wireframe: {\n type: 'boolean', buffer: true\n },\n\n colorData: {\n type: 'hidden',\n update: 'color',\n },\n\n colorScheme: {\n type: 'select',\n update: 'color',\n options: {}\n },\n colorScale: {\n type: 'select',\n update: 'color',\n options: ColormakerRegistry.getScales()\n },\n colorReverse: {\n type: 'boolean', update: 'color'\n },\n colorValue: {\n type: 'color', update: 'color'\n },\n colorDomain: {\n type: 'hidden', update: 'color'\n },\n colorMode: {\n type: 'select',\n update: 'color',\n options: ColormakerRegistry.getModes()\n },\n\n roughness: {\n type: 'range', step: 0.01, max: 1, min: 0, buffer: true\n },\n metalness: {\n type: 'range', step: 0.01, max: 1, min: 0, buffer: true\n },\n diffuse: {\n type: 'color', buffer: true\n },\n\n diffuseInterior: {\n type: 'boolean', buffer: true\n },\n useInteriorColor: {\n type: 'boolean', buffer: true\n },\n interiorColor: {\n type: 'color', buffer: true\n },\n interiorDarkening: {\n type: 'range', step: 0.01, max: 1, min: 0, buffer: true\n },\n\n matrix: {\n type: 'hidden', buffer: true\n },\n\n disablePicking: {\n type: 'boolean', rebuild: true\n }\n\n }\n\n /**\n * @type {Viewer}\n */\n this.viewer = viewer\n\n /**\n * Counter that keeps track of tasks related to the creation of\n * the representation, including surface calculations.\n * @type {Counter}\n */\n this.tasks = new Counter()\n\n /**\n * @type {Queue}\n * @private\n */\n this.queue = new Queue(this.make.bind(this))\n\n /**\n * @type {Array}\n * @private\n */\n this.bufferList = []\n\n if (this.parameters.colorScheme) {\n this.parameters.colorScheme.options = ColormakerRegistry.getSchemes()\n }\n\n this.toBePrepared = false\n }\n\n init (params: Partial) {\n const p = params || {}\n\n this.clipNear = defaults(p.clipNear, 0)\n this.clipRadius = defaults(p.clipRadius, 0)\n this.clipCenter = defaults(p.clipCenter, new Vector3())\n this.flatShaded = defaults(p.flatShaded, false)\n this.side = defaults(p.side, 'double')\n this.opacity = defaults(p.opacity, 1.0)\n this.depthWrite = defaults(p.depthWrite, true)\n this.wireframe = defaults(p.wireframe, false)\n\n this.setColor(p.color, p)\n\n this.colorData = defaults(p.colorData, undefined)\n this.colorScheme = defaults(p.colorScheme, 'uniform')\n this.colorScale = defaults(p.colorScale, '')\n this.colorReverse = defaults(p.colorReverse, false)\n this.colorValue = defaults(p.colorValue, 0x909090)\n this.colorDomain = defaults(p.colorDomain, undefined)\n this.colorMode = defaults(p.colorMode, 'hcl')\n\n this.visible = defaults(p.visible, true)\n this.quality = defaults(p.quality, undefined)\n\n this.roughness = defaults(p.roughness, 0.4)\n this.metalness = defaults(p.metalness, 0.0)\n this.diffuse = defaults(p.diffuse, 0xffffff)\n\n this.diffuseInterior = defaults(p.diffuseInterior, false)\n this.useInteriorColor = defaults(p.useInteriorColor, false)\n this.interiorColor = defaults(p.interiorColor, 0x222222)\n this.interiorDarkening = defaults(p.interiorDarkening, 0)\n\n this.lazy = defaults(p.lazy, false)\n this.lazyProps = {\n build: false,\n bufferParams: {},\n what: {}\n }\n\n this.matrix = defaults(p.matrix, new Matrix4())\n\n this.disablePicking = defaults(p.disablePicking, false)\n\n // handle common parameters when applicable\n\n const tp = this.parameters\n\n if (tp.sphereDetail === true) {\n tp.sphereDetail = {\n type: 'integer', max: 3, min: 0, rebuild: 'impostor'\n }\n }\n if (tp.radialSegments === true) {\n tp.radialSegments = {\n type: 'integer', max: 25, min: 5, rebuild: 'impostor'\n }\n }\n if (tp.openEnded === true) {\n tp.openEnded = {\n type: 'boolean', rebuild: 'impostor', buffer: true\n }\n }\n if (tp.disableImpostor === true) {\n tp.disableImpostor = {\n type: 'boolean', rebuild: true\n }\n }\n\n if (p.quality === 'low') {\n if (tp.sphereDetail) this.sphereDetail = 0\n if (tp.radialSegments) this.radialSegments = 5\n } else if (p.quality === 'medium') {\n if (tp.sphereDetail) this.sphereDetail = 1\n if (tp.radialSegments) this.radialSegments = 10\n } else if (p.quality === 'high') {\n if (tp.sphereDetail) this.sphereDetail = 2\n if (tp.radialSegments) this.radialSegments = 20\n } else {\n if (tp.sphereDetail) {\n this.sphereDetail = defaults(p.sphereDetail, 1)\n }\n if (tp.radialSegments) {\n this.radialSegments = defaults(p.radialSegments, 10)\n }\n }\n\n if (tp.openEnded) {\n this.openEnded = defaults(p.openEnded, true)\n }\n\n if (tp.disableImpostor) {\n this.disableImpostor = defaults(p.disableImpostor, false)\n }\n\n }\n\n getColorParams (p?: {[k: string]: any}): { scheme: string, [k: string]: any } & ColormakerParameters {\n return Object.assign({\n\n data: this.colorData,\n scheme: this.colorScheme,\n scale: this.colorScale,\n reverse: this.colorReverse,\n value: this.colorValue,\n domain: this.colorDomain,\n mode: this.colorMode,\n colorSpace: this.colorSpace,\n\n }, p)\n }\n\n getBufferParams (p: {[k: string]: any} = {}) {\n return Object.assign({\n\n clipNear: this.clipNear,\n clipRadius: this.clipRadius,\n clipCenter: this.clipCenter,\n flatShaded: this.flatShaded,\n opacity: this.opacity,\n depthWrite: this.depthWrite,\n side: this.side,\n wireframe: this.wireframe,\n\n roughness: this.roughness,\n metalness: this.metalness,\n diffuse: this.diffuse,\n\n diffuseInterior: this.diffuseInterior,\n useInteriorColor: this.useInteriorColor,\n interiorColor: this.interiorColor,\n interiorDarkening: this.interiorDarkening,\n\n matrix: this.matrix,\n\n disablePicking: this.disablePicking\n\n }, p)\n }\n\n setColor (value: number | string | Color | undefined , p?: Partial) {\n const types = Object.keys(ColormakerRegistry.getSchemes())\n\n if (typeof value === 'string' && types.includes(value.toLowerCase())) {\n if (p) {\n p.colorScheme = value\n } else {\n this.setParameters({ colorScheme: value })\n }\n } else if (value !== undefined) {\n let val = new Color(value as string).getHex() //TODO\n if (p) {\n p.colorScheme = 'uniform'\n p.colorValue = val\n } else {\n this.setParameters({\n colorScheme: 'uniform', colorValue: val\n })\n }\n }\n\n return this\n }\n\n // TODO\n prepare (cb: ()=> void) {\n\n }\n\n create () {\n // this.bufferList.length = 0;\n }\n\n update (what?: any) {\n this.build()\n }\n\n build (updateWhat?: {[k: string]: boolean}) {\n if (this.lazy && (!this.visible || !this.opacity)) {\n this.lazyProps.build = true\n return\n }\n\n if (!this.toBePrepared) {\n this.tasks.increment()\n this.make()\n return\n }\n\n // don't let tasks accumulate\n if (this.queue.length() > 0) {\n this.tasks.change(1 - this.queue.length())\n this.queue.kill()\n } else {\n this.tasks.increment()\n }\n\n this.queue.push(updateWhat || false)\n }\n\n make (updateWhat?: boolean, callback?: () => void) {\n if (Debug) Log.time('Representation.make ' + this.type)\n\n const _make = () => {\n if (updateWhat) {\n this.update(updateWhat)\n this.viewer.requestRender()\n this.tasks.decrement()\n if (callback) callback()\n } else {\n this.clear()\n this.create()\n if (!this.manualAttach && !this.disposed) {\n if (Debug) Log.time('Representation.attach ' + this.type)\n this.attach(() => {\n if (Debug) Log.timeEnd('Representation.attach ' + this.type)\n this.tasks.decrement()\n if (callback) callback()\n })\n }\n }\n\n if (Debug) Log.timeEnd('Representation.make ' + this.type)\n }\n\n if (this.toBePrepared) {\n this.prepare(_make)\n } else {\n _make()\n }\n }\n\n attach (callback: () => void) {\n this.setVisibility(this.visible)\n\n callback()\n }\n\n /**\n * Set the visibility of the representation\n * @param {Boolean} value - visibility flag\n * @param {Boolean} [noRenderRequest] - whether or not to request a re-render from the viewer\n * @return {Representation} this object\n */\n setVisibility (value: boolean, noRenderRequest?: boolean): Representation {\n this.visible = value\n\n if (this.visible && this.opacity) {\n const lazyProps = this.lazyProps\n const bufferParams = lazyProps.bufferParams\n const what = lazyProps.what\n\n if (lazyProps.build) {\n lazyProps.build = false\n this.build()\n return this\n } else if (Object.keys(bufferParams).length || Object.keys(what).length) {\n lazyProps.bufferParams = {}\n lazyProps.what = {}\n this.updateParameters(bufferParams, what)\n }\n }\n\n this.bufferList.forEach(function (buffer) {\n buffer.setVisibility(value)\n })\n\n if (!noRenderRequest) this.viewer.requestRender()\n\n return this\n }\n\n /**\n * Set the visibility of the representation\n * @param {RepresentationParameters} params - parameters object\n * @param {Object} [what] - buffer data attributes to be updated,\n * note that this needs to be implemented in the\n * derived classes. Generally it allows more\n * fine-grained control over updating than\n * forcing a rebuild.\n * @param {Boolean} what.position - update position data\n * @param {Boolean} what.color - update color data\n * @param {Boolean} [rebuild] - whether or not to rebuild the representation\n * @return {Representation} this object\n */\n setParameters (params: Partial, what:{[propName: string]: any} = {}, rebuild = false) {\n const p = params || {}\n const tp = this.parameters\n const bufferParams: BufferParameters = {}\n\n if (!this.opacity && p.opacity !== undefined) {\n if (this.lazyProps.build) {\n this.lazyProps.build = false\n rebuild = true\n } else {\n Object.assign(bufferParams, this.lazyProps.bufferParams)\n Object.assign(what, this.lazyProps.what)\n this.lazyProps.bufferParams = {}\n this.lazyProps.what = {}\n }\n }\n\n this.setColor(p.color, p)\n\n for (let name in p) {\n if (p[ name ] === undefined) continue\n if (tp[ name ] == undefined ) continue // Skip nulls as well as undefined\n\n if (tp[ name ].int) p[ name ] = parseInt(p[ name ] as string)\n if (tp[ name ].float) p[ name ] = parseFloat(p[ name ] as string)\n\n // no value change\n if (p[ name ] === this[ name ] && (\n !p[ name ].equals || p[ name ].equals(this[ name ])\n )) continue\n\n if (this[ name ] && this[ name ].copy && p[ name ].copy) {\n this[ name ].copy(p[ name ])\n } else if (this[ name ] && this[ name ].set) {\n this[ name ].set(p[ name ])\n } else {\n this[ name ] = p[ name ]\n }\n\n // buffer param\n if (tp[ name ].buffer) {\n if (tp[ name ].buffer === true) {\n (bufferParams[ name as keyof BufferParameters ] as any) = p[ name ]\n } else {\n let key: (keyof BufferParameters) = tp[ name ].buffer;\n (bufferParams[ key ] as any) = p[ name ]\n }\n }\n\n // mark for update\n if (tp[ name ].update) {\n what[ tp[ name ].update ] = true\n }\n\n // mark for rebuild\n if (tp[ name ].rebuild &&\n !(tp[ name ].rebuild === 'impostor' &&\n ExtensionFragDepth && !this.disableImpostor)\n ) {\n rebuild = true\n }\n }\n\n //\n\n if (rebuild) {\n this.build()\n } else {\n this.updateParameters(bufferParams, what)\n }\n\n return this\n }\n\n updateParameters (bufferParams: BufferParameters | {} = {}, what?: any) {\n if (this.lazy && (!this.visible || !this.opacity) && bufferParams.hasOwnProperty('opacity') === false) {\n Object.assign(this.lazyProps.bufferParams, bufferParams)\n Object.assign(this.lazyProps.what, what)\n return\n }\n\n this.bufferList.forEach(function (buffer) {\n buffer.setParameters(bufferParams)\n })\n\n if (Object.keys(what).length) {\n this.update(what) // update buffer attribute\n }\n\n this.viewer.requestRender()\n }\n\n getParameters () {\n const params: Partial = {\n lazy: this.lazy,\n visible: this.visible,\n quality: this.quality\n }\n\n Object.keys(this.parameters).forEach(name => {\n if (this.parameters[ name ] !== null) {\n params[ name ] = this[ name ]\n }\n })\n\n return params\n }\n\n clear () {\n this.bufferList.forEach(buffer => {\n this.viewer.remove(buffer)\n buffer.dispose()\n })\n this.bufferList.length = 0\n\n this.viewer.requestRender()\n }\n\n dispose () {\n this.disposed = true\n this.queue.kill()\n this.tasks.dispose()\n this.clear()\n }\n}\n\nexport default Representation\n","/**\n * @file Worker\n * @author Alexander Rose \n * @private\n */\n\nimport { Log, Debug, WorkerRegistry } from '../globals'\n\nexport default class _Worker {\n\n pending = 0\n postCount = 0\n onmessageDict: { [k: number]: Function|undefined } = {}\n onerrorDict: { [k: number]: Function|undefined } = {}\n\n name: string\n blobUrl: string\n worker: Worker\n\n constructor (name: string) {\n\n this.name = name\n this.blobUrl = window.URL.createObjectURL(WorkerRegistry.get(name))\n this.worker = new Worker(this.blobUrl)\n\n WorkerRegistry.activeWorkerCount += 1\n\n this.worker.onmessage = (event: any) => {\n this.pending -= 1\n const postId = event.data.__postId\n\n if (Debug) Log.timeEnd('Worker.postMessage ' + name + ' #' + postId)\n\n const onmessage = this.onmessageDict[ postId ]\n if (onmessage) {\n onmessage.call(this.worker, event)\n } else {\n // Log.debug('No onmessage', postId, name)\n }\n\n delete this.onmessageDict[ postId ]\n delete this.onerrorDict[ postId ]\n }\n\n this.worker.onerror = (event: any) => {\n this.pending -= 1\n if (event.data) {\n const postId = event.data.__postId\n\n const onerror = this.onerrorDict[ postId ]\n if (onerror) {\n onerror.call(this.worker, event)\n } else {\n Log.error('Worker.onerror', postId, name, event)\n }\n\n delete this.onmessageDict[ postId ]\n delete this.onerrorDict[ postId ]\n } else {\n Log.error('Worker.onerror', name, event)\n }\n }\n }\n\n post (aMessage: any = {}, transferList?: any, onmessage?: Function, onerror?: Function) {\n this.onmessageDict[ this.postCount ] = onmessage\n this.onerrorDict[ this.postCount ] = onerror\n\n aMessage.__name = this.name\n aMessage.__postId = this.postCount\n aMessage.__debug = Debug\n\n if (Debug) Log.time(`Worker.postMessage ${this.name} #${this.postCount}`)\n\n try {\n this.worker.postMessage(aMessage, transferList)\n } catch (error) {\n Log.error('worker.post:', error)\n this.worker.postMessage(aMessage)\n }\n\n this.pending += 1\n this.postCount += 1\n\n return this\n }\n\n terminate () {\n if (this.worker) {\n this.worker.terminate()\n window.URL.revokeObjectURL(this.blobUrl)\n WorkerRegistry.activeWorkerCount -= 1\n } else {\n Log.log('no worker to terminate')\n }\n }\n}\n","/**\n * @file Worker Pool\n * @author Alexander Rose \n * @private\n */\n\nimport Worker from './worker'\n\nclass WorkerPool {\n maxCount: number\n pool: Worker[] = []\n count = 0\n name: string\n\n constructor (name: string, maxCount = 2) {\n this.maxCount = Math.min(8, maxCount)\n this.name = name\n }\n\n post (aMessage: any = {}, transferList?: any, onmessage?: Function, onerror?: Function) {\n const worker = this.getNextWorker()\n if (worker) {\n worker.post(aMessage, transferList, onmessage, onerror)\n } else {\n console.error('unable to get worker from pool')\n }\n\n return this\n }\n\n terminate () {\n this.pool.forEach(function (worker) {\n worker.terminate()\n })\n }\n\n getNextWorker () {\n let nextWorker\n let minPending = Infinity\n\n for (let i = 0; i < this.maxCount; ++i) {\n if (i >= this.count) {\n nextWorker = new Worker(this.name)\n this.pool.push(nextWorker)\n this.count += 1\n break\n }\n\n const worker = this.pool[ i ]\n\n if (worker.pending === 0) {\n nextWorker = worker\n break\n } else if (worker.pending < minPending) {\n minPending = worker.pending\n nextWorker = worker\n }\n }\n\n return nextWorker\n }\n}\n\nWorkerPool.prototype.constructor = WorkerPool\n\nexport default WorkerPool\n","/**\n * @file Vector Utils\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { NumberArray } from '../types'\nimport { EPS } from './math-constants'\n\n/**\n * Calculate the two intersection points\n * Converted to JavaScript from\n * {@link http://paulbourke.net/geometry/pointlineplane/lineline.c}\n */\nexport function lineLineIntersect (p1: Vector3, p2: Vector3, p3: Vector3, p4: Vector3) {\n const p13 = new Vector3()\n const p43 = new Vector3()\n const p21 = new Vector3()\n let d1343, d4321, d1321, d4343, d2121\n let denom, numer\n\n p13.x = p1.x - p3.x\n p13.y = p1.y - p3.y\n p13.z = p1.z - p3.z\n p43.x = p4.x - p3.x\n p43.y = p4.y - p3.y\n p43.z = p4.z - p3.z\n if (Math.abs(p43.x) < EPS && Math.abs(p43.y) < EPS && Math.abs(p43.z) < EPS) { return null }\n\n p21.x = p2.x - p1.x\n p21.y = p2.y - p1.y\n p21.z = p2.z - p1.z\n if (Math.abs(p21.x) < EPS && Math.abs(p21.y) < EPS && Math.abs(p21.z) < EPS) { return null }\n\n d1343 = p13.x * p43.x + p13.y * p43.y + p13.z * p43.z\n d4321 = p43.x * p21.x + p43.y * p21.y + p43.z * p21.z\n d1321 = p13.x * p21.x + p13.y * p21.y + p13.z * p21.z\n d4343 = p43.x * p43.x + p43.y * p43.y + p43.z * p43.z\n d2121 = p21.x * p21.x + p21.y * p21.y + p21.z * p21.z\n\n denom = d2121 * d4343 - d4321 * d4321\n if (Math.abs(denom) < EPS) { return null }\n numer = d1343 * d4321 - d1321 * d4343\n\n const mua = numer / denom\n const mub = (d1343 + d4321 * mua) / d4343\n\n const pa = new Vector3(\n p1.x + mua * p21.x,\n p1.y + mua * p21.y,\n p1.z + mua * p21.z\n )\n const pb = new Vector3(\n p3.x + mub * p43.x,\n p3.y + mub * p43.y,\n p3.z + mub * p43.z\n )\n\n return [ pa, pb ]\n}\n\nexport function calculateMeanVector3 (array: NumberArray) {\n const n = array.length\n const m = n / 3\n\n let x = 0\n let y = 0\n let z = 0\n\n for (let i = 0; i < n; i += 3) {\n x += array[ i + 0 ]\n y += array[ i + 1 ]\n z += array[ i + 2 ]\n }\n\n return new Vector3(x / m, y / m, z / m)\n}\n\nexport function isPointOnSegment (p: Vector3, l1: Vector3, l2: Vector3) {\n const len = l1.distanceTo(l2)\n\n return p.distanceTo(l1) <= len && p.distanceTo(l2) <= len\n}\n\nexport function projectPointOnVector (point: Vector3, vector: Vector3, origin?: Vector3) {\n if (origin) {\n point.sub(origin).projectOnVector(vector).add(origin)\n } else {\n point.projectOnVector(vector)\n }\n\n return point\n}\n\nexport function computeBoundingBox (array: NumberArray) {\n let minX = +Infinity\n let minY = +Infinity\n let minZ = +Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n let maxZ = -Infinity\n for (let i = 0, l = array.length; i < l; i += 3) {\n const x = array[ i ]\n const y = array[ i + 1 ]\n const z = array[ i + 2 ]\n if (x < minX) minX = x\n if (y < minY) minY = y\n if (z < minZ) minZ = z\n if (x > maxX) maxX = x\n if (y > maxY) maxY = y\n if (z > maxZ) maxZ = z\n }\n return [\n v3new([ minX, minY, minZ ]),\n v3new([ maxX, maxY, maxZ ])\n ]\n}\n(computeBoundingBox as any).__deps = [ v3new ]\n\nexport function applyMatrix4toVector3array (m: Float32Array, a: Float32Array) {\n for (let i = 0, il = a.length; i < il; i += 3) {\n const x = a[ i ]\n const y = a[ i + 1 ]\n const z = a[ i + 2 ]\n a[ i ] = m[ 0 ] * x + m[ 4 ] * y + m[ 8 ] * z + m[ 12 ]\n a[ i + 1 ] = m[ 1 ] * x + m[ 5 ] * y + m[ 9 ] * z + m[ 13 ]\n a[ i + 2 ] = m[ 2 ] * x + m[ 6 ] * y + m[ 10 ] * z + m[ 14 ]\n }\n}\n\nexport function applyMatrix3toVector3array (m: Float32Array, a: Float32Array) {\n for (let i = 0, il = a.length; i < il; i += 3) {\n const x = a[ i ]\n const y = a[ i + 1 ]\n const z = a[ i + 2 ]\n a[ i ] = m[ 0 ] * x + m[ 3 ] * y + m[ 6 ] * z\n a[ i + 1 ] = m[ 1 ] * x + m[ 4 ] * y + m[ 7 ] * z\n a[ i + 2 ] = m[ 2 ] * x + m[ 5 ] * y + m[ 8 ] * z\n }\n}\n\nexport function normalizeVector3array (a: Float32Array) {\n for (let i = 0, il = a.length; i < il; i += 3) {\n const x = a[ i ]\n const y = a[ i + 1 ]\n const z = a[ i + 2 ]\n const len2 = x * x + y * y + z * z\n if (len2 > 0) { // avoid divide by zero\n const s = 1 / Math.sqrt(len2)\n a[ i ] = x * s\n a[ i + 1 ] = y * s\n a[ i + 2 ] = z * s\n }\n // else leave as all zeros\n }\n}\n\nexport function v3new (array?: NumberArray) {\n return new Float32Array(array as any || 3) // TODO\n}\n\nexport function v3cross (out: Float32Array, a: Float32Array, b: Float32Array) {\n const ax = a[0]\n const ay = a[1]\n const az = a[2]\n const bx = b[0]\n const by = b[1]\n const bz = b[2]\n out[0] = ay * bz - az * by\n out[1] = az * bx - ax * bz\n out[2] = ax * by - ay * bx\n}\n\nexport function v3dot (a: Float32Array, b: Float32Array) {\n return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]\n}\n\nexport function v3sub (out: Float32Array, a: Float32Array, b: Float32Array) {\n out[0] = a[0] - b[0]\n out[1] = a[1] - b[1]\n out[2] = a[2] - b[2]\n}\n\nexport function v3add (out: Float32Array, a: Float32Array, b: Float32Array) {\n out[0] = a[0] + b[0]\n out[1] = a[1] + b[1]\n out[2] = a[2] + b[2]\n}\n\nexport function v3fromArray (out: Float32Array, array: Float32Array, offset = 0) {\n out[0] = array[offset]\n out[1] = array[offset + 1]\n out[2] = array[offset + 2]\n}\n\nexport function v3toArray (input: Float32Array, array: Float32Array, offset = 0) {\n array[offset] = input[0]\n array[offset + 1] = input[1]\n array[offset + 2] = input[2]\n}\n\nexport function v3forEach (array: Float32Array, fn: (i: Float32Array, j: Float32Array, k: Float32Array) => void, b: Float32Array) {\n const a = v3new()\n for (let i = 0, n = array.length; i < n; i += 3) {\n v3fromArray(a, array, i)\n fn(a, a, b)\n v3toArray(a, array, i)\n }\n}\n(v3forEach as any).__deps = [ v3new, v3fromArray, v3toArray ]\n\nexport function v3length2 (a: Float32Array) {\n return a[0] * a[0] + a[1] * a[1] + a[2] * a[2]\n}\n\nexport function v3length (a: Float32Array) {\n return Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2])\n}\n\nexport function v3divide (out: Float32Array, a: Float32Array, b: Float32Array) {\n out[0] = a[0] / b[0]\n out[1] = a[1] / b[1]\n out[2] = a[2] / b[2]\n}\n\nexport function v3multiply (out: Float32Array, a: Float32Array, b: Float32Array) {\n out[0] = a[0] * b[0]\n out[1] = a[1] * b[1]\n out[2] = a[2] * b[2]\n}\n\nexport function v3divideScalar (out: Float32Array, a: Float32Array, s: number) {\n v3multiplyScalar(out, a, 1 / s)\n}\n(v3divideScalar as any).__deps = [ v3multiplyScalar ]\n\nexport function v3multiplyScalar (out: Float32Array, a: Float32Array, s: number) {\n out[0] = a[0] * s\n out[1] = a[1] * s\n out[2] = a[2] * s\n}\n\nexport function v3normalize (out: Float32Array, a: Float32Array) {\n const length2 = v3length2(a)\n if (length2 == 0) {\n out[0] = a[0]\n out[1] = a[1]\n out[2] = a[2]\n } else {\n v3multiplyScalar(out, a, 1 / Math.sqrt(length2))\n }\n}\n(v3normalize as any).__deps = [ v3multiplyScalar, v3length2 ]\n\nexport function v3subScalar (out: Float32Array, a: Float32Array, s: number) {\n out[0] = a[0] - s\n out[1] = a[1] - s\n out[2] = a[2] - s\n}\n\nexport function v3addScalar (out: Float32Array, a: Float32Array, s: number) {\n out[0] = a[0] + s\n out[1] = a[1] + s\n out[2] = a[2] + s\n}\n\nexport function v3floor (out: Float32Array, a: Float32Array) {\n out[0] = Math.floor(a[0])\n out[1] = Math.floor(a[1])\n out[2] = Math.floor(a[2])\n}\n\nexport function v3ceil (out: Float32Array, a: Float32Array) {\n out[0] = Math.ceil(a[0])\n out[1] = Math.ceil(a[1])\n out[2] = Math.ceil(a[2])\n}\n\nexport function v3round (out: Float32Array, a: Float32Array) {\n out[0] = Math.round(a[0])\n out[1] = Math.round(a[1])\n out[2] = Math.round(a[2])\n}\n\nexport function v3negate (out: Float32Array, a: Float32Array) {\n out[0] = -a[0]\n out[1] = -a[1]\n out[2] = -a[2]\n}\n\nexport function v3angle (a: Float32Array, b: Float32Array) {\n const ax = a[0]\n const ay = a[1]\n const az = a[2]\n const bx = b[0]\n const by = b[1]\n const bz = b[2]\n const cx = ay * bz - az * by\n const cy = az * bx - ax * bz\n const cz = ax * by - ay * bx\n const s = Math.sqrt(cx * cx + cy * cy + cz * cz)\n const c = ax * bx + ay * by + az * bz\n return Math.atan2(s, c)\n}\n","/**\n * @file Dash\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { CylinderBufferData } from '../buffer/cylinder-buffer'\nimport { WideLineBufferData } from '../buffer/wideline-buffer'\nimport {\n calculateDirectionArray, calculateCenterArray,\n replicateArrayEntries, replicateArray3Entries\n} from '../math/array-utils'\n\nexport function getFixedCountDashData (data: T, segmentCount: number = 9) {\n\n const s = Math.floor(segmentCount / 2)\n const n = data.position1.length / 3\n const sn = s * n\n const sn3 = sn * 3\n const step = 1 / segmentCount\n\n const direction = calculateDirectionArray(data.position1, data.position2)\n const position1 = new Float32Array(sn3)\n const position2 = new Float32Array(sn3)\n\n const v = new Vector3()\n\n for (let i = 0; i < n; ++i) {\n const i3 = i * 3\n v.set(direction[ i3 ], direction[ i3 + 1 ], direction[ i3 + 2 ])\n\n const x = data.position1[ i3 ]\n const y = data.position1[ i3 + 1 ]\n const z = data.position1[ i3 + 2 ]\n\n for (let j = 0; j < s; ++j) {\n const j3 = s * i3 + j * 3\n\n const f1 = step * (j * 2 + 1)\n const f2 = step * (j * 2 + 2)\n\n position1[ j3 ] = x + v.x * f1\n position1[ j3 + 1 ] = y + v.y * f1\n position1[ j3 + 2 ] = z + v.z * f1\n\n position2[ j3 ] = x + v.x * f2\n position2[ j3 + 1 ] = y + v.y * f2\n position2[ j3 + 2 ] = z + v.z * f2\n }\n }\n\n const position = calculateCenterArray(position1, position2) as Float32Array\n const color = replicateArray3Entries(data.color!, s) // TODO\n const color2 = color\n\n const d: any = { position, position1, position2, color, color2 }\n\n if ((data as any).radius) { // TODO\n d.radius = replicateArrayEntries((data as any).radius, s) // TODO\n }\n\n if (data.picking && data.picking.array) {\n data.picking.array = replicateArrayEntries(data.picking.array, s)\n d.picking = data.picking\n }\n if (data.primitiveId) {\n d.primitiveId = replicateArrayEntries(data.primitiveId, s)\n }\n\n return d as T\n}\n\nexport function getFixedLengthDashData (data: T, segmentLength: number = 0.1) {\n\n const direction = calculateDirectionArray(data.position1, data.position2)\n const pos1: number[] = []\n const pos2: number[] = []\n const col: number[] = []\n const rad: number[]|undefined = (data as any).radius ? [] : undefined\n const pick: number[]|undefined = (data as any).picking ? [] : undefined\n const id: number[]|undefined = (data as any).primitiveId ? [] : undefined\n\n const v = new Vector3()\n const n = data.position1.length / 3\n\n let k = 0\n\n for (let i = 0; i < n; ++i) {\n const i3 = i * 3\n v.set(direction[ i3 ], direction[ i3 + 1 ], direction[ i3 + 2 ])\n\n const vl = v.length()\n const segmentCount = vl / segmentLength\n const s = Math.floor(segmentCount / 2)\n const step = 1 / segmentCount\n\n const x = data.position1[ i3 ]\n const y = data.position1[ i3 + 1 ]\n const z = data.position1[ i3 + 2 ]\n\n for (let j = 0; j < s; ++j) {\n const j3 = k * 3 + j * 3\n\n const f1 = step * (j * 2 + 1)\n const f2 = step * (j * 2 + 2)\n\n pos1[ j3 ] = x + v.x * f1\n pos1[ j3 + 1 ] = y + v.y * f1\n pos1[ j3 + 2 ] = z + v.z * f1\n\n pos2[ j3 ] = x + v.x * f2\n pos2[ j3 + 1 ] = y + v.y * f2\n pos2[ j3 + 2 ] = z + v.z * f2\n\n if (data.color) {\n col[ j3 ] = data.color[ i3 ]\n col[ j3 + 1 ] = data.color[ i3 + 1 ]\n col[ j3 + 2 ] = data.color[ i3 + 2 ]\n }\n\n if (rad) rad[ k + j ] = (data as any).radius[ i ]\n if (pick) {\n if ((data as any).picking.array) {\n pick[ k + j ] = (data as any).picking.array[ i ]\n } else {\n pick[ k + j ] = i\n }\n }\n if (id) id[ k + j ] = (data as any).primitiveId[ i ]\n }\n\n k += s\n }\n\n const position1 = new Float32Array(pos1)\n const position2 = new Float32Array(pos2)\n const position = calculateCenterArray(position1, position2) as Float32Array\n const color = new Float32Array(col)\n const color2 = color\n\n const d: any = { position, position1, position2, color, color2 }\n\n if (rad) d.radius = new Float32Array(rad)\n if (pick && data.picking) {\n data.picking.array = new Float32Array(pick)\n d.picking = data.picking\n }\n if (id) d.primitiveId = new Float32Array(id)\n\n return d as T\n}\n\nexport function getFixedLengthWrappedDashData (data: T, segmentLength: number = 0.1) {\n\n const direction = calculateDirectionArray(data.position1, data.position2)\n const pos1: number[] = []\n const pos2: number[] = []\n const col: number[] = []\n const rad: number[]|undefined = (data as any).radius ? [] : undefined\n const pick: number[]|undefined = (data as any).picking ? [] : undefined\n const id: number[]|undefined = (data as any).primitiveId ? [] : undefined\n\n const v = new Vector3()\n const n = data.position1.length / 3\n\n let remaining = segmentLength\n let drawing = true\n\n let k = 0\n let k3 = 0\n let kprev = 0\n\n for (let i = 0; i < n; ++i) {\n const i3 = i * 3\n const x = data.position1[ i3 ]\n const y = data.position1[ i3 + 1 ]\n const z = data.position1[ i3 + 2 ]\n\n v.set(direction[ i3 ], direction[ i3 + 1 ], direction[ i3 + 2 ])\n const vl = v.length()\n\n if (drawing) {\n pos1[ k3 ] = x\n pos1[ k3 + 1 ] = y\n pos1[ k3 + 2 ] = z\n }\n\n let dist = remaining\n const inv = 1 / vl\n while (dist < vl) {\n const a = drawing ? pos2 : pos1\n a[ k3 ] = x + v.x * dist * inv\n a[ k3 + 1 ] = y + v.y * dist * inv\n a[ k3 + 2 ] = z + v.z * dist * inv\n if (drawing) {\n k++\n k3 = k * 3\n }\n drawing = !drawing\n remaining = segmentLength\n dist += segmentLength\n }\n\n if (drawing) {\n pos2[ k3 ] = data.position2[ i3 ]\n pos2[ k3 + 1 ] = data.position2[ i3 + 1 ]\n pos2[ k3 + 2 ] = data.position2[ i3 + 2 ]\n k++\n k3 = k * 3\n }\n\n remaining = dist - vl\n\n for (let j = kprev; j < k ; j++){\n if (data.color) {\n const j3 = j * 3\n col[ j3 ] = data.color[ i3 ]\n col[ j3 + 1 ] = data.color[ i3 + 1 ]\n col[ j3 + 2 ] = data.color[ i3 + 2 ]\n }\n\n if (rad) rad[ j ] = (data as any).radius[ i ]\n if (pick) {\n if ((data as any).picking.array) {\n pick[ j ] = (data as any).picking.array[ i ]\n } else {\n pick[ j ] = i\n }\n }\n if (id) id[ j ] = (data as any).primitiveId[ i ]\n }\n\n kprev = k\n\n }\n\n if (!drawing && n > 0) {\n const k3 = k * 3\n pos2[ k3 ] = data.position2[ 3 * n - 3 ]\n pos2[ k3 + 1 ] = data.position2[ 3 * n - 2 ]\n pos2[ k3 + 1 ] = data.position2[ 3 * n - 1 ]\n }\n\n const position1 = new Float32Array(pos1)\n const position2 = new Float32Array(pos2)\n const position = calculateCenterArray(position1, position2) as Float32Array\n const color = new Float32Array(col)\n const color2 = color\n\n const d: any = { position, position1, position2, color, color2 }\n\n if (rad) d.radius = new Float32Array(rad)\n if (pick && data.picking) {\n data.picking.array = new Float32Array(pick)\n d.picking = data.picking\n }\n if (id) d.primitiveId = new Float32Array(id)\n\n return d as T\n}\n","/**\n * @file Primitive\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Color, Box3 } from 'three'\n\nimport { BufferRegistry, PickerRegistry } from '../globals'\nimport Shape from './shape'\nimport { getFixedLengthDashData } from './dash'\n\nfunction addElement (elm: any, array: any[]) {\n if (elm.toArray !== undefined) {\n elm = elm.toArray()\n } else if (elm.x !== undefined) {\n elm = [ elm.x, elm.y, elm.z ]\n } else if (elm.r !== undefined) {\n elm = [ elm.r, elm.g, elm.b ]\n }\n array.push.apply(array, elm)\n}\n\nconst tmpVec = new Vector3()\n\nexport type PrimitiveFields = { [k: string]: string }\n\n/**\n * Base class for geometry primitives\n * @interface\n */\nexport abstract class Primitive {\n static type = ''\n static fields: PrimitiveFields = {}\n\n static get Picker () { return PickerRegistry.get(this.type) }\n static get Buffer () { return BufferRegistry.get(this.type) }\n\n static getShapeKey (name: string) {\n return this.type + name[0].toUpperCase() + name.substr(1)\n }\n\n static expandBoundingBox (box: Box3, data: any) {}\n\n static valueToShape (shape: Shape, name: string, value: any) {\n const data = shape._primitiveData[this.getShapeKey(name)]\n const type = this.fields[name]\n\n switch (type) {\n case 'v3':\n case 'c':\n addElement(value, data)\n break\n default:\n data.push(value)\n }\n }\n\n static objectToShape (shape: Shape, data: any) {\n Object.keys(this.fields).forEach(name => {\n this.valueToShape(shape, name, data[name])\n })\n this.valueToShape(shape, 'name', data.name)\n this.expandBoundingBox(shape.boundingBox, data)\n }\n\n static valueFromShape (shape: Shape, pid: number, name: string) {\n const data = shape._primitiveData[this.getShapeKey(name)]\n const type = this.fields[name]\n\n switch (type) {\n case 'v3':\n return new Vector3().fromArray(data, 3 * pid)\n case 'c':\n return new Color().fromArray(data, 3 * pid)\n default:\n return data[pid]\n }\n }\n\n static objectFromShape (shape: Shape, pid: number) {\n let name = this.valueFromShape(shape, pid, 'name')\n if (name === undefined) {\n name = `${this.type}: ${pid} (${shape.name})`\n }\n const o: any = { shape, name }\n\n Object.keys(this.fields).forEach(name => {\n o[name] = this.valueFromShape(shape, pid, name)\n })\n\n return o\n }\n\n static arrayFromShape (shape: Shape, name: string) {\n const data = shape._primitiveData[this.getShapeKey(name)]\n const type = this.fields[name]\n\n switch (type) {\n case 's':\n return data\n default:\n return new Float32Array(data)\n }\n }\n\n static dataFromShape (shape: Shape) {\n const data: any = {}\n\n if (this.Picker) {\n data.picking = new this.Picker(shape)\n }\n\n Object.keys(this.fields).forEach(name => {\n data[name] = this.arrayFromShape(shape, name)\n })\n\n return data\n }\n\n static bufferFromShape (shape: Shape, params: any) {\n return new this.Buffer(this.dataFromShape(shape), params)\n }\n}\n\n/**\n * Sphere geometry primitive\n */\nexport class SpherePrimitive extends Primitive {\n static type = 'sphere'\n\n static fields = {\n position: 'v3',\n color: 'c',\n radius: 'f'\n }\n\n static positionFromShape (shape: Shape, pid: number) {\n return this.valueFromShape(shape, pid, 'position')\n }\n\n static expandBoundingBox (box: Box3, data: any) {\n box.expandByPoint(tmpVec.fromArray(data.position))\n }\n}\n\n/**\n * Box geometry primitive\n */\nexport class BoxPrimitive extends Primitive {\n static type = 'box'\n\n static fields = {\n position: 'v3',\n color: 'c',\n size: 'f',\n heightAxis: 'v3',\n depthAxis: 'v3'\n }\n\n static positionFromShape (shape: Shape, pid: number) {\n return this.valueFromShape(shape, pid, 'position')\n }\n\n static expandBoundingBox (box: Box3, data: any) {\n box.expandByPoint(tmpVec.fromArray(data.position))\n }\n}\n\n/**\n * Octahedron geometry primitive\n */\nexport class OctahedronPrimitive extends BoxPrimitive {\n static type = 'octahedron'\n}\n\n/**\n * Tetrahedron geometry primitive\n */\nexport class TetrahedronPrimitive extends BoxPrimitive {\n static type = 'tetrahedron'\n}\n\n/**\n * Cylinder geometry primitive\n */\nexport class CylinderPrimitive extends Primitive {\n static type = 'cylinder'\n\n static fields = {\n position1: 'v3',\n position2: 'v3',\n color: 'c',\n radius: 'f'\n }\n\n static positionFromShape (shape: Shape, pid: number) {\n const p1 = this.valueFromShape(shape, pid, 'position1')\n const p2 = this.valueFromShape(shape, pid, 'position2')\n return p1.add(p2).multiplyScalar(0.5)\n }\n\n static expandBoundingBox (box: Box3, data: any) {\n box.expandByPoint(tmpVec.fromArray(data.position1))\n box.expandByPoint(tmpVec.fromArray(data.position2))\n }\n\n static bufferFromShape (shape: Shape, params: any = {}) {\n let data = this.dataFromShape(shape)\n if (this.type === 'cylinder' && params.dashedCylinder) {\n data = getFixedLengthDashData(data)\n }\n return new this.Buffer(data, params)\n }\n}\n\n/**\n * Arrow geometry primitive\n */\nexport class ArrowPrimitive extends CylinderPrimitive {\n static type = 'arrow'\n}\n\n/**\n * Cone geometry primitive\n */\nexport class ConePrimitive extends CylinderPrimitive {\n static type = 'cone'\n}\n\n/**\n * Ellipsoid geometry primitive\n */\nexport class EllipsoidPrimitive extends SpherePrimitive {\n static type = 'ellipsoid'\n\n static fields = {\n position: 'v3',\n color: 'c',\n radius: 'f',\n majorAxis: 'v3',\n minorAxis: 'v3'\n }\n}\n\n/**\n * Torus geometry primitive\n */\nexport class TorusPrimitive extends EllipsoidPrimitive {\n static type = 'torus'\n}\n\n/**\n * Text geometry primitive\n */\nexport class TextPrimitive extends Primitive {\n static type = 'text'\n\n static fields = {\n position: 'v3',\n color: 'c',\n size: 'f',\n text: 's'\n }\n\n static positionFromShape (shape: Shape, pid: number) {\n return this.valueFromShape(shape, pid, 'position')\n }\n\n static expandBoundingBox (box: Box3, data: any) {\n box.expandByPoint(tmpVec.fromArray(data.position))\n }\n}\n\n/**\n * Point primitive\n */\nexport class PointPrimitive extends Primitive {\n static type = 'point'\n\n static fields = {\n position: 'v3',\n color: 'c',\n }\n\n static positionFromShape (shape: Shape, pid: number) {\n return this.valueFromShape(shape, pid, 'position')\n }\n\n static expandBoundingBox (box: Box3, data: any) {\n box.expandByPoint(tmpVec.fromArray(data.position))\n }\n}\n\n/**\n * Wideline geometry primitive\n */\nexport class WidelinePrimitive extends Primitive {\n static type = 'wideline'\n\n static fields = {\n position1: 'v3',\n position2: 'v3',\n color: 'c'\n }\n\n static positionFromShape (shape: Shape, pid: number) {\n const p1 = this.valueFromShape(shape, pid, 'position1')\n const p2 = this.valueFromShape(shape, pid, 'position2')\n return p1.add(p2).multiplyScalar(0.5)\n }\n\n static expandBoundingBox (box: Box3, data: any) {\n box.expandByPoint(tmpVec.fromArray(data.position1))\n box.expandByPoint(tmpVec.fromArray(data.position2))\n }\n}\n","/**\n * @file Spatial Hash\n * @author Alexander Rose \n * @private\n */\n\nimport { Box3 } from 'three'\n\nexport type Positions = {\n x: ArrayLike,\n y: ArrayLike,\n z: ArrayLike,\n count?:number\n}\n\nfunction createBoundingBox(positions: Positions) {\n const { x, y, z } = positions\n const boundingBox = new Box3()\n const count = x.length\n const { min, max } = boundingBox\n\n for (let i = 0; i < count; i++) {\n min.x = Math.min(x[i], min.x)\n min.y = Math.min(y[i], min.y)\n min.z = Math.min(z[i], min.z)\n max.x = Math.max(x[i], max.x)\n max.y = Math.max(y[i], max.y)\n max.z = Math.max(z[i], max.z)\n }\n\n return boundingBox\n}\n\nexport default class SpatialHash {\n exp = 3\n\n minX: number\n minY: number\n minZ: number\n\n boundX: number\n boundY: number\n boundZ: number\n\n grid: Uint32Array\n bucketCount: Uint16Array\n bucketOffset: Uint32Array\n bucketArray: Int32Array\n\n xArray: ArrayLike\n yArray: ArrayLike\n zArray: ArrayLike\n\n constructor(positions: Positions, boundingBox?: Box3) {\n const bb = boundingBox || createBoundingBox(positions)\n this.minX = bb.min.x\n this.minY = bb.min.y\n this.minZ = bb.min.z\n this.boundX = ((bb.max.x - this.minX) >> this.exp) + 1\n this.boundY = ((bb.max.y - this.minY) >> this.exp) + 1\n this.boundZ = ((bb.max.z - this.minZ) >> this.exp) + 1\n\n const n = this.boundX * this.boundY * this.boundZ\n const an = (positions.count !== undefined) ? positions.count : positions.x.length\n\n const xArray = positions.x\n const yArray = positions.y\n const zArray = positions.z\n\n let count = 0\n const grid = new Uint32Array(n)\n const bucketIndex = new Int32Array(an)\n for (let i = 0; i < an; ++i) {\n const x = (xArray[ i ] - this.minX) >> this.exp\n const y = (yArray[ i ] - this.minY) >> this.exp\n const z = (zArray[ i ] - this.minZ) >> this.exp\n const idx = (((x * this.boundY) + y) * this.boundZ) + z\n if ((grid[ idx ] += 1) === 1) {\n count += 1\n }\n bucketIndex[ i ] = idx\n }\n\n const bucketCount = new Uint16Array(count)\n for (let i = 0, j = 0; i < n; ++i) {\n const c = grid[ i ]\n if (c > 0) {\n grid[ i ] = j + 1\n bucketCount[ j ] = c\n j += 1\n }\n }\n\n const bucketOffset = new Uint32Array(count)\n for (let i = 1; i < count; ++i) {\n bucketOffset[ i ] += bucketOffset[ i - 1 ] + bucketCount[ i - 1 ]\n }\n\n const bucketFill = new Uint16Array(count)\n const bucketArray = new Int32Array(an)\n for (let i = 0; i < an; ++i) {\n const bucketIdx = grid[ bucketIndex[ i ] ]\n if (bucketIdx > 0) {\n const k = bucketIdx - 1\n bucketArray[ bucketOffset[ k ] + bucketFill[ k ] ] = i\n bucketFill[ k ] += 1\n }\n }\n\n this.grid = grid\n this.bucketCount = bucketCount\n this.bucketOffset = bucketOffset\n this.bucketArray = bucketArray\n\n this.xArray = xArray\n this.yArray = yArray\n this.zArray = zArray\n }\n\n within (x: number, y: number, z: number, r: number) {\n const result: number[] = []\n\n this.eachWithin(x, y, z, r, atomIndex => result.push(atomIndex))\n\n return result\n }\n\n eachWithin (x: number, y: number, z: number, r: number, callback: (atomIndex: number, dSq: number) => void) {\n const rSq = r * r\n\n const loX = Math.max(0, (x - r - this.minX) >> this.exp)\n const loY = Math.max(0, (y - r - this.minY) >> this.exp)\n const loZ = Math.max(0, (z - r - this.minZ) >> this.exp)\n\n const hiX = Math.min(this.boundX, ((x + r - this.minX) >> this.exp) + 1)\n const hiY = Math.min(this.boundY, ((y + r - this.minY) >> this.exp) + 1)\n const hiZ = Math.min(this.boundZ, ((z + r - this.minZ) >> this.exp) + 1)\n\n for (let ix = loX; ix < hiX; ++ix) {\n for (let iy = loY; iy < hiY; ++iy) {\n for (let iz = loZ; iz < hiZ; ++iz) {\n const idx = (((ix * this.boundY) + iy) * this.boundZ) + iz\n const bucketIdx = this.grid[ idx ]\n\n if (bucketIdx > 0) {\n const k = bucketIdx - 1\n const offset = this.bucketOffset[ k ]\n const count = this.bucketCount[ k ]\n const end = offset + count\n\n for (let i = offset; i < end; ++i) {\n const atomIndex = this.bucketArray[ i ]\n const dx = this.xArray[ atomIndex ] - x\n const dy = this.yArray[ atomIndex ] - y\n const dz = this.zArray[ atomIndex ] - z\n\n const dSq = dx * dx + dy * dy + dz * dz\n if (dSq <= rSq) callback(atomIndex, dSq)\n }\n }\n }\n }\n }\n }\n}","/**\n * @file Store\n * @author Alexander Rose \n * @private\n */\n\nimport { Log } from '../globals'\nimport { getTypedArray, TypedArrayString } from '../utils'\n\nexport type StoreField = [string, number, TypedArrayString]\n\n/**\n * Store base class\n * @interface\n */\nexport default class Store {\n [k: string]: any\n\n length: number\n count: number\n\n _fields: StoreField[]\n get _defaultFields(): StoreField[] { return [] }\n\n /**\n * @param {Integer} [size] - initial size\n */\n constructor (size = 0) {\n this._fields = this._defaultFields\n this._init(0)\n }\n\n /**\n * Initialize the store\n * @param {Integer} size - size to initialize\n * @return {undefined}\n */\n _init (size: number) {\n this.length = size\n this.count = 0\n\n for (let i = 0, il = this._fields.length; i < il; ++i) {\n const [name, size, type]: StoreField = this._fields[ i ]\n this._initField(name, size, type)\n }\n }\n\n /**\n * Initialize a field\n * @param {String} name - field name\n * @param {Integer} size - element size\n * @param {String} type - data type, one of int8, int16, int32,\n * uint8, uint16, uint32, float32\n * @return {undefined}\n */\n _initField (name: string, size: number, type: TypedArrayString) {\n this[ name ] = getTypedArray(type, this.length * size)\n }\n\n /**\n * Add a field\n * @param {String} name - field name\n * @param {Integer} size - element size\n * @param {String} type - data type, one of int8, int16, int32,\n * uint8, uint16, uint32, float32\n * @return {undefined}\n */\n addField (name: string, size: number, type: TypedArrayString) {\n this._fields.push([name, size, type])\n this._initField(name, size, type)\n }\n\n /**\n * Resize the store to the new size\n * @param {Integer} size - new size\n * @return {undefined}\n */\n resize (size?: number) {\n // Log.time( \"Store.resize\" );\n\n this.length = Math.round(size || 0)\n this.count = Math.min(this.count, this.length)\n\n for (let i = 0, il = this._fields.length; i < il; ++i) {\n const name = this._fields[ i ][ 0 ]\n const itemSize = this._fields[ i ][ 1 ]\n const arraySize = this.length * itemSize\n const tmpArray = new this[ name ].constructor(arraySize)\n\n if (this[ name ].length > arraySize) {\n tmpArray.set(this[ name ].subarray(0, arraySize))\n } else {\n tmpArray.set(this[ name ])\n }\n this[ name ] = tmpArray\n }\n\n // Log.timeEnd( \"Store.resize\" );\n }\n\n /**\n * Resize the store to 1.5 times its current size if full\n * @return {undefined}\n */\n growIfFull () {\n if (this.count >= this.length) {\n const size = Math.round(this.length * 1.5)\n this.resize(Math.max(256, size))\n }\n }\n\n /**\n * Copy data from one store to another\n * @param {Store} other - store to copy from\n * @param {Integer} thisOffset - offset to start copying to\n * @param {Integer} otherOffset - offset to start copying from\n * @param {Integer} length - number of entries to copy\n * @return {undefined}\n */\n copyFrom (other: Store, thisOffset: number, otherOffset: number, length: number) {\n for (let i = 0, il = this._fields.length; i < il; ++i) {\n const name = this._fields[ i ][ 0 ]\n const itemSize = this._fields[ i ][ 1 ]\n const thisField = this[ name ]\n const otherField = other[ name ]\n\n for (let j = 0; j < length; ++j) {\n const thisIndex = itemSize * (thisOffset + j)\n const otherIndex = itemSize * (otherOffset + j)\n for (let k = 0; k < itemSize; ++k) {\n thisField[ thisIndex + k ] = otherField[ otherIndex + k ]\n }\n }\n }\n }\n\n /**\n * Copy data within this store\n * @param {Integer} thisOffset - offset to start copying to\n * @param {Integer} otherOffset - offset to start copying from\n * @param {Integer} length - number of entries to copy\n * @return {undefined}\n */\n copyWithin (offsetTarget: number, offsetSource: number, length: number) {\n for (let i = 0, il = this._fields.length; i < il; ++i) {\n const name = this._fields[ i ][ 0 ]\n const itemSize = this._fields[ i ][ 1 ]\n const thisField = this[ name ]\n\n for (let j = 0; j < length; ++j) {\n const targetIndex = itemSize * (offsetTarget + j)\n const sourceIndex = itemSize * (offsetSource + j)\n for (let k = 0; k < itemSize; ++k) {\n thisField[ targetIndex + k ] = thisField[ sourceIndex + k ]\n }\n }\n }\n }\n\n /**\n * Sort entries in the store given the compare function\n * @param {[type]} compareFunction - function to sort by\n * @return {undefined}\n */\n sort (compareFunction: (a: any, b: any) => number) {\n Log.time('Store.sort')\n\n const thisStore = this\n const tmpStore = new (this.constructor as any)(1)\n\n function swap (index1: number, index2: number) {\n if (index1 === index2) return\n tmpStore.copyFrom(thisStore, 0, index1, 1)\n thisStore.copyWithin(index1, index2, 1)\n thisStore.copyFrom(tmpStore, index2, 0, 1)\n }\n\n function quicksort (left: number, right: number) {\n if (left < right) {\n let pivot = Math.floor((left + right) / 2)\n let leftNew = left\n let rightNew = right\n do {\n while (compareFunction(leftNew, pivot) < 0) {\n leftNew += 1\n }\n while (compareFunction(rightNew, pivot) > 0) {\n rightNew -= 1\n }\n if (leftNew <= rightNew) {\n if (leftNew === pivot) {\n pivot = rightNew\n } else if (rightNew === pivot) {\n pivot = leftNew\n }\n swap(leftNew, rightNew)\n leftNew += 1\n rightNew -= 1\n }\n } while (leftNew <= rightNew)\n quicksort(left, rightNew)\n quicksort(leftNew, right)\n }\n }\n\n quicksort(0, this.count - 1)\n\n Log.timeEnd('Store.sort')\n }\n\n /**\n * Empty the store\n * @return {undefined}\n */\n clear () {\n this.count = 0\n }\n\n /**\n * Dispose of the store entries and fields\n * @return {undefined}\n */\n dispose () {\n\n for (let i = 0, il = this._fields.length; i < il; ++i) {\n const name = this._fields[ i ][ 0 ]\n delete this[ name ]\n }\n }\n}\n","/**\n * @file Contact Store\n * @author Alexander Rose \n * @private\n */\n\nimport Store, { StoreField } from './store'\n\n/**\n * Bond store\n */\nexport default class ContactStore extends Store {\n index1: Uint32Array\n index2: Uint32Array\n type: Uint8Array\n\n get _defaultFields () {\n return [\n [ 'index1', 1, 'int32' ],\n [ 'index2', 1, 'int32' ],\n [ 'type', 1, 'int8' ]\n ] as StoreField[]\n }\n\n addContact (index1: number, index2: number, type?: number) {\n this.growIfFull()\n\n const i = this.count\n\n if (index1 < index2) {\n this.index1[ i ] = index1\n this.index2[ i ] = index2\n } else {\n this.index2[ i ] = index1\n this.index1[ i ] = index2\n }\n if (type) this.type[ i ] = type\n\n this.count += 1\n }\n}","/**\n * @file Bit array\n * @author Alexander Rose \n * @author Paul Pillot \n * @private\n */\n\n/**\n * Compute the Hamming weight of a 32-bit unsigned integer\n * @param {Integer} v - a 32-bit unsigned integer\n * @return {Integer} the Hamming weight\n */\nfunction hammingWeight (v: number) {\n // works with signed or unsigned shifts\n v -= ((v >>> 1) & 0x55555555)\n v = (v & 0x33333333) + ((v >>> 2) & 0x33333333)\n return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24\n}\n\n/**\n * Bit array\n *\n * Based heavily on https://github.com/lemire/FastBitSet.js\n * which is licensed under the Apache License, Version 2.0.\n */\nexport default class BitArray {\n private _words: Uint32Array\n public length: number\n\n /**\n * @param {Integer} length - array length\n * @param {Boolean} [setAll] - initialize with true\n */\n constructor (length: number, setAll?: boolean) {\n this.length = length\n this._words = new Uint32Array((length + 32) >>> 5)\n if (setAll === true) {\n this.setAll()\n }\n }\n\n /**\n * Get value at index\n * @param {Integer} index - the index\n * @return {Boolean} value\n */\n get (index: number) {\n return (this._words[ index >>> 5 ] & (1 << index)) !== 0\n }\n\n /**\n * Set value at index to true\n * @param {Integer} index - the index\n * @return {undefined}\n */\n set (index: number) {\n this._words[ index >>> 5 ] |= 1 << index\n }\n\n /**\n * Set value at index to false\n * @param {Integer} index - the index\n * @return {undefined}\n */\n clear (index: number) {\n this._words[ index >>> 5 ] &= ~(1 << index)\n }\n\n /**\n * Flip value at index\n * @param {Integer} index - the index\n * @return {undefined}\n */\n flip (index: number) {\n this._words[ index >>> 5 ] ^= 1 << index\n }\n\n _assignRange (start: number, end: number, value: boolean) {\n if (end < start) return\n const words = this._words\n const wordValue = value === true ? 0xFFFFFFFF : 0\n const wordStart = start >>> 5\n const wordEnd = end >>> 5\n // set complete words when applicable\n for (let k = wordStart + 1; k < wordEnd; ++k) {\n words[ k ] = wordValue\n }\n // set parts of the range not spanning complete words\n const startWord = wordStart << 5\n const endWord = wordEnd << 5\n if (value === true) {\n if (end - start < 32) {\n for (let i = start, n = end + 1; i < n; ++i) {\n words[ i >>> 5 ] |= 1 << i\n }\n } else {\n for (let i = start, n = startWord + 32; i < n; ++i) {\n words[ i >>> 5 ] |= 1 << i\n }\n for (let i = endWord, n = end + 1; i < n; ++i) {\n words[ i >>> 5 ] |= 1 << i\n }\n }\n } else {\n if (end - start < 32) {\n for (let i = start, n = end + 1; i < n; ++i) {\n words[ i >>> 5 ] &= ~(1 << i)\n }\n } else {\n for (let i = start, n = startWord + 32; i < n; ++i) {\n words[ i >>> 5 ] &= ~(1 << i)\n }\n for (let i = endWord, n = end + 1; i < n; ++i) {\n words[ i >>> 5 ] &= ~(1 << i)\n }\n }\n }\n return this\n }\n\n /**\n * Set bits of the given range\n * @param {Integer} start - start index\n * @param {Integer} end - end index\n * @return {BitArray} this object\n */\n setRange (start: number, end: number) {\n return this._assignRange(start, end, true)\n }\n\n /**\n * Clear bits of the given range\n * @param {Integer} start - start index\n * @param {Integer} end - end index\n * @return {BitArray} this object\n */\n clearRange (start: number, end: number) {\n return this._assignRange(start, end, false)\n }\n\n /**\n * Set bits at all given indices\n * @param {...Integer} arguments - indices\n * @return {Boolean} this object\n */\n setBits (...indices: number[]) {\n const words = this._words\n const n = indices.length\n for (let i = 0; i < n; ++i) {\n const index = indices[ i ]\n words[ index >>> 5 ] |= 1 << index\n }\n return this\n }\n\n /**\n * Clear bits at all given indices\n * @param {...Integer} arguments - indices\n * @return {Boolean} this object\n */\n clearBits (...indices: number[]) {\n const words = this._words\n const n = indices.length\n for (let i = 0; i < n; ++i) {\n const index = indices[ i ]\n words[ index >>> 5 ] &= ~(1 << index)\n }\n return this\n }\n\n /**\n * Set all bits of the array\n * @return {BitArray} this object\n */\n setAll () {\n return this._assignRange(0, this.length - 1, true)\n }\n\n /**\n * Clear all bits of the array\n * @return {BitArray} this object\n */\n clearAll () {\n return this._assignRange(0, this.length - 1, false)\n }\n\n /**\n * Flip all the values in the array\n * @return {BitArray} this object\n */\n flipAll () {\n const count = this._words.length\n const words = this._words\n const bs = 32 - this.length % 32\n for (let k = 0; k < count - 1; ++k) {\n words[k] = ~words[ k ]\n }\n words[ count - 1 ] = (~(words[ count - 1 ] << bs)) >>> bs\n return this\n }\n\n _isRangeValue (start: number, end: number, value: boolean) {\n if (end < start) return\n const words = this._words\n const wordValue = value === true ? 0xFFFFFFFF : 0\n const wordStart = start >>> 5\n const wordEnd = end >>> 5\n // set complete words when applicable\n for (let k = wordStart + 1; k < wordEnd; ++k) {\n if (words[ k ] !== wordValue) return false\n }\n // set parts of the range not spanning complete words\n if (end - start < 32) {\n for (let i = start, n = end + 1; i < n; ++i) {\n if (!!(words[ i >>> 5 ] & (1 << i)) !== value) return false\n }\n } else {\n const startWord = wordStart << 5\n const endWord = wordEnd << 5\n for (let i = start, n = startWord + 32; i < n; ++i) {\n if (!!(words[ i >>> 5 ] & (1 << i)) !== value) return false\n }\n for (let i = endWord, n = end + 1; i < n; ++i) {\n if (!!(words[ i >>> 5 ] & (1 << i)) !== value) return false\n }\n }\n return true\n }\n\n /**\n * Test if bits in given range are set\n * @param {Integer} start - start index\n * @param {Integer} end - end index\n * @return {BitArray} this object\n */\n isRangeSet (start: number, end: number) {\n return this._isRangeValue(start, end, true)\n }\n\n /**\n * Test if bits in given range are clear\n * @param {Integer} start - start index\n * @param {Integer} end - end index\n * @return {BitArray} this object\n */\n isRangeClear (start: number, end: number) {\n return this._isRangeValue(start, end, false)\n }\n\n /**\n * Test if all bits in the array are set\n * @return {Boolean} test result\n */\n isAllSet () {\n return this._isRangeValue(0, this.length - 1, true)\n }\n\n /**\n * Test if all bits in the array are clear\n * @return {Boolean} test result\n */\n isAllClear () {\n return this._isRangeValue(0, this.length - 1, false)\n }\n\n /**\n * Test if bits at all given indices are set\n * @param {...Integer} arguments - indices\n * @return {Boolean} test result\n */\n isSet (...indices: number[]) {\n const words = this._words\n const n = indices.length\n for (let i = 0; i < n; ++i) {\n const index = indices[ i ]\n if ((words[ index >>> 5 ] & (1 << index)) === 0) return false\n }\n return true\n }\n\n /**\n * Test if bits at all given indices are clear\n * @param {...Integer} arguments - indices\n * @return {Boolean} test result\n */\n isClear (...indices: number[]) {\n const words = this._words\n const n = indices.length\n for (let i = 0; i < n; ++i) {\n const index = indices[ i ]\n if ((words[ index >>> 5 ] & (1 << index)) !== 0) return false\n }\n return true\n }\n\n /**\n * Test if two BitArrays are identical in all their values\n * @param {BitArray} otherBitarray - the other BitArray\n * @return {Boolean} test result\n */\n isEqualTo (otherBitarray: BitArray) {\n const words1 = this._words\n const words2 = otherBitarray._words\n const count = Math.min(words1.length, words2.length)\n for (let k = 0; k < count; ++k) {\n if (words1[ k ] !== words2[ k ]) {\n return false\n }\n }\n return true\n }\n\n /**\n * How many set bits?\n * @return {Integer} number of set bits\n */\n getSize () {\n const count = this._words.length\n const words = this._words\n let size = 0\n for (let i = 0; i < count; ++i) {\n size += hammingWeight(words[ i ])\n }\n return size\n }\n\n /**\n * Calculate difference betwen this and another bit array.\n * Store result in this object.\n * @param {BitArray} otherBitarray - the other bit array\n * @return {BitArray} this object\n */\n difference (otherBitarray: BitArray) {\n const words1 = this._words\n const words2 = otherBitarray._words\n const count = Math.min(words1.length, words2.length)\n for (let k = 0; k < count; ++k) {\n words1[ k ] = words1[ k ] & ~words2[ k ]\n }\n for (let k = words1.length; k < count; ++k) {\n words1[ k ] = 0\n }\n return this\n }\n\n /**\n * Calculate union betwen this and another bit array.\n * Store result in this object.\n * @param {BitArray} otherBitarray - the other bit array\n * @return {BitArray} this object\n */\n union (otherBitarray: BitArray) {\n const words1 = this._words\n const words2 = otherBitarray._words\n const count = Math.min(words1.length, words2.length)\n for (let k = 0; k < count; ++k) {\n words1[ k ] |= words2[ k ]\n }\n for (let k = words1.length; k < count; ++k) {\n words1[ k ] = 0\n }\n return this\n }\n\n /**\n * Calculate intersection betwen this and another bit array.\n * Store result in this object.\n * @param {BitArray} otherBitarray - the other bit array\n * @return {BitArray} this object\n */\n intersection (otherBitarray: BitArray) {\n const words1 = this._words\n const words2 = otherBitarray._words\n const count = Math.min(words1.length, words2.length)\n for (let k = 0; k < count; ++k) {\n words1[ k ] &= words2[ k ]\n }\n for (let k = words1.length; k < count; ++k) {\n words1[ k ] = 0\n }\n return this\n }\n\n /**\n * Test if there is any intersection betwen this and another bit array.\n * @param {BitArray} otherBitarray - the other bit array\n * @return {Boolean} test result\n */\n intersects (otherBitarray: BitArray) {\n const words1 = this._words\n const words2 = otherBitarray._words\n const count = Math.min(words1.length, words2.length)\n for (let k = 0; k < count; ++k) {\n if ((words1[ k ] & words2[ k ]) !== 0) {\n return true\n }\n }\n return false\n }\n\n /**\n * Calculate the number of bits in common betwen this and another bit array.\n * @param {BitArray} otherBitarray - the other bit array\n * @return {Integer} size\n */\n getIntersectionSize (otherBitarray: BitArray) {\n const words1 = this._words\n const words2 = otherBitarray._words\n const count = Math.min(words1.length, words2.length)\n let size = 0\n for (let k = 0; k < count; ++k) {\n size += hammingWeight(words1[ k ] & words2[ k ])\n }\n return size\n }\n\n /**\n * Calculate intersection betwen this and another bit array.\n * Store result in a new bit array.\n * @param {BitArray} otherBitarray - the other bit array\n * @return {BitArray} the new bit array\n */\n makeIntersection (otherBitarray: BitArray) {\n const words1 = this._words\n const words2 = otherBitarray._words\n const count = Math.min(words1.length, words2.length)\n const wordsA = new Uint32Array(count)\n const intersection = Object.create(BitArray.prototype)\n intersection._words = wordsA\n intersection.length = Math.min(this.length, otherBitarray.length)\n for (let k = 0; k < count; ++k) {\n wordsA[ k ] = words1[ k ] & words2[ k ]\n }\n return intersection\n }\n\n /**\n * Iterate over all set bits in the array\n * @param {function( index: Integer, i: Integer )} callback - the callback\n * @return {undefined}\n */\n forEach (callback: (index: number, i: number) => any) {\n const count = this._words.length\n const words = this._words\n let i = 0\n for (let k = 0; k < count; ++k) {\n let w = words[ k ]\n while (w !== 0) {\n const t = w & -w\n const index = (k << 5) + hammingWeight(t - 1)\n callback(index, i)\n w ^= t\n ++i\n }\n }\n }\n\n /**\n * Get an array with the set bits\n * @return {Array} bit indices\n */\n toArray () {\n const words = this._words\n const answer = new Array(this.getSize())\n const count = this._words.length\n let pos = 0\n for (let k = 0; k < count; ++k) {\n let w = words[ k ]\n while (w !== 0) {\n const t = w & -w\n answer[ pos++ ] = (k << 5) + hammingWeight(t - 1)\n w ^= t\n }\n }\n return answer\n }\n\n toString () {\n return '{' + this.toArray().join(',') + '}'\n }\n\n toSeleString () {\n const sele = this.toArray().join(',')\n return sele ? '@' + sele : 'NONE'\n }\n\n /**\n * Clone this object\n * @return {BitArray} the cloned object\n */\n clone () {\n const clone = Object.create(BitArray.prototype)\n clone.length = this.length\n clone._words = new Uint32Array(this._words)\n return clone\n }\n}","/**\n * @file Adjacency List\n * @author Alexander Rose \n * @private\n */\n\nexport interface Edges {\n nodeArray1: ArrayLike\n nodeArray2: ArrayLike\n edgeCount: number\n nodeCount: number\n}\n\nexport interface AdjacencyList {\n /* number of edges for each node */\n countArray: Uint8Array\n /* offset into indexArray for each node */\n offsetArray: Int32Array\n /* edge indices, grouped by nodes */\n indexArray: Int32Array\n}\n\nexport function createAdjacencyList (edges: Edges): AdjacencyList {\n const { edgeCount, nodeCount, nodeArray1, nodeArray2 } = edges\n\n const countArray = new Uint8Array(nodeCount)\n const offsetArray = new Int32Array(nodeCount)\n\n // count edges per node\n for (let i = 0; i < edgeCount; ++i) {\n countArray[ nodeArray1[ i ] ] += 1\n countArray[ nodeArray2[ i ] ] += 1\n }\n\n // get offsets to node edges\n for (let i = 1; i < nodeCount; ++i) {\n offsetArray[ i ] += offsetArray[ i - 1 ] + countArray[ i - 1 ]\n }\n\n // prepare index array\n const bondCount2 = edgeCount * 2\n const indexArray = new Int32Array(bondCount2)\n for (let j = 0; j < bondCount2; ++j) {\n indexArray[ j ] = -1\n }\n\n // build index array\n for (let i = 0; i < edgeCount; ++i) {\n const idx1 = nodeArray1[ i ]\n const idx2 = nodeArray2[ i ]\n let j1 = offsetArray[ idx1 ]\n while (indexArray[ j1 ] !== -1 && j1 < bondCount2) {\n j1 += 1\n }\n indexArray[ j1 ] = i\n let j2 = offsetArray[ idx2 ]\n while (indexArray[ j2 ] !== -1 && j2 < bondCount2) {\n j2 += 1\n }\n indexArray[ j2 ] = i\n }\n\n return { countArray, offsetArray, indexArray }\n}\n","/**\n * @file Features\n * @author Alexander Rose \n */\n\nimport AtomProxy from '../../proxy/atom-proxy'\n\nexport interface Features {\n types: FeatureType[]\n groups: FeatureGroup[]\n centers: { x: number[], y: number[], z: number[] }\n atomSets: number[][]\n}\n\nexport const enum FeatureType {\n Unknown = 0,\n PositiveCharge = 1,\n NegativeCharge = 2,\n AromaticRing = 3,\n HydrogenDonor = 4,\n HydrogenAcceptor = 5,\n HalogenDonor = 6,\n HalogenAcceptor = 7,\n Hydrophobic = 8,\n WeakHydrogenDonor = 9,\n IonicTypePartner = 10,\n DativeBondPartner = 11,\n TransitionMetal = 12,\n IonicTypeMetal = 13\n}\n\nexport const enum FeatureGroup {\n Unknown = 0,\n QuaternaryAmine = 1,\n TertiaryAmine = 2,\n Sulfonium = 3,\n SulfonicAcid = 4,\n Sulfate = 5,\n Phosphate = 6,\n Halocarbon = 7,\n Guanidine = 8,\n Acetamidine = 9,\n Carboxylate = 10\n}\n\nexport function createFeatures (): Features {\n return {\n types: [],\n groups: [],\n centers: { x: [], y: [], z: [] },\n atomSets: []\n }\n}\n\nexport interface FeatureState {\n type: FeatureType\n group: FeatureGroup\n x: number\n y: number\n z: number\n atomSet: number[]\n}\n\nexport function createFeatureState(type = FeatureType.Unknown, group = FeatureGroup.Unknown): FeatureState {\n return { type, group, x: 0, y: 0, z: 0, atomSet: [] }\n}\n\nexport function addAtom (state: FeatureState, atom: AtomProxy) {\n state.x += atom.x\n state.y += atom.y\n state.z += atom.z\n state.atomSet.push(atom.index)\n}\n\nexport function addFeature (features: Features, state: FeatureState) {\n const n = state.atomSet.length\n if (n > 0) {\n const { types, groups, centers, atomSets } = features\n types.push(state.type)\n groups.push(state.group)\n centers.x.push(state.x / n)\n centers.y.push(state.y / n)\n centers.z.push(state.z / n)\n atomSets.push(state.atomSet)\n }\n}\n","/**\n * @file Structure Constants\n * @author Alexander Rose \n * @private\n */\n\n// entity types\nexport const UnknownEntity = 0\nexport const PolymerEntity = 1\nexport const NonPolymerEntity = 2\nexport const MacrolideEntity = 3\nexport const WaterEntity = 4\n\n// molecule types\nexport const UnknownType = 0\nexport const WaterType = 1\nexport const IonType = 2\nexport const ProteinType = 3\nexport const RnaType = 4\nexport const DnaType = 5\nexport const SaccharideType = 6\n\n// backbone types\nexport const UnknownBackboneType = 0\nexport const ProteinBackboneType = 1\nexport const RnaBackboneType = 2\nexport const DnaBackboneType = 3\nexport const CgProteinBackboneType = 4\nexport const CgRnaBackboneType = 5\nexport const CgDnaBackboneType = 6\n\n// chemical component types\nexport const ChemCompProtein = [\n 'D-BETA-PEPTIDE, C-GAMMA LINKING', 'D-GAMMA-PEPTIDE, C-DELTA LINKING',\n 'D-PEPTIDE COOH CARBOXY TERMINUS', 'D-PEPTIDE NH3 AMINO TERMINUS', 'D-PEPTIDE LINKING',\n 'L-BETA-PEPTIDE, C-GAMMA LINKING', 'L-GAMMA-PEPTIDE, C-DELTA LINKING',\n 'L-PEPTIDE COOH CARBOXY TERMINUS', 'L-PEPTIDE NH3 AMINO TERMINUS', 'L-PEPTIDE LINKING',\n 'PEPTIDE LINKING', 'PEPTIDE-LIKE'\n]\nexport const ChemCompRna = [\n 'RNA OH 3 PRIME TERMINUS', 'RNA OH 5 PRIME TERMINUS', 'RNA LINKING'\n]\nexport const ChemCompDna = [\n 'DNA OH 3 PRIME TERMINUS', 'DNA OH 5 PRIME TERMINUS', 'DNA LINKING',\n 'L-DNA LINKING', 'L-RNA LINKING'\n]\nexport const ChemCompSaccharide = [\n 'D-SACCHARIDE', 'D-SACCHARIDE 1,4 AND 1,4 LINKING', 'D-SACCHARIDE 1,4 AND 1,6 LINKING',\n 'L-SACCHARIDE', 'L-SACCHARIDE 1,4 AND 1,4 LINKING', 'L-SACCHARIDE 1,4 AND 1,6 LINKING',\n 'SACCHARIDE'\n]\nexport const ChemCompOther = [\n 'OTHER'\n]\nexport const ChemCompNonPolymer = [\n 'NON-POLYMER'\n]\nexport const ChemCompHetero = ChemCompNonPolymer.concat(ChemCompOther, ChemCompSaccharide)\n\n// secondary structure\nexport const SecStrucHelix = [ 'h', 'g', 'i' ]\nexport const SecStrucSheet = [ 'e', 'b' ]\nexport const SecStrucTurn = [ 's', 't', 'l', '' ]\n\nexport const AtomicNumbers: { [e: string]: number | undefined } = {\n 'H': 1, 'D': 1, 'T': 1, 'HE': 2, 'LI': 3, 'BE': 4, 'B': 5, 'C': 6, 'N': 7, 'O': 8, 'F': 9, 'NE': 10, 'NA': 11, 'MG': 12, 'AL': 13, 'SI': 14, 'P': 15, 'S': 16, 'CL': 17, 'AR': 18, 'K': 19, 'CA': 20, 'SC': 21, 'TI': 22, 'V': 23, 'CR': 24, 'MN': 25, 'FE': 26, 'CO': 27, 'NI': 28, 'CU': 29, 'ZN': 30, 'GA': 31, 'GE': 32, 'AS': 33, 'SE': 34, 'BR': 35, 'KR': 36, 'RB': 37, 'SR': 38, 'Y': 39, 'ZR': 40, 'NB': 41, 'MO': 42, 'TC': 43, 'RU': 44, 'RH': 45, 'PD': 46, 'AG': 47, 'CD': 48, 'IN': 49, 'SN': 50, 'SB': 51, 'TE': 52, 'I': 53, 'XE': 54, 'CS': 55, 'BA': 56, 'LA': 57, 'CE': 58, 'PR': 59, 'ND': 60, 'PM': 61, 'SM': 62, 'EU': 63, 'GD': 64, 'TB': 65, 'DY': 66, 'HO': 67, 'ER': 68, 'TM': 69, 'YB': 70, 'LU': 71, 'HF': 72, 'TA': 73, 'W': 74, 'RE': 75, 'OS': 76, 'IR': 77, 'PT': 78, 'AU': 79, 'HG': 80, 'TL': 81, 'PB': 82, 'BI': 83, 'PO': 84, 'AT': 85, 'RN': 86, 'FR': 87, 'RA': 88, 'AC': 89, 'TH': 90, 'PA': 91, 'U': 92, 'NP': 93, 'PU': 94, 'AM': 95, 'CM': 96, 'BK': 97, 'CF': 98, 'ES': 99, 'FM': 100, 'MD': 101, 'NO': 102, 'LR': 103, 'RF': 104, 'DB': 105, 'SG': 106, 'BH': 107, 'HS': 108, 'MT': 109, 'DS': 110, 'RG': 111, 'CN': 112, 'NH': 113, 'FL': 114, 'MC': 115, 'LV': 116, 'TS': 117, 'OG': 118\n}\nexport const DefaultAtomicNumber = 0\n\n/**\n * Enum mapping element to atomic number\n */\nexport const enum Elements {\n H = 1, D = 1, T = 1, HE = 2, LI = 3, BE = 4, B = 5, C = 6, N = 7, O = 8, F = 9, NE = 10, NA = 11, MG = 12, AL = 13, SI = 14, P = 15, S = 16, CL = 17, AR = 18, K = 19, CA = 20, SC = 21, TI = 22, V = 23, CR = 24, MN = 25, FE = 26, CO = 27, NI = 28, CU = 29, ZN = 30, GA = 31, GE = 32, AS = 33, SE = 34, BR = 35, KR = 36, RB = 37, SR = 38, Y = 39, ZR = 40, NB = 41, MO = 42, TC = 43, RU = 44, RH = 45, PD = 46, AG = 47, CD = 48, IN = 49, SN = 50, SB = 51, TE = 52, I = 53, XE = 54, CS = 55, BA = 56, LA = 57, CE = 58, PR = 59, ND = 60, PM = 61, SM = 62, EU = 63, GD = 64, TB = 65, DY = 66, HO = 67, ER = 68, TM = 69, YB = 70, LU = 71, HF = 72, TA = 73, W = 74, RE = 75, OS = 76, IR = 77, PT = 78, AU = 79, HG = 80, TL = 81, PB = 82, BI = 83, PO = 84, AT = 85, RN = 86, FR = 87, RA = 88, AC = 89, TH = 90, PA = 91, U = 92, NP = 93, PU = 94, AM = 95, CM = 96, BK = 97, CF = 98, ES = 99, FM = 100, MD = 101, NO = 102, LR = 103, RF = 104, DB = 105, SG = 106, BH = 107, HS = 108, MT = 109, DS = 110, RG = 111, CN = 112, NH = 113, FL = 114, MC = 115, LV = 116, TS = 117, OG = 118\n}\n\n// https://doi.org/10.1515/pac-2015-0305 (table 2, 3, and 4)\nexport const AtomWeights: { [e: number]: number | undefined } = {\n 1: 1.008, 2: 4.0026, 3: 6.94, 4: 9.0122, 5: 10.81, 6: 10.81, 7: 14.007, 8: 15.999, 9: 18.998, 10: 20.180, 11: 22.990, 12: 24.305, 13: 26.982, 14: 28.085, 15: 30.974, 16: 32.06, 17: 35.45, 18: 39.948, 19: 39.098, 20: 40.078, 21: 44.956, 22: 47.867, 23: 50.942, 24: 51.996, 25: 54.938, 26: 55.845, 27: 58.933, 28: 58.693, 29: 63.546, 30: 65.38, 31: 69.723, 32: 72.630, 33: 74.922, 34: 78.971, 35: 79.904, 36: 83.798, 37: 85.468, 38: 87.62, 39: 88.906, 40: 91.224, 41: 92.906, 42: 95.95, 43: 96.906, 44: 101.07, 45: 102.91, 46: 106.42, 47: 107.87, 48: 112.41, 49: 114.82, 50: 118.71, 51: 121.76, 52: 127.60, 53: 127.60, 54: 131.29, 55: 132.91, 56: 137.33, 57: 138.91, 58: 140.12, 59: 140.91, 60: 144.24, 61: 144.912, 62: 150.36, 63: 151.96, 64: 157.25, 65: 158.93, 66: 162.50, 67: 164.93, 68: 167.26, 69: 168.93, 70: 173.05, 71: 174.97, 72: 178.49, 73: 180.95, 74: 183.84, 75: 186.21, 76: 190.23, 77: 192.22, 78: 195.08, 79: 196.97, 80: 200.59, 81: 204.38, 82: 207.2, 83: 208.98, 84: 1.97, 85: 2.02, 86: 2.2, 87: 3.48, 88: 2.83, 89: 2.0, 90: 232.04, 91: 231.04, 92: 238.03, 93: 237.048, 94: 244.064, 95: 243.061, 96: 247.070, 97: 247.070, 98: 251.079, 99: 252.083, 100: 257.095, 101: 258.098, 102: 259.101, 103: 262.110, 104: 267.122, 105: 270.131, 106: 271.134, 107: 270.133, 108: 270.134, 109: 278.156, 110: 281.165, 111: 281.166, 112: 285.177, 113: 286.182, 114: 289.190, 115: 289.194, 116: 293.204, 117: 293.208, 118: 294.214\n}\nexport const DefaultAtomWeight = 10.81 // C\n\n// http://dx.doi.org/10.1021/jp8111556 (or 2.0)\nexport const VdwRadii: { [e: number]: number | undefined } = {\n 1: 1.1, 2: 1.4, 3: 1.81, 4: 1.53, 5: 1.92, 6: 1.7, 7: 1.55, 8: 1.52, 9: 1.47, 10: 1.54, 11: 2.27, 12: 1.73, 13: 1.84, 14: 2.1, 15: 1.8, 16: 1.8, 17: 1.75, 18: 1.88, 19: 2.75, 20: 2.31, 21: 2.3, 22: 2.15, 23: 2.05, 24: 2.05, 25: 2.05, 26: 2.05, 27: 2.0, 28: 2.0, 29: 2.0, 30: 2.1, 31: 1.87, 32: 2.11, 33: 1.85, 34: 1.9, 35: 1.83, 36: 2.02, 37: 3.03, 38: 2.49, 39: 2.4, 40: 2.3, 41: 2.15, 42: 2.1, 43: 2.05, 44: 2.05, 45: 2.0, 46: 2.05, 47: 2.1, 48: 2.2, 49: 2.2, 50: 1.93, 51: 2.17, 52: 2.06, 53: 1.98, 54: 2.16, 55: 3.43, 56: 2.68, 57: 2.5, 58: 2.48, 59: 2.47, 60: 2.45, 61: 2.43, 62: 2.42, 63: 2.4, 64: 2.38, 65: 2.37, 66: 2.35, 67: 2.33, 68: 2.32, 69: 2.3, 70: 2.28, 71: 2.27, 72: 2.25, 73: 2.2, 74: 2.1, 75: 2.05, 76: 2.0, 77: 2.0, 78: 2.05, 79: 2.1, 80: 2.05, 81: 1.96, 82: 2.02, 83: 2.07, 84: 1.97, 85: 2.02, 86: 2.2, 87: 3.48, 88: 2.83, 89: 2.0, 90: 2.4, 91: 2.0, 92: 2.3, 93: 2.0, 94: 2.0, 95: 2.0, 96: 2.0, 97: 2.0, 98: 2.0, 99: 2.0, 100: 2.0, 101: 2.0, 102: 2.0, 103: 2.0, 104: 2.0, 105: 2.0, 106: 2.0, 107: 2.0, 108: 2.0, 109: 2.0, 110: 2.0, 111: 2.0, 112: 2.0, 113: 2.0, 114: 2.0, 115: 2.0, 116: 2.0, 117: 2.0, 118: 2.0\n}\nexport const DefaultVdwRadius = 2.0 // C\n\n// Peter Rose (peter.rose@rcsb.org), private communication, average accross PDB\nexport const ResidueRadii: { [k: string]: number } = {\n '2QY': 6.58,\n 'CY0': 11.98,\n '2QZ': 2.52,\n 'CY1': 6.59,\n 'HHK': 5.11,\n 'CXM': 4.69,\n 'HHI': 4.58,\n 'CY4': 4.57,\n 'S12': 18.57,\n 'CY3': 2.79,\n 'C5C': 5.35,\n 'PFX': 11.84,\n '2R3': 6.94,\n '2R1': 3.78,\n 'ILX': 4.99,\n '32S': 5.68,\n 'BTK': 8.59,\n '32T': 5.72,\n 'FAK': 9.8,\n 'B27': 2.78,\n 'ILM': 3.84,\n 'C4R': 5.63,\n '32L': 6.75,\n 'SYS': 3.01,\n '1MH': 5.04,\n 'ILE': 3.65,\n 'YNM': 6.39,\n '2RX': 4.91,\n 'B3A': 2.48,\n 'GEE': 4.76,\n '7MN': 7.34,\n 'B3E': 5.4,\n 'ARG': 6.33,\n '200': 6.89,\n 'HIP': 5.47,\n 'HIA': 4.64,\n 'B3K': 5.89,\n 'HIC': 5.76,\n 'B3L': 4.96,\n 'B3M': 5.07,\n 'ARM': 6.86,\n 'ARO': 7.35,\n 'AR4': 8.42,\n 'PG1': 10.67,\n 'YOF': 6.44,\n 'IML': 3.74,\n 'SXE': 6.65,\n 'HIQ': 7.98,\n 'PFF': 6.31,\n 'HIS': 4.52,\n '0TD': 3.62,\n 'C3Y': 5.24,\n '1OP': 11.55,\n '02Y': 4.77,\n '02V': 4.83,\n 'ASB': 5.59,\n '30V': 8.53,\n 'S2P': 4.81,\n 'ASP': 3.55,\n 'ASN': 3.54,\n '2OR': 6.91,\n 'QMM': 6.13,\n '2P0': 8.52,\n 'ASL': 5.36,\n 'HFA': 5.14,\n '5PG': 5.69,\n 'B3X': 4.38,\n 'AS9': 4.1,\n 'ARV': 7.59,\n 'B3U': 6.06,\n 'S2C': 7.54,\n 'B3T': 3.34,\n '175': 5.64,\n 'GFT': 8.18,\n 'HG7': 6.8,\n 'B3Q': 4.48,\n 'ASA': 3.64,\n '02K': 2.94,\n 'B3Y': 7.45,\n 'PHD': 5.35,\n 'C6C': 6.42,\n 'BUC': 5.8,\n 'HGL': 8.07,\n 'PHE': 5.06,\n '03Y': 2.6,\n 'PHA': 5.11,\n 'OCY': 5.0,\n '4PH': 6.79,\n '5OH': 4.7,\n '31Q': 10.46,\n 'BTR': 7.98,\n '3PX': 4.7,\n '1PA': 8.07,\n 'ASX': 3.54,\n 'IOR': 7.23,\n '03E': 3.38,\n 'PHL': 5.17,\n 'KWS': 5.09,\n 'PHI': 7.12,\n 'NAL': 7.22,\n 'S1H': 19.21,\n '2ML': 3.86,\n '2MR': 7.35,\n 'GHG': 4.83,\n 'TYY': 6.54,\n '2MT': 3.67,\n '56A': 13.01,\n 'SVA': 5.46,\n 'TYX': 8.31,\n 'TYS': 8.59,\n 'TYR': 6.38,\n 'TYQ': 6.43,\n 'HLU': 3.99,\n 'MYK': 19.47,\n 'TYO': 7.71,\n 'HLX': 4.98,\n 'TYN': 9.87,\n 'TYJ': 6.25,\n 'TYI': 6.49,\n 'LYH': 5.13,\n 'LYF': 12.19,\n 'SUN': 6.73,\n 'LYR': 18.28,\n 'TYB': 6.46,\n '11W': 14.39,\n 'LYS': 5.54,\n 'LYN': 4.8,\n '11Q': 4.85,\n 'LYO': 4.71,\n 'LYZ': 1.76,\n 'TXY': 6.44,\n 'MYN': 4.71,\n 'TY5': 10.6,\n 'HMR': 5.09,\n '01W': 8.55,\n 'LYX': 13.36,\n 'TY8': 7.22,\n 'TY2': 6.49,\n 'KYN': 6.18,\n 'KYQ': 9.75,\n 'CZZ': 5.14,\n 'IIL': 3.81,\n 'HNC': 10.41,\n 'OIC': 4.62,\n 'LVN': 2.89,\n 'QIL': 3.84,\n 'JJL': 8.3,\n 'VAH': 3.88,\n 'JJJ': 7.5,\n 'JJK': 7.43,\n 'VAD': 2.56,\n 'CYW': 4.65,\n '0QL': 5.72,\n '143': 8.22,\n 'SVX': 7.04,\n 'CYJ': 11.64,\n 'SVY': 7.1,\n 'SVZ': 6.6,\n 'CYG': 8.03,\n 'CYF': 13.54,\n 'SVV': 5.09,\n 'GL3': 2.72,\n '8SP': 14.26,\n 'CYS': 2.78,\n '004': 4.33,\n 'CYR': 10.33,\n 'PLJ': 3.71,\n 'EXY': 7.37,\n 'HL2': 3.75,\n 'A5N': 5.21,\n 'CYQ': 5.67,\n 'CZ2': 5.16,\n 'LWY': 4.12,\n 'PM3': 8.78,\n 'OHS': 6.98,\n 'OHI': 5.35,\n '3TY': 8.42,\n 'CYD': 8.55,\n 'DYS': 7.87,\n 'DAH': 6.47,\n '4IK': 11.81,\n '3EG': 3.66,\n 'AYA': 3.65,\n '4IN': 6.31,\n 'DAB': 3.48,\n '4HT': 6.03,\n 'RGL': 7.03,\n 'DAM': 2.49,\n 'NFA': 5.04,\n 'WFP': 6.07,\n '2JC': 2.97,\n 'HAR': 7.55,\n '2JG': 5.67,\n 'MH6': 1.72,\n '2JF': 9.13,\n '3FG': 4.96,\n 'MGN': 4.84,\n 'AZH': 5.36,\n 'AZK': 6.03,\n 'ZBZ': 7.79,\n 'TBG': 2.58,\n 'VAL': 2.51,\n 'MGG': 7.34,\n 'AZS': 5.61,\n 'FHL': 9.75,\n '2JH': 4.56,\n 'IEL': 7.07,\n 'FHO': 6.75,\n 'DA2': 7.79,\n 'FH7': 6.99,\n 'ME0': 4.52,\n '3GL': 4.84,\n 'MDO': 5.03,\n 'AZY': 7.37,\n 'A8E': 3.76,\n 'ZCL': 6.71,\n 'MDH': 2.58,\n 'LA2': 14.07,\n '4FW': 6.1,\n 'YCM': 5.32,\n 'MDF': 4.95,\n 'YCP': 3.01,\n 'TEF': 8.63,\n 'FGP': 4.34,\n 'UF0': 19.72,\n 'XCN': 4.57,\n 'FGL': 2.56,\n 'MF3': 6.37,\n 'MEQ': 5.13,\n 'LAA': 3.23,\n 'IGL': 5.52,\n 'MET': 4.49,\n 'NIY': 6.81,\n 'QCS': 5.18,\n 'TCQ': 8.56,\n 'MEN': 4.33,\n '4HL': 8.79,\n 'MEA': 4.95,\n 'EFC': 5.28,\n 'LAL': 2.41,\n '2HF': 5.52,\n 'KBE': 5.64,\n 'OCS': 3.94,\n 'CAF': 5.46,\n 'NC1': 11.4,\n 'NBQ': 9.82,\n 'CAB': 4.19,\n 'MBQ': 9.55,\n '193': 7.38,\n '192': 2.44,\n '0WZ': 7.61,\n 'CAS': 5.35,\n 'NB8': 11.98,\n 'OBS': 11.71,\n '1AC': 2.42,\n 'PCA': 3.48,\n 'MCL': 9.73,\n 'LBY': 7.75,\n 'GAU': 4.67,\n 'PBF': 9.75,\n 'MCG': 6.46,\n 'DDE': 6.86,\n '19W': 3.94,\n 'MD5': 9.33,\n 'MD6': 6.44,\n 'MD3': 8.41,\n 'MCS': 7.56,\n 'OBF': 3.64,\n 'UAL': 4.68,\n 'PAT': 6.05,\n 'IAM': 8.88,\n 'PAQ': 8.77,\n 'FDL': 9.49,\n 'NCB': 3.45,\n 'LCK': 9.81,\n 'DDZ': 2.52,\n '2FM': 5.54,\n 'IAR': 6.77,\n 'OAS': 4.8,\n 'HBN': 8.8,\n 'TA4': 5.55,\n '1C3': 7.43,\n 'ECX': 5.51,\n 'PF5': 6.28,\n 'RE3': 5.29,\n 'FCL': 6.25,\n 'ECC': 4.79,\n 'LDH': 7.06,\n 'NCY': 2.91,\n 'CCS': 4.58,\n 'PEC': 6.54,\n '2CO': 4.45,\n 'LE1': 2.72,\n 'HCM': 5.53,\n '07O': 8.05,\n 'HCL': 4.96,\n 'NEP': 6.94,\n 'PE1': 8.01,\n 'LEF': 4.37,\n 'FC0': 5.18,\n 'LED': 4.34,\n 'HCS': 4.09,\n 'DBU': 2.49,\n 'RE0': 5.53,\n 'LEN': 3.82,\n '1E3': 8.71,\n 'BB9': 2.56,\n 'BB8': 5.14,\n 'PCS': 5.05,\n 'BB7': 4.56,\n 'BB6': 2.62,\n 'LEU': 3.83,\n 'DBZ': 7.08,\n 'LET': 11.29,\n 'DBY': 6.46,\n 'ICY': 7.76,\n 'MAA': 2.4,\n 'CGA': 7.91,\n '5CS': 8.34,\n 'UGY': 3.7,\n 'LGY': 11.71,\n 'N10': 8.96,\n 'AAR': 6.39,\n 'FT6': 7.5,\n 'MOD': 12.62,\n '5CW': 7.21,\n 'PVH': 4.58,\n 'BBC': 6.42,\n 'YYA': 7.3,\n 'O12': 14.08,\n 'NOT': 7.15,\n 'KGC': 9.88,\n 'MP4': 5.86,\n '0CS': 4.07,\n 'MP8': 3.75,\n 'VLL': 2.54,\n 'VLM': 2.51,\n 'BCS': 8.03,\n 'MNL': 4.9,\n 'AA4': 4.47,\n 'SAC': 3.49,\n 'BCX': 2.99,\n '3CF': 6.47,\n 'SAH': 11.7,\n 'NNH': 6.86,\n 'CGU': 4.71,\n 'SIB': 12.41,\n 'TLY': 8.78,\n 'SIC': 4.81,\n 'VMS': 8.82,\n 'TMD': 6.76,\n 'MMO': 6.53,\n 'PXU': 2.46,\n '4AW': 6.22,\n 'OTH': 3.6,\n 'DLS': 6.84,\n 'MME': 4.99,\n 'DM0': 6.99,\n '0FL': 2.76,\n 'SBL': 8.96,\n 'CDV': 3.72,\n 'OTY': 6.51,\n 'PYA': 7.75,\n '2AS': 3.57,\n 'DMH': 4.92,\n 'ELY': 7.42,\n 'GVL': 9.6,\n 'FVA': 2.9,\n 'SAR': 2.48,\n '4BF': 6.92,\n 'EME': 4.69,\n 'CDE': 2.51,\n '3AR': 7.86,\n '3AH': 9.11,\n 'AC5': 2.44,\n 'FTR': 6.08,\n 'MLL': 3.76,\n 'NPH': 11.66,\n 'NPI': 6.9,\n 'DMT': 6.67,\n 'PYX': 11.3,\n 'MLE': 3.87,\n 'PYL': 9.67,\n 'ZZU': 6.94,\n 'H5M': 3.61,\n 'SCH': 4.46,\n 'DMK': 3.52,\n 'FTY': 9.07,\n '2AG': 3.7,\n 'ABA': 2.55,\n 'ZZJ': 2.44,\n 'MLZ': 6.8,\n 'MLY': 6.88,\n 'KCX': 7.28,\n 'ZZD': 8.16,\n '3A5': 5.37,\n 'LHC': 7.75,\n '9AT': 2.47,\n 'OZT': 3.4,\n 'THO': 2.62,\n 'THR': 2.5,\n 'DFI': 3.93,\n 'MKD': 6.42,\n '4CY': 4.6,\n 'SDP': 6.07,\n 'DFO': 3.94,\n '0A0': 3.45,\n '4DB': 9.73,\n 'ML3': 6.26,\n 'BG1': 8.02,\n 'SD4': 4.57,\n 'THC': 3.8,\n 'SCS': 5.48,\n 'TH5': 4.65,\n 'BFD': 5.33,\n 'AEI': 6.34,\n 'TH6': 2.85,\n 'SCY': 4.53,\n 'TIS': 4.81,\n 'SEE': 4.53,\n 'BHD': 3.48,\n 'SEB': 8.18,\n 'SEC': 2.96,\n 'SEP': 4.8,\n 'CLH': 7.13,\n 'TIH': 5.02,\n 'CLG': 13.62,\n 'SEN': 6.43,\n 'XXA': 7.34,\n 'SEL': 2.46,\n 'SE7': 4.19,\n '4CF': 7.72,\n 'G8M': 3.57,\n 'BH2': 3.51,\n 'UN2': 3.22,\n 'VR0': 10.51,\n 'MK8': 4.76,\n 'DHA': 2.32,\n 'LMQ': 4.69,\n 'SFE': 5.01,\n 'AHB': 3.47,\n 'OXX': 7.05,\n 'BIF': 9.63,\n 'IZO': 4.47,\n 'NMM': 8.25,\n '0BN': 7.0,\n 'HZP': 3.12,\n 'NMC': 4.23,\n 'DHL': 2.69,\n '9DS': 9.29,\n 'SER': 2.41,\n 'CHG': 4.2,\n 'MIR': 6.54,\n 'AGQ': 7.79,\n 'SET': 2.46,\n 'MIS': 6.32,\n '4FB': 3.08,\n '0AR': 8.46,\n 'LME': 3.99,\n 'FZN': 24.42,\n 'AGT': 9.04,\n 'IYR': 6.46,\n '9DN': 9.31,\n 'CHP': 5.75,\n 'UNK': 1.64,\n 'XX1': 9.92,\n 'AGM': 6.57,\n '0AH': 5.78,\n 'LLP': 10.22,\n '0AF': 6.72,\n '4DP': 9.28,\n 'HYP': 2.25,\n 'DIR': 5.8,\n 'LLY': 8.71,\n '0AK': 6.11,\n 'NLE': 4.67,\n 'OYL': 6.42,\n 'WVL': 4.69,\n '0A8': 8.1,\n 'NLY': 6.37,\n 'MHO': 4.89,\n 'VOL': 2.55,\n '0A1': 7.1,\n 'MHL': 3.92,\n 'NLP': 4.81,\n 'NLQ': 4.65,\n 'MHW': 2.74,\n 'BIL': 4.7,\n 'NLO': 4.8,\n 'MHU': 7.51,\n 'XW1': 9.36,\n 'LLO': 10.13,\n 'SGB': 6.88,\n 'MHV': 3.6,\n 'MHS': 4.51,\n '0A9': 5.17,\n '0LF': 9.96,\n 'HT7': 6.82,\n 'X2W': 6.6,\n 'YPZ': 9.38,\n 'I58': 6.73,\n 'FLA': 2.4,\n 'M0H': 4.83,\n 'HSL': 2.46,\n 'FLE': 6.17,\n 'KOR': 10.1,\n '1VR': 3.89,\n 'HSO': 4.56,\n 'TTS': 9.41,\n 'RVX': 7.01,\n 'TTQ': 7.71,\n 'H14': 5.27,\n 'HTI': 7.8,\n 'ONH': 6.14,\n 'LP6': 8.58,\n 'ONL': 4.83,\n 'AHH': 5.06,\n 'HS8': 7.4,\n 'HS9': 4.71,\n 'BL2': 5.82,\n 'AHP': 5.26,\n '6HN': 7.34,\n 'HRP': 5.46,\n 'POM': 3.6,\n 'WPA': 5.11,\n '2ZC': 4.29,\n 'CPC': 2.65,\n 'AIB': 2.4,\n 'XSN': 3.47,\n 'M2S': 5.28,\n 'GND': 6.67,\n 'GNC': 4.6,\n 'MVA': 2.56,\n 'OLZ': 5.32,\n 'M2L': 6.15,\n 'TRF': 6.69,\n 'NZH': 7.66,\n 'SRZ': 5.27,\n 'OLD': 10.47,\n 'CME': 5.86,\n 'CMH': 5.3,\n 'ALA': 2.38,\n 'TRQ': 7.36,\n 'PPN': 7.24,\n 'TRP': 6.07,\n 'TRO': 5.82,\n 'TRN': 5.95,\n 'NYS': 8.1,\n 'ALC': 5.26,\n 'U3X': 11.7,\n 'HVA': 2.58,\n 'TS9': 3.92,\n 'TRX': 7.27,\n 'TRW': 11.8,\n 'LPL': 7.51,\n 'GMA': 4.4,\n 'OMT': 5.07,\n 'CMT': 3.54,\n 'GME': 4.66,\n 'NYB': 6.07,\n 'PR3': 5.12,\n 'LPD': 2.48,\n 'GLU': 4.49,\n '1X6': 6.84,\n 'LPG': 2.39,\n 'GLX': 4.52,\n 'PR4': 4.52,\n 'CML': 6.16,\n 'FME': 4.52,\n 'HTR': 6.48,\n 'PR7': 4.66,\n 'Z3E': 7.2,\n 'GLZ': 2.39,\n 'BMT': 6.37,\n 'WRP': 8.16,\n 'GLY': 2.37,\n 'OMY': 6.11,\n 'MTY': 5.46,\n 'OMX': 6.15,\n 'GLN': 4.46,\n '2XA': 8.25,\n '28X': 7.84,\n '7JA': 9.46,\n 'FLT': 9.65,\n 'GLJ': 3.7,\n 'OMH': 5.26,\n 'TSY': 4.26,\n 'PRV': 4.28,\n 'CS4': 11.21,\n 'DOA': 12.33,\n '23P': 5.42,\n 'CS3': 8.24,\n '6CL': 6.47,\n 'PRR': 5.58,\n 'KST': 11.58,\n 'CS1': 7.23,\n 'PRS': 2.63,\n 'ZYJ': 11.4,\n 'IT1': 9.75,\n 'UU5': 4.98,\n 'ESB': 6.69,\n 'UU4': 2.49,\n 'ESC': 5.65,\n 'LSO': 10.58,\n 'ZYK': 11.45,\n '9NV': 8.99,\n '23F': 5.27,\n 'ORN': 4.25,\n 'HOX': 6.61,\n 'CSD': 3.95,\n 'FP9': 3.03,\n 'DO2': 4.44,\n 'SLL': 11.53,\n 'P3Q': 9.54,\n 'ORQ': 6.04,\n 'MSL': 5.21,\n 'DNP': 2.45,\n 'CSB': 3.51,\n 'WLU': 4.24,\n 'CSA': 5.7,\n 'MT2': 5.51,\n 'CSO': 3.53,\n 'TPO': 4.73,\n 'MSP': 13.11,\n '23S': 6.09,\n 'MSO': 4.96,\n 'PRO': 2.41,\n 'TPL': 5.41,\n 'DNS': 8.79,\n 'CSK': 3.91,\n 'Z70': 7.4,\n 'CSJ': 7.51,\n 'DNW': 7.97,\n 'PRK': 9.15,\n 'GSU': 11.81,\n 'LTA': 6.57,\n 'HPE': 6.63,\n 'TPQ': 6.48,\n 'PRJ': 5.26,\n 'PSW': 4.65,\n 'L3O': 3.89,\n 'CSU': 4.89,\n 'ALY': 7.38,\n 'M3L': 7.12,\n 'CSW': 3.68,\n 'XPR': 7.68,\n 'D4P': 5.66,\n 'FOE': 8.17,\n 'SLZ': 5.69,\n 'CSP': 5.26,\n 'TQI': 7.68,\n 'ALT': 2.72,\n 'CSR': 5.42,\n 'CSS': 3.61,\n 'M3R': 7.18,\n 'ALO': 2.57,\n 'R4K': 4.67,\n 'SMF': 9.0,\n 'MSA': 2.73,\n 'SMC': 3.39,\n 'CSX': 3.47,\n 'SME': 4.8,\n 'ETA': 2.4,\n 'CSZ': 3.6,\n '22G': 8.8,\n 'MSE': 4.62,\n 'ALN': 6.16,\n 'PSH': 7.26,\n 'CTE': 7.27,\n 'DON': 6.72,\n 'CTH': 3.45,\n 'U2X': 11.54,\n '6CW': 7.56,\n 'TQZ': 6.97,\n '3YM': 6.52,\n 'OSE': 4.49,\n '2VA': 9.82,\n 'TQQ': 7.76,\n 'NRG': 8.35,\n 'BPE': 7.24,\n 'F2F': 6.25,\n '1TQ': 8.58,\n 'I2M': 3.13,\n 'NVA': 3.76,\n 'R1A': 8.2,\n 'QPA': 6.95,\n 'C1X': 11.63,\n 'FRD': 5.05,\n 'HR7': 6.98,\n 'SNC': 3.93,\n 'QPH': 5.15,\n '26B': 8.39,\n 'DPQ': 6.54,\n 'DPP': 2.51,\n '2TY': 8.65,\n 'TNR': 6.88,\n 'PTH': 8.35,\n 'DPL': 3.58,\n 'APK': 8.79,\n '1TY': 8.84,\n 'HRG': 7.36,\n 'PTM': 8.74,\n '1U8': 3.62,\n 'PTR': 8.64,\n 'LVG': 3.01,\n '6FL': 4.85,\n 'SOC': 4.05,\n 'KPI': 9.79,\n 'IPG': 2.91,\n 'P2Y': 2.51,\n 'N2C': 3.55,\n 'T0I': 7.34,\n 'MPH': 5.29,\n 'R2T': 4.71,\n 'TOX': 6.78,\n 'P2Q': 9.8,\n 'GPL': 10.77,\n 'MPJ': 5.07,\n 'F2Y': 6.2,\n 'T11': 8.58,\n '9NR': 9.33,\n 'FPR': 8.85,\n '9NF': 8.93,\n 'KPY': 10.17,\n '9NE': 9.77,\n 'TOQ': 7.5,\n 'MPQ': 4.2,\n 'FPK': 3.08,\n 'HQA': 7.25,\n 'SOY': 10.94\n}\nexport const DefaultResidueRadius = 5.0\n\n// http://dx.doi.org/10.1039/b801115j (or 1.6)\nexport const CovalentRadii: { [e: number]: number | undefined } = {\n 1: 0.31, 2: 0.28, 3: 1.28, 4: 0.96, 5: 0.84, 6: 0.76, 7: 0.71, 8: 0.66, 9: 0.57, 10: 0.58, 11: 1.66, 12: 1.41, 13: 1.21, 14: 1.11, 15: 1.07, 16: 1.05, 17: 1.02, 18: 1.06, 19: 2.03, 20: 1.76, 21: 1.7, 22: 1.6, 23: 1.53, 24: 1.39, 25: 1.39, 26: 1.32, 27: 1.26, 28: 1.24, 29: 1.32, 30: 1.22, 31: 1.22, 32: 1.2, 33: 1.19, 34: 1.2, 35: 1.2, 36: 1.16, 37: 2.2, 38: 1.95, 39: 1.9, 40: 1.75, 41: 1.64, 42: 1.54, 43: 1.47, 44: 1.46, 45: 1.42, 46: 1.39, 47: 1.45, 48: 1.44, 49: 1.42, 50: 1.39, 51: 1.39, 52: 1.38, 53: 1.39, 54: 1.4, 55: 2.44, 56: 2.15, 57: 2.07, 58: 2.04, 59: 2.03, 60: 2.01, 61: 1.99, 62: 1.98, 63: 1.98, 64: 1.96, 65: 1.94, 66: 1.92, 67: 1.92, 68: 1.89, 69: 1.9, 70: 1.87, 71: 1.87, 72: 1.75, 73: 1.7, 74: 1.62, 75: 1.51, 76: 1.44, 77: 1.41, 78: 1.36, 79: 1.36, 80: 1.32, 81: 1.45, 82: 1.46, 83: 1.48, 84: 1.4, 85: 1.5, 86: 1.5, 87: 2.6, 88: 2.21, 89: 2.15, 90: 2.06, 91: 2.0, 92: 1.96, 93: 1.9, 94: 1.87, 95: 1.8, 96: 1.69, 97: 1.6, 98: 1.6, 99: 1.6, 100: 1.6, 101: 1.6, 102: 1.6, 103: 1.6, 104: 1.6, 105: 1.6, 106: 1.6, 107: 1.6, 108: 1.6, 109: 1.6, 110: 1.6, 111: 1.6, 112: 1.6, 113: 1.6, 114: 1.6, 115: 1.6, 116: 1.6, 117: 1.6, 118: 1.6\n}\nexport const DefaultCovalentRadius = 1.6\n\nexport const Valences: { [e: number]: number[] | undefined } = {\n 1: [ 1 ],\n 2: [ 0 ],\n 3: [ 1 ],\n 4: [ 2 ],\n 5: [ 3 ],\n 6: [ 4 ],\n 7: [ 3 ],\n 8: [ 2 ],\n 9: [ 1 ],\n 10: [ 0 ],\n 11: [ 1 ],\n 12: [ 2 ],\n 13: [ 6 ],\n 14: [ 6 ],\n 15: [ 3, 5, 7 ],\n 16: [ 2, 4, 6 ],\n 17: [ 1 ],\n 18: [ 0 ],\n 19: [ 1 ],\n 20: [ 2 ],\n\n 31: [ 3 ],\n 32: [ 4 ],\n 33: [ 3, 5 ],\n 34: [ 2, 4, 6 ],\n 35: [ 1 ],\n 36: [ 0 ],\n 37: [ 1 ],\n 38: [ 2 ],\n\n 49: [ 3 ],\n 50: [ 4 ],\n 51: [ 3, 5 ],\n 52: [ 2 ],\n 53: [ 1, 2, 5 ],\n 54: [ 0, 2 ],\n 55: [ 1 ],\n 56: [ 2 ],\n\n 81: [ 3 ],\n 82: [ 4 ],\n 83: [ 3 ],\n 84: [ 2 ],\n 85: [ 1 ],\n 86: [ 0 ],\n 87: [ 1 ],\n 88: [ 2 ]\n}\nexport const DefaultValence = -1\n\nexport const OuterShellElectronCounts: { [e: number]: number | undefined } = {\n1: 1, 2: 2, 3: 1, 4: 2, 5: 3, 6: 4, 7: 5, 8: 6, 9: 7, 10: 8, 11: 1, 12: 2, 13: 3, 14: 4, 15: 5, 16: 6, 17: 7, 18: 8, 19: 1, 20: 2, 21: 3, 22: 4, 23: 5, 24: 6, 25: 7, 26: 8, 27: 9, 28: 10, 29: 11, 30: 2, 31: 3, 32: 4, 33: 5, 34: 6, 35: 7, 36: 8, 37: 1, 38: 2, 39: 3, 40: 4, 41: 5, 42: 6, 43: 7, 44: 8, 45: 9, 46: 10, 47: 11, 48: 2, 49: 3, 50: 4, 51: 5, 52: 6, 53: 7, 54: 8, 55: 1, 56: 2, 57: 3, 58: 4, 59: 3, 60: 4, 61: 5, 62: 6, 63: 7, 64: 8, 65: 9, 66: 10, 67: 11, 68: 12, 69: 13, 70: 14, 71: 15, 72: 4, 73: 5, 74: 6, 75: 7, 76: 8, 77: 9, 78: 10, 79: 11, 80: 2, 81: 3, 82: 4, 83: 5, 84: 6, 85: 7, 86: 8, 87: 1, 88: 2, 89: 3, 90: 4, 91: 3, 92: 4, 93: 5, 94: 6, 95: 7, 96: 8, 97: 9, 98: 10, 99: 11, 100: 12, 101: 13, 102: 14, 103: 15, 104: 2, 105: 2, 106: 2, 107: 2, 108: 2, 109: 2, 110: 2, 111: 2, 112: 2, 113: 3, 114: 4, 115: 5, 116: 6, 117: 7, 118: 8\n}\nexport const DefaultOuterShellElectronCount = 2\n\n// http://blanco.biomol.uci.edu/Whole_residue_HFscales.txt\n// https://www.nature.com/articles/nsb1096-842\nexport const ResidueHydrophobicity: { [k: string]: [number, number, number] } = {\n // AA DGwif DGwoct Oct-IF\n 'ALA': [ 0.17, 0.50, 0.33 ],\n 'ARG': [ 0.81, 1.81, 1.00 ],\n 'ASN': [ 0.42, 0.85, 0.43 ],\n 'ASP': [ 1.23, 3.64, 2.41 ],\n 'ASH': [ -0.07, 0.43, 0.50 ],\n 'CYS': [ -0.24, -0.02, 0.22 ],\n 'GLN': [ 0.58, 0.77, 0.19 ],\n 'GLU': [ 2.02, 3.63, 1.61 ],\n 'GLH': [ -0.01, 0.11, 0.12 ],\n 'GLY': [ 0.01, 1.15, 1.14 ],\n // \"His+\": [ 0.96, 2.33, 1.37 ],\n 'HIS': [ 0.17, 0.11, -0.06 ],\n 'ILE': [ -0.31, -1.12, -0.81 ],\n 'LEU': [ -0.56, -1.25, -0.69 ],\n 'LYS': [ 0.99, 2.80, 1.81 ],\n 'MET': [ -0.23, -0.67, -0.44 ],\n 'PHE': [ -1.13, -1.71, -0.58 ],\n 'PRO': [ 0.45, 0.14, -0.31 ],\n 'SER': [ 0.13, 0.46, 0.33 ],\n 'THR': [ 0.14, 0.25, 0.11 ],\n 'TRP': [ -1.85, -2.09, -0.24 ],\n 'TYR': [ -0.94, -0.71, 0.23 ],\n 'VAL': [ 0.07, -0.46, -0.53 ]\n}\nexport const DefaultResidueHydrophobicity = [ 0.00, 0.00, 0.00 ]\n\nexport const AA1: { [k: string]: string } = {\n 'HIS': 'H',\n 'ARG': 'R',\n 'LYS': 'K',\n 'ILE': 'I',\n 'PHE': 'F',\n 'LEU': 'L',\n 'TRP': 'W',\n 'ALA': 'A',\n 'MET': 'M',\n 'PRO': 'P',\n 'CYS': 'C',\n 'ASN': 'N',\n 'VAL': 'V',\n 'GLY': 'G',\n 'SER': 'S',\n 'GLN': 'Q',\n 'TYR': 'Y',\n 'ASP': 'D',\n 'GLU': 'E',\n 'THR': 'T',\n\n 'SEC': 'U', // as per IUPAC definition\n 'PYL': 'O', // as per IUPAC definition\n}\n\nexport const AA3 = Object.keys(AA1)\n\nexport const RnaBases = [ 'A', 'C', 'T', 'G', 'U', 'I' ]\n\nexport const DnaBases = [ 'DA', 'DC', 'DT', 'DG', 'DU', 'DI' ]\n\nexport const PurinBases = [ 'A', 'G', 'I', 'DA', 'DG', 'DI' ]\n\nexport const Bases = RnaBases.concat(DnaBases)\n\nexport const WaterNames = [\n 'SOL', 'WAT', 'HOH', 'H2O', 'W', 'DOD', 'D3O', 'TIP3', 'TIP4', 'SPC'\n]\n\n// all chemical components with the word \"ion\" in their name, Sep 2016\n//\n// SET SESSION group_concat_max_len = 1000000;\n// SELECT GROUP_CONCAT(id_ ORDER BY id_ ASC SEPARATOR '\", \"') from\n// (\n// SELECT count(obj_id) as c, id_\n// FROM pdb.chem_comp WHERE name LIKE \"% ION%\"\n// GROUP BY id_\n// ) AS t1;\nexport const IonNames = [\n '118', '119', '1AL', '1CU', '2FK', '2HP', '2OF', '3CO',\n '3MT', '3NI', '3OF', '3P8', '4MO', '4PU', '543', '6MO', 'ACT', 'AG', 'AL',\n 'ALF', 'AM', 'ATH', 'AU', 'AU3', 'AUC', 'AZI', 'BA', 'BCT', 'BEF', 'BF4', 'BO4',\n 'BR', 'BS3', 'BSY', 'CA', 'CAC', 'CD', 'CD1', 'CD3', 'CD5', 'CE', 'CHT', 'CL',\n 'CO', 'CO3', 'CO5', 'CON', 'CR', 'CS', 'CSB', 'CU', 'CU1', 'CU3', 'CUA', 'CUZ',\n 'CYN', 'DME', 'DMI', 'DSC', 'DTI', 'DY', 'E4N', 'EDR', 'EMC', 'ER3', 'EU',\n 'EU3', 'F', 'FE', 'FE2', 'FPO', 'GA', 'GD3', 'GEP', 'HAI', 'HG', 'HGC', 'IN',\n 'IOD', 'IR', 'IR3', 'IRI', 'IUM', 'K', 'KO4', 'LA', 'LCO', 'LCP', 'LI', 'LU',\n 'MAC', 'MG', 'MH2', 'MH3', 'MLI', 'MLT', 'MMC', 'MN', 'MN3', 'MN5', 'MN6',\n 'MO1', 'MO2', 'MO3', 'MO4', 'MO5', 'MO6', 'MOO', 'MOS', 'MOW', 'MW1', 'MW2',\n 'MW3', 'NA', 'NA2', 'NA5', 'NA6', 'NAO', 'NAW', 'NCO', 'NET', 'NH4', 'NI',\n 'NI1', 'NI2', 'NI3', 'NO2', 'NO3', 'NRU', 'O4M', 'OAA', 'OC1', 'OC2', 'OC3',\n 'OC4', 'OC5', 'OC6', 'OC7', 'OC8', 'OCL', 'OCM', 'OCN', 'OCO', 'OF1', 'OF2',\n 'OF3', 'OH', 'OS', 'OS4', 'OXL', 'PB', 'PBM', 'PD', 'PDV', 'PER', 'PI', 'PO3',\n 'PO4', 'PR', 'PT', 'PT4', 'PTN', 'RB', 'RH3', 'RHD', 'RU', 'SB', 'SCN', 'SE4',\n 'SEK', 'SM', 'SMO', 'SO3', 'SO4', 'SR', 'T1A', 'TB', 'TBA', 'TCN', 'TEA', 'TH',\n 'THE', 'TL', 'TMA', 'TRA', 'UNX', 'V', 'VN3', 'VO4', 'W', 'WO5', 'Y1', 'YB',\n 'YB2', 'YH', 'YT3', 'ZCM', 'ZN', 'ZN2', 'ZN3', 'ZNO', 'ZO3',\n // additional ion names\n 'OHX'\n]\n\n// all chemical components with the word \"%saccharide%\" in their type, Sep 2016\n//\n// SET SESSION group_concat_max_len = 1000000;\n// select GROUP_CONCAT(id_ ORDER BY id_ ASC SEPARATOR '\", \"') from\n// (\n// SELECT count(obj_id), id_\n// FROM pdb.chem_comp WHERE type like \"%SACCHARIDE%\"\n// GROUP BY id_\n// ) AS t1;\nexport const SaccharideNames = [\n '045', '0AT', '0BD', '0MK', '0NZ', '0TS', '0V4', '0XY', '0YT', '10M',\n '147', '149', '14T', '15L', '16G', '18T', '18Y', '1AR', '1BW', '1GL', '1GN',\n '1JB', '1LL', '1NA', '1S3', '26M', '26Q', '26R', '26V', '26W', '26Y', '27C',\n '289', '291', '293', '2DG', '2F8', '2FG', '2FL', '2FP', '2GL', '2M4', '2M5',\n '32O', '34V', '3CM', '3DO', '3DY', '3FM', '3LR', '3MF', '3MG', '3SA', '3ZW',\n '46D', '46M', '46Z', '48Z', '4CQ', '4GC', '4NN', '50A', '5DI', '5GF', '5MM',\n '5RP', '5SA', '5SP', '64K', '6PG', '6SA', '7JZ', '7SA', 'A1Q', 'A2G', 'AAB',\n 'AAL', 'AAO', 'ABC', 'ABD', 'ABE', 'ABF', 'ABL', 'ACG', 'ACI', 'ACR', 'ACX',\n 'ADA', 'ADG', 'ADR', 'AF1', 'AFD', 'AFL', 'AFO', 'AFP', 'AFR', 'AGC', 'AGH',\n 'AGL', 'AHR', 'AIG', 'ALL', 'ALX', 'AMU', 'AOG', 'AOS', 'ARA', 'ARB', 'ARE',\n 'ARI', 'ASG', 'ASO', 'AXP', 'AXR', 'B0D', 'B16', 'B2G', 'B4G', 'B6D', 'B8D',\n 'B9D', 'BBK', 'BCD', 'BDG', 'BDP', 'BDR', 'BEM', 'BFP', 'BGC', 'BGL', 'BGP',\n 'BGS', 'BHG', 'BMA', 'BMX', 'BNG', 'BNX', 'BOG', 'BRI', 'BXF', 'BXP', 'BXX',\n 'BXY', 'C3X', 'C4X', 'C5X', 'CAP', 'CBI', 'CBK', 'CBS', 'CDR', 'CEG', 'CGF',\n 'CHO', 'CR1', 'CR6', 'CRA', 'CT3', 'CTO', 'CTR', 'CTT', 'D6G', 'DAF', 'DAG',\n 'DDA', 'DDB', 'DDL', 'DEL', 'DFR', 'DFX', 'DG0', 'DGC', 'DGD', 'DGM', 'DGS',\n 'DIG', 'DLF', 'DLG', 'DMU', 'DNO', 'DOM', 'DP5', 'DQQ', 'DQR', 'DR2', 'DR3',\n 'DR4', 'DRI', 'DSR', 'DT6', 'DVC', 'E4P', 'E5G', 'EAG', 'EBG', 'EBQ', 'EGA',\n 'EJT', 'EPG', 'ERE', 'ERI', 'F1P', 'F1X', 'F6P', 'FBP', 'FCA', 'FCB', 'FCT',\n 'FDP', 'FDQ', 'FFC', 'FIX', 'FMO', 'FRU', 'FSI', 'FU4', 'FUB', 'FUC', 'FUD',\n 'FUL', 'FXP', 'G16', 'G1P', 'G2F', 'G3I', 'G4D', 'G4S', 'G6D', 'G6P', 'G6S',\n 'GAC', 'GAD', 'GAL', 'GC1', 'GC4', 'GCD', 'GCN', 'GCO', 'GCS', 'GCT', 'GCU',\n 'GCV', 'GCW', 'GCX', 'GE1', 'GFG', 'GFP', 'GIV', 'GL0', 'GL2', 'GL5', 'GL6',\n 'GL7', 'GL9', 'GLA', 'GLB', 'GLC', 'GLD', 'GLF', 'GLG', 'GLO', 'GLP', 'GLS',\n 'GLT', 'GLW', 'GMH', 'GN1', 'GNX', 'GP1', 'GP4', 'GPH', 'GPM', 'GQ1', 'GQ2',\n 'GQ4', 'GS1', 'GS4', 'GSA', 'GSD', 'GTE', 'GTH', 'GTK', 'GTR', 'GTZ', 'GU0',\n 'GU1', 'GU2', 'GU3', 'GU4', 'GU5', 'GU6', 'GU8', 'GU9', 'GUF', 'GUP', 'GUZ',\n 'GYP', 'GYV', 'H2P', 'HDL', 'HMS', 'HS2', 'HSD', 'HSG', 'HSH', 'HSJ', 'HSQ',\n 'HSR', 'HSU', 'HSX', 'HSY', 'HSZ', 'IAB', 'IDG', 'IDR', 'IDS', 'IDT', 'IDU',\n 'IDX', 'IDY', 'IMK', 'IN1', 'IPT', 'ISL', 'KBG', 'KD2', 'KDA', 'KDM', 'KDO',\n 'KFN', 'KO1', 'KO2', 'KTU', 'L6S', 'LAG', 'LAI', 'LAK', 'LAO', 'LAT', 'LB2',\n 'LBT', 'LCN', 'LDY', 'LGC', 'LGU', 'LM2', 'LMT', 'LMU', 'LOG', 'LOX', 'LPK',\n 'LSM', 'LTM', 'LVZ', 'LXB', 'LXZ', 'M1F', 'M3M', 'M6P', 'M8C', 'MA1', 'MA2',\n 'MA3', 'MAB', 'MAG', 'MAL', 'MAN', 'MAT', 'MAV', 'MAW', 'MBG', 'MCU', 'MDA',\n 'MDM', 'MDP', 'MFA', 'MFB', 'MFU', 'MG5', 'MGA', 'MGL', 'MLB', 'MMA', 'MMN',\n 'MN0', 'MRP', 'MTT', 'MUG', 'MVP', 'MXY', 'N1L', 'N9S', 'NAA', 'NAG', 'NBG',\n 'NDG', 'NED', 'NG1', 'NG6', 'NGA', 'NGB', 'NGC', 'NGE', 'NGF', 'NGL', 'NGS',\n 'NGY', 'NHF', 'NM6', 'NM9', 'NTF', 'NTO', 'NTP', 'NXD', 'NYT', 'OPG', 'OPM',\n 'ORP', 'OX2', 'P3M', 'P53', 'P6P', 'PA5', 'PNA', 'PNG', 'PNW', 'PRP', 'PSJ',\n 'PSV', 'PTQ', 'QDK', 'QPS', 'QV4', 'R1P', 'R1X', 'R2B', 'R5P', 'RAA', 'RAE',\n 'RAF', 'RAM', 'RAO', 'RAT', 'RB5', 'RBL', 'RCD', 'RDP', 'REL', 'RER', 'RF5',\n 'RG1', 'RGG', 'RHA', 'RIB', 'RIP', 'RNS', 'RNT', 'ROB', 'ROR', 'RPA', 'RST',\n 'RUB', 'RUU', 'RZM', 'S6P', 'S7P', 'SA0', 'SCR', 'SDD', 'SF6', 'SF9', 'SG4',\n 'SG5', 'SG6', 'SG7', 'SGA', 'SGC', 'SGD', 'SGN', 'SGS', 'SHB', 'SHG', 'SI3',\n 'SIO', 'SOE', 'SOL', 'SSG', 'SUC', 'SUP', 'SUS', 'T6P', 'T6T', 'TAG', 'TCB',\n 'TDG', 'TGK', 'TGY', 'TH1', 'TIA', 'TM5', 'TM6', 'TM9', 'TMR', 'TMX', 'TOA',\n 'TOC', 'TRE', 'TYV', 'UCD', 'UDC', 'VG1', 'X0X', 'X1X', 'X2F', 'X4S', 'X5S',\n 'X6X', 'XBP', 'XDN', 'XDP', 'XIF', 'XIM', 'XLF', 'XLS', 'XMM', 'XUL', 'XXR',\n 'XYP', 'XYS', 'YO5', 'Z3Q', 'Z6J', 'Z9M', 'ZDC', 'ZDM'\n]\n\nexport const ProteinBackboneAtoms = [\n 'CA', 'C', 'N', 'O',\n 'O1', 'O2', 'OC1', 'OC2', 'OX1', 'OXT', 'OT1', 'OT2',\n 'H', 'H1', 'H2', 'H3', 'HA', 'HN',\n 'BB'\n]\n\nexport const NucleicBackboneAtoms = [\n 'P', 'OP1', 'OP2', 'HOP2', 'HOP3',\n \"O2'\", \"O3'\", \"O4'\", \"O5'\", \"C1'\", \"C2'\", \"C3'\", \"C4'\", \"C5'\",\n \"H1'\", \"H2'\", \"H2''\", \"HO2'\", \"H3'\", \"H4'\", \"H5'\", \"H5''\", \"HO3'\", \"HO5'\",\n 'O2*', 'O3*', 'O4*', 'O5*', 'C1*', 'C2*', 'C3*', 'C4*', 'C5*'\n]\n\nexport const ResidueTypeAtoms: { [k: number]: { [k: string]: string|string[] } } = {}\n\nResidueTypeAtoms[ ProteinBackboneType ] = {\n trace: 'CA',\n direction1: 'C',\n direction2: [ 'O', 'OC1', 'O1', 'OX1', 'OXT', 'OT1', 'OT2' ],\n backboneStart: 'N',\n backboneEnd: 'C'\n}\n\nResidueTypeAtoms[ RnaBackboneType ] = {\n trace: [ \"C4'\", 'C4*' ],\n direction1: [ \"C1'\", 'C1*' ],\n direction2: [ \"C3'\", 'C3*' ],\n backboneStart: 'P',\n backboneEnd: [ \"O3'\", 'O3*' ]\n}\n\nResidueTypeAtoms[ DnaBackboneType ] = {\n trace: [ \"C3'\", 'C3*' ],\n direction1: [ \"C2'\", 'C2*' ],\n direction2: [ \"O4'\", 'O4*' ],\n backboneStart: 'P',\n backboneEnd: [ \"O3'\", 'O3*' ]\n}\n\nResidueTypeAtoms[ CgProteinBackboneType ] = {\n trace: [ 'CA', 'BB' ],\n backboneStart: [ 'CA', 'BB' ],\n backboneEnd: [ 'CA', 'BB' ]\n}\n\nResidueTypeAtoms[ CgRnaBackboneType ] = {\n trace: [ \"C4'\", 'C4*', 'P' ],\n backboneStart: [ \"C4'\", 'C4*', 'P' ],\n backboneEnd: [ \"C4'\", 'C4*', 'P' ]\n}\n\nResidueTypeAtoms[ CgDnaBackboneType ] = {\n trace: [ \"C3'\", 'C3*', \"C2'\", 'P' ], // C2' is used in martini ff\n backboneStart: [ \"C3'\", 'C3*', \"C2'\", 'P' ],\n backboneEnd: [ \"C3'\", 'C3*', \"C2'\", 'P' ]\n}\n\nResidueTypeAtoms[ UnknownBackboneType ] = {}\n\n// Mappings taken from Meeko: https://github.com/forlilab/Meeko/blob/develop/meeko/utils/autodock4_atom_types_elements.py\nexport const PDBQTSpecialElements = {\n 'HD': 'H',\n 'HS': 'H',\n 'A': 'C',\n 'NA': 'N',\n 'NS': 'N',\n 'OA': 'O',\n 'OS': 'O',\n 'SA': 'S',\n 'G0': 'C',\n 'G1': 'C',\n 'G2': 'C',\n 'G3': 'C',\n 'CG0': 'C',\n 'CG1': 'C',\n 'CG2': 'C',\n 'CG3': 'C',\n 'W': 'O'\n}","/**\n * @file Geometry\n * @author Fred Ludlow \n * @author Alexander Rose \n */\n\nimport { Vector3 } from 'three'\n\nimport { Elements } from '../structure/structure-constants'\nimport { degToRad } from '../math/math-utils'\nimport AtomProxy from '../proxy/atom-proxy'\n\n// Changed numbering so they're mostly inline with coordination number\n// from VSEPR\nexport const enum AtomGeometry {\n Spherical = 0,\n Terminal = 1,\n Linear = 2,\n Trigonal = 3,\n Tetrahedral = 4,\n TrigonalBiPyramidal = 5,\n Octahedral = 6,\n SquarePlanar = 7, // Okay, it breaks down somewhere!\n Unknown = 8\n}\n\nexport function assignGeometry (totalCoordination: number): AtomGeometry {\n switch(totalCoordination){\n case 0:\n return AtomGeometry.Spherical\n case 1:\n return AtomGeometry.Terminal\n case 2:\n return AtomGeometry.Linear\n case 3:\n return AtomGeometry.Trigonal\n case 4:\n return AtomGeometry.Tetrahedral\n default:\n return AtomGeometry.Unknown\n }\n}\n\nexport const Angles = new Map([\n [ AtomGeometry.Linear, degToRad(180) ],\n [ AtomGeometry.Trigonal, degToRad(120) ],\n [ AtomGeometry.Tetrahedral, degToRad(109.4721) ],\n [ AtomGeometry.Octahedral, degToRad(90) ]\n])\n\n/**\n * Calculate the angles x-1-2 for all x where x is a heavy atom bonded to ap1.\n * @param {AtomProxy} ap1 First atom (angle centre)\n * @param {AtomProxy} ap2 Second atom\n * @return {number[]} Angles in radians\n */\nexport function calcAngles (ap1: AtomProxy, ap2: AtomProxy): number[] {\n let angles: number[] = []\n const d1 = new Vector3()\n const d2 = new Vector3()\n d1.subVectors(ap2 as any, ap1 as any)\n ap1.eachBondedAtom( x => {\n if (x.number !== Elements.H) {\n d2.subVectors(x as any, ap1 as any)\n angles.push(d1.angleTo(d2))\n }\n })\n return angles\n}\n\n/**\n * Find two neighbours of ap1 to define a plane (if possible) and\n * measure angle out of plane to ap2\n * @param {AtomProxy} ap1 First atom (angle centre)\n * @param {AtomProxy} ap2 Second atom (out-of-plane)\n * @return {number} Angle from plane to second atom\n */\nexport function calcPlaneAngle (ap1: AtomProxy, ap2: AtomProxy): number | undefined {\n const x1 = ap1.clone()\n\n const v12 = new Vector3()\n v12.subVectors(ap2 as any, ap1 as any)\n\n const neighbours = [new Vector3(), new Vector3()]\n let ni = 0\n ap1.eachBondedAtom( x => {\n if (ni > 1) { return }\n if (x.number !== Elements.H) {\n x1.index = x.index\n neighbours[ni++].subVectors(x as any, ap1 as any)\n }\n })\n if (ni === 1) {\n x1.eachBondedAtom( x => {\n if (ni > 1) { return }\n if (x.number !== Elements.H && x.index !== ap1.index){\n neighbours[ni++].subVectors(x as any, ap1 as any)\n }\n })\n }\n if (ni !== 2) {\n return\n }\n\n const cp = neighbours[0].cross(neighbours[1])\n return Math.abs((Math.PI / 2) - cp.angleTo(v12))\n}\n","/**\n * @file Valence Model\n * @author Fred Ludlow \n * @author Alexander Rose \n */\n\n/**\n * Reworked ValenceModel\n *\n * TODO:\n * Ensure proper treatment of disorder/models. e.g. V257 N in 5vim\n * Formal charge of 255 for SO4 anion (e.g. 5ghl)\n * Have removed a lot of explicit features (as I think they're more\n * generally captured by better VM).\n * Could we instead have a \"delocalised negative/positive\" charge\n * feature and flag these up?\n *\n */\nimport { Data } from '../structure/data'\nimport AtomProxy from '../proxy/atom-proxy'\nimport { AtomGeometry, assignGeometry } from './geometry'\nimport { Elements } from '../structure/structure-constants'\n\n/**\n * Are we involved in some kind of pi system. Either explicitly forming\n * double bond or N, O next to a double bond, except:\n *\n * N,O with degree 4 cannot be conjugated.\n * N,O adjacent to P=O or S=O do not qualify (keeps sulfonamide N sp3 geom)\n */\nfunction isConjugated (a: AtomProxy) {\n const _bp = a.structure.getBondProxy()\n const atomicNumber = a.number\n const hetero = atomicNumber === Elements.O || atomicNumber === Elements.N\n\n if (hetero && a.bondCount === 4) {\n return false\n }\n\n let flag = false\n\n a.eachBond(b => {\n if (b.bondOrder > 1) {\n flag = true\n return\n }\n if (hetero) {\n const a2 = b.getOtherAtom(a)\n\n a2.eachBond(b2 => {\n if (b2.bondOrder > 1) {\n const atomicNumber2 = a2.number\n if (\n (atomicNumber2 === Elements.P || atomicNumber2 === Elements.S) &&\n b2.getOtherAtom(a2).number === Elements.O\n ) {\n return\n }\n flag = true\n }\n }, _bp) // Avoid reuse of structure._bp\n }\n })\n\n return flag\n}\n\n/* function hasExplicitCharge(r: ResidueProxy) {\n let flag = false\n r.eachAtom(a => {\n if (a.formalCharge != null && a.formalCharge !== 0) flag = true\n })\n return flag\n}\n\nfunction hasExplicitHydrogen(r: ResidueProxy) {\n let flag = false\n r.eachAtom(a => {\n if (a.number === Elements.H) flag = true\n })\n return flag\n} */\n\nexport function explicitValence (a: AtomProxy) {\n let v = 0\n a.eachBond(b => v += b.bondOrder)\n return v\n}\n\n/**\n * Attempts to produce a consistent charge and implicit\n * H-count for an atom.\n *\n * If both params.assignCharge and params.assignH, this\n * approximately followsthe rules described in\n * https://docs.eyesopen.com/toolkits/python/oechemtk/valence.html#openeye-hydrogen-count-model\n *\n * If only charge or hydrogens are to be assigned it takes\n * a much simpler view and deduces one from the other\n *\n * @param {AtomProxy} a Atom to analyze\n * @param {assignChargeHParams} params What to assign\n */\nexport function calculateHydrogensCharge (a: AtomProxy, params: ValenceModelParams) {\n const hydrogenCount = a.bondToElementCount(Elements.H)\n let charge = a.formalCharge || 0\n\n const assignCharge = (params.assignCharge === 'always' ||\n (params.assignCharge === 'auto' && charge === 0))\n const assignH = (params.assignH === 'always' ||\n (params.assignH === 'auto' && hydrogenCount === 0))\n\n const degree = a.bondCount\n const valence = explicitValence(a)\n\n const conjugated = isConjugated(a)\n const multiBond = (valence - degree > 0)\n\n\n let implicitHCount = 0\n let geom = AtomGeometry.Unknown\n\n switch (a.number) {\n case Elements.H:\n if (assignCharge){\n if (degree === 0){\n charge = 1\n geom = AtomGeometry.Spherical\n } else if (degree === 1) {\n charge = 0\n geom = AtomGeometry.Terminal\n }\n }\n break\n\n case Elements.C:\n // TODO: Isocyanide?\n if (assignCharge) {\n charge = 0 // Assume carbon always neutral\n }\n if (assignH) {\n // Carbocation/carbanion are 3-valent\n implicitHCount = Math.max(0, 4 - valence - Math.abs(charge))\n }\n // Carbocation is planar, carbanion is tetrahedral\n geom = assignGeometry(degree + implicitHCount + Math.max(0, -charge))\n break\n\n case Elements.N:\n if (assignCharge) {\n if (!assignH) { // Trust input H explicitly:\n charge = valence - 3\n } else if (conjugated && valence < 4) {\n // Neutral unless amidine/guanidine double-bonded N:\n if (degree - hydrogenCount === 1 && valence - hydrogenCount === 2) {\n charge = 1\n } else {\n charge = 0\n }\n } else {\n // Sulfonamide nitrogen and classed as sp3 in conjugation model but\n // they won't be charged\n // Don't assign charge to nitrogens bound to metals\n let flag = false\n a.eachBondedAtom(ba => {\n if (ba.number === Elements.S || ba.isMetal()) flag = true\n })\n if (flag) charge = 0\n else charge = 1\n // TODO: Planarity sanity check?\n }\n\n }\n\n if (assignH) {\n // NH4+ -> 4, 1' amide -> 2, nitro N/N+ depiction -> 0\n implicitHCount = Math.max(0, 3 - valence + charge)\n }\n\n if (conjugated && !multiBond) {\n // Amide, anilinic N etc. cannot consider lone-pair for geometry purposes\n // Anilinic N geometry is depenent on ring electronics, for our purposes we\n // assume it's trigonal!\n geom = assignGeometry(degree + implicitHCount - charge)\n } else {\n // Everything else, pyridine, amine, nitrile, lp plays normal role:\n geom = assignGeometry(degree + implicitHCount + 1 - charge)\n }\n break\n\n case Elements.O:\n if (assignCharge) {\n if (!assignH) {\n charge = valence - 2 //\n }\n if (valence === 1) {\n a.eachBondedAtom(ba => {\n ba.eachBond(b => {\n const oa = b.getOtherAtom(ba)\n if (oa.index !== a.index && oa.number === Elements.O && b.bondOrder === 2){\n charge = -1\n }\n })\n })\n }\n }\n if (assignH) {\n // ethanol -> 1, carboxylate -> -1\n implicitHCount = Math.max(0, 2 - valence + charge)\n }\n if (conjugated && !multiBond){\n // carboxylate OH, phenol OH, one lone-pair taken up with conjugation\n geom = assignGeometry(degree + implicitHCount - charge + 1)\n } else {\n // Carbonyl (trigonal)\n geom = assignGeometry(degree + implicitHCount - charge + 2)\n }\n break\n\n // Only handles thiols/thiolates/thioether/sulfonium. Sulfoxides and higher\n // oxidiation states are assumed neutral S (charge carried on O if required)\n case Elements.S:\n if (assignCharge) {\n if (!assignH) {\n if (valence <= 3 && !a.bondToElementCount(Elements.O)) {\n charge = valence - 2 // e.g. explicitly deprotonated thiol\n } else {\n charge = 0\n }\n }\n }\n if (assignH){\n if (valence < 2){\n implicitHCount = Math.max(0, 2 - valence + charge)\n }\n }\n if (valence <= 3){\n // Thiol, thiolate, tioether -> tetrahedral\n geom = assignGeometry(degree + implicitHCount - charge + 2)\n }\n\n break\n\n case Elements.F:\n case Elements.CL:\n case Elements.BR:\n case Elements.I:\n case Elements.AT:\n // Never implicitly protonate halides\n if (assignCharge) {\n charge = valence - 1\n }\n break\n\n case Elements.LI:\n case Elements.NA:\n case Elements.K:\n case Elements.RB:\n case Elements.CS:\n case Elements.FR:\n if (assignCharge) {\n charge = 1 - valence\n }\n break\n\n case Elements.BE:\n case Elements.MG:\n case Elements.CA:\n case Elements.SR:\n case Elements.BA:\n case Elements.RA:\n if (assignCharge) {\n charge = 2 - valence\n }\n break\n\n default:\n console.warn('Requested charge, protonation for an unhandled element', a.element)\n }\n\n return [ charge, implicitHCount, implicitHCount + hydrogenCount, geom ]\n}\n\n\nexport interface ValenceModel {\n charge: Int8Array,\n implicitH: Int8Array,\n totalH: Int8Array,\n idealGeometry: Int8Array\n}\n\nexport interface ValenceModelParams {\n assignCharge: string,\n assignH: string\n}\n\nexport function ValenceModel (data: Data, params: ValenceModelParams) {\n const structure = data.structure\n const n = structure.atomCount\n\n const charge = new Int8Array(n)\n const implicitH = new Int8Array(n)\n const totalH = new Int8Array(n)\n const idealGeometry = new Int8Array(n)\n\n structure.eachAtom(a => {\n const i = a.index\n const [ chg, implH, totH, geom ] = calculateHydrogensCharge(a, params)\n charge[ i ] = chg\n implicitH[ i ] = implH\n totalH[ i ] = totH\n idealGeometry[ i ] = geom\n })\n\n return { charge, implicitH, totalH, idealGeometry }\n}","\nimport Structure from './structure'\nimport SpatialHash from '../geometry/spatial-hash'\nimport { ValenceModel } from '../chemistry/valence-model'\n\nexport interface Data {\n structure: Structure\n '@spatialLookup': SpatialHash | undefined\n '@valenceModel': ValenceModel | undefined\n}\n\nexport function createData(structure: Structure): Data {\n return {\n structure,\n '@spatialLookup': undefined,\n '@valenceModel': undefined\n }\n}\n\nexport function spatialLookup(data: Data): SpatialHash {\n if (data['@spatialLookup']) return data['@spatialLookup']!\n const lookup = new SpatialHash(data.structure.atomStore, data.structure.boundingBox)\n data['@spatialLookup'] = lookup\n return lookup\n}\n\nexport function valenceModel(data: Data): ValenceModel {\n if (data['@valenceModel']) return data['@valenceModel']!\n const valenceModel = ValenceModel(data, {assignCharge: 'auto', assignH: 'auto'})\n data['@valenceModel'] = valenceModel\n return valenceModel\n}\n","/**\n * @file Functional Groups\n * @author Alexander Rose \n */\n\nimport AtomProxy from '../proxy/atom-proxy'\nimport { Elements } from '../structure/structure-constants'\n\n/**\n * Nitrogen in a quaternary amine\n */\nexport function isQuaternaryAmine (a: AtomProxy) {\n return (\n a.number === 7 &&\n a.bondCount === 4 &&\n a.bondToElementCount(Elements.H) === 0\n )\n}\n\n/**\n * Nitrogen in a tertiary amine\n */\nexport function isTertiaryAmine (a: AtomProxy, idealValence: number) {\n return (\n a.number === 7 &&\n a.bondCount >= 3 &&\n idealValence === 3\n )\n}\n\n/**\n * Nitrogen in an imide\n */\nexport function isImide (a: AtomProxy) {\n let flag = false\n if (a.number === Elements.N && (a.bondCount - a.bondToElementCount(Elements.H)) === 2) {\n let carbonylCount = 0\n a.eachBondedAtom(ba => {\n if (isCarbonyl(ba)) ++carbonylCount\n })\n flag = carbonylCount === 2\n }\n return flag\n}\n\n/**\n * Nitrogen in an amide\n */\nexport function isAmide (a: AtomProxy) {\n let flag = false\n if (a.number === Elements.N && (a.bondCount - a.bondToElementCount(Elements.H)) === 2) {\n let carbonylCount = 0\n a.eachBondedAtom(ba => {\n if (isCarbonyl(ba)) ++carbonylCount\n })\n flag = carbonylCount === 1\n }\n return flag\n}\n\n/**\n * Sulfur in a sulfonium group\n */\nexport function isSulfonium (a: AtomProxy) {\n return (\n a.number === 16 &&\n a.bondCount === 3 &&\n a.bondToElementCount(Elements.H) === 0\n )\n}\n\n/**\n * Sulfur in a sulfonic acid or sulfonate group\n */\nexport function isSulfonicAcid (a: AtomProxy) {\n return (\n a.number === 16 &&\n a.bondToElementCount(Elements.O) === 3\n )\n}\n\n/**\n * Sulfur in a sulfate group\n */\nexport function isSulfate (a: AtomProxy) {\n return (\n a.number === 16 &&\n a.bondToElementCount(Elements.O) === 4\n )\n}\n\n/**\n * Phosphor in a phosphate group\n */\nexport function isPhosphate (a: AtomProxy) {\n return (\n a.number === 15 &&\n a.bondToElementCount(Elements.O) === a.bondCount\n )\n}\n\n/**\n * Halogen with one bond to a carbon\n */\nexport function isHalocarbon (a: AtomProxy) {\n return (\n a.isHalogen() &&\n a.bondCount === 1 &&\n a.bondToElementCount(Elements.C) === 1\n )\n}\n\n/**\n * Carbon in a carbonyl/acyl group\n */\nexport function isCarbonyl (a: AtomProxy) {\n let flag = false\n if (a.number === Elements.C) {\n a.eachBond(b => {\n if (b.bondOrder === 2 && b.getOtherAtom(a).number === Elements.O) {\n flag = true\n }\n })\n }\n return flag\n}\n\n/**\n * Carbon in a carboxylate group\n */\nexport function isCarboxylate (a: AtomProxy) {\n let terminalOxygenCount = 0\n if (\n a.number === 6 &&\n a.bondToElementCount(Elements.O) === 2 &&\n a.bondToElementCount(Elements.C) === 1\n ) {\n a.eachBondedAtom(ba => {\n if (ba.number === 8 && ba.bondCount - ba.bondToElementCount(Elements.H) === 1) {\n ++terminalOxygenCount\n }\n })\n }\n return terminalOxygenCount === 2\n}\n\n/**\n * Carbon in a guanidine group\n */\nexport function isGuanidine (a: AtomProxy) {\n let terminalNitrogenCount = 0\n if (\n a.number === 6 &&\n a.bondCount === 3 &&\n a.bondToElementCount(Elements.N) === 3\n ) {\n a.eachBondedAtom(ba => {\n if (ba.bondCount - ba.bondToElementCount(Elements.H) === 1) {\n ++terminalNitrogenCount\n }\n })\n }\n return terminalNitrogenCount === 2\n}\n\n/**\n * Carbon in a acetamidine group\n */\nexport function isAcetamidine (a: AtomProxy) {\n let terminalNitrogenCount = 0\n if (\n a.number === 6 &&\n a.bondCount === 3 &&\n a.bondToElementCount(Elements.N) === 2 &&\n a.bondToElementCount(Elements.C) === 1\n ) {\n a.eachBondedAtom(ba => {\n if (ba.bondCount - ba.bondToElementCount(Elements.H) === 1) {\n ++terminalNitrogenCount\n }\n })\n }\n return terminalNitrogenCount === 2\n}\n\nconst PolarElements = [\n Elements.N, Elements.O, Elements.S,\n Elements.F, Elements.CL, Elements.BR, Elements.I\n]\n\nexport function isPolar (a: AtomProxy) {\n return PolarElements.includes(a.number)\n}\n\nexport function hasPolarNeighbour (a: AtomProxy) {\n let flag = false\n a.eachBondedAtom(ba => {\n if (isPolar(ba)) flag = true\n })\n return flag\n}\n\nexport function hasAromaticNeighbour (a: AtomProxy) {\n let flag = false\n a.eachBondedAtom(function (bap) {\n if (bap.aromatic) flag = true\n })\n return flag\n}\n","/**\n * @file Charged\n * @author Alexander Rose \n * @author Fred Ludlow \n */\n\nimport { Vector3 } from 'three'\n\nimport { defaults } from '../../utils'\nimport { radToDeg } from '../../math/math-utils'\nimport Structure from '../../structure/structure'\nimport { AA3, Bases, Elements } from '../../structure/structure-constants'\nimport { valenceModel } from '../../structure/data'\nimport {\n isGuanidine, isAcetamidine, isSulfonicAcid, isPhosphate, isSulfate, isCarboxylate\n} from '../functional-groups'\nimport {\n Features, FeatureType, FeatureGroup,\n addAtom, addFeature, createFeatureState,\n} from './features'\nimport { Contacts, ContactType, ContactDefaultParams, invalidAtomContact } from './contact'\n\nconst PositvelyCharged = [ 'ARG', 'HIS', 'LYS' ]\nconst NegativelyCharged = [ 'GLU', 'ASP' ]\n\nexport function addPositiveCharges (structure: Structure, features: Features) {\n const { charge } = valenceModel(structure.data)\n const atomInGroupDict: { [atomIndex: number]: true } = {}\n\n structure.eachResidue(r => {\n if (PositvelyCharged.includes(r.resname)) {\n const state = createFeatureState(FeatureType.PositiveCharge)\n r.eachAtom(a => {\n if (a.number === Elements.N && a.isSidechain()) {\n addAtom(state, a)\n }\n })\n addFeature(features, state)\n } else if(!AA3.includes(r.resname) && !r.isNucleic()) {\n r.eachAtom(a => {\n let addGroup = false\n const state = createFeatureState(FeatureType.PositiveCharge)\n if (isGuanidine(a)) {\n state.group = FeatureGroup.Guanidine\n addGroup = true\n } else if (isAcetamidine(a)) {\n state.group = FeatureGroup.Acetamidine\n addGroup = true\n }\n if (addGroup) {\n a.eachBondedAtom(a => {\n if (a.number === Elements.N) {\n atomInGroupDict[a.index] = true\n addAtom(state, a)\n }\n })\n addFeature(features, state)\n }\n })\n r.eachAtom(a => {\n const state = createFeatureState(FeatureType.PositiveCharge)\n if (charge[a.index] > 0) {\n if (!atomInGroupDict[a.index]) {\n addAtom(state, a)\n addFeature(features, state)\n }\n }\n })\n }\n })\n}\n\nexport function addNegativeCharges (structure: Structure, features: Features) {\n const { charge } = valenceModel(structure.data)\n const atomInGroupDict: { [atomIndex: number]: true } = {}\n\n structure.eachResidue(r => {\n if (NegativelyCharged.includes(r.resname)) {\n const state = createFeatureState(FeatureType.NegativeCharge)\n r.eachAtom(a => {\n if (a.number === Elements.O && a.isSidechain()) {\n addAtom(state, a)\n }\n })\n addFeature(features, state)\n } else if (Bases.includes(r.resname)) {\n const state = createFeatureState(FeatureType.NegativeCharge)\n r.eachAtom(a => {\n if (isPhosphate(a)) {\n state.group = FeatureGroup.Phosphate\n a.eachBondedAtom(a => {\n if (a.number === Elements.O) addAtom(state, a)\n })\n addFeature(features, state)\n }\n })\n } else if(!AA3.includes(r.resname) && !Bases.includes(r.resname)) {\n r.eachAtom(a => {\n let addGroup = false\n const state = createFeatureState(FeatureType.NegativeCharge)\n if (isSulfonicAcid(a)) {\n state.group = FeatureGroup.SulfonicAcid\n addGroup = true\n } else if (isPhosphate(a)) {\n state.group = FeatureGroup.Phosphate\n addGroup = true\n } else if (isSulfate(a)) {\n state.group = FeatureGroup.Sulfate\n addGroup = true\n } else if (isCarboxylate(a)) {\n state.group = FeatureGroup.Carboxylate\n addGroup = true\n }\n if (addGroup) {\n a.eachBondedAtom(a => {\n if (a.number === Elements.O) {\n atomInGroupDict[a.index] = true\n addAtom(state, a)\n }\n })\n addFeature(features, state)\n }\n })\n r.eachAtom(a => {\n const state = createFeatureState(FeatureType.NegativeCharge)\n if (charge[a.index] < 0) {\n if (!atomInGroupDict[a.index]) {\n addAtom(state, a)\n addFeature(features, state)\n }\n }\n })\n }\n })\n}\n\nexport function addAromaticRings (structure: Structure, features: Features) {\n const a = structure.getAtomProxy()\n structure.eachResidue(r => {\n const rings = r.getAromaticRings()\n if (rings) {\n const offset = r.atomOffset\n rings.forEach(ring => {\n const state = createFeatureState(FeatureType.AromaticRing)\n ring.forEach(i => {\n a.index = i + offset\n addAtom(state, a)\n })\n addFeature(features, state)\n })\n }\n })\n}\n\nfunction isIonicInteraction (ti: FeatureType, tj: FeatureType) {\n return (\n (ti === FeatureType.NegativeCharge && tj === FeatureType.PositiveCharge) ||\n (ti === FeatureType.PositiveCharge && tj === FeatureType.NegativeCharge)\n )\n}\n\nfunction isPiStacking (ti: FeatureType, tj: FeatureType) {\n return ti === FeatureType.AromaticRing && tj === FeatureType.AromaticRing\n}\n\nfunction isCationPi (ti: FeatureType, tj: FeatureType) {\n return (\n (ti === FeatureType.AromaticRing && tj === FeatureType.PositiveCharge) ||\n (ti === FeatureType.PositiveCharge && tj === FeatureType.AromaticRing)\n )\n}\n\nexport interface ChargedContactsParams {\n maxIonicDist?: number\n maxPiStackingDist?: number\n maxPiStackingOffset?: number\n maxPiStackingAngle?: number\n maxCationPiDist?: number\n maxCationPiOffset?: number\n masterModelIndex?: number\n}\n\nexport function addChargedContacts (structure: Structure, contacts: Contacts, params: ChargedContactsParams = {}) {\n const maxIonicDist = defaults(params.maxIonicDist, ContactDefaultParams.maxIonicDist)\n const maxPiStackingDist = defaults(params.maxPiStackingDist, ContactDefaultParams.maxPiStackingDist)\n const maxPiStackingOffset = defaults(params.maxPiStackingOffset, ContactDefaultParams.maxPiStackingOffset)\n const maxPiStackingAngle = defaults(params.maxPiStackingAngle, ContactDefaultParams.maxPiStackingAngle)\n const maxCationPiDist = defaults(params.maxCationPiDist, ContactDefaultParams.maxCationPiDist)\n const maxCationPiOffset = defaults(params.maxCationPiOffset, ContactDefaultParams.maxCationPiOffset)\n const masterIdx = defaults(params.masterModelIndex, ContactDefaultParams.masterModelIndex)\n\n const maxDistance = Math.max(maxIonicDist + 2, maxPiStackingDist, maxCationPiDist)\n // const maxSaltBridgeDistSq = maxSaltBridgeDist * maxSaltBridgeDist\n const maxPiStackingDistSq = maxPiStackingDist * maxPiStackingDist\n const maxCationPiDistSq = maxCationPiDist * maxCationPiDist\n\n const { features, spatialHash, contactStore, featureSet } = contacts\n const { types, centers, atomSets } = features\n const { x, y, z } = centers\n const n = types.length\n\n const ax = structure.atomStore.x\n const ay = structure.atomStore.y\n const az = structure.atomStore.z\n\n const ap1 = structure.getAtomProxy()\n const ap2 = structure.getAtomProxy()\n\n const areAtomSetsWithinDist = function (atomSet1: number[], atomSet2: number[], maxDist: number) {\n const sn = atomSet1.length\n const sm = atomSet2.length\n for (let si = 0; si < sn; ++si) {\n ap1.index = atomSet1[ si ]\n for (let sj = 0; sj < sm; ++sj) {\n ap2.index = atomSet2[ sj ]\n if (ap1.distanceTo(ap2) <= maxDist) {\n return true\n }\n }\n }\n return false\n }\n\n const v1 = new Vector3()\n const v2 = new Vector3()\n const v3 = new Vector3()\n const d1 = new Vector3()\n const d2 = new Vector3()\n const n1 = new Vector3()\n const n2 = new Vector3()\n\n const getNormal = function (atoms: number[], normal: Vector3) {\n v1.set(ax[ atoms[ 0 ] ], ay[ atoms[ 0 ] ], az[ atoms[ 0 ] ])\n v2.set(ax[ atoms[ 1 ] ], ay[ atoms[ 1 ] ], az[ atoms[ 1 ] ])\n v3.set(ax[ atoms[ 2 ] ], ay[ atoms[ 2 ] ], az[ atoms[ 2 ] ])\n d1.subVectors(v1, v2)\n d2.subVectors(v1, v3)\n normal.crossVectors(d1, d2)\n }\n\n const getOffset = function (i: number, j: number, normal: Vector3) {\n v1.set(x[ i ], y[ i ], z[ i ])\n v2.set(x[ j ], y[ j ], z[ j ])\n return v1.sub(v2).projectOnPlane(normal).add(v2).distanceTo(v2)\n }\n\n const add = function (i: number, j: number, ct: ContactType) {\n featureSet.setBits(i, j)\n contactStore.addContact(i, j, ct)\n }\n\n for (let i = 0; i < n; ++i) {\n spatialHash.eachWithin(x[i], y[i], z[i], maxDistance, (j, dSq) => {\n if (j <= i) return\n\n ap1.index = atomSets[ i ][ 0 ]\n ap2.index = atomSets[ j ][ 0 ]\n\n if (invalidAtomContact(ap1, ap2, masterIdx)) return\n\n const ti = types[ i ]\n const tj = types[ j ]\n\n if (isIonicInteraction(ti, tj)) {\n if (areAtomSetsWithinDist(atomSets[ i ], atomSets[ j ], maxIonicDist)) {\n add(i, j, ContactType.IonicInteraction)\n }\n } else if (isPiStacking(ti, tj)) {\n if (dSq <= maxPiStackingDistSq) {\n getNormal(atomSets[ i ], n1)\n getNormal(atomSets[ j ], n2)\n\n const angle = radToDeg(n1.angleTo(n2))\n const offset = Math.min(getOffset(i, j, n2), getOffset(j, i, n1))\n if (offset <= maxPiStackingOffset) {\n if (angle <= maxPiStackingAngle || angle >= 180 - maxPiStackingAngle) {\n add(i, j, ContactType.PiStacking) // parallel\n } else if (angle <= maxPiStackingAngle + 90 && angle >= 90 - maxPiStackingAngle) {\n add(i, j, ContactType.PiStacking) // t-shaped\n }\n }\n }\n } else if (isCationPi(ti, tj)) {\n if (dSq <= maxCationPiDistSq) {\n const [ l, k ] = ti === FeatureType.AromaticRing ? [ i, j ] : [ j, i ]\n\n getNormal(atomSets[ l ], n1)\n const offset = getOffset(k, l, n1)\n if (offset <= maxCationPiOffset) {\n add(l, k, ContactType.CationPi)\n }\n }\n }\n })\n }\n}\n","/**\n * @file Hydrogen Bonds\n * @author Alexander Rose \n * @author Fred Ludlow \n */\nimport { defaults } from '../../utils'\nimport { degToRad } from '../../math/math-utils'\nimport Structure from '../../structure/structure'\nimport AtomProxy from '../../proxy/atom-proxy'\nimport { valenceModel } from '../../structure/data'\nimport { Elements } from '../../structure/structure-constants'\nimport { Angles, AtomGeometry, calcAngles, calcPlaneAngle } from '../geometry'\nimport {\n Features, FeatureType,\n addAtom, addFeature, createFeatureState,\n} from './features'\nimport { Contacts, ContactType, ContactDefaultParams, invalidAtomContact } from './contact'\n\n\n// Geometric characteristics of hydrogen bonds involving sulfur atoms in proteins\n// https://doi.org/10.1002/prot.22327\n\n// Satisfying Hydrogen Bonding Potential in Proteins (HBPLUS)\n// https://doi.org/10.1006/jmbi.1994.1334\n// http://www.csb.yale.edu/userguides/datamanip/hbplus/hbplus_descrip.html\n\n/**\n * Potential hydrogen donor\n */\nexport function addHydrogenDonors (structure: Structure, features: Features) {\n const { totalH } = valenceModel(structure.data)\n\n structure.eachAtom(a => {\n const state = createFeatureState(FeatureType.HydrogenDonor)\n\n const an = a.number\n if (isHistidineNitrogen(a)) {\n // include both nitrogen atoms in histidine due to\n // their often ambiguous protonation assignment\n addAtom(state, a)\n addFeature(features, state)\n } else if (\n totalH[ a.index ] > 0 &&\n (an === Elements.N || an === Elements.O || an === Elements.S)\n ) {\n addAtom(state, a)\n addFeature(features, state)\n }\n })\n}\n\n/**\n * Weak hydrogen donor.\n */\nexport function addWeakHydrogenDonors (structure: Structure, features: Features) {\n const { totalH } = valenceModel(structure.data)\n\n structure.eachAtom(a => {\n if (\n a.number === Elements.C &&\n totalH[ a.index ] > 0 &&\n (\n a.bondToElementCount(Elements.N) > 0 ||\n a.bondToElementCount(Elements.O) > 0 ||\n inAromaticRingWithElectronNegativeElement(a)\n )\n ) {\n const state = createFeatureState(FeatureType.WeakHydrogenDonor)\n addAtom(state, a)\n addFeature(features, state)\n }\n })\n}\n\nfunction inAromaticRingWithElectronNegativeElement (a: AtomProxy) {\n if (!a.isAromatic()) return false\n\n const ringData = a.residueType.getRings()\n if (!ringData) return false\n\n let hasElement = false\n const rings = ringData.rings\n rings.forEach(ring => {\n if (hasElement) return // already found one\n if (ring.some(idx => (a.index - a.residueAtomOffset) === idx)) { // in ring\n hasElement = ring.some(idx => {\n const atomTypeId = a.residueType.atomTypeIdList[ idx ]\n const number = a.atomMap.get(atomTypeId).number\n return number === Elements.N || number === Elements.O\n })\n }\n })\n\n return hasElement\n}\n\n/**\n * Potential hydrogen acceptor\n */\nexport function addHydrogenAcceptors (structure: Structure, features: Features) {\n const { charge, implicitH, idealGeometry } = valenceModel(structure.data)\n\n structure.eachAtom(a => {\n const state = createFeatureState(FeatureType.HydrogenAcceptor)\n\n const an = a.number\n if (an === Elements.O) {\n // Basically assume all oxygen atoms are acceptors!\n addAtom(state, a)\n addFeature(features, state)\n }else if (an === Elements.N) {\n if (isHistidineNitrogen(a)) {\n // include both nitrogen atoms in histidine due to\n // their often ambiguous protonation assignment\n addAtom(state, a)\n addFeature(features, state)\n } else if (charge[ a.index ] < 1){\n // Neutral nitrogen might be an acceptor\n // It must have at least one lone pair not conjugated\n const totalBonds = a.bondCount + implicitH[ a.index ]\n const ig = idealGeometry[ a.index ]\n if (\n (ig === AtomGeometry.Tetrahedral && totalBonds < 4) ||\n (ig === AtomGeometry.Trigonal && totalBonds < 3) ||\n (ig === AtomGeometry.Linear && totalBonds < 2)\n ) {\n addAtom(state, a)\n addFeature(features, state)\n }\n }\n }else if (an === 16) { // S\n if (a.resname === 'CYS' || a.resname === 'MET' || a.formalCharge === -1) {\n addAtom(state, a)\n addFeature(features, state)\n }\n }\n })\n}\n\n/**\n * Atom that is only bound to carbon or hydrogen\n */\n// function isHydrocarbon (atom: AtomProxy) {\n// let flag = true\n// atom.eachBondedAtom(ap => {\n// const e = ap.element\n// if (e !== 'C' && e !== 'H') flag = false\n// })\n// return flag\n// }\n\nfunction isHistidineNitrogen (ap: AtomProxy) {\n return ap.resname === 'HIS' && ap.number == Elements.N && ap.isRing()\n}\n\nfunction isBackboneHydrogenBond (ap1: AtomProxy, ap2: AtomProxy) {\n return ap1.isBackbone() && ap2.isBackbone()\n}\n\nfunction isWaterHydrogenBond (ap1: AtomProxy, ap2: AtomProxy) {\n return ap1.isWater() && ap2.isWater()\n}\n\nfunction isHydrogenBond (ti: FeatureType, tj: FeatureType) {\n return (\n (ti === FeatureType.HydrogenAcceptor && tj === FeatureType.HydrogenDonor) ||\n (ti === FeatureType.HydrogenDonor && tj === FeatureType.HydrogenAcceptor)\n )\n}\n\nfunction isWeakHydrogenBond (ti: FeatureType, tj: FeatureType){\n return (\n (ti === FeatureType.WeakHydrogenDonor && tj === FeatureType.HydrogenAcceptor) ||\n (ti === FeatureType.HydrogenAcceptor && tj === FeatureType.WeakHydrogenDonor)\n )\n}\n\nfunction getHydrogenBondType (ap1: AtomProxy, ap2: AtomProxy) {\n if (isWaterHydrogenBond(ap1, ap2)) {\n return ContactType.WaterHydrogenBond\n } else if (isBackboneHydrogenBond(ap1, ap2)) {\n return ContactType.BackboneHydrogenBond\n } else {\n return ContactType.HydrogenBond\n }\n}\n\nexport interface HydrogenBondParams {\n maxHbondDist?: number\n maxHbondSulfurDist?: number\n maxHbondAccAngle?: number\n maxHbondDonAngle?: number\n maxHbondAccPlaneAngle?: number\n maxHbondDonPlaneAngle?: number\n backboneHbond?: boolean\n waterHbond?: boolean\n masterModelIndex?: number\n}\n\n/**\n * All pairs of hydrogen donor and acceptor atoms\n */\nexport function addHydrogenBonds (structure: Structure, contacts: Contacts, params: HydrogenBondParams = {}) {\n const maxHbondDist = defaults(params.maxHbondDist, ContactDefaultParams.maxHbondDist)\n const maxHbondSulfurDist = defaults(params.maxHbondSulfurDist, ContactDefaultParams.maxHbondSulfurDist)\n const maxHbondAccAngle = degToRad(defaults(params.maxHbondAccAngle, ContactDefaultParams.maxHbondAccAngle))\n const maxHbondDonAngle = degToRad(defaults(params.maxHbondDonAngle, ContactDefaultParams.maxHbondDonAngle))\n const maxHbondAccPlaneAngle = degToRad(defaults(params.maxHbondAccPlaneAngle, ContactDefaultParams.maxHbondAccPlaneAngle))\n const maxHbondDonPlaneAngle = degToRad(defaults(params.maxHbondDonPlaneAngle, ContactDefaultParams.maxHbondDonPlaneAngle))\n const masterIdx = defaults(params.masterModelIndex, ContactDefaultParams.masterModelIndex)\n\n const maxDist = Math.max(maxHbondDist, maxHbondSulfurDist)\n const maxHbondDistSq = maxHbondDist * maxHbondDist\n\n const { features, spatialHash, contactStore, featureSet } = contacts\n const { types, centers, atomSets } = features\n const { x, y, z } = centers\n const n = types.length\n\n const { idealGeometry } = valenceModel(structure.data)\n\n const donor = structure.getAtomProxy()\n const acceptor = structure.getAtomProxy()\n\n for (let i = 0; i < n; ++i) {\n spatialHash.eachWithin(x[i], y[i], z[i], maxDist, (j, dSq) => {\n if (j <= i) return\n\n const ti = types[ i ]\n const tj = types[ j ]\n\n const isWeak = isWeakHydrogenBond(ti, tj)\n if (!isWeak && !isHydrogenBond(ti, tj)) return\n\n const [ l, k ] = tj === FeatureType.HydrogenAcceptor ? [ i, j ] : [ j, i ]\n\n donor.index = atomSets[ l ][ 0 ]\n acceptor.index = atomSets[ k ][ 0 ]\n\n if (acceptor.index === donor.index) return // DA to self\n\n if (invalidAtomContact(donor, acceptor, masterIdx)) return\n if (donor.number !== Elements.S && acceptor.number !== Elements.S && dSq > maxHbondDistSq) return\n if (donor.connectedTo(acceptor)) return\n\n const donorAngles = calcAngles(donor, acceptor)\n const idealDonorAngle = Angles.get(idealGeometry[donor.index]) || degToRad(120)\n if (donorAngles.some(donorAngle => {\n return Math.abs(idealDonorAngle - donorAngle) > maxHbondDonAngle\n })) return\n\n if (idealGeometry[donor.index] === AtomGeometry.Trigonal){\n const outOfPlane = calcPlaneAngle(donor, acceptor)\n if (outOfPlane !== undefined && outOfPlane > maxHbondDonPlaneAngle) return\n }\n\n const acceptorAngles = calcAngles(acceptor, donor)\n const idealAcceptorAngle = Angles.get(idealGeometry[acceptor.index]) || degToRad(120)\n if (acceptorAngles.some(acceptorAngle => {\n // Do not limit large acceptor angles\n return idealAcceptorAngle - acceptorAngle > maxHbondAccAngle\n })) return\n\n if (idealGeometry[acceptor.index] === AtomGeometry.Trigonal){\n const outOfPlane = calcPlaneAngle(acceptor, donor)\n if (outOfPlane !== undefined && outOfPlane > maxHbondAccPlaneAngle) return\n }\n\n featureSet.setBits(l, k)\n const bondType = isWeak ? ContactType.WeakHydrogenBond : getHydrogenBondType(donor, acceptor)\n contactStore.addContact(l, k, bondType)\n })\n }\n}\n","/**\n * @file Metal Binding\n * @author Alexander Rose \n */\n\nimport { defaults } from '../../utils'\nimport Structure from '../../structure/structure'\n// import { valenceModel } from '../../structure/data'\nimport { Elements, AA3, Bases } from '../../structure/structure-constants'\n// import { hasAromaticNeighbour } from '../functional-groups'\nimport {\n Features, FeatureType,\n addAtom, addFeature, createFeatureState,\n} from './features'\nimport { Contacts, ContactType, ContactDefaultParams, invalidAtomContact } from './contact'\n\nconst IonicTypeMetals = [\n Elements.LI, Elements.NA, Elements.K, Elements.RB, Elements.CS,\n Elements.MG, Elements.CA, Elements.SR, Elements.BA, Elements.AL,\n Elements.GA, Elements.IN, Elements.TL, Elements.SC, Elements.SN,\n Elements.PB, Elements.BI, Elements.SB, Elements.HG\n]\n\n/**\n * Metal binding partners (dative bond or ionic-type interaction)\n */\nexport function addMetalBinding (structure: Structure, features: Features) {\n structure.eachAtom(a => {\n let dative = false\n let ionic = false\n\n const isStandardAminoacid = AA3.includes(a.resname)\n const isStandardBase = Bases.includes(a.resname)\n\n if (!isStandardAminoacid && !isStandardBase) {\n if (a.isHalogen() || a.number === Elements.O || a.number === Elements.S) {\n dative = true\n ionic = true\n } else if (a.number === Elements.N) {\n dative = true\n }\n } else if (isStandardAminoacid){\n // main chain oxygen atom or oxygen, nitrogen and sulfur from specific amino acids\n if (a.number === Elements.O) {\n if(['ASP', 'GLU', 'SER', 'THR', 'TYR', 'ASN', 'GLN'].includes(a.resname) && a.isSidechain()) {\n dative = true\n ionic = true\n } else if (a.isBackbone()) {\n dative = true\n ionic = true\n }\n } else if (a.number === Elements.S && 'CYS' === a.resname) {\n dative = true\n ionic = true\n } else if (a.number === Elements.N) {\n if(a.resname === 'HIS' && a.isSidechain()) {\n dative = true\n }\n }\n } else if (isStandardBase){\n // http://pubs.acs.org/doi/pdf/10.1021/acs.accounts.6b00253\n // http://onlinelibrary.wiley.com/doi/10.1002/anie.200900399/full\n if (a.number === Elements.O && a.isBackbone()) {\n dative = true\n ionic = true\n } else if(['N3', 'N4', 'N7'].includes(a.atomname)) {\n dative = true\n } else if(['O2', 'O4', 'O6'].includes(a.atomname)) {\n dative = true\n ionic = true\n }\n }\n if (dative) {\n const state = createFeatureState(FeatureType.DativeBondPartner)\n addAtom(state, a)\n addFeature(features, state)\n }\n if (ionic) {\n const state = createFeatureState(FeatureType.IonicTypePartner)\n addAtom(state, a)\n addFeature(features, state)\n }\n })\n}\n\n/**\n * Metal Pi complexation partner\n */\n// export function addMetalPiPartners (structure: Structure, features: Features) {\n// const { charge } = valenceModel(structure.data)\n\n// structure.eachAtom(a => {\n// const state = createFeatureState(FeatureType.MetalPiPartner)\n\n// const resname = a.resname\n// const element = a.element\n// const atomname = a.atomname\n// if (!a.isPolymer()) {\n// // water oxygen, as well as oxygen from carboxylate, phosphoryl, phenolate, alcohol;\n// // nitrogen from imidazole; sulfur from thiolate\n// if (element === 'O') {\n// // Water oxygen\n// if (a.bondCount === 0 || a.isWater()) {\n// addAtom(state, a)\n// addFeature(features, state)\n// return\n// }\n// // Oxygen in alcohol (R-[O]-H)\n// if (a.bondCount === 2 && charge[ a.index ] || a.hasBondToElement('H')) {\n// addAtom(state, a)\n// addFeature(features, state)\n// return\n// }\n// // Phenolate oxygen\n// if (hasAromaticNeighbour(a) && !a.aromatic) {\n// addAtom(state, a)\n// addFeature(features, state)\n// return\n// }\n// // Carboxylic acid oxygen\n// if (a.bondToElementCount('C') === 1) {\n// let flag = false\n// a.eachBondedAtom(ba => {\n// if (ba.element === 'C' && ba.bondToElementCount('O') === 2 && ba.bondToElementCount('C') === 1) {\n// flag = true\n// }\n// })\n// if (flag) {\n// addAtom(state, a)\n// addFeature(features, state)\n// return\n// }\n// }\n// // Phosphoryl oxygen\n// if (a.bondToElementCount('P') === 1) {\n// let flag = false\n// a.eachBondedAtom(ba => {\n// if (ba.element === 'P' && ba.bondToElementCount('O') >= 3) {\n// flag = true\n// }\n// })\n// if (flag) {\n// addAtom(state, a)\n// addFeature(features, state)\n// return\n// }\n// }\n// } else if (element === 'N') {\n// // Imidazole/pyrrole or similar\n// if (a.bondToElementCount('C') === 2) {\n// addAtom(state, a)\n// addFeature(features, state)\n// return\n// }\n// } else if (element === 'S') {\n// // Thiolate\n// if (hasAromaticNeighbour(a) && !a.aromatic) {\n// addAtom(state, a)\n// addFeature(features, state)\n// return\n// }\n// // Sulfur in Iron sulfur cluster\n// const ironCount = a.bondToElementCount('FE')\n// if (ironCount > 0 && ironCount === a.bondCount) {\n// addAtom(state, a)\n// addFeature(features, state)\n// return\n// }\n// }\n// }\n// })\n// }\n\nexport function addMetals (structure: Structure, features: Features) {\n structure.eachAtom(a => {\n if (a.isTransitionMetal() || a.number === Elements.ZN || a.number === Elements.CD) {\n const state = createFeatureState(FeatureType.TransitionMetal)\n addAtom(state, a)\n addFeature(features, state)\n } else if (IonicTypeMetals.includes(a.number)) {\n const state = createFeatureState(FeatureType.IonicTypeMetal)\n addAtom(state, a)\n addFeature(features, state)\n }\n })\n}\n\nfunction isMetalComplex (ti: FeatureType, tj: FeatureType) {\n if (ti === FeatureType.TransitionMetal) {\n return (\n tj === FeatureType.DativeBondPartner ||\n tj === FeatureType.TransitionMetal\n )\n } else if (ti === FeatureType.IonicTypeMetal) {\n return (\n tj === FeatureType.IonicTypePartner\n )\n }\n}\n\nexport interface MetalComplexationParams {\n maxMetalDist?: number\n masterModelIndex?: number\n}\n\n/**\n * Metal complexes of metals and appropriate groups in protein and ligand, including water\n */\nexport function addMetalComplexation (structure: Structure, contacts: Contacts, params: MetalComplexationParams = {}) {\n const maxMetalDist = defaults(params.maxMetalDist, ContactDefaultParams.maxMetalDist)\n const masterIdx = defaults(params.masterModelIndex, ContactDefaultParams.masterModelIndex)\n\n const { features, spatialHash, contactStore, featureSet } = contacts\n const { types, centers, atomSets } = features\n const { x, y, z } = centers\n const n = types.length\n\n const ap1 = structure.getAtomProxy()\n const ap2 = structure.getAtomProxy()\n\n for (let i = 0; i < n; ++i) {\n spatialHash.eachWithin(x[i], y[i], z[i], maxMetalDist, (j, dSq) => {\n if (j <= i) return\n\n ap1.index = atomSets[ i ][ 0 ]\n ap2.index = atomSets[ j ][ 0 ]\n\n if (invalidAtomContact(ap1, ap2, masterIdx)) return\n\n const m1 = ap1.isMetal()\n const m2 = ap2.isMetal()\n if (!m1 && !m2) return\n\n const [ ti, tj ] = m1 ? [ types[ i ],types[ j ] ] : [ types[ j ],types[ i ] ]\n\n if (isMetalComplex(ti, tj)) {\n featureSet.setBits(i, j)\n contactStore.addContact(i, j, ContactType.MetalCoordination)\n }\n })\n }\n}\n","/**\n * @file Halogen Bonds\n * @author Alexander Rose \n * @author Fred Ludlow \n */\n\nimport { defaults } from '../../utils'\nimport Structure from '../../structure/structure'\nimport { Elements } from '../../structure/structure-constants'\nimport { degToRad } from '../../math/math-utils'\nimport {\n Features, FeatureType,\n addAtom, addFeature, createFeatureState,\n} from './features'\nimport { Contacts, ContactType, ContactDefaultParams, invalidAtomContact } from './contact'\nimport { calcAngles } from '../geometry'\n\nconst halBondElements = [17, 35, 53, 85]\n\n/**\n * Halogen bond donors (X-C, with X one of Cl, Br, I or At) not F!\n */\nexport function addHalogenDonors (structure: Structure, features: Features) {\n structure.eachAtom(a => {\n if (halBondElements.includes(a.number) && a.bondToElementCount(Elements.C) === 1) {\n const state = createFeatureState(FeatureType.HalogenDonor)\n addAtom(state, a)\n addFeature(features, state)\n }\n })\n}\n\nconst X = [ Elements.N, Elements.O, Elements.S ]\nconst Y = [ Elements.C, Elements.N, Elements.P, Elements.S ]\n\n/**\n * Halogen bond acceptors (Y-{O|N|S}, with Y=C,P,N,S)\n */\nexport function addHalogenAcceptors (structure: Structure, features: Features) {\n structure.eachAtom(a => {\n if (X.includes(a.number)) {\n let flag = false\n a.eachBondedAtom(ba => {\n if (Y.includes(ba.number)) {\n flag = true\n }\n })\n if (flag) {\n const state = createFeatureState(FeatureType.HalogenAcceptor)\n addAtom(state, a)\n addFeature(features, state)\n }\n }\n })\n}\n\nfunction isHalogenBond (ti: FeatureType, tj: FeatureType) {\n return (\n (ti === FeatureType.HalogenAcceptor && tj === FeatureType.HalogenDonor) ||\n (ti === FeatureType.HalogenDonor && tj === FeatureType.HalogenAcceptor)\n )\n}\n\nexport interface HalogenBondsParams {\n maxHalogenBondDist?: number\n maxHalogenBondAngle?: number\n masterModelIndex?: number\n}\n\n// http://www.pnas.org/content/101/48/16789.full\nconst OptimalHalogenAngle = degToRad(180) // adjusted from 165 to account for spherical statistics\nconst OptimalAcceptorAngle = degToRad(120)\n\n/**\n * All pairs of halogen donor and acceptor atoms\n */\nexport function addHalogenBonds (structure: Structure, contacts: Contacts, params: HalogenBondsParams = {}) {\n const maxHalogenBondDist = defaults(params.maxHalogenBondDist, ContactDefaultParams.maxHalogenBondDist)\n const maxHalogenBondAngle = degToRad(defaults(params.maxHalogenBondAngle, ContactDefaultParams.maxHalogenBondAngle))\n const masterIdx = defaults(params.masterModelIndex, ContactDefaultParams.masterModelIndex)\n\n const { features, spatialHash, contactStore, featureSet } = contacts\n const { types, centers, atomSets } = features\n const { x, y, z } = centers\n const n = types.length\n\n const ap1 = structure.getAtomProxy()\n const ap2 = structure.getAtomProxy()\n\n for (let i = 0; i < n; ++i) {\n spatialHash.eachWithin(x[i], y[i], z[i], maxHalogenBondDist, (j, dSq) => {\n if (j <= i) return\n\n ap1.index = atomSets[ i ][ 0 ]\n ap2.index = atomSets[ j ][ 0 ]\n\n if (invalidAtomContact(ap1, ap2, masterIdx)) return\n if (!isHalogenBond(types[ i ], types[ j ])) return\n\n const [ halogen, acceptor ] = types[ i ] === FeatureType.HalogenDonor ? [ ap1, ap2 ] : [ ap2, ap1 ]\n\n const halogenAngles = calcAngles(halogen, acceptor)\n // Singly bonded halogen only (not bromide ion for example)\n if (halogenAngles.length !== 1) return\n if (OptimalHalogenAngle - halogenAngles[0] > maxHalogenBondAngle) return\n\n const acceptorAngles = calcAngles(acceptor, halogen)\n // Angle must be defined. Excludes water as acceptor. Debatable\n if (acceptorAngles.length === 0) return\n if (acceptorAngles.some(acceptorAngle => {\n return (OptimalAcceptorAngle - acceptorAngle > maxHalogenBondAngle)\n })) return\n\n\n featureSet.setBits(i, j)\n contactStore.addContact(i, j, ContactType.HalogenBond)\n\n })\n }\n}\n","/**\n * @file Refine Contacts\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { Debug, Log } from '../../globals'\nimport { defaults } from '../../utils'\nimport Structure from '../../structure/structure'\nimport AtomProxy from '../../proxy/atom-proxy'\nimport { Elements } from '../../structure/structure-constants'\nimport { FrozenContacts, ContactType, ContactDefaultParams, isMasterContact } from './contact'\nimport { FeatureType } from './features'\n\nexport interface LineOfSightParams {\n lineOfSightDistFactor?: number\n masterModelIndex?: number\n}\n\n// also allows intra-residue contacts\nexport function invalidAtomContact (ap1: AtomProxy, ap2: AtomProxy, masterIdx: number) {\n return !isMasterContact(ap1, ap2, masterIdx) && (\n ap1.modelIndex !== ap2.modelIndex ||\n (ap1.altloc && ap2.altloc && ap1.altloc !== ap2.altloc)\n )\n}\n\nexport function refineLineOfSight (structure: Structure, contacts: FrozenContacts, params: LineOfSightParams = {}) {\n if (Debug) Log.time('refineLineOfSight')\n\n const lineOfSightDistFactor = defaults(params.lineOfSightDistFactor, ContactDefaultParams.lineOfSightDistFactor)\n const masterIdx = defaults(params.masterModelIndex, ContactDefaultParams.masterModelIndex)\n\n const spatialHash = structure.spatialHash!\n const { contactSet, contactStore, features } = contacts\n const { index1, index2 } = contactStore\n const { centers, atomSets } = features\n const { x, y, z } = centers\n\n const ac1 = structure.getAtomProxy()\n const ac2 = structure.getAtomProxy()\n const aw = structure.getAtomProxy()\n\n const c1 = new Vector3()\n const c2 = new Vector3()\n\n const lineOfSightDist = 3 * lineOfSightDistFactor\n const lineOfSightDistFactorSq = lineOfSightDistFactor * lineOfSightDistFactor\n\n contactSet.forEach(i => {\n c1.set(x[index1[i]], y[index1[i]], z[index1[i]])\n c2.set(x[index2[i]], y[index2[i]], z[index2[i]])\n\n const cx = ( c1.x + c2.x ) / 2\n const cy = ( c1.y + c2.y ) / 2\n const cz = ( c1.z + c2.z ) / 2\n\n const as1 = atomSets[ index1[ i ] ]\n const as2 = atomSets[ index2[ i ] ]\n\n ac1.index = as1[ 0 ]\n ac2.index = as2[ 0 ]\n\n spatialHash.eachWithin(cx, cy, cz, lineOfSightDist, (j, dSq) => {\n aw.index = j\n if (\n aw.number !== Elements.H &&\n (aw.vdw * aw.vdw * lineOfSightDistFactorSq) > dSq &&\n !invalidAtomContact(ac1, aw, masterIdx) &&\n !invalidAtomContact(ac2, aw, masterIdx) &&\n !as1.includes(j) &&\n !as2.includes(j) &&\n // to ignore atoms in the center of functional groups\n c1.distanceToSquared(aw as any) > 1 &&\n c2.distanceToSquared(aw as any) > 1\n ) {\n contactSet.clear(i)\n if (Debug) Log.log('removing', ac1.qualifiedName(), ac2.qualifiedName(), 'because', aw.qualifiedName())\n }\n })\n })\n\n if (Debug) Log.timeEnd('refineLineOfSight')\n}\n\n/**\n * For atoms interacting with several atoms in the same residue\n * only the one with the closest distance is kept.\n */\nexport function refineHydrophobicContacts (structure: Structure, contacts: FrozenContacts) {\n const { contactSet, contactStore, features } = contacts\n const { type, index1, index2 } = contactStore\n const { atomSets } = features\n\n const ap1 = structure.getAtomProxy()\n const ap2 = structure.getAtomProxy()\n\n const residueContactDict: { [k: string]: number[] } = {}\n\n /* keep only closest contact between residues */\n const handleResidueContact = function (dist: number, i: number, key: string) {\n const [ minDist, minIndex ] = residueContactDict[ key ] || [ Infinity, -1 ]\n if (dist < minDist) {\n if (minIndex !== -1) contactSet.clear(minIndex)\n residueContactDict[ key ] = [ dist, i ]\n } else {\n contactSet.clear(i)\n }\n }\n\n contactSet.forEach(i => {\n if (type[ i ] !== ContactType.Hydrophobic) return\n\n ap1.index = atomSets[ index1[ i ] ][ 0 ]\n ap2.index = atomSets[ index2[ i ] ][ 0 ]\n\n const dist = ap1.distanceTo(ap2)\n handleResidueContact(dist, i, `${ap1.index}|${ap2.residueIndex}`)\n handleResidueContact(dist, i, `${ap2.index}|${ap1.residueIndex}`)\n })\n}\n\nfunction isHydrogenBondType (type: number) {\n return (\n type === ContactType.HydrogenBond ||\n type === ContactType.WaterHydrogenBond ||\n type === ContactType.BackboneHydrogenBond\n )\n}\n\n/**\n * Remove weak hydrogen bonds when the acceptor is involved in\n * a normal/strong hydrogen bond\n */\nexport function refineWeakHydrogenBonds (structure: Structure, contacts: FrozenContacts) {\n const { contactSet, contactStore, features, adjacencyList } = contacts\n const { type, index1, index2 } = contactStore\n const { types } = features\n\n contactSet.forEach(i => {\n if (type[ i ] !== ContactType.WeakHydrogenBond) return\n\n let accFeat: number\n if (types[ index1[ i ] ] === FeatureType.WeakHydrogenDonor) {\n accFeat = index2[ i ]\n } else {\n accFeat = index1[ i ]\n }\n\n const n = adjacencyList.countArray[ accFeat ]\n const offset = adjacencyList.offsetArray[ accFeat ]\n for (let j = 0; j < n; ++j) {\n const ci = adjacencyList.indexArray[ offset + j ]\n if (isHydrogenBondType(type[ ci ])) {\n contactSet.clear(i)\n return\n }\n }\n })\n}\n\n/**\n * Remove hydrogen bonds between groups that also form\n * a salt bridge between each other\n */\nexport function refineSaltBridges (structure: Structure, contacts: FrozenContacts) {\n const { contactSet, contactStore, features } = contacts\n const { type, index1, index2 } = contactStore\n const { atomSets } = features\n\n const ionicInteractionDict: { [atomIndex: number]: number[] } = {}\n\n const add = function(idx: number, i: number) {\n if (!ionicInteractionDict[ idx ]) ionicInteractionDict[ idx ] = []\n ionicInteractionDict[ idx ].push(i)\n }\n\n contactSet.forEach(i => {\n if (type[ i ] !== ContactType.IonicInteraction) return\n atomSets[ index1[ i ] ].forEach(idx => add(idx, i))\n atomSets[ index2[ i ] ].forEach(idx => add(idx, i))\n })\n\n contactSet.forEach(i => {\n if (!isHydrogenBondType(type[ i ])) return\n\n const iil1 = ionicInteractionDict[ atomSets[ index1[ i ] ][ 0 ] ]\n const iil2 = ionicInteractionDict[ atomSets[ index2[ i ] ][ 0 ] ]\n if (!iil1 || !iil2) return\n\n const n = iil1.length\n for (let j = 0; j < n; ++j) {\n if (iil2.includes(iil1[j])) {\n contactSet.clear(i)\n return\n }\n }\n })\n}\n\n/**\n * Remove hydrophobic and cation-pi interactions between groups that also form\n * a pi-stacking interaction between each other\n */\nexport function refinePiStacking (structure: Structure, contacts: FrozenContacts) {\n const { contactSet, contactStore, features } = contacts\n const { type, index1, index2 } = contactStore\n const { atomSets } = features\n\n const piStackingDict: { [atomIndex: number]: number[] } = {}\n\n const add = function(idx: number, i: number) {\n if (!piStackingDict[ idx ]) piStackingDict[ idx ] = []\n piStackingDict[ idx ].push(i)\n }\n\n contactSet.forEach(i => {\n if (type[ i ] !== ContactType.PiStacking) return\n atomSets[ index1[ i ] ].forEach(idx => add(idx, i))\n atomSets[ index2[ i ] ].forEach(idx => add(idx, i))\n })\n\n contactSet.forEach(i => {\n if (\n type[ i ] !== ContactType.Hydrophobic &&\n type[ i ] !== ContactType.CationPi\n ) return\n\n const pil1 = piStackingDict[ atomSets[ index1[ i ] ][ 0 ] ]\n const pil2 = piStackingDict[ atomSets[ index2[ i ] ][ 0 ] ]\n if (!pil1 || !pil2) return\n\n const n = pil1.length\n for (let j = 0; j < n; ++j) {\n if (pil2.includes(pil1[j])) {\n contactSet.clear(i)\n return\n }\n }\n })\n}\n\n/**\n * Remove ionic interactions between groups that also form\n * a metal coordination between each other\n */\nexport function refineMetalCoordination (structure: Structure, contacts: FrozenContacts) {\n const { contactSet, contactStore, features } = contacts\n const { type, index1, index2 } = contactStore\n const { atomSets } = features\n\n const ionicInteractionDict: { [atomIndex: number]: number[] } = {}\n\n const add = function(idx: number, i: number) {\n if (!ionicInteractionDict[ idx ]) ionicInteractionDict[ idx ] = []\n ionicInteractionDict[ idx ].push(i)\n }\n\n contactSet.forEach(i => {\n if (type[ i ] !== ContactType.IonicInteraction) return\n atomSets[ index1[ i ] ].forEach(idx => add(idx, i))\n atomSets[ index2[ i ] ].forEach(idx => add(idx, i))\n })\n\n contactSet.forEach(i => {\n if (type[ i ] !== ContactType.MetalCoordination) return\n\n const iil1 = ionicInteractionDict[ atomSets[ index1[ i ] ][ 0 ] ]\n const iil2 = ionicInteractionDict[ atomSets[ index2[ i ] ][ 0 ] ]\n if (!iil1 || !iil2) return\n\n const n = iil1.length\n for (let j = 0; j < n; ++j) {\n if (iil2.includes(iil1[j])) {\n contactSet.clear(iil1[j])\n return\n }\n }\n })\n}\n\n// TODO: refactor refineSaltBridges, refinePiStacking and refineMetalCoordination to be DRY\n","/**\n * @file Contact\n * @author Alexander Rose \n */\n\nimport { Color } from 'three'\n\nimport { Debug, Log } from '../../globals'\nimport { createParams } from '../../utils'\nimport { TextBufferData } from '../../buffer/text-buffer'\nimport Structure from '../../structure/structure'\nimport AtomProxy from '../../proxy/atom-proxy'\nimport SpatialHash from '../../geometry/spatial-hash'\nimport { calculateCenterArray, calculateDirectionArray, uniformArray } from '../../math/array-utils'\nimport ContactStore from '../../store/contact-store'\nimport BitArray from '../../utils/bitarray'\nimport Selection from '../../selection/selection'\nimport { ContactPicker } from '../../utils/picker'\nimport { createAdjacencyList, AdjacencyList } from '../../utils/adjacency-list'\nimport { createFeatures, Features } from './features'\nimport { addAromaticRings, addNegativeCharges, addPositiveCharges, addChargedContacts } from './charged'\nimport { addHydrogenAcceptors, addHydrogenDonors, addHydrogenBonds, addWeakHydrogenDonors } from './hydrogen-bonds'\nimport { addMetalBinding, addMetals, addMetalComplexation } from './metal-binding'\nimport { addHydrophobic, addHydrophobicContacts } from './hydrophobic'\nimport { addHalogenAcceptors, addHalogenDonors, addHalogenBonds } from './halogen-bonds'\nimport {\n refineLineOfSight,\n refineHydrophobicContacts, refineSaltBridges, refinePiStacking, refineMetalCoordination\n} from './refine-contacts'\n\nexport interface Contacts {\n features: Features\n spatialHash: SpatialHash\n contactStore: ContactStore\n featureSet: BitArray\n}\n\nexport interface FrozenContacts extends Contacts {\n contactSet: BitArray\n adjacencyList: AdjacencyList\n}\n\nexport const enum ContactType {\n Unknown = 0,\n IonicInteraction = 1,\n CationPi = 2,\n PiStacking = 3,\n HydrogenBond = 4,\n HalogenBond = 5,\n Hydrophobic = 6,\n MetalCoordination = 7,\n WeakHydrogenBond = 8,\n WaterHydrogenBond = 9,\n BackboneHydrogenBond = 10\n}\n\nexport const ContactDefaultParams = {\n maxHydrophobicDist: 4.0,\n maxHbondDist: 3.5,\n maxHbondSulfurDist: 4.1,\n maxHbondAccAngle: 45,\n maxHbondDonAngle: 45,\n maxHbondAccPlaneAngle: 90,\n maxHbondDonPlaneAngle: 30,\n maxPiStackingDist: 5.5,\n maxPiStackingOffset: 2.0,\n maxPiStackingAngle: 30,\n maxCationPiDist: 6.0,\n maxCationPiOffset: 2.0,\n maxIonicDist: 5.0,\n maxHalogenBondDist: 4.0,\n maxHalogenBondAngle: 30,\n maxMetalDist: 3.0,\n refineSaltBridges: true,\n masterModelIndex: -1,\n lineOfSightDistFactor: 1.0\n}\n\nexport function isMasterContact (ap1: AtomProxy, ap2: AtomProxy, masterIdx: number) {\n return (\n (ap1.modelIndex === masterIdx && ap2.modelIndex !== masterIdx) ||\n (ap2.modelIndex === masterIdx && ap1.modelIndex !== masterIdx)\n )\n}\n\nexport function invalidAtomContact (ap1: AtomProxy, ap2: AtomProxy, masterIdx: number) {\n return !isMasterContact(ap1, ap2, masterIdx) && (\n ap1.modelIndex !== ap2.modelIndex ||\n ap1.residueIndex === ap2.residueIndex ||\n (ap1.altloc && ap2.altloc && ap1.altloc !== ap2.altloc)\n )\n}\n\nexport function createContacts (features: Features): Contacts {\n const { types, centers } = features\n\n const spatialHash = new SpatialHash(centers)\n const contactStore = new ContactStore()\n const featureSet = new BitArray(types.length, false)\n\n return { features, spatialHash, contactStore, featureSet }\n}\n\nexport function createFrozenContacts (contacts: Contacts): FrozenContacts {\n const { index1, index2, count } = contacts.contactStore\n\n const adjacencyList = createAdjacencyList({\n nodeArray1: index1,\n nodeArray2: index2,\n edgeCount: count,\n nodeCount: contacts.featureSet.length\n })\n const contactSet = new BitArray(contacts.contactStore.count, true)\n\n return Object.assign({ adjacencyList, contactSet }, contacts)\n}\n\nfunction calculateFeatures (structure: Structure) {\n const features = createFeatures()\n\n if (Debug) Log.time('calculateFeatures')\n\n addPositiveCharges(structure, features)\n addNegativeCharges(structure, features)\n addAromaticRings(structure, features)\n\n addHydrogenAcceptors(structure, features)\n addHydrogenDonors(structure, features)\n addWeakHydrogenDonors(structure, features)\n\n addMetalBinding(structure, features)\n addMetals(structure, features)\n\n addHydrophobic(structure, features)\n\n addHalogenAcceptors(structure, features)\n addHalogenDonors(structure, features)\n\n if (Debug) Log.timeEnd('calculateFeatures')\n\n return features\n}\n\nexport function calculateContacts (structure: Structure, params = ContactDefaultParams) {\n const features = calculateFeatures(structure)\n const contacts = createContacts(features)\n\n if (Debug) Log.time('calculateContacts')\n\n addChargedContacts(structure, contacts, params)\n addHydrogenBonds(structure, contacts, params)\n addMetalComplexation(structure, contacts, params)\n addHydrophobicContacts(structure, contacts, params)\n addHalogenBonds(structure, contacts, params)\n\n const frozenContacts = createFrozenContacts(contacts)\n\n refineLineOfSight(structure, frozenContacts, params)\n refineHydrophobicContacts(structure, frozenContacts)\n if (params.refineSaltBridges) refineSaltBridges(structure, frozenContacts)\n refinePiStacking(structure, frozenContacts)\n refineMetalCoordination(structure, frozenContacts)\n\n if (Debug) Log.timeEnd('calculateContacts')\n\n return frozenContacts\n}\n\nexport function contactTypeName (type: ContactType) {\n switch (type) {\n case ContactType.HydrogenBond:\n case ContactType.WaterHydrogenBond:\n case ContactType.BackboneHydrogenBond:\n return 'hydrogen bond'\n case ContactType.Hydrophobic:\n return 'hydrophobic contact'\n case ContactType.HalogenBond:\n return 'halogen bond'\n case ContactType.IonicInteraction:\n return 'ionic interaction'\n case ContactType.MetalCoordination:\n return 'metal coordination'\n case ContactType.CationPi:\n return 'cation-pi interaction'\n case ContactType.PiStacking:\n return 'pi-pi stacking'\n case ContactType.WeakHydrogenBond:\n return 'weak hydrogen bond'\n default:\n return 'unknown contact'\n }\n}\n\nexport const ContactDataDefaultParams = {\n hydrogenBond: true,\n hydrophobic: true,\n halogenBond: true,\n ionicInteraction: true,\n metalCoordination: true,\n cationPi: true,\n piStacking: true,\n weakHydrogenBond: true,\n waterHydrogenBond: true,\n backboneHydrogenBond: true,\n radius: 1,\n filterSele: ''\n}\nexport type ContactDataParams = typeof ContactDataDefaultParams\n | { filterSele: string|[string, string] }\n\nexport const ContactLabelDefaultParams = {\n unit: '',\n size: 2.0\n}\n\nexport type ContactLabelParams = typeof ContactLabelDefaultParams\n\nconst tmpColor = new Color()\nfunction contactColor (type: ContactType) {\n switch (type) {\n case ContactType.HydrogenBond:\n case ContactType.WaterHydrogenBond:\n case ContactType.BackboneHydrogenBond:\n return tmpColor.setHex(0x2B83BA).toArray()\n case ContactType.Hydrophobic:\n return tmpColor.setHex(0x808080).toArray()\n case ContactType.HalogenBond:\n return tmpColor.setHex(0x40FFBF).toArray()\n case ContactType.IonicInteraction:\n return tmpColor.setHex(0xF0C814).toArray()\n case ContactType.MetalCoordination:\n return tmpColor.setHex(0x8C4099).toArray()\n case ContactType.CationPi:\n return tmpColor.setHex(0xFF8000).toArray()\n case ContactType.PiStacking:\n return tmpColor.setHex(0x8CB366).toArray()\n case ContactType.WeakHydrogenBond:\n return tmpColor.setHex(0xC5DDEC).toArray()\n default:\n return tmpColor.setHex(0xCCCCCC).toArray()\n }\n}\n\nexport interface ContactData {\n position1: Float32Array,\n position2: Float32Array,\n color: Float32Array,\n color2: Float32Array,\n radius: Float32Array,\n picking: ContactPicker\n}\n\nexport function getContactData (contacts: FrozenContacts, structure: Structure, params: ContactDataParams): ContactData {\n const p = createParams(params, ContactDataDefaultParams)\n const types: ContactType[] = []\n if (p.hydrogenBond) types.push(ContactType.HydrogenBond)\n if (p.hydrophobic) types.push(ContactType.Hydrophobic)\n if (p.halogenBond) types.push(ContactType.HalogenBond)\n if (p.ionicInteraction) types.push(ContactType.IonicInteraction)\n if (p.metalCoordination) types.push(ContactType.MetalCoordination)\n if (p.cationPi) types.push(ContactType.CationPi)\n if (p.piStacking) types.push(ContactType.PiStacking)\n if (p.weakHydrogenBond) types.push(ContactType.WeakHydrogenBond)\n if (p.waterHydrogenBond) types.push(ContactType.WaterHydrogenBond)\n if (p.backboneHydrogenBond) types.push(ContactType.BackboneHydrogenBond)\n\n const { features, contactSet, contactStore } = contacts\n const { centers, atomSets } = features\n const { x, y, z } = centers\n const { index1, index2, type } = contactStore\n\n const position1: number[] = []\n const position2: number[] = []\n const color: number[] = []\n const radius: number[] = []\n const picking: number[] = []\n\n let filterSet: BitArray | BitArray[] | undefined\n if (p.filterSele) {\n if (Array.isArray(p.filterSele)) {\n filterSet = p.filterSele.map(sele => {\n return structure.getAtomSet(new Selection(sele))\n })\n } else {\n filterSet = structure.getAtomSet(new Selection(p.filterSele))\n }\n }\n\n contactSet.forEach(i => {\n const ti = type[ i ]\n if (!types.includes(ti)) return\n\n if (filterSet) {\n const idx1 = atomSets[index1[i]][0]\n const idx2 = atomSets[index2[i]][0]\n\n if (Array.isArray(filterSet)) {\n if (!(filterSet[0].isSet(idx1) && filterSet[1].isSet(idx2) || (filterSet[1].isSet(idx1) && filterSet[0].isSet(idx2)))) return\n } else {\n if (!filterSet.isSet(idx1) && !filterSet.isSet(idx2)) return\n }\n }\n\n const k = index1[i]\n const l = index2[i]\n position1.push(x[k], y[k], z[k])\n position2.push(x[l], y[l], z[l])\n color.push(...contactColor(ti))\n radius.push(p.radius)\n picking.push(i)\n })\n\n return {\n position1: new Float32Array(position1),\n position2: new Float32Array(position2),\n color: new Float32Array(color),\n color2: new Float32Array(color),\n radius: new Float32Array(radius),\n picking: new ContactPicker(picking, contacts, structure)\n }\n}\n\nexport function getLabelData (contactData: ContactData, params: ContactLabelParams): TextBufferData {\n\n const position = calculateCenterArray(contactData.position1, contactData.position2)\n const text: string[] = []\n\n const direction = calculateDirectionArray(contactData.position1, contactData.position2)\n\n const n = direction.length / 3\n for (let i=0; i\n */\n\nimport { defaults } from '../../utils'\nimport Structure from '../../structure/structure'\nimport { Elements } from '../../structure/structure-constants'\nimport {\n Features, FeatureType,\n addAtom, addFeature, createFeatureState,\n} from './features'\nimport { Contacts, ContactType, ContactDefaultParams, invalidAtomContact } from './contact'\n\n/**\n * Hydrophobic carbon (only bonded to carbon or hydrogen); fluorine\n */\nexport function addHydrophobic (structure: Structure, features: Features) {\n structure.eachAtom(a => {\n const state = createFeatureState(FeatureType.Hydrophobic)\n let flag = false\n if (a.number === Elements.C) {\n flag = true\n a.eachBondedAtom(ap => {\n const an = ap.number\n if (an !== Elements.C && an !== Elements.H) flag = false\n })\n } else if (a.number === Elements.F) {\n flag = true\n }\n if (flag) {\n addAtom(state, a)\n addFeature(features, state)\n }\n })\n}\n\nfunction isHydrophobicContact (ti: FeatureType, tj: FeatureType) {\n return ti === FeatureType.Hydrophobic && tj === FeatureType.Hydrophobic\n}\n\nexport interface HydrophobicContactsParams {\n maxHydrophobicDist?: number\n masterModelIndex?: number\n}\n\n/**\n * All hydrophobic contacts\n */\nexport function addHydrophobicContacts (structure: Structure, contacts: Contacts, params: HydrophobicContactsParams = {}) {\n const maxHydrophobicDist = defaults(params.maxHydrophobicDist, ContactDefaultParams.maxHydrophobicDist)\n const masterIdx = defaults(params.masterModelIndex, ContactDefaultParams.masterModelIndex)\n\n const { features, spatialHash, contactStore, featureSet } = contacts\n const { types, centers, atomSets } = features\n const { x, y, z } = centers\n const n = types.length\n\n const ap1 = structure.getAtomProxy()\n const ap2 = structure.getAtomProxy()\n\n for (let i = 0; i < n; ++i) {\n spatialHash.eachWithin(x[i], y[i], z[i], maxHydrophobicDist, (j, dSq) => {\n if (j <= i) return\n\n ap1.index = atomSets[ i ][ 0 ]\n ap2.index = atomSets[ j ][ 0 ]\n\n if (invalidAtomContact(ap1, ap2, masterIdx)) return\n if (ap1.number === Elements.F && ap2.number === Elements.F) return\n if (ap1.connectedTo(ap2)) return\n\n if (isHydrophobicContact(types[ i ], types[ j ])) {\n featureSet.setBits(i, j)\n contactStore.addContact(i, j, ContactType.Hydrophobic)\n }\n })\n }\n}\n","/**\n * @file Picker\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { PickerRegistry } from '../globals'\nimport { calculateMeanVector3 } from '../math/vector-utils'\nimport Selection from '../selection/selection'\nimport {\n ArrowPrimitive, BoxPrimitive, ConePrimitive, CylinderPrimitive,\n EllipsoidPrimitive, OctahedronPrimitive, SpherePrimitive,\n TetrahedronPrimitive, TorusPrimitive, PointPrimitive, WidelinePrimitive\n} from '../geometry/primitive'\nimport { contactTypeName, Contacts } from '../chemistry/interactions/contact'\nimport { TypedArray } from '../types';\nimport Component from '../component/component';\nimport { Shape, Structure, Volume } from '../ngl';\nimport BondStore from '../store/bond-store';\nimport Validation from '../structure/validation';\nimport PrincipalAxes from '../math/principal-axes';\nimport Surface from '../surface/surface';\nimport Unitcell from '../symmetry/unitcell';\nimport BondProxy from '../proxy/bond-proxy';\nimport AtomProxy from '../proxy/atom-proxy';\n\n/**\n * Picker class\n * @interface\n */\nclass Picker {\n array: number[]|TypedArray|undefined\n /**\n * @param {Array|TypedArray} [array] - mapping\n */\n constructor (array?: number[]|TypedArray) {\n this.array = array\n }\n\n get type () { return '' }\n get data () { return {} }\n\n /**\n * Get the index for the given picking id\n * @param {Integer} pid - the picking id\n * @return {Integer} the index\n */\n getIndex (pid: number) {\n return this.array ? this.array[ pid ] : pid\n }\n\n /**\n * Get object data\n * @abstract\n * @param {Integer} pid - the picking id\n * @return {Object} the object data\n */\n getObject (pid: number) {\n return {}\n }\n\n _applyTransformations (vector: Vector3, instance: any, component: Component) {\n if (instance) {\n vector.applyMatrix4(instance.matrix)\n }\n if (component) {\n vector.applyMatrix4(component.matrix)\n }\n return vector\n }\n\n /**\n * Get object position\n * @abstract\n * @param {Integer} pid - the picking id\n * @return {Vector3} the object position\n */\n _getPosition (pid: number) {\n return new Vector3()\n }\n\n /**\n * Get position for the given picking id\n * @param {Integer} pid - the picking id\n * @param {Object} instance - the instance that should be applied\n * @param {Component} component - the component of the picked object\n * @return {Vector3} the position\n */\n getPosition (pid: number, instance: any, component: Component) {\n return this._applyTransformations(\n this._getPosition(pid), instance, component\n )\n }\n}\n\n/**\n * Shape picker class\n * @interface\n */\nclass ShapePicker extends Picker {\n shape: Shape\n /**\n * @param {Shape} shape - shape object\n */\n constructor (shape: Shape) {\n super()\n this.shape = shape\n }\n\n get primitive (): any { return }\n\n get data () { return this.shape }\n get type () { return this.primitive.type }\n\n getObject (pid: number) {\n return this.primitive.objectFromShape(this.shape, this.getIndex(pid))\n }\n\n _getPosition (pid: number) {\n return this.primitive.positionFromShape(this.shape, this.getIndex(pid))\n }\n}\n\n//\n\nclass CylinderPicker extends ShapePicker {\n get primitive () { return CylinderPrimitive }\n}\n\nclass ArrowPicker extends ShapePicker {\n get primitive () { return ArrowPrimitive }\n}\n\nclass AtomPicker extends Picker {\n structure: Structure\n constructor (array: Float32Array, structure: Structure) {\n super(array)\n this.structure = structure\n }\n\n get type () { return 'atom' }\n get data () { return this.structure }\n\n getObject (pid: number): AtomProxy {\n return this.structure.getAtomProxy(this.getIndex(pid))\n }\n\n _getPosition (pid: number) {\n return new Vector3().copy(this.getObject(pid) as any)\n }\n}\n\nclass AxesPicker extends Picker {\n axes: PrincipalAxes\n constructor (axes: PrincipalAxes) {\n super()\n this.axes = axes\n }\n\n get type () { return 'axes' }\n get data () { return this.axes }\n\n getObject (/* pid */) {\n return {\n axes: this.axes\n }\n }\n\n _getPosition (/* pid */) {\n return this.axes.center.clone()\n }\n}\n\nclass BondPicker extends Picker {\n structure: Structure\n bondStore: BondStore\n constructor (array: number[]|TypedArray|undefined, structure: Structure, bondStore?: BondStore) {\n super(array)\n this.structure = structure\n this.bondStore = bondStore || structure.bondStore\n }\n\n get type () { return 'bond' }\n get data () { return this.structure }\n\n getObject (pid: number): BondProxy {\n const bp = this.structure.getBondProxy(this.getIndex(pid))\n bp.bondStore = this.bondStore\n return bp\n }\n\n _getPosition (pid: number) {\n const b = this.getObject(pid)\n return new Vector3()\n .copy(b.atom1 as any)\n .add(b.atom2 as any)\n .multiplyScalar(0.5)\n }\n}\n\nclass ContactPicker extends Picker {\n contacts: Contacts\n structure: Structure\n constructor (array: number[]|TypedArray|undefined, contacts: Contacts, structure: Structure) {\n super(array)\n this.contacts = contacts\n this.structure = structure\n }\n\n get type () { return 'contact' }\n get data () { return this.contacts }\n\n getObject (pid: number) {\n const idx = this.getIndex(pid)\n const { features, contactStore } = this.contacts\n const { centers, atomSets } = features\n const { x, y, z } = centers\n const { index1, index2, type } = contactStore\n const k = index1[idx]\n const l = index2[idx]\n return {\n center1: new Vector3(x[k], y[k], z[k]),\n center2: new Vector3(x[l], y[l], z[l]),\n atom1: this.structure.getAtomProxy(atomSets[k][0]),\n atom2: this.structure.getAtomProxy(atomSets[l][0]),\n type: contactTypeName(type[idx])\n }\n }\n\n _getPosition (pid: number) {\n const { center1, center2 } = this.getObject(pid)\n return new Vector3().addVectors(center1, center2).multiplyScalar(0.5)\n }\n}\n\nclass ConePicker extends ShapePicker {\n get primitive () { return ConePrimitive }\n}\n\nclass ClashPicker extends Picker {\n validation: Validation\n structure: Structure\n constructor (array: number[]|TypedArray|undefined, validation: Validation, structure: Structure) {\n super(array)\n this.validation = validation\n this.structure = structure\n }\n\n get type () { return 'clash' }\n get data () { return this.validation }\n\n getObject (pid: number) {\n const val = this.validation\n const idx = this.getIndex(pid)\n return {\n validation: val,\n index: idx,\n clash: val.clashArray[ idx ]\n }\n }\n\n _getAtomProxyFromSele (sele: string) {\n const selection = new Selection(sele)\n const idx = this.structure.getAtomIndices(selection)![ 0 ]\n return this.structure.getAtomProxy(idx)\n }\n\n _getPosition (pid: number) {\n const clash = this.getObject(pid).clash\n const ap1 = this._getAtomProxyFromSele(clash.sele1)\n const ap2 = this._getAtomProxyFromSele(clash.sele2)\n return new Vector3().copy(ap1 as any).add(ap2 as any).multiplyScalar(0.5)\n }\n}\n\nclass DistancePicker extends BondPicker {\n get type () { return 'distance' }\n}\n\nclass EllipsoidPicker extends ShapePicker {\n get primitive () { return EllipsoidPrimitive }\n}\n\nclass OctahedronPicker extends ShapePicker {\n get primitive () { return OctahedronPrimitive }\n}\n\nclass BoxPicker extends ShapePicker {\n get primitive () { return BoxPrimitive }\n}\n\nclass IgnorePicker extends Picker {\n get type () { return 'ignore' }\n}\n\nexport interface MeshData {\n name: string|undefined\n serial: number\n index: Uint32Array|Uint16Array|number[]\n normal?: Float32Array|number[]\n position: Float32Array|number[]\n color: Float32Array|number[]\n}\nclass MeshPicker extends ShapePicker {\n mesh: MeshData\n __position: Vector3\n\n constructor (shape: Shape, mesh: MeshData) {\n super(shape)\n this.mesh = mesh\n }\n\n get type () { return 'mesh' }\n\n getObject (/* pid */) {\n const m = this.mesh\n return {\n shape: this.shape,\n name: m.name,\n serial: m.serial\n }\n }\n\n _getPosition (/* pid */) {\n if (!this.__position) {\n this.__position = calculateMeanVector3(this.mesh.position as any)\n }\n return this.__position\n }\n}\n\nclass SpherePicker extends ShapePicker {\n get primitive () { return SpherePrimitive }\n}\n\nclass SurfacePicker extends Picker {\n surface: Surface\n constructor (array: number[]|TypedArray|undefined, surface: Surface) {\n super(array)\n this.surface = surface\n }\n\n get type () { return 'surface' }\n get data () { return this.surface }\n\n getObject (pid: number) {\n return {\n surface: this.surface,\n index: this.getIndex(pid)\n }\n }\n\n _getPosition (/* pid */) {\n return this.surface.center.clone()\n }\n}\n\nclass TetrahedronPicker extends ShapePicker {\n get primitive () { return TetrahedronPrimitive }\n}\n\nclass TorusPicker extends ShapePicker {\n get primitive () { return TorusPrimitive }\n}\n\nclass UnitcellPicker extends Picker {\n unitcell: Unitcell\n structure: Structure\n\n constructor (unitcell: Unitcell, structure: Structure) {\n super()\n this.unitcell = unitcell\n this.structure = structure\n }\n\n get type () { return 'unitcell' }\n get data () { return this.unitcell }\n\n getObject (/* pid */) {\n return {\n unitcell: this.unitcell,\n structure: this.structure\n }\n }\n\n _getPosition (/* pid */) {\n return this.unitcell.getCenter(this.structure)\n }\n}\n\nclass UnknownPicker extends Picker {\n get type () { return 'unknown' }\n}\n\nclass VolumePicker extends Picker {\n volume: Volume\n constructor (array: TypedArray, volume: Volume) {\n super(array)\n this.volume = volume\n }\n\n get type () { return 'volume' }\n get data () { return this.volume }\n\n getObject (pid: number) {\n const vol = this.volume\n const idx = this.getIndex(pid)\n return {\n volume: vol,\n index: idx,\n value: vol.data[ idx ]\n }\n }\n\n _getPosition (pid: number) {\n const dp = this.volume.position\n const idx = this.getIndex(pid)\n return new Vector3(\n dp[ idx * 3 ],\n dp[ idx * 3 + 1 ],\n dp[ idx * 3 + 2 ]\n )\n }\n}\n\nclass SlicePicker extends VolumePicker {\n get type () { return 'slice' }\n}\n\nclass PointPicker extends ShapePicker {\n get primitive () { return PointPrimitive }\n}\n\nclass WidelinePicker extends ShapePicker {\n get primitive () { return WidelinePrimitive }\n}\n\nPickerRegistry.add('arrow', ArrowPicker)\nPickerRegistry.add('box', BoxPicker)\nPickerRegistry.add('cone', ConePicker)\nPickerRegistry.add('cylinder', CylinderPicker)\nPickerRegistry.add('ellipsoid', EllipsoidPicker)\nPickerRegistry.add('octahedron', OctahedronPicker)\nPickerRegistry.add('sphere', SpherePicker)\nPickerRegistry.add('tetrahedron', TetrahedronPicker)\nPickerRegistry.add('torus', TorusPicker)\nPickerRegistry.add('point', PointPicker)\nPickerRegistry.add('wideline', WidelinePicker)\n\nexport {\n Picker,\n ShapePicker,\n ArrowPicker,\n AtomPicker,\n AxesPicker,\n BondPicker,\n BoxPicker,\n ConePicker,\n ContactPicker,\n CylinderPicker,\n ClashPicker,\n DistancePicker,\n EllipsoidPicker,\n IgnorePicker,\n OctahedronPicker,\n MeshPicker,\n SlicePicker,\n SpherePicker,\n SurfacePicker,\n TetrahedronPicker,\n TorusPicker,\n UnitcellPicker,\n UnknownPicker,\n VolumePicker,\n PointPicker,\n WidelinePicker\n}\n","/**\n * @file Marching Cubes\n * @author Alexander Rose \n * @private\n */\n\nimport { getUintArray } from '../utils'\n\nfunction getEdgeTable () {\n return new Uint32Array([\n 0x0, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,\n 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,\n 0x190, 0x99, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,\n 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,\n 0x230, 0x339, 0x33, 0x13a, 0x636, 0x73f, 0x435, 0x53c,\n 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,\n 0x3a0, 0x2a9, 0x1a3, 0xaa, 0x7a6, 0x6af, 0x5a5, 0x4ac,\n 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,\n 0x460, 0x569, 0x663, 0x76a, 0x66, 0x16f, 0x265, 0x36c,\n 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,\n 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff, 0x3f5, 0x2fc,\n 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,\n 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55, 0x15c,\n 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,\n 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc,\n 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,\n 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,\n 0xcc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,\n 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,\n 0x15c, 0x55, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,\n 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,\n 0x2fc, 0x3f5, 0xff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,\n 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,\n 0x36c, 0x265, 0x16f, 0x66, 0x76a, 0x663, 0x569, 0x460,\n 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,\n 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa, 0x1a3, 0x2a9, 0x3a0,\n 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,\n 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33, 0x339, 0x230,\n 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,\n 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99, 0x190,\n 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,\n 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0\n ])\n}\n\nfunction getTriTable (): Int32Array {\n return new Int32Array([\n -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1,\n 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1,\n 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1,\n 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1,\n 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1,\n 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1,\n 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1,\n 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1,\n 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1,\n 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1,\n 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1,\n 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1,\n 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1,\n 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1,\n 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1,\n 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1,\n 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1,\n 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1,\n 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1,\n 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1,\n 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1,\n 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1,\n 10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1,\n 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1,\n 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1,\n 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1,\n 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1,\n 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1,\n 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1,\n 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1,\n 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1,\n 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1,\n 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1,\n 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1,\n 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1,\n 11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1,\n 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1,\n 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1,\n 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1,\n 11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1,\n 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1,\n 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1,\n 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1,\n 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1,\n 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1,\n 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1,\n 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1,\n 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1,\n 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1,\n 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1,\n 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1,\n 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1,\n 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1,\n 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1,\n 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1,\n 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1,\n 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1,\n 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1,\n 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1,\n 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1,\n 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1,\n 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1,\n 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1,\n 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1,\n 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1,\n 10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1,\n 10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1,\n 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1,\n 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1,\n 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1,\n 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1,\n 10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1,\n 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1,\n 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1,\n 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1,\n 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1,\n 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1,\n 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1,\n 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1,\n 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1,\n 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1,\n 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1,\n 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1,\n 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1,\n 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1,\n 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1,\n 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1,\n 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1,\n 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1,\n 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1,\n 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1,\n 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1,\n 10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1,\n 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1,\n 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1,\n 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1,\n 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1,\n 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1,\n 10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1,\n 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1,\n 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1,\n 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1,\n 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1,\n 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1,\n 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1,\n 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1,\n 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1,\n 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1,\n 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1,\n 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1,\n 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1,\n 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1,\n 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1,\n 10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1,\n 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1,\n 10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1,\n 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1,\n 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1,\n 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1,\n 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1,\n 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1,\n 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1,\n 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1,\n 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1,\n 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1,\n 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1,\n 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1,\n 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1,\n 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1,\n 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1,\n 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1,\n 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1,\n 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1,\n 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1,\n 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1,\n 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1,\n 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1,\n 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1,\n 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1,\n 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1,\n 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1,\n 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1,\n 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1,\n 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1,\n 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1,\n 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1,\n 11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1,\n 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1,\n 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1,\n 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1,\n 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1,\n 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1,\n 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1,\n 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1,\n 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1,\n 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1,\n 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1,\n 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1,\n 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1,\n 10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1,\n 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1,\n 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1,\n 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1,\n 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1,\n 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1,\n 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1,\n 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1,\n 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1,\n 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1,\n 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1,\n 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1,\n 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1,\n 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1,\n 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1,\n 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1,\n 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1,\n 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1,\n 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1,\n 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1,\n 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1,\n 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1,\n 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1,\n 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1,\n 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1,\n 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1,\n 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1,\n 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1,\n 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1,\n 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1\n ])\n}\n\ninterface MarchingCubes {\n new (field: number[], nx: number, ny: number, nz: number, atomindex: number[]): void\n triangulate: (_isolevel: number, _noNormals: boolean, _box: number[][]|undefined, _contour: boolean, _wrap: boolean) => {\n position: Float32Array\n normal: undefined|Float32Array\n index: Uint32Array|Uint16Array\n atomindex: Int32Array|undefined\n contour: boolean\n }\n}\nfunction MarchingCubes (this: MarchingCubes, field: number[], nx: number, ny: number, nz: number, atomindex: number[]) {\n // Based on alteredq / http://alteredqualia.com/\n // port of greggman's ThreeD version of marching cubes to Three.js\n // http://webglsamples.googlecode.com/hg/blob/blob.html\n //\n // Adapted for NGL by Alexander Rose\n\n // Triangles are constructed between points on cube edges.\n // allowedContours[edge1][edge1] indicates which lines from a given\n // triangle should be shown in line mode.\n\n // Values are bitmasks:\n // In loop over cubes we keep another bitmask indicating whether our current\n // cell is the first x-value (1),\n // first y-value (2) or first z-value (4) of the current loop.\n // We draw all lines on leading faces but only draw trailing face lines the first\n // time through the loop\n // A value of 8 below means the edge is always drawn (leading face)\n\n // E.g. the first row, lines between edge0 and other edges in the bottom\n // x-y plane are only drawn for the first value of z, edges in the\n // x-z plane are only drawn for the first value of y. No other lines\n // are drawn as they're redundant\n // The line between edge 1 and 5 is always drawn as it's on the leading edge\n var allowedContours = [\n\n [ 0, 4, 4, 4, 2, 0, 0, 0, 2, 2, 0, 0 ], // 1 2 3 4 8 9\n [ 4, 0, 4, 4, 0, 8, 0, 0, 0, 8, 8, 0 ], // 0 2 3 5 9 10\n [ 4, 4, 0, 4, 0, 0, 8, 0, 0, 0, 8, 8 ], // 0 1 3 6 10 11\n [ 4, 4, 4, 0, 0, 0, 0, 1, 1, 0, 0, 1 ], // 0 1 2 7 8 11\n [ 2, 0, 0, 0, 0, 8, 8, 8, 2, 2, 0, 0 ], // 0 5 6 7 8 9\n [ 0, 8, 0, 0, 8, 0, 8, 8, 0, 8, 8, 0 ], // And rotate it\n [ 0, 0, 8, 0, 8, 8, 0, 8, 0, 0, 8, 8 ],\n [ 0, 0, 0, 1, 8, 8, 8, 0, 1, 0, 0, 1 ],\n [ 2, 0, 0, 1, 2, 0, 0, 1, 0, 2, 0, 1 ], // 0 3 4 7 9 11\n [ 2, 8, 0, 0, 2, 8, 0, 0, 2, 0, 8, 0 ], // And rotate some more\n [ 0, 8, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8 ],\n [ 0, 0, 8, 1, 0, 0, 8, 1, 1, 0, 8, 0 ]\n\n ]\n\n var isolevel = 0\n var noNormals = false\n var contour = false\n var wrap = false\n var isNegativeIso = false\n var normalFactor = -1\n\n\n var n = nx * ny * nz\n\n // deltas\n var yd = nx\n var zd = nx * ny\n\n var normalCache: Float32Array, vertexIndex: Int32Array\n var count: number, icount: number\n\n var ilist = new Int32Array(12)\n\n var positionArray: number[] = []\n var normalArray: number[] = []\n var indexArray: number[] = []\n var atomindexArray: number[] = []\n\n var edgeTable = getEdgeTable()\n var triTable = getTriTable()\n\n var mx: number, my: number, mz: number\n\n //\n\n this.triangulate = function (_isolevel: number, _noNormals: boolean, _box: number[][]|undefined, _contour: boolean, _wrap: boolean) {\n isolevel = _isolevel\n isNegativeIso = isolevel < 0.0\n contour = _contour\n wrap = _wrap\n // Normals currently disabled in contour mode for performance (unused)\n noNormals = _noNormals || contour\n\n if (!noNormals) {\n normalFactor = isolevel > 0 ? -1.0 : 1.0\n if (!normalCache) {\n normalCache = new Float32Array(n * 3)\n } \n }\n\n var vIndexLength = n * 3\n\n if (!vertexIndex || vertexIndex.length !== vIndexLength) {\n vertexIndex = new Int32Array(vIndexLength)\n }\n\n count = 0\n icount = 0\n\n if (_box !== undefined) {\n var min = _box[ 0 ].map(Math.round)\n var max = _box[ 1 ].map(Math.round)\n\n mx = nx * Math.ceil(Math.abs(min[ 0 ]) / nx)\n my = ny * Math.ceil(Math.abs(min[ 1 ]) / ny)\n mz = nz * Math.ceil(Math.abs(min[ 2 ]) / nz)\n\n triangulate(\n min[ 0 ], min[ 1 ], min[ 2 ],\n max[ 0 ], max[ 1 ], max[ 2 ]\n )\n } else {\n mx = my = mz = 0\n\n triangulate()\n }\n\n positionArray.length = count * 3\n if (!noNormals) normalArray.length = count * 3\n indexArray.length = icount\n if (atomindex) atomindexArray.length = count\n\n return {\n position: new Float32Array(positionArray),\n normal: noNormals ? undefined : new Float32Array(normalArray),\n index: getUintArray(indexArray, positionArray.length / 3),\n atomindex: atomindex ? new Int32Array(atomindexArray) : undefined,\n contour: contour\n }\n }\n\n // polygonization\n\n function lerp (a: number, b: number, t: number) { return a + (b - a) * t }\n\n function index (x: number, y: number, z: number) {\n x = (x + mx) % nx\n y = (y + my) % ny\n z = (z + mz) % nz\n return ((zd * z) + yd * y) + x\n }\n\n function VIntX (q: number, offset: number, x: number, y: number, z: number, valp1: number, valp2: number) {\n var _q = 3 * q\n\n if (vertexIndex[ _q ] < 0) {\n var mu = (isolevel - valp1) / (valp2 - valp1)\n var nc = normalCache\n\n var c = count * 3\n\n positionArray[ c ] = x + mu\n positionArray[ c + 1 ] = y\n positionArray[ c + 2 ] = z\n\n if (!noNormals) {\n var q3 = q * 3\n\n normalArray[ c ] = normalFactor * lerp(nc[ q3 ], nc[ q3 + 3 ], mu)\n normalArray[ c + 1 ] = normalFactor * lerp(nc[ q3 + 1 ], nc[ q3 + 4 ], mu)\n normalArray[ c + 2 ] = normalFactor * lerp(nc[ q3 + 2 ], nc[ q3 + 5 ], mu)\n }\n\n if (atomindex) atomindexArray[ count ] = atomindex[ q + Math.round(mu) ]\n\n vertexIndex[ _q ] = count\n ilist[ offset ] = count\n\n count += 1\n } else {\n ilist[ offset ] = vertexIndex[ _q ]\n }\n }\n\n function VIntY (q: number, offset: number, x: number, y: number, z: number, valp1: number, valp2: number) {\n var _q = 3 * q + 1\n\n if (vertexIndex[ _q ] < 0) {\n var mu = (isolevel - valp1) / (valp2 - valp1)\n var nc = normalCache\n\n var c = count * 3\n\n positionArray[ c ] = x\n positionArray[ c + 1 ] = y + mu\n positionArray[ c + 2 ] = z\n\n if (!noNormals) {\n var q3 = q * 3\n var q6 = q3 + yd * 3\n\n normalArray[ c ] = normalFactor * lerp(nc[ q3 ], nc[ q6 ], mu)\n normalArray[ c + 1 ] = normalFactor * lerp(nc[ q3 + 1 ], nc[ q6 + 1 ], mu)\n normalArray[ c + 2 ] = normalFactor * lerp(nc[ q3 + 2 ], nc[ q6 + 2 ], mu)\n }\n\n if (atomindex) atomindexArray[ count ] = atomindex[ q + Math.round(mu) * yd ]\n\n vertexIndex[ _q ] = count\n ilist[ offset ] = count\n\n count += 1\n } else {\n ilist[ offset ] = vertexIndex[ _q ]\n }\n }\n\n function VIntZ (q: number, offset: number, x: number, y: number, z: number, valp1: number, valp2: number) {\n var _q = 3 * q + 2\n\n if (vertexIndex[ _q ] < 0) {\n var mu = (isolevel - valp1) / (valp2 - valp1)\n var nc = normalCache\n\n var c = count * 3\n\n positionArray[ c ] = x\n positionArray[ c + 1 ] = y\n positionArray[ c + 2 ] = z + mu\n\n if (!noNormals) {\n var q3 = q * 3\n var q6 = q3 + zd * 3\n\n normalArray[ c ] = normalFactor * lerp(nc[ q3 ], nc[ q6 ], mu)\n normalArray[ c + 1 ] = normalFactor * lerp(nc[ q3 + 1 ], nc[ q6 + 1 ], mu)\n normalArray[ c + 2 ] = normalFactor * lerp(nc[ q3 + 2 ], nc[ q6 + 2 ], mu)\n }\n\n if (atomindex) atomindexArray[ count ] = atomindex[ q + Math.round(mu) * zd ]\n\n vertexIndex[ _q ] = count\n ilist[ offset ] = count\n\n count += 1\n } else {\n ilist[ offset ] = vertexIndex[ _q ]\n }\n }\n\n function compNorm (q: number) {\n var q3 = q * 3\n\n if (normalCache[ q3 ] === 0.0) {\n normalCache[ q3 ] = field[ (q - 1 + n) % n ] - field[ (q + 1) % n ]\n normalCache[ q3 + 1 ] = field[ (q - yd + n) % n ] - field[ (q + yd) % n ]\n normalCache[ q3 + 2 ] = field[ (q - zd + n) % n ] - field[ (q + zd) % n ]\n }\n }\n\n function polygonize (fx: number, fy: number, fz: number, q: number, edgeFilter: number) {\n // cache indices\n var q1\n var qy\n var qz\n var q1y\n var q1z\n var qyz\n var q1yz\n if (wrap) {\n q = index(fx, fy, fz)\n q1 = index(fx + 1, fy, fz)\n qy = index(fx, fy + 1, fz)\n qz = index(fx, fy, fz + 1)\n q1y = index(fx + 1, fy + 1, fz)\n q1z = index(fx + 1, fy, fz + 1)\n qyz = index(fx, fy + 1, fz + 1)\n q1yz = index(fx + 1, fy + 1, fz + 1)\n } else {\n q1 = q + 1\n qy = q + yd\n qz = q + zd\n q1y = qy + 1\n q1z = qz + 1\n qyz = qy + zd\n q1yz = qyz + 1\n }\n\n var cubeindex = 0\n var field0 = field[ q ]\n var field1 = field[ q1 ]\n var field2 = field[ qy ]\n var field3 = field[ q1y ]\n var field4 = field[ qz ]\n var field5 = field[ q1z ]\n var field6 = field[ qyz ]\n var field7 = field[ q1yz ]\n\n if (field0 < isolevel) cubeindex |= 1\n if (field1 < isolevel) cubeindex |= 2\n if (field2 < isolevel) cubeindex |= 8\n if (field3 < isolevel) cubeindex |= 4\n if (field4 < isolevel) cubeindex |= 16\n if (field5 < isolevel) cubeindex |= 32\n if (field6 < isolevel) cubeindex |= 128\n if (field7 < isolevel) cubeindex |= 64\n\n // if cube is entirely in/out of the surface - bail, nothing to draw\n\n var bits = edgeTable[ cubeindex ]\n if (bits === 0) return 0\n\n var fx2 = fx + 1\n var fy2 = fy + 1\n var fz2 = fz + 1\n\n // top of the cube\n\n if (bits & 1) {\n if (!noNormals) {\n compNorm(q)\n compNorm(q1)\n }\n VIntX(q, 0, fx, fy, fz, field0, field1)\n }\n\n if (bits & 2) {\n if (!noNormals) {\n compNorm(q1)\n compNorm(q1y)\n }\n VIntY(q1, 1, fx2, fy, fz, field1, field3)\n }\n\n if (bits & 4) {\n if (!noNormals) {\n compNorm(qy)\n compNorm(q1y)\n }\n VIntX(qy, 2, fx, fy2, fz, field2, field3)\n }\n\n if (bits & 8) {\n if (!noNormals) {\n compNorm(q)\n compNorm(qy)\n }\n VIntY(q, 3, fx, fy, fz, field0, field2)\n }\n\n // bottom of the cube\n\n if (bits & 16) {\n if (!noNormals) {\n compNorm(qz)\n compNorm(q1z)\n }\n VIntX(qz, 4, fx, fy, fz2, field4, field5)\n }\n\n if (bits & 32) {\n if (!noNormals) {\n compNorm(q1z)\n compNorm(q1yz)\n }\n VIntY(q1z, 5, fx2, fy, fz2, field5, field7)\n }\n\n if (bits & 64) {\n if (!noNormals) {\n compNorm(qyz)\n compNorm(q1yz)\n }\n VIntX(qyz, 6, fx, fy2, fz2, field6, field7)\n }\n\n if (bits & 128) {\n if (!noNormals) {\n compNorm(qz)\n compNorm(qyz)\n }\n VIntY(qz, 7, fx, fy, fz2, field4, field6)\n }\n\n // vertical lines of the cube\n\n if (bits & 256) {\n if (!noNormals) {\n compNorm(q)\n compNorm(qz)\n }\n VIntZ(q, 8, fx, fy, fz, field0, field4)\n }\n\n if (bits & 512) {\n if (!noNormals) {\n compNorm(q1)\n compNorm(q1z)\n }\n VIntZ(q1, 9, fx2, fy, fz, field1, field5)\n }\n\n if (bits & 1024) {\n if (!noNormals) {\n compNorm(q1y)\n compNorm(q1yz)\n }\n VIntZ(q1y, 10, fx2, fy2, fz, field3, field7)\n }\n\n if (bits & 2048) {\n if (!noNormals) {\n compNorm(qy)\n compNorm(qyz)\n }\n VIntZ(qy, 11, fx, fy2, fz, field2, field6)\n }\n\n var triIndex = cubeindex << 4 // re-purpose cubeindex into an offset into triTable\n\n var e1\n var e2\n var e3\n var i = 0\n\n // here is where triangles are created\n\n while (triTable[ triIndex + i ] !== -1) {\n e1 = triTable[ triIndex + i ]\n e2 = triTable[ triIndex + i + 1 ]\n e3 = triTable[ triIndex + i + 2 ]\n\n if (contour) {\n if (allowedContours[ e1 ][ e2 ] & edgeFilter) {\n indexArray[ icount++ ] = ilist[ e1 ]\n indexArray[ icount++ ] = ilist[ e2 ]\n }\n if (allowedContours[ e2 ][ e3 ] & edgeFilter) {\n indexArray[ icount++ ] = ilist[ e2 ]\n indexArray[ icount++ ] = ilist[ e3 ]\n }\n if (allowedContours[ e1 ][ e3 ] & edgeFilter) {\n indexArray[ icount++ ] = ilist[ e1 ]\n indexArray[ icount++ ] = ilist[ e3 ]\n }\n } else {\n indexArray[ icount++ ] = ilist[ isNegativeIso ? e1 : e2 ]\n indexArray[ icount++ ] = ilist[ isNegativeIso ? e2 : e1 ]\n indexArray[ icount++ ] = ilist[ e3 ]\n }\n\n i += 3\n }\n }\n\n function triangulate (xBeg?: number, yBeg?: number, zBeg?: number, xEnd?: number, yEnd?: number, zEnd?: number) {\n let q\n let q3\n let x\n let y\n let z\n let yOffset\n let zOffset\n\n xBeg = xBeg !== undefined ? xBeg : 0\n yBeg = yBeg !== undefined ? yBeg : 0\n zBeg = zBeg !== undefined ? zBeg : 0\n\n xEnd = xEnd !== undefined ? xEnd : nx - 1\n yEnd = yEnd !== undefined ? yEnd : ny - 1\n zEnd = zEnd !== undefined ? zEnd : nz - 1\n\n if (!wrap) {\n if (noNormals) {\n xBeg = Math.max(0, xBeg)\n yBeg = Math.max(0, yBeg)\n zBeg = Math.max(0, zBeg)\n\n xEnd = Math.min(nx - 1, xEnd)\n yEnd = Math.min(ny - 1, yEnd)\n zEnd = Math.min(nz - 1, zEnd)\n } else {\n xBeg = Math.max(1, xBeg)\n yBeg = Math.max(1, yBeg)\n zBeg = Math.max(1, zBeg)\n\n xEnd = Math.min(nx - 2, xEnd)\n yEnd = Math.min(ny - 2, yEnd)\n zEnd = Math.min(nz - 2, zEnd)\n }\n }\n\n let xBeg2, yBeg2, zBeg2, xEnd2, yEnd2, zEnd2\n\n if (!wrap) {\n // init part of the vertexIndex\n // (takes a significant amount of time to do for all)\n\n xBeg2 = Math.max(0, xBeg - 2)\n yBeg2 = Math.max(0, yBeg - 2)\n zBeg2 = Math.max(0, zBeg - 2)\n\n xEnd2 = Math.min(nx, xEnd + 2)\n yEnd2 = Math.min(ny, yEnd + 2)\n zEnd2 = Math.min(nz, zEnd + 2)\n\n for (z = zBeg2; z < zEnd2; ++z) {\n zOffset = zd * z\n for (y = yBeg2; y < yEnd2; ++y) {\n yOffset = zOffset + yd * y\n for (x = xBeg2; x < xEnd2; ++x) {\n q = 3 * (yOffset + x)\n vertexIndex[ q ] = -1\n vertexIndex[ q + 1 ] = -1\n vertexIndex[ q + 2 ] = -1\n }\n }\n }\n } else {\n xBeg2 = xBeg - 2\n yBeg2 = yBeg - 2\n zBeg2 = zBeg - 2\n\n xEnd2 = xEnd + 2\n yEnd2 = yEnd + 2\n zEnd2 = zEnd + 2\n\n for (z = zBeg2; z < zEnd2; ++z) {\n for (y = yBeg2; y < yEnd2; ++y) {\n for (x = xBeg2; x < xEnd2; ++x) {\n q3 = index(x, y, z) * 3\n vertexIndex[ q3 ] = -1\n vertexIndex[ q3 + 1 ] = -1\n vertexIndex[ q3 + 2 ] = -1\n }\n }\n }\n }\n\n if (!wrap) {\n // clip space where the isovalue is too low\n\n var __break\n var __xBeg = xBeg; var __yBeg = yBeg; var __zBeg = zBeg\n var __xEnd = xEnd; var __yEnd = yEnd; var __zEnd = zEnd\n\n __break = false\n for (z = zBeg; z < zEnd; ++z) {\n for (y = yBeg; y < yEnd; ++y) {\n for (x = xBeg; x < xEnd; ++x) {\n q = ((nx * ny) * z) + (nx * y) + x\n if (field[ q ] >= isolevel) {\n __zBeg = z\n __break = true\n break\n }\n }\n if (__break) break\n }\n if (__break) break\n }\n\n __break = false\n for (y = yBeg; y < yEnd; ++y) {\n for (z = __zBeg; z < zEnd; ++z) {\n for (x = xBeg; x < xEnd; ++x) {\n q = ((nx * ny) * z) + (nx * y) + x\n if (field[ q ] >= isolevel) {\n __yBeg = y\n __break = true\n break\n }\n }\n if (__break) break\n }\n if (__break) break\n }\n\n __break = false\n for (x = xBeg; x < xEnd; ++x) {\n for (y = __yBeg; y < yEnd; ++y) {\n for (z = __zBeg; z < zEnd; ++z) {\n q = ((nx * ny) * z) + (nx * y) + x\n if (field[ q ] >= isolevel) {\n __xBeg = x\n __break = true\n break\n }\n }\n if (__break) break\n }\n if (__break) break\n }\n\n __break = false\n for (z = zEnd; z >= zBeg; --z) {\n for (y = yEnd; y >= yBeg; --y) {\n for (x = xEnd; x >= xBeg; --x) {\n q = ((nx * ny) * z) + (nx * y) + x\n if (field[ q ] >= isolevel) {\n __zEnd = z\n __break = true\n break\n }\n }\n if (__break) break\n }\n if (__break) break\n }\n\n __break = false\n for (y = yEnd; y >= yBeg; --y) {\n for (z = __zEnd; z >= zBeg; --z) {\n for (x = xEnd; x >= xBeg; --x) {\n q = ((nx * ny) * z) + (nx * y) + x\n if (field[ q ] >= isolevel) {\n __yEnd = y\n __break = true\n break\n }\n }\n if (__break) break\n }\n if (__break) break\n }\n\n __break = false\n for (x = xEnd; x >= xBeg; --x) {\n for (y = __yEnd; y >= yBeg; --y) {\n for (z = __zEnd; z >= zBeg; --z) {\n q = ((nx * ny) * z) + (nx * y) + x\n if (field[ q ] >= isolevel) {\n __xEnd = x\n __break = true\n break\n }\n }\n if (__break) break\n }\n if (__break) break\n }\n\n //\n\n if (noNormals) {\n xBeg = Math.max(0, __xBeg - 1)\n yBeg = Math.max(0, __yBeg - 1)\n zBeg = Math.max(0, __zBeg - 1)\n\n xEnd = Math.min(nx - 1, __xEnd + 1)\n yEnd = Math.min(ny - 1, __yEnd + 1)\n zEnd = Math.min(nz - 1, __zEnd + 1)\n } else {\n xBeg = Math.max(1, __xBeg - 1)\n yBeg = Math.max(1, __yBeg - 1)\n zBeg = Math.max(1, __zBeg - 1)\n\n xEnd = Math.min(nx - 2, __xEnd + 1)\n yEnd = Math.min(ny - 2, __yEnd + 1)\n zEnd = Math.min(nz - 2, __zEnd + 1)\n }\n }\n\n // polygonize part of the grid\n var edgeFilter = 15\n for (z = zBeg; z < zEnd; ++z, edgeFilter &= ~4) {\n zOffset = zd * z\n edgeFilter |= 2\n for (y = yBeg; y < yEnd; ++y, edgeFilter &= ~2) {\n yOffset = zOffset + yd * y\n edgeFilter |= 1\n for (x = xBeg; x < xEnd; ++x, edgeFilter &= ~1) {\n q = yOffset + x\n polygonize(x, y, z, q, edgeFilter)\n }\n }\n }\n }\n}\nObject.assign(MarchingCubes, {__deps: [ getEdgeTable, getTriTable, getUintArray ]})\n\nexport default MarchingCubes\n","/**\n * @file Matrix Utils\n * @private\n * @author Alexander Rose \n *\n * svd methods from Eugene Zatepyakin / http://inspirit.github.io/jsfeat/\n */\n\nimport { NumberArray } from '../types'\nimport { v3new, v3cross } from './vector-utils'\n\nexport class Matrix {\n size: number\n data: Float32Array\n\n constructor (readonly cols: number, readonly rows: number) {\n this.size = this.cols * this.rows\n this.data = new Float32Array(this.size)\n }\n\n copyTo (matrix: Matrix) {\n matrix.data.set(this.data)\n }\n}\n\nexport function transpose (At: Matrix, A: Matrix) {\n let i = 0\n let j = 0\n const nrows = A.rows\n const ncols = A.cols\n let Ai = 0\n let Ati = 0\n let pAt = 0\n const ad = A.data\n const atd = At.data\n\n for (; i < nrows; Ati += 1, Ai += ncols, i++) {\n pAt = Ati\n for (j = 0; j < ncols; pAt += nrows, j++) atd[pAt] = ad[Ai + j]\n }\n}\n\n// C = A * B\nexport function multiply (C: Matrix, A: Matrix, B: Matrix) {\n let i = 0\n let j = 0\n let k = 0\n let Ap = 0\n let pA = 0\n let pB = 0\n let _pB = 0\n let Cp = 0\n const ncols = A.cols\n const nrows = A.rows\n const mcols = B.cols\n const ad = A.data\n const bd = B.data\n const cd = C.data\n let sum = 0.0\n\n for (; i < nrows; Ap += ncols, i++) {\n for (_pB = 0, j = 0; j < mcols; Cp++, _pB++, j++) {\n pB = _pB\n pA = Ap\n sum = 0.0\n for (k = 0; k < ncols; pA++, pB += mcols, k++) {\n sum += ad[pA] * bd[pB]\n }\n cd[Cp] = sum\n }\n }\n}\n\n// C = A * B'\nexport function multiplyABt (C: Matrix, A: Matrix, B: Matrix) {\n let i = 0\n let j = 0\n let k = 0\n let Ap = 0\n let pA = 0\n let pB = 0\n let Cp = 0\n const ncols = A.cols\n const nrows = A.rows\n const mrows = B.rows\n const ad = A.data\n const bd = B.data\n const cd = C.data\n let sum = 0.0\n\n for (; i < nrows; Ap += ncols, i++) {\n for (pB = 0, j = 0; j < mrows; Cp++, j++) {\n pA = Ap\n sum = 0.0\n for (k = 0; k < ncols; pA++, pB++, k++) {\n sum += ad[pA] * bd[pB]\n }\n cd[Cp] = sum\n }\n }\n}\n\n// C = A' * B\nexport function multiplyAtB (C: Matrix, A: Matrix, B: Matrix) {\n let i = 0\n let j = 0\n let k = 0\n let Ap = 0\n let pA = 0\n let pB = 0\n let _pB = 0\n let Cp = 0\n const ncols = A.cols\n const nrows = A.rows\n const mcols = B.cols\n const ad = A.data\n const bd = B.data\n const cd = C.data\n let sum = 0.0\n\n for (; i < ncols; Ap++, i++) {\n for (_pB = 0, j = 0; j < mcols; Cp++, _pB++, j++) {\n pB = _pB\n pA = Ap\n sum = 0.0\n for (k = 0; k < nrows; pA += ncols, pB += mcols, k++) {\n sum += ad[pA] * bd[pB]\n }\n cd[Cp] = sum\n }\n }\n}\n\nexport function invert3x3 (from: Matrix, to: Matrix) {\n const A = from.data\n const invA = to.data\n const t1 = A[4]\n const t2 = A[8]\n const t4 = A[5]\n const t5 = A[7]\n const t8 = A[0]\n\n const t9 = t8 * t1\n const t11 = t8 * t4\n const t13 = A[3]\n const t14 = A[1]\n const t15 = t13 * t14\n const t17 = A[2]\n const t18 = t13 * t17\n const t20 = A[6]\n const t21 = t20 * t14\n const t23 = t20 * t17\n const t26 = 1.0 / (t9 * t2 - t11 * t5 - t15 * t2 + t18 * t5 + t21 * t4 - t23 * t1)\n invA[0] = (t1 * t2 - t4 * t5) * t26\n invA[1] = -(t14 * t2 - t17 * t5) * t26\n invA[2] = -(-t14 * t4 + t17 * t1) * t26\n invA[3] = -(t13 * t2 - t4 * t20) * t26\n invA[4] = (t8 * t2 - t23) * t26\n invA[5] = -(t11 - t18) * t26\n invA[6] = -(-t13 * t5 + t1 * t20) * t26\n invA[7] = -(t8 * t5 - t21) * t26\n invA[8] = (t9 - t15) * t26\n}\n\nexport function mat3x3determinant (M: Matrix) {\n const md = M.data\n return md[0] * md[4] * md[8] -\n md[0] * md[5] * md[7] -\n md[3] * md[1] * md[8] +\n md[3] * md[2] * md[7] +\n md[6] * md[1] * md[5] -\n md[6] * md[2] * md[4]\n}\n\n// C = A * B\nexport function multiply3x3 (C: Matrix, A: Matrix, B: Matrix) {\n const Cd = C.data\n const Ad = A.data\n const Bd = B.data\n const m10 = Ad[0]\n const m11 = Ad[1]\n const m12 = Ad[2]\n const m13 = Ad[3]\n const m14 = Ad[4]\n const m15 = Ad[5]\n const m16 = Ad[6]\n const m17 = Ad[7]\n const m18 = Ad[8]\n\n const m20 = Bd[0]\n const m21 = Bd[1]\n const m22 = Bd[2]\n const m23 = Bd[3]\n const m24 = Bd[4]\n const m25 = Bd[5]\n const m26 = Bd[6]\n const m27 = Bd[7]\n const m28 = Bd[8]\n\n Cd[0] = m10 * m20 + m11 * m23 + m12 * m26\n Cd[1] = m10 * m21 + m11 * m24 + m12 * m27\n Cd[2] = m10 * m22 + m11 * m25 + m12 * m28\n Cd[3] = m13 * m20 + m14 * m23 + m15 * m26\n Cd[4] = m13 * m21 + m14 * m24 + m15 * m27\n Cd[5] = m13 * m22 + m14 * m25 + m15 * m28\n Cd[6] = m16 * m20 + m17 * m23 + m18 * m26\n Cd[7] = m16 * m21 + m17 * m24 + m18 * m27\n Cd[8] = m16 * m22 + m17 * m25 + m18 * m28\n}\n\nexport function meanRows (A: Matrix) {\n const nrows = A.rows\n const ncols = A.cols\n const Ad = A.data\n const mean = new Array(ncols)\n\n for (let j = 0; j < ncols; ++j) {\n mean[ j ] = 0.0\n }\n\n for (let i = 0, p = 0; i < nrows; ++i) {\n for (let j = 0; j < ncols; ++j, ++p) {\n mean[ j ] += Ad[ p ]\n }\n }\n\n for (let j = 0; j < ncols; ++j) {\n mean[ j ] /= nrows\n }\n\n return mean\n}\n\nexport function meanCols (A: Matrix) {\n const nrows = A.rows\n const ncols = A.cols\n const Ad = A.data\n const mean = new Array(nrows)\n\n for (let j = 0; j < nrows; ++j) {\n mean[ j ] = 0.0\n }\n\n for (let i = 0, p = 0; i < ncols; ++i) {\n for (let j = 0; j < nrows; ++j, ++p) {\n mean[ j ] += Ad[ p ]\n }\n }\n\n for (let j = 0; j < nrows; ++j) {\n mean[ j ] /= ncols\n }\n\n return mean\n}\n\nexport function subRows (A: Matrix, row: number[]) {\n const nrows = A.rows\n const ncols = A.cols\n const Ad = A.data\n\n for (let i = 0, p = 0; i < nrows; ++i) {\n for (let j = 0; j < ncols; ++j, ++p) {\n Ad[ p ] -= row[ j ]\n }\n }\n}\n\nexport function subCols (A: Matrix, col: number[]) {\n const nrows = A.rows\n const ncols = A.cols\n const Ad = A.data\n\n for (let i = 0, p = 0; i < ncols; ++i) {\n for (let j = 0; j < nrows; ++j, ++p) {\n Ad[ p ] -= col[ j ]\n }\n }\n}\n\nexport function addRows (A: Matrix, row: number[]) {\n const nrows = A.rows\n const ncols = A.cols\n const Ad = A.data\n\n for (let i = 0, p = 0; i < nrows; ++i) {\n for (let j = 0; j < ncols; ++j, ++p) {\n Ad[ p ] += row[ j ]\n }\n }\n}\n\nexport function addCols (A: Matrix, col: number[]) {\n const nrows = A.rows\n const ncols = A.cols\n const Ad = A.data\n\n for (let i = 0, p = 0; i < ncols; ++i) {\n for (let j = 0; j < nrows; ++j, ++p) {\n Ad[ p ] += col[ j ]\n }\n }\n}\n\nexport function swap (A: NumberArray, i0: number, i1: number, t: number) {\n t = A[i0]\n A[i0] = A[i1]\n A[i1] = t\n}\n\nexport function hypot (a: number, b: number) {\n a = Math.abs(a)\n b = Math.abs(b)\n if (a > b) {\n b /= a\n return a * Math.sqrt(1.0 + b * b)\n }\n if (b > 0) {\n a /= b\n return b * Math.sqrt(1.0 + a * a)\n }\n return 0.0\n}\n\nconst EPSILON = 0.0000001192092896\nconst FLT_MIN = 1E-37\n\nexport function JacobiSVDImpl (At: NumberArray, astep: number, _W: NumberArray, Vt: NumberArray, vstep: number, m: number, n: number, n1: number) {\n const eps = EPSILON * 2.0\n const minval = FLT_MIN\n let i = 0\n let j = 0\n let k = 0\n let iter = 0\n const maxIter = Math.max(m, 30)\n let Ai = 0\n let Aj = 0\n let Vi = 0\n let Vj = 0\n let changed = 0\n let c = 0.0\n let s = 0.0\n let t = 0.0\n let t0 = 0.0\n let t1 = 0.0\n let sd = 0.0\n let beta = 0.0\n let gamma = 0.0\n let delta = 0.0\n let a = 0.0\n let p = 0.0\n let b = 0.0\n let seed = 0x1234\n let val = 0.0\n let val0 = 0.0\n let asum = 0.0\n\n const W = new Float64Array(n << 3)\n\n for (; i < n; i++) {\n for (k = 0, sd = 0; k < m; k++) {\n t = At[i * astep + k]\n sd += t * t\n }\n W[i] = sd\n\n if (Vt) {\n for (k = 0; k < n; k++) {\n Vt[i * vstep + k] = 0\n }\n Vt[i * vstep + i] = 1\n }\n }\n\n for (; iter < maxIter; iter++) {\n changed = 0\n\n for (i = 0; i < n - 1; i++) {\n for (j = i + 1; j < n; j++) {\n Ai = (i * astep) | 0\n Aj = (j * astep) | 0\n a = W[i]\n p = 0\n b = W[j]\n\n k = 2\n p += At[Ai] * At[Aj]\n p += At[Ai + 1] * At[Aj + 1]\n\n for (; k < m; k++) { p += At[Ai + k] * At[Aj + k] }\n\n if (Math.abs(p) <= eps * Math.sqrt(a * b)) continue\n\n p *= 2.0\n beta = a - b\n gamma = hypot(p, beta)\n if (beta < 0) {\n delta = (gamma - beta) * 0.5\n s = Math.sqrt(delta / gamma)\n c = (p / (gamma * s * 2.0))\n } else {\n c = Math.sqrt((gamma + beta) / (gamma * 2.0))\n s = (p / (gamma * c * 2.0))\n }\n\n a = 0.0\n b = 0.0\n\n k = 2 // unroll\n t0 = c * At[Ai] + s * At[Aj]\n t1 = -s * At[Ai] + c * At[Aj]\n At[Ai] = t0; At[Aj] = t1\n a += t0 * t0; b += t1 * t1\n\n t0 = c * At[Ai + 1] + s * At[Aj + 1]\n t1 = -s * At[Ai + 1] + c * At[Aj + 1]\n At[Ai + 1] = t0; At[Aj + 1] = t1\n a += t0 * t0; b += t1 * t1\n\n for (; k < m; k++) {\n t0 = c * At[Ai + k] + s * At[Aj + k]\n t1 = -s * At[Ai + k] + c * At[Aj + k]\n At[Ai + k] = t0; At[Aj + k] = t1\n\n a += t0 * t0; b += t1 * t1\n }\n\n W[i] = a\n W[j] = b\n\n changed = 1\n\n if (Vt) {\n Vi = (i * vstep) | 0\n Vj = (j * vstep) | 0\n\n k = 2\n t0 = c * Vt[Vi] + s * Vt[Vj]\n t1 = -s * Vt[Vi] + c * Vt[Vj]\n Vt[Vi] = t0; Vt[Vj] = t1\n\n t0 = c * Vt[Vi + 1] + s * Vt[Vj + 1]\n t1 = -s * Vt[Vi + 1] + c * Vt[Vj + 1]\n Vt[Vi + 1] = t0; Vt[Vj + 1] = t1\n\n for (; k < n; k++) {\n t0 = c * Vt[Vi + k] + s * Vt[Vj + k]\n t1 = -s * Vt[Vi + k] + c * Vt[Vj + k]\n Vt[Vi + k] = t0; Vt[Vj + k] = t1\n }\n }\n }\n }\n if (changed === 0) break\n }\n\n for (i = 0; i < n; i++) {\n for (k = 0, sd = 0; k < m; k++) {\n t = At[i * astep + k]\n sd += t * t\n }\n W[i] = Math.sqrt(sd)\n }\n\n for (i = 0; i < n - 1; i++) {\n j = i\n for (k = i + 1; k < n; k++) {\n if (W[j] < W[k]) { j = k }\n }\n if (i !== j) {\n swap(W, i, j, sd)\n if (Vt) {\n for (k = 0; k < m; k++) {\n swap(At, i * astep + k, j * astep + k, t)\n }\n\n for (k = 0; k < n; k++) {\n swap(Vt, i * vstep + k, j * vstep + k, t)\n }\n }\n }\n }\n\n for (i = 0; i < n; i++) {\n _W[i] = W[i]\n }\n\n if (!Vt) {\n return\n }\n\n for (i = 0; i < n1; i++) {\n sd = i < n ? W[i] : 0\n\n while (sd <= minval) {\n // if we got a zero singular value, then in order to get the corresponding left singular vector\n // we generate a random vector, project it to the previously computed left singular vectors,\n // subtract the projection and normalize the difference.\n val0 = (1.0 / m)\n for (k = 0; k < m; k++) {\n seed = (seed * 214013 + 2531011)\n val = (((seed >> 16) & 0x7fff) & 256) !== 0 ? val0 : -val0\n At[i * astep + k] = val\n }\n for (iter = 0; iter < 2; iter++) {\n for (j = 0; j < i; j++) {\n sd = 0\n for (k = 0; k < m; k++) {\n sd += At[i * astep + k] * At[j * astep + k]\n }\n asum = 0.0\n for (k = 0; k < m; k++) {\n t = (At[i * astep + k] - sd * At[j * astep + k])\n At[i * astep + k] = t\n asum += Math.abs(t)\n }\n asum = asum ? 1.0 / asum : 0\n for (k = 0; k < m; k++) {\n At[i * astep + k] *= asum\n }\n }\n }\n sd = 0\n for (k = 0; k < m; k++) {\n t = At[i * astep + k]\n sd += t * t\n }\n sd = Math.sqrt(sd)\n }\n\n s = (1.0 / sd)\n for (k = 0; k < m; k++) {\n At[i * astep + k] *= s\n }\n }\n}\n\nexport function svd (A: Matrix, W: Matrix, U: Matrix, V: Matrix) {\n let at = 0\n let i = 0\n const _m = A.rows\n const _n = A.cols\n let m = _m\n let n = _n\n\n if (m < n) {\n at = 1\n i = m\n m = n\n n = i\n }\n\n const amt = new Matrix(m, m)\n const wmt = new Matrix(1, n)\n const vmt = new Matrix(n, n)\n\n if (at === 0) {\n transpose(amt, A)\n } else {\n for (i = 0; i < _n * _m; i++) {\n amt.data[i] = A.data[i]\n }\n for (; i < n * m; i++) {\n amt.data[i] = 0\n }\n }\n\n JacobiSVDImpl(amt.data, m, wmt.data, vmt.data, n, m, n, m)\n\n if (W) {\n for (i = 0; i < n; i++) {\n W.data[i] = wmt.data[i]\n }\n for (; i < _n; i++) {\n W.data[i] = 0\n }\n }\n\n if (at === 0) {\n if (U) transpose(U, amt)\n if (V) transpose(V, vmt)\n } else {\n if (U) transpose(U, vmt)\n if (V) transpose(V, amt)\n }\n}\n\n//\n\nexport function m4new () {\n return new Float32Array([\n 1, 0, 0, 0,\n 0, 1, 0, 0,\n 0, 0, 1, 0,\n 0, 0, 0, 1\n ])\n}\n\nexport function m4set (out: Float32Array, n11: number, n12: number, n13: number, n14: number, n21: number, n22: number, n23: number, n24: number, n31: number, n32: number, n33: number, n34: number, n41: number, n42: number, n43: number, n44: number) {\n out[ 0 ] = n11; out[ 4 ] = n12; out[ 8 ] = n13; out[ 12 ] = n14\n out[ 1 ] = n21; out[ 5 ] = n22; out[ 9 ] = n23; out[ 13 ] = n24\n out[ 2 ] = n31; out[ 6 ] = n32; out[ 10 ] = n33; out[ 14 ] = n34\n out[ 3 ] = n41; out[ 7 ] = n42; out[ 11 ] = n43; out[ 15 ] = n44\n}\n\nexport function m4identity (out: Float32Array) {\n m4set(out,\n 1, 0, 0, 0,\n 0, 1, 0, 0,\n 0, 0, 1, 0,\n 0, 0, 0, 1\n )\n}\n(m4identity as any).__deps = [ m4set ]\n\nexport function m4multiply (out: Float32Array, a: Float32Array, b: Float32Array) {\n const a11 = a[ 0 ]\n const a12 = a[ 4 ]\n const a13 = a[ 8 ]\n const a14 = a[ 12 ]\n const a21 = a[ 1 ]\n const a22 = a[ 5 ]\n const a23 = a[ 9 ]\n const a24 = a[ 13 ]\n const a31 = a[ 2 ]\n const a32 = a[ 6 ]\n const a33 = a[ 10 ]\n const a34 = a[ 14 ]\n const a41 = a[ 3 ]\n const a42 = a[ 7 ]\n const a43 = a[ 11 ]\n const a44 = a[ 15 ]\n\n const b11 = b[ 0 ]\n const b12 = b[ 4 ]\n const b13 = b[ 8 ]\n const b14 = b[ 12 ]\n const b21 = b[ 1 ]\n const b22 = b[ 5 ]\n const b23 = b[ 9 ]\n const b24 = b[ 13 ]\n const b31 = b[ 2 ]\n const b32 = b[ 6 ]\n const b33 = b[ 10 ]\n const b34 = b[ 14 ]\n const b41 = b[ 3 ]\n const b42 = b[ 7 ]\n const b43 = b[ 11 ]\n const b44 = b[ 15 ]\n\n out[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41\n out[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42\n out[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43\n out[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44\n\n out[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41\n out[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42\n out[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43\n out[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44\n\n out[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41\n out[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42\n out[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43\n out[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44\n\n out[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41\n out[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42\n out[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43\n out[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44\n}\n\nexport function m4makeScale (out: Float32Array, x: number, y: number, z: number) {\n m4set(out,\n x, 0, 0, 0,\n 0, y, 0, 0,\n 0, 0, z, 0,\n 0, 0, 0, 1\n )\n}\n(m4makeScale as any).__deps = [ m4set ]\n\nexport function m4makeTranslation (out: Float32Array, x: number, y: number, z: number) {\n m4set(out,\n 1, 0, 0, x,\n 0, 1, 0, y,\n 0, 0, 1, z,\n 0, 0, 0, 1\n )\n}\n(m4makeTranslation as any).__deps = [ m4set ]\n\nexport function m4makeRotationY (out: Float32Array, theta: number) {\n const c = Math.cos(theta)\n const s = Math.sin(theta)\n m4set(out,\n c, 0, s, 0,\n 0, 1, 0, 0,\n -s, 0, c, 0,\n 0, 0, 0, 1\n )\n}\n(m4makeRotationY as any).__deps = [ m4set ]\n\n//\n\nexport function m3new () {\n return new Float32Array([\n 1, 0, 0,\n 0, 1, 0,\n 0, 0, 1\n ])\n}\n\nexport function m3makeNormal (out: Float32Array, m4: Float32Array) {\n const r0 = v3new([ m4[0], m4[1], m4[2] ])\n const r1 = v3new([ m4[4], m4[5], m4[6] ])\n const r2 = v3new([ m4[8], m4[9], m4[10] ])\n const cp = v3new()\n // [ r0 ] [ r1 x r2 ]\n // M3x3 = [ r1 ] N = [ r2 x r0 ]\n // [ r2 ] [ r0 x r1 ]\n v3cross(cp, r1, r2)\n out[ 0 ] = cp[ 0 ]\n out[ 1 ] = cp[ 1 ]\n out[ 2 ] = cp[ 2 ]\n v3cross(cp, r2, r0)\n out[ 3 ] = cp[ 0 ]\n out[ 4 ] = cp[ 1 ]\n out[ 5 ] = cp[ 2 ]\n v3cross(cp, r0, r1)\n out[ 6 ] = cp[ 0 ]\n out[ 7 ] = cp[ 1 ]\n out[ 8 ] = cp[ 2 ]\n}\n(m3makeNormal as any).__deps = [ v3new, v3cross ]\n","/**\n * @file Surface Utils\n * @author Alexander Rose \n * @private\n */\n\nimport { degToRad } from '../math/math-utils'\nimport {\n m4new, m4multiply, m4makeTranslation, m4makeScale, m4makeRotationY\n} from '../math/matrix-utils'\nimport {\n v3addScalar, v3subScalar, v3divideScalar, v3multiplyScalar,\n v3floor, v3ceil, v3sub, v3negate,\n v3cross, v3fromArray, normalizeVector3array\n} from '../math/vector-utils'\nimport { NumberArray } from '../types'\n\nfunction laplacianSmooth (verts: Float32Array, faces: Float32Array, numiter: number, inflate: boolean) {\n // based on D. Xu, Y. Zhang (2009) Generating Triangulated Macromolecular\n // Surfaces by Euclidean Distance Transform. PLoS ONE 4(12): e8140.\n //\n // Permission to use, copy, modify, and distribute this program for\n // any purpose, with or without fee, is hereby granted, provided that\n // the notices on the head, the reference information, and this\n // copyright notice appear in all copies or substantial portions of\n // the Software. It is provided \"as is\" without express or implied\n // warranty.\n //\n // ported to JavaScript and adapted to NGL by Alexander Rose\n\n numiter = numiter || 1\n inflate = inflate || true\n\n const nv = verts.length / 3\n const nf = faces.length / 3\n let norms: Float32Array | undefined = undefined\n\n if (inflate) {\n norms = new Float32Array(nv * 3)\n }\n\n const tps = new Float32Array(nv * 3)\n\n let i\n const ndeg = 20\n const vertdeg = new Array(ndeg)\n\n for (i = 0; i < ndeg; ++i) {\n vertdeg[ i ] = new Uint32Array(nv)\n }\n\n for (i = 0; i < nv; ++i) {\n vertdeg[ 0 ][ i ] = 0\n }\n\n let j, jl\n let flagvert: boolean\n\n // for each face\n\n for (i = 0; i < nf; ++i) {\n var ao = i * 3\n var bo = i * 3 + 1\n var co = i * 3 + 2\n\n // vertex a\n\n flagvert = true\n for (j = 0, jl = vertdeg[ 0 ][ faces[ao] ]; j < jl; ++j) {\n if (faces[ bo ] === vertdeg[ j + 1 ][ faces[ ao ] ]) {\n flagvert = false\n break\n }\n }\n if (flagvert) {\n vertdeg[ 0 ][ faces[ ao ] ]++\n vertdeg[ vertdeg[ 0 ][ faces[ ao ] ] ][ faces[ ao ] ] = faces[ bo ]\n }\n\n flagvert = true\n for (j = 0, jl = vertdeg[ 0 ][ faces[ ao ] ]; j < jl; ++j) {\n if (faces[ co ] === vertdeg[ j + 1 ][ faces[ ao ] ]) {\n flagvert = false\n break\n }\n }\n if (flagvert) {\n vertdeg[ 0 ][ faces[ ao ] ]++\n vertdeg[ vertdeg[ 0 ][ faces[ ao ] ] ][ faces[ ao ] ] = faces[ co ]\n }\n\n // vertex b\n\n flagvert = true\n for (j = 0, jl = vertdeg[ 0 ][ faces[ bo ] ]; j < jl; ++j) {\n if (faces[ ao ] === vertdeg[ j + 1 ][ faces[ bo ] ]) {\n flagvert = false\n break\n }\n }\n if (flagvert) {\n vertdeg[ 0 ][ faces[ bo ] ]++\n vertdeg[ vertdeg[ 0 ][ faces[ bo ] ] ][ faces[ bo ] ] = faces[ ao ]\n }\n\n flagvert = true\n for (j = 0, jl = vertdeg[ 0 ][ faces[ bo ] ]; j < jl; ++j) {\n if (faces[ co ] === vertdeg[ j + 1 ][ faces[ bo ] ]) {\n flagvert = false\n break\n }\n }\n if (flagvert) {\n vertdeg[ 0 ][ faces[ bo ] ]++\n vertdeg[ vertdeg[ 0 ][ faces[ bo ] ] ][ faces[ bo ] ] = faces[ co ]\n }\n\n // vertex c\n\n flagvert = true\n for (j = 0; j < vertdeg[ 0 ][ faces[ co ] ]; ++j) {\n if (faces[ ao ] === vertdeg[ j + 1 ][ faces[ co ] ]) {\n flagvert = false\n break\n }\n }\n if (flagvert) {\n vertdeg[ 0 ][ faces[ co ] ]++\n vertdeg[ vertdeg[ 0 ][ faces[ co ] ] ][ faces[ co ] ] = faces[ ao ]\n }\n\n flagvert = true\n for (j = 0, jl = vertdeg[ 0 ][ faces[ co ] ]; j < jl; ++j) {\n if (faces[ bo ] === vertdeg[ j + 1 ][ faces[ co ] ]) {\n flagvert = false\n break\n }\n }\n if (flagvert) {\n vertdeg[ 0 ][ faces[ co ] ]++\n vertdeg[ vertdeg[ 0 ][ faces[ co ] ] ][ faces[ co ] ] = faces[ bo ]\n }\n }\n\n var wt = 1.0\n var wt2 = 0.5\n var i3, vi3, vdi, wtvi, wt2vi\n var ssign = -1\n var scaleFactor = 1\n var outwt = 0.75 / (scaleFactor + 3.5) // area-preserving\n\n // smoothing iterations\n\n for (var k = 0; k < numiter; ++k) {\n // for each vertex\n\n for (i = 0; i < nv; ++i) {\n i3 = i * 3\n vdi = vertdeg[ 0 ][ i ]\n\n if (vdi < 3) {\n tps[ i3 ] = verts[ i3 ]\n tps[ i3 + 1 ] = verts[ i3 + 1 ]\n tps[ i3 + 2 ] = verts[ i3 + 2 ]\n } else if (vdi === 3 || vdi === 4) {\n tps[ i3 ] = 0\n tps[ i3 + 1 ] = 0\n tps[ i3 + 2 ] = 0\n\n for (j = 0; j < vdi; ++j) {\n vi3 = vertdeg[ j + 1 ][ i ] * 3\n tps[ i3 ] += verts[ vi3 ]\n tps[ i3 + 1 ] += verts[ vi3 + 1 ]\n tps[ i3 + 2 ] += verts[ vi3 + 2 ]\n }\n\n tps[ i3 ] += wt2 * verts[ i3 ]\n tps[ i3 + 1 ] += wt2 * verts[ i3 + 1 ]\n tps[ i3 + 2 ] += wt2 * verts[ i3 + 2 ]\n\n wt2vi = wt2 + vdi\n tps[ i3 ] /= wt2vi\n tps[ i3 + 1 ] /= wt2vi\n tps[ i3 + 2 ] /= wt2vi\n } else {\n tps[ i3 ] = 0\n tps[ i3 + 1 ] = 0\n tps[ i3 + 2 ] = 0\n\n for (j = 0; j < vdi; ++j) {\n vi3 = vertdeg[ j + 1 ][ i ] * 3\n tps[ i3 ] += verts[ vi3 ]\n tps[ i3 + 1 ] += verts[ vi3 + 1 ]\n tps[ i3 + 2 ] += verts[ vi3 + 2 ]\n }\n\n tps[ i3 ] += wt * verts[ i3 ]\n tps[ i3 + 1 ] += wt * verts[ i3 + 1 ]\n tps[ i3 + 2 ] += wt * verts[ i3 + 2 ]\n\n wtvi = wt + vdi\n tps[ i3 ] /= wtvi\n tps[ i3 + 1 ] /= wtvi\n tps[ i3 + 2 ] /= wtvi\n }\n }\n\n verts.set(tps) // copy smoothed positions\n\n if (inflate) {\n computeVertexNormals(verts, faces, norms)\n var nv3 = nv * 3\n\n for (i3 = 0; i3 < nv3; i3 += 3) {\n // if(verts[i].inout) ssign=1;\n // else ssign=-1;\n\n verts[ i3 ] += ssign * outwt * norms![ i3 ]\n verts[ i3 + 1 ] += ssign * outwt * norms![ i3 + 1 ]\n verts[ i3 + 2 ] += ssign * outwt * norms![ i3 + 2 ]\n }\n }\n }\n}\nObject.assign(laplacianSmooth, {__deps: [ computeVertexNormals ]})\n\nfunction computeVertexNormals (position: Float32Array, index?: NumberArray, normal?: Float32Array) {\n var i, il\n\n if (normal === undefined) {\n normal = new Float32Array(position.length)\n } else {\n // reset existing normals to zero\n for (i = 0, il = normal.length; i < il; i++) {\n normal[ i ] = 0\n }\n }\n\n var a = new Float32Array(3)\n var b = new Float32Array(3)\n var c = new Float32Array(3)\n var cb = new Float32Array(3)\n var ab = new Float32Array(3)\n\n if (index) {\n // indexed elements\n for (i = 0, il = index.length; i < il; i += 3) {\n var ai = index[ i ] * 3\n var bi = index[ i + 1 ] * 3\n var ci = index[ i + 2 ] * 3\n\n v3fromArray(a, position, ai)\n v3fromArray(b, position, bi)\n v3fromArray(c, position, ci)\n\n v3sub(cb, c, b)\n v3sub(ab, a, b)\n v3cross(cb, cb, ab)\n\n normal[ ai ] += cb[ 0 ]\n normal[ ai + 1 ] += cb[ 1 ]\n normal[ ai + 2 ] += cb[ 2 ]\n\n normal[ bi ] += cb[ 0 ]\n normal[ bi + 1 ] += cb[ 1 ]\n normal[ bi + 2 ] += cb[ 2 ]\n\n normal[ ci ] += cb[ 0 ]\n normal[ ci + 1 ] += cb[ 1 ]\n normal[ ci + 2 ] += cb[ 2 ]\n }\n } else {\n // non-indexed elements (unconnected triangle soup)\n for (i = 0, il = position.length; i < il; i += 9) {\n v3fromArray(a, position, i)\n v3fromArray(b, position, i + 3)\n v3fromArray(c, position, i + 6)\n\n v3sub(cb, c, b)\n v3sub(ab, a, b)\n v3cross(cb, cb, ab)\n\n normal[ i ] = cb[ 0 ]\n normal[ i + 1 ] = cb[ 1 ]\n normal[ i + 2 ] = cb[ 2 ]\n\n normal[ i + 3 ] = cb[ 0 ]\n normal[ i + 4 ] = cb[ 1 ]\n normal[ i + 5 ] = cb[ 2 ]\n\n normal[ i + 6 ] = cb[ 0 ]\n normal[ i + 7 ] = cb[ 1 ]\n normal[ i + 8 ] = cb[ 2 ]\n }\n }\n\n normalizeVector3array(normal)\n\n return normal\n}\nObject.assign(computeVertexNormals, {__deps: [\n v3sub, v3cross, v3fromArray, normalizeVector3array\n]})\n\nfunction getRadiusDict (radiusList: number[]) {\n var radiusDict: {[k: number]: boolean} = {}\n for (var i = 0, il = radiusList.length; i < il; ++i) {\n radiusDict[ radiusList[ i ] ] = true\n }\n return radiusDict\n}\n\nfunction getSurfaceGrid (min: Float32Array, max: Float32Array, maxRadius: number, scaleFactor: number, extraMargin: number) {\n // need margin to avoid boundary/round off effects\n var margin = (1 / scaleFactor) * 3\n margin += maxRadius\n\n v3subScalar(min, min, extraMargin + margin)\n v3addScalar(max, max, extraMargin + margin)\n\n v3multiplyScalar(min, min, scaleFactor)\n v3floor(min, min)\n v3divideScalar(min, min, scaleFactor)\n\n v3multiplyScalar(max, max, scaleFactor)\n v3ceil(max, max)\n v3divideScalar(max, max, scaleFactor)\n\n var dim = new Float32Array(3)\n v3sub(dim, max, min)\n v3multiplyScalar(dim, dim, scaleFactor)\n v3ceil(dim, dim)\n v3addScalar(dim, dim, 1)\n\n var maxSize = Math.pow(10, 6) * 256\n var tmpSize = dim[ 0 ] * dim[ 1 ] * dim[ 2 ] * 3\n\n if (maxSize <= tmpSize) {\n scaleFactor *= Math.pow(maxSize / tmpSize, 1 / 3)\n\n v3multiplyScalar(min, min, scaleFactor)\n v3floor(min, min)\n v3divideScalar(min, min, scaleFactor)\n\n v3multiplyScalar(max, max, scaleFactor)\n v3ceil(max, max)\n v3divideScalar(max, max, scaleFactor)\n\n v3sub(dim, max, min)\n v3multiplyScalar(dim, dim, scaleFactor)\n v3ceil(dim, dim)\n v3addScalar(dim, dim, 1)\n }\n\n var tran = new Float32Array(min)\n v3negate(tran, tran)\n\n // coordinate transformation matrix\n var matrix = m4new()\n var mroty = m4new()\n m4makeRotationY(mroty, degToRad(90))\n m4multiply(matrix, matrix, mroty)\n\n var mscale = m4new()\n m4makeScale(\n mscale,\n -1 / scaleFactor,\n 1 / scaleFactor,\n 1 / scaleFactor\n )\n m4multiply(matrix, matrix, mscale)\n\n var mtrans = m4new()\n m4makeTranslation(\n mtrans,\n -scaleFactor * tran[2],\n -scaleFactor * tran[1],\n -scaleFactor * tran[0]\n )\n m4multiply(matrix, matrix, mtrans)\n\n return {\n dim: dim,\n tran: tran,\n matrix: matrix,\n scaleFactor: scaleFactor\n }\n}\nObject.assign(getSurfaceGrid, {__deps: [\n degToRad,\n v3subScalar, v3addScalar, v3divideScalar, v3multiplyScalar,\n v3floor, v3ceil, v3sub, v3negate,\n m4new, m4multiply, m4makeTranslation, m4makeScale, m4makeRotationY\n]})\n\nexport {\n laplacianSmooth,\n computeVertexNormals,\n getRadiusDict,\n getSurfaceGrid\n}\n","/**\n * @file Surface\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Box3, Geometry, BufferGeometry, Group, Color } from 'three'\n\nimport { Debug, Log, ColormakerRegistry } from '../globals'\nimport { getUintArray } from '../utils'\nimport { AtomPicker, SurfacePicker } from '../utils/picker'\nimport { uniformArray, uniformArray3, serialArray } from '../math/array-utils'\nimport Selection from '../selection/selection'\nimport { ColormakerParameters } from '../color/colormaker';\nimport { Structure, Volume } from '../ngl';\n\nexport interface SurfaceData {\n position: Float32Array\n index: Uint32Array|Uint16Array|undefined\n normal: Float32Array\n color: Float32Array\n atomindex: Int32Array\n contour: boolean\n}\n/**\n * Surface\n */\nclass Surface {\n name: string\n path: string\n position: Float32Array\n index: Uint32Array|Uint16Array|undefined\n normal: Float32Array|undefined\n color: Float32Array|undefined\n atomindex: Int32Array|undefined\n contour: boolean\n center: Vector3\n boundingBox: Box3\n size: number\n info: {\n type?: string\n probeRadius?: number\n scaleFactor?: number\n smooth?: number\n cutoff?: number\n isolevel?: number\n volume?: Volume\n }\n\n /**\n * @param {String} name - surface name\n * @param {String} path - source path\n * @param {Object} data - surface data\n * @param {Float32Array} data.position - surface positions\n * @param {Int32Array} data.index - surface indices\n * @param {Float32Array} data.normal - surface normals\n * @param {Float32Array} data.color - surface colors\n * @param {Int32Array} data.atomindex - atom indices\n * @param {boolean} data.contour - contour mode flag\n */\n constructor (name: string, path: string, data?: SurfaceData) {\n this.name = name || ''\n this.path = path || ''\n this.info = {}\n\n this.center = new Vector3()\n this.boundingBox = new Box3()\n\n if (data instanceof Geometry ||\n data instanceof BufferGeometry ||\n data instanceof Group\n ) {\n // to be removed\n this.fromGeometry(data)\n } else if (data) {\n this.set(\n data.position,\n data.index,\n data.normal,\n data.color,\n data.atomindex,\n data.contour\n )\n\n this.boundingBox.setFromArray(data.position)\n this.boundingBox.getCenter(this.center)\n }\n }\n\n get type () { return 'Surface' }\n\n /**\n * set surface data\n * @param {Float32Array} position - surface positions\n * @param {Int32Array} index - surface indices\n * @param {Float32Array} normal - surface normals\n * @param {Float32Array} color - surface colors\n * @param {Int32Array} atomindex - atom indices\n * @param {boolean} contour - contour mode flag\n * @return {undefined}\n */\n set (position: Float32Array,\n index: Uint32Array|Uint16Array|undefined,\n normal: Float32Array|undefined,\n color: Float32Array|undefined,\n atomindex: Int32Array|undefined,\n contour: boolean = false) {\n /**\n * @type {Float32Array}\n */\n this.position = position\n /**\n * @type {Uint32Array|Uint16Array|undefined}\n */\n this.index = index\n /**\n * @type {Float32Array|undefined}\n */\n this.normal = normal\n /**\n * @type {Float32Array|undefined}\n */\n this.color = color\n /**\n * @type {Int32Array|undefined}\n */\n this.atomindex = atomindex\n\n this.size = position.length / 3\n this.contour = contour\n }\n\n fromGeometry (geometry: Geometry|BufferGeometry|Group) {\n if (Debug) Log.time('GeometrySurface.fromGeometry')\n\n let geo\n\n if (geometry instanceof Geometry) {\n geometry.computeVertexNormals(true)\n geo = new BufferGeometry().fromGeometry(geometry)\n } else if (geometry instanceof BufferGeometry) {\n geo = geometry\n } else {\n geo = (geometry as any)[ 0 ]\n }\n\n if (!geo.boundingBox) geo.computeBoundingBox()\n\n this.boundingBox.copy(geo.boundingBox)\n this.boundingBox.getCenter(this.center)\n\n let position, color, index, normal\n\n if (geo instanceof BufferGeometry) {\n const attr = geo.attributes\n const an = (attr as any).normal ? (attr as any).normal.array : false\n\n // assume there are no normals if the first is zero\n if (!an || (an[ 0 ] === 0 && an[ 1 ] === 0 && an[ 2 ] === 0)) {\n geo.computeVertexNormals()\n }\n\n position = (attr).position.array\n index = (attr).index ? (attr).index.array : null\n normal = (attr).normal.array\n }\n\n this.set(position, index, normal, color, undefined)\n\n if (Debug) Log.timeEnd('GeometrySurface.setGeometry')\n }\n\n getPosition () {\n return this.position\n }\n\n getColor (params: ColormakerParameters&{ scheme: string}) {\n const p = params || {}\n p.surface = this\n\n const n = this.size\n const array = new Float32Array(n * 3)\n const colormaker = ColormakerRegistry.getScheme(p)\n\n if (colormaker.volumeColor || p.scheme === 'random') {\n for (let i = 0; i < n; ++i) {\n colormaker.volumeColorToArray(i, array, i * 3)\n }\n } else if (colormaker.positionColor) {\n const v = new Vector3()\n const pos = this.position\n\n for (let i = 0; i < n; ++i) {\n var i3 = i * 3\n v.set(pos[ i3 ], pos[ i3 + 1 ], pos[ i3 + 2 ])\n colormaker.positionColorToArray(v, array, i3)\n }\n } else if (colormaker.atomColor && this.atomindex) {\n const atomProxy = p.structure!.getAtomProxy()\n const atomindex = this.atomindex\n\n for (let i = 0; i < n; ++i) {\n atomProxy.index = atomindex[ i ]\n colormaker.atomColorToArray(atomProxy, array, i * 3)\n }\n } else {\n const tc = new Color(p.value)\n uniformArray3(n, tc.r, tc.g, tc.b, array)\n }\n\n return array\n }\n\n getPicking (structure?: Structure) {\n if (this.atomindex && structure) {\n return new AtomPicker(this.atomindex as any, structure)\n } else {\n return new SurfacePicker(serialArray(this.size), this)\n }\n }\n\n getNormal () {\n return this.normal\n }\n\n getSize (size: number, scale: number) {\n return uniformArray(this.size, size * scale)\n }\n\n getIndex () {\n return this.index\n }\n\n getFilteredIndex (sele: string, structure: Structure) {\n if (sele && this.atomindex) {\n const selection = new Selection(sele)\n const atomSet = structure.getAtomSet(selection)\n const filteredIndex = []\n\n const atomindex = this.atomindex\n const index = this.index\n const n = index!.length\n const elementSize = this.contour ? 2 : 3\n\n let j = 0\n\n for (let i = 0; i < n; i += elementSize) {\n let include = true\n\n for (let a = 0; a < elementSize; a++) {\n const idx = index![ i + a ]\n const ai = atomindex[ idx ]\n if (!atomSet.get(ai)) {\n include = false\n break\n }\n }\n\n if (!include) { continue }\n\n for (let a = 0; a < elementSize; a++, j++) {\n filteredIndex[ j ] = index![ i + a ]\n }\n }\n\n return getUintArray(filteredIndex, this.position.length / 3)\n } else {\n return this.index\n }\n }\n\n getAtomindex () {\n return this.atomindex\n }\n\n dispose () {\n\n //\n\n }\n}\n\nexport default Surface\n","/**\n * @file Volume\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Box3, Matrix3, Matrix4 } from 'three'\n\nimport { WorkerRegistry, ColormakerRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport WorkerPool from '../worker/worker-pool'\nimport { VolumePicker } from '../utils/picker'\nimport {\n uniformArray, serialArray,\n arrayMin, arrayMax, arraySum, arrayMean, arrayRms\n} from '../math/array-utils'\nimport MarchingCubes from './marching-cubes'\nimport { laplacianSmooth, computeVertexNormals } from './surface-utils'\nimport {\n applyMatrix4toVector3array, applyMatrix3toVector3array\n} from '../math/vector-utils'\nimport { m3new, m3makeNormal } from '../math/matrix-utils'\nimport Surface from './surface'\nimport { NumberArray } from '../types';\nimport { ColormakerParameters } from '../color/colormaker';\n\nexport interface VolumeSurface {\n new (data: NumberArray, nx: number, ny: number, nz: number, atomindex: NumberArray): void\n getSurface: (isolevel: number, smooth: boolean|number, box: number[][]|undefined, matrix: Float32Array, contour: boolean, wrap?: boolean) => {\n position: Float32Array\n normal: undefined|Float32Array\n index: Uint32Array|Uint16Array\n atomindex: Int32Array|undefined\n contour: boolean\n }\n}\nexport function VolumeSurface (this: VolumeSurface,data: NumberArray, nx: number, ny: number, nz: number, atomindex: NumberArray) {\n var mc = new (MarchingCubes as any)(data, nx, ny, nz, atomindex) as MarchingCubes\n\n function getSurface (isolevel: number, smooth: boolean|number, box: number[][]|undefined, matrix: Float32Array, contour: boolean, wrap: boolean = false) {\n const sd = mc.triangulate(isolevel, smooth as boolean, box, contour, wrap)\n if (smooth && !contour) {\n laplacianSmooth(sd.position, sd.index as any, smooth as number, true)\n sd.normal = computeVertexNormals(sd.position, sd.index as any)\n }\n if (matrix) {\n applyMatrix4toVector3array(matrix, sd.position)\n if (sd.normal) {\n const normalMatrix = m3new()\n m3makeNormal(normalMatrix, matrix)\n applyMatrix3toVector3array(normalMatrix, sd.normal)\n }\n }\n return sd\n }\n\n this.getSurface = getSurface\n}\nObject.assign(VolumeSurface, {__deps: [\n laplacianSmooth, computeVertexNormals, MarchingCubes,\n applyMatrix4toVector3array, applyMatrix3toVector3array,\n m3new, m3makeNormal\n]})\n\nWorkerRegistry.add('surf', function func (e: any, callback: (data: any, transferList: any) => void) {\n const a = e.data.args\n const p = e.data.params\n if (a) {\n /* global self */\n (self as any).volsurf = new (VolumeSurface as any)(a[0], a[1], a[2], a[3], a[4]) as VolumeSurface\n }\n if (p) {\n const sd = ((self as any).volsurf as VolumeSurface).getSurface(\n p.isolevel, p.smooth, p.box, p.matrix, p.contour, p.wrap\n )\n const transferList = [ sd.position.buffer, sd.index.buffer ]\n if (sd.normal) transferList.push(sd.normal.buffer)\n if (sd.atomindex) transferList.push(sd.atomindex.buffer)\n const data = {\n sd: sd,\n p: p\n }\n callback(data, transferList)\n }\n}, [ VolumeSurface ])\n\nexport type VolumeSize = 'value'|'abs-value'|'value-min'|'deviation'\n/**\n * Volume\n */\nclass Volume {\n name: string\n path: string\n\n matrix: Matrix4\n normalMatrix: Matrix3\n inverseMatrix: Matrix4\n center: Vector3\n boundingBox: Box3\n\n nx: number\n ny: number\n nz: number\n data: Float32Array\n\n worker: Worker\n workerPool: WorkerPool\n _position: Float32Array\n _min: number|undefined\n _max: number|undefined\n _mean: number|undefined\n _rms: number|undefined\n _sum: number|undefined\n __box: Box3|undefined\n\n atomindex: Int32Array|undefined\n volsurf: VolumeSurface|undefined\n header: any\n /**\n * Make Volume instance\n * @param {String} name - volume name\n * @param {String} path - source path\n * @param {Float32array} data - volume 3d grid\n * @param {Integer} nx - x dimension of the 3d volume\n * @param {Integer} ny - y dimension of the 3d volume\n * @param {Integer} nz - z dimension of the 3d volume\n * @param {Int32Array} atomindex - atom indices corresponding to the cells in the 3d grid\n */\n constructor (name: string, path: string, data?: Float32Array, nx?: number, ny?: number, nz?: number, atomindex?: Int32Array) {\n this.name = name\n this.path = path\n\n this.matrix = new Matrix4()\n this.normalMatrix = new Matrix3()\n this.inverseMatrix = new Matrix4()\n this.center = new Vector3()\n this.boundingBox = new Box3()\n\n this.setData(data, nx, ny, nz, atomindex)\n }\n\n get type () { return 'Volume' }\n\n /**\n * set volume data\n * @param {Float32array} data - volume 3d grid\n * @param {Integer} nx - x dimension of the 3d volume\n * @param {Integer} ny - y dimension of the 3d volume\n * @param {Integer} nz - z dimension of the 3d volume\n * @param {Int32Array} atomindex - atom indices corresponding to the cells in the 3d grid\n * @return {undefined}\n */\n setData (data?: Float32Array, nx?: number, ny?: number, nz?: number, atomindex?: Int32Array) {\n this.nx = nx || 1\n this.ny = ny || 1\n this.nz = nz || 1\n\n this.data = data || new Float32Array(1)\n this.setAtomindex(atomindex)\n\n this._position = new Float32Array()\n\n delete this._min\n delete this._max\n delete this._mean\n delete this._rms\n\n if (this.worker) this.worker.terminate()\n }\n\n /**\n * Set statistics, which can be different from the data in this volume,\n * if this volume is a slice of a bigger volume\n * @param {Number|undefined} min - minimum value of the whole data set\n * @param {Number|undefined} max - maximum value of the whole data set\n * @param {Number|undefined} mean - average value of the whole data set\n * @param {Number|undefined} rms - sigma value of the whole data set\n */\n setStats (min: number|undefined, max: number|undefined, mean: number|undefined, rms: number|undefined) {\n this._min = min\n this._max = max\n this._mean = mean\n this._rms = rms\n }\n\n /**\n * set transformation matrix\n * @param {Matrix4} matrix - 4x4 transformation matrix\n * @return {undefined}\n */\n setMatrix (matrix: Matrix4) {\n this.matrix.copy(matrix)\n\n const bb = this.boundingBox\n const v = this.center // temporary re-purposing\n\n const x = this.nx - 1\n const y = this.ny - 1\n const z = this.nz - 1\n\n bb.makeEmpty()\n\n bb.expandByPoint(v.set(x, y, z))\n bb.expandByPoint(v.set(x, y, 0))\n bb.expandByPoint(v.set(x, 0, z))\n bb.expandByPoint(v.set(x, 0, 0))\n bb.expandByPoint(v.set(0, y, z))\n bb.expandByPoint(v.set(0, 0, z))\n bb.expandByPoint(v.set(0, y, 0))\n bb.expandByPoint(v.set(0, 0, 0))\n\n bb.applyMatrix4(this.matrix)\n bb.getCenter(this.center)\n\n // make normal matrix\n\n const me = this.matrix.elements\n const r0 = new Vector3(me[0], me[1], me[2])\n const r1 = new Vector3(me[4], me[5], me[6])\n const r2 = new Vector3(me[8], me[9], me[10])\n const cp = new Vector3()\n // [ r0 ] [ r1 x r2 ]\n // M3x3 = [ r1 ] N = [ r2 x r0 ]\n // [ r2 ] [ r0 x r1 ]\n const ne = this.normalMatrix.elements\n cp.crossVectors(r1, r2)\n ne[ 0 ] = cp.x\n ne[ 1 ] = cp.y\n ne[ 2 ] = cp.z\n cp.crossVectors(r2, r0)\n ne[ 3 ] = cp.x\n ne[ 4 ] = cp.y\n ne[ 5 ] = cp.z\n cp.crossVectors(r0, r1)\n ne[ 6 ] = cp.x\n ne[ 7 ] = cp.y\n ne[ 8 ] = cp.z\n\n this.inverseMatrix.getInverse(this.matrix)\n }\n\n /**\n * set atom indices\n * @param {Int32Array} atomindex - atom indices corresponding to the cells in the 3d grid\n * @return {undefined}\n */\n setAtomindex (atomindex?: Int32Array) {\n this.atomindex = atomindex\n }\n\n getBox (center: Vector3, size: number, target: Box3) {\n if (!target) target = new Box3()\n\n target.set(center, center)\n target.expandByScalar(size)\n target.applyMatrix4(this.inverseMatrix)\n\n target.min.round()\n target.max.round()\n\n return target\n }\n\n _getBox (center: Vector3|undefined, size: number) {\n if (!center || !size) return\n\n if (!this.__box) this.__box = new Box3()\n const box = this.getBox(center, size, this.__box)\n return [ box.min.toArray(), box.max.toArray() ]\n }\n\n _makeSurface (sd: any, isolevel: number, smooth: number) {\n const name = this.name + '@' + isolevel.toPrecision(2)\n const surface = new Surface(name, '', sd)\n surface.info.isolevel = isolevel\n surface.info.smooth = smooth\n surface.info.volume = this\n\n return surface\n }\n\n getSurface (isolevel: number, smooth: number, center: Vector3, size: number, contour: boolean, wrap: boolean = false) {\n isolevel = isNaN(isolevel) ? this.getValueForSigma(2) : isolevel\n smooth = defaults(smooth, 0)\n\n //\n\n if (this.volsurf === undefined) {\n this.volsurf = new (VolumeSurface as any)(\n this.data, this.nx, this.ny, this.nz, this.atomindex\n ) as VolumeSurface\n }\n\n const box = this._getBox(center, size)\n const sd = this.volsurf.getSurface(\n isolevel, smooth, box!, this.matrix.elements as unknown as Float32Array, contour, wrap\n )\n\n return this._makeSurface(sd, isolevel, smooth)\n }\n\n getSurfaceWorker (isolevel: number, smooth: number, center: Vector3, size: number, contour: boolean, wrap: boolean, callback: (s: Surface) => void) {\n isolevel = isNaN(isolevel) ? this.getValueForSigma(2) : isolevel\n smooth = smooth || 0\n\n //\n\n if (window.hasOwnProperty('Worker')) {\n if (this.workerPool === undefined) {\n this.workerPool = new WorkerPool('surf', 2)\n }\n\n const msg = {}\n const worker = this.workerPool.getNextWorker()\n\n if (worker!.postCount === 0) {\n Object.assign(msg, {\n args: [\n this.data, this.nx, this.ny, this.nz, this.atomindex\n ]\n })\n }\n\n Object.assign(msg, {\n params: {\n isolevel: isolevel,\n smooth: smooth,\n box: this._getBox(center, size),\n matrix: this.matrix.elements,\n contour: contour,\n wrap: wrap\n }\n })\n\n worker!.post(msg, undefined,\n (e: any) => {\n const sd = e.data.sd\n const p = e.data.p\n callback(this._makeSurface(sd, p.isolevel, p.smooth))\n },\n (e : string) => {\n console.warn(\n 'Volume.getSurfaceWorker error - trying without worker', e\n )\n const surface = this.getSurface(isolevel, smooth, center, size, contour, wrap)\n callback(surface)\n }\n )\n } else {\n const surface = this.getSurface(isolevel, smooth, center, size, contour, wrap)\n callback(surface)\n }\n }\n\n getValueForSigma (sigma: number) {\n return this.mean + defaults(sigma, 2) * this.rms\n }\n\n getSigmaForValue (value: number) {\n return (defaults(value, 0) - this.mean) / this.rms\n }\n\n get position () {\n if (!this._position) {\n const nz = this.nz\n const ny = this.ny\n const nx = this.nx\n const position = new Float32Array(nx * ny * nz * 3)\n\n let p = 0\n for (let z = 0; z < nz; ++z) {\n for (let y = 0; y < ny; ++y) {\n for (let x = 0; x < nx; ++x) {\n position[ p + 0 ] = x\n position[ p + 1 ] = y\n position[ p + 2 ] = z\n p += 3\n }\n }\n }\n\n applyMatrix4toVector3array(this.matrix.elements as unknown as Float32Array, position)\n this._position = position\n }\n\n return this._position\n }\n\n getDataAtomindex () {\n return this.atomindex\n }\n\n getDataPosition () {\n return this.position\n }\n\n getDataColor (params: ColormakerParameters & {scheme: string}) {\n const p = params || {}\n p.volume = this\n p.scale = p.scale || 'Spectral'\n p.domain = p.domain || [ this.min, this.max ]\n\n const colormaker = ColormakerRegistry.getScheme(p)\n\n const n = this.position.length / 3\n const array = new Float32Array(n * 3)\n\n // var atoms = p.structure.atoms;\n // var atomindex = this.atomindex;\n\n for (let i = 0; i < n; ++i) {\n colormaker.volumeColorToArray(i, array, i * 3)\n // a = atoms[ atomindex[ i ] ];\n // if( a ) colormaker.atomColorToArray( a, array, i * 3 );\n }\n\n return array\n }\n\n getDataPicking () {\n const picking = serialArray(this.position.length / 3)\n return new VolumePicker(picking, this)\n }\n\n getDataSize (size: VolumeSize|number, scale: number) {\n const data = this.data\n const n = this.position.length / 3\n let array\n\n switch (size) {\n case 'value':\n array = new Float32Array(data)\n break\n\n case 'abs-value':\n array = new Float32Array(data)\n for (let i = 0; i < n; ++i) {\n array[ i ] = Math.abs(array[ i ])\n }\n break\n\n case 'value-min': {\n array = new Float32Array(data)\n const min = this.min\n for (let i = 0; i < n; ++i) {\n array[ i ] -= min\n }\n break\n }\n\n case 'deviation':\n array = new Float32Array(data)\n break\n\n default:\n array = uniformArray(n, size)\n break\n }\n\n if (scale !== 1.0) {\n for (let i = 0; i < n; ++i) {\n array[ i ] *= scale\n }\n }\n\n return array\n }\n\n get min () {\n if (this._min === undefined) {\n this._min = arrayMin(this.data)\n }\n return this._min\n }\n\n get max () {\n if (this._max === undefined) {\n this._max = arrayMax(this.data)\n }\n return this._max\n }\n\n get sum () {\n if (this._sum === undefined) {\n this._sum = arraySum(this.data)\n }\n return this._sum\n }\n\n get mean () {\n if (this._mean === undefined) {\n this._mean = arrayMean(this.data)\n }\n return this._mean\n }\n\n get rms () {\n if (this._rms === undefined) {\n this._rms = arrayRms(this.data)\n }\n return this._rms\n }\n\n clone () {\n const vol = new Volume(\n this.name,\n this.path,\n\n this.data,\n\n this.nx,\n this.ny,\n this.nz,\n\n this.atomindex\n )\n\n vol.matrix.copy(this.matrix)\n vol.header = Object.assign({}, this.header)\n\n return vol\n }\n\n dispose () {\n if (this.workerPool) this.workerPool.terminate()\n }\n}\n\nexport default Volume\n","/**\n * @file Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport {\n Color, Vector3, Matrix4,\n FrontSide, BackSide, DoubleSide,\n // VertexColors,\n NoBlending,\n BufferGeometry, BufferAttribute,\n UniformsUtils, UniformsLib, Uniform,\n Group, LineSegments, Points, Mesh, Object3D,\n ShaderMaterial\n} from 'three'\n\nimport { Log } from '../globals'\nimport { createParams, getTypedArray, getUintArray } from '../utils'\nimport { GenericColor, NumberArray } from '../types'\nimport { getShader, ShaderDefines } from '../shader/shader-utils'\nimport { serialArray } from '../math/array-utils'\nimport { Picker } from '../utils/picker'\n\nexport type BufferSide = 'front'|'back'|'double'\n\nfunction getThreeSide (side: BufferSide) {\n if (side === 'front') {\n return FrontSide\n } else if (side === 'back') {\n return BackSide\n } else if (side === 'double') {\n return DoubleSide\n } else {\n return DoubleSide\n }\n}\n\nconst itemSize = {\n 'f': 1, 'v2': 2, 'v3': 3, 'c': 3\n}\n\nfunction setObjectMatrix (object: Object3D, matrix: Matrix4) {\n object.matrix.copy(matrix)\n object.matrix.decompose(object.position, object.quaternion, object.scale)\n object.matrixWorldNeedsUpdate = true\n}\n\nexport type BufferTypes = 'picking'|'background'\nexport type BufferMaterials = 'material'|'wireframeMaterial'|'pickingMaterial'\n\nexport interface _BufferAttribute {\n type: 'f'|'v2'|'v3'|'c'\n value?: NumberArray\n}\n\nexport type Uniforms = { [k: string]: Uniform|{ value: any } }\n\nexport const BufferDefaultParameters = {\n opaqueBack: false,\n side: 'double' as BufferSide, // which triangle sides to render\n opacity: 1.0, // translucency: 1 is fully opaque, 0 is fully transparent\n depthWrite: true,\n clipNear: 0, // position of camera near/front clipping plane in percent of scene bounding box\n clipRadius: 0,\n clipCenter: new Vector3(),\n flatShaded: false, // render flat shaded\n wireframe: false, // render as wireframe\n roughness: 0.4, // how rough the material is, between 0 and 1\n metalness: 0.0, // how metallic the material is, between 0 and 1\n diffuse: 0xffffff, // diffuse color for lighting\n diffuseInterior: false,\n useInteriorColor: false, // render back-side with interior color\n interiorColor: 0xdddddd, // interior color\n interiorDarkening: 0, // interior darkening factor\n forceTransparent: false, // force the material to allow transparency\n matrix: new Matrix4(), // additional transformation matrix\n disablePicking: false, // disable picking\n sortParticles: false,\n background: false\n}\nexport type BufferParameters = Omit & { diffuse: GenericColor; interiorColor: GenericColor }\n\nexport const BufferParameterTypes = {\n opaqueBack: { updateShader: true },\n side: { updateShader: true, property: true },\n opacity: { uniform: true },\n depthWrite: { property: true },\n clipNear: { updateShader: true, property: true },\n clipRadius: { updateShader: true, uniform: true },\n clipCenter: { uniform: true },\n flatShaded: { updateShader: true },\n background: { updateShader: true },\n wireframe: { updateVisibility: true },\n roughness: { uniform: true },\n metalness: { uniform: true },\n diffuse: { uniform: true },\n diffuseInterior: { updateShader: true },\n useInteriorColor: { updateShader: true },\n interiorColor: { uniform: true },\n interiorDarkening: { uniform: true },\n matrix: {}\n}\n\nexport interface BufferData {\n position?: Float32Array\n position1?: Float32Array // TODO\n color?: Float32Array\n index?: Uint32Array|Uint16Array\n normal?: Float32Array\n\n picking?: Picker\n primitiveId?: Float32Array\n}\n\n/**\n * Buffer class. Base class for buffers.\n * @interface\n */\nclass Buffer {\n parameterTypes = BufferParameterTypes\n get defaultParameters() { return BufferDefaultParameters }\n parameters: BufferParameters\n uniforms: Uniforms\n pickingUniforms: Uniforms\n\n private _positionDataSize: number\n\n geometry = new BufferGeometry()\n indexVersion = 0\n wireframeIndexVersion = -1\n group = new Group()\n wireframeGroup = new Group()\n pickingGroup = new Group()\n\n vertexShader = ''\n fragmentShader = ''\n isImpostor = false\n isText = false\n isSurface = false\n isPoint = false\n isLine = false\n dynamic = true\n visible = true\n\n picking?: Picker\n\n material: ShaderMaterial\n wireframeMaterial: ShaderMaterial\n pickingMaterial: ShaderMaterial\n\n wireframeIndex?: Uint32Array|Uint16Array\n wireframeIndexCount = 0\n wireframeGeometry?: BufferGeometry\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.color - colors\n * @param {Uint32Array|Uint16Array} data.index - triangle indices\n * @param {Picker} [data.picking] - picking ids\n * @param {BufferParameters} params - parameters object\n */\n constructor (data: BufferData, params: Partial = {}) {\n this.parameters = createParams(params, this.defaultParameters)\n\n this.uniforms = UniformsUtils.merge([\n UniformsLib.common,\n {\n fogColor: { value: new Color(0x000000) },\n fogNear: { value: 0.0 },\n fogFar: { value: 0.0 },\n opacity: { value: this.parameters.opacity },\n clipNear: { value: 0.0 },\n clipRadius: { value: this.parameters.clipRadius },\n clipCenter: { value: this.parameters.clipCenter }\n },\n {\n emissive: { value: new Color(0x000000) },\n roughness: { value: this.parameters.roughness },\n metalness: { value: this.parameters.metalness },\n interiorColor: { value: new Color(this.parameters.interiorColor) },\n interiorDarkening: { value: this.parameters.interiorDarkening },\n },\n UniformsLib.lights\n ])\n\n this.uniforms.diffuse.value.set(this.parameters.diffuse)\n\n this.pickingUniforms = {\n clipNear: { value: 0.0 },\n objectId: { value: 0 },\n opacity: { value: this.parameters.opacity }\n }\n\n //\n\n const position = data.position || data.position1\n this._positionDataSize = position ? position.length / 3 : 0\n\n if (!data.primitiveId) {\n data.primitiveId = serialArray(this._positionDataSize)\n }\n\n this.addAttributes({\n position: { type: 'v3', value: data.position },\n color: { type: 'c', value: data.color },\n primitiveId: { type: 'f', value: data.primitiveId }\n })\n\n if (params.matrix) {\n this.matrix = params.matrix\n }\n\n if (data.index) {\n this.initIndex(data.index)\n }\n this.picking = data.picking\n\n this.makeWireframeGeometry()\n }\n\n set matrix (m) {\n this.setMatrix(m)\n }\n get matrix () {\n return this.group.matrix.clone()\n }\n\n get transparent () {\n return this.parameters.opacity < 1 || this.parameters.forceTransparent\n }\n\n get size () {\n return this._positionDataSize\n }\n\n get attributeSize () {\n return this.size\n }\n\n get pickable () {\n return !!this.picking && !this.parameters.disablePicking\n }\n\n setMatrix (m: Matrix4) {\n setObjectMatrix(this.group, m)\n setObjectMatrix(this.wireframeGroup, m)\n setObjectMatrix(this.pickingGroup, m)\n }\n\n initIndex (index: Uint32Array|Uint16Array) {\n this.geometry.setIndex(\n new BufferAttribute(index, 1)\n )\n const nindex = this.geometry.getIndex();\n if (!nindex) { Log.error('Index is null'); return; }\n nindex.setUsage(this.dynamic ? WebGLRenderingContext.DYNAMIC_DRAW : 0)\n }\n\n makeMaterial () {\n const side = getThreeSide(this.parameters.side)\n\n const m = new ShaderMaterial({\n uniforms: this.uniforms,\n vertexShader: '',\n fragmentShader: '',\n depthTest: true,\n transparent: this.transparent,\n depthWrite: this.parameters.depthWrite,\n lights: true,\n fog: true,\n side: side\n })\n m.vertexColors = true\n m.extensions.derivatives = true\n m.extensions.fragDepth = this.isImpostor\n\n const wm = new ShaderMaterial({\n uniforms: this.uniforms,\n vertexShader: '',\n fragmentShader: '',\n depthTest: true,\n transparent: this.transparent,\n depthWrite: this.parameters.depthWrite,\n lights: false,\n fog: true,\n side: side\n })\n wm.vertexColors = true\n\n const pm = new ShaderMaterial({\n uniforms: this.pickingUniforms,\n vertexShader: '',\n fragmentShader: '',\n depthTest: true,\n transparent: false,\n depthWrite: this.parameters.depthWrite,\n lights: false,\n fog: false,\n side: side,\n blending: NoBlending\n })\n pm.vertexColors = true\n pm.extensions.fragDepth = this.isImpostor\n\n ;(m as any).clipNear = this.parameters.clipNear\n ;(wm as any).clipNear = this.parameters.clipNear\n ;(pm as any).clipNear = this.parameters.clipNear\n\n this.material = m\n this.wireframeMaterial = wm\n this.pickingMaterial = pm\n\n // also sets vertexShader/fragmentShader\n this.updateShader()\n }\n\n makeWireframeGeometry () {\n this.makeWireframeIndex()\n\n const geometry = this.geometry\n const wireframeIndex = this.wireframeIndex\n const wireframeGeometry = new BufferGeometry()\n\n wireframeGeometry.attributes = geometry.attributes\n if (wireframeIndex) {\n wireframeGeometry.setIndex(\n new BufferAttribute(wireframeIndex, 1).setUsage(this.dynamic ? WebGLRenderingContext.DYNAMIC_DRAW : 0)\n )\n wireframeGeometry.setDrawRange(0, this.wireframeIndexCount)\n }\n\n this.wireframeGeometry = wireframeGeometry\n }\n\n makeWireframeIndex () {\n const edges: number[][] = []\n\n function checkEdge (a: number, b: number) {\n if (a > b) {\n const tmp = a\n a = b\n b = tmp\n }\n\n const list = edges[ a ]\n\n if (list === undefined) {\n edges[ a ] = [ b ]\n return true\n } else if (!list.includes(b)) {\n list.push(b)\n return true\n }\n\n return false\n }\n\n const geometry = this.geometry\n const index = geometry.index\n\n if (!this.parameters.wireframe) {\n this.wireframeIndex = new Uint16Array(0)\n this.wireframeIndexCount = 0\n } else if (index) {\n const array = index.array\n let n = array.length\n if (geometry.drawRange.count !== Infinity) {\n n = geometry.drawRange.count\n }\n let wireframeIndex\n if (this.wireframeIndex && this.wireframeIndex.length > n * 2) {\n wireframeIndex = this.wireframeIndex\n } else {\n const count = (geometry.attributes as any).position.count // TODO\n wireframeIndex = getUintArray(n * 2, count)\n }\n\n let j = 0\n edges.length = 0\n\n for (let i = 0; i < n; i += 3) {\n const a = array[ i + 0 ]\n const b = array[ i + 1 ]\n const c = array[ i + 2 ]\n\n if (checkEdge(a, b)) {\n wireframeIndex[ j + 0 ] = a\n wireframeIndex[ j + 1 ] = b\n j += 2\n }\n if (checkEdge(b, c)) {\n wireframeIndex[ j + 0 ] = b\n wireframeIndex[ j + 1 ] = c\n j += 2\n }\n if (checkEdge(c, a)) {\n wireframeIndex[ j + 0 ] = c\n wireframeIndex[ j + 1 ] = a\n j += 2\n }\n }\n\n this.wireframeIndex = wireframeIndex\n this.wireframeIndexCount = j\n this.wireframeIndexVersion = this.indexVersion\n } else {\n const n = (geometry.attributes as any).position.count // TODO\n\n let wireframeIndex\n if (this.wireframeIndex && this.wireframeIndex.length > n * 2) {\n wireframeIndex = this.wireframeIndex\n } else {\n wireframeIndex = getUintArray(n * 2, n)\n }\n\n for (let i = 0, j = 0; i < n; i += 3) {\n wireframeIndex[ j + 0 ] = i\n wireframeIndex[ j + 1 ] = i + 1\n wireframeIndex[ j + 2 ] = i + 1\n wireframeIndex[ j + 3 ] = i + 2\n wireframeIndex[ j + 4 ] = i + 2\n wireframeIndex[ j + 5 ] = i\n\n j += 6\n }\n\n this.wireframeIndex = wireframeIndex\n this.wireframeIndexCount = n * 2\n this.wireframeIndexVersion = this.indexVersion\n }\n }\n\n updateWireframeIndex () {\n if (!this.wireframeGeometry || !this.wireframeIndex) return\n\n this.wireframeGeometry.setDrawRange(0, Infinity)\n if (this.wireframeIndexVersion < this.indexVersion) this.makeWireframeIndex()\n\n if (this.wireframeGeometry.index &&\n this.wireframeIndex.length > this.wireframeGeometry.index.array.length) {\n this.wireframeGeometry.setIndex(\n new BufferAttribute(this.wireframeIndex, 1).setUsage(this.dynamic ? WebGLRenderingContext.DYNAMIC_DRAW : 0)\n )\n } else {\n const index = this.wireframeGeometry.getIndex()\n if (!index) { Log.error('Index is null'); return; }\n index.set(this.wireframeIndex)\n index.needsUpdate = this.wireframeIndexCount > 0\n index.updateRange.count = this.wireframeIndexCount\n }\n\n this.wireframeGeometry.setDrawRange(0, this.wireframeIndexCount)\n }\n\n getRenderOrder () {\n let renderOrder = 0\n\n if (this.isText) {\n renderOrder = 1\n } else if (this.transparent) {\n if (this.isSurface) {\n renderOrder = 3\n } else {\n renderOrder = 2\n }\n }\n\n return renderOrder\n }\n\n _getMesh (materialName: BufferMaterials) {\n if (!this.material) this.makeMaterial()\n\n const g = this.geometry\n const m = this[ materialName ]\n\n let mesh\n\n if (this.isLine) {\n mesh = new LineSegments(g, m)\n } else if (this.isPoint) {\n mesh = new Points(g, m)\n } else {\n mesh = new Mesh(g, m)\n }\n\n mesh.frustumCulled = false\n mesh.renderOrder = this.getRenderOrder()\n\n return mesh\n }\n\n getMesh () {\n return this._getMesh('material')\n }\n\n getWireframeMesh () {\n let mesh\n\n if (!this.material) this.makeMaterial()\n if (!this.wireframeGeometry) this.makeWireframeGeometry()\n\n mesh = new LineSegments(\n this.wireframeGeometry, this.wireframeMaterial\n )\n\n mesh.frustumCulled = false\n mesh.renderOrder = this.getRenderOrder()\n\n return mesh\n }\n\n getPickingMesh () {\n return this._getMesh('pickingMaterial')\n }\n\n getShader (name: string, type?: BufferTypes) {\n return getShader(name, this.getDefines(type))\n }\n\n getVertexShader (type?: BufferTypes) {\n return this.getShader(this.vertexShader, type)\n }\n\n getFragmentShader (type?: BufferTypes) {\n return this.getShader(this.fragmentShader, type)\n }\n\n getDefines (type?: BufferTypes) {\n const defines: ShaderDefines = {}\n\n if (this.parameters.clipNear) {\n defines.NEAR_CLIP = 1\n }\n\n if (this.parameters.clipRadius) {\n defines.RADIUS_CLIP = 1\n }\n\n if (type === 'picking') {\n defines.PICKING = 1\n } else {\n if (type === 'background' || this.parameters.background) {\n defines.NOLIGHT = 1\n }\n if (this.parameters.flatShaded) {\n defines.FLAT_SHADED = 1\n }\n if (this.parameters.opaqueBack) {\n defines.OPAQUE_BACK = 1\n }\n if (this.parameters.diffuseInterior) {\n defines.DIFFUSE_INTERIOR = 1\n }\n if (this.parameters.useInteriorColor) {\n defines.USE_INTERIOR_COLOR = 1\n }\n }\n\n return defines\n }\n\n getParameters () {\n return this.parameters\n }\n\n addUniforms (uniforms: Uniforms) {\n this.uniforms = UniformsUtils.merge(\n [ this.uniforms, uniforms ]\n )\n\n this.pickingUniforms = UniformsUtils.merge(\n [ this.pickingUniforms, uniforms ]\n )\n }\n\n addAttributes (attributes: { [k: string]: _BufferAttribute }) {\n for (let name in attributes) {\n let buf\n const a = attributes[ name ]\n const arraySize = this.attributeSize * itemSize[ a.type ]\n\n if (a.value) {\n if (arraySize !== a.value.length) {\n Log.error('attribute value has wrong length', name)\n }\n buf = a.value\n } else {\n buf = getTypedArray('float32', arraySize)\n }\n\n this.geometry.setAttribute(\n name,\n new BufferAttribute(buf, itemSize[ a.type ]).setUsage(this.dynamic ? WebGLRenderingContext.DYNAMIC_DRAW : 0)\n )\n }\n }\n\n updateRenderOrder () {\n const renderOrder = this.getRenderOrder()\n function setRenderOrder (mesh: Object3D) {\n mesh.renderOrder = renderOrder\n }\n\n this.group.children.forEach(setRenderOrder)\n if (this.pickingGroup) {\n this.pickingGroup.children.forEach(setRenderOrder)\n }\n }\n\n updateShader () {\n const m = this.material\n const wm = this.wireframeMaterial\n const pm = this.pickingMaterial\n\n m.vertexShader = this.getVertexShader()\n m.fragmentShader = this.getFragmentShader()\n m.needsUpdate = true\n\n wm.vertexShader = this.getShader('Line.vert')\n wm.fragmentShader = this.getShader('Line.frag')\n wm.needsUpdate = true\n\n pm.vertexShader = this.getVertexShader('picking')\n pm.fragmentShader = this.getFragmentShader('picking')\n pm.needsUpdate = true\n }\n\n /**\n * Set buffer parameters\n * @param {BufferParameters} params - buffer parameters object\n * @return {undefined}\n */\n setParameters (params: Partial) {\n const p = params as any\n const pt = this.parameterTypes as any\n const pv = this.parameters as any\n\n const propertyData: { [k: string]: any } = {}\n const uniformData: { [k: string]: any } = {}\n let doShaderUpdate = false\n let doVisibilityUpdate = false\n\n for (const name in p) {\n const value = p[ name ]\n\n if (value === undefined) continue\n pv[ name ] = value\n\n if (pt[ name ] === undefined) continue\n\n if (pt[ name ].property) {\n if (pt[ name ].property !== true) {\n propertyData[ pt[ name ].property as any ] = value\n } else {\n propertyData[ name ] = value\n }\n }\n\n if (pt[ name ].uniform) {\n if (pt[ name ].uniform !== true) {\n uniformData[ pt[ name ].uniform as any ] = value\n } else {\n uniformData[ name ] = value\n }\n }\n\n if (pt[ name ].updateShader) {\n doShaderUpdate = true\n }\n\n if (pt[ name ].updateVisibility) {\n doVisibilityUpdate = true\n }\n\n if (this.dynamic && name === 'wireframe' && value === true) {\n this.updateWireframeIndex()\n }\n\n if (name === 'forceTransparent') {\n propertyData.transparent = this.transparent\n }\n\n if (name === 'matrix') {\n this.matrix = value\n }\n }\n\n this.setProperties(propertyData)\n this.setUniforms(uniformData)\n if (doShaderUpdate) this.updateShader()\n if (doVisibilityUpdate) this.setVisibility(this.visible)\n }\n\n /**\n * Sets buffer attributes\n * @param {Object} data - An object where the keys are the attribute names\n * and the values are the attribute data.\n * @example\n * var buffer = new Buffer();\n * buffer.setAttributes({ attrName: attrData });\n */\n setAttributes (data: any) { // TODO\n const geometry = this.geometry\n const attributes = geometry.attributes as any // TODO\n\n for (const name in data) {\n if (name === 'picking') continue\n\n const array = data[ name ]\n const length = array.length\n\n if (name === 'index') {\n const index = geometry.getIndex()\n if (!index) { Log.error('Index is null'); continue; }\n geometry.setDrawRange(0, Infinity)\n\n if (length > index.array.length) {\n geometry.setIndex(\n new BufferAttribute(array, 1)\n .setUsage(this.dynamic ? WebGLRenderingContext.DYNAMIC_DRAW : 0)\n )\n } else {\n index.set(array)\n index.count = length\n index.needsUpdate = length > 0\n index.updateRange.count = length\n geometry.setDrawRange(0, length)\n }\n\n this.indexVersion++\n if (this.parameters.wireframe) this.updateWireframeIndex()\n } else {\n const attribute = attributes[ name ]\n\n if (length > attribute.array.length) {\n geometry.setAttribute(\n name,\n new BufferAttribute(array, attribute.itemSize)\n .setUsage(this.dynamic ? WebGLRenderingContext.DYNAMIC_DRAW : 0)\n )\n } else {\n attributes[ name ].set(array)\n attributes[ name ].needsUpdate = length > 0\n attributes[ name ].updateRange.count = length\n }\n }\n }\n }\n\n setUniforms (data: any) { // TODO\n if (!data) return\n\n const u = this.material.uniforms\n const wu = this.wireframeMaterial.uniforms\n const pu = this.pickingMaterial.uniforms\n\n for (let name in data) {\n if (name === 'opacity') {\n this.setProperties({ transparent: this.transparent })\n }\n\n if (u[ name ] !== undefined) {\n if (u[ name ].value.isVector3) {\n u[ name ].value.copy(data[ name ])\n } else if (u[ name ].value.set) {\n u[ name ].value.set(data[ name ])\n } else {\n u[ name ].value = data[ name ]\n }\n }\n\n if (wu[ name ] !== undefined) {\n if (wu[ name ].value.isVector3) {\n wu[ name ].value.copy(data[ name ])\n } else if (wu[ name ].value.set) {\n wu[ name ].value.set(data[ name ])\n } else {\n wu[ name ].value = data[ name ]\n }\n }\n\n if (pu[ name ] !== undefined) {\n if (pu[ name ].value.isVector3) {\n pu[ name ].value.copy(data[ name ])\n } else if (pu[ name ].value.set) {\n pu[ name ].value.set(data[ name ])\n } else {\n pu[ name ].value = data[ name ]\n }\n }\n }\n }\n\n setProperties (data: any) { // TODO\n if (!data) return\n\n const m = this.material\n const wm = this.wireframeMaterial\n const pm = this.pickingMaterial\n\n for (const _name in data) {\n const name = _name as 'side'|'transparent' // TODO\n\n let value = data[ name ]\n\n if (name === 'transparent') {\n this.updateRenderOrder()\n } else if (name === 'side') {\n value = getThreeSide(value)\n }\n\n (m[ name ] as any) = value;\n (wm[ name ] as any) = value;\n (pm[ name ] as any) = value\n }\n\n m.needsUpdate = true\n wm.needsUpdate = true\n pm.needsUpdate = true\n }\n\n /**\n * Set buffer visibility\n * @param {Boolean} value - visibility value\n * @return {undefined}\n */\n setVisibility (value: boolean) {\n this.visible = value\n\n if (this.parameters.wireframe) {\n this.group.visible = false\n this.wireframeGroup.visible = value\n if (this.pickable) {\n this.pickingGroup.visible = false\n }\n } else {\n this.group.visible = value\n this.wireframeGroup.visible = false\n if (this.pickable) {\n this.pickingGroup.visible = value\n }\n }\n }\n\n /**\n * Free buffer resources\n * @return {undefined}\n */\n dispose () {\n if (this.material) this.material.dispose()\n if (this.wireframeMaterial) this.wireframeMaterial.dispose()\n if (this.pickingMaterial) this.pickingMaterial.dispose()\n\n this.geometry.dispose()\n if (this.wireframeGeometry) this.wireframeGeometry.dispose()\n }\n\n /**\n * Customize JSON serialization to avoid circular references\n */\n toJSON () {\n var result: any = {};\n for (var x in this) {\n if (x !== \"group\" && x !== \"wireframeGroup\" && x != \"pickingGroup\"\n && x !== \"picking\") {\n result[x] = this[x];\n }\n }\n return result;\n }\n}\n\nexport default Buffer\n","/**\n * @file Mesh Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport '../shader/Mesh.vert'\nimport '../shader/Mesh.frag'\n\nimport Buffer, { BufferParameters, BufferData } from './buffer'\n\n/**\n * Mesh buffer. Draws a triangle mesh.\n *\n * @example\n * var meshBuffer = new MeshBuffer({\n * position: new Float32Array(\n * [ 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1 ]\n * ),\n * color: new Float32Array(\n * [ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 ]\n * )\n * });\n */\nclass MeshBuffer extends Buffer {\n vertexShader = 'Mesh.vert'\n fragmentShader = 'Mesh.frag'\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} [data.index] - triangle indices\n * @param {Float32Array} [data.normal] - radii\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: BufferData, params: Partial = {}) {\n super(data, params)\n\n this.addAttributes({\n 'normal': { type: 'v3', value: data.normal }\n })\n\n if (data.normal === undefined) {\n this.geometry.computeVertexNormals()\n }\n }\n}\n\nexport default MeshBuffer\n","/**\n * @file Surface Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport MeshBuffer from './mesh-buffer'\n\n/**\n * Surface buffer. Like a {@link MeshBuffer}, but with `.isSurface` set to `true`.\n */\nclass SurfaceBuffer extends MeshBuffer {\n isSurface = true\n}\n\nexport default SurfaceBuffer\n","/**\n * @file Double Sided Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Vector3, Matrix4 required for declaration only\nimport { Group, BufferGeometry, Object3D, Mesh, LineSegments, Vector3, Matrix4 } from 'three'\n\nimport Buffer, { BufferSide } from './buffer'\nimport { Picker } from '../utils/picker'\n\nfunction setVisibilityTrue (m: Object3D) { m.visible = true }\nfunction setVisibilityFalse (m: Object3D) { m.visible = false }\n\n/**\n * A double-sided mesh buffer. Takes a buffer and renders the front and\n * the back as seperate objects to avoid some artifacts when rendering\n * transparent meshes. Also allows to render the back of a mesh opaque\n * while the front is transparent.\n * @implements {Buffer}\n *\n * @example\n * var sphereGeometryBuffer = new SphereGeometryBuffer({\n * position: new Float32Array([ 0, 0, 0 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * radius: new Float32Array([ 1 ])\n * });\n * var doubleSidedBuffer = new DoubleSidedBuffer(sphereGeometryBuffer);\n */\nclass DoubleSidedBuffer {\n size: number\n side: BufferSide\n visible: boolean\n wireframe: boolean\n geometry: BufferGeometry\n\n picking?: Picker\n\n group = new Group()\n wireframeGroup = new Group()\n pickingGroup = new Group()\n\n frontMeshes: (Mesh|LineSegments)[] = []\n backMeshes: (Mesh|LineSegments)[] = []\n\n buffer: Buffer\n frontBuffer: Buffer\n backBuffer: Buffer\n\n /**\n * Create a double sided buffer\n * @param {Buffer} buffer - the buffer to be rendered double-sided\n */\n constructor (buffer: Buffer) {\n this.size = buffer.size\n this.side = buffer.parameters.side\n this.visible = buffer.visible\n this.geometry = buffer.geometry\n this.picking = buffer.picking\n\n this.group = new Group()\n this.wireframeGroup = new Group()\n this.pickingGroup = new Group()\n\n // requires Group objects to be present\n this.matrix = buffer.matrix\n\n const frontBuffer = buffer\n const backBuffer = new (buffer as any).constructor({ // TODO\n position: new Float32Array(0)\n }) as Buffer\n\n frontBuffer.makeMaterial()\n backBuffer.makeMaterial()\n\n backBuffer.picking = buffer.picking\n backBuffer.geometry = buffer.geometry\n backBuffer.wireframeGeometry = buffer.wireframeGeometry\n backBuffer.setParameters(buffer.getParameters())\n backBuffer.updateShader()\n\n frontBuffer.setParameters({\n side: 'front'\n })\n backBuffer.setParameters({\n side: 'back',\n opacity: backBuffer.parameters.opacity\n })\n\n this.buffer = buffer\n this.frontBuffer = frontBuffer\n this.backBuffer = backBuffer\n }\n\n set matrix (m) {\n Buffer.prototype.setMatrix.call(this, m)\n }\n get matrix () {\n return this.group.matrix.clone()\n }\n\n get pickable () {\n return !!this.picking && !this.parameters.disablePicking\n }\n\n get parameters () {\n return this.buffer.parameters\n }\n\n getParameters () {\n const p = Object.assign({}, this.buffer.parameters)\n p.side = this.side\n return p\n }\n\n getMesh (picking: boolean) {\n let front, back\n\n if (picking) {\n back = this.backBuffer.getPickingMesh()\n front = this.frontBuffer.getPickingMesh()\n } else {\n back = this.backBuffer.getMesh()\n front = this.frontBuffer.getMesh()\n }\n\n this.frontMeshes.push(front)\n this.backMeshes.push(back)\n\n this.setParameters({ side: this.side })\n\n return new Group().add(back, front)\n }\n\n getWireframeMesh () {\n return this.buffer.getWireframeMesh()\n }\n\n getPickingMesh () {\n return this.getMesh(true)\n }\n\n setAttributes (data: any) { // TODO\n this.buffer.setAttributes(data)\n }\n\n setParameters (data: any) { // TODO\n data = Object.assign({}, data)\n\n if (data.side === 'front') {\n this.frontMeshes.forEach(setVisibilityTrue)\n this.backMeshes.forEach(setVisibilityFalse)\n } else if (data.side === 'back') {\n this.frontMeshes.forEach(setVisibilityFalse)\n this.backMeshes.forEach(setVisibilityTrue)\n } else if (data.side === 'double') {\n this.frontMeshes.forEach(setVisibilityTrue)\n this.backMeshes.forEach(setVisibilityTrue)\n }\n\n if (data.side !== undefined) {\n this.side = data.side\n }\n delete data.side\n\n if (data.matrix !== undefined) {\n this.matrix = data.matrix\n }\n delete data.matrix\n\n this.frontBuffer.setParameters(data)\n\n if (data.wireframe !== undefined) {\n this.wireframe = data.wireframe\n this.setVisibility(this.visible)\n }\n delete data.wireframe\n\n this.backBuffer.setParameters(data)\n }\n\n setVisibility (value: boolean) {\n this.visible = value\n\n if (this.parameters.wireframe) {\n this.group.visible = false\n this.wireframeGroup.visible = value\n if (this.pickable) {\n this.pickingGroup.visible = false\n }\n } else {\n this.group.visible = value\n this.wireframeGroup.visible = false\n if (this.pickable) {\n this.pickingGroup.visible = value\n }\n }\n }\n\n dispose () {\n this.frontBuffer.dispose()\n this.backBuffer.dispose()\n }\n\n /**\n * Customize JSON serialization to avoid circular references.\n * Only export simple params which could be useful.\n */\n toJSON () {\n var result: any = {};\n for (var x in this) {\n if (['side', 'size', 'visible', 'matrix', 'parameters'].includes(x)) {\n result[x] = this[x];\n }\n }\n return result;\n }\n}\n\nexport default DoubleSidedBuffer\n","/**\n * @file Contour Buffer\n * @author Fred ludlow \n * @private\n */\n\nimport '../shader/Line.vert'\nimport '../shader/Line.frag'\n\nimport Buffer from './buffer'\n\n/**\n * Contour buffer. A buffer that draws lines (instead of triangle meshes).\n */\nclass ContourBuffer extends Buffer {\n isLine = true\n vertexShader = 'Line.vert'\n fragmentShader = 'Line.frag'\n}\n\nexport default ContourBuffer\n","/**\n * @file Surface Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4, Vector3, Box3 } from 'three'\n\nimport { defaults } from '../utils'\nimport Representation, { RepresentationParameters } from './representation'\nimport Volume from '../surface/volume'\nimport SurfaceBuffer from '../buffer/surface-buffer'\nimport DoubleSidedBuffer from '../buffer/doublesided-buffer'\nimport ContourBuffer from '../buffer/contour-buffer'\nimport Surface from '../surface/surface';\nimport Viewer from '../viewer/viewer';\nimport {SurfaceData} from '../surface/surface'\n// @ts-ignore: unused import ColormakerParameters required for declaration only\nimport { ColormakerParameters } from '../color/colormaker';\nexport type SurfaceDataFields = {position: boolean, color: boolean, index: boolean, normal: boolean, radius: boolean}\n\n/**\n * Surface representation parameter object. Extends {@link RepresentationParameters}\n *\n * @typedef {Object} SurfaceRepresentationParameters - surface representation parameters\n *\n * @property {String} isolevelType - Meaning of the isolevel value. Either *value* for the literal value or *sigma* as a factor of the sigma of the data. For volume data only.\n * @property {Float} isolevel - The value at which to create the isosurface. For volume data only.\n * @property {Boolean} negateIsolevel - For volume data only.\n * @property {Boolean} isolevelScroll - For volume data only\n * @property {Integer} smooth - How many iterations of laplacian smoothing after surface triangulation. For volume data only.\n * @property {Boolean} background - Render the surface in the background, unlit.\n * @property {Boolean} opaqueBack - Render the back-faces (where normals point away from the camera) of the surface opaque, ignoring the transparency parameter.\n * @property {Integer} boxSize - Size of the box to triangulate volume data in. Set to zero to triangulate the whole volume. For volume data only.\n * @property {Boolean} useWorker - Weather or not to triangulate the volume asynchronously in a Web Worker. For volume data only.\n * @property {Boolean} wrap - Wrap volume data around the edges; use in conjuction with boxSize but not larger than the volume dimension. For volume data only.\n */\nexport interface SurfaceRepresentationParameters extends RepresentationParameters {\n isolevelType: 'value'|'sigma'\n isolevel: number\n smooth: number\n background: boolean\n opaqueBack: boolean\n boxSize: number\n useWorker: boolean\n wrap: boolean\n}\n/**\n * Surface representation\n */\n/**\n * Create Surface representation object\n * @param {Surface|Volume} surface - the surface or volume to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {SurfaceRepresentationParameters} params - surface representation parameters\n */\nclass SurfaceRepresentation extends Representation {\n protected surface: Surface|Volume|undefined\n protected volume: Volume|undefined\n protected boxCenter: Vector3\n protected __boxCenter: Vector3\n protected box: Box3\n protected __box: Box3\n protected _position: Vector3\n protected isolevelType: 'value'|'sigma'\n protected isolevel: number\n protected negateIsolevel: boolean\n protected isolevelScroll: boolean\n protected smooth: number\n protected background: boolean\n protected opaqueBack: boolean\n protected boxSize: number\n protected inverseMatrix: Matrix4\n protected colorVolume: Volume\n protected contour: boolean\n protected useWorker: boolean\n protected wrap: boolean\n\n protected __isolevel: number\n protected __smooth: number\n protected __contour: boolean\n protected __wrap: boolean\n protected __boxSize: number\n\n setBox: () => void\n\n constructor (surface: Surface, viewer: Viewer, params: Partial) {\n super(surface, viewer, params)\n\n this.type = 'surface'\n\n this.parameters = Object.assign({\n\n isolevelType: {\n type: 'select',\n options: {\n 'value': 'value', 'sigma': 'sigma'\n }\n },\n isolevel: {\n type: 'number', precision: 2, max: 1000, min: -1000\n },\n negateIsolevel: {\n type: 'boolean'\n },\n isolevelScroll: {\n type: 'boolean'\n },\n smooth: {\n type: 'integer', precision: 1, max: 10, min: 0\n },\n background: {\n type: 'boolean', rebuild: true // FIXME\n },\n opaqueBack: {\n type: 'boolean', buffer: true\n },\n boxSize: {\n type: 'integer', precision: 1, max: 100, min: 0\n },\n colorVolume: {\n type: 'hidden'\n },\n contour: {\n type: 'boolean', rebuild: true\n },\n useWorker: {\n type: 'boolean', rebuild: true\n },\n wrap: {\n type: 'boolean', rebuild: true\n }\n\n }, this.parameters)\n\n if (surface instanceof Volume) {\n this.surface = undefined\n this.volume = surface\n } else {\n this.surface = surface\n this.volume = undefined\n }\n\n this.boxCenter = new Vector3()\n this.__boxCenter = new Vector3()\n this.box = new Box3()\n this.__box = new Box3()\n\n this._position = new Vector3()\n this.inverseMatrix = new Matrix4()\n\n this.setBox = function setBox () {\n this._position.copy(viewer.translationGroup.position).negate()\n this._position.applyMatrix4(this.inverseMatrix)\n if (!this._position.equals(this.boxCenter)) {\n this.setParameters({ 'boxCenter': this._position })\n }\n }\n\n this.toBePrepared = true\n\n this.viewer.signals.ticked.add(this.setBox, this)\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n p.colorScheme = defaults(p.colorScheme, 'uniform')\n p.colorValue = defaults(p.colorValue, 0xDDDDDD)\n\n this.isolevelType = defaults(p.isolevelType, 'sigma')\n this.isolevel = defaults(p.isolevel, 2.0)\n this.negateIsolevel = defaults(p.negateIsolevel, false)\n this.isolevelScroll = defaults(p.isolevelScroll, false)\n this.smooth = defaults(p.smooth, 0)\n this.background = defaults(p.background, false)\n this.opaqueBack = defaults(p.opaqueBack, true)\n this.boxSize = defaults(p.boxSize, 0)\n this.colorVolume = defaults(p.colorVolume, undefined)\n this.contour = defaults(p.contour, false)\n this.useWorker = defaults(p.useWorker, true)\n this.wrap = defaults(p.wrap, false)\n\n super.init(p)\n\n this.inverseMatrix.getInverse(this.matrix)\n\n this.build()\n }\n\n attach (callback: () => void) {\n this.bufferList.forEach(buffer => {\n this.viewer.add(buffer)\n })\n\n this.setVisibility(this.visible)\n\n callback()\n }\n\n prepare (callback: () => void) {\n if (this.volume) {\n let isolevel\n\n if (this.isolevelType === 'sigma') {\n isolevel = this.volume.getValueForSigma(this.isolevel)\n } else {\n isolevel = this.isolevel\n }\n if (this.negateIsolevel) isolevel *= -1\n\n if (!this.surface ||\n this.__isolevel !== isolevel ||\n this.__smooth !== this.smooth ||\n this.__contour !== this.contour ||\n this.__wrap !== this.wrap ||\n this.__boxSize !== this.boxSize ||\n (this.boxSize > 0 &&\n !this.__boxCenter.equals(this.boxCenter))\n ) {\n this.__isolevel = isolevel\n this.__smooth = this.smooth\n this.__contour = this.contour\n this.__wrap = this.wrap\n this.__boxSize = this.boxSize\n this.__boxCenter.copy(this.boxCenter)\n this.__box.copy(this.box)\n\n const onSurfaceFinish = (surface: Surface) => {\n this.surface = surface\n callback()\n }\n\n if (this.useWorker) {\n this.volume.getSurfaceWorker(\n isolevel, this.smooth, this.boxCenter, this.boxSize,\n this.contour, this.wrap, onSurfaceFinish\n )\n } else {\n onSurfaceFinish(\n this.volume.getSurface(\n isolevel, this.smooth, this.boxCenter, this.boxSize,\n this.contour, this.wrap\n )\n )\n }\n } else {\n callback()\n }\n } else {\n callback()\n }\n }\n\n create () {\n const sd = {\n position: (this.surface as Surface).getPosition(),\n color: (this.surface as Surface).getColor(this.getColorParams()),\n index: (this.surface as Surface).getIndex()\n }\n\n let buffer\n\n if (this.contour) {\n buffer = new ContourBuffer(\n sd,\n this.getBufferParams({ wireframe: false })\n )\n } else {\n Object.assign(sd, {\n normal: (this.surface as Surface).getNormal(),\n picking: (this.surface as Surface).getPicking()\n })\n\n const surfaceBuffer = new SurfaceBuffer(\n sd,\n this.getBufferParams({\n background: this.background,\n opaqueBack: this.opaqueBack,\n dullInterior: false\n })\n )\n\n buffer = new DoubleSidedBuffer(surfaceBuffer)\n }\n\n this.bufferList.push(buffer as ContourBuffer)\n }\n\n update (what: SurfaceDataFields) {\n if (this.bufferList.length === 0) return\n\n what = what || {}\n\n const surfaceData: Partial = {}\n\n if (what.position) {\n surfaceData.position = (this.surface as Surface).getPosition()\n }\n\n if (what.color) {\n surfaceData.color = (this.surface as Surface).getColor(\n this.getColorParams()\n )\n }\n\n if (what.index) {\n surfaceData.index = (this.surface as Surface).getIndex()\n }\n\n if (what.normal) {\n surfaceData.normal = (this.surface as Surface).getNormal()\n }\n\n this.bufferList.forEach(function (buffer) {\n buffer.setAttributes(surfaceData)\n })\n }\n\n /**\n * Set representation parameters\n * @alias SurfaceRepresentation#setParameters\n * @param {SurfaceRepresentationParameters} params - surface parameter object\n * @param {Object} [what] - buffer data attributes to be updated,\n * note that this needs to be implemented in the\n * derived classes. Generally it allows more\n * fine-grained control over updating than\n * forcing a rebuild.\n * @param {Boolean} what.position - update position data\n * @param {Boolean} what.color - update color data\n * @param {Boolean} [rebuild] - whether or not to rebuild the representation\n * @return {SurfaceRepresentation} this object\n */\n setParameters (params: Partial, what?: SurfaceDataFields, rebuild?: boolean) {\n if (params && params.isolevelType !== undefined &&\n this.volume\n ) {\n if (this.isolevelType === 'value' &&\n params.isolevelType === 'sigma'\n ) {\n this.isolevel = this.volume.getSigmaForValue(this.isolevel)\n } else if (this.isolevelType === 'sigma' &&\n params.isolevelType === 'value'\n ) {\n this.isolevel = this.volume.getValueForSigma(this.isolevel)\n }\n\n this.isolevelType = params.isolevelType\n }\n\n if (params && params.boxCenter) {\n this.boxCenter.copy(params.boxCenter)\n delete params.boxCenter\n }\n\n // Forbid wireframe && contour as in molsurface\n if (params && params.wireframe && (\n params.contour || (params.contour === undefined && this.contour)\n )) {\n params.wireframe = false\n }\n\n super.setParameters(params, what, rebuild)\n\n if (params.matrix) {\n this.inverseMatrix.getInverse(params.matrix)\n }\n\n if (this.volume) {\n this.volume.getBox(this.boxCenter, this.boxSize, this.box)\n }\n\n if (params && params.colorVolume !== undefined) {\n if (what) what.color = true\n }\n\n if (this.surface && (\n params.isolevel !== undefined ||\n params.negateIsolevel !== undefined ||\n params.smooth !== undefined ||\n params.wrap !== undefined ||\n params.boxSize !== undefined ||\n (this.boxSize > 0 &&\n !this.__box.equals(this.box))\n )) {\n this.build({\n 'position': true,\n 'color': true,\n 'index': true,\n 'normal': !this.contour\n })\n }\n\n return this\n }\n\n getColorParams () {\n const p = super.getColorParams()\n\n p.volume = this.colorVolume\n\n return p\n }\n\n dispose () {\n this.viewer.signals.ticked.remove(this.setBox, this)\n\n super.dispose()\n }\n}\n\nexport default SurfaceRepresentation\n","/**\n * @file Mouse Actions\n * @author Alexander Rose \n * @private\n */\n\nimport PickingProxy from './picking-proxy'\nimport { almostIdentity } from '../math/math-utils'\nimport Stage from '../stage/stage'\nimport StructureComponent from '../component/structure-component'\nimport SurfaceRepresentation from '../representation/surface-representation'\n\nexport type ScrollCallback = (stage: Stage, delta: number) => void\nexport type DragCallback = (stage: Stage, dx: number, dy: number) => void\nexport type PickCallback = (stage: Stage, pickingProxy: PickingProxy) => void\nexport type MouseActionCallback = ScrollCallback | DragCallback | PickCallback\n\n/**\n * Mouse actions provided as static methods\n */\nclass MouseActions {\n /**\n * Zoom scene based on scroll-delta\n * @param {Stage} stage - the stage\n * @param {Number} delta - amount to zoom\n * @return {undefined}\n */\n static zoomScroll (stage: Stage, delta: number) {\n stage.trackballControls.zoom(delta)\n }\n\n /**\n * Move near clipping plane based on scroll-delta\n * @param {Stage} stage - the stage\n * @param {Number} delta - amount to move clipping plane\n * @return {undefined}\n */\n static clipNearScroll (stage: Stage, delta: number) {\n const sp = stage.getParameters()\n stage.setParameters({ clipNear: sp.clipNear + delta / 10 })\n }\n\n /**\n * Move clipping planes based on scroll-delta.\n * @param {Stage} stage - the stage\n * @param {Number} delta - direction to move planes\n * @return {undefined}\n */\n static focusScroll (stage: Stage, delta: number) {\n const focus = stage.getFocus()\n const sign = Math.sign(delta)\n const step = sign * almostIdentity((100 - focus) / 10, 5, 0.2)\n stage.setFocus(focus + step)\n }\n\n /**\n * Zoom scene based on scroll-delta and\n * move focus planes based on camera position (zoom)\n * @param {Stage} stage - the stage\n * @param {Number} delta - amount to move focus planes and zoom\n * @return {undefined}\n */\n static zoomFocusScroll (stage: Stage, delta: number) {\n stage.trackballControls.zoom(delta)\n const z = stage.viewer.camera.position.z\n stage.setFocus(100 - Math.abs(z / 8))\n }\n\n /**\n * Change isolevel of volume surfaces based on scroll-delta\n * @param {Stage} stage - the stage\n * @param {Number} delta - amount to change isolevel\n * @return {undefined}\n */\n static isolevelScroll (stage: Stage, delta: number) {\n const d = Math.sign(delta) / 10\n stage.eachRepresentation((reprElem, comp) => {\n if (reprElem.repr instanceof SurfaceRepresentation) {\n const p = reprElem.getParameters() as any // TODO\n if (p.isolevelScroll) {\n reprElem.setParameters({ isolevel: p.isolevel + d })\n }\n }\n })\n }\n\n /**\n * Pan scene based on mouse coordinate changes\n * @param {Stage} stage - the stage\n * @param {Number} dx - amount to pan in x direction\n * @param {Number} dy - amount to pan in y direction\n * @return {undefined}\n */\n static panDrag (stage: Stage, dx: number, dy: number) {\n stage.trackballControls.pan(dx, dy)\n }\n\n /**\n * Rotate scene based on mouse coordinate changes\n * @param {Stage} stage - the stage\n * @param {Number} dx - amount to rotate in x direction\n * @param {Number} dy - amount to rotate in y direction\n * @return {undefined}\n */\n static rotateDrag (stage: Stage, dx: number, dy: number) {\n stage.trackballControls.rotate(dx, dy)\n }\n\n /**\n * Rotate scene around z axis based on mouse coordinate changes\n * @param {Stage} stage - the stage\n * @param {Number} dx - amount to rotate in x direction\n * @param {Number} dy - amount to rotate in y direction\n * @return {undefined}\n */\n static zRotateDrag (stage: Stage, dx: number, dy: number) {\n stage.trackballControls.zRotate(dx, dy)\n }\n\n /**\n * Zoom scene based on mouse coordinate changes\n * @param {Stage} stage - the stage\n * @param {Number} dx - amount to zoom\n * @param {Number} dy - amount to zoom\n * @return {undefined}\n */\n static zoomDrag (stage: Stage, dx: number, dy: number) {\n stage.trackballControls.zoom((dx + dy) / -2)\n }\n\n /**\n * Zoom scene based on mouse coordinate changes and\n * move focus planes based on camera position (zoom)\n * @param {Stage} stage - the stage\n * @param {Number} dx - amount to zoom and focus\n * @param {Number} dy - amount to zoom and focus\n * @return {undefined}\n */\n static zoomFocusDrag (stage: Stage, dx: number, dy: number) {\n stage.trackballControls.zoom((dx + dy) / -2)\n const z = stage.viewer.camera.position.z\n stage.setFocus(100 - Math.abs(z / 8))\n }\n\n /**\n * Pan picked component based on mouse coordinate changes\n * @param {Stage} stage - the stage\n * @param {Number} dx - amount to pan in x direction\n * @param {Number} dy - amount to pan in y direction\n * @return {undefined}\n */\n static panComponentDrag (stage: Stage, dx: number, dy: number) {\n stage.trackballControls.panComponent(dx, dy)\n }\n\n /**\n * Pan picked atom based on mouse coordinate changes\n * @param {Stage} stage - the stage\n * @param {Number} dx - amount to pan in x direction\n * @param {Number} dy - amount to pan in y direction\n * @return {undefined}\n */\n static panAtomDrag (stage: Stage, dx: number, dy: number) {\n stage.trackballControls.panAtom(dx, dy)\n }\n\n /**\n * Rotate picked component based on mouse coordinate changes\n * @param {Stage} stage - the stage\n * @param {Number} dx - amount to rotate in x direction\n * @param {Number} dy - amount to rotate in y direction\n * @return {undefined}\n */\n static rotateComponentDrag (stage: Stage, dx: number, dy: number) {\n stage.trackballControls.rotateComponent(dx, dy)\n }\n\n /**\n * Move picked element to the center of the screen\n * @param {Stage} stage - the stage\n * @param {PickingProxy} pickingProxy - the picking data object\n * @return {undefined}\n */\n static movePick (stage: Stage, pickingProxy: PickingProxy) {\n if (pickingProxy) {\n stage.animationControls.move(pickingProxy.position.clone())\n }\n }\n\n /**\n * Show tooltip with information of picked element\n * @param {Stage} stage - the stage\n * @param {PickingProxy} pickingProxy - the picking data object\n * @return {undefined}\n */\n static tooltipPick (stage: Stage, pickingProxy: PickingProxy) {\n const tt = stage.tooltip\n const sp = stage.getParameters() as any\n if (sp.tooltip && pickingProxy) {\n const mp = pickingProxy.mouse.position\n tt.innerText = pickingProxy.getLabel()\n tt.style.bottom = (window.innerHeight - mp.y + 3) + 'px'\n tt.style.left = (mp.x + 3) + 'px'\n tt.style.display = 'block'\n } else {\n tt.style.display = 'none'\n }\n }\n\n static measurePick (stage: Stage, pickingProxy: PickingProxy) {\n if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) {\n const atom = pickingProxy.atom || pickingProxy.closestBondAtom\n const sc = pickingProxy.component as StructureComponent\n sc.measurePick(atom)\n } else {\n stage.measureClear()\n }\n }\n}\n\ntype MouseActionPreset = [ string, MouseActionCallback ][]\nexport const MouseActionPresets = {\n default: [\n [ 'scroll', MouseActions.zoomScroll ],\n [ 'scroll-shift', MouseActions.focusScroll ],\n [ 'scroll-ctrl', MouseActions.isolevelScroll ],\n [ 'scroll-shift-ctrl', MouseActions.zoomFocusScroll ],\n\n [ 'drag-left', MouseActions.rotateDrag ],\n [ 'drag-right', MouseActions.panDrag ],\n [ 'drag-ctrl-left', MouseActions.panDrag ],\n [ 'drag-ctrl-right', MouseActions.zRotateDrag ],\n [ 'drag-shift-left', MouseActions.zoomDrag ],\n [ 'drag-middle', MouseActions.zoomFocusDrag ],\n\n [ 'drag-ctrl-shift-right', MouseActions.panComponentDrag ],\n [ 'drag-ctrl-shift-left', MouseActions.rotateComponentDrag ],\n\n [ 'clickPick-right', MouseActions.measurePick ],\n [ 'clickPick-ctrl-left', MouseActions.measurePick ],\n [ 'clickPick-middle', MouseActions.movePick ],\n [ 'clickPick-left', MouseActions.movePick ],\n [ 'hoverPick', MouseActions.tooltipPick ]\n ] as MouseActionPreset,\n pymol: [\n [ 'drag-left', MouseActions.rotateDrag ],\n [ 'drag-middle', MouseActions.panDrag ],\n [ 'drag-right', MouseActions.zoomDrag ],\n [ 'scroll', MouseActions.focusScroll ],\n [ 'drag-shift-right', MouseActions.focusScroll ],\n\n [ 'clickPick-ctrl+shift-middle', MouseActions.movePick ],\n [ 'hoverPick', MouseActions.tooltipPick ]\n ] as MouseActionPreset,\n coot: [\n [ 'scroll', MouseActions.isolevelScroll ],\n\n [ 'drag-left', MouseActions.rotateDrag ],\n [ 'drag-middle', MouseActions.panDrag ],\n [ 'drag-ctrl-left', MouseActions.panDrag ],\n [ 'drag-right', MouseActions.zoomFocusDrag ],\n [ 'drag-ctrl-right', MouseActions.focusScroll ],\n\n [ 'clickPick-middle', MouseActions.movePick ],\n [ 'hoverPick', MouseActions.tooltipPick ]\n ] as MouseActionPreset,\n astexviewer: [\n [ 'drag-left', MouseActions.rotateDrag ],\n [ 'drag-ctrl-left', MouseActions.panDrag ],\n [ 'drag-shift-left', MouseActions.zoomDrag ],\n [ 'scroll', MouseActions.focusScroll ],\n [ 'clickPick-middle', MouseActions.movePick ],\n [ 'hoverPick', MouseActions.tooltipPick ]\n ] as MouseActionPreset\n}\n\nexport default MouseActions\n","/**\n * @file Mouse Controls\n * @author Alexander Rose \n * @private\n */\n\nimport { MouseActionPresets, MouseActionCallback } from './mouse-actions'\nimport Stage from '../stage/stage'\nimport MouseObserver from '../stage/mouse-observer'\n\nexport type MouseControlPreset = keyof typeof MouseActionPresets\nexport interface MouseControlsParams {\n preset?: MouseControlPreset\n disabled?: boolean\n}\n\nexport type MouseActionType = ''|'scroll'|'drag'|'click'|'doubleClick'|'hover'|'clickPick'|'hoverPick'\nexport interface MouseAction {\n type: MouseActionType\n key: number\n button: number\n callback: MouseActionCallback\n}\n\n/**\n * Strings to describe mouse events (including optional keyboard modifiers).\n * Must contain an event type: \"scroll\", \"drag\", \"click\", \"doubleClick\",\n * \"hover\", \"clickPick\" or \"hoverPick\". Optionally contain one or more\n * (seperated by plus signs) keyboard modifiers: \"alt\", \"ctrl\", \"meta\" or\n * \"shift\". Can contain the mouse button performing the event: \"left\",\n * \"middle\" or \"right\". The type, key and button parts must be seperated by\n * dashes.\n *\n * @example\n * // triggered on scroll event (no key or button)\n * \"scroll\"\n *\n * @example\n * // triggered on scroll event while shift key is pressed\n * \"scroll-shift\"\n *\n * @example\n * // triggered on drag event with left mouse button\n * \"drag-left\"\n *\n * @example\n * // triggered on drag event with right mouse button\n * // while ctrl and shift keys are pressed\n * \"drag-right-ctrl+shift\"\n *\n * @typedef {String} TriggerString\n */\n\n/**\n * Get event type, key and button\n * @param {TriggerString} str - input trigger string\n * @return {Array} event type, key and button\n */\nfunction triggerFromString (str: string) {\n const tokens = str.split(/[-+]/)\n\n let type = ''\n if (tokens.includes('scroll')) type = 'scroll'\n if (tokens.includes('drag')) type = 'drag'\n if (tokens.includes('click')) type = 'click'\n if (tokens.includes('doubleClick')) type = 'doubleClick'\n if (tokens.includes('hover')) type = 'hover'\n if (tokens.includes('clickPick')) type = 'clickPick'\n if (tokens.includes('hoverPick')) type = 'hoverPick'\n\n let key = 0\n if (tokens.includes('alt')) key += 1\n if (tokens.includes('ctrl')) key += 2\n if (tokens.includes('meta')) key += 4\n if (tokens.includes('shift')) key += 8\n\n let button = 0\n if (tokens.includes('left')) button += 1\n if (tokens.includes('right')) button += 2\n if (tokens.includes('middle')) button += 4\n\n return [ type, key, button ] as [ MouseActionType, number, number ]\n}\n\n/**\n * Mouse controls\n */\nclass MouseControls {\n actionList: MouseAction[] = []\n mouse: MouseObserver\n\n disabled: boolean // Flag to disable all actions\n\n /**\n * @param {Stage} stage - the stage object\n * @param {Object} [params] - the parameters\n * @param {String} params.preset - one of \"default\", \"pymol\", \"coot\"\n * @param {String} params.disabled - flag to disable all actions\n */\n constructor (readonly stage: Stage, params: MouseControlsParams = {}) {\n this.mouse = stage.mouseObserver\n this.disabled = params.disabled || false\n this.preset(params.preset || 'default')\n }\n\n run (type: MouseActionType, ...args: any[]) {\n if (this.disabled) return\n\n const key = this.mouse.key || 0\n const button = this.mouse.buttons || 0\n\n this.actionList.forEach(a => {\n if (a.type === type && a.key === key && a.button === button) {\n (a.callback as any)(this.stage, ...args) // TODO\n }\n })\n }\n\n /**\n * Add a new mouse action triggered by an event, key and button combination.\n * The {@link MouseActions} class provides a number of static methods for\n * use as callback functions.\n *\n * @example\n * // change ambient light intensity on mouse scroll\n * // while the ctrl and shift keys are pressed\n * stage.mouseControls.add( \"scroll-ctrl+shift\", function( stage, delta ){\n * var ai = stage.getParameters().ambientIntensity;\n * stage.setParameters( { ambientIntensity: Math.max( 0, ai + delta / 50 ) } );\n * } );\n *\n * @example\n * // Call the MouseActions.zoomDrag method on mouse drag events\n * // with left and right mouse buttons simultaneous\n * stage.mouseControls.add( \"drag-left+right\", MouseActions.zoomDrag );\n *\n * @param {TriggerString} triggerStr - the trigger for the action\n * @param {function(stage: Stage, ...args: Any)} callback - the callback function for the action\n * @return {undefined}\n */\n add (triggerStr: string, callback: MouseActionCallback) {\n const [ type, key, button ] = triggerFromString(triggerStr)\n\n this.actionList.push({ type, key, button, callback })\n }\n\n /**\n * Remove a mouse action. The trigger string can contain an asterix (*)\n * as a wildcard for any key or mouse button. When the callback function\n * is given, only actions that call that function are removed.\n *\n * @example\n * // remove actions triggered solely by a scroll event\n * stage.mouseControls.remove( \"scroll\" );\n *\n * @example\n * // remove actions triggered by a scroll event, including\n * // those requiring a key pressed or mouse button used\n * stage.mouseControls.remove( \"scroll-*\" );\n *\n * @example\n * // remove actions triggered by a scroll event\n * // while the shift key is pressed\n * stage.mouseControls.remove( \"scroll-shift\" );\n *\n * @param {TriggerString} triggerStr - the trigger for the action\n * @param {Function} [callback] - the callback function for the action\n * @return {undefined}\n */\n remove (triggerStr: string, callback?: MouseActionCallback) {\n const wildcard = triggerStr.includes('*')\n const [ type, key, button ] = triggerFromString(triggerStr)\n\n const actionList = this.actionList.filter(function (a) {\n return !(\n (a.type === type || (wildcard && type === '')) &&\n (a.key === key || (wildcard && key === 0)) &&\n (a.button === button || (wildcard && button === 0)) &&\n (a.callback === callback || callback === undefined)\n )\n })\n\n this.actionList = actionList\n }\n\n /**\n * Set mouse action preset\n * @param {String} name - one of \"default\", \"pymol\", \"coot\"\n * @return {undefined}\n */\n preset (name: MouseControlPreset) {\n this.clear()\n\n const list = MouseActionPresets[ name ] || []\n\n list.forEach(action => this.add(action[0], action[1]))\n }\n\n /**\n * Remove all mouse actions\n * @return {undefined}\n */\n clear () {\n this.actionList.length = 0\n }\n}\n\nexport default MouseControls\n","/**\n * @file Key Actions\n * @author Alexander Rose \n * @private\n */\n\nimport Stage from '../stage/stage'\n\nexport type KeyActionCallback = (stage: Stage) => void\n\n/**\n * Key actions provided as static methods\n */\nclass KeyActions {\n /**\n * Stage auto view\n */\n static autoView (stage: Stage) {\n stage.autoView(1000)\n }\n\n /**\n * Toggle stage animations\n */\n static toggleAnimations (stage: Stage) {\n stage.animationControls.toggle()\n }\n\n /**\n * Toggle stage rocking\n */\n static toggleRock (stage: Stage) {\n stage.toggleRock()\n }\n\n /**\n * Toggle stage spinning\n */\n static toggleSpin (stage: Stage) {\n stage.toggleSpin()\n }\n\n /**\n * Toggle anti-aliasing\n */\n static toggleAntialiasing (stage: Stage) {\n const p = stage.getParameters()\n stage.setParameters({ sampleLevel: p.sampleLevel === -1 ? 0 : -1 })\n }\n}\n\ntype KeyActionPreset = [ string, KeyActionCallback ][]\nexport const KeyActionPresets = {\n default: [\n [ 'i', KeyActions.toggleSpin ],\n [ 'k', KeyActions.toggleRock ],\n [ 'p', KeyActions.toggleAnimations ],\n [ 'a', KeyActions.toggleAntialiasing ],\n [ 'r', KeyActions.autoView ]\n ] as KeyActionPreset\n}\n\nexport default KeyActions\n","/**\n * @file Key Controls\n * @author Alexander Rose \n * @private\n */\n\nimport { KeyActionPresets, KeyActionCallback } from './key-actions'\nimport Stage from '../stage/stage'\n\nexport type KeyControlPreset = keyof typeof KeyActionPresets\nexport interface KeyControlsParams {\n preset?: KeyControlPreset\n disabled?: boolean\n}\n\nexport interface KeyAction {\n key: string,\n callback: KeyActionCallback\n}\n\n/**\n * Mouse controls\n */\nclass KeyControls {\n actionList: KeyAction[] = []\n\n disabled: boolean // Flag to disable all actions\n\n /**\n * @param {Stage} stage - the stage object\n * @param {Object} [params] - the parameters\n * @param {String} params.preset - one of \"default\"\n * @param {String} params.disabled - flag to disable all actions\n */\n constructor (readonly stage: Stage, params: KeyControlsParams = {}) {\n this.disabled = params.disabled || false\n this.preset(params.preset || 'default')\n }\n\n run (key: string) {\n if (this.disabled) return\n\n this.actionList.forEach(a => {\n if (a.key === key) {\n a.callback(this.stage)\n }\n })\n }\n\n /**\n * Add a key action triggered by pressing the given character.\n * The {@link KeyActions} class provides a number of static methods for\n * use as callback functions.\n *\n * @example\n * // call KeyActions.toggleRock when \"k\" is pressed\n * stage.keyControls.remove( \"k\", KeyActions.toggleRock );\n *\n * @param {Char} char - the key/character\n * @param {Function} callback - the callback function for the action\n * @return {undefined}\n */\n add (char: string, callback: KeyActionCallback) {\n this.actionList.push({ key: char, callback })\n }\n\n /**\n * Remove a key action. When the callback function\n * is given, only actions that call that function are removed.\n *\n * @example\n * // remove all actions triggered by pressing \"k\"\n * stage.keyControls.remove( \"k\" );\n *\n * @example\n * // remove action `toggleRock` triggered by pressing \"k\"\n * stage.keyControls.remove( \"k\", toggleRock );\n *\n * @param {Char} char - the key/character\n * @param {Function} [callback] - the callback function for the action\n * @return {undefined}\n */\n remove (char: string, callback: KeyActionCallback) {\n\n const actionList = this.actionList.filter(function (a) {\n return !(\n (a.key === char) &&\n (a.callback === callback || callback === undefined)\n )\n })\n\n this.actionList = actionList\n }\n\n /**\n * Set key action preset\n * @param {String} name - one of \"default\"\n * @return {undefined}\n */\n preset (name: KeyControlPreset) {\n this.clear()\n\n const list = KeyActionPresets[ name ] || []\n\n list.forEach(action => this.add(action[0], action[1]))\n }\n\n /**\n * Remove all key actions\n * @return {undefined}\n */\n clear () {\n this.actionList.length = 0\n }\n}\n\nexport default KeyControls\n","/**\n * @file Picking Behavior\n * @author Alexander Rose \n * @private\n */\n\nimport Stage from './stage'\nimport MouseObserver from './mouse-observer'\nimport Viewer from '../viewer/viewer'\nimport MouseControls from '../controls/mouse-controls'\n\nclass PickingBehavior {\n viewer: Viewer\n mouse: MouseObserver\n controls: MouseControls\n\n constructor (readonly stage: Stage) {\n this.stage = stage\n this.mouse = stage.mouseObserver\n this.controls = stage.mouseControls\n\n this.mouse.signals.clicked.add(this._onClick, this)\n this.mouse.signals.hovered.add(this._onHover, this)\n }\n\n _onClick (x: number, y: number) {\n const pickingProxy = this.stage.pickingControls.pick(x, y)\n this.stage.signals.clicked.dispatch(pickingProxy)\n this.controls.run('clickPick', pickingProxy)\n }\n\n _onHover (x: number, y: number) {\n const pickingProxy = this.stage.pickingControls.pick(x, y)\n if (pickingProxy && this.mouse.down.equals(this.mouse.position)) {\n this.stage.transformComponent = pickingProxy.component\n this.stage.transformAtom = pickingProxy.atom\n }\n this.stage.signals.hovered.dispatch(pickingProxy)\n this.controls.run('hoverPick', pickingProxy)\n }\n\n dispose () {\n this.mouse.signals.clicked.remove(this._onClick, this)\n this.mouse.signals.hovered.remove(this._onHover, this)\n }\n}\n\nexport default PickingBehavior\n","/**\n * @file Mouse Behavior\n * @author Alexander Rose \n * @private\n */\n\nimport Stage from './stage'\nimport MouseObserver from './mouse-observer'\nimport Viewer from '../viewer/viewer'\nimport MouseControls from '../controls/mouse-controls'\n\nclass MouseBehavior {\n viewer: Viewer\n mouse: MouseObserver\n controls: MouseControls\n domElement: HTMLCanvasElement\n\n constructor (readonly stage: Stage) {\n this.stage = stage\n this.mouse = stage.mouseObserver\n this.controls = stage.mouseControls\n\n this.mouse.signals.moved.add(this._onMove, this)\n this.mouse.signals.scrolled.add(this._onScroll, this)\n this.mouse.signals.dragged.add(this._onDrag, this)\n this.mouse.signals.clicked.add(this._onClick, this)\n this.mouse.signals.hovered.add(this._onHover, this)\n this.mouse.signals.doubleClicked.add(this._onDblclick, this)\n }\n\n _onMove (/* x, y */) {\n this.stage.tooltip.style.display = 'none'\n }\n\n _onScroll (delta: number) {\n this.controls.run('scroll', delta)\n }\n\n _onDrag (dx: number, dy: number) {\n this.controls.run('drag', dx, dy)\n }\n\n _onClick (x: number, y: number) {\n this.controls.run('click', x, y)\n }\n\n _onDblclick (x: number, y: number) {\n this.controls.run('doubleClick', x, y)\n }\n\n _onHover (x: number, y: number) {\n this.controls.run('hover', x, y)\n }\n\n dispose () {\n this.mouse.signals.moved.remove(this._onMove, this)\n this.mouse.signals.scrolled.remove(this._onScroll, this)\n this.mouse.signals.dragged.remove(this._onDrag, this)\n this.mouse.signals.clicked.remove(this._onClick, this)\n this.mouse.signals.hovered.remove(this._onHover, this)\n }\n}\n\nexport default MouseBehavior\n","/**\n * @file Animation Behavior\n * @author Alexander Rose \n * @private\n */\n\nimport Stage from './stage'\nimport Viewer from '../viewer/viewer'\nimport Stats from '../viewer/stats'\nimport AnimationControls from '../controls/animation-controls'\n\nclass AnimationBehavior {\n viewer: Viewer\n animationControls: AnimationControls\n\n constructor (readonly stage: Stage) {\n this.viewer = stage.viewer\n this.animationControls = stage.animationControls\n\n this.viewer.signals.ticked.add(this._onTick, this)\n }\n\n _onTick (stats: Stats) {\n this.animationControls.run(stats)\n }\n\n dispose () {\n this.viewer.signals.ticked.remove(this._onTick, this)\n }\n}\n\nexport default AnimationBehavior\n","/**\n * @file Key Behavior\n * @author Alexander Rose \n * @private\n */\n\nimport { SupportsPassiveEventHandler } from '../globals'\nimport Stage from './stage'\nimport Viewer from '../viewer/viewer'\nimport KeyControls from '../controls/key-controls'\n\nconst passive = SupportsPassiveEventHandler ? { passive: true } : false\n\nclass KeyBehavior {\n viewer: Viewer\n controls: KeyControls\n domElement: HTMLCanvasElement\n\n /**\n * @param {Stage} stage - the stage object\n */\n constructor (readonly stage: Stage) {\n this.stage = stage\n this.controls = stage.keyControls\n this.domElement = stage.viewer.renderer.domElement\n\n // ensure the domElement is focusable\n this.domElement.setAttribute('tabIndex', '-1')\n this.domElement.style.outline = 'none'\n\n this._focusDomElement = this._focusDomElement.bind(this)\n this._onKeydown = this._onKeydown.bind(this)\n this._onKeyup = this._onKeyup.bind(this)\n this._onKeypress = this._onKeypress.bind(this)\n\n this.domElement.addEventListener('mousedown', this._focusDomElement)\n this.domElement.addEventListener('touchstart', this._focusDomElement, passive as any) // TODO\n this.domElement.addEventListener('keydown', this._onKeydown)\n this.domElement.addEventListener('keyup', this._onKeyup)\n this.domElement.addEventListener('keypress', this._onKeypress)\n }\n\n /**\n * handle key down\n * @param {Event} event - key event\n * @return {undefined}\n */\n _onKeydown (/* event */) {\n // console.log( \"down\", event.keyCode, String.fromCharCode( event.keyCode ) );\n }\n\n /**\n * handle key up\n * @param {Event} event - key event\n * @return {undefined}\n */\n _onKeyup (/* event */) {\n // console.log( \"up\", event.keyCode, String.fromCharCode( event.keyCode ) );\n }\n\n /**\n * handle key press\n * @param {Event} event - key event\n * @return {undefined}\n */\n _onKeypress (event: KeyboardEvent) {\n // console.log( \"press\", event.keyCode, String.fromCharCode( event.keyCode ) );\n let pressedKey: string;\n if (\"key\" in KeyboardEvent.prototype) {\n pressedKey = event.key;\n // some mobile browsers don't support this attribute\n } else {\n pressedKey = String.fromCharCode(event.which || event.keyCode);\n }\n this.controls.run(pressedKey);\n }\n\n _focusDomElement () {\n this.domElement.focus()\n }\n\n dispose () {\n this.domElement.removeEventListener('mousedown', this._focusDomElement)\n this.domElement.removeEventListener('touchstart', this._focusDomElement, passive as any) // TODO\n this.domElement.removeEventListener('keydown', this._onKeypress)\n this.domElement.removeEventListener('keyup', this._onKeypress)\n this.domElement.removeEventListener('keypress', this._onKeypress)\n }\n}\n\nexport default KeyBehavior\n","/**\n * @file Annotation\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector2, Vector3 } from 'three'\n\nimport { defaults } from '../utils'\nimport { smoothstep } from '../math/math-utils'\nimport Stage from '../stage/stage'\nimport Viewer from '../viewer/viewer'\nimport Component from './component'\n\nexport interface AnnotationParams {\n offsetX?: number\n offsetY?: number\n visible?: boolean\n}\n\n/**\n * Annotation HTML element floating on top of a position rendered in 3d\n */\nexport default class Annotation {\n offsetX: number\n offsetY: number\n visible: boolean\n\n stage: Stage\n viewer: Viewer\n element: HTMLElement\n\n private _viewerPosition: Vector3\n private _canvasPosition: Vector2\n private _cameraPosition: Vector3\n private _clientRect: ClientRect\n\n /**\n * @param {Component} component - the associated component\n * @param {Vector3} position - position in 3d\n * @param {String|Element} content - HTML content\n * @param {Object} [params] - parameters\n * @param {Integer} params.offsetX - 2d offset in x direction\n * @param {Integer} params.offsetY - 2d offset in y direction\n * @param {Boolean} params.visible - visibility flag\n */\n constructor (readonly component: Component, readonly position: Vector3, content: string|HTMLElement, params: AnnotationParams = {}) {\n this.offsetX = defaults(params.offsetX, 0)\n this.offsetY = defaults(params.offsetY, 0)\n this.visible = defaults(params.visible, true)\n\n this.stage = component.stage\n this.viewer = component.stage.viewer\n\n this._viewerPosition = new Vector3()\n this._updateViewerPosition()\n this._canvasPosition = new Vector2()\n this._cameraPosition = new Vector3()\n\n this.element = document.createElement('div')\n Object.assign(this.element.style, {\n display: 'block',\n position: 'absolute',\n pointerEvents: 'none',\n whiteSpace: 'nowrap',\n left: '-10000px'\n })\n\n this.viewer.wrapper.appendChild(this.element)\n this.setContent(content)\n this.updateVisibility()\n this.viewer.signals.rendered.add(this._update, this)\n this.component.signals.matrixChanged.add(this._updateViewerPosition, this)\n }\n\n /**\n * Set HTML content of the annotation\n * @param {String|Element} value - HTML content\n * @return {undefined}\n */\n setContent (value: string|HTMLElement) {\n const displayValue = this.element.style.display\n if (displayValue === 'none') {\n this.element.style.left = '-10000px'\n this.element.style.display = 'block'\n }\n\n if (value instanceof HTMLElement) {\n this.element.appendChild(value)\n } else {\n const content = document.createElement('div')\n content.innerText = value\n Object.assign(content.style, {\n backgroundColor: 'rgba( 0, 0, 0, 0.6 )',\n color: 'lightgrey',\n padding: '8px',\n fontFamily: 'sans-serif',\n })\n this.element.appendChild(content)\n }\n\n this._clientRect = this.element.getBoundingClientRect()\n\n if (displayValue === 'none') {\n this.element.style.display = displayValue\n }\n }\n\n /**\n * Set visibility of the annotation\n * @param {Boolean} value - visibility flag\n * @return {undefined}\n */\n setVisibility (value: boolean) {\n this.visible = value\n this.updateVisibility()\n }\n\n getVisibility () {\n return this.visible && this.component.parameters.visible\n }\n\n updateVisibility () {\n this.element.style.display = this.getVisibility() ? 'block' : 'none'\n }\n\n _updateViewerPosition () {\n this._viewerPosition\n .copy(this.position)\n .applyMatrix4(this.component.matrix)\n }\n\n _update () {\n if (!this.getVisibility()) return\n\n const s = this.element.style\n const cp = this._canvasPosition\n const vp = this._viewerPosition\n const cr = this._clientRect\n\n this._cameraPosition.copy(vp)\n .add(this.viewer.translationGroup.position)\n .applyMatrix4(this.viewer.rotationGroup.matrix)\n .sub(this.viewer.camera.position)\n\n if (this._cameraPosition.z < 0) {\n s.display = 'none'\n return\n } else {\n s.display = 'block'\n }\n\n const depth = this._cameraPosition.length()\n const fog = this.viewer.scene.fog as any // TODO\n\n s.opacity = (1 - smoothstep(fog.near, fog.far, depth)).toString()\n s.zIndex = (Math.round((fog.far - depth) * 100)).toString()\n\n this.stage.viewerControls.getPositionOnCanvas(vp, cp)\n\n s.bottom = (this.offsetX + cp.y + cr.height / 2) + 'px'\n s.left = (this.offsetY + cp.x - cr.width / 2) + 'px'\n }\n\n /**\n * Safely remove the annotation\n * @return {undefined}\n */\n dispose () {\n this.viewer.wrapper.removeChild(this.element)\n this.viewer.signals.ticked.remove(this._update, this)\n this.component.signals.matrixChanged.remove(this._updateViewerPosition, this)\n }\n}","/**\n * @file Component Controls\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Matrix4, Quaternion } from 'three'\nimport * as signalsWrapper from 'signals'\n\nimport { ensureVector3 } from '../utils'\nimport Component from '../component/component'\nimport Stage from '../stage/stage'\nimport Viewer from '../viewer/viewer'\n\nconst tmpRotateMatrix = new Matrix4()\nconst tmpRotateVector = new Vector3()\nconst tmpRotateQuaternion = new Quaternion()\n\n/**\n * Component controls\n */\nclass ComponentControls {\n signals = {\n changed: new signalsWrapper.Signal()\n }\n\n stage: Stage\n viewer: Viewer\n\n /**\n * @param {Component} component - the component object\n */\n constructor (readonly component: Component) {\n this.stage = component.stage\n this.viewer = component.stage.viewer\n }\n\n /**\n * component center position\n * @type {Vector3}\n */\n get position () {\n return this.component.position\n }\n\n /**\n * component rotation\n * @type {Quaternion}\n */\n get rotation () {\n return this.component.quaternion\n }\n\n /**\n * Trigger render and emit changed event\n * @emits {ComponentControls.signals.changed}\n * @return {undefined}\n */\n changed () {\n this.component.updateMatrix()\n this.viewer.requestRender()\n this.signals.changed.dispatch()\n }\n\n /**\n * spin component on axis\n * @param {Vector3|Array} axis - rotation axis\n * @param {Number} angle - amount to spin\n * @return {undefined}\n */\n spin (axis: Vector3, angle: number) {\n tmpRotateMatrix.getInverse(this.viewer.rotationGroup.matrix)\n tmpRotateVector\n .copy(ensureVector3(axis)).applyMatrix4(tmpRotateMatrix)\n\n tmpRotateMatrix.extractRotation(this.component.transform)\n tmpRotateMatrix.premultiply(this.viewer.rotationGroup.matrix)\n tmpRotateMatrix.getInverse(tmpRotateMatrix)\n\n tmpRotateVector.copy(ensureVector3(axis))\n tmpRotateVector.applyMatrix4(tmpRotateMatrix)\n tmpRotateMatrix.makeRotationAxis(tmpRotateVector, angle)\n tmpRotateQuaternion.setFromRotationMatrix(tmpRotateMatrix)\n\n this.component.quaternion.premultiply(tmpRotateQuaternion)\n this.changed()\n }\n}\n\nexport default ComponentControls\n","/**\n * @file Radius Factory\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport { NucleicBackboneAtoms } from '../structure/structure-constants'\nimport AtomProxy from '../proxy/atom-proxy'\n\nexport const RadiusFactoryTypes = {\n '': '',\n 'vdw': 'by vdW radius',\n 'covalent': 'by covalent radius',\n 'sstruc': 'by secondary structure',\n 'bfactor': 'by bfactor',\n 'size': 'size',\n 'data': 'data',\n 'explicit' : 'explicit'\n}\nexport type RadiusType = keyof typeof RadiusFactoryTypes\n\nexport interface RadiusParams {\n type?: RadiusType\n scale?: number\n size?: number\n data?: { [k: number]: number }\n}\n\nclass RadiusFactory {\n max = 10\n\n static types = RadiusFactoryTypes\n\n readonly type: RadiusType\n readonly scale: number\n readonly size: number\n readonly data: { [k: number]: number }\n\n constructor (params: RadiusParams = {}) {\n this.type = defaults(params.type, 'size')\n this.scale = defaults(params.scale, 1)\n this.size = defaults(params.size, 1)\n this.data = defaults(params.data, {})\n }\n\n atomRadius (a: AtomProxy) {\n let r\n\n switch (this.type) {\n case 'vdw':\n r = a.vdw\n break\n\n case 'covalent':\n r = a.covalent\n break\n\n case 'bfactor':\n r = a.bfactor || 1.0\n break\n\n case 'sstruc':\n const sstruc = a.sstruc\n if (sstruc === 'h') {\n r = 0.25\n } else if (sstruc === 'g') {\n r = 0.25\n } else if (sstruc === 'i') {\n r = 0.25\n } else if (sstruc === 'e') {\n r = 0.25\n } else if (sstruc === 'b') {\n r = 0.25\n } else if (NucleicBackboneAtoms.includes(a.atomname)) {\n r = 0.4\n } else {\n r = 0.1\n }\n break\n\n case 'data':\n r = defaults(this.data[ a.index ], 1.0)\n break\n\n case 'explicit':\n // defaults is inappropriate as AtomProxy.radius returns\n // null for missing radii\n r = a.radius\n if (r === null) r = this.size\n break\n\n default:\n r = this.size\n break\n }\n\n return Math.min(r * this.scale, this.max)\n }\n\n}\n\nexport default RadiusFactory\n","/**\n * @file Principal Axes\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Matrix4, Quaternion } from 'three'\n\nimport {\n Matrix, meanRows, subRows, transpose, multiplyABt, svd\n} from './matrix-utils'\nimport { projectPointOnVector } from './vector-utils'\nimport Structure from '../structure/structure'\nimport AtomProxy from '../proxy/atom-proxy'\n\nconst negateVector = new Vector3(-1, -1, -1)\nconst tmpMatrix = new Matrix4()\n\n/**\n * Principal axes\n */\nclass PrincipalAxes {\n begA: Vector3\n endA: Vector3\n begB: Vector3\n endB: Vector3\n begC: Vector3\n endC: Vector3\n\n center: Vector3\n\n vecA: Vector3\n vecB: Vector3\n vecC: Vector3\n\n normVecA: Vector3\n normVecB: Vector3\n normVecC: Vector3\n\n /**\n * @param {Matrix} points - 3 by N matrix\n */\n constructor (points: Matrix) {\n // console.time( \"PrincipalAxes\" );\n\n const n = points.rows\n const n3 = n / 3\n const pointsT = new Matrix(n, 3)\n const A = new Matrix(3, 3)\n const W = new Matrix(1, 3)\n const U = new Matrix(3, 3)\n const V = new Matrix(3, 3)\n\n // calculate\n const mean = meanRows(points)\n subRows(points, mean)\n transpose(pointsT, points)\n multiplyABt(A, pointsT, pointsT)\n svd(A, W, U, V)\n\n // console.log( points, pointsT, mean )\n // console.log( n, A, W, U, V );\n\n // center\n const vm = new Vector3(mean[0], mean[1], mean[2])\n\n // normalized\n const van = new Vector3(U.data[0], U.data[3], U.data[6])\n const vbn = new Vector3(U.data[1], U.data[4], U.data[7])\n const vcn = new Vector3(U.data[2], U.data[5], U.data[8])\n\n // scaled\n const va = van.clone().multiplyScalar(Math.sqrt(W.data[0] / n3))\n const vb = vbn.clone().multiplyScalar(Math.sqrt(W.data[1] / n3))\n const vc = vcn.clone().multiplyScalar(Math.sqrt(W.data[2] / n3))\n\n // points\n this.begA = vm.clone().sub(va)\n this.endA = vm.clone().add(va)\n this.begB = vm.clone().sub(vb)\n this.endB = vm.clone().add(vb)\n this.begC = vm.clone().sub(vc)\n this.endC = vm.clone().add(vc)\n\n //\n\n this.center = vm\n\n this.vecA = va\n this.vecB = vb\n this.vecC = vc\n\n this.normVecA = van\n this.normVecB = vbn\n this.normVecC = vcn\n\n // console.timeEnd( \"PrincipalAxes\" );\n }\n\n /**\n * Get the basis matrix descriping the axes\n * @param {Matrix4} [optionalTarget] - target object\n * @return {Matrix4} the basis\n */\n getBasisMatrix (optionalTarget = new Matrix4()) {\n const basis = optionalTarget\n\n basis.makeBasis(this.normVecB, this.normVecA, this.normVecC)\n if (basis.determinant() < 0) {\n basis.scale(negateVector)\n }\n\n return basis\n }\n\n /**\n * Get a quaternion descriping the axes rotation\n * @param {Quaternion} [optionalTarget] - target object\n * @return {Quaternion} the rotation\n */\n getRotationQuaternion (optionalTarget = new Quaternion()) {\n const q = optionalTarget\n q.setFromRotationMatrix(this.getBasisMatrix(tmpMatrix))\n\n return q.inverse()\n }\n\n /**\n * Get the scale/length for each dimension for a box around the axes\n * to enclose the atoms of a structure\n * @param {Structure|StructureView} structure - the structure\n * @return {{d1a: Number, d2a: Number, d3a: Number, d1b: Number, d2b: Number, d3b: Number}} scale\n */\n getProjectedScaleForAtoms (structure: Structure) {\n let d1a = -Infinity\n let d1b = -Infinity\n let d2a = -Infinity\n let d2b = -Infinity\n let d3a = -Infinity\n let d3b = -Infinity\n\n const p = new Vector3()\n const t = new Vector3()\n\n const center = this.center\n const ax1 = this.normVecA\n const ax2 = this.normVecB\n const ax3 = this.normVecC\n\n structure.eachAtom(function (ap: AtomProxy) {\n projectPointOnVector(p.copy(ap as any), ax1, center) // TODO\n const dp1 = t.subVectors(p, center).normalize().dot(ax1)\n const dt1 = p.distanceTo(center)\n if (dp1 > 0) {\n if (dt1 > d1a) d1a = dt1\n } else {\n if (dt1 > d1b) d1b = dt1\n }\n\n projectPointOnVector(p.copy(ap as any), ax2, center)\n const dp2 = t.subVectors(p, center).normalize().dot(ax2)\n const dt2 = p.distanceTo(center)\n if (dp2 > 0) {\n if (dt2 > d2a) d2a = dt2\n } else {\n if (dt2 > d2b) d2b = dt2\n }\n\n projectPointOnVector(p.copy(ap as any), ax3, center)\n const dp3 = t.subVectors(p, center).normalize().dot(ax3)\n const dt3 = p.distanceTo(center)\n if (dp3 > 0) {\n if (dt3 > d3a) d3a = dt3\n } else {\n if (dt3 > d3b) d3b = dt3\n }\n })\n\n return {\n d1a: d1a,\n d2a: d2a,\n d3a: d3a,\n d1b: -d1b,\n d2b: -d2b,\n d3b: -d3b\n }\n }\n}\n\nexport default PrincipalAxes\n","/**\n * @file Filtered Volume\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport Volume from './volume'\nimport { Box3, Matrix4, Matrix3, Vector3 } from 'three';\n\nclass FilteredVolume {\n volume: Volume\n data: Float32Array\n position: Float32Array\n atomindex: Int32Array\n _filterHash: string\n _dataBuffer: ArrayBuffer\n _positionBuffer: ArrayBuffer\n _atomindexBuffer: ArrayBuffer\n getValueForSigma: typeof Volume.prototype.getValueForSigma\n getSigmaForValue: typeof Volume.prototype.getSigmaForValue\n getDataAtomindex: typeof Volume.prototype.getDataAtomindex\n getDataPosition: typeof Volume.prototype.getDataPosition\n getDataColor: typeof Volume.prototype.getDataColor\n getDataPicking: typeof Volume.prototype.getDataPicking\n getDataSize: typeof Volume.prototype.getDataSize\n\n\n constructor (volume: Volume, minValue?: number, maxValue?: number, outside?: boolean) {\n this.volume = volume\n this.setFilter(minValue, maxValue, outside)\n }\n\n get header () { return this.volume.header }\n get matrix (): Matrix4 { return this.volume.matrix }\n get normalMatrix (): Matrix3 { return this.volume.normalMatrix }\n get inverseMatrix (): Matrix4 { return this.volume.inverseMatrix }\n get center (): Vector3 { return this.volume.center }\n get boundingBox (): Box3 { return this.volume.boundingBox }\n get min () { return this.volume.min }\n get max () { return this.volume.max }\n get mean () { return this.volume.mean }\n get rms () { return this.volume.rms }\n\n _getFilterHash (minValue: number, maxValue: number, outside: boolean) {\n return JSON.stringify([ minValue, maxValue, outside ])\n }\n\n setFilter (minValue: number|undefined, maxValue: number|undefined, outside: boolean|undefined) {\n if (isNaN(minValue) && this.header) {\n minValue = this.header.DMEAN + 2.0 * this.header.ARMS\n }\n\n minValue = (minValue !== undefined && !isNaN(minValue)) ? minValue : -Infinity\n maxValue = defaults(maxValue, Infinity) as number\n outside = defaults(outside, false) as boolean\n\n const data = this.volume.data\n const position = this.volume.position\n const atomindex = this.volume.atomindex\n\n const filterHash = this._getFilterHash(minValue, maxValue, outside)\n\n if (filterHash === this._filterHash) {\n // already filtered\n return\n } else if (minValue === -Infinity && maxValue === Infinity) {\n this.data = data\n this.position = position\n this.atomindex = atomindex!\n } else {\n const n = data.length\n\n if (!this._dataBuffer) {\n // ArrayBuffer for re-use as Float32Array backend\n\n this._dataBuffer = new ArrayBuffer(n * 4)\n this._positionBuffer = new ArrayBuffer(n * 3 * 4)\n if (atomindex) this._atomindexBuffer = new ArrayBuffer(n * 4)\n }\n\n const filteredData = new Float32Array(this._dataBuffer)\n const filteredPosition = new Float32Array(this._positionBuffer)\n let filteredAtomindex\n if (atomindex) filteredAtomindex = new Uint32Array(this._atomindexBuffer)\n\n let j = 0\n\n for (let i = 0; i < n; ++i) {\n const i3 = i * 3\n const v = data[ i ]\n\n if ((!outside && v >= minValue && v <= maxValue) ||\n (outside && (v < minValue || v > maxValue))\n ) {\n const j3 = j * 3\n\n filteredData[ j ] = v\n\n filteredPosition[ j3 + 0 ] = position[ i3 + 0 ]\n filteredPosition[ j3 + 1 ] = position[ i3 + 1 ]\n filteredPosition[ j3 + 2 ] = position[ i3 + 2 ]\n\n if (atomindex && filteredAtomindex) filteredAtomindex[ j ] = atomindex[ i ]\n\n j += 1\n }\n }\n\n // set views\n\n this.data = new Float32Array(this._dataBuffer, 0, j)\n this.position = new Float32Array(this._positionBuffer, 0, j * 3)\n if (atomindex) this.atomindex = new Int32Array(this._atomindexBuffer, 0, j)\n }\n\n this._filterHash = filterHash\n }\n}\n\nFilteredVolume.prototype.getValueForSigma = Volume.prototype.getValueForSigma\nFilteredVolume.prototype.getSigmaForValue = Volume.prototype.getSigmaForValue\n\nFilteredVolume.prototype.getDataAtomindex = Volume.prototype.getDataAtomindex\nFilteredVolume.prototype.getDataPosition = Volume.prototype.getDataPosition\nFilteredVolume.prototype.getDataColor = Volume.prototype.getDataColor\nFilteredVolume.prototype.getDataPicking = Volume.prototype.getDataPicking\nFilteredVolume.prototype.getDataSize = Volume.prototype.getDataSize\n\nexport default FilteredVolume\n","/**\n * @file Bond Hash\n * @author Alexander Rose \n * @private\n */\n\nimport BondStore from './bond-store'\nimport { createAdjacencyList } from '../utils/adjacency-list'\n\nclass BondHash {\n countArray: Uint8Array\n offsetArray: Int32Array\n indexArray: Int32Array\n\n constructor (bondStore: BondStore, atomCount: number) {\n const al = createAdjacencyList({\n nodeArray1: bondStore.atomIndex1,\n nodeArray2: bondStore.atomIndex2,\n edgeCount: bondStore.count,\n nodeCount: atomCount\n })\n\n this.countArray = al.countArray\n this.offsetArray = al.offsetArray\n this.indexArray = al.indexArray\n }\n}\n\nexport default BondHash\n","/**\n * @file Bond Store\n * @author Alexander Rose \n * @private\n */\n\nimport Store, { StoreField } from './store'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Bond store\n */\nexport default class BondStore extends Store {\n atomIndex1: Uint32Array\n atomIndex2: Uint32Array\n bondOrder: Uint8Array\n\n get _defaultFields () {\n return [\n [ 'atomIndex1', 1, 'int32' ],\n [ 'atomIndex2', 1, 'int32' ],\n [ 'bondOrder', 1, 'int8' ]\n ] as StoreField[]\n }\n\n addBond (atom1: AtomProxy, atom2: AtomProxy, bondOrder?: number) {\n this.growIfFull()\n\n const i = this.count\n const ai1 = atom1.index\n const ai2 = atom2.index\n\n if (ai1 < ai2) {\n this.atomIndex1[ i ] = ai1\n this.atomIndex2[ i ] = ai2\n } else {\n this.atomIndex2[ i ] = ai1\n this.atomIndex1[ i ] = ai2\n }\n if (bondOrder) this.bondOrder[ i ] = bondOrder\n\n this.count += 1\n }\n\n addBondIfConnected (atom1: AtomProxy, atom2: AtomProxy, bondOrder?: number) {\n if (atom1.connectedTo(atom2)) {\n this.addBond(atom1, atom2, bondOrder)\n return true\n }\n\n return false\n }\n}","/**\n * @file Atom Store\n * @author Alexander Rose \n * @private\n */\n\nimport Store, { StoreField } from './store'\n\n/**\n * Atom store\n */\nexport default class AtomStore extends Store {\n residueIndex: Uint32Array\n atomTypeId: Uint16Array\n\n x: Float32Array\n y: Float32Array\n z: Float32Array\n serial: Int32Array\n bfactor: Float32Array\n altloc: Uint8Array\n occupancy: Float32Array\n\n partialCharge?: Float32Array\n formalCharge?: Uint8Array\n\n get _defaultFields () {\n return [\n [ 'residueIndex', 1, 'uint32' ],\n [ 'atomTypeId', 1, 'uint16' ],\n\n [ 'x', 1, 'float32' ],\n [ 'y', 1, 'float32' ],\n [ 'z', 1, 'float32' ],\n [ 'serial', 1, 'int32' ],\n [ 'bfactor', 1, 'float32' ],\n [ 'altloc', 1, 'uint8' ],\n [ 'occupancy', 1, 'float32' ]\n ] as StoreField[]\n }\n\n setAltloc (i: number, str: string) {\n this.altloc[ i ] = str.charCodeAt(0)\n }\n\n getAltloc (i: number) {\n const code = this.altloc[ i ]\n return code ? String.fromCharCode(code) : ''\n }\n}","/**\n * @file Residue Store\n * @author Alexander Rose \n * @private\n */\n\nimport Store, { StoreField } from './store'\n\n/**\n * Residue store\n */\nexport default class ResidueStore extends Store {\n chainIndex: Uint32Array\n atomOffset: Uint32Array\n atomCount: Uint32Array\n residueTypeId: Uint16Array\n\n resno: Uint32Array\n sstruc: Uint8Array\n inscode: Uint8Array\n\n get _defaultFields () {\n return [\n [ 'chainIndex', 1, 'uint32' ],\n [ 'atomOffset', 1, 'uint32' ],\n [ 'atomCount', 1, 'uint32' ],\n [ 'residueTypeId', 1, 'uint16' ],\n\n [ 'resno', 1, 'int32' ],\n [ 'sstruc', 1, 'uint8' ],\n [ 'inscode', 1, 'uint8' ]\n ] as StoreField[]\n }\n\n setSstruc (i: number, str: string) {\n this.sstruc[ i ] = str.charCodeAt(0)\n }\n\n getSstruc (i: number) {\n const code = this.sstruc[ i ]\n return code ? String.fromCharCode(code) : ''\n }\n\n setInscode (i: number, str: string) {\n this.inscode[ i ] = str.charCodeAt(0)\n }\n\n getInscode (i: number) {\n const code = this.inscode[ i ]\n return code ? String.fromCharCode(code) : ''\n }\n}","/**\n * @file Chain Store\n * @author Alexander Rose \n * @private\n */\n\nimport Store, { StoreField } from './store'\n\n/**\n * Chain store\n */\nexport default class ChainStore extends Store {\n entityIndex: Uint16Array\n modelIndex: Uint16Array\n residueOffset: Uint32Array\n residueCount: Uint32Array\n\n chainname: Uint8Array\n chainid: Uint8Array\n\n get _defaultFields () {\n return [\n [ 'entityIndex', 1, 'uint16' ],\n [ 'modelIndex', 1, 'uint16' ],\n [ 'residueOffset', 1, 'uint32' ],\n [ 'residueCount', 1, 'uint32' ],\n\n [ 'chainname', 4, 'uint8' ],\n [ 'chainid', 4, 'uint8' ]\n ] as StoreField[]\n }\n\n setChainname (i: number, str: string) {\n const j = 4 * i\n this.chainname[ j ] = str.charCodeAt(0)\n this.chainname[ j + 1 ] = str.charCodeAt(1)\n this.chainname[ j + 2 ] = str.charCodeAt(2)\n this.chainname[ j + 3 ] = str.charCodeAt(3)\n }\n\n getChainname (i: number) {\n let chainname = ''\n for (let k = 0; k < 4; ++k) {\n const code = this.chainname[ 4 * i + k ]\n if (code) {\n chainname += String.fromCharCode(code)\n } else {\n break\n }\n }\n return chainname\n }\n\n setChainid (i: number, str: string) {\n const j = 4 * i\n this.chainid[ j ] = str.charCodeAt(0)\n this.chainid[ j + 1 ] = str.charCodeAt(1)\n this.chainid[ j + 2 ] = str.charCodeAt(2)\n this.chainid[ j + 3 ] = str.charCodeAt(3)\n }\n\n getChainid (i: number) {\n let chainid = ''\n for (let k = 0; k < 4; ++k) {\n const code = this.chainid[ 4 * i + k ]\n if (code) {\n chainid += String.fromCharCode(code)\n } else {\n break\n }\n }\n return chainid\n }\n}\n","/**\n * @file Model Store\n * @author Alexander Rose \n * @private\n */\n\nimport Store, { StoreField } from './store'\n\n/**\n * Model store\n */\nexport default class ModelStore extends Store {\n\tchainOffset: Uint32Array\n\tchainCount: Uint32Array\n\n get _defaultFields () {\n return [\n [ 'chainOffset', 1, 'uint32' ],\n [ 'chainCount', 1, 'uint32' ]\n ] as StoreField[]\n }\n}","/**\n * @file Helixorient\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { ColormakerRegistry } from '../globals'\nimport { ColormakerParameters } from '../color/colormaker'\nimport { AtomPicker } from '../utils/picker'\nimport RadiusFactory, { RadiusParams } from '../utils/radius-factory'\nimport { copyArray } from '../math/array-utils'\nimport { projectPointOnVector } from '../math/vector-utils'\nimport Polymer from '../proxy/polymer'\n\nexport interface HelixIterator {\n size: number\n next: () => Vector3\n get: (idx: number) => Vector3\n reset: () => void\n}\n\nexport interface HelixPosition {\n center: Float32Array\n axis: Float32Array\n bending: Float32Array\n radius: Float32Array\n rise: Float32Array\n twist: Float32Array\n resdir: Float32Array\n}\n\nclass Helixorient {\n size: number\n\n constructor (readonly polymer: Polymer) {\n this.size = polymer.residueCount\n }\n\n getCenterIterator (smooth = 0): HelixIterator {\n const center = this.getPosition().center\n const size = center.length / 3\n\n let i = 0\n let j = -1\n\n const cache = [\n new Vector3(),\n new Vector3(),\n new Vector3(),\n new Vector3()\n ]\n\n function next (this: HelixIterator) {\n const vector = this.get(j)\n j += 1\n return vector\n }\n\n function get (idx: number) {\n idx = Math.min(size - 1, Math.max(0, idx))\n const v = cache[ i % 4 ]\n const idx3 = 3 * idx\n v.fromArray(center as any, idx3) // TODO\n if (smooth) {\n const w = Math.min(smooth, idx, size - idx - 1)\n for (let k = 1; k <= w; ++k) {\n const l = k * 3\n const t = (w + 1 - k) / (w + 1)\n v.x += t * center[ idx3 - l + 0 ] + t * center[ idx3 + l + 0 ]\n v.y += t * center[ idx3 - l + 1 ] + t * center[ idx3 + l + 1 ]\n v.z += t * center[ idx3 - l + 2 ] + t * center[ idx3 + l + 2 ]\n }\n v.x /= w + 1\n v.y /= w + 1\n v.z /= w + 1\n }\n i += 1\n return v\n }\n\n function reset () {\n i = 0\n j = -1\n }\n\n return { size, next, get, reset }\n }\n\n getColor (params: { scheme: string } & ColormakerParameters) {\n const polymer = this.polymer\n const structure = polymer.structure\n const n = polymer.residueCount\n const residueIndexStart = polymer.residueIndexStart\n\n const col = new Float32Array(n * 3)\n\n const p = params || {}\n p.structure = structure\n\n const colormaker = ColormakerRegistry.getScheme(p)\n\n const rp = structure.getResidueProxy()\n const ap = structure.getAtomProxy()\n\n for (let i = 0; i < n; ++i) {\n rp.index = residueIndexStart + i\n ap.index = rp.traceAtomIndex\n\n colormaker.atomColorToArray(ap, col, i * 3)\n }\n\n return {\n 'color': col\n }\n }\n\n getPicking () {\n const polymer = this.polymer\n const structure = polymer.structure\n const n = polymer.residueCount\n const residueIndexStart = polymer.residueIndexStart\n\n const pick = new Float32Array(n)\n const rp = structure.getResidueProxy()\n\n for (let i = 0; i < n; ++i) {\n rp.index = residueIndexStart + i\n pick[ i ] = rp.traceAtomIndex\n }\n\n return {\n 'picking': new AtomPicker(pick, structure)\n }\n }\n\n getSize (params: RadiusParams) {\n const polymer = this.polymer\n const structure = polymer.structure\n const n = polymer.residueCount\n const residueIndexStart = polymer.residueIndexStart\n\n const size = new Float32Array(n)\n const radiusFactory = new RadiusFactory(params)\n\n const rp = structure.getResidueProxy()\n const ap = structure.getAtomProxy()\n\n for (let i = 0; i < n; ++i) {\n rp.index = residueIndexStart + i\n ap.index = rp.traceAtomIndex\n size[ i ] = radiusFactory.atomRadius(ap)\n }\n\n return { size }\n }\n\n getPosition (): HelixPosition {\n const polymer = this.polymer\n const structure = polymer.structure\n const n = polymer.residueCount\n const n3 = n - 3\n\n const center = new Float32Array(3 * n)\n const axis = new Float32Array(3 * n)\n const diff = new Float32Array(n)\n const radius = new Float32Array(n)\n const rise = new Float32Array(n)\n const twist = new Float32Array(n)\n const resdir = new Float32Array(3 * n)\n\n const r12 = new Vector3()\n const r23 = new Vector3()\n const r34 = new Vector3()\n\n const diff13 = new Vector3()\n const diff24 = new Vector3()\n\n const v1 = new Vector3()\n const v2 = new Vector3()\n const vt = new Vector3()\n\n const _axis = new Vector3()\n const _prevAxis = new Vector3()\n\n const _resdir = new Vector3()\n const _center = new Vector3(0, 0, 0)\n\n const type = 'trace'\n const a1 = structure.getAtomProxy()\n const a2 = structure.getAtomProxy(polymer.getAtomIndexByType(0, type))\n const a3 = structure.getAtomProxy(polymer.getAtomIndexByType(1, type))\n const a4 = structure.getAtomProxy(polymer.getAtomIndexByType(2, type))\n\n for (let i = 0; i < n3; ++i) {\n a1.index = a2.index\n a2.index = a3.index\n a3.index = a4.index\n a4.index = polymer.getAtomIndexByType(i + 3, type)! // TODO\n\n const j = 3 * i\n\n // ported from GROMACS src/tools/gmx_helixorient.c\n\n r12.subVectors(a2 as any, a1 as any) // TODO\n r23.subVectors(a3 as any, a2 as any) // TODO\n r34.subVectors(a4 as any, a3 as any) // TODO\n\n diff13.subVectors(r12, r23)\n diff24.subVectors(r23, r34)\n\n _axis.crossVectors(diff13, diff24).normalize()\n _axis.toArray(axis as any, j) // TODO\n\n if (i > 0) {\n diff[ i ] = _axis.angleTo(_prevAxis)\n }\n\n const tmp = Math.cos(diff13.angleTo(diff24))\n twist[ i ] = 180.0 / Math.PI * Math.acos(tmp)\n\n const diff13Length = diff13.length()\n const diff24Length = diff24.length()\n\n radius[ i ] = (\n Math.sqrt(diff24Length * diff13Length) /\n // clamp, to avoid instabilities for when\n // angle between diff13 and diff24 is near 0\n Math.max(2.0, 2.0 * (1.0 - tmp))\n )\n\n rise[ i ] = Math.abs(r23.dot(_axis))\n\n //\n\n v1.copy(diff13).multiplyScalar(radius[ i ] / diff13Length)\n v2.copy(diff24).multiplyScalar(radius[ i ] / diff24Length)\n\n v1.subVectors(a2 as any, v1) // TODO\n v2.subVectors(a3 as any, v2) // TODO\n\n v1.toArray(center as any, j + 3) // TODO\n v2.toArray(center as any, j + 6) // TODO\n\n //\n\n _resdir.subVectors(a1 as any, _center) // TODO\n _resdir.toArray(resdir as any, j) // TODO\n\n _prevAxis.copy(_axis)\n _center.copy(v1)\n }\n\n //\n\n // calc axis as dir of second and third center pos\n // project first traceAtom onto axis to get first center pos\n v1.fromArray(center as any, 3) // TODO\n v2.fromArray(center as any, 6) // TODO\n _axis.subVectors(v1, v2).normalize()\n // _center.copy( res[ 0 ].getTraceAtom() );\n a1.index = polymer.getAtomIndexByType(0, type)! // TODO\n _center.copy(a1 as any) // TODO\n vt.copy(a1 as any) // TODO\n projectPointOnVector(vt, _axis, v1)\n vt.toArray(center as any, 0) // TODO\n\n // calc first resdir\n _resdir.subVectors(_center, v1)\n _resdir.toArray(resdir as any, 0) // TODO\n\n // calc axis as dir of n-1 and n-2 center pos\n // project last traceAtom onto axis to get last center pos\n v1.fromArray(center as any, 3 * n - 6) // TODO\n v2.fromArray(center as any, 3 * n - 9) // TODO\n _axis.subVectors(v1, v2).normalize()\n // _center.copy( res[ n - 1 ].getTraceAtom() );\n a1.index = polymer.getAtomIndexByType(n - 1, type)! // TODO\n _center.copy(a1 as any) // TODO\n vt.copy(a1 as any) // TODO\n projectPointOnVector(vt, _axis, v1)\n vt.toArray(center as any, 3 * n - 3) // TODO\n\n // calc last three resdir\n for (let i = n - 3; i < n; ++i) {\n v1.fromArray(center as any, 3 * i) // TODO\n // _center.copy( res[ i ].getTraceAtom() );\n a1.index = polymer.getAtomIndexByType(i, type)! // TODO\n _center.copy(a1 as any) // TODO\n\n _resdir.subVectors(_center, v1)\n _resdir.toArray(resdir as any, 3 * i) // TODO\n }\n\n // average measures to define them on the residues\n\n const resRadius = new Float32Array(n)\n const resTwist = new Float32Array(n)\n const resRise = new Float32Array(n)\n const resBending = new Float32Array(n)\n\n resRadius[ 1 ] = radius[ 0 ]\n resTwist[ 1 ] = twist[ 0 ]\n resRise[ 1 ] = radius[ 0 ]\n\n for (let i = 2; i < n - 2; ++i) {\n resRadius[ i ] = 0.5 * (radius[ i - 2 ] + radius[ i - 1 ])\n resTwist[ i ] = 0.5 * (twist[ i - 2 ] + twist[ i - 1 ])\n resRise[ i ] = 0.5 * (rise[ i - 2 ] + rise[ i - 1 ])\n\n v1.fromArray(axis as any, 3 * (i - 2)) // TODO\n v2.fromArray(axis as any, 3 * (i - 1)) // TODO\n resBending[ i ] = 180.0 / Math.PI * Math.acos(Math.cos(v1.angleTo(v2)))\n }\n\n resRadius[ n - 2 ] = radius[ n - 4 ]\n resTwist[ n - 2 ] = twist[ n - 4 ]\n resRise[ n - 2 ] = rise[ n - 4 ]\n\n // average helix axes to define them on the residues\n\n const resAxis = new Float32Array(3 * n)\n\n copyArray(axis, resAxis, 0, 0, 3)\n copyArray(axis, resAxis, 0, 3, 3)\n\n for (let i = 2; i < n - 2; ++i) {\n v1.fromArray(axis as any, 3 * (i - 2)) // TODO\n v2.fromArray(axis as any, 3 * (i - 1)) // TODO\n\n _axis.addVectors(v2, v1).multiplyScalar(0.5).normalize()\n _axis.toArray(resAxis as any, 3 * i) // TODO\n }\n\n copyArray(axis, resAxis, 3 * n - 12, 3 * n - 6, 3)\n copyArray(axis, resAxis, 3 * n - 12, 3 * n - 3, 3)\n\n return {\n center,\n axis: resAxis,\n bending: resBending,\n radius: resRadius,\n rise: resRise,\n twist: resTwist,\n resdir: resdir\n }\n }\n\n}\n\nexport default Helixorient\n","/**\n * @file Helixbundle\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { ColormakerRegistry } from '../globals'\nimport { AtomPicker } from '../utils/picker'\nimport RadiusFactory, { RadiusParams } from '../utils/radius-factory'\nimport Helixorient, { HelixPosition } from './helixorient'\nimport { calculateMeanVector3, projectPointOnVector } from '../math/vector-utils'\nimport Polymer from '../proxy/polymer'\nimport { ColormakerParameters } from '../color/colormaker';\n\nexport interface Axis {\n axis: Float32Array\n center: Float32Array\n begin: Float32Array\n end: Float32Array\n color: Float32Array\n picking: AtomPicker\n size: Float32Array\n residueOffset: number[]\n residueCount: number[]\n}\n\nclass Helixbundle {\n helixorient: Helixorient;\n position: HelixPosition;\n\n constructor (readonly polymer: Polymer) {\n\n this.helixorient = new Helixorient(polymer)\n this.position = this.helixorient.getPosition()\n }\n\n getAxis (localAngle: number, centerDist: number, ssBorder: boolean, colorParams: { scheme: string} & ColormakerParameters, radiusParams: RadiusParams): Axis {\n localAngle = localAngle || 30\n centerDist = centerDist || 2.5\n ssBorder = ssBorder === undefined ? false : ssBorder\n\n const polymer = this.polymer\n const structure = polymer.structure\n const n = polymer.residueCount\n const residueIndexStart = polymer.residueIndexStart\n\n const pos = this.position\n\n const cp = colorParams || {}\n cp.structure = structure\n\n const colormaker = ColormakerRegistry.getScheme(cp)\n\n const radiusFactory = new RadiusFactory(radiusParams)\n\n let j = 0\n let k = 0\n\n const axis: number[] = []\n const center: number[] = []\n const beg: number[] = []\n const end: number[] = []\n const col: number[] = []\n const pick = []\n const size = []\n const residueOffset = []\n const residueCount = []\n\n let tmpAxis = new Float32Array(n * 3)\n let tmpCenter = new Float32Array(n * 3)\n\n let _axis, _center\n const _beg = new Vector3()\n const _end = new Vector3()\n\n const rp1 = structure.getResidueProxy()\n const rp2 = structure.getResidueProxy()\n const ap = structure.getAtomProxy()\n\n const c1 = new Vector3()\n const c2 = new Vector3()\n\n let split = false\n\n for (let i = 0; i < n; ++i) {\n rp1.index = residueIndexStart + i\n c1.fromArray(pos.center as any, i * 3)\n\n if (i === n - 1) {\n split = true\n } else {\n rp2.index = residueIndexStart + i + 1\n c2.fromArray(pos.center as any, i * 3 + 3)\n\n if (ssBorder && rp1.sstruc !== rp2.sstruc) {\n split = true\n } else if (c1.distanceTo(c2) > centerDist) {\n split = true\n } else if (pos.bending[ i ] > localAngle) {\n split = true\n }\n }\n\n if (split) {\n if (i - j < 4) {\n j = i\n split = false\n continue\n }\n\n ap.index = rp1.traceAtomIndex\n\n // ignore first and last axis\n tmpAxis = pos.axis.subarray(j * 3 + 3, i * 3)\n tmpCenter = pos.center.subarray(j * 3, i * 3 + 3)\n\n _axis = calculateMeanVector3(tmpAxis).normalize()\n _center = calculateMeanVector3(tmpCenter)\n\n _beg.fromArray(tmpCenter as any)\n projectPointOnVector(_beg, _axis, _center)\n\n _end.fromArray(tmpCenter as any, tmpCenter.length - 3)\n projectPointOnVector(_end, _axis, _center)\n\n _axis.subVectors(_end, _beg)\n\n _axis.toArray(axis as any, k)\n _center.toArray(center as any, k)\n _beg.toArray(beg as any, k)\n _end.toArray(end as any, k)\n\n colormaker.atomColorToArray(ap, col, k)\n\n pick.push(ap.index)\n\n size.push(radiusFactory.atomRadius(ap))\n\n residueOffset.push(residueIndexStart + j)\n residueCount.push(residueIndexStart + i + 1 - j)\n\n k += 3\n j = i\n split = false\n }\n }\n\n const picking = new Float32Array(pick)\n\n return {\n axis: new Float32Array(axis),\n center: new Float32Array(center),\n begin: new Float32Array(beg),\n end: new Float32Array(end),\n color: new Float32Array(col),\n picking: new AtomPicker(picking, structure),\n size: new Float32Array(size),\n residueOffset: residueOffset,\n residueCount: residueCount\n }\n }\n}\n\nexport default Helixbundle\n","/**\n * @file Binary Heap\n * @author Alexander Rose \n * @private\n */\n\n/**\n * Binary heap implementation\n * @class\n * @author http://eloquentjavascript.net/appendix2.htm\n * @param {Function} scoreFunction - the heap scoring function\n */\nclass BinaryHeap {\n content: T[] = []\n\n constructor(readonly scoreFunction: (x: T) => number) {\n\n this.scoreFunction = scoreFunction\n }\n\n push (element: T) {\n // Add the new element to the end of the array.\n this.content.push(element)\n\n // Allow it to bubble up.\n this.bubbleUp(this.content.length - 1)\n }\n\n pop () {\n // Store the first element so we can return it later.\n const result = this.content[ 0 ]\n\n // Get the element at the end of the array.\n const end = this.content.pop()\n\n // If there are any elements left, put the end element at the\n // start, and let it sink down.\n if (end && this.content.length > 0) {\n this.content[ 0 ] = end\n this.sinkDown(0)\n }\n\n return result\n }\n\n peek () {\n return this.content[ 0 ]\n }\n\n remove (element: T) {\n const len = this.content.length\n\n // To remove a value, we must search through the array to find it.\n for (let i = 0; i < len; i++) {\n if (this.content[ i ] === element) {\n // When it is found, the process seen in 'pop' is repeated\n // to fill up the hole.\n const end = this.content.pop()\n\n if (end && i !== len - 1) {\n this.content[ i ] = end\n\n if (this.scoreFunction(end) < this.scoreFunction(element)) {\n this.bubbleUp(i)\n } else {\n this.sinkDown(i)\n }\n }\n\n return\n }\n }\n\n throw new Error('Node not found.')\n }\n\n size () {\n return this.content.length\n }\n\n bubbleUp (n: number) {\n // Fetch the element that has to be moved.\n const element = this.content[ n ]\n\n // When at 0, an element can not go up any further.\n while (n > 0) {\n // Compute the parent element's index, and fetch it.\n const parentN = Math.floor((n + 1) / 2) - 1\n const parent = this.content[ parentN ]\n\n // Swap the elements if the parent is greater.\n if (this.scoreFunction(element) < this.scoreFunction(parent)) {\n this.content[ parentN ] = element\n this.content[ n ] = parent\n\n // Update 'n' to continue at the new position.\n n = parentN\n } else {\n // Found a parent that is less, no need to move it further.\n break\n }\n }\n }\n\n sinkDown (n: number) {\n // Look up the target element and its score.\n const length = this.content.length\n const element = this.content[ n ]\n const elemScore = this.scoreFunction(element)\n\n let child1Score = 0\n let child2Score = 0\n\n while (true) {\n // Compute the indices of the child elements.\n const child2N = (n + 1) * 2\n const child1N = child2N - 1\n\n // This is used to store the new position of the element, if any.\n let swap = null\n\n // If the first child exists (is inside the array)...\n if (child1N < length) {\n // Look it up and compute its score.\n const child1 = this.content[ child1N ]\n child1Score = this.scoreFunction(child1)\n\n // If the score is less than our element's, we need to swap.\n if (child1Score < elemScore) swap = child1N\n }\n\n // Do the same checks for the other child.\n if (child2N < length) {\n const child2 = this.content[ child2N ]\n child2Score = this.scoreFunction(child2)\n\n if (child2Score < (swap === null ? elemScore : child1Score)) swap = child2N\n }\n\n // If the element needs to be moved, swap it, and continue.\n if (swap !== null) {\n this.content[ n ] = this.content[ swap ]\n this.content[ swap ] = element\n n = swap\n } else {\n // Otherwise, we are done.\n break\n }\n }\n }\n\n}\n\nexport default BinaryHeap\n","/**\n * @file Kdtree\n * @author Alexander Rose \n * @private\n */\n\nimport { NumberArray } from '../types'\nimport BinaryHeap from './binary-heap'\n\n/**\n * Kdtree\n * @class\n * @author Alexander Rose , 2016\n * @author Roman Bolzern , 2013\n * @author I4DS http://www.fhnw.ch/i4ds, 2013\n * @license MIT License \n * @description\n * k-d Tree for typed arrays of 3d points (e.g. for Float32Array), in-place\n * provides fast nearest neighbour search\n *\n * Based on https://github.com/ubilabs/kd-tree-javascript by Ubilabs\n *\n * Further information (including mathematical properties)\n * http://en.wikipedia.org/wiki/Binary_tree\n * http://en.wikipedia.org/wiki/K-d_tree\n *\n * @example\n * points: [x, y, z, x, y, z, x, y, z, ...]\n * metric: function(a, b){\n * return Math.pow(a[0]-b[0], 2) + Math.pow(a[1]-b[1], 2) + Math.pow(a[2]-b[2], 2);\n * }\n *\n * @param {Float32Array} points - points\n * @param {Function} metric - metric\n */\nclass Kdtree {\n indices: Uint32Array\n nodes: Int32Array\n rootIndex: number\n\n maxDepth = 0\n currentNode = 0\n\n constructor(readonly points: NumberArray, readonly metric: (a: NumberArray, b: NumberArray) => number) {\n const n = points.length / 3\n\n const indices = new Uint32Array(n)\n for (let i = 0; i < n; ++i) {\n indices[ i ] = i\n }\n this.indices = indices\n this.nodes = new Int32Array(n * 4)\n this.rootIndex = this.buildTree(0, -1, 0, n)\n }\n\n buildTree (depth: number, parent: number, arrBegin: number, arrEnd: number) {\n if (depth > this.maxDepth) this.maxDepth = depth\n\n const plength = arrEnd - arrBegin\n if (plength === 0) {\n return -1\n }\n\n const nodeIndex = this.currentNode * 4\n const nodes = this.nodes\n\n this.currentNode += 1\n if (plength === 1) {\n nodes[ nodeIndex ] = arrBegin\n nodes[ nodeIndex + 1 ] = -1\n nodes[ nodeIndex + 2 ] = -1\n nodes[ nodeIndex + 3 ] = parent\n return nodeIndex\n }\n // if(plength <= 32){\n // return nodeIndex;\n // }\n\n const indices = this.indices\n const points = this.points\n\n const arrMedian = arrBegin + Math.floor(plength / 2)\n const currentDim = depth % 3\n\n // inlined quickselect function\n let j, tmp, pivotIndex, pivotValue, storeIndex\n let left = arrBegin\n let right = arrEnd - 1\n while (right > left) {\n pivotIndex = (left + right) >> 1\n pivotValue = points[ indices[ pivotIndex ] * 3 + currentDim ]\n // swap( pivotIndex, right );\n tmp = indices[ pivotIndex ]\n indices[ pivotIndex ] = indices[ right ]\n indices[ right ] = tmp\n storeIndex = left\n for (j = left; j < right; ++j) {\n if (points[ indices[ j ] * 3 + currentDim ] < pivotValue) {\n // swap( storeIndex, j );\n tmp = indices[ storeIndex ]\n indices[ storeIndex ] = indices[ j ]\n indices[ j ] = tmp\n ++storeIndex\n }\n }\n // swap( right, storeIndex );\n tmp = indices[ right ]\n indices[ right ] = indices[ storeIndex ]\n indices[ storeIndex ] = tmp\n pivotIndex = storeIndex\n if (arrMedian === pivotIndex) {\n break\n } else if (arrMedian < pivotIndex) {\n right = pivotIndex - 1\n } else {\n left = pivotIndex + 1\n }\n }\n\n nodes[ nodeIndex ] = arrMedian\n nodes[ nodeIndex + 1 ] = this.buildTree(depth + 1, nodeIndex, arrBegin, arrMedian)\n nodes[ nodeIndex + 2 ] = this.buildTree(depth + 1, nodeIndex, arrMedian + 1, arrEnd)\n nodes[ nodeIndex + 3 ] = parent\n\n return nodeIndex\n }\n\n getNodeDepth (nodeIndex: number): number {\n const parentIndex = this.nodes[ nodeIndex + 3 ]\n return (parentIndex === -1) ? 0 : this.getNodeDepth(parentIndex) + 1\n }\n\n // TODO\n // function getNodePos (node) {}\n\n /**\n * find nearest points\n * @param {Array} point - array of size 3\n * @param {Integer} maxNodes - max amount of nodes to return\n * @param {Float} maxDistance - maximum distance of point to result nodes\n * @return {Array} array of point, distance pairs\n */\n nearest (point: NumberArray, maxNodes: number, maxDistance: number) {\n const bestNodes = new BinaryHeap<[number, number]>(e => -e[ 1 ])\n\n const nodes = this.nodes\n const points = this.points\n const indices = this.indices\n\n const nearestSearch = (nodeIndex: number) => {\n let bestChild, otherChild\n const dimension = this.getNodeDepth(nodeIndex) % 3\n const pointIndex = indices[ nodes[ nodeIndex ] ] * 3\n const ownPoint = [\n points[ pointIndex + 0 ],\n points[ pointIndex + 1 ],\n points[ pointIndex + 2 ]\n ]\n const ownDistance = this.metric(point, ownPoint)\n\n function saveNode (nodeIndex: number, distance: number) {\n bestNodes.push([ nodeIndex, distance ])\n if (bestNodes.size() > maxNodes) {\n bestNodes.pop()\n }\n }\n\n const leftIndex = nodes[ nodeIndex + 1 ]\n const rightIndex = nodes[ nodeIndex + 2 ]\n\n // if it's a leaf\n if (rightIndex === -1 && leftIndex === -1) {\n if ((bestNodes.size() < maxNodes || ownDistance < bestNodes.peek()[ 1 ]) &&\n ownDistance <= maxDistance\n ) {\n saveNode(nodeIndex, ownDistance)\n }\n return\n }\n\n if (rightIndex === -1) {\n bestChild = leftIndex\n } else if (leftIndex === -1) {\n bestChild = rightIndex\n } else {\n if (point[ dimension ] <= points[ pointIndex + dimension ]) {\n bestChild = leftIndex\n } else {\n bestChild = rightIndex\n }\n }\n\n // recursive search\n nearestSearch(bestChild)\n\n if ((bestNodes.size() < maxNodes || ownDistance < bestNodes.peek()[ 1 ]) &&\n ownDistance <= maxDistance\n ) {\n saveNode(nodeIndex, ownDistance)\n }\n\n // if there's still room or the current distance is nearer than the best distance\n const linearPoint = []\n for (let i = 0; i < 3; i += 1) {\n if (i === dimension) {\n linearPoint[ i ] = point[ i ]\n } else {\n linearPoint[ i ] = points[ pointIndex + i ]\n }\n }\n const linearDistance = this.metric(linearPoint, ownPoint)\n\n if ((bestNodes.size() < maxNodes || Math.abs(linearDistance) < bestNodes.peek()[ 1 ]) &&\n Math.abs(linearDistance) <= maxDistance\n ) {\n if (bestChild === leftIndex) {\n otherChild = rightIndex\n } else {\n otherChild = leftIndex\n }\n if (otherChild !== -1) {\n nearestSearch(otherChild)\n }\n }\n }\n\n nearestSearch(this.rootIndex)\n\n const result = []\n for (let i = 0, il = Math.min(bestNodes.size(), maxNodes); i < il; i += 1) {\n result.push(bestNodes.content[ i ])\n }\n\n return result\n }\n\n verify (nodeIndex?: number, depth = 0) {\n let count = 1\n\n if (nodeIndex === undefined) {\n nodeIndex = this.rootIndex\n }\n\n if (nodeIndex === -1) {\n throw new Error('node is null')\n }\n\n const dim = depth % 3\n const nodes = this.nodes\n const points = this.points\n const indices = this.indices\n\n const leftIndex = nodes[ nodeIndex + 1 ]\n const rightIndex = nodes[ nodeIndex + 2 ]\n\n if (leftIndex !== -1) {\n if (points[ indices[ nodes[ leftIndex ] ] * 3 + dim ] >\n points[ indices[ nodes[ nodeIndex ] ] * 3 + dim ]\n ) {\n throw new Error('left child is > parent!')\n }\n count += this.verify(leftIndex, depth + 1)\n }\n\n if (rightIndex !== -1) {\n if (points[ indices[ nodes[ rightIndex ] ] * 3 + dim ] <\n points[ indices[ nodes[ nodeIndex ] ] * 3 + dim ]\n ) {\n throw new Error('right child is < parent!')\n }\n count += this.verify(rightIndex, depth + 1)\n }\n\n return count\n }\n}\n\nexport default Kdtree\n","/**\n * @file Atom Proxy\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { NumberArray } from '../types'\nimport {\n Elements,\n SecStrucHelix, SecStrucSheet, SecStrucTurn,\n ProteinType, RnaType, DnaType, WaterType, IonType, SaccharideType,\n CgProteinBackboneType, CgRnaBackboneType, CgDnaBackboneType\n} from '../structure/structure-constants'\n\nimport Structure from '../structure/structure'\n\nimport ChainStore from '../store/chain-store'\nimport ResidueStore from '../store/residue-store'\nimport AtomStore from '../store/atom-store'\n\nimport AtomMap from '../store/atom-map'\nimport ResidueMap from '../store/residue-map'\n\nimport BondProxy from '../proxy/bond-proxy'\nimport AtomType from '../store/atom-type';\nimport ResidueType from '../store/residue-type';\nimport ResidueProxy from './residue-proxy';\nimport Entity from '../structure/entity';\nimport BondHash from '../store/bond-hash';\n\n/**\n * Atom proxy\n */\nclass AtomProxy {\n index: number\n\n chainStore: ChainStore\n residueStore: ResidueStore\n atomStore: AtomStore\n\n residueMap: ResidueMap\n atomMap: AtomMap\n\n /**\n * @param {Structure} structure - the structure\n * @param {Integer} index - the index\n */\n constructor (readonly structure: Structure, index = 0) {\n this.index = index\n this.chainStore = structure.chainStore\n this.residueStore = structure.residueStore\n this.atomStore = structure.atomStore\n this.residueMap = structure.residueMap\n this.atomMap = structure.atomMap\n }\n\n /**\n * @type {BondHash}\n */\n get bondHash (): BondHash|undefined { return this.structure.bondHash }\n\n /**\n * Molecular enity\n * @type {Entity}\n */\n get entity (): Entity {\n return this.structure.entityList[ this.entityIndex ]\n }\n get entityIndex () {\n return this.chainStore.entityIndex[ this.chainIndex ]\n }\n get modelIndex () {\n return this.chainStore.modelIndex[ this.chainIndex ]\n }\n get chainIndex () {\n return this.residueStore.chainIndex[ this.residueIndex ]\n }\n /**\n * @type {ResidueProxy}\n */\n get residue (): ResidueProxy {\n console.warn('residue - might be expensive')\n return this.structure.getResidueProxy(this.residueIndex)\n }\n\n get residueIndex () {\n return this.atomStore.residueIndex[ this.index ]\n }\n set residueIndex (value) {\n this.atomStore.residueIndex[ this.index ] = value\n }\n\n //\n\n /**\n * Secondary structure code\n * @type {String}\n */\n get sstruc () {\n return this.residueStore.getSstruc(this.residueIndex)\n }\n /**\n * Insertion code\n * @type {String}\n */\n get inscode () {\n return this.residueStore.getInscode(this.residueIndex)\n }\n /**\n * Residue number/label\n * @type {Integer}\n */\n get resno () {\n return this.residueStore.resno[ this.residueIndex ]\n }\n /**\n * Chain name\n * @type {String}\n */\n get chainname () {\n return this.chainStore.getChainname(this.chainIndex)\n }\n /**\n * Chain id\n * @type {String}\n */\n get chainid () {\n return this.chainStore.getChainid(this.chainIndex)\n }\n\n //\n\n /**\n * @type {ResidueType}\n */\n get residueType (): ResidueType {\n return this.residueMap.get(this.residueStore.residueTypeId[ this.residueIndex ])\n }\n /**\n * @type {AtomType}\n */\n get atomType (): AtomType {\n return this.atomMap.get(this.atomStore.atomTypeId[ this.index ])\n }\n get residueAtomOffset () {\n return this.residueStore.atomOffset[ this.residueIndex ]\n }\n\n //\n\n /**\n * Residue name\n */\n get resname () {\n return this.residueType.resname\n }\n /**\n * Hetero flag\n */\n get hetero () {\n return this.residueType.hetero\n }\n\n //\n\n /**\n * Atom name\n */\n get atomname () {\n return this.atomType.atomname\n }\n /**\n * Atomic number\n */\n get number () {\n return this.atomType.number\n }\n /**\n * Element\n */\n get element () {\n return this.atomType.element\n }\n /**\n * Van-der-Waals radius\n */\n get vdw () {\n return this.atomType.vdw\n }\n /**\n * Covalent radius\n */\n get covalent () {\n return this.atomType.covalent\n }\n\n //\n\n /**\n * X coordinate\n */\n get x () {\n return this.atomStore.x[ this.index ]\n }\n set x (value) {\n this.atomStore.x[ this.index ] = value\n }\n\n /**\n * Y coordinate\n */\n get y () {\n return this.atomStore.y[ this.index ]\n }\n set y (value) {\n this.atomStore.y[ this.index ] = value\n }\n\n /**\n * Z coordinate\n */\n get z () {\n return this.atomStore.z[ this.index ]\n }\n set z (value) {\n this.atomStore.z[ this.index ] = value\n }\n\n /**\n * Serial number\n */\n get serial () {\n return this.atomStore.serial[ this.index ]\n }\n set serial (value) {\n this.atomStore.serial[ this.index ] = value\n }\n\n /**\n * B-factor value\n */\n get bfactor () {\n return this.atomStore.bfactor[ this.index ]\n }\n set bfactor (value) {\n this.atomStore.bfactor[ this.index ] = value\n }\n\n /**\n * Occupancy value\n */\n get occupancy () {\n return this.atomStore.occupancy[ this.index ]\n }\n set occupancy (value) {\n this.atomStore.occupancy[ this.index ] = value\n }\n\n /**\n * Alternate location identifier\n */\n get altloc () {\n return this.atomStore.getAltloc(this.index)\n }\n set altloc (value) {\n this.atomStore.setAltloc(this.index, value)\n }\n\n /**\n * Partial charge\n */\n get partialCharge () {\n return this.atomStore.partialCharge ? this.atomStore.partialCharge[ this.index ] : null\n }\n set partialCharge (value) {\n if (this.atomStore.partialCharge) {\n this.atomStore.partialCharge[ this.index ] = value as number\n }\n }\n\n /**\n * Explicit radius\n */\n get radius () {\n return this.atomStore.radius ? this.atomStore.radius[ this.index ] : null\n }\n set radius (value) {\n if (this.atomStore.radius) {\n this.atomStore.radius[ this.index ] = value as number\n }\n }\n\n /**\n * Formal charge\n */\n get formalCharge () {\n return this.atomStore.formalCharge ? this.atomStore.formalCharge[ this.index ] : null\n }\n set formalCharge (value) {\n if (this.atomStore.formalCharge) {\n this.atomStore.formalCharge[ this.index ] = value as number\n }\n }\n\n /**\n * Aromaticity flag\n */\n get aromatic () {\n if (this.atomStore.aromatic) {\n return this.atomStore.aromatic[ this.index ] as number\n } else {\n return this.residueType.isAromatic(this) ? 1 : 0\n }\n }\n set aromatic (value) {\n if (this.atomStore.aromatic) {\n this.atomStore.aromatic[ this.index ] = value as number\n }\n }\n\n //\n\n get bondCount () {\n return this.bondHash!.countArray[ this.index ] // TODO\n }\n\n //\n\n /**\n * Iterate over each bond\n * @param {function(bond: BondProxy)} callback - iterator callback function\n * @param {BondProxy} [bp] - optional target bond proxy for use in the callback\n * @return {undefined}\n */\n eachBond (callback: (bp: BondProxy) => void, bp?: BondProxy) {\n bp = bp || this.structure._bp\n const idx = this.index\n const bondHash = this.bondHash! // TODO\n const indexArray = bondHash.indexArray\n const n = bondHash.countArray[ idx ]\n const offset = bondHash.offsetArray[ idx ]\n\n for (let i = 0; i < n; ++i) {\n bp.index = indexArray[ offset + i ]\n callback(bp)\n }\n }\n\n /**\n * Iterate over each bonded atom\n * @param {function(atom: AtomProxy)} callback - iterator callback function\n * @param {AtomProxy} [ap] - optional target atom proxy for use in the callback\n * @return {undefined}\n */\n eachBondedAtom (callback: (ap: AtomProxy) => void, _ap?: AtomProxy) {\n const ap = _ap ? _ap : this.structure._ap\n const idx = this.index\n\n this.eachBond(function (bp) {\n ap.index = idx !== bp.atomIndex1 ? bp.atomIndex1 : bp.atomIndex2\n callback(ap)\n })\n this.index = idx\n }\n\n /**\n * Check if this atom is bonded to the given atom,\n * assumes both atoms are from the same structure\n * @param {AtomProxy} ap - the given atom\n * @return {Boolean} whether a bond exists or not\n */\n hasBondTo (ap: AtomProxy) {\n let flag = false\n this.eachBondedAtom(function (bap) {\n if (ap.index === bap.index) flag = true\n })\n return flag\n }\n\n bondToElementCount (element: Elements) {\n let count = 0\n const idx = this.index // Avoid reentrancy problems\n this.eachBondedAtom(function (bap) {\n if (bap.number === element) count += 1\n })\n this.index = idx\n return count\n }\n\n hasBondToElement (element: Elements) {\n return this.bondToElementCount(element) > 0\n }\n\n //\n\n /**\n * If atom is part of a backbone\n * @return {Boolean} flag\n */\n isBackbone () {\n const backboneIndexList = this.residueType.backboneIndexList\n if (backboneIndexList.length > 0) {\n return backboneIndexList.includes(this.index - this.residueAtomOffset)\n } else {\n return false\n }\n }\n\n /**\n * If atom is part of a polymer\n * @return {Boolean} flag\n */\n isPolymer () {\n if (this.structure.entityList.length > 0) {\n return this.entity.isPolymer()\n } else {\n const moleculeType = this.residueType.moleculeType\n return (\n moleculeType === ProteinType ||\n moleculeType === RnaType ||\n moleculeType === DnaType\n )\n }\n }\n\n /**\n * If atom is part of a sidechin\n * @return {Boolean} flag\n */\n isSidechain () {\n return this.isPolymer() && !this.isBackbone()\n }\n\n /**\n * If atom is part of a coarse-grain group\n * @return {Boolean} flag\n */\n isCg () {\n const backboneType = this.residueType.backboneType\n return (\n backboneType === CgProteinBackboneType ||\n backboneType === CgRnaBackboneType ||\n backboneType === CgDnaBackboneType\n )\n }\n\n isTrace () {\n return this.index === (this.residueType.traceAtomIndex + this.residueAtomOffset)\n }\n\n /**\n * If atom is part of a hetero group\n * @return {Boolean} flag\n */\n isHetero () {\n return this.residueType.hetero === 1\n }\n\n /**\n * If atom is part of a protein molecule\n * @return {Boolean} flag\n */\n isProtein () {\n return this.residueType.moleculeType === ProteinType\n }\n\n /**\n * If atom is part of a nucleic molecule\n * @return {Boolean} flag\n */\n isNucleic () {\n const moleculeType = this.residueType.moleculeType\n return moleculeType === RnaType || moleculeType === DnaType\n }\n\n /**\n * If atom is part of a rna\n * @return {Boolean} flag\n */\n isRna () {\n return this.residueType.moleculeType === RnaType\n }\n\n /**\n * If atom is part of a dna\n * @return {Boolean} flag\n */\n isDna () {\n return this.residueType.moleculeType === DnaType\n }\n\n /**\n * If atom is part of a water molecule\n * @return {Boolean} flag\n */\n isWater () {\n return this.residueType.moleculeType === WaterType\n }\n\n /**\n * If atom is part of an ion\n * @return {Boolean} flag\n */\n isIon () {\n return this.residueType.moleculeType === IonType\n }\n\n /**\n * If atom is part of a saccharide\n * @return {Boolean} flag\n */\n isSaccharide () {\n return this.residueType.moleculeType === SaccharideType\n }\n\n /**\n * If atom is part of a helix\n * @return {Boolean} flag\n */\n isHelix () {\n return SecStrucHelix.includes(this.sstruc)\n }\n\n /**\n * If atom is part of a sheet\n * @return {Boolean} flag\n */\n isSheet () {\n return SecStrucSheet.includes(this.sstruc)\n }\n\n /**\n * If atom is part of a turn\n * @return {Boolean} flag\n */\n isTurn () {\n return SecStrucTurn.includes(this.sstruc) && this.isProtein()\n }\n\n isBonded () {\n return this.bondHash!.countArray[ this.index ] !== 0 // TODO\n }\n\n /**\n * If atom is part of a ring\n * @return {Boolean} flag\n */\n isRing () {\n const atomRings = this.residueType.getRings()!.atomRings // TODO\n return atomRings[ this.index - this.residueAtomOffset ] !== undefined\n }\n\n isAromatic () {\n return this.aromatic === 1\n }\n\n isPolarHydrogen () {\n let result = false\n\n if (this.number !== 1) return result\n\n result = !this.hasBondToElement(Elements.C)\n\n return result\n }\n\n isMetal () { return this.atomType.isMetal() }\n isNonmetal () { return this.atomType.isNonmetal() }\n isMetalloid () { return this.atomType.isMetalloid() }\n isHalogen () { return this.atomType.isHalogen() }\n isDiatomicNonmetal () { return this.atomType.isDiatomicNonmetal() }\n isPolyatomicNonmetal () { return this.atomType.isPolyatomicNonmetal() }\n isAlkaliMetal () { return this.atomType.isAlkaliMetal() }\n isAlkalineEarthMetal () { return this.atomType.isAlkalineEarthMetal() }\n isNobleGas () { return this.atomType.isNobleGas() }\n isTransitionMetal () { return this.atomType.isTransitionMetal() }\n isPostTransitionMetal () { return this.atomType.isPostTransitionMetal() }\n isLanthanide () { return this.atomType.isLanthanide() }\n isActinide () { return this.atomType.isActinide() }\n\n getDefaultValence () { return this.atomType.getDefaultValence() }\n getValenceList () { return this.atomType.getValenceList() }\n getOuterShellElectronCount () { return this.atomType.getOuterShellElectronCount() }\n\n /**\n * Distance to another atom\n * @param {AtomProxy} atom - the other atom\n * @return {Number} the distance\n */\n distanceTo (atom: AtomProxy) {\n const taa = this.atomStore\n const aaa = atom.atomStore\n const ti = this.index\n const ai = atom.index\n const x = taa.x[ ti ] - aaa.x[ ai ]\n const y = taa.y[ ti ] - aaa.y[ ai ]\n const z = taa.z[ ti ] - aaa.z[ ai ]\n const distSquared = x * x + y * y + z * z\n return Math.sqrt(distSquared)\n }\n\n /**\n * If connected to another atom\n * @param {AtomProxy} atom - the other atom\n * @return {Boolean} flag\n */\n connectedTo (atom: AtomProxy) {\n const taa = this.atomStore\n const aaa = atom.atomStore\n const ti = this.index\n const ai = atom.index\n\n if (taa.altloc && aaa.altloc) {\n const ta = taa.altloc[ ti ] // use Uint8 value to compare\n const aa = aaa.altloc[ ai ] // no need to convert to char\n // 0 is the Null character, 32 is the space character\n if (!(ta === 0 || aa === 0 || ta === 32 || aa === 32 || (ta === aa))) return false\n }\n\n const x = taa.x[ ti ] - aaa.x[ ai ]\n const y = taa.y[ ti ] - aaa.y[ ai ]\n const z = taa.z[ ti ] - aaa.z[ ai ]\n\n const distSquared = x * x + y * y + z * z\n\n // if( this.isCg() ) console.log( this.qualifiedName(), Math.sqrt( distSquared ), distSquared )\n if (distSquared < 48.0 && this.isCg()) return true\n\n if (isNaN(distSquared)) return false\n\n const d = this.covalent + atom.covalent\n const d1 = d + 0.3\n const d2 = d - 0.5\n\n return distSquared < (d1 * d1) && distSquared > (d2 * d2)\n }\n\n /**\n * Set atom position from array\n * @param {Array|TypedArray} array - input array\n * @param {Integer} [offset] - the offset\n * @return {AtomProxy} this object\n */\n positionFromArray (array: NumberArray, offset = 0) {\n this.x = array[ offset + 0 ]\n this.y = array[ offset + 1 ]\n this.z = array[ offset + 2 ]\n\n return this\n }\n\n /**\n * Write atom position to array\n * @param {Array|TypedArray} [array] - target array\n * @param {Integer} [offset] - the offset\n * @return {Array|TypedArray} target array\n */\n positionToArray (array: NumberArray = [], offset = 0) {\n const index = this.index\n const atomStore = this.atomStore\n\n array[ offset + 0 ] = atomStore.x[ index ]\n array[ offset + 1 ] = atomStore.y[ index ]\n array[ offset + 2 ] = atomStore.z[ index ]\n\n return array\n }\n\n /**\n * Write atom position to vector\n * @param {Vector3} [v] - target vector\n * @return {Vector3} target vector\n */\n positionToVector3 (v?: Vector3) {\n if (v === undefined) v = new Vector3()\n\n v.x = this.x\n v.y = this.y\n v.z = this.z\n\n return v\n }\n\n /**\n * Set atom position from vector\n * @param {Vector3} v - input vector\n * @return {AtomProxy} this object\n */\n positionFromVector3 (v: Vector3) {\n this.x = v.x\n this.y = v.y\n this.z = v.z\n\n return this\n }\n\n /**\n * Add vector to atom position\n * @param {Vector3} v - input vector\n * @return {AtomProxy} this object\n */\n positionAdd (v: Vector3|AtomProxy) {\n this.x += v.x\n this.y += v.y\n this.z += v.z\n\n return this\n }\n\n /**\n * Subtract vector from atom position\n * @param {Vector3} v - input vector\n * @return {AtomProxy} this object\n */\n positionSub (v: Vector3|AtomProxy) {\n this.x -= v.x\n this.y -= v.y\n this.z -= v.z\n\n return this\n }\n\n /**\n * Get intra group/residue bonds\n * @param {Boolean} firstOnly - immediately return the first connected atomIndex\n * @return {Integer[]|Integer|undefined} connected atomIndices\n */\n getResidueBonds (firstOnly = false) {\n const residueAtomOffset = this.residueAtomOffset\n const relativeIndex = this.index - this.residueAtomOffset\n const bonds = this.residueType.getBonds()! // TODO\n const atomIndices1 = bonds.atomIndices1\n const atomIndices2 = bonds.atomIndices2\n let idx1, idx2, connectedAtomIndex\n let connectedAtomIndices: number[]|undefined\n\n if (!firstOnly) connectedAtomIndices = []\n\n idx1 = atomIndices1.indexOf(relativeIndex)\n while (idx1 !== -1) {\n connectedAtomIndex = atomIndices2[ idx1 ] + residueAtomOffset\n if (connectedAtomIndices) {\n connectedAtomIndices.push(connectedAtomIndex)\n idx1 = atomIndices1.indexOf(relativeIndex, idx1 + 1)\n } else {\n return connectedAtomIndex\n }\n }\n\n idx2 = atomIndices2.indexOf(relativeIndex)\n while (idx2 !== -1) {\n connectedAtomIndex = atomIndices1[ idx2 ] + residueAtomOffset\n if (connectedAtomIndices) {\n connectedAtomIndices.push(connectedAtomIndex)\n idx2 = atomIndices2.indexOf(relativeIndex, idx2 + 1)\n } else {\n return connectedAtomIndex\n }\n }\n\n return connectedAtomIndices\n }\n\n //\n\n qualifiedName (noResname = false) {\n var name = ''\n if (this.resname && !noResname) name += '[' + this.resname + ']'\n if (this.resno !== undefined) name += this.resno\n if (this.inscode) name += '^' + this.inscode\n if (this.chainname) name += ':' + this.chainname\n if (this.atomname) name += '.' + this.atomname\n if (this.altloc) name += '%' + this.altloc\n if (this.structure.modelStore.count > 1) name += '/' + this.modelIndex\n return name\n }\n\n /**\n * Clone object\n * @return {AtomProxy} cloned atom\n */\n clone () {\n return new AtomProxy(this.structure, this.index)\n }\n\n toObject () {\n return {\n index: this.index,\n residueIndex: this.residueIndex,\n\n resname: this.resname,\n x: this.x,\n y: this.y,\n z: this.z,\n element: this.element,\n chainname: this.chainname,\n resno: this.resno,\n serial: this.serial,\n vdw: this.vdw,\n covalent: this.covalent,\n hetero: this.hetero,\n bfactor: this.bfactor,\n altloc: this.altloc,\n atomname: this.atomname,\n modelIndex: this.modelIndex\n }\n }\n}\n\nexport default AtomProxy\n","/**\n * @file Kdtree\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { Debug, Log } from '../globals'\nimport _Kdtree from '../utils/kdtree'\nimport Structure from '../structure/structure'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ResidueProxy from '../proxy/residue-proxy'\n\nfunction euclideanDistSq(a: number[], b: number[]) {\n const dx = a[0] - b[0]\n const dy = a[1] - b[1]\n const dz = a[2] - b[2]\n return dx * dx + dy * dy + dz * dz\n}\n\nfunction euclideanDist(a: number[], b: number[]) {\n return Math.sqrt(euclideanDistSq(a, b))\n}\n\nconst pointArray = new Float32Array(3)\n\nclass Kdtree {\n points: Float32Array\n atomIndices: Uint32Array\n kdtree: _Kdtree\n\n constructor(structure: Structure|ResidueProxy, useSquaredDist = false) {\n if (Debug) Log.time('Kdtree build')\n\n const metric = useSquaredDist ? euclideanDistSq : euclideanDist\n\n const points = new Float32Array(structure.atomCount * 3)\n const atomIndices = new Uint32Array(structure.atomCount)\n let i = 0\n\n structure.eachAtom(function (ap) {\n points[ i + 0 ] = ap.x\n points[ i + 1 ] = ap.y\n points[ i + 2 ] = ap.z\n atomIndices[ i / 3 ] = ap.index\n i += 3\n })\n\n this.atomIndices = atomIndices\n this.points = points\n this.kdtree = new _Kdtree(points, metric)\n\n if (Debug) Log.timeEnd('Kdtree build')\n\n // console.log(\"this.kdtree.verify()\", this.kdtree.verify())\n }\n\n nearest (point: number[]|Vector3, maxNodes: number, maxDistance: number) {\n // Log.time( \"Kdtree nearest\" );\n\n if (point instanceof Vector3) {\n point.toArray(pointArray as any)\n } else if (point instanceof AtomProxy) {\n point.positionToArray(pointArray)\n }\n\n const nodeList = this.kdtree.nearest(pointArray, maxNodes, maxDistance)\n\n const indices = this.kdtree.indices\n const nodes = this.kdtree.nodes\n const atomIndices = this.atomIndices\n const resultList = []\n\n for (let i = 0, n = nodeList.length; i < n; ++i) {\n const d = nodeList[ i ]\n const nodeIndex = d[ 0 ]\n const dist = d[ 1 ]\n\n resultList.push({\n index: atomIndices[ indices[ nodes[ nodeIndex ] ] ],\n distance: dist\n })\n }\n\n // Log.timeEnd( \"Kdtree nearest\" );\n\n return resultList\n }\n}\n\nexport default Kdtree\n","/**\n * @file Symmetry Constants\n * @author Alexander Rose \n * @private\n */\n\nexport const SymOpCode: { [k: string]: string } = {\n ' ': 'X',\n '!': 'Y',\n '#': 'Z',\n '$': '-X',\n '%': '-Y',\n '&': '-Z',\n \"'\": 'Y+1/2',\n '(': '1/2+X',\n ')': '1/2+Y',\n '*': '1/2-X',\n '+': '1/2+Z',\n ',': '1/2-Y',\n '-': '1/2-Z',\n '.': 'X+1/2',\n '/': 'Z+1/2',\n '0': '-X+1/2',\n '1': '-Y+1/2',\n '2': '-Z+1/2',\n '3': '1/4+X',\n '4': '1/4-Y',\n '5': '1/4+Z',\n '6': '1/4-X',\n '7': '1/4+Y',\n '8': '3/4-Y',\n '9': '3/4+Z',\n ':': '3/4+Y',\n ';': '3/4+X',\n '<': '3/4-X',\n '=': '1/4-Z',\n '>': '3/4-Z',\n '?': 'X-Y',\n '@': 'Y-X',\n 'A': 'Z+1/3',\n 'B': 'Z+2/3',\n 'C': 'X+2/3',\n 'D': 'Y+1/3',\n 'E': '-Y+2/3',\n 'F': 'X-Y+1/3',\n 'G': 'Y-X+2/3',\n 'H': '-X+1/3',\n 'I': 'X+1/3',\n 'J': 'Y+2/3',\n 'K': '-Y+1/3',\n 'L': 'X-Y+2/3',\n 'M': 'Y-X+1/3',\n 'N': '-X+2/3',\n 'O': '2/3+X',\n 'P': '1/3+Y',\n 'Q': '1/3+Z',\n 'R': '2/3-Y',\n 'S': '1/3+X-Y',\n 'T': '2/3+Y-X',\n 'U': '1/3-X',\n 'V': '2/3-X',\n 'W': '1/3-Y',\n 'X': '1/3-Z',\n 'Y': '2/3+Y',\n 'Z': '1/3+Y-X',\n '[': '2/3+X-Y',\n ']': '1/3+X',\n '^': '2/3+Z',\n '_': '2/3-Z',\n '`': '5/6+Z',\n 'a': '1/6+Z',\n 'b': '5/6-Z',\n 'c': '1/6-Z',\n 'd': 'Z+5/6',\n 'e': 'Z+1/6',\n 'f': 'Z+1/4',\n 'g': '+Y'\n}\n\n// encoded, originally from CCP4 symop.lib\nexport const EncodedSymOp: { [k: string]: string } = {\n 'P 1': ' !#',\n 'P -1': ' !#$%&',\n 'P 1 2 1': ' !#$!&',\n 'P 1 21 1': \" !#$'&\",\n 'C 1 2 1': ' !#$!&()#*)&',\n 'P 1 m 1': ' !# %#',\n 'P 1 c 1': ' !# %+',\n 'C 1 m 1': ' !# %#()#(,#',\n 'C 1 c 1': ' !# %+()#(,+',\n 'P 1 2/m 1': ' !# %#$!&$%&',\n 'P 1 21/m 1': ' !#$)&$%& ,#',\n 'C 1 2/m 1': ' !# %#$!&$%&()#(,#*)&*,&',\n 'P 1 2/c 1': ' !#$!-$%& %+',\n 'P 1 21/c 1': ' !#$%&$)- ,+',\n 'C 1 2/c 1': ' !#$!-$%& %+()#*)-*,&(,+',\n 'P 2 2 2': ' !#$%#$!& %&',\n 'P 2 2 21': ' !#$%+$!- %&',\n 'P 21 21 2': ' !#$%#*)&(,&',\n 'P 21 21 21': ' !#*%+$)-(,&',\n 'C 2 2 21': ' !#$%+$!- %&()#*,+*)-(,&',\n 'C 2 2 2': ' !#$%#$!& %&()#*,#*)&(,&',\n 'F 2 2 2': ' !#$%#$!& %& )+$,+$)- ,-(!+*%+*!-(%-()#*,#*)&(,&',\n 'I 2 2 2': \" !#$%# %&$!&.'/01/.120'2\",\n 'I 21 21 21': ' !#*%+$)-(,&()+$,#*!& %-',\n 'P m m 2': ' !#$%# %#$!#',\n 'P m c 21': ' !#$%+ %+$!#',\n 'P c c 2': ' !#$%# %+$!+',\n 'P m a 2': ' !#$%#(%#*!#',\n 'P c a 21': ' !#$%+(%#*!+',\n 'P n c 2': ' !#$%# ,+$)+',\n 'P m n 21': ' !#*%+(%+$!#',\n 'P b a 2': ' !#$%#(,#*)#',\n 'P n a 21': ' !#$%+(,#*)+',\n 'P n n 2': ' !#$%#(,+*)+',\n 'C m m 2': ' !#$%# %#$!#()#*,#(,#*)#',\n 'C m c 21': ' !#$%+ %+$!#()#*,+(,+*)#',\n 'C c c 2': ' !#$%# %+$!+()#*,#(,+*)+',\n 'A m m 2': ' !#$%# %#$!# )+$,+ ,+$)+',\n 'A b m 2': ' !#$%# ,#$)# )+$,+ %+$!+',\n 'A m a 2': ' !#$%#(%#*!# )+$,+(,+*)+',\n 'A b a 2': ' !#$%#(,#*)# )+$,+(%+*!+',\n 'F m m 2': ' !#$%# %#$!# )+$,+ ,+$)+(!+*%+(%+*!+()#*,#(,#*)#',\n 'F d d 2': ' !#$%#345675 )+$,+3896:9(!+*%+;49<79()#*,#;85<:5',\n 'I m m 2': ' !#$%# %#$!#()+*,+(,+*)+',\n 'I b a 2': ' !#$%#(,#*)#()+*,+ %+$!+',\n 'I m a 2': ' !#$%#(%#*!#()+*,+ ,+$)+',\n 'P 2/m 2/m 2/m': ' !#$%#$!& %&$%& !& %#$!#',\n 'P 2/n 2/n 2/n': ' !#$%#$!& %&*,-()-(,+*)+',\n 'P 2/c 2/c 2/m': ' !#$%#$!- %-$%& !& %+$!+',\n 'P 2/b 2/a 2/n': ' !#$%#$!& %&*,&()&(,#*)#',\n 'P 21/m 2/m 2/a': ' !#*%#$!&(%&$%&(!& %#*!#',\n 'P 2/n 21/n 2/a': ' !#*%#*)- ,-$%&(!&(,+$)+',\n 'P 2/m 2/n 21/a': ' !#*%+*!- %&$%&(!-(%+$!#',\n 'P 21/c 2/c 2/a': ' !#*%#$!-(%-$%&(!& %+*!+',\n 'P 21/b 21/a 2/m': ' !#$%#*)&(,&$%& !&(,#*)#',\n 'P 21/c 21/c 2/n': ' !#*,#$)-(%-$%&()& ,+*!+',\n 'P 2/b 21/c 21/m': ' !#$%+$)- ,&$%& !- ,+$)#',\n 'P 21/n 21/n 2/m': ' !#$%#*)-(,-$%& !&(,+*)+',\n 'P 21/m 21/m 2/n': \" !#$%#*'&.,&*,&.'& %#$!#\",\n 'P 21/b 2/c 21/n': ' !#*,+$!-(,&$%&()- %+*)#',\n 'P 21/b 21/c 21/a': ' !#*%+$)-(,&$%&(!- ,+*)#',\n 'P 21/n 21/m 21/a': \" !#0%/$'&.12$%&.!2 1#0'/\",\n 'C 2/m 2/c 21/m': ' !#$%+$!- %&$%& !- %+$!#()#*,+*)-(,&*,&()-(,+*)#',\n 'C 2/m 2/c 21/a': ' !#$,+$)- %&$%& )- ,+$!#()#*%+*!-(,&*,&(!-(%+*)#',\n 'C 2/m 2/m 2/m': ' !#$%#$!& %&$%& !& %#$!#()#*,#*)&(,&*,&()&(,#*)#',\n 'C 2/c 2/c 2/m': ' !#$%#$!- %-$%& !& %+$!+()#*,#*)-(,-*,&()&(,+*)+',\n 'C 2/m 2/m 2/a': ' !#$,#$)& %&$%& )& ,#$!#()#*%#*!&(,&*,&(!&(%#*)#',\n 'C 2/c 2/c 2/a': ' !#*,#$!&(,&$,-(!- ,+*!+()#$%#*)& %&*%- )-(%+$)+',\n 'F 2/m 2/m 2/m': ' !#$%#$!& %&$%& !& %#$!# )+$,+$)- ,-$,- )- ,+$)+(!+*%+*!-(%-*%-(!-(%+*!+()#*,#*)&(,&*,&()&(,#*)#',\n 'F 2/d 2/d 2/d': ' !#$%#$!& %&64=37=345675 )+$,+$)- ,-68>3:>3896:9(!+*%+*!-(%-<4>;7>;49<79()#*,#*)&(,&<8=;:=;85<:5',\n 'I 2/m 2/m 2/m': ' !#$%#$!& %&$%& !& %#$!#()+*,+*)-(,-*,-()-(,+*)+',\n 'I 2/b 2/a 2/m': ' !#$%#*)&(,&$%& !&(,#*)#()+*,+$!- %-*,-()- %+$!+',\n 'I 21/b 21/c 21/a': ' !#*%+$)-(,&$%&(!- ,+*)#()+$,#*!& %-*,- )&(%#$!+',\n 'I 21/m 21/m 21/a': ' !#$,#$)& %&$%& )& ,#$!#()+*%+*!-(,-*,-(!-(%+*)+',\n 'P 4': ' !#$%#% #!$#',\n 'P 41': ' !#$%+% 5!$9',\n 'P 42': ' !#$%#% +!$+',\n 'P 43': ' !#$%+% 9!$5',\n 'I 4': ' !#$%#% #!$#()+*,+,(+)*+',\n 'I 41': ' !#*,+%(5)$9()+$%#, 9!*5',\n 'P -4': ' !#$%#!$&% &',\n 'I -4': ' !#$%#!$&% &()+*,+)*-,(-',\n 'P 4/m': ' !#$%#% #!$#$%& !&!$&% &',\n 'P 42/m': ' !#$%#% +!$+$%& !&!$-% -',\n 'P 4/n': ' !#$%#,(#)*#*,&()&!$&% &',\n 'P 42/n': ' !#$%#,(+)*+*,-()-!$&% &',\n 'I 4/m': ' !#$%#% #!$#$%& !&!$&% &()+*,+,(+)*+*,-()-)*-,(-',\n 'I 41/a': ' !#*,+%(5)$9$,=(!>!$&,(-()+$%#, 9!*5*%> )=)*-% &',\n 'P 4 2 2': ' !#$%#% #!$#$!& %&! &%$&',\n 'P 4 21 2': ' !#$%#,(#)*#*)&(,&! &%$&',\n 'P 41 2 2': ' !#$%+% 5!$9$!& %-! >%$=',\n 'P 41 21 2': ' !#$%+,(5)*9*)=(,>! &%$-',\n 'P 42 2 2': ' !#$%#% +!$+$!& %&! -%$-',\n 'P 42 21 2': ' !#$%#,(+)*+*)-(,-! &%$&',\n 'P 43 2 2': ' !#$%+% 9!$5$!& %-! =%$>',\n 'P 43 21 2': ' !#$%+,(9)*5*)>(,=! &%$-',\n 'I 4 2 2': ' !#$%#% #!$#$!& %&! &%$&()+*,+,(+)*+*)-(,-)(-,*-',\n 'I 41 2 2': ' !#*,+%(5)$9*!> ,=)(-%$&()+$%#, 9!*5$)=(%>! &,*-',\n 'P 4 m m': ' !#$%#% #!$# %#$!#%$#! #',\n 'P 4 b m': ' !#$%#% #!$#(,#*)#,*#)(#',\n 'P 42 c m': ' !#$%#% +!$+ %+$!+%$#! #',\n 'P 42 n m': ' !#$%#,(+)*+(,+*)+%$#! #',\n 'P 4 c c': ' !#$%#% #!$# %+$!+%$+! +',\n 'P 4 n c': ' !#$%#% #!$#(,+*)+,*+)(+',\n 'P 42 m c': ' !#$%#% +!$+ %#$!#%$+! +',\n 'P 42 b c': ' !#$%#% +!$+(,#*)#,*+)(+',\n 'I 4 m m': ' !#$%#% #!$# %#$!#%$#! #()+*,+,(+)*+(,+*)+,*+)(+',\n 'I 4 c m': ' !#$%#% #!$# %+$!+%$+! +()+*,+,(+)*+(,#*)#,*#)(#',\n 'I 41 m d': ' !#*,+%(5)$9 %#*)+%*5) 9()+$%#, 9!*5(,+$!#,$9!(5',\n 'I 41 c d': ' !#*,+%(5)$9 %+*)#%*9) 5()+$%#, 9!*5(,#$!+,$5!(9',\n 'P -4 2 m': ' !#$%#% &!$&$!& %&%$#! #',\n 'P -4 2 c': ' !#$%#% &!$&$!- %-%$+! +',\n 'P -4 21 m': ' !#$%#% &!$&*)&(,&,*#)(#',\n 'P -4 21 c': ' !#$%#% &!$&*)-(,-,*+)(+',\n 'P -4 m 2': ' !#$%#!$&% & %#$!#! &%$&',\n 'P -4 c 2': ' !#$%#% &!$& %+$!+! -%$-',\n 'P -4 b 2': ' !#$%#% &!$&(,#*)#)(&,*&',\n 'P -4 n 2': ' !#$%#% &!$&(,+*)+)(-,*-',\n 'I -4 m 2': ' !#$%#% &!$& %#$!#! &%$&()+*,+,(-)*-(,+*)+)(-,*-',\n 'I -4 c 2': ' !#$%#% &!$& %+$!+! -%$-()+*,+,(-)*-(,#*)#)(&,*&',\n 'I -4 2 m': ' !#$%#% &!$&$!& %&%$#! #()+*,+,(-)*-*)-(,-,*+)(+',\n 'I -4 2 d': ' !#$%#% &!$&*!>(%>,$9) 9()+*,+,(-)*-$)= ,=%*5!(5',\n 'P 4/m 2/m 2/m': ' !#$%#% #!$#$!& %&! &%$&$%& !&!$&% & %#$!#%$#! #',\n 'P 4/m 2/c 2/c': ' !#$%#% #!$#$!- %-! -%$-$%& !&!$&% & %+$!+%$+! +',\n 'P 4/n 2/b 2/m': ' !#$%#% #!$#$!& %&! &%$&*,&()&)*&,(&(,#*)#,*#)(#',\n 'P 4/n 2/n 2/c': ' !#$%#% #!$#$!& %&! &%$&*,-()-)*-,(-(,+*)+,*+)(+',\n 'P 4/m 21/b 2/m': ' !#$%#% #!$#*)&(,&)(&,*&$%& !&!$&% &(,#*)#,*#)(#',\n 'P 4/m 21/n 2/c': ' !#$%#% #!$#*)-(,-)(-,*-$%& !&!$&% &(,+*)+,*+)(+',\n 'P 4/n 21/m 2/m': ' !#$%#,(#)*#*)&(,&! &%$&*,&()&!$&% & %#$!#,*#)(#',\n 'P 4/n 2/c 2/c': ' !#$%#,(#)*#*)-(,-! -%$-*,&()&!$&% & %+$!+,*+)(+',\n 'P 42/m 2/m 2/c': ' !#$%#% +!$+$!& %&! -%$-$%& !&!$-% - %#$!#%$+! +',\n 'P 42/m 2/c 2/m': ' !#$%#% +!$+$!- %-! &%$&$%& !&!$-% - %+$!+%$#! #',\n 'P 42/n 2/b 2/c': ' !#$%#,(+)*+$!- %-)(&,*&*,-()-!$&% &(,#*)#%$+! +',\n 'P 42/n 2/n 2/m': ' !#$%#,(+)*+$!& %&)(-,*-*,-()-!$&% &(,+*)+%$#! #',\n 'P 42/m 21/b 2/c': ' !#$%#% +!$+*)&(,&)(-,*-$%& !&!$-% -(,#*)#,*+)(+',\n 'P 42/m 21/n 2/m': \" !#$%#,./'*/*'-.,-! &%$&$%& !&'*-,.-.,/*'/%$#! #\",\n 'P 42/n 21/m 2/c': ' !#$%#,(+)*+*)-(,-! &%$&*,-()-!$&% & %#$!#,*+)(+',\n 'P 42/n 21/c 2/m': ' !#$%#,(+)*+*)&(,&! -%$-*,-()-!$&% & %+$!+,*#)(#',\n 'I 4/m 2/m 2/m': ' !#$%#% #!$#$!& %&! &%$&$%& !&!$&% & %#$!#%$#! #()+*,+,(+)*+*)-(,-)(-,*-*,-()-)*-,(-(,+*)+,*+)(+',\n 'I 4/m 2/c 2/m': ' !#$%#% #!$#$!- %-! -%$-$%& !&!$&% & %+$!+%$+! +()+*,+,(+)*+*)&(,&)(&,*&*,-()-)*-,(-(,#*)#,*#)(#',\n 'I 41/a 2/m 2/d': ' !#*,+%(5)$9*!> ,=)(-%$&$,=(!>!$&,(-(,+$!#,$9!(5()+$%#, 9!*5$)=(%>! &,*-*%> )=)*-% & %#*)+%*5) 9',\n 'I 41/a 2/c 2/d': ' !#*,+%(5)$9*!= ,>)(&%$-$,=(!>!$&,(-(,#$!+,$5!(9()+$%#, 9!*5$)>(%=! -,*&*%> )=)*-% & %+*)#%*9) 5',\n 'P 3': ' !#%?#@$#',\n 'P 31': ' !#%?A@$B',\n 'P 32': ' !#%?B@$A',\n 'H 3': ' !#%?#@$#CDAEFAGHAIJBKLBMNB',\n 'R 3': ' !## !!# ',\n 'P -3': ' !#%?#@$#$%&!@&? &',\n 'H -3': ' !#%?#@$#$%&!@&? &OPQRSQTUQVWXYZX[]X]Y^W[^ZV^UR_PT_SO_',\n 'R -3': ' !## !!# $%&&$%%&$',\n 'P 3 1 2': ' !#%?#@$#%$&@!& ?&',\n 'P 3 2 1': ' !#%?#@$#! &?%&$@&',\n 'P 31 1 2': ' !#%?Q@$^%$_@!X ?&',\n 'P 31 2 1': ' !#%?A@$B! &?%_$@X',\n 'P 32 1 2': ' !#%?^@$Q%$X@!_ ?&',\n 'P 32 2 1': ' !#%?B@$A! &?%X$@_',\n 'H 3 2': ' !#%?#@$#! &?%&$@&OPQRSQTUQY]X[WXVZX]Y^W[^ZV^PO_SR_UT_',\n 'R 3 2': ' !## !!# %$&$&%&%$',\n 'P 3 m 1': ' !#%?#@$#%$#@!# ?#',\n 'P 3 1 m': ' !#%?#@$#! #?%#$@#',\n 'P 3 c 1': ' !#%?#@$#%$+@!+ ?+',\n 'P 3 1 c': ' !#%?#@$#! +?%+$@+',\n 'H 3 m': ' !#%?#@$#%$#@!# ?#OPQRSQTUQRUQTPQOSQ]Y^W[^ZV^WV^ZY^][^',\n 'R 3 m': ' !## !!# ! # #!#! ',\n 'H 3 c': ' !#%?#@$#%$+@!+ ?+OPQRSQTUQRU`TP`OS`]Y^W[^ZV^WVaZYa][a',\n 'R 3 c': \" !## !!# '././'/'.\",\n 'P -3 1 2/m': ' !#%?#@$#%$&@!& ?&$%&!@&? &! #?%#$@#',\n 'P -3 1 2/c': ' !#%?#@$#%$-@!- ?-$%&!@&? &! +?%+$@+',\n 'P -3 2/m 1': ' !#%?#@$#! &?%&$@&$%&!@&? &%$#@!# ?#',\n 'P -3 2/c 1': ' !#%?#@$#! -?%-$@-$%&!@&? &%$+@!+ ?+',\n 'H -3 2/m': ' !#%?#@$#! &?%&$@&$%&!@&? &%$#@!# ?#OPQRSQTUQY]X[WXVZXVWXYZX[]XRUQTPQOSQ]Y^W[^ZV^PO_SR_UT_UR_PT_SO_WV^ZY^][^',\n 'R -3 2/m': ' !## !!# %$&$&%&%$$%&&$%%&$! # #!#! ',\n 'H -3 2/c': ' !#%?#@$#! -?%-$@-$%&!@&? &%$+@!+ ?+OPQRSQTUQY]b[WbVZbVWXYZX[]XRU`TP`OS`]Y^W[^ZV^POcSRcUTcUR_PT_SO_WVaZYa][a',\n 'R -3 2/c': \" !## !!# 102021210$%&&$%%&$'././'/'.\",\n 'P 6': ' !#%?#@$#$%#!@#? #',\n 'P 61': ' !#%?A@$B$%/!@d? e',\n 'P 65': ' !#%?B@$A$%/!@e? d',\n 'P 62': ' !#%?^@$Q$%#!@^? Q',\n 'P 64': ' !#%?Q@$^$%#!@Q? ^',\n 'P 63': ' !#%?#@$#$%+!@+? +',\n 'P -6': ' !#%?#@$# !&%?&@$&',\n 'P 6/m': ' !#%?#@$#$%#!@#? #$%&!@&? & !&%?&@$&',\n 'P 63/m': ' !#%?#@$#$%+!@+? +$%&!@&? & !-%?-@$-',\n 'P 6 2 2': ' !#%?#@$#$%#!@#? #! &?%&$@&%$&@!& ?&',\n 'P 61 2 2': ' !#%?Q@$^$%+!@`? a! X?%&$@_%$b@!- ?c',\n 'P 65 2 2': ' !#%?^@$Q$%+!@a? `! _?%&$@X%$c@!- ?b',\n 'P 62 2 2': ' !#%?^@$Q$%#!@^? Q! _?%&$@X%$_@!& ?X',\n 'P 64 2 2': ' !#%?Q@$^$%#!@Q? ^! X?%&$@_%$X@!& ?_',\n 'P 63 2 2': ' !#%?#@$#$%+!@+? +! &?%&$@&%$-@!- ?-',\n 'P 6 m m': ' !#%?#@$#$%#!@#? #%$#@!# ?#! #?%#$@#',\n 'P 6 c c': ' !#%?#@$#$%#!@#? #%$+@!+ ?+! +?%+$@+',\n 'P 63 c m': ' !#%?#@$#$%+!@+? +%$+@!+ ?+! #?%#$@#',\n 'P 63 m c': ' !#%?#@$#$%+!@+? +%$#@!# ?#! +?%+$@+',\n 'P -6 m 2': ' !#%?#@$# !&%?&@$&%$#@!# ?#%$&@!& ?&',\n 'P -6 c 2': ' !#%?#@$# !-%?-@$-%$+@!+ ?+%$&@!& ?&',\n 'P -6 2 m': ' !#%?#@$# !&%?&@$&! &?%&$@&! #?%#$@#',\n 'P -6 2 c': ' !#%?#@$# !-%?-@$-! &?%&$@&! +?%+$@+',\n 'P 6/m 2/m 2/m': ' !#%?#@$#$%#!@#? #! &?%&$@&%$&@!& ?&$%&!@&? & !&@$&%?&%$#@!# ?#! #?%#$@#',\n 'P 6/m 2/c 2/c': ' !#%?#@$#$%#!@#? #! -?%-$@-%$-@!- ?-$%&!@&? & !&@$&%?&%$+@!+ ?+! +?%+$@+',\n 'P 63/m 2/c 2/m': ' !#%?#@$#$%+!@+? +! -?%-$@-%$&@!& ?&$%&!@&? & !-@$-%?-%$+@!+ ?+! #?%#$@#',\n 'P 63/m 2/m 2/c': ' !#%?#@$#$%+!@+? +! &?%&$@&%$-@!- ?-$%&!@&? & !-@$-%?-%$#@!# ?#! +?%+$@+',\n 'P 2 3': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ',\n 'F 2 3': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-((!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- ',\n 'I 2 3': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-(',\n 'P 21 3': ' !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(',\n 'I 21 3': ' !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(()+$,#*!& %-+()#$,&*!- %)+(,#$!&*%- ',\n 'P 2/m -3': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& $%& !& %#$!#&$%& !# %#$!%&$!& %# !#$',\n 'P 2/n -3': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& *,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*',\n 'F 2/m -3': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& $%& !& %#$!#&$%& !# %#$!%&$!& %# !#$ )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-($,- )- ,+$)+&*,&()#(,#*)%-*!-(%+(!+*(!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(*%-(!-(%+*!+-$,- )+ ,+$),&*)&(,#()#*()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- *,&()&(,#*)#-*%-(!+(%+*!,-$)- ,+ )+$',\n 'F 2/d -3': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& 64=37=345675=64=375345674=67=3453756 )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-(68>3:>3896:9=<8=;:5;85<:4><7>;49;79<(!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(<4>;7>;49<79>68>3:93896:8=<:=;85;:5<()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- <8=;:=;8f<:f><4>;79;49<78>6:>3893:96',\n 'I 2/m -3': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& $%& !& %#$!#&$%& !# %#$!%&$!& %# !#$()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-(*,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*',\n 'P 21/a -3': ' !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&($%&(!- ,+*)#&$%-(!+ ,#*)%&$!-(,+ )#*',\n 'I 21/a -3': ' !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&($%&(!- ,+*)#&$%-(!+ ,#*)%&$!-(,+ )#*()+$,#*g& %-+()#$,&*!- %)+(,#$!&*%- *,- )&(%#$!+-*,& )#(%+$!,-*)& %#(!+$',\n 'P 4 3 2': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$',\n 'P 42 3 2': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,*',\n 'F 4 3 2': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$ )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-(!(-%*-!*+%(+ +,$+)$-, -)#)*#,(&)(&,*(!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&() -,$-)$+, +(#,*#)*&,(&)+!*+%(-!(-%*()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- )(&,*&)*#,(#(+%*+!*-%(-!+)$+, -) -,$',\n 'F 41 3 2': ' !#$,+*)&(%-# !+$,&*)-(%!# ,+$)&*%-(:3>46=7<98;5;58<976=43>:97<58;>:3=46 )+$%#*!-(,&#()+*%&$!- ,!+(,#*)-$%& :;=4<>765839;94<5:6>83=79:6543>7;=8<(!+*,#$)- %&+ )#$%-*!&(,)#(%+*!&$,- 73=86>:<54;935469:<=8;>7576983=:;>4<()#*%+$!& ,-+(!#*,-$)& %)+ %#$!-*,&(7;>8<=:69435398657<>4;=:5:<94;=73>86',\n 'I 4 3 2': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-()(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,*',\n 'P 43 3 2': ' !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(7;>46=:<5839398<5:6=4;>75:<983>7;=46',\n 'P 41 3 2': ' !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(:3=8<>7694;5;54697<>83=:97654;=:3>8<',\n 'I 41 3 2': ' !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(:3=8<>7694;5;54697<>83=:97654;=:3>8<()+$,#*!& %-+()#$,&*!- %)+(,#$!&*%- 7;>46=:<5839398<5:6=4;>75:<983>7;=46',\n 'P -4 3 m': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! #%$#!$&% & #!$#%$&! &%#! #%$&!$&% ',\n 'F -4 3 m': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! #%$#!$&% & #!$#%$&! &%#! #%$&!$&% )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-(!(+%*+!*-%(- +)$+,$-) -,#)(#,*&)*&,((!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&() +,$+)$-, -(#)*#,*&)(&,+!(+%*-!*-%(()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- )(#,*#)*&,(&(+!*+%*-!(-%+) +,$-)$-, ',\n 'I -4 3 m': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! #%$#!$&% & #!$#%$&! &%#! #%$&!$&% ()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-()(+,*+)*-,(-(+)*+,*-)(-,+)(+,*-)*-,(',\n 'P -4 3 n': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(+,*+)*-,(-(+)*+,*-)(-,+)(+,*-)*-,(',\n 'F -4 3 c': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(+,*+)*-,(-(+)*+,*-)(-,+)(+,*-)*-,( )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-() #,$#)$&, &(#!*#%*&!(&%+! +%$-!$-% (!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(!(#%*#!*&%(& +!$+%$-! -%#) #,$&)$&, ()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- ! +%$+!$-% - #)$#,$&) &,#!(#%*&!*&%(',\n 'I -4 3 d': ' !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(7354<9:6>8;=357<946>:;=857394<>:6=8;()+$,#*!& %-+()#$,&*!- %)+(,#$!&*%- :;98657<=43>;9:658<=73>49:;586=7<>43',\n 'P 4/m -3 2/m': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$%$#! #% &!$&$&! &% #!$#%&% &!$#%$#! ',\n 'P 4/n -3 2/n': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$*,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*,*+)(+,(-)*-*-)(-,(+)*+,-,(-)*+,*+)(',\n 'P 42/m -3 2/n': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,*$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$,*+)(+,(-)*-*-)(-,(+)*+,-,(-)*+,*+)(',\n 'P 42/n -3 2/m': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,**,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*%$#! #% &!$&$&! &% #!$#%&% &!$#%$#! ',\n 'F 4/m -3 2/m': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$%$#! #% &!$&$&! &% #!$#%&% &!$#%$#! )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-(!(-%*-!*+%(+ +,$+)$-, -)#)*#,(&)(&,*$,- )- ,+$)+&*,&()#(,#*)%-*!-(%+(!+*%*+!(+%(-!*-$-) -, +)$+,&,(&)*#,*#)((!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&() -,$-)$+, +(#,*#)*&,(&)+!*+%(-!(-%**%-(!-(%+*!+-$,- )+ ,+$),&*)&(,#()#*,$+) +, -)$-*&)(&,(#)*#,-%(-!*+%*+!(()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- )(&,*&)*#,(#(+%*+!*-%(-!+)$+, -) -,$*,&()&(,#*)#-*%-(!+(%+*!,-$)- ,+ )+$,*#)(#,(&)*&*-!(-%(+!*+%-, -)$+,$+) ',\n 'F 4/m -3 2/c': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,*$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$,*+)(+,(-)*-*-)(-,(+)*+,-,(-)*+,*+)( )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-() &,$&)$#, #(#%*#!*&%(&!+!$+% -! -%$$,- )- ,+$)+&*,&()#(,#*)%-*!-(%+(!+*,$#) #, &)$&*&!(&%(#!*#%-% -!$+%$+! (!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(!(&%*&!*#%(# +%$+!$-% -!#)$#, &) &,$*%-(!-(%+*!+-$,- )+ ,+$),&*)&(,#()#*%*#!(#%(&!*&$-! -% +!$+%&, &)$#,$#) ()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- ! -%$-!$+% + #,$#)$&, &)#!*#%(&!(&%**,&()&(,#*)#-*%-(!+(%+*!,-$)- ,+ )+$%$+! +% -!$-$&) &, #)$#,&%(&!*#%*#!(',\n 'F 41/d -3 2/m': ' !#$,+*)&(%-# !+$,&*)-(%!# ,+$)&*%-(:3>46=7<98;5;58<976=43>:97<58;>:3=4664=3:>;85<79=64>3:5;89<74=6:>385;79<,$+! #%(-)*&*&)(-% #!$+,-%(&)*+,$#! )+$%#*!-(,&#()+*%&$!- ,!+(,#*)-$%& :;=4<>765839;94<5:6>83=79:6543>7;=8<68>37=;49<:5=<8>;753496:4><:=;893756,*#!(+% &)$-*-!(&, +)$#%-, &!$+%*#)((!+*,#$)- %&+ )#$%-*!&(,)#(%+*!&$,- 73=86>:<54;935469:<=8;>7576983=:;>4<<4>;:=389675>68=379;45<:8=<7>;453:96%$#) +,(&!*-$&! -,(#)*+%&% -)$#,*+!(()#*%+$!& ,-+(!#*,-$)& %)+ %#$!-*,&(7;>8<=:69435398657<>4;=:5:<94;=73>86<8=;7>3456:9><4=;:9385678>67=349;:5<%*+)(#, -!$&$-) &%(+!*#,&,(-!*#%$+) ',\n 'F 41/d -3 2/c': ' !#$,+*)&(%-# !+$,&*)-(%!# ,+$)&*%-(:3>46=7<98;5;58<976=43>:97<58;>:3=46<8>;7=3496:5><8=;793456:8><7=;493:56%*#)(+, &!$-$-! &,(+)*#%&, -!$#%*+)( )+$%#*!-(,&#()+*%&$!- ,!+(,#*)-$%& :;=4<>765839;94<5:6>83=79:6543>7;=8<<4=;:>385679>64=3:9;85<78=67>345;:9<%$+) #,(-!*&$&) -%(#!*+,&%(-)*#,$+! (!+*,#$)- %&+ )#$%-*!&(,)#(%+*!&$,- 73=86>:<54;935469:<=8;>7576983=:;>4<68=37>;45<:9=<4>;:5389674>6:=389;75<,*+!(#% -)$&*-)(&% +!$#,-,(&!*+%$#) ()#*%+$!& ,-+(!#*,-$)& %)+ %#$!-*,&(7;>8<=:69435398657<>4;=:5:<94;=73>8664>3:=;89<75=68>375;49<:4=<:>;853796,$#! +%(&)*-*&!(-, #)$+%-% &)$+,*#!(',\n 'I 4/m -3 2/m': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$%$#! #% &!$&$&! &% #!$#%&% &!$#%$#! ()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-()(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,**,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*,*+)(+,(-)*-*-)(-,(+)*+,-,(-)*+,*+)(',\n 'I 41/a -3 2/d': ' !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(:3=8<>7694;5;54697<>83=:97654;=:3>8<$%&(!- ,+*)#&$%-(!+ ,#*)%&$!-(,+ )#*4<97358;=:6>6>:;=8357<94=8;>:694<573()+$,#*!& %-+()#$,&*!- %)+(,#$!&*%- 7;>46=:<5839398<5:6=4;>75:<983>7;=46*,- )&(%#$!+-*,& )#(%+$!,-*)& %#(!+$865:;943>7<=<=73>4;9:658>43=7<5869:;',\n 'P 1 1 2': ' !#$%#',\n 'P 1 1 21': ' !#$%+',\n 'B 1 1 2': ' !#$%#(g+*%+',\n 'A 1 2 1': ' !#$!& )+$)-',\n 'C 1 21 1': ' !#$)&()#*!&',\n 'I 1 2 1': \" !#$!&.'/0'2\",\n 'I 1 21 1': \" !#$)&.'/0!-\",\n 'P 1 1 m': ' !# !&',\n 'P 1 1 b': ' !# )&',\n 'B 1 1 m': ' !# !&(!+(!-',\n 'B 1 1 b': ' !# )&(!+()-',\n 'P 1 1 2/m': ' !# !&$%#$%&',\n 'P 1 1 21/m': ' !#$%+$%& !-',\n 'B 1 1 2/m': ' !# !&$%#$%&(!+(!-*%+*%-',\n 'P 1 1 2/b': ' !#$,#$%& )&',\n 'P 1 1 21/b': ' !#$%&$,+ )-',\n 'B 1 1 2/b': ' !#$,#$%& )&(!+*,+*%-()-',\n 'P 21 2 2': ' !#$!&(%&*%#',\n 'P 2 21 2': ' !# ,&$)&$%#',\n 'P 21 21 2 (a)': \" !#*,#.%&$'&\",\n 'P 21 2 21': ' !#$!&(%-*%+',\n 'P 2 21 21': ' !# %&$)-$,+',\n 'C 2 2 21a)': ' !#*%+(,&$)-()#$,+ %&*!-',\n 'C 2 2 2a': \" !#*,#.%&$'&()#$%# ,&*!&\",\n 'F 2 2 2a': \" !#*,#.%&$'& '/*%/.12$!2.!/$,/ %20'2.'#$%# 1&0!&\",\n 'I 2 2 2a': \" !#*,#.%&$'&()+$%+*!- ,-\",\n 'P 21/m 21/m 2/n a': \" !#*,#$)&(%&$%&.'& ,#*!#\",\n 'P 42 21 2a': \" !#*,#%.+'$+$'&.%&! -,*-\",\n 'I 2 3a': \" !#*,#.%&$'&!# ,- '&$%/$# !-*!/$%&.%()+$%+ ,-*!-)+(%&(!-*,#*+()&$)#*,- ,\"\n}\n","/**\n * @file Symmetry Utils\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4 } from 'three'\n\nimport { Log } from '../globals'\nimport { EncodedSymOp, SymOpCode } from './symmetry-constants'\n\nconst reInteger = /^[1-9]$/\n\nexport function getSymmetryOperations (spacegroup: string) {\n const encodedSymopList = EncodedSymOp[ spacegroup ]\n const matrixDict: { [k: string]: Matrix4 } = {}\n\n if (encodedSymopList === undefined) {\n console.warn(`spacegroup '${spacegroup}' not found in symop library`)\n return matrixDict\n }\n\n const symopList = []\n for (let i = 0, il = encodedSymopList.length; i < il; i += 3) {\n const symop = []\n for (let j = 0; j < 3; ++j) {\n symop.push(SymOpCode[ encodedSymopList[ i + j ] ])\n }\n symopList.push(symop)\n }\n\n symopList.forEach(function (symop) {\n let row = 0\n const matrix = new Matrix4().set(\n 0, 0, 0, 0,\n 0, 0, 0, 0,\n 0, 0, 0, 0,\n 0, 0, 0, 1\n )\n const me = matrix.elements\n\n matrixDict[ symop.toString() ] = matrix\n\n symop.forEach(function (elm) {\n let negate = false\n let denominator = false\n\n for (let i = 0, n = elm.length; i < n; ++i) {\n const c = elm[ i ]\n\n if (c === '-') {\n negate = true\n } else if (c === '+') {\n negate = false\n } else if (c === '/') {\n denominator = true\n } else if (c === 'X') {\n me[ 0 + row ] = negate ? -1 : 1\n } else if (c === 'Y') {\n me[ 4 + row ] = negate ? -1 : 1\n } else if (c === 'Z') {\n me[ 8 + row ] = negate ? -1 : 1\n } else if (reInteger.test(c)) {\n const integer = parseInt(c)\n if (denominator) {\n me[ 12 + row ] /= integer\n } else {\n me[ 12 + row ] = integer\n }\n } else {\n Log.warn(`getSymmetryOperations: unknown token '${c}'`)\n }\n }\n\n row += 1\n })\n })\n\n return matrixDict\n}\n","/**\n * @file Assembly\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4, Box3, Vector3 } from 'three'\n\nimport { uniqueArray } from '../utils'\nimport Selection from '../selection/selection'\nimport Structure from '../structure/structure'\nimport StructureView from '../structure/structure-view';\n\nfunction selectionFromChains (chainList: string[]) {\n let sele = ''\n if (chainList.length > 0) {\n sele = ':' + uniqueArray(chainList).join(' OR :')\n }\n return new Selection(sele)\n}\n\n/**\n * Assembly of transformed parts of a {@link Structure}\n */\nclass Assembly {\n partList: AssemblyPart[] = []\n\n /**\n * @param {String} name - assembly name\n */\n constructor (readonly name = '') {}\n\n get type () { return 'Assembly' }\n\n /**\n * Add transformed parts to the assembly\n * @example\n * var m1 = new NGL.Matrix4().set( ... );\n * var m2 = new NGL.Matrix4().set( ... );\n * var assembly = new NGL.Assembly( \"myAssembly\" );\n * // add part that transforms chain 'A' and 'B' using matrices `m1` and `m2`\n * assembly.addPart( [ m1, m2 ], [ \"A\", \"B\" ] )\n *\n * @param {Matrix4[]} matrixList - array of 4x4 transformation matrices\n * @param {String[]} chainList - array of chain names\n * @return {AssemblyPart} the added assembly part\n */\n addPart (matrixList?: Matrix4[], chainList?: string[]) {\n const part = new AssemblyPart(matrixList, chainList)\n this.partList.push(part)\n return part\n }\n\n /**\n * Get the number of atom for a given structure\n * @param {Structure} structure - the given structure\n * @return {Integer} number of atoms in the assembly\n */\n getAtomCount (structure: Structure) {\n return this.partList.reduce(\n (count, part) => count + part.getAtomCount(structure), 0\n )\n }\n\n /**\n * Get the number of residues for a given structure\n * @param {Structure} structure - the given structure\n * @return {Integer} number of residues in the assembly\n */\n getResidueCount (structure: Structure) {\n return this.partList.reduce(\n (count, part) => count + part.getResidueCount(structure), 0\n )\n }\n\n /**\n * Get number of instances the assembly will produce, i.e.\n * the number of transformations performed by the assembly\n * @return {Integer} number of instances\n */\n getInstanceCount () {\n let instanceCount = 0\n\n this.partList.forEach(function (part) {\n instanceCount += part.matrixList.length\n })\n\n return instanceCount\n }\n\n /**\n * Determine if the assembly is the full and untransformed structure\n * @param {Structure} structure - the given structure\n * @return {Boolean} whether the assembly is identical to the structure\n */\n isIdentity (structure: Structure) {\n if (this.partList.length !== 1) return false\n\n const part = this.partList[ 0 ]\n if (part.matrixList.length !== 1) return false\n\n const identityMatrix = new Matrix4()\n if (!identityMatrix.equals(part.matrixList[ 0 ])) return false\n\n let structureChainList: string[] = []\n structure.eachChain(function (cp) {\n structureChainList.push(cp.chainname)\n })\n structureChainList = uniqueArray(structureChainList)\n if (part.chainList.length !== structureChainList.length) return false\n\n return true\n }\n\n getBoundingBox (structure: Structure) {\n const boundingBox = new Box3()\n\n this.partList.forEach(function (part) {\n const partBox = part.getBoundingBox(structure)\n boundingBox.expandByPoint(partBox.min)\n boundingBox.expandByPoint(partBox.max)\n })\n\n return boundingBox\n }\n\n getCenter (structure: Structure) {\n return this.getBoundingBox(structure).getCenter(new Vector3())\n }\n\n getSelection () {\n let chainList: string[] = []\n this.partList.forEach(function (part) {\n chainList = chainList.concat(part.chainList)\n })\n return selectionFromChains(chainList)\n }\n}\n\nexport class AssemblyPart {\n constructor (readonly matrixList: Matrix4[] = [], readonly chainList: string[] = []) {}\n\n get type () { return 'AssemblyPart' }\n\n _getCount (structure: Structure, propertyName: 'atomCount'|'residueCount') {\n let count = 0\n\n structure.eachChain(cp => {\n if (this.chainList.length === 0 || this.chainList.includes(cp.chainname)) {\n count += cp[ propertyName ]\n }\n })\n\n return this.matrixList.length * count\n }\n\n getAtomCount (structure: Structure) {\n return this._getCount(structure, 'atomCount')\n }\n\n getResidueCount (structure: Structure) {\n return this._getCount(structure, 'residueCount')\n }\n\n getBoundingBox (structure: Structure) {\n const partBox = new Box3()\n const instanceBox = new Box3()\n\n const selection = this.getSelection()\n const structureBox = structure.getBoundingBox(selection)\n\n this.matrixList.forEach(function (matrix) {\n instanceBox.copy(structureBox).applyMatrix4(matrix)\n partBox.expandByPoint(instanceBox.min)\n partBox.expandByPoint(instanceBox.max)\n })\n\n return partBox\n }\n\n getSelection () {\n return selectionFromChains(this.chainList)\n }\n\n getView (structure: Structure): Structure | StructureView {\n const selection = this.getSelection()\n if (selection) {\n return structure.getView(selection)\n } else {\n return structure\n }\n }\n\n getInstanceList () {\n const instanceList = []\n for (let j = 0, jl = this.matrixList.length; j < jl; ++j) {\n instanceList.push({\n id: j + 1,\n name: j,\n matrix: this.matrixList[ j ]\n })\n }\n return instanceList\n }\n}\n\nexport default Assembly\n","/**\n * @file Structure Builder\n * @author Alexander Rose \n * @private\n */\n\nimport Structure from './structure'\n\nclass StructureBuilder {\n currentModelindex: number|null = null\n currentChainid: string|null = null\n currentResname: string|null = null\n currentResno: number|null = null\n currentInscode: string|undefined = undefined\n currentHetero: boolean|null = null\n\n previousResname: string|null = ''\n previousHetero: boolean|null = null\n\n ai = -1\n ri = -1\n ci = -1\n mi = -1\n\n constructor(readonly structure: Structure) {}\n\n addResidueType (ri: number) {\n const atomStore = this.structure.atomStore\n const residueStore = this.structure.residueStore\n const residueMap = this.structure.residueMap\n\n const count = residueStore.atomCount[ ri ]\n const offset = residueStore.atomOffset[ ri ]\n const atomTypeIdList = new Array(count)\n for (let i = 0; i < count; ++i) {\n atomTypeIdList[ i ] = atomStore.atomTypeId[ offset + i ]\n }\n residueStore.residueTypeId[ ri ] = residueMap.add(\n this.previousResname!, atomTypeIdList, this.previousHetero! // TODO\n )\n }\n\n addAtom (modelindex: number, chainname: string, chainid: string, resname: string, resno: number, hetero: boolean, sstruc?: string|undefined, inscode?: string|undefined) {\n const atomStore = this.structure.atomStore\n const residueStore = this.structure.residueStore\n const chainStore = this.structure.chainStore\n const modelStore = this.structure.modelStore\n\n let addModel = false\n let addChain = false\n let addResidue = false\n\n if (this.currentModelindex !== modelindex) {\n addModel = true\n addChain = true\n addResidue = true\n this.mi += 1\n this.ci += 1\n this.ri += 1\n } else if (this.currentChainid !== chainid) {\n addChain = true\n addResidue = true\n this.ci += 1\n this.ri += 1\n } else if (this.currentResno !== resno || this.currentResname !== resname || this.currentInscode !== inscode) {\n addResidue = true\n this.ri += 1\n }\n this.ai += 1\n\n if (addModel) {\n modelStore.growIfFull()\n modelStore.chainOffset[ this.mi ] = this.ci\n modelStore.chainCount[ this.mi ] = 0\n modelStore.count += 1\n chainStore.modelIndex[ this.ci ] = this.mi\n }\n\n if (addChain) {\n chainStore.growIfFull()\n chainStore.setChainname(this.ci, chainname)\n chainStore.setChainid(this.ci, chainid)\n chainStore.residueOffset[ this.ci ] = this.ri\n chainStore.residueCount[ this.ci ] = 0\n chainStore.count += 1\n chainStore.modelIndex[ this.ci ] = this.mi\n modelStore.chainCount[ this.mi ] += 1\n residueStore.chainIndex[ this.ri ] = this.ci\n }\n\n if (addResidue) {\n this.previousResname = this.currentResname\n this.previousHetero = this.currentHetero\n if (this.ri > 0) this.addResidueType(this.ri - 1)\n residueStore.growIfFull()\n residueStore.resno[ this.ri ] = resno\n if (sstruc !== undefined) {\n residueStore.sstruc[ this.ri ] = sstruc.charCodeAt(0)\n }\n if (inscode !== undefined) {\n residueStore.inscode[ this.ri ] = inscode.charCodeAt(0)\n }\n residueStore.atomOffset[ this.ri ] = this.ai\n residueStore.atomCount[ this.ri ] = 0\n residueStore.count += 1\n residueStore.chainIndex[ this.ri ] = this.ci\n chainStore.residueCount[ this.ci ] += 1\n }\n\n atomStore.count += 1\n atomStore.residueIndex[ this.ai ] = this.ri\n residueStore.atomCount[ this.ri ] += 1\n\n this.currentModelindex = modelindex\n this.currentChainid = chainid\n this.currentResname = resname\n this.currentResno = resno\n this.currentInscode = inscode\n this.currentHetero = hetero\n }\n\n finalize () {\n this.previousResname = this.currentResname\n this.previousHetero = this.currentHetero\n if (this.ri > -1) this.addResidueType(this.ri)\n }\n}\n\nexport default StructureBuilder\n","/**\n * @file Structure Utils\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Matrix4 } from 'three'\n\nimport { Debug, Log } from '../globals'\nimport { binarySearchIndexOf } from '../utils'\nimport Helixbundle from '../geometry/helixbundle'\nimport Kdtree from '../geometry/kdtree'\nimport { getSymmetryOperations } from '../symmetry/symmetry-utils'\nimport Assembly from '../symmetry/assembly'\nimport Structure from '../structure/structure'\nimport StructureBuilder from '../structure/structure-builder'\nimport Polymer from '../proxy/polymer'\nimport ResidueProxy from '../proxy/residue-proxy'\n\nimport { UnknownBackboneType, AA3, Bases, AtomicNumbers } from './structure-constants'\n\nexport function reorderAtoms (structure: Structure) {\n if (Debug) Log.time('reorderAtoms')\n\n var ap1 = structure.getAtomProxy()\n var ap2 = structure.getAtomProxy()\n\n function compareModelChainResno (index1: number, index2: number) {\n ap1.index = index1\n ap2.index = index2\n if (ap1.modelIndex < ap2.modelIndex) {\n return -1\n } else if (ap1.modelIndex > ap2.modelIndex) {\n return 1\n } else {\n if (ap1.chainname < ap2.chainname) {\n return -1\n } else if (ap1.chainname > ap2.chainname) {\n return 1\n } else {\n if (ap1.resno < ap2.resno) {\n return -1\n } else if (ap1.resno > ap2.resno) {\n return 1\n } else {\n return 0\n }\n }\n }\n }\n\n structure.atomStore.sort(compareModelChainResno)\n\n if (Debug) Log.timeEnd('reorderAtoms')\n}\n\nexport interface SecStruct {\n helices: [string, number, string, string, number, string, number][]\n sheets: [string, number, string, string, number, string][]\n}\n\nexport function assignSecondaryStructure (structure: Structure, secStruct: SecStruct) {\n if (!secStruct) return\n\n if (Debug) Log.time('assignSecondaryStructure')\n\n const chainnames: string[] = []\n structure.eachModel(function (mp) {\n mp.eachChain(function (cp) {\n chainnames.push(cp.chainname)\n })\n })\n\n const chainnamesSorted = chainnames.slice().sort()\n const chainnamesIndex: number[] = []\n chainnamesSorted.forEach(function (c) {\n chainnamesIndex.push(chainnames.indexOf(c))\n })\n\n // helix assignment\n\n const helices = secStruct.helices.filter(function (h) {\n return binarySearchIndexOf(chainnamesSorted, h[ 0 ]) >= 0\n })\n\n helices.sort(function (h1, h2) {\n const c1 = h1[ 0 ]\n const c2 = h2[ 0 ]\n const r1 = h1[ 1 ]\n const r2 = h2[ 1 ]\n\n if (c1 === c2) {\n if (r1 === r2) {\n return 0\n } else {\n return r1 < r2 ? -1 : 1\n }\n } else {\n const idx1 = binarySearchIndexOf(chainnamesSorted, c1)\n const idx2 = binarySearchIndexOf(chainnamesSorted, c2)\n return chainnamesIndex[ idx1 ] < chainnamesIndex[ idx2 ] ? -1 : 1\n }\n })\n\n const residueStore = structure.residueStore\n\n structure.eachModel(function (mp) {\n let i = 0\n const n = helices.length\n if (n === 0) return\n let helix = helices[ i ]\n let helixRun = false\n let done = false\n\n mp.eachChain(function (cp) {\n let chainChange = false\n\n if (cp.chainname === helix[ 0 ]) {\n const count = cp.residueCount\n const offset = cp.residueOffset\n const end = offset + count\n\n for (let j = offset; j < end; ++j) {\n if (residueStore.resno[ j ] === helix[ 1 ] && // resnoBeg\n residueStore.getInscode(j) === helix[ 2 ] // inscodeBeg\n ) {\n helixRun = true\n }\n\n if (helixRun) {\n residueStore.sstruc[ j ] = helix[ 6 ]\n\n if (residueStore.resno[ j ] === helix[ 4 ] && // resnoEnd\n residueStore.getInscode(j) === helix[ 5 ] // inscodeEnd\n ) {\n helixRun = false\n i += 1\n\n if (i < n) {\n // must look at previous residues as\n // residues may not be ordered by resno\n j = offset - 1\n helix = helices[ i ]\n chainChange = cp.chainname !== helix[ 0 ]\n } else {\n done = true\n }\n }\n }\n\n if (chainChange || done) return\n }\n }\n })\n })\n\n // sheet assignment\n\n const sheets = secStruct.sheets.filter(function (s) {\n return binarySearchIndexOf(chainnamesSorted, s[ 0 ]) >= 0\n })\n\n sheets.sort(function (s1, s2) {\n const c1 = s1[ 0 ]\n const c2 = s2[ 0 ]\n\n if (c1 === c2) return 0\n const idx1 = binarySearchIndexOf(chainnamesSorted, c1)\n const idx2 = binarySearchIndexOf(chainnamesSorted, c2)\n return chainnamesIndex[ idx1 ] < chainnamesIndex[ idx2 ] ? -1 : 1\n })\n\n const strandCharCode = 'e'.charCodeAt(0)\n structure.eachModel(function (mp) {\n let i = 0\n const n = sheets.length\n if (n === 0) return\n let sheet = sheets[ i ]\n let sheetRun = false\n let done = false\n\n mp.eachChain(function (cp) {\n let chainChange = false\n\n if (cp.chainname === sheet[ 0 ]) {\n const count = cp.residueCount\n const offset = cp.residueOffset\n const end = offset + count\n\n for (let j = offset; j < end; ++j) {\n if (residueStore.resno[ j ] === sheet[ 1 ] && // resnoBeg\n residueStore.getInscode(j) === sheet[ 2 ] // inscodeBeg\n ) {\n sheetRun = true\n }\n\n if (sheetRun) {\n residueStore.sstruc[ j ] = strandCharCode\n\n if (residueStore.resno[ j ] === sheet[ 4 ] && // resnoEnd\n residueStore.getInscode(j) === sheet[ 5 ] // inscodeEnd\n ) {\n sheetRun = false\n i += 1\n\n if (i < n) {\n // must look at previous residues as\n // residues may not be ordered by resno\n j = offset - 1\n sheet = sheets[ i ]\n chainChange = cp.chainname !== sheet[ 0 ]\n } else {\n done = true\n }\n }\n }\n\n if (chainChange || done) return\n }\n }\n })\n })\n\n if (Debug) Log.timeEnd('assignSecondaryStructure')\n}\n\nexport const calculateSecondaryStructure = (function () {\n // Implementation for proteins based on \"pv\"\n //\n // assigns secondary structure information based on a simple and very fast\n // algorithm published by Zhang and Skolnick in their TM-align paper.\n // Reference:\n //\n // TM-align: a protein structure alignment algorithm based on the Tm-score\n // (2005) NAR, 33(7) 2302-2309\n\n const zhangSkolnickSS = function (polymer: Polymer, i: number, distances: number[], delta: number) {\n const structure = polymer.structure\n const offset = polymer.residueIndexStart\n const rp1 = structure.getResidueProxy()\n const rp2 = structure.getResidueProxy()\n const ap1 = structure.getAtomProxy()\n const ap2 = structure.getAtomProxy()\n\n for (let j = Math.max(0, i - 2); j <= i; ++j) {\n for (let k = 2; k < 5; ++k) {\n if (j + k >= polymer.residueCount) {\n continue\n }\n\n rp1.index = offset + j\n rp2.index = offset + j + k\n ap1.index = rp1.traceAtomIndex\n ap2.index = rp2.traceAtomIndex\n\n const d = ap1.distanceTo(ap2)\n\n if (Math.abs(d - distances[ k - 2 ]) > delta) {\n return false\n }\n }\n }\n\n return true\n }\n\n const isHelical = function (polymer: Polymer, i: number) {\n const helixDistances = [ 5.45, 5.18, 6.37 ]\n const helixDelta = 2.1\n return zhangSkolnickSS(polymer, i, helixDistances, helixDelta)\n }\n\n const isSheet = function (polymer: Polymer, i: number) {\n const sheetDistances = [ 6.1, 10.4, 13.0 ]\n const sheetDelta = 1.42\n return zhangSkolnickSS(polymer, i, sheetDistances, sheetDelta)\n }\n\n const proteinPolymer = function (p: Polymer) {\n const residueStore = p.residueStore\n const offset = p.residueIndexStart\n for (let i = 0, il = p.residueCount; i < il; ++i) {\n let sstruc = 'c'\n if (isHelical(p, i)) {\n sstruc = 'h'\n } else if (isSheet(p, i)) {\n sstruc = 'e'\n }\n residueStore.sstruc[ offset + i ] = sstruc.charCodeAt(0)\n }\n }\n\n const cgPolymer = function (p: Polymer) {\n const localAngle = 20\n const centerDist = 2.0\n\n const residueStore = p.residueStore\n const offset = p.residueIndexStart\n\n const helixbundle = new Helixbundle(p)\n const pos = helixbundle.position\n\n const c1 = new Vector3()\n const c2 = new Vector3()\n\n for (let i = 0, il = p.residueCount; i < il; ++i) {\n c1.fromArray(pos.center as any, i * 3) // TODO\n c2.fromArray(pos.center as any, i * 3 + 3) // TODO\n const d = c1.distanceTo(c2)\n\n if (d < centerDist && d > 1.0 && pos.bending[ i ] < localAngle) {\n residueStore.sstruc[ offset + i ] = 'h'.charCodeAt(0)\n residueStore.sstruc[ offset + i + 1 ] = 'h'.charCodeAt(0)\n }\n }\n }\n\n return function calculateSecondaryStructure (structure: Structure) {\n if (Debug) Log.time('calculateSecondaryStructure')\n\n structure.eachPolymer(function (p) {\n // assign secondary structure\n if (p.residueCount < 4) return\n if (p.isCg()) {\n cgPolymer(p)\n } else if (p.isProtein()) {\n proteinPolymer(p)\n } else {\n return\n }\n\n // set lone secondary structure assignments to \"c\"\n let prevSstruc: string\n let sstrucCount = 0\n p.eachResidue(function (r: ResidueProxy) {\n if (r.sstruc === prevSstruc) {\n sstrucCount += 1\n } else {\n if (sstrucCount === 1) {\n r.index -= 1\n r.sstruc = 'c'\n }\n sstrucCount = 1\n prevSstruc = r.sstruc\n }\n })\n })\n\n if (Debug) Log.timeEnd('calculateSecondaryStructure')\n }\n}())\n\n// const ChainnameAlphabet = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" +\n// \"abcdefghijklmnopqrstuvwxyz\" +\n// \"0123456789\";\nconst ChainnameAlphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'\n\nexport function getChainname (index: number) {\n const n = ChainnameAlphabet.length\n let j = index\n let k = 0\n let chainname = ChainnameAlphabet[j % n]\n while (j >= n) {\n j = Math.floor(j / n)\n chainname += ChainnameAlphabet[j % n]\n k += 1\n }\n if (k >= 5) {\n Log.warn('chainname overflow')\n }\n return chainname\n}\n\ninterface ChainData {\n mIndex: number\n chainname: string\n rStart: number\n rCount: number\n}\n\n/**\n * When no chain names are set for the given structure, calculates\n * chains based on:\n * - polymer connectivity: when adjacent residues are not bonded, a new chain is created.\n * - non polymer chemical type: adjacent residues which are not polymers but are of the same\n * chemical type (e.g. water molecules) are grouped into the same chain.\n **/\nexport function calculateChainnames (structure: Structure, useExistingBonds = false) {\n if (Debug) Log.time('calculateChainnames')\n\n let doAutoChainName = true\n structure.eachChain(function (c) {\n if (c.chainname) doAutoChainName = false\n })\n\n if (doAutoChainName) {\n const modelStore = structure.modelStore\n const chainStore = structure.chainStore\n const residueStore = structure.residueStore\n\n const addChain = function (mIndex: number, chainname: string, rOffset: number, rCount: number) {\n const ci = chainStore.count\n for (let i = 0; i < rCount; ++i) {\n residueStore.chainIndex[ rOffset + i ] = ci\n }\n chainStore.growIfFull()\n chainStore.modelIndex[ ci ] = mIndex\n chainStore.setChainname(ci, chainname)\n chainStore.setChainid(ci, chainname)\n chainStore.residueOffset[ ci ] = rOffset\n chainStore.residueCount[ ci ] = rCount\n chainStore.count += 1\n modelStore.chainCount[ mIndex ] += 1\n }\n\n const ap1 = structure.getAtomProxy()\n const ap2 = structure.getAtomProxy()\n\n let i = 0\n let mi = 0\n let rStart = 0\n let rEnd = 0\n const chainData: ChainData[] = []\n\n if (residueStore.count === 1) {\n chainData.push({\n mIndex: 0,\n chainname: 'A',\n rStart: 0,\n rCount: 1\n })\n } else {\n structure.eachResidueN(2, function (rp1: ResidueProxy, rp2: ResidueProxy) {\n let newChain = false\n\n const bbType1 = rp1.backboneType\n const bbType2 = rp2.backboneType\n const bbTypeUnk = UnknownBackboneType\n\n rEnd = rp1.index\n\n if (rp1.modelIndex !== rp2.modelIndex) {\n newChain = true\n } else if (rp1.moleculeType !== rp2.moleculeType) {\n newChain = true\n } else if (bbType1 !== bbTypeUnk && bbType1 === bbType2) {\n ap1.index = rp1.backboneEndAtomIndex\n ap2.index = rp2.backboneStartAtomIndex\n if (useExistingBonds) {\n newChain = !ap1.hasBondTo(ap2)\n } else {\n newChain = !ap1.connectedTo(ap2)\n }\n }\n\n // current chain goes to end of the structure\n if (!newChain && rp2.index === residueStore.count - 1) {\n newChain = true\n rEnd = rp2.index\n }\n\n if (newChain) {\n chainData.push({\n mIndex: mi,\n chainname: getChainname(i),\n rStart: rStart,\n rCount: rEnd - rStart + 1\n })\n\n i += 1\n\n if (rp1.modelIndex !== rp2.modelIndex) {\n i = 0\n mi += 1\n }\n\n // new chain for the last residue of the structure\n if (rp2.index === residueStore.count - 1 && rEnd !== rp2.index) {\n chainData.push({\n mIndex: mi,\n chainname: getChainname(i),\n rStart: residueStore.count - 1,\n rCount: 1\n })\n }\n\n rStart = rp2.index\n rEnd = rp2.index\n }\n })\n }\n\n //\n\n chainStore.count = 0\n modelStore.chainCount.fill(0, 0, modelStore.count)\n modelStore.chainOffset.fill(0, 0, modelStore.count)\n chainData.forEach(function (d) {\n addChain(d.mIndex, d.chainname, d.rStart, d.rCount)\n })\n\n let chainOffset = 0\n structure.eachModel(function (mp) {\n modelStore.chainOffset[ mp.index ] = chainOffset\n chainOffset += modelStore.chainCount[ mp.index ]\n })\n }\n\n if (Debug) Log.timeEnd('calculateChainnames')\n}\n\nexport function calculateBonds (structure: Structure, inferBonds: InferBondsOptions='all') {\n if (inferBonds === 'none') return \n if (Debug) Log.time('calculateBonds')\n\n calculateBondsWithin(structure, false, inferBonds)\n calculateBondsBetween(structure)\n\n if (Debug) Log.timeEnd('calculateBonds')\n}\n\n/**\n * Should Bonds be inferred for `all` atoms, `none` or `auto`\n * If `auto`, any hetgroup residue with at least one CONECT record will \n * not have bonding inferred, and will rely on the CONECT records\n */\nexport type InferBondsOptions = 'all' | 'none' | 'auto'\n\nexport interface ResidueBonds {\n atomIndices1: number[]\n atomIndices2: number[]\n bondOrders: number[]\n}\n\n\nconst BondOrderTable: { [k: string]: number } = {\n 'HIS|CD2|CG': 2,\n 'HIS|CE1|ND1': 2,\n 'ARG|CZ|NH2': 2,\n 'PHE|CE1|CZ': 2,\n 'PHE|CD2|CE2': 2,\n 'PHE|CD1|CG': 2,\n 'TRP|CD1|CG': 2,\n 'TRP|CD2|CE2': 2,\n 'TRP|CE3|CZ3': 2,\n 'TRP|CH2|CZ2': 2,\n 'ASN|CG|OD1': 2,\n 'GLN|CD|OE1': 2,\n 'TYR|CD1|CG': 2,\n 'TYR|CD2|CE2': 2,\n 'TYR|CE1|CZ': 2,\n 'ASP|CG|OD1': 2,\n 'GLU|CD|OE1': 2,\n\n 'G|C8|N7': 2,\n 'G|C4|C5': 2,\n 'G|C2|N3': 2,\n 'G|C6|O6': 2,\n 'C|C4|N3': 2,\n 'C|C5|C6': 2,\n 'C|C2|O2': 2,\n 'A|C2|N3': 2,\n 'A|C6|N1': 2,\n 'A|C4|C5': 2,\n 'A|C8|N7': 2,\n 'U|C5|C6': 2,\n 'U|C2|O2': 2,\n 'U|C4|O4': 2,\n\n 'DG|C8|N7': 2,\n 'DG|C4|C5': 2,\n 'DG|C2|N3': 2,\n 'DG|C6|O6': 2,\n 'DC|C4|N3': 2,\n 'DC|C5|C6': 2,\n 'DC|C2|O2': 2,\n 'DA|C2|N3': 2,\n 'DA|C6|N1': 2,\n 'DA|C4|C5': 2,\n 'DA|C8|N7': 2,\n 'DT|C5|C6': 2,\n 'DT|C2|O2': 2,\n 'DT|C4|O4': 2\n}\nfunction getBondOrderFromTable (resname: string, atomname1: string, atomname2: string) {\n [ atomname1, atomname2 ] = atomname1 < atomname2 ? [ atomname1, atomname2 ] : [ atomname2, atomname1 ]\n if (AA3.includes(resname) && atomname1 === 'C' && atomname2 === 'O') return 2\n if (Bases.includes(resname) && atomname1 === 'OP1' && atomname2 === 'P') return 2\n return BondOrderTable[ `${resname}|${atomname1}|${atomname2}` ] || 1\n}\n\nexport function calculateResidueBonds (r: ResidueProxy) {\n const structure = r.structure\n const a1 = structure.getAtomProxy()\n const a2 = structure.getAtomProxy()\n\n const count = r.atomCount\n const offset = r.atomOffset\n const end = offset + count\n const end1 = end - 1\n\n const atomIndices1 = []\n const atomIndices2 = []\n const bondOrders = []\n\n if (count > 500) {\n if (Debug) Log.warn('more than 500 atoms, skip residue for auto-bonding', r.qualifiedName())\n } else {\n if (count > 50) {\n const kdtree = new Kdtree(r, true)\n const radius = r.isCg() ? 1.2 : 2.3\n\n for (let i = offset; i < end1; ++i) {\n a1.index = i\n const maxd = a1.covalent + radius + 0.3\n const nearestAtoms = kdtree.nearest(a1 as any, Infinity, maxd * maxd) // TODO\n const m = nearestAtoms.length\n for (let j = 0; j < m; ++j) {\n a2.index = nearestAtoms[ j ].index\n if (a1.index < a2.index) {\n if (a1.connectedTo(a2)) {\n atomIndices1.push(a1.index - offset)\n atomIndices2.push(a2.index - offset)\n bondOrders.push(getBondOrderFromTable(a1.resname, a1.atomname, a2.atomname))\n }\n }\n }\n }\n } else {\n for (let i = offset; i < end1; ++i) {\n a1.index = i\n for (let j = i + 1; j <= end1; ++j) {\n a2.index = j\n if (a1.connectedTo(a2)) {\n atomIndices1.push(i - offset)\n atomIndices2.push(j - offset)\n bondOrders.push(getBondOrderFromTable(a1.resname, a1.atomname, a2.atomname))\n }\n }\n }\n }\n }\n\n return {\n atomIndices1: atomIndices1,\n atomIndices2: atomIndices2,\n bondOrders: bondOrders\n }\n}\n\nexport function calculateAtomBondMap (structure: Structure) {\n if (Debug) Log.time('calculateAtomBondMap')\n\n var atomBondMap: number[][] = []\n\n structure.eachBond(function (bp) {\n var ai1 = bp.atomIndex1\n var ai2 = bp.atomIndex2\n if (atomBondMap[ ai1 ] === undefined) atomBondMap[ ai1 ] = []\n atomBondMap[ ai1 ][ ai2 ] = bp.index\n })\n\n if (Debug) Log.timeEnd('calculateAtomBondMap')\n\n return atomBondMap\n}\n\nexport function calculateBondsWithin (structure: Structure, onlyAddRung = false, inferBonds: InferBondsOptions='all') {\n if (Debug) Log.time('calculateBondsWithin')\n\n const bondStore = structure.bondStore\n const rungBondStore = structure.rungBondStore\n const rungAtomSet = structure.getAtomSet(false)\n const a1 = structure.getAtomProxy()\n const a2 = structure.getAtomProxy()\n const bp = structure.getBondProxy()\n const atomBondMap = onlyAddRung ? null : calculateAtomBondMap(structure)\n\n let bondedAtoms: Set\n if (!onlyAddRung && inferBonds === 'auto') {\n bondedAtoms = new Set()\n atomBondMap!.forEach((a, i) => {\n bondedAtoms.add(i)\n a.forEach(j => {bondedAtoms.add(j)})\n })\n }\n\n structure.eachResidue(function (r) {\n if (!onlyAddRung && atomBondMap) {\n const count = r.atomCount\n const offset = r.atomOffset\n\n if (count > 500) {\n Log.warn('more than 500 atoms, skip residue for auto-bonding', r.qualifiedName())\n return\n }\n\n if (inferBonds === 'auto' && r.hetero) {\n // Are bonds present on this residue?\n for (let rai=r.atomOffset; rai {\n ncsMatrixList.forEach(nm => {\n ncsUnitcellMatrixList.push(sm.clone().multiply(nm))\n })\n })\n unitcellAssembly.addPart(ncsUnitcellMatrixList)\n } else {\n unitcellAssembly.addPart(unitcellMatrixList)\n }\n\n const vec = new Vector3()\n const supercellAssembly = new Assembly('SUPERCELL')\n const supercellMatrixList = Array.prototype.concat.call(\n getMatrixList(vec.set(1, 0, 0)), // 655\n getMatrixList(vec.set(0, 1, 0)), // 565\n getMatrixList(vec.set(0, 0, 1)), // 556\n\n getMatrixList(vec.set(-1, 0, 0)), // 455\n getMatrixList(vec.set(0, -1, 0)), // 545\n getMatrixList(vec.set(0, 0, -1)), // 554\n\n getMatrixList(vec.set(1, 1, 0)), // 665\n getMatrixList(vec.set(1, 0, 1)), // 656\n getMatrixList(vec.set(0, 1, 1)), // 566\n\n getMatrixList(vec.set(-1, -1, 0)), // 445\n getMatrixList(vec.set(-1, 0, -1)), // 454\n getMatrixList(vec.set(0, -1, -1)), // 544\n\n getMatrixList(vec.set(1, -1, -1)), // 644\n getMatrixList(vec.set(1, 1, -1)), // 664\n getMatrixList(vec.set(1, -1, 1)), // 646\n getMatrixList(vec.set(-1, 1, 1)), // 466\n getMatrixList(vec.set(-1, -1, 1)), // 446\n getMatrixList(vec.set(-1, 1, -1)), // 464\n\n getMatrixList(vec.set(0, 1, -1)), // 564\n getMatrixList(vec.set(0, -1, 1)), // 546\n getMatrixList(vec.set(1, 0, -1)), // 654\n getMatrixList(vec.set(-1, 0, 1)), // 456\n getMatrixList(vec.set(1, -1, 0)), // 645\n getMatrixList(vec.set(-1, 1, 0)), // 465\n\n getMatrixList(), // 555\n getMatrixList(vec.set(1, 1, 1)), // 666\n getMatrixList(vec.set(-1, -1, -1)) // 444\n )\n if (structure.biomolDict.NCS) {\n const ncsSupercellMatrixList: Matrix4[] = []\n supercellMatrixList.forEach(function (sm: Matrix4) {\n ncsMatrixList.forEach(function (nm) {\n ncsSupercellMatrixList.push(sm.clone().multiply(nm))\n })\n })\n supercellAssembly.addPart(ncsSupercellMatrixList)\n } else {\n supercellAssembly.addPart(supercellMatrixList)\n }\n\n structure.biomolDict.UNITCELL = unitcellAssembly\n structure.biomolDict.SUPERCELL = supercellAssembly\n\n if (Debug) Log.timeEnd('buildUnitcellAssembly')\n}\n\nconst elm1 = [ 'H', 'C', 'O', 'N', 'S', 'P' ]\nconst elm2 = [ 'NA', 'CL', 'FE' ]\n\nexport function guessElement (atomName: string) {\n // Retain first group of letters in atomName\n let at = atomName.toUpperCase()\n let begin = 0, end = 0\n for (let i = 0; i < at.length ; i++) {\n if (at.charCodeAt(i) < 65) {\n if (end > 0) break\n ++begin\n }\n else end = i + 1\n }\n if (begin > 0 || end < at.length) at = at.substring(begin, end)\n \n const n = at.length\n\n if (n === 0) return ''\n if (n === 1) return at\n if (n === 2) {\n if (elm2.indexOf(at) !== -1) return at\n if (elm1.indexOf(at[0]) !== -1) return at[0]\n if (at in AtomicNumbers) return at\n }\n if (n >= 3) {\n if (elm1.indexOf(at[0]) !== -1) return at[0]\n }\n return ''\n}\n\n/**\n * Assigns ResidueType bonds.\n * @param {Structure} structure - the structure object\n * @return {undefined}\n */\nexport function assignResidueTypeBonds (structure: Structure) {\n // if( Debug ) Log.time( \"assignResidueTypeBonds\" )\n\n const bondHash = structure.bondHash! // TODO\n const countArray = bondHash.countArray\n const offsetArray = bondHash.offsetArray\n const indexArray = bondHash.indexArray\n const bp = structure.getBondProxy()\n\n structure.eachResidue(function (rp) {\n const residueType = rp.residueType\n if (residueType.bonds !== undefined) return\n\n var atomOffset = rp.atomOffset\n var atomIndices1: number[] = []\n var atomIndices2: number[] = []\n var bondOrders: number[] = []\n var bondDict: { [k: string]: boolean } = {}\n\n const nextAtomOffset = atomOffset + rp.atomCount\n\n rp.eachAtom(function (ap) {\n const index = ap.index\n const offset = offsetArray[ index ]\n const count = countArray[ index ]\n for (let i = 0, il = count; i < il; ++i) {\n bp.index = indexArray[ offset + i ]\n let idx1 = bp.atomIndex1\n if (idx1 < atomOffset || idx1 >= nextAtomOffset) {\n // Don't add bonds outside of this resiude\n continue\n }\n let idx2 = bp.atomIndex2\n if (idx2 < atomOffset || idx2 >= nextAtomOffset) {\n continue\n }\n\n if (idx1 > idx2) {\n const tmp = idx2\n idx2 = idx1\n idx1 = tmp\n }\n const hash = idx1 + '|' + idx2\n if (bondDict[ hash ] === undefined) {\n bondDict[ hash ] = true\n atomIndices1.push(idx1 - atomOffset)\n atomIndices2.push(idx2 - atomOffset)\n bondOrders.push(bp.bondOrder)\n }\n }\n })\n\n residueType.bonds = {\n atomIndices1: atomIndices1,\n atomIndices2: atomIndices2,\n bondOrders: bondOrders\n }\n })\n\n // if( Debug ) Log.timeEnd( \"assignResidueTypeBonds\" )\n}\n\nexport function concatStructures (name: string, ...structures: Structure[]) {\n if( Debug ) Log.time( \"concatStructures\" )\n\n const s = new Structure(name, '')\n const sb = new StructureBuilder(s)\n\n const atomStore = s.atomStore as any\n const atomMap = s.atomMap\n atomStore.addField('formalCharge', 1, 'int8')\n atomStore.addField('partialCharge', 1, 'float32')\n\n const atomIndexDict: { [k: number]: number } = {}\n\n let idx = 0\n let atomCount = 0\n let modelCount = 0\n structures.forEach(structure => {\n structure.eachAtom(a => {\n atomStore.growIfFull()\n atomStore.atomTypeId[ idx ] = atomMap.add(a.atomname, a.element)\n\n atomStore.x[ idx ] = a.x\n atomStore.y[ idx ] = a.y\n atomStore.z[ idx ] = a.z\n atomStore.serial[ idx ] = a.serial\n atomStore.formalCharge[ idx ] = a.formalCharge\n atomStore.partialCharge[ idx ] = a.partialCharge\n atomStore.altloc[ idx ] = a.altloc\n atomStore.occupancy[ idx ] = a.occupancy\n atomStore.bfactor[ idx ] = a.bfactor\n\n sb.addAtom(\n a.modelIndex + modelCount,\n a.chainname,\n a.chainid,\n a.resname,\n a.resno,\n a.hetero === 1,\n a.sstruc,\n a.inscode\n )\n\n atomIndexDict[a.index + atomCount] = idx\n idx += 1\n })\n atomCount += structure.atomStore.count\n modelCount += structure.modelStore.count\n })\n\n const bondStore = s.bondStore\n const a1 = s.getAtomProxy()\n const a2 = s.getAtomProxy()\n\n atomCount = 0\n structures.forEach(structure => {\n structure.eachBond(b => {\n a1.index = atomIndexDict[ b.atomIndex1 + atomCount ]\n a2.index = atomIndexDict[ b.atomIndex2 + atomCount ]\n bondStore.addBond(a1, a2, b.bondOrder)\n })\n atomCount += structure.atomStore.count\n })\n\n sb.finalize()\n\n calculateBondsBetween(s, true) // calculate backbone bonds\n calculateBondsWithin(s, true) // calculate rung bonds\n\n s.finalizeAtoms()\n s.finalizeBonds()\n assignResidueTypeBonds(s)\n\n if( Debug ) Log.timeEnd( \"concatStructures\" )\n\n return s\n}\n","/**\n * @file Atom Type\n * @author Alexander Rose \n * @private\n */\n\nimport { guessElement } from '../structure/structure-utils'\nimport {\n AtomicNumbers, DefaultAtomicNumber,\n VdwRadii, DefaultVdwRadius,\n CovalentRadii, DefaultCovalentRadius,\n Valences, DefaultValence,\n OuterShellElectronCounts, DefaultOuterShellElectronCount\n} from '../structure/structure-constants'\nimport Structure from '../structure/structure'\n\n// Li, Na, K, Rb, Cs Fr\nconst AlkaliMetals = [ 3, 11, 19, 37, 55, 87 ]\n\n// Be, Mg, Ca, Sr, Ba, Ra\nconst AlkalineEarthMetals = [ 4, 12, 20, 38, 56, 88 ]\n\n// C, P, S, Se\nconst PolyatomicNonmetals = [ 6, 15, 16, 34, ]\n\n// H, N, O, F, Cl, Br, I\nconst DiatomicNonmetals = [ 1, 7, 8, 9, 17, 35, 53 ]\n\n// He, Ne, Ar, Kr, Xe, Rn\nconst NobleGases = [ 2, 10, 18, 36, 54, 86 ]\n\n// Zn, Ga, Cd, In, Sn, Hg, Ti, Pb, Bi, Po, Cn\nconst PostTransitionMetals = [ 13, 30, 31, 48, 49, 50, 80, 81, 82, 83, 84, 85, 112 ]\n\n// B, Si, Ge, As, Sb, Te, At\nconst Metalloids = [ 5, 14, 32, 33, 51, 52, 85 ]\n\n// F, Cl, Br, I, At\nconst Halogens = [ 9, 17, 35, 53, 85 ]\n\n/**\n * Atom type\n */\nclass AtomType {\n element: string\n number: number\n vdw: number\n covalent: number\n\n /**\n * @param {Structure} structure - the structure object\n * @param {String} atomname - the name of the atom\n * @param {String} element - the chemical element\n */\n constructor (readonly structure: Structure, readonly atomname: string, element?: string) {\n element = element || guessElement(atomname)\n\n this.element = element\n this.number = AtomicNumbers[ element ] || DefaultAtomicNumber\n this.vdw = VdwRadii[ this.number ] || DefaultVdwRadius\n this.covalent = CovalentRadii[ this.number ] || DefaultCovalentRadius\n }\n\n getDefaultValence() {\n const vl = Valences[ this.number ]\n return vl ? vl[ 0 ] : DefaultValence\n }\n\n getValenceList () {\n return Valences[ this.number ] || []\n }\n\n getOuterShellElectronCount () {\n return OuterShellElectronCounts[ this.number ] || DefaultOuterShellElectronCount\n }\n\n isMetal () {\n return (\n this.isAlkaliMetal() ||\n this.isAlkalineEarthMetal() ||\n this.isLanthanide() ||\n this.isActinide() ||\n this.isTransitionMetal() ||\n this.isPostTransitionMetal()\n )\n }\n\n isNonmetal () {\n return (\n this.isDiatomicNonmetal() ||\n this.isPolyatomicNonmetal() ||\n this.isNobleGas()\n )\n }\n\n isMetalloid () {\n return Metalloids.includes(this.number)\n }\n\n isHalogen () {\n return Halogens.includes(this.number)\n }\n\n isDiatomicNonmetal () {\n return DiatomicNonmetals.includes(this.number)\n }\n\n isPolyatomicNonmetal () {\n return PolyatomicNonmetals.includes(this.number)\n }\n\n isAlkaliMetal () {\n return AlkaliMetals.includes(this.number)\n }\n\n isAlkalineEarthMetal () {\n return AlkalineEarthMetals.includes(this.number)\n }\n\n isNobleGas () {\n return NobleGases.includes(this.number)\n }\n\n isTransitionMetal () {\n const no = this.number\n return (\n (no >= 21 && no <= 29) ||\n (no >= 39 && no <= 47) ||\n (no >= 72 && no <= 79) ||\n (no >= 104 && no <= 108)\n )\n }\n\n isPostTransitionMetal () {\n return PostTransitionMetals.includes(this.number)\n }\n\n isLanthanide () {\n return this.number >= 57 && this.number <= 71\n }\n\n isActinide () {\n return this.number >= 89 && this.number <= 103\n }\n\n}\n\nexport default AtomType","/**\n * @file Atom Map\n * @author Alexander Rose \n * @private\n */\n\nimport AtomType from './atom-type'\nimport { guessElement } from '../structure/structure-utils'\nimport Structure from '../structure/structure'\n\nfunction getHash (atomname: string, element: string) {\n return atomname + '|' + element\n}\n\nclass AtomMap {\n dict: { [k: string]: number } = {}\n list: AtomType[] = []\n\n constructor (readonly structure: Structure) {\n this.structure = structure\n }\n\n add (atomname: string, element?: string) {\n atomname = atomname.toUpperCase()\n if (!element) {\n element = guessElement(atomname)\n } else {\n element = element.toUpperCase()\n }\n const hash = getHash(atomname, element)\n let id = this.dict[ hash ]\n if (id === undefined) {\n const atomType = new AtomType(this.structure, atomname, element)\n id = this.list.length\n this.dict[ hash ] = id\n this.list.push(atomType)\n }\n return id\n }\n\n get (id: number) {\n return this.list[ id ]\n }\n}\n\nexport default AtomMap\n","/**\n * @file Residue Type\n * @author Alexander Rose \n * @author Fred Ludlow\n * @private\n */\n\nimport { defaults } from '../utils'\nimport PrincipalAxes from '../math/principal-axes'\nimport { Matrix } from '../math/matrix-utils'\nimport { calculateResidueBonds, ResidueBonds } from '../structure/structure-utils'\nimport {\n Elements,\n ProteinType, RnaType, DnaType, WaterType, IonType, SaccharideType, UnknownType,\n ProteinBackboneType, RnaBackboneType, DnaBackboneType, UnknownBackboneType,\n CgProteinBackboneType, CgRnaBackboneType, CgDnaBackboneType,\n ChemCompProtein, ChemCompRna, ChemCompDna, ChemCompSaccharide,\n AA3, PurinBases, RnaBases, DnaBases, Bases, IonNames, WaterNames, SaccharideNames,\n ProteinBackboneAtoms, NucleicBackboneAtoms, ResidueTypeAtoms\n} from '../structure/structure-constants'\nimport Structure from '../structure/structure'\nimport ResidueProxy from '../proxy/residue-proxy'\nimport AtomProxy from '../proxy/atom-proxy'\n\nexport interface BondGraph {\n [k: number]: number[]\n}\n\nexport interface RingData {\n atomRings: number[][] // sparse array:\n // atomRings[atomIdx] -> array of ring indices\n rings: number[][] // rings as arrays of indices\n}\n\n/**\n * Residue type\n */\nexport default class ResidueType {\n resname: string\n atomTypeIdList: number[]\n hetero: number\n chemCompType: string\n bonds?: ResidueBonds\n rings?: RingData\n bondGraph?: BondGraph\n aromaticAtoms?: Uint8Array\n aromaticRings?: number[][]\n\n atomCount: number\n\n moleculeType: number\n backboneType: number\n backboneEndType: number\n backboneStartType: number\n backboneIndexList: number[]\n\n traceAtomIndex: number\n direction1AtomIndex: number\n direction2AtomIndex: number\n backboneStartAtomIndex: number\n backboneEndAtomIndex: number\n rungEndAtomIndex: number\n\n // Sparse array containing the reference atom index for each bond.\n bondReferenceAtomIndices: number[] = []\n\n /**\n * @param {Structure} structure - the structure object\n * @param {String} resname - name of the residue\n * @param {Array} atomTypeIdList - list of IDs of {@link AtomType}s corresponding\n * to the atoms of the residue\n * @param {Boolean} hetero - hetero flag\n * @param {String} chemCompType - chemical component type\n * @param {Object} [bonds] - TODO\n */\n constructor (readonly structure: Structure, resname: string, atomTypeIdList: number[], hetero: boolean, chemCompType: string, bonds?: ResidueBonds) {\n this.resname = resname\n this.atomTypeIdList = atomTypeIdList\n this.hetero = hetero ? 1 : 0\n this.chemCompType = chemCompType\n this.bonds = bonds\n this.atomCount = atomTypeIdList.length\n\n this.moleculeType = this.getMoleculeType()\n this.backboneType = this.getBackboneType(0)\n this.backboneEndType = this.getBackboneType(-1)\n this.backboneStartType = this.getBackboneType(1)\n this.backboneIndexList = this.getBackboneIndexList()\n\n const atomnames = ResidueTypeAtoms[ this.backboneType ]\n const atomnamesStart = ResidueTypeAtoms[ this.backboneStartType ]\n const atomnamesEnd = ResidueTypeAtoms[ this.backboneEndType ]\n\n const traceIndex = this.getAtomIndexByName(atomnames.trace)\n this.traceAtomIndex = defaults(traceIndex, -1)\n\n const dir1Index = this.getAtomIndexByName(atomnames.direction1)\n this.direction1AtomIndex = defaults(dir1Index, -1)\n\n const dir2Index = this.getAtomIndexByName(atomnames.direction2)\n this.direction2AtomIndex = defaults(dir2Index, -1)\n\n const bbStartIndex = this.getAtomIndexByName(atomnamesStart.backboneStart)\n this.backboneStartAtomIndex = defaults(bbStartIndex, -1)\n\n const bbEndIndex = this.getAtomIndexByName(atomnamesEnd.backboneEnd)\n this.backboneEndAtomIndex = defaults(bbEndIndex, -1)\n\n let rungEndIndex\n if (PurinBases.includes(resname)) {\n rungEndIndex = this.getAtomIndexByName('N1')\n } else {\n rungEndIndex = this.getAtomIndexByName('N3')\n }\n this.rungEndAtomIndex = defaults(rungEndIndex, -1)\n }\n\n getBackboneIndexList () {\n const backboneIndexList: number[] = []\n let atomnameList\n switch (this.moleculeType) {\n case ProteinType:\n atomnameList = ProteinBackboneAtoms\n break\n case RnaType:\n case DnaType:\n atomnameList = NucleicBackboneAtoms\n break\n default:\n return backboneIndexList\n }\n const atomMap = this.structure.atomMap\n const atomTypeIdList = this.atomTypeIdList\n for (let i = 0, il = this.atomCount; i < il; ++i) {\n const atomType = atomMap.get(atomTypeIdList[ i ])\n if (atomnameList.includes(atomType.atomname)) {\n backboneIndexList.push(i)\n }\n }\n return backboneIndexList\n }\n\n getMoleculeType () {\n if (this.isProtein()) {\n return ProteinType\n } else if (this.isRna()) {\n return RnaType\n } else if (this.isDna()) {\n return DnaType\n } else if (this.isWater()) {\n return WaterType\n } else if (this.isIon()) {\n return IonType\n } else if (this.isSaccharide()) {\n return SaccharideType\n } else {\n return UnknownType\n }\n }\n\n getBackboneType (position: number) {\n if (this.hasProteinBackbone(position)) {\n return ProteinBackboneType\n } else if (this.hasRnaBackbone(position)) {\n return RnaBackboneType\n } else if (this.hasDnaBackbone(position)) {\n return DnaBackboneType\n } else if (this.hasCgProteinBackbone(position)) {\n return CgProteinBackboneType\n } else if (this.hasCgRnaBackbone(position)) {\n return CgRnaBackboneType\n } else if (this.hasCgDnaBackbone(position)) {\n return CgDnaBackboneType\n } else {\n return UnknownBackboneType\n }\n }\n\n isProtein () {\n if (this.chemCompType) {\n return ChemCompProtein.includes(this.chemCompType)\n } else {\n return (\n this.hasAtomWithName('CA', 'C', 'N') ||\n AA3.includes(this.resname)\n )\n }\n }\n\n isCg () {\n const backboneType = this.backboneType\n return (\n backboneType === CgProteinBackboneType ||\n backboneType === CgRnaBackboneType ||\n backboneType === CgDnaBackboneType\n )\n }\n\n isNucleic () {\n return this.isRna() || this.isDna()\n }\n\n isRna () {\n if (this.chemCompType) {\n return ChemCompRna.includes(this.chemCompType)\n } else if (this.hetero === 1) {\n return false\n } else {\n return (\n this.hasAtomWithName(\n [ 'P', \"O3'\", 'O3*' ], [ \"C4'\", 'C4*' ], [ \"O2'\", 'O2*', \"F2'\", 'F2*' ]\n ) ||\n (RnaBases.includes(this.resname) &&\n (this.hasAtomWithName([ \"O2'\", 'O2*', \"F2'\", 'F2*' ])))\n )\n }\n }\n\n isDna () {\n if (this.chemCompType) {\n return ChemCompDna.includes(this.chemCompType)\n } else if (this.hetero === 1) {\n return false\n } else {\n return (\n (this.hasAtomWithName([ 'P', \"O3'\", 'O3*' ], [ \"C3'\", 'C3*' ]) &&\n !this.hasAtomWithName([ \"O2'\", 'O2*', \"F2'\", 'F2*' ])) ||\n DnaBases.includes(this.resname)\n )\n }\n }\n\n isHetero () {\n return this.hetero === 1\n }\n\n isIon () {\n return IonNames.includes(this.resname)\n }\n\n isWater () {\n return WaterNames.includes(this.resname)\n }\n\n isSaccharide () {\n if (this.chemCompType) {\n return ChemCompSaccharide.includes(this.chemCompType)\n } else {\n return SaccharideNames.includes(this.resname)\n }\n }\n\n isStandardAminoacid () {\n return AA3.includes(this.resname)\n }\n\n isStandardBase () {\n return Bases.includes(this.resname)\n }\n\n hasBackboneAtoms (position: number, type: number) {\n const atomnames = ResidueTypeAtoms[ type ]\n if (position === -1) {\n return this.hasAtomWithName(\n atomnames.trace,\n atomnames.backboneEnd,\n atomnames.direction1,\n atomnames.direction2\n )\n } else if (position === 0) {\n return this.hasAtomWithName(\n atomnames.trace,\n atomnames.direction1,\n atomnames.direction2\n )\n } else if (position === 1) {\n return this.hasAtomWithName(\n atomnames.trace,\n atomnames.backboneStart,\n atomnames.direction1,\n atomnames.direction2\n )\n } else {\n return this.hasAtomWithName(\n atomnames.trace,\n atomnames.backboneStart,\n atomnames.backboneEnd,\n atomnames.direction1,\n atomnames.direction2\n )\n }\n }\n\n hasProteinBackbone (position: number) {\n return (\n this.isProtein() &&\n this.hasBackboneAtoms(position, ProteinBackboneType)\n )\n }\n\n hasRnaBackbone (position: number) {\n return (\n this.isRna() &&\n this.hasBackboneAtoms(position, RnaBackboneType)\n )\n }\n\n hasDnaBackbone (position: number) {\n return (\n this.isDna() &&\n this.hasBackboneAtoms(position, DnaBackboneType)\n )\n }\n\n hasCgProteinBackbone (position: number) {\n return (\n this.atomCount < 7 &&\n this.isProtein() &&\n this.hasBackboneAtoms(position, CgProteinBackboneType)\n )\n }\n\n hasCgRnaBackbone (position: number) {\n return (\n this.atomCount < 11 &&\n this.isRna() &&\n this.hasBackboneAtoms(position, CgRnaBackboneType)\n )\n }\n\n hasCgDnaBackbone (position: number) {\n return (\n this.atomCount < 11 &&\n this.isDna() &&\n this.hasBackboneAtoms(position, CgDnaBackboneType)\n )\n }\n\n hasBackbone (position: number) {\n return (\n this.hasProteinBackbone(position) ||\n this.hasRnaBackbone(position) ||\n this.hasDnaBackbone(position) ||\n this.hasCgProteinBackbone(position) ||\n this.hasCgRnaBackbone(position) ||\n this.hasCgDnaBackbone(position)\n )\n }\n\n getAtomIndexByName (atomname: string|string[]) {\n const n = this.atomCount\n const atomMap = this.structure.atomMap\n const atomTypeIdList = this.atomTypeIdList\n if (Array.isArray(atomname)) {\n for (let i = 0; i < n; ++i) {\n const index = atomTypeIdList[ i ]\n if (atomname.includes(atomMap.get(index).atomname)) {\n return i\n }\n }\n } else {\n for (let i = 0; i < n; ++i) {\n const index = atomTypeIdList[ i ]\n if (atomname === atomMap.get(index).atomname) {\n return i\n }\n }\n }\n return undefined\n }\n\n hasAtomWithName (...atomnames: (string|string[])[]) {\n const n = atomnames.length\n for (let i = 0; i < n; ++i) {\n if (atomnames[ i ] === undefined) continue\n if (this.getAtomIndexByName(atomnames[ i ]) === undefined) {\n return false\n }\n }\n return true\n }\n\n getBonds (r?: ResidueProxy) {\n if (this.bonds === undefined) {\n this.bonds = calculateResidueBonds(r!) // TODO\n }\n return this.bonds\n }\n\n getRings () {\n if (this.rings === undefined) {\n this.calculateRings()\n }\n return this.rings\n }\n\n getBondGraph () {\n if (this.bondGraph === undefined) {\n this.calculateBondGraph()\n }\n return this.bondGraph\n }\n\n getAromatic (a?: AtomProxy) {\n if (this.aromaticAtoms === undefined) {\n this.calculateAromatic(this.structure.getResidueProxy((a!).residueIndex)) // TODO\n }\n return this.aromaticAtoms\n }\n\n getAromaticRings (r?: ResidueProxy) {\n if (this.aromaticRings === undefined) {\n this.calculateAromatic(r!) // TODO\n }\n return this.aromaticRings\n }\n\n /**\n * @return {Object} bondGraph - represents the bonding in this\n * residue: { ai1: [ ai2, ai3, ...], ...}\n */\n calculateBondGraph () {\n const bondGraph: BondGraph = this.bondGraph = {}\n const bonds = this.getBonds()\n const nb = bonds.atomIndices1.length\n const atomIndices1 = bonds.atomIndices1\n const atomIndices2 = bonds.atomIndices2\n\n for (let i = 0; i < nb; ++i) {\n const ai1 = atomIndices1[i]\n const ai2 = atomIndices2[i]\n\n const a1 = bondGraph[ ai1 ] = bondGraph[ ai1 ] || []\n a1.push(ai2)\n\n const a2 = bondGraph[ ai2 ] = bondGraph[ ai2 ] || []\n a2.push(ai1)\n }\n }\n\n /**\n * Find all rings up to 2 * RingFinderMaxDepth\n */\n calculateRings () {\n const bondGraph = this.getBondGraph()! // TODO\n const state = RingFinderState(bondGraph, this.atomCount)\n\n for (let i = 0; i < state.count; i++) {\n if (state.visited[i] >= 0) continue\n findRings(state, i)\n }\n\n this.rings = { atomRings: state.atomRings, rings: state.rings }\n }\n\n isAromatic (atom: AtomProxy) {\n this.aromaticAtoms = this.getAromatic(atom)! // TODO\n return this.aromaticAtoms[atom.index - atom.residueAtomOffset] === 1\n }\n\n calculateAromatic (r: ResidueProxy) {\n const aromaticAtoms = this.aromaticAtoms = new Uint8Array(this.atomCount)\n const rings = this.getRings()!.rings\n\n const aromaticRingFlags = rings.map(ring => {\n return isRingAromatic(ring.map(idx => {\n return this.structure.getAtomProxy(idx + r.atomOffset)\n }))\n })\n\n const aromaticRings: number[][] = this.aromaticRings = []\n rings.forEach((ring, i) => {\n if (aromaticRingFlags[i]) {\n aromaticRings.push(ring)\n ring.forEach(idx => aromaticAtoms[idx] = 1)\n }\n })\n }\n\n /**\n * For bonds with order > 1, pick a reference atom\n * @return {undefined}\n */\n assignBondReferenceAtomIndices () {\n const bondGraph = this.getBondGraph()! // TODO\n const rings = this.getRings()! // TODO\n const atomRings = rings.atomRings\n const ringData = rings.rings\n\n const bonds = this.bonds! // TODO\n const atomIndices1 = bonds.atomIndices1\n const atomIndices2 = bonds.atomIndices2\n const bondOrders = bonds.bondOrders\n const bondReferenceAtomIndices = this.bondReferenceAtomIndices\n\n const nb = bonds.atomIndices1.length\n\n bondReferenceAtomIndices.length = 0 // reset array\n\n for (let i = 0; i < nb; ++i) {\n // Not required for single bonds\n if (bondOrders[i] <= 1) continue\n\n let refRing\n\n const ai1 = atomIndices1[i]\n const ai2 = atomIndices2[i]\n\n const rings1 = atomRings[ ai1 ]\n const rings2 = atomRings[ ai2 ]\n // Are both atoms in a ring?\n if (rings1 && rings2) {\n // Are they in the same ring? (If not, ignore ring info)\n for (let ri1 = 0; ri1 < rings1.length; ri1++){\n if (rings2.indexOf(rings1[ ri1 ]) !== -1) {\n refRing = ringData[ rings1[ ri1 ] ]\n break\n }\n }\n }\n\n // Find the first neighbour.\n if (bondGraph[ ai1 ].length > 1) {\n for (let j = 0; j < bondGraph[ ai1 ].length; ++j) {\n const ai3 = bondGraph[ ai1 ][ j ]\n if (ai3 !== ai2) {\n if (refRing === undefined || refRing.indexOf(ai3) !== -1){\n bondReferenceAtomIndices[i] = ai3\n break\n }\n }\n }\n } else if (bondGraph[ ai2 ].length > 1) {\n for (let j = 0; j < bondGraph[ ai2 ].length; ++j) {\n const ai3 = bondGraph[ ai2 ][ j ]\n if (ai3 !== ai1) {\n if (refRing === undefined || refRing.indexOf(ai3) !== -1){\n bondReferenceAtomIndices[i] = ai3\n break\n }\n }\n }\n } // No reference atom could be found (e.g. diatomic molecule/fragment)\n }\n }\n\n getBondIndex (atomIndex1: number, atomIndex2: number) {\n const bonds = this.bonds! // TODO\n const atomIndices1 = bonds.atomIndices1\n const atomIndices2 = bonds.atomIndices2\n let idx1 = atomIndices1.indexOf(atomIndex1)\n let idx2 = atomIndices2.indexOf(atomIndex2)\n const _idx2 = idx2\n while (idx1 !== -1) {\n while (idx2 !== -1) {\n if (idx1 === idx2) return idx1\n idx2 = atomIndices2.indexOf(atomIndex2, idx2 + 1)\n }\n idx1 = atomIndices1.indexOf(atomIndex1, idx1 + 1)\n idx2 = _idx2\n }\n // returns undefined when no bond is found\n }\n\n getBondReferenceAtomIndex (atomIndex1: number, atomIndex2: number) {\n const bondIndex = this.getBondIndex(atomIndex1, atomIndex2)\n if (bondIndex === undefined) return undefined\n if (this.bondReferenceAtomIndices.length === 0) {\n this.assignBondReferenceAtomIndices()\n }\n return this.bondReferenceAtomIndices[ bondIndex ]\n }\n}\n\n//\n\nconst AromaticRingElements = [\n Elements.B, Elements.C, Elements.N, Elements.O,\n Elements.SI, Elements.P, Elements.S,\n Elements.GE, Elements.AS,\n Elements.SN, Elements.SB,\n Elements.BI\n]\nconst AromaticRingPlanarityThreshold = 0.05\n\nfunction isRingAromatic (ring: AtomProxy[]) {\n if (ring.some(a => !AromaticRingElements.includes(a.number))) return false\n\n let i = 0\n const coords = new Matrix(3, ring.length)\n const cd = coords.data\n\n ring.forEach(a => {\n cd[ i + 0 ] = a.x\n cd[ i + 1 ] = a.y\n cd[ i + 2 ] = a.z\n i += 3\n })\n\n const pa = new PrincipalAxes(coords)\n\n return pa.vecC.length() < AromaticRingPlanarityThreshold\n}\n\n//\n\n/**\n * Ring finding code below adapted from MolQL\n * Copyright (c) 2017 MolQL contributors, licensed under MIT\n * @author David Sehnal \n */\n\nfunction addRing(state: RingFinderState, a: number, b: number) {\n // only \"monotonous\" rings\n if (b < a) return\n\n const { pred, color, left, right } = state\n const nc = ++state.currentColor\n\n let current = a\n\n for (let t = 0; t < RingFinderMaxDepth; t++) {\n color[current] = nc\n current = pred[current]\n if (current < 0) break\n }\n\n let leftOffset = 0\n let rightOffset = 0\n\n let found = false\n let target = 0\n current = b\n for (let t = 0; t < RingFinderMaxDepth; t++) {\n if (color[current] === nc) {\n target = current\n found = true\n break\n }\n right[rightOffset++] = current\n current = pred[current]\n if (current < 0) break\n }\n if (!found) return\n\n current = a\n for (let t = 0; t < RingFinderMaxDepth; t++) {\n left[leftOffset++] = current\n if (target === current) break\n current = pred[current]\n if (current < 0) break\n }\n\n const rn = leftOffset + rightOffset\n const ring: number[] = new Array(rn)\n let ringOffset = 0;\n for (let t = 0; t < leftOffset; t++) {\n ring[ringOffset++] = left[t]\n }\n for (let t = rightOffset - 1; t >= 0; t--) {\n ring[ringOffset++] = right[t]\n }\n\n const ri = state.rings.length\n // set atomRing indices:\n for (let i = 0; i < rn; ++i) {\n const ai = ring[i]\n if (state.atomRings[ai]) {\n state.atomRings[ai].push(ri)\n } else {\n state.atomRings[ai] = [ri]\n }\n }\n\n state.rings.push(ring)\n}\n\nfunction findRings(state: RingFinderState, from: number) {\n const { bonds, visited, queue, pred } = state\n\n visited[from] = 1\n queue[0] = from\n\n let head = 0\n let size = 1\n\n while (head < size) {\n const top = queue[head++]\n const start = 0\n if (bonds[top] === undefined) {\n continue\n }\n const end = bonds[top].length\n\n for (let i = start; i < end; i++) {\n const other = bonds[top][i]\n\n if (visited[other] > 0) {\n if (pred[other] !== top && pred[top] !== other) {\n addRing(state, top, other)\n }\n continue\n }\n\n visited[other] = 1\n queue[size++] = other\n pred[other] = top\n }\n }\n}\n\nconst RingFinderMaxDepth = 4\n\ninterface RingFinderState {\n count: number,\n visited: Int32Array,\n queue: Int32Array,\n color: Int32Array,\n pred: Int32Array,\n\n left: Int32Array,\n right: Int32Array,\n\n currentColor: number,\n\n rings: number[][],\n atomRings: number[][],\n\n bonds: BondGraph\n}\n\nfunction RingFinderState(bonds: BondGraph, capacity: number): RingFinderState {\n const state = {\n count: capacity,\n visited: new Int32Array(capacity),\n queue: new Int32Array(capacity),\n pred: new Int32Array(capacity),\n left: new Int32Array(RingFinderMaxDepth),\n right: new Int32Array(RingFinderMaxDepth),\n color: new Int32Array(capacity),\n currentColor: 0,\n rings: [],\n atomRings: [],\n bonds\n }\n for (let i = 0; i < capacity; i++) {\n state.visited[i] = -1\n state.pred[i] = -1\n }\n return state\n}\n","/**\n * @file Residue Map\n * @author Alexander Rose \n * @private\n */\n\nimport Structure from '../structure/structure'\nimport { ResidueBonds } from '../structure/structure-utils'\nimport ResidueType from './residue-type'\n\nfunction getHash (resname: string, atomTypeIdList: number[], hetero: boolean, chemCompType = '') {\n return (\n resname + '|' +\n atomTypeIdList.join(',') + '|' +\n (hetero ? 1 : 0) + '|' +\n chemCompType\n )\n}\n\nclass ResidueMap {\n dict: { [k: string]: number } = {}\n list: ResidueType[] = []\n\n constructor (readonly structure: Structure) {}\n\n add (resname: string, atomTypeIdList: number[], hetero: boolean, chemCompType = '', bonds?: ResidueBonds) {\n resname = resname.toUpperCase()\n const hash = getHash(resname, atomTypeIdList, hetero, chemCompType)\n let id = this.dict[ hash ]\n if (id === undefined) {\n const residueType = new ResidueType(\n this.structure, resname, atomTypeIdList, hetero, chemCompType, bonds\n )\n id = this.list.length\n this.dict[ hash ] = id\n this.list.push(residueType)\n }\n return id\n }\n\n get (id: number) {\n return this.list[ id ]\n }\n}\n\nexport default ResidueMap\n","/**\n * @file Bond Proxy\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport Structure from '../structure/structure'\nimport BondStore from '../store/bond-store'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Bond proxy\n */\nclass BondProxy {\n index: number\n\n bondStore: BondStore\n\n private _v12: Vector3\n private _v13: Vector3\n private _ap1: AtomProxy\n private _ap2: AtomProxy\n private _ap3: AtomProxy\n\n /**\n * @param {Structure} structure - the structure\n * @param {Integer} index - the index\n */\n constructor (readonly structure: Structure, index = 0) {\n this.index = index\n this.bondStore = structure.bondStore\n\n this._v12 = new Vector3()\n this._v13 = new Vector3()\n this._ap1 = this.structure.getAtomProxy()\n this._ap2 = this.structure.getAtomProxy()\n this._ap3 = this.structure.getAtomProxy()\n }\n\n /**\n * @type {AtomProxy}\n */\n get atom1 () {\n return this.structure.getAtomProxy(this.atomIndex1)\n }\n\n /**\n * @type {AtomProxy}\n */\n get atom2 () {\n return this.structure.getAtomProxy(this.atomIndex2)\n }\n\n /**\n * @type {Integer}\n */\n get atomIndex1 () {\n return this.bondStore.atomIndex1[ this.index ]\n }\n set atomIndex1 (value) {\n this.bondStore.atomIndex1[ this.index ] = value\n }\n\n /**\n * @type {Integer}\n */\n get atomIndex2 () {\n return this.bondStore.atomIndex2[ this.index ]\n }\n set atomIndex2 (value) {\n this.bondStore.atomIndex2[ this.index ] = value\n }\n\n /**\n * @type {Integer}\n */\n get bondOrder () {\n return this.bondStore.bondOrder[ this.index ]\n }\n set bondOrder (value) {\n this.bondStore.bondOrder[ this.index ] = value\n }\n\n getOtherAtomIndex (atomIndex: number) {\n return atomIndex === this.atomIndex1 ? this.atomIndex2 : this.atomIndex1\n }\n\n getOtherAtom (atom: AtomProxy) {\n return this.structure.getAtomProxy(this.getOtherAtomIndex(atom.index))\n }\n\n /**\n * Get reference atom index for the bond\n * @return {Integer|undefined} atom index, or `undefined` if unavailable\n */\n getReferenceAtomIndex () {\n const ap1 = this._ap1\n const ap2 = this._ap2\n ap1.index = this.atomIndex1\n ap2.index = this.atomIndex2\n if (ap1.residueIndex !== ap2.residueIndex) {\n return undefined // Bond between residues, for now ignore (could detect)\n }\n const typeAtomIndex1 = ap1.index - ap1.residueAtomOffset\n const typeAtomIndex2 = ap2.index - ap2.residueAtomOffset\n const residueType = ap1.residueType\n const ix = residueType.getBondReferenceAtomIndex(typeAtomIndex1, typeAtomIndex2)\n if (ix !== undefined) {\n return ix + ap1.residueAtomOffset\n } else {\n console.warn('No reference atom found', ap1.index, ap2.index)\n }\n }\n\n /**\n * calculate shift direction for displaying double/triple bonds\n * @param {Vector3} [v] pre-allocated output vector\n * @return {Vector3} the shift direction vector\n */\n calculateShiftDir (v = new Vector3()) {\n const ap1 = this._ap1\n const ap2 = this._ap2\n const ap3 = this._ap3\n const v12 = this._v12\n const v13 = this._v13\n\n ap1.index = this.atomIndex1\n ap2.index = this.atomIndex2\n const ai3 = this.getReferenceAtomIndex()\n\n v12.subVectors(ap1 as any, ap2 as any).normalize() // TODO\n if (ai3 !== undefined) {\n ap3.index = ai3\n v13.subVectors(ap1 as any, ap3 as any) // TODO\n } else {\n v13.copy(ap1 as any) // no reference point, use origin // TODO\n }\n v13.normalize()\n\n // make sure v13 and v12 are not colinear\n let dp = v12.dot(v13)\n if (1 - Math.abs(dp) < 1e-5) {\n v13.set(1, 0, 0)\n dp = v12.dot(v13)\n if (1 - Math.abs(dp) < 1e-5) {\n v13.set(0, 1, 0)\n dp = v12.dot(v13)\n }\n }\n\n return v.copy(v13.sub(v12.multiplyScalar(dp))).normalize()\n }\n\n qualifiedName () {\n return this.atomIndex1 + '=' + this.atomIndex2\n }\n\n /**\n * Clone object\n * @return {BondProxy} cloned bond\n */\n clone () {\n return new BondProxy(this.structure, this.index)\n }\n\n toObject () {\n return {\n atomIndex1: this.atomIndex1,\n atomIndex2: this.atomIndex2,\n bondOrder: this.bondOrder\n }\n }\n}\n\nexport default BondProxy\n","/**\n * @file Residue Proxy\n * @author Alexander Rose \n * @private\n */\n\nimport { NumberArray } from '../types'\nimport { defaults } from '../utils'\nimport {\n SecStrucHelix, SecStrucSheet, SecStrucTurn,\n ProteinType, RnaType, DnaType, WaterType, IonType, SaccharideType,\n CgProteinBackboneType, CgRnaBackboneType, CgDnaBackboneType,\n AA1\n} from '../structure/structure-constants'\n\nimport Structure from '../structure/structure'\nimport Selection from '../selection/selection'\n\nimport ChainStore from '../store/chain-store'\nimport ResidueStore from '../store/residue-store'\nimport AtomStore from '../store/atom-store'\n\nimport AtomMap from '../store/atom-map'\nimport ResidueMap from '../store/residue-map'\n\nimport AtomProxy from '../proxy/atom-proxy'\nimport ResidueType, { RingData } from '../store/residue-type';\nimport { ResidueBonds } from '../structure/structure-utils';\nimport AtomType from '../store/atom-type';\nimport ChainProxy from './chain-proxy';\nimport Entity from '../structure/entity';\n\n/**\n * Residue proxy\n */\nclass ResidueProxy {\n index: number\n\n chainStore: ChainStore\n residueStore: ResidueStore\n atomStore: AtomStore\n\n residueMap: ResidueMap\n atomMap: AtomMap\n\n /**\n * @param {Structure} structure - the structure\n * @param {Integer} index - the index\n */\n constructor (readonly structure: Structure, index = 0) {\n this.index = index\n this.chainStore = structure.chainStore\n this.residueStore = structure.residueStore\n this.atomStore = structure.atomStore\n this.residueMap = structure.residueMap\n this.atomMap = structure.atomMap\n }\n\n /**\n * Entity\n * @type {Entity}\n */\n get entity (): Entity {\n return this.structure.entityList[ this.entityIndex ]\n }\n get entityIndex () {\n return this.chainStore.entityIndex[ this.chainIndex ]\n }\n /**\n * Chain\n * @type {ChainProxy}\n */\n get chain (): ChainProxy {\n return this.structure.getChainProxy(this.chainIndex)\n }\n\n get chainIndex () {\n return this.residueStore.chainIndex[ this.index ]\n }\n set chainIndex (value) {\n this.residueStore.chainIndex[ this.index ] = value\n }\n\n get atomOffset () {\n return this.residueStore.atomOffset[ this.index ]\n }\n set atomOffset (value) {\n this.residueStore.atomOffset[ this.index ] = value\n }\n\n /**\n * Atom count\n * @type {Integer}\n */\n get atomCount () {\n return this.residueStore.atomCount[ this.index ]\n }\n set atomCount (value) {\n this.residueStore.atomCount[ this.index ] = value\n }\n\n get atomEnd () {\n return this.atomOffset + this.atomCount - 1\n }\n\n //\n\n get modelIndex () {\n return this.chainStore.modelIndex[ this.chainIndex ]\n }\n /**\n * Chain name\n * @type {String}\n */\n get chainname () {\n return this.chainStore.getChainname(this.chainIndex)\n }\n /**\n * Chain id\n * @type {String}\n */\n get chainid () {\n return this.chainStore.getChainid(this.chainIndex)\n }\n\n //\n\n /**\n * Residue number/label\n * @type {Integer}\n */\n get resno () {\n return this.residueStore.resno[ this.index ]\n }\n set resno (value) {\n this.residueStore.resno[ this.index ] = value\n }\n\n /**\n * Secondary structure code\n * @type {String}\n */\n get sstruc () {\n return this.residueStore.getSstruc(this.index)\n }\n set sstruc (value) {\n this.residueStore.setSstruc(this.index, value)\n }\n\n /**\n * Insertion code\n * @type {String}\n */\n get inscode () {\n return this.residueStore.getInscode(this.index)\n }\n set inscode (value) {\n this.residueStore.setInscode(this.index, value)\n }\n\n //\n\n get residueType (): ResidueType {\n return this.residueMap.get(this.residueStore.residueTypeId[ this.index ])\n }\n\n /**\n * Residue name\n * @type {String}\n */\n get resname () {\n return this.residueType.resname\n }\n /**\n * Hetero flag\n * @type {Boolean}\n */\n get hetero () {\n return this.residueType.hetero\n }\n get moleculeType () {\n return this.residueType.moleculeType\n }\n get backboneType () {\n return this.residueType.backboneType\n }\n get backboneStartType () {\n return this.residueType.backboneStartType\n }\n get backboneEndType () {\n return this.residueType.backboneEndType\n }\n get traceAtomIndex () {\n return this.residueType.traceAtomIndex + this.atomOffset\n }\n get direction1AtomIndex () {\n return this.residueType.direction1AtomIndex + this.atomOffset\n }\n get direction2AtomIndex () {\n return this.residueType.direction2AtomIndex + this.atomOffset\n }\n get backboneStartAtomIndex () {\n return this.residueType.backboneStartAtomIndex + this.atomOffset\n }\n get backboneEndAtomIndex () {\n return this.residueType.backboneEndAtomIndex + this.atomOffset\n }\n get rungEndAtomIndex () {\n return this.residueType.rungEndAtomIndex + this.atomOffset\n }\n\n //\n\n get x () {\n let x = 0\n for (let i = this.atomOffset; i <= this.atomEnd; ++i) {\n x += this.atomStore.x[ i ]\n }\n return x / this.atomCount\n }\n\n get y () {\n let y = 0\n for (let i = this.atomOffset; i <= this.atomEnd; ++i) {\n y += this.atomStore.y[ i ]\n }\n return y / this.atomCount\n }\n\n get z () {\n let z = 0\n for (let i = this.atomOffset; i <= this.atomEnd; ++i) {\n z += this.atomStore.z[ i ]\n }\n return z / this.atomCount\n }\n\n //\n\n /**\n * Atom iterator\n * @param {function(atom: AtomProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachAtom (callback: (ap: AtomProxy) => void, selection?: Selection) {\n const count = this.atomCount\n const offset = this.atomOffset\n const ap = this.structure._ap\n const end = offset + count\n\n if (selection && selection.atomOnlyTest) {\n const atomOnlyTest = selection.atomOnlyTest\n for (let i = offset; i < end; ++i) {\n ap.index = i\n if (atomOnlyTest(ap)) callback(ap)\n }\n } else {\n for (let i = offset; i < end; ++i) {\n ap.index = i\n callback(ap)\n }\n }\n }\n\n //\n\n /**\n * Write residue center position to array\n * @param {Array|TypedArray} [array] - target array\n * @param {Integer} [offset] - the offset\n * @return {Array|TypedArray} target array\n */\n positionToArray (array: NumberArray = [], offset = 0) {\n array[ offset + 0 ] = this.x\n array[ offset + 1 ] = this.y\n array[ offset + 2 ] = this.z\n\n return array\n }\n\n //\n\n /**\n * If residue is from a protein\n * @return {Boolean} flag\n */\n isProtein () {\n return this.residueType.moleculeType === ProteinType\n }\n\n /**\n * If residue is nucleic\n * @return {Boolean} flag\n */\n isNucleic () {\n const moleculeType = this.residueType.moleculeType\n return moleculeType === RnaType || moleculeType === DnaType\n }\n\n /**\n * If residue is rna\n * @return {Boolean} flag\n */\n isRna () {\n return this.residueType.moleculeType === RnaType\n }\n\n /**\n * If residue is dna\n * @return {Boolean} flag\n */\n isDna () {\n return this.residueType.moleculeType === DnaType\n }\n\n /**\n * If residue is coarse-grain\n * @return {Boolean} flag\n */\n isCg () {\n const backboneType = this.residueType.backboneType\n return (\n backboneType === CgProteinBackboneType ||\n backboneType === CgRnaBackboneType ||\n backboneType === CgDnaBackboneType\n )\n }\n\n /**\n * If residue is from a polymer\n * @return {Boolean} flag\n */\n isPolymer () {\n if (this.structure.entityList.length > 0) {\n return this.entity.isPolymer()\n } else {\n const moleculeType = this.residueType.moleculeType\n return (\n moleculeType === ProteinType ||\n moleculeType === RnaType ||\n moleculeType === DnaType\n )\n }\n }\n\n /**\n * If residue is hetero\n * @return {Boolean} flag\n */\n isHetero () {\n return this.residueType.hetero === 1\n }\n\n /**\n * If residue is a water molecule\n * @return {Boolean} flag\n */\n isWater () {\n return this.residueType.moleculeType === WaterType\n }\n\n /**\n * If residue is an ion\n * @return {Boolean} flag\n */\n isIon () {\n return this.residueType.moleculeType === IonType\n }\n\n /**\n * If residue is a saccharide\n * @return {Boolean} flag\n */\n isSaccharide () {\n return this.residueType.moleculeType === SaccharideType\n }\n\n isStandardAminoacid () {\n return this.residueType.isStandardAminoacid()\n }\n\n isStandardBase () {\n return this.residueType.isStandardBase()\n }\n\n /**\n * If residue is part of a helix\n * @return {Boolean} flag\n */\n isHelix () {\n return SecStrucHelix.includes(this.sstruc)\n }\n\n /**\n * If residue is part of a sheet\n * @return {Boolean} flag\n */\n isSheet () {\n return SecStrucSheet.includes(this.sstruc)\n }\n\n /**\n * If residue is part of a turn\n * @return {Boolean} flag\n */\n isTurn () {\n return SecStrucTurn.includes(this.sstruc) && this.isProtein()\n }\n\n getAtomType (index: number): AtomType {\n return this.atomMap.get(this.atomStore.atomTypeId[ index ])\n }\n\n getResname1 () {\n // FIXME nucleic support\n return AA1[ this.resname.toUpperCase() ] || 'X'\n }\n\n getBackboneType (position: number) {\n switch (position) {\n case -1:\n return this.residueType.backboneStartType\n case 1:\n return this.residueType.backboneEndType\n default:\n return this.residueType.backboneType\n }\n }\n\n getAtomIndexByName (atomname: string) {\n let index = this.residueType.getAtomIndexByName(atomname)\n if (index !== undefined) {\n index += this.atomOffset\n }\n return index\n }\n\n hasAtomWithName (atomname: string) {\n return this.residueType.hasAtomWithName(atomname)\n }\n\n getAtomnameList () {\n console.warn('getAtomnameList - might be expensive')\n\n const n = this.atomCount\n const offset = this.atomOffset\n const list = new Array(n)\n for (let i = 0; i < n; ++i) {\n list[ i ] = this.getAtomType(offset + i).atomname\n }\n return list\n }\n\n /**\n * If residue is connected to another\n * @param {ResidueProxy} rNext - the other residue\n * @return {Boolean} - flag\n */\n connectedTo (rNext: ResidueProxy) {\n const bbAtomEnd = this.structure.getAtomProxy(this.backboneEndAtomIndex)\n const bbAtomStart = this.structure.getAtomProxy(rNext.backboneStartAtomIndex)\n if (bbAtomEnd && bbAtomStart) {\n return bbAtomEnd.connectedTo(bbAtomStart)\n } else {\n return false\n }\n }\n\n getNextConnectedResidue () {\n const rOffset = this.chainStore.residueOffset[ this.chainIndex ]\n const rCount = this.chainStore.residueCount[ this.chainIndex ]\n const nextIndex = this.index + 1\n if (nextIndex < rOffset + rCount) {\n const rpNext = this.structure.getResidueProxy(nextIndex)\n if (this.connectedTo(rpNext)) {\n return rpNext\n }\n } else if (nextIndex === rOffset + rCount) { // cyclic\n const rpFirst = this.structure.getResidueProxy(rOffset)\n if (this.connectedTo(rpFirst)) {\n return rpFirst\n }\n }\n return undefined\n }\n\n getPreviousConnectedResidue (residueProxy?: ResidueProxy) {\n const rOffset = this.chainStore.residueOffset[ this.chainIndex ]\n const prevIndex = this.index - 1\n if (prevIndex >= rOffset) {\n const rpPrev = defaults(residueProxy, this.structure.getResidueProxy())\n rpPrev.index = prevIndex\n if (rpPrev.connectedTo(this)) {\n return rpPrev\n }\n } else if (prevIndex === rOffset - 1) { // cyclic\n const rCount = this.chainStore.residueCount[ this.chainIndex ]\n const rpLast = defaults(residueProxy, this.structure.getResidueProxy())\n rpLast.index = rOffset + rCount - 1\n if (rpLast.connectedTo(this)) {\n return rpLast\n }\n }\n return undefined\n }\n\n getBonds (): ResidueBonds {\n return this.residueType.getBonds(this)\n }\n\n getRings (): RingData|undefined {\n return this.residueType.getRings()\n }\n\n getAromaticRings () {\n return this.residueType.getAromaticRings(this)\n }\n\n qualifiedName (noResname = false) {\n let name = ''\n if (this.resname && !noResname) name += '[' + this.resname + ']'\n if (this.resno !== undefined) name += this.resno\n if (this.inscode) name += '^' + this.inscode\n if (this.chain) name += ':' + this.chainname\n name += '/' + this.modelIndex\n return name\n }\n\n /**\n * Clone object\n * @return {ResidueProxy} cloned residue\n */\n clone () {\n return new ResidueProxy(this.structure, this.index)\n }\n\n toObject () {\n return {\n index: this.index,\n chainIndex: this.chainIndex,\n atomOffset: this.atomOffset,\n atomCount: this.atomCount,\n\n resno: this.resno,\n resname: this.resname,\n sstruc: this.sstruc\n }\n }\n}\n\nexport default ResidueProxy\n","/**\n * @file Polymer\n * @author Alexander Rose \n * @private\n */\n\n// import { Log } from '../globals'\n\nimport Structure from '../structure/structure'\nimport Selection from '../selection/selection'\n\nimport ChainStore from '../store/chain-store'\nimport ResidueStore from '../store/residue-store'\nimport AtomStore from '../store/atom-store'\n\nimport ResidueProxy from '../proxy/residue-proxy'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Polymer\n */\nclass Polymer {\n chainStore: ChainStore\n residueStore: ResidueStore\n atomStore: AtomStore\n\n residueCount: number\n\n isPrevConnected: boolean\n isNextConnected: boolean\n isNextNextConnected: boolean\n isCyclic: boolean\n\n private __residueProxy: ResidueProxy\n\n /**\n * @param {Structure} structure - the structure\n * @param {Integer} residueIndexStart - the index of the first residue\n * @param {Integer} residueIndexEnd - the index of the last residue\n */\n constructor (readonly structure: Structure, readonly residueIndexStart: number, readonly residueIndexEnd: number) {\n this.chainStore = structure.chainStore\n this.residueStore = structure.residueStore\n this.atomStore = structure.atomStore\n\n /**\n * @type {Integer}\n */\n this.residueCount = residueIndexEnd - residueIndexStart + 1\n\n const rpStart = this.structure.getResidueProxy(this.residueIndexStart)\n const rpEnd = this.structure.getResidueProxy(this.residueIndexEnd)\n this.isPrevConnected = rpStart.getPreviousConnectedResidue() !== undefined\n const rpNext = rpEnd.getNextConnectedResidue()\n this.isNextConnected = rpNext !== undefined\n this.isNextNextConnected = rpNext !== undefined && rpNext.getNextConnectedResidue() !== undefined\n this.isCyclic = rpEnd.connectedTo(rpStart)\n\n this.__residueProxy = this.structure.getResidueProxy()\n\n // console.log( this.qualifiedName(), this );\n }\n\n get chainIndex () {\n return this.residueStore.chainIndex[ this.residueIndexStart ]\n }\n get modelIndex () {\n return this.chainStore.modelIndex[ this.chainIndex ]\n }\n\n /**\n * @type {String}\n */\n get chainname () {\n return this.chainStore.getChainname(this.chainIndex)\n }\n\n //\n\n /**\n * If first residue is from aprotein\n * @return {Boolean} flag\n */\n isProtein () {\n this.__residueProxy.index = this.residueIndexStart\n return this.__residueProxy.isProtein()\n }\n\n /**\n * If atom is part of a coarse-grain group\n * @return {Boolean} flag\n */\n isCg () {\n this.__residueProxy.index = this.residueIndexStart\n return this.__residueProxy.isCg()\n }\n\n /**\n * If atom is part of a nucleic molecule\n * @return {Boolean} flag\n */\n isNucleic () {\n this.__residueProxy.index = this.residueIndexStart\n return this.__residueProxy.isNucleic()\n }\n\n getMoleculeType () {\n this.__residueProxy.index = this.residueIndexStart\n return this.__residueProxy.moleculeType\n }\n\n getBackboneType (position: number) {\n this.__residueProxy.index = this.residueIndexStart\n return this.__residueProxy.getBackboneType(position)\n }\n\n getAtomIndexByType (index: number, type: string) {\n // TODO pre-calculate, add to residueStore???\n\n if (this.isCyclic) {\n if (index === -1) {\n index = this.residueCount - 1\n } else if (index === this.residueCount) {\n index = 0\n }\n } else {\n if (index === -1 && !this.isPrevConnected) index += 1\n if (index === this.residueCount && !this.isNextNextConnected) index -= 1\n // if( index === this.residueCount - 1 && !this.isNextConnected ) index -= 1;\n }\n\n const rp = this.__residueProxy\n rp.index = this.residueIndexStart + index\n let aIndex\n\n switch (type) {\n case 'trace':\n aIndex = rp.traceAtomIndex\n break\n case 'direction1':\n aIndex = rp.direction1AtomIndex\n break\n case 'direction2':\n aIndex = rp.direction2AtomIndex\n break\n default:\n aIndex = rp.getAtomIndexByName(type)\n }\n\n // if (!ap){\n // console.log(this, type, rp.residueType)\n // // console.log(rp.qualifiedName(), rp.index, index, this.residueCount - 1)\n // // rp.index = this.residueIndexStart;\n // // console.log(rp.qualifiedName(), this.residueIndexStart)\n // // rp.index = this.residueIndexEnd;\n // // console.log(rp.qualifiedName(), this.residueIndexEnd)\n // }\n\n return aIndex\n }\n\n /**\n * Atom iterator\n * @param {function(atom: AtomProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachAtom (callback: (ap: AtomProxy) => void, selection?: Selection) {\n this.eachResidue(function (rp) {\n rp.eachAtom(callback, selection)\n })\n }\n\n eachAtomN (n: number, callback: (...apArray: AtomProxy[]) => void, type: string) {\n const m = this.residueCount\n const array: AtomProxy[] = new Array(n)\n\n for (let i = 0; i < n; ++i) {\n array[ i ] = this.structure.getAtomProxy(this.getAtomIndexByType(i, type))\n }\n callback.apply(this, array)\n\n for (var j = n; j < m; ++j) {\n for (let i = 1; i < n; ++i) {\n array[ i - 1 ].index = array[ i ].index\n }\n array[ n - 1 ].index = this.getAtomIndexByType(j, type)! // TODO\n callback.apply(this, array)\n }\n }\n\n /**\n * Residue iterator\n * @param {function(residue: ResidueProxy)} callback - the callback\n * @return {undefined}\n */\n eachResidue (callback: (rp: ResidueProxy) => void) {\n const rp = this.structure.getResidueProxy()\n const n = this.residueCount\n const rStartIndex = this.residueIndexStart\n\n for (let i = 0; i < n; ++i) {\n rp.index = rStartIndex + i\n callback(rp)\n }\n }\n\n qualifiedName () {\n const rpStart = this.structure.getResidueProxy(this.residueIndexStart)\n const rpEnd = this.structure.getResidueProxy(this.residueIndexEnd)\n return rpStart.qualifiedName() + ' - ' + rpEnd.qualifiedName()\n }\n}\n\nexport default Polymer\n","/**\n * @file Chain Proxy\n * @author Alexander Rose \n * @private\n */\n\nimport { UnknownBackboneType } from '../structure/structure-constants'\n\nimport Structure from '../structure/structure'\nimport Selection from '../selection/selection'\n\nimport ChainStore from '../store/chain-store'\nimport ResidueStore from '../store/residue-store'\n\nimport Polymer from '../proxy/polymer'\nimport ResidueProxy from '../proxy/residue-proxy'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ModelProxy from './model-proxy';\nimport Entity from '../structure/entity';\n\n/**\n * Chain proxy\n */\nclass ChainProxy {\n index: number\n\n chainStore: ChainStore\n residueStore: ResidueStore\n\n /**\n * @param {Structure} structure - the structure\n * @param {Integer} index - the index\n */\n constructor (readonly structure: Structure, index = 0) {\n this.index = index\n this.chainStore = structure.chainStore\n this.residueStore = structure.residueStore\n }\n\n /**\n * Entity\n * @type {Entity}\n */\n get entity (): Entity {\n return this.structure.entityList[ this.entityIndex ]\n }\n /**\n * Model\n * @type {ModelProxy}\n */\n get model (): ModelProxy {\n return this.structure.getModelProxy(this.modelIndex)\n }\n\n get entityIndex () {\n return this.chainStore.entityIndex[ this.index ]\n }\n set entityIndex (value) {\n this.chainStore.entityIndex[ this.index ] = value\n }\n\n get modelIndex () {\n return this.chainStore.modelIndex[ this.index ]\n }\n set modelIndex (value) {\n this.chainStore.modelIndex[ this.index ] = value\n }\n\n get residueOffset () {\n return this.chainStore.residueOffset[ this.index ]\n }\n set residueOffset (value) {\n this.chainStore.residueOffset[ this.index ] = value\n }\n\n /**\n * Residue count\n * @type {Integer}\n */\n get residueCount () {\n return this.chainStore.residueCount[ this.index ]\n }\n set residueCount (value) {\n this.chainStore.residueCount[ this.index ] = value\n }\n\n get residueEnd () {\n return this.residueOffset + this.residueCount - 1\n }\n\n get atomOffset () {\n return this.residueStore.atomOffset[ this.residueOffset ]\n }\n get atomEnd () {\n return (\n this.residueStore.atomOffset[ this.residueEnd ] +\n this.residueStore.atomCount[ this.residueEnd ] - 1\n )\n }\n /**\n * Atom count\n * @type {Integer}\n */\n get atomCount () {\n if (this.residueCount === 0) {\n return 0\n } else {\n return this.atomEnd - this.atomOffset + 1\n }\n }\n\n //\n\n /**\n * Chain name\n * @type {String}\n */\n get chainname () {\n return this.chainStore.getChainname(this.index)\n }\n set chainname (value) {\n this.chainStore.setChainname(this.index, value)\n }\n\n /**\n * Chain id\n * @type {String}\n */\n get chainid () {\n return this.chainStore.getChainid(this.index)\n }\n set chainid (value) {\n this.chainStore.setChainid(this.index, value)\n }\n\n //\n\n /**\n * Atom iterator\n * @param {function(atom: AtomProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachAtom (callback: (ap: AtomProxy) => void, selection?: Selection) {\n this.eachResidue(function (rp) {\n rp.eachAtom(callback, selection)\n }, selection)\n }\n\n /**\n * Residue iterator\n * @param {function(residue: ResidueProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachResidue (callback: (rp: ResidueProxy) => void, selection?: Selection) {\n const count = this.residueCount\n const offset = this.residueOffset\n const rp = this.structure._rp\n const end = offset + count\n\n if (selection && selection.test) {\n const residueOnlyTest = selection.residueOnlyTest\n if (residueOnlyTest) {\n for (let i = offset; i < end; ++i) {\n rp.index = i\n if (residueOnlyTest(rp)) {\n callback(rp)\n }\n }\n } else {\n for (let i = offset; i < end; ++i) {\n rp.index = i\n callback(rp)\n }\n }\n } else {\n for (let i = offset; i < end; ++i) {\n rp.index = i\n callback(rp)\n }\n }\n }\n\n /**\n * Multi-residue iterator\n * @param {Integer} n - window size\n * @param {function(residueList: ResidueProxy[])} callback - the callback\n * @return {undefined}\n */\n eachResidueN (n: number, callback: (...rpArray: ResidueProxy[]) => void) {\n const count = this.residueCount\n const offset = this.residueOffset\n const end = offset + count\n if (count < n) return\n const array: ResidueProxy[] = new Array(n)\n\n for (let i = 0; i < n; ++i) {\n array[ i ] = this.structure.getResidueProxy(offset + i)\n }\n callback.apply(this, array)\n\n for (let j = offset + n; j < end; ++j) {\n for (let i = 0; i < n; ++i) {\n array[ i ].index += 1\n }\n callback.apply(this, array)\n }\n }\n\n /**\n * Polymer iterator\n * @param {function(polymer: Polymer)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachPolymer (callback: (p: Polymer) => void, selection?: Selection) {\n let rStartIndex = 0\n let rNextIndex = 0\n const test = selection ? selection.residueOnlyTest : undefined\n const structure = this.model.structure\n\n const count = this.residueCount\n const offset = this.residueOffset\n const end = offset + count\n\n const rp1 = this.structure.getResidueProxy()\n const rp2 = this.structure.getResidueProxy(offset)\n\n const ap1 = this.structure.getAtomProxy()\n const ap2 = this.structure.getAtomProxy()\n\n let first = true\n\n for (let i = offset + 1; i < end; ++i) {\n rp1.index = rp2.index\n rp2.index = i\n\n const bbType1 = first ? rp1.backboneEndType : rp1.backboneType\n const bbType2 = rp2.backboneType\n\n if (first) {\n rStartIndex = rp1.index\n first = false\n }\n rNextIndex = rp2.index\n\n if (bbType1 !== UnknownBackboneType && bbType1 === bbType2) {\n ap1.index = rp1.backboneEndAtomIndex\n ap2.index = rp2.backboneStartAtomIndex\n } else {\n if (bbType1 !== UnknownBackboneType) {\n if (rp1.index - rStartIndex > 1) {\n // console.log(\"FOO1\",rStartIndex, rp1.index)\n callback(new Polymer(structure, rStartIndex, rp1.index))\n }\n }\n rStartIndex = rNextIndex\n\n continue\n }\n\n if (!ap1 || !ap2 || !ap1.connectedTo(ap2) ||\n (test && (!test(rp1) || !test(rp2)))\n ) {\n if (rp1.index - rStartIndex > 1) {\n // console.log(\"FOO2\",rStartIndex, rp1.index)\n callback(new Polymer(structure, rStartIndex, rp1.index))\n }\n rStartIndex = rNextIndex\n }\n }\n\n if (rNextIndex - rStartIndex > 1) {\n if (this.structure.getResidueProxy(rStartIndex).backboneEndType) {\n // console.log(\"FOO3\",rStartIndex, rNextIndex)\n callback(new Polymer(structure, rStartIndex, rNextIndex))\n }\n }\n }\n\n //\n\n qualifiedName () {\n var name = ':' + this.chainname + '/' + this.modelIndex\n return name\n }\n\n /**\n * Clone object\n * @return {ChainProxy} cloned chain\n */\n clone () {\n return new ChainProxy(this.structure, this.index)\n }\n\n toObject () {\n return {\n index: this.index,\n residueOffset: this.residueOffset,\n residueCount: this.residueCount,\n\n chainname: this.chainname\n }\n }\n}\n\nexport default ChainProxy\n","/**\n * @file Model Proxy\n * @author Alexander Rose \n * @private\n */\n\nimport Structure from '../structure/structure'\nimport Selection from '../selection/selection'\n\nimport ModelStore from '../store/model-store'\nimport ChainStore from '../store/chain-store'\nimport ResidueStore from '../store/residue-store'\n\nimport ChainProxy from '../proxy/chain-proxy'\nimport Polymer from '../proxy/polymer'\nimport ResidueProxy from '../proxy/residue-proxy'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Model proxy\n */\nclass ModelProxy {\n index: number\n\n modelStore: ModelStore\n chainStore: ChainStore\n residueStore: ResidueStore\n\n /**\n * @param {Structure} structure - the structure\n * @param {Integer} index - the index\n */\n constructor (readonly structure: Structure, index = 0) {\n this.index = index\n this.modelStore = structure.modelStore\n this.chainStore = structure.chainStore\n this.residueStore = structure.residueStore\n }\n\n get chainOffset () {\n return this.modelStore.chainOffset[ this.index ]\n }\n set chainOffset (value) {\n this.modelStore.chainOffset[ this.index ] = value\n }\n\n get chainCount () {\n return this.modelStore.chainCount[ this.index ]\n }\n set chainCount (value) {\n this.modelStore.chainCount[ this.index ] = value\n }\n\n get residueOffset () {\n return this.chainStore.residueOffset[ this.chainOffset ]\n }\n get atomOffset () {\n return this.residueStore.atomOffset[ this.residueOffset ]\n }\n\n get chainEnd () {\n return this.chainOffset + this.chainCount - 1\n }\n get residueEnd () {\n return (\n this.chainStore.residueOffset[ this.chainEnd ] +\n this.chainStore.residueCount[ this.chainEnd ] - 1\n )\n }\n get atomEnd () {\n return (\n this.residueStore.atomOffset[ this.residueEnd ] +\n this.residueStore.atomCount[ this.residueEnd ] - 1\n )\n }\n\n /**\n * Residue count\n * @type {Integer}\n */\n get residueCount () {\n if (this.chainCount === 0) {\n return 0\n } else {\n return this.residueEnd - this.residueOffset + 1\n }\n }\n\n /**\n * Atom count\n * @type {Integer}\n */\n get atomCount () {\n if (this.residueCount === 0) {\n return 0\n } else {\n return this.atomEnd - this.atomOffset + 1\n }\n }\n\n //\n\n /**\n * Atom iterator\n * @param {function(atom: AtomProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachAtom (callback: (ap: AtomProxy) => void, selection?: Selection) {\n this.eachChain(function (cp) {\n cp.eachAtom(callback, selection)\n }, selection)\n }\n\n /**\n * Residue iterator\n * @param {function(residue: ResidueProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachResidue (callback: (rp: ResidueProxy) => void, selection?: Selection) {\n this.eachChain(function (cp) {\n cp.eachResidue(callback, selection)\n }, selection)\n }\n\n /**\n * Polymer iterator\n * @param {function(polymer: Polymer)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachPolymer (callback: (p: Polymer) => void, selection?: Selection) {\n if (selection && selection.chainOnlyTest) {\n const chainOnlyTest = selection.chainOnlyTest\n\n this.eachChain(function (cp) {\n if (chainOnlyTest(cp)) {\n cp.eachPolymer(callback, selection)\n }\n })\n } else {\n this.eachChain(function (cp) {\n cp.eachPolymer(callback, selection)\n })\n }\n }\n\n /**\n * Chain iterator\n * @param {function(chain: ChainProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachChain (callback: (cp: ChainProxy) => void, selection?: Selection) {\n const count = this.chainCount\n const offset = this.chainOffset\n const cp = this.structure._cp\n const end = offset + count\n\n if (selection && selection.test) {\n const chainOnlyTest = selection.chainOnlyTest\n if (chainOnlyTest) {\n for (let i = offset; i < end; ++i) {\n cp.index = i\n if (chainOnlyTest(cp)) {\n callback(cp)\n }\n }\n } else {\n for (let i = offset; i < end; ++i) {\n cp.index = i\n callback(cp)\n }\n }\n } else {\n for (let i = offset; i < end; ++i) {\n cp.index = i\n callback(cp)\n }\n }\n }\n\n //\n\n qualifiedName () {\n const name = '/' + this.index\n return name\n }\n\n /**\n * Clone object\n * @return {ModelProxy} cloned model\n */\n clone () {\n return new ModelProxy(this.structure, this.index)\n }\n\n toObject () {\n return {\n index: this.index,\n chainOffset: this.chainOffset,\n chainCount: this.chainCount\n }\n }\n}\n\nexport default ModelProxy\n","/**\n * @file Structure\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Box3 } from 'three'\nimport { Signal } from 'signals'\n\nimport { Debug, Log, ColormakerRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport { AtomPicker, BondPicker } from '../utils/picker'\nimport { copyWithin, arrayMin, arrayMax } from '../math/array-utils'\nimport BitArray from '../utils/bitarray'\nimport RadiusFactory, { RadiusParams } from '../utils/radius-factory'\nimport { Matrix } from '../math/matrix-utils'\nimport PrincipalAxes from '../math/principal-axes'\nimport SpatialHash from '../geometry/spatial-hash'\nimport FilteredVolume from '../surface/filtered-volume'\nimport StructureView from './structure-view'\nimport { AtomDataParams, AtomData, BondDataParams, BondData } from './structure-data'\nimport { Data, createData } from './data'\n\nimport Entity from './entity'\nimport Unitcell from '../symmetry/unitcell'\nimport Validation from './validation'\nimport Selection from '../selection/selection'\nimport Assembly from '../symmetry/assembly'\nimport Volume from '../surface/volume'\nimport Polymer from '../proxy/polymer'\n\nimport BondHash from '../store/bond-hash'\nimport BondStore from '../store/bond-store'\nimport AtomStore from '../store/atom-store'\nimport ResidueStore from '../store/residue-store'\nimport ChainStore from '../store/chain-store'\nimport ModelStore from '../store/model-store'\n\nimport AtomMap from '../store/atom-map'\nimport ResidueMap from '../store/residue-map'\n\nimport BondProxy from '../proxy/bond-proxy'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ResidueProxy from '../proxy/residue-proxy'\nimport ChainProxy from '../proxy/chain-proxy'\nimport ModelProxy from '../proxy/model-proxy'\n\ninterface Structure {\n signals: StructureSignals\n\n name: string\n path: string\n title: string\n id: string\n\n data: Data\n\n atomCount: number\n bondCount: number\n\n header: StructureHeader\n extraData: StructureExtraData\n\n atomSetCache: { [k: string]: BitArray }\n atomSetDict: { [k: string]: BitArray }\n biomolDict: { [k: string]: Assembly }\n\n entityList: Entity[]\n unitcell?: Unitcell\n\n frames: Float32Array[]\n boxes: Float32Array[]\n\n validation?: Validation\n\n bondStore: BondStore\n backboneBondStore: BondStore\n rungBondStore: BondStore\n atomStore: AtomStore\n residueStore: ResidueStore\n chainStore: ChainStore\n modelStore: ModelStore\n\n atomMap: AtomMap\n residueMap: ResidueMap\n\n bondHash?: BondHash\n spatialHash?: SpatialHash\n\n atomSet?: BitArray\n bondSet?: BitArray\n\n center: Vector3\n boundingBox: Box3\n\n trajectory?: {\n name: string\n frame: number\n }\n\n getView(selection: Selection): StructureView\n\n _hasCoords?: boolean\n\n _bp: BondProxy\n _ap: AtomProxy\n _rp: ResidueProxy\n _cp: ChainProxy\n}\n\nexport type StructureHeader = {\n releaseDate?: string\n depositionDate?: string\n resolution?: number\n rFree?: number\n rWork?: number\n experimentalMethods?: string[]\n}\n\nexport type StructureExtraData = {\n cif?: object\n sdf?: object[]\n}\n\nexport type StructureSignals = {\n refreshed: Signal\n}\n\n/**\n * Structure\n */\nclass Structure implements Structure{\n signals: StructureSignals = {\n refreshed: new Signal()\n }\n\n /**\n * @param {String} name - structure name\n * @param {String} path - source path\n */\n constructor (name = '', path = '') {\n this.init(name, path)\n }\n\n init (name: string, path: string) {\n this.name = name\n this.path = path\n this.title = ''\n this.id = ''\n\n this.data = createData(this)\n\n this.header = {}\n this.extraData = {}\n\n this.atomSetCache = {}\n this.atomSetDict = {}\n this.biomolDict = {}\n\n this.entityList = []\n this.unitcell = undefined\n\n this.frames = []\n this.boxes = []\n\n this.validation = undefined\n\n this.bondStore = new BondStore(0)\n this.backboneBondStore = new BondStore(0)\n this.rungBondStore = new BondStore(0)\n this.atomStore = new AtomStore(0)\n this.residueStore = new ResidueStore(0)\n this.chainStore = new ChainStore(0)\n this.modelStore = new ModelStore(0)\n\n this.atomMap = new AtomMap(this)\n this.residueMap = new ResidueMap(this)\n\n this.bondHash = undefined\n this.spatialHash = undefined\n\n this.atomSet = undefined\n this.bondSet = undefined\n\n this.center = new Vector3()\n this.boundingBox = new Box3()\n\n this._bp = this.getBondProxy()\n this._ap = this.getAtomProxy()\n this._rp = this.getResidueProxy()\n this._cp = this.getChainProxy()\n }\n\n get type () { return 'Structure' }\n\n finalizeAtoms () {\n this.atomSet = this.getAtomSet()\n this.atomCount = this.atomStore.count\n this.boundingBox = this.getBoundingBox(undefined, this.boundingBox)\n this.center = this.boundingBox.getCenter(new Vector3())\n this.spatialHash = new SpatialHash(this.atomStore, this.boundingBox)\n }\n\n finalizeBonds () {\n this.bondSet = this.getBondSet()\n this.bondCount = this.bondStore.count\n this.bondHash = new BondHash(this.bondStore, this.atomStore.count)\n\n this.atomSetCache = {}\n if (!this.atomSetDict.rung) {\n this.atomSetDict.rung = this.getAtomSet(false)\n }\n\n for (let name in this.atomSetDict) {\n this.atomSetCache[ '__' + name ] = this.atomSetDict[ name ].clone()\n }\n }\n\n //\n\n getBondProxy (index?: number) {\n return new BondProxy(this, index)\n }\n\n getAtomProxy (index?: number) {\n return new AtomProxy(this, index)\n }\n\n getResidueProxy (index?: number) {\n return new ResidueProxy(this, index)\n }\n\n getChainProxy (index?: number) {\n return new ChainProxy(this, index)\n }\n\n getModelProxy (index?: number) {\n return new ModelProxy(this, index)\n }\n\n //\n\n getBondSet (/* selection */) {\n // TODO implement selection parameter\n\n const n = this.bondStore.count\n const bondSet = new BitArray(n)\n const atomSet = this.atomSet\n\n if (atomSet) {\n if (atomSet.isAllSet()) {\n bondSet.setAll()\n } else if (atomSet.isAllClear()) {\n bondSet.clearAll()\n } else {\n const bp = this.getBondProxy()\n\n for (let i = 0; i < n; ++i) {\n bp.index = i\n if (atomSet.isSet(bp.atomIndex1, bp.atomIndex2)) {\n bondSet.set(bp.index)\n }\n }\n }\n } else {\n bondSet.setAll()\n }\n\n return bondSet\n }\n\n getBackboneBondSet (/* selection */) {\n // TODO implement selection parameter\n\n const n = this.backboneBondStore.count\n const backboneBondSet = new BitArray(n)\n const backboneAtomSet = this.atomSetCache.__backbone\n\n if (backboneAtomSet) {\n const bp = this.getBondProxy()\n bp.bondStore = this.backboneBondStore\n\n for (let i = 0; i < n; ++i) {\n bp.index = i\n if (backboneAtomSet.isSet(bp.atomIndex1, bp.atomIndex2)) {\n backboneBondSet.set(bp.index)\n }\n }\n } else {\n backboneBondSet.setAll()\n }\n\n return backboneBondSet\n }\n\n getRungBondSet (/* selection */) {\n // TODO implement selection parameter\n\n const n = this.rungBondStore.count\n const rungBondSet = new BitArray(n)\n const rungAtomSet = this.atomSetCache.__rung\n\n if (rungAtomSet) {\n const bp = this.getBondProxy()\n bp.bondStore = this.rungBondStore\n\n for (let i = 0; i < n; ++i) {\n bp.index = i\n if (rungAtomSet.isSet(bp.atomIndex1, bp.atomIndex2)) {\n rungBondSet.set(bp.index)\n }\n }\n } else {\n rungBondSet.setAll()\n }\n\n return rungBondSet\n }\n\n /**\n * Get a set of atoms\n * @param {Boolean|Selection|BitArray} selection - object defining how to\n * initialize the atom set.\n * Boolean: init with value;\n * Selection: init with selection;\n * BitArray: return bit array\n * @return {BitArray} set of atoms\n */\n getAtomSet (selection?: boolean|Selection|BitArray) {\n const n = this.atomStore.count\n\n if (selection === undefined) {\n return new BitArray(n, true)\n } else if (selection instanceof BitArray) {\n return selection\n } else if (selection === true) {\n return new BitArray(n, true)\n } else if (selection && selection.test) {\n const seleString = selection.string\n if (seleString in this.atomSetCache) {\n return this.atomSetCache[ seleString ]\n } else {\n if (seleString === '') {\n return new BitArray(n, true)\n } else {\n const atomSet = new BitArray(n)\n this.eachAtom(function (ap: AtomProxy) {\n atomSet.set(ap.index)\n }, selection)\n this.atomSetCache[ seleString ] = atomSet\n return atomSet\n }\n }\n } else if (selection === false) {\n return new BitArray(n)\n }\n\n return new BitArray(n, true)\n }\n\n /**\n * Get set of atoms around a set of atoms from a selection\n * @param {Selection} selection - the selection object\n * @param {Number} radius - radius to select within\n * @return {BitArray} set of atoms\n */\n getAtomSetWithinSelection (selection: boolean|Selection|BitArray, radius: number) {\n const spatialHash = this.spatialHash\n const atomSet = this.getAtomSet(false)\n const ap = this.getAtomProxy()\n\n if (!spatialHash) return atomSet\n\n this.getAtomSet(selection).forEach(function (idx: number) {\n ap.index = idx\n spatialHash.within(ap.x, ap.y, ap.z, radius).forEach(function (idx2: number) {\n atomSet.set(idx2)\n })\n })\n\n return atomSet\n }\n\n /**\n * Get set of atoms around a point\n * @param {Vector3|AtomProxy} point - the point\n * @param {Number} radius - radius to select within\n * @return {BitArray} set of atoms\n */\n getAtomSetWithinPoint (point: Vector3|AtomProxy, radius: number) {\n const p = point\n const atomSet = this.getAtomSet(false)\n\n if (!this.spatialHash) return atomSet\n\n this.spatialHash.within(p.x, p.y, p.z, radius).forEach(function (idx: number) {\n atomSet.set(idx)\n })\n\n return atomSet\n }\n\n /**\n * Get set of atoms within a volume\n * @param {Volume} volume - the volume\n * @param {Number} radius - radius to select within\n * @param {[type]} minValue - minimum value to be considered as within the volume\n * @param {[type]} maxValue - maximum value to be considered as within the volume\n * @param {[type]} outside - use only values falling outside of the min/max values\n * @return {BitArray} set of atoms\n */\n getAtomSetWithinVolume (volume: Volume, radius: number, minValue: number, maxValue: number, outside: boolean) {\n const fv = new FilteredVolume(volume, minValue, maxValue, outside) as any // TODO\n\n const dp = fv.getDataPosition()\n const n = dp.length\n const r = fv.matrix.getMaxScaleOnAxis()\n const atomSet = this.getAtomSet(false)\n\n if (!this.spatialHash) return atomSet\n\n for (let i = 0; i < n; i += 3) {\n this.spatialHash.within(dp[ i ], dp[ i + 1 ], dp[ i + 2 ], r).forEach(function (idx) {\n atomSet.set(idx)\n })\n }\n\n return atomSet\n }\n\n /**\n * Get set of all atoms within the groups of a selection\n * @param {Selection} selection - the selection object\n * @return {BitArray} set of atoms\n */\n getAtomSetWithinGroup (selection: boolean|Selection|BitArray) {\n const atomResidueIndex = this.atomStore.residueIndex\n const atomSet = this.getAtomSet(false)\n const rp = this.getResidueProxy()\n\n this.getAtomSet(selection).forEach(function (idx) {\n rp.index = atomResidueIndex[ idx ]\n for (let idx2 = rp.atomOffset; idx2 <= rp.atomEnd; ++idx2) {\n atomSet.set(idx2)\n }\n })\n\n return atomSet\n }\n\n //\n\n getSelection (): undefined|Selection {\n return\n }\n\n getStructure (): Structure|StructureView {\n return this\n }\n\n /**\n * Entity iterator\n * @param {function(entity: Entity)} callback - the callback\n * @param {EntityType} type - entity type\n * @return {undefined}\n */\n eachEntity (callback: (entity: Entity) => void, type: number) {\n this.entityList.forEach(function (entity) {\n if (type === undefined || entity.getEntityType() === type) {\n callback(entity)\n }\n })\n }\n\n /**\n * Bond iterator\n * @param {function(bond: BondProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachBond (callback: (entity: BondProxy) => void, selection?: Selection) {\n const bp = this.getBondProxy()\n let bondSet\n\n if (selection && selection.test) {\n bondSet = this.getBondSet(/*selection*/)\n if (this.bondSet) {\n bondSet.intersection(this.bondSet)\n }\n }\n\n if (bondSet) {\n bondSet.forEach(function (index) {\n bp.index = index\n callback(bp)\n })\n } else {\n const n = this.bondStore.count\n for (let i = 0; i < n; ++i) {\n bp.index = i\n callback(bp)\n }\n }\n }\n\n /**\n * Atom iterator\n * @param {function(atom: AtomProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachAtom (callback: (entity: AtomProxy) => void, selection?: Selection) {\n if (selection && selection.test) {\n this.eachModel(function (mp) {\n mp.eachAtom(callback, selection)\n }, selection)\n } else {\n const an = this.atomStore.count\n const ap = this.getAtomProxy()\n for (let i = 0; i < an; ++i) {\n ap.index = i\n callback(ap)\n }\n }\n }\n\n /**\n * Residue iterator\n * @param {function(residue: ResidueProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachResidue (callback: (entity: ResidueProxy) => void, selection?: Selection) {\n if (selection && selection.test) {\n const mn = this.modelStore.count\n const mp = this.getModelProxy()\n const modelOnlyTest = selection.modelOnlyTest\n if (modelOnlyTest) {\n for (let i = 0; i < mn; ++i) {\n mp.index = i\n if (modelOnlyTest(mp)) {\n mp.eachResidue(callback, selection)\n }\n }\n } else {\n for (let i = 0; i < mn; ++i) {\n mp.index = i\n mp.eachResidue(callback, selection)\n }\n }\n } else {\n const rn = this.residueStore.count\n const rp = this.getResidueProxy()\n for (let i = 0; i < rn; ++i) {\n rp.index = i\n callback(rp)\n }\n }\n }\n\n /**\n * Multi-residue iterator\n * @param {Integer} n - window size\n * @param {function(residueList: ResidueProxy[])} callback - the callback\n * @return {undefined}\n */\n eachResidueN (n: number, callback: (...entityArray: ResidueProxy[]) => void) {\n const rn = this.residueStore.count\n if (rn < n) return\n const array: ResidueProxy[] = new Array(n)\n\n for (let i = 0; i < n; ++i) {\n array[ i ] = this.getResidueProxy(i)\n }\n callback.apply(this, array)\n\n for (let j = n; j < rn; ++j) {\n for (let i = 0; i < n; ++i) {\n array[ i ].index += 1\n }\n callback.apply(this, array)\n }\n }\n\n /**\n * Polymer iterator\n * @param {function(polymer: Polymer)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachPolymer (callback: (entity: Polymer) => void, selection?: Selection) {\n if (selection && selection.modelOnlyTest) {\n const modelOnlyTest = selection.modelOnlyTest\n\n this.eachModel(function (mp) {\n if (modelOnlyTest(mp)) {\n mp.eachPolymer(callback, selection)\n }\n })\n } else {\n this.eachModel(function (mp) {\n mp.eachPolymer(callback, selection)\n })\n }\n }\n\n /**\n * Chain iterator\n * @param {function(chain: ChainProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachChain (callback: (entity: ChainProxy) => void, selection?: Selection) {\n if (selection && selection.test) {\n this.eachModel(function (mp) {\n mp.eachChain(callback, selection)\n })\n } else {\n const cn = this.chainStore.count\n const cp = this.getChainProxy()\n for (let i = 0; i < cn; ++i) {\n cp.index = i\n callback(cp)\n }\n }\n }\n\n /**\n * Model iterator\n * @param {function(model: ModelProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachModel (callback: (entity: ModelProxy) => void, selection?: Selection) {\n const n = this.modelStore.count\n const mp = this.getModelProxy()\n\n if (selection && selection.test) {\n const modelOnlyTest = selection.modelOnlyTest\n if (modelOnlyTest) {\n for (let i = 0; i < n; ++i) {\n mp.index = i\n if (modelOnlyTest(mp)) {\n callback(mp)\n }\n }\n } else {\n for (let i = 0; i < n; ++i) {\n mp.index = i\n callback(mp)\n }\n }\n } else {\n for (let i = 0; i < n; ++i) {\n mp.index = i\n callback(mp)\n }\n }\n }\n\n //\n\n getAtomData (params: AtomDataParams) {\n const p = Object.assign({}, params)\n if (p.colorParams) p.colorParams.structure = this.getStructure()\n\n const what = p.what\n const atomSet = defaults(p.atomSet, this.atomSet)\n\n let radiusFactory: any // TODO\n let colormaker: any // TODO\n\n const atomData: AtomData = {}\n const ap = this.getAtomProxy()\n const atomCount = atomSet.getSize()\n\n if (!what || what.position) {\n atomData.position = new Float32Array(atomCount * 3)\n }\n if ((!what || what.color) && p.colorParams) {\n atomData.color = new Float32Array(atomCount * 3)\n colormaker = ColormakerRegistry.getScheme(p.colorParams)\n }\n if (!what || what.picking) {\n atomData.picking = new AtomPicker(new Float32Array(atomCount), this.getStructure())\n }\n if (!what || what.radius) {\n atomData.radius = new Float32Array(atomCount)\n radiusFactory = new RadiusFactory(p.radiusParams as RadiusParams)\n }\n if (!what || what.index) {\n atomData.index = new Uint32Array(atomCount)\n }\n\n const {position, color, picking, radius, index} = atomData\n\n atomSet.forEach((idx: number, i: number) => {\n const i3 = i * 3\n ap.index = idx\n if (position) {\n ap.positionToArray(position, i3)\n }\n if (color) {\n colormaker.atomColorToArray(ap, color, i3)\n }\n if (picking) {\n picking.array![ i ] = idx\n }\n if (radius) {\n radius[ i ] = radiusFactory.atomRadius(ap)\n }\n if (index) {\n index[ i ] = idx\n }\n })\n return atomData\n }\n\n getBondData (params: BondDataParams) {\n const p = Object.assign({}, params)\n if (p.colorParams) p.colorParams.structure = this.getStructure()\n\n const what = p.what\n const bondSet = defaults(p.bondSet, this.bondSet)\n const multipleBond = defaults(p.multipleBond, 'off')\n const isMulti = multipleBond !== 'off'\n const isOffset = multipleBond === 'offset'\n const bondScale = defaults(p.bondScale, 0.4)\n const bondSpacing = defaults(p.bondSpacing, 1.0)\n\n let radiusFactory: any // TODO\n let colormaker: any // TODO\n\n const bondData: BondData = {}\n const bp = this.getBondProxy()\n if (p.bondStore) bp.bondStore = p.bondStore\n const ap1 = this.getAtomProxy()\n const ap2 = this.getAtomProxy()\n\n let bondCount: number\n if (isMulti) {\n const storeBondOrder = bp.bondStore.bondOrder\n bondCount = 0\n bondSet.forEach(function (index: number) {\n bondCount += storeBondOrder[ index ]\n })\n } else {\n bondCount = bondSet.getSize()\n }\n\n if (!what || what.position) {\n bondData.position1 = new Float32Array(bondCount * 3)\n bondData.position2 = new Float32Array(bondCount * 3)\n }\n if ((!what || what.color) && p.colorParams) {\n bondData.color = new Float32Array(bondCount * 3)\n bondData.color2 = new Float32Array(bondCount * 3)\n colormaker = ColormakerRegistry.getScheme(p.colorParams)\n }\n if (!what || what.picking) {\n bondData.picking = new BondPicker(new Float32Array(bondCount), this.getStructure(), p.bondStore)\n }\n if (!what || what.radius || (isMulti && what.position)) {\n radiusFactory = new RadiusFactory(p.radiusParams as RadiusParams)\n }\n if (!what || what.radius) {\n bondData.radius = new Float32Array(bondCount)\n if (p.radius2) {\n bondData.radius2 = new Float32Array(bondCount)\n }\n }\n\n const {position1, position2, color, color2, picking, radius, radius2} = bondData\n\n let i = 0\n let j, i3, k, bondOrder, absOffset\n let multiRadius\n\n const vt = new Vector3()\n const vShortening = new Vector3()\n const vShift = new Vector3()\n\n bondSet.forEach((index: number) => {\n i3 = i * 3\n bp.index = index\n ap1.index = bp.atomIndex1\n ap2.index = bp.atomIndex2\n bondOrder = bp.bondOrder\n if (position1) {\n if (isMulti && bondOrder > 1) {\n const atomRadius = radiusFactory.atomRadius(ap1)\n multiRadius = atomRadius * bondScale / (0.5 * bondOrder)\n\n bp.calculateShiftDir(vShift)\n\n if (isOffset) {\n absOffset = 2 * bondSpacing * atomRadius\n vShift.multiplyScalar(absOffset)\n vShift.negate()\n\n // Shortening is calculated so that neighbouring double\n // bonds on tetrahedral geometry (e.g. sulphonamide)\n // are not quite touching (arccos(1.9 / 2) ~ 109deg)\n // but don't shorten beyond 10% each end or it looks odd\n vShortening.subVectors(ap2 as any, ap1 as any).multiplyScalar( // TODO\n Math.max(0.1, absOffset / 1.88)\n )\n ap1.positionToArray(position1, i3)\n ap2.positionToArray(position2, i3)\n\n if (bondOrder >= 2) {\n vt.addVectors(ap1 as any, vShift).add(vShortening).toArray(position1 as any, i3 + 3) // TODO\n vt.addVectors(ap2 as any, vShift).sub(vShortening).toArray(position2 as any, i3 + 3) // TODO\n\n if (bondOrder >= 3) {\n vt.subVectors(ap1 as any, vShift).add(vShortening).toArray(position1 as any, i3 + 6) // TODO\n vt.subVectors(ap2 as any, vShift).sub(vShortening).toArray(position2 as any, i3 + 6) // TODO\n }\n }\n } else {\n absOffset = (bondSpacing - bondScale) * atomRadius\n vShift.multiplyScalar(absOffset)\n\n if (bondOrder === 2) {\n vt.addVectors(ap1 as any, vShift).toArray(position1 as any, i3) // TODO\n vt.subVectors(ap1 as any, vShift).toArray(position1 as any, i3 + 3) // TODO\n vt.addVectors(ap2 as any, vShift).toArray(position2 as any, i3) // TODO\n vt.subVectors(ap2 as any, vShift).toArray(position2 as any, i3 + 3) // TODO\n } else if (bondOrder === 3) {\n ap1.positionToArray(position1, i3)\n vt.addVectors(ap1 as any, vShift).toArray(position1 as any, i3 + 3) // TODO\n vt.subVectors(ap1 as any, vShift).toArray(position1 as any, i3 + 6) // TODO\n ap2.positionToArray(position2, i3)\n vt.addVectors(ap2 as any, vShift).toArray(position2 as any, i3 + 3) // TODO\n vt.subVectors(ap2 as any, vShift).toArray(position2 as any, i3 + 6) // TODO\n } else {\n // todo, better fallback\n ap1.positionToArray(position1, i3)\n ap2.positionToArray(position2, i3)\n }\n }\n } else {\n ap1.positionToArray(position1, i3)\n ap2.positionToArray(position2, i3)\n }\n }\n if (color && color2) {\n colormaker.bondColorToArray(bp, 1, color, i3)\n colormaker.bondColorToArray(bp, 0, color2, i3)\n if (isMulti && bondOrder > 1) {\n for (j = 1; j < bondOrder; ++j) {\n k = j * 3 + i3\n copyWithin(color, i3, k, 3)\n copyWithin(color2, i3, k, 3)\n }\n }\n }\n if (picking && picking.array) {\n picking.array[ i ] = index\n if (isMulti && bondOrder > 1) {\n for (j = 1; j < bondOrder; ++j) {\n picking.array[ i + j ] = index\n }\n }\n }\n if (radius) {\n radius[ i ] = radiusFactory.atomRadius(ap1)\n if (isMulti && bondOrder > 1) {\n multiRadius = radius[ i ] * bondScale / (isOffset ? 1 : (0.5 * bondOrder))\n for (j = isOffset ? 1 : 0; j < bondOrder; ++j) {\n radius[ i + j ] = multiRadius\n }\n }\n }\n if (radius2) {\n radius2[ i ] = radiusFactory.atomRadius(ap2)\n if (isMulti && bondOrder > 1) {\n multiRadius = radius2[ i ] * bondScale / (isOffset ? 1 : (0.5 * bondOrder))\n for (j = isOffset ? 1 : 0; j < bondOrder; ++j) {\n radius2[ i + j ] = multiRadius\n }\n }\n }\n i += isMulti ? bondOrder : 1\n })\n\n return bondData\n }\n\n getBackboneAtomData (params: AtomDataParams) {\n params = Object.assign({\n atomSet: this.atomSetCache.__backbone\n }, params)\n\n return this.getAtomData(params)\n }\n\n getBackboneBondData (params: BondDataParams) {\n params = Object.assign({\n bondSet: this.getBackboneBondSet(),\n bondStore: this.backboneBondStore\n }, params)\n\n return this.getBondData(params)\n }\n\n getRungAtomData (params: AtomDataParams) {\n params = Object.assign({\n atomSet: this.atomSetCache.__rung\n }, params)\n\n return this.getAtomData(params)\n }\n\n getRungBondData (params: BondDataParams) {\n params = Object.assign({\n bondSet: this.getRungBondSet(),\n bondStore: this.rungBondStore\n }, params)\n\n return this.getBondData(params)\n }\n\n //\n\n /**\n * Gets the bounding box of the (selected) structure atoms\n * @param {Selection} [selection] - the selection\n * @param {Box3} [box] - optional target\n * @return {Vector3} the box\n */\n getBoundingBox (selection?: Selection, box?: Box3) {\n if (Debug) Log.time('getBoundingBox')\n\n box = box || new Box3()\n\n let minX = +Infinity\n let minY = +Infinity\n let minZ = +Infinity\n\n let maxX = -Infinity\n let maxY = -Infinity\n let maxZ = -Infinity\n\n this.eachAtom(ap => {\n const x = ap.x\n const y = ap.y\n const z = ap.z\n\n if (x < minX) minX = x\n if (y < minY) minY = y\n if (z < minZ) minZ = z\n\n if (x > maxX) maxX = x\n if (y > maxY) maxY = y\n if (z > maxZ) maxZ = z\n }, selection)\n\n box.min.set(minX, minY, minZ)\n box.max.set(maxX, maxY, maxZ)\n\n if (Debug) Log.timeEnd('getBoundingBox')\n\n return box\n }\n\n /**\n * Gets the principal axes of the (selected) structure atoms\n * @param {Selection} [selection] - the selection\n * @return {PrincipalAxes} the principal axes\n */\n getPrincipalAxes (selection?: Selection) {\n if (Debug) Log.time('getPrincipalAxes')\n\n let i = 0\n const coords = new Matrix(3, this.atomCount)\n const cd = coords.data\n\n this.eachAtom(a => {\n cd[ i + 0 ] = a.x\n cd[ i + 1 ] = a.y\n cd[ i + 2 ] = a.z\n i += 3\n }, selection)\n\n if (Debug) Log.timeEnd('getPrincipalAxes')\n\n return new PrincipalAxes(coords)\n }\n\n /**\n * Gets the center of the (selected) structure atoms\n * @param {Selection} [selection] - the selection\n * @return {Vector3} the center\n */\n atomCenter (selection?: Selection) {\n if (selection) {\n return this.getBoundingBox(selection).getCenter(new Vector3())\n } else {\n return this.center.clone()\n }\n }\n\n hasCoords () {\n if (this._hasCoords === undefined) {\n const atomStore = this.atomStore\n this._hasCoords = (\n arrayMin(atomStore.x) !== 0 || arrayMax(atomStore.x) !== 0 ||\n arrayMin(atomStore.y) !== 0 || arrayMax(atomStore.y) !== 0 ||\n arrayMin(atomStore.z) !== 0 || arrayMax(atomStore.z) !== 0\n ) || (\n // allow models with a single atom at the origin\n atomStore.count / this.modelStore.count === 1\n )\n }\n return this._hasCoords;\n }\n\n getSequence (selection?: Selection) {\n const seq: string[] = []\n const rp = this.getResidueProxy()\n\n this.eachAtom(function (ap: AtomProxy) {\n rp.index = ap.residueIndex\n if (ap.index === rp.traceAtomIndex) {\n seq.push(rp.getResname1())\n }\n }, selection)\n\n return seq\n }\n\n getAtomIndices (selection?: Selection) {\n if (selection && selection.string) {\n const indices: number[] = []\n this.eachAtom(function (ap: AtomProxy) {\n indices.push(ap.index)\n }, selection)\n return new Uint32Array(indices)\n } else {\n const p = { what: { index: true } }\n return this.getAtomData(p).index\n }\n }\n\n /**\n * Get number of unique chainnames\n * @param {Selection} selection - limit count to selection\n * @return {Integer} count\n */\n getChainnameCount (selection?: Selection) {\n const chainnames = new Set()\n this.eachChain(function (cp: ChainProxy) {\n if (cp.residueCount) {\n chainnames.add(cp.chainname)\n }\n }, selection)\n\n return chainnames.size\n }\n\n /**\n * Update atomic positions\n * @param position - Array to copy positions from\n * @param refresh - Whether or not to issue a full refresh (automatically\n * triggers re-calculation of bounding boxes, spatial hash,\n * representations etc etc). This provides compatibility with\n * the old behaviour\n */\n updatePosition (position: Float32Array|number[], refresh: boolean = true) {\n let i = 0\n\n this.eachAtom(function (ap: AtomProxy) {\n ap.positionFromArray(position, i)\n i += 3\n }, undefined)\n\n this._hasCoords = undefined // to trigger recalculation (of the _hasCoords value)\n\n if (refresh) { \n this.refreshPosition() // Recalculate bounds - structure-component listener will \n // trigger representation rebuild\n }\n\n }\n\n refreshPosition () {\n this.getBoundingBox(undefined, this.boundingBox)\n this.boundingBox.getCenter(this.center)\n this.spatialHash = new SpatialHash(this.atomStore, this.boundingBox)\n\n this.signals.refreshed.dispatch(this)\n }\n\n /**\n * Calls dispose() method of property objects.\n * Unsets properties to help garbage collection.\n * @return {undefined}\n */\n dispose () {\n if (this.frames) this.frames.length = 0\n if (this.boxes) this.boxes.length = 0\n\n this.bondStore.dispose()\n this.backboneBondStore.dispose()\n this.rungBondStore.dispose()\n this.atomStore.dispose()\n this.residueStore.dispose()\n this.chainStore.dispose()\n this.modelStore.dispose()\n\n // can't delete non-optional properties as of TS 4\n // and since we've already disposed them, don't need to.\n\n delete this.bondSet\n delete this.atomSet\n }\n}\n\nexport default Structure\n","/**\n * @file Shape\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Matrix4 required for declaration only\nimport { Box3, Vector3, Color, Matrix4 } from 'three'\n\nimport { createParams, ensureFloat32Array, getUintArray } from '../utils'\nimport {\n ArrowPrimitive, BoxPrimitive, ConePrimitive, CylinderPrimitive, EllipsoidPrimitive,\n OctahedronPrimitive, SpherePrimitive, TetrahedronPrimitive, TextPrimitive,\n TorusPrimitive, PointPrimitive, WidelinePrimitive\n} from './primitive'\nimport { MeshPicker } from '../utils/picker'\nimport Buffer from '../buffer/buffer'\nimport MeshBuffer from '../buffer/mesh-buffer'\nimport { TextBufferParameters } from '../buffer/text-buffer'\n\nconst tmpBox = new Box3()\n\nconst Primitives = [\n ArrowPrimitive, BoxPrimitive, ConePrimitive, CylinderPrimitive,\n EllipsoidPrimitive, OctahedronPrimitive, SpherePrimitive, TetrahedronPrimitive,\n TextPrimitive, TorusPrimitive, PointPrimitive, WidelinePrimitive\n]\n\nexport const ShapeDefaultParameters = {\n aspectRatio: 1.5,\n sphereDetail: 2,\n radialSegments: 50,\n disableImpostor: false,\n openEnded: false,\n dashedCylinder: false,\n labelParams: {} as Partial,\n pointSize: 2,\n sizeAttenuation: false,\n useTexture: true,\n linewidth: 2\n}\nexport type ShapeParameters = typeof ShapeDefaultParameters\n\n/**\n * Class for building custom shapes.\n *\n * @example\n * var shape = new NGL.Shape('shape', { disableImpostor: true });\n * shape.addSphere([ 0, 0, 9 ], [ 1, 0, 0 ], 1.5 );\n * shape.addEllipsoid([ 6, 0, 0 ], [ 1, 0, 0 ], 1.5, [ 3, 0, 0 ], [ 0, 2, 0 ]);\n * shape.addCylinder([ 0, 2, 7 ], [ 0, 0, 9 ], [ 1, 1, 0 ], 0.5);\n * shape.addCone([ 0, 2, 7 ], [ 0, 3, 3 ], [ 1, 1, 0 ], 1.5);\n * shape.addArrow([ 1, 2, 7 ], [ 30, 3, 3 ], [ 1, 0, 1 ], 1.0);\n * shape.addBox([ 0, 3, 0 ], [ 1, 0, 1 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]);\n * var shapeComp = stage.addComponentFromObject(shape);\n * geoComp.addRepresentation('buffer');\n */\nclass Shape {\n name: string\n parameters: ShapeParameters\n\n boundingBox = new Box3()\n bufferList: Buffer[] = []\n meshCount = 0\n\n _center?: Vector3\n _primitiveData: { [k: string]: any } = {}\n\n /**\n * @param {String} name - name\n * @param {Object} params - parameter object\n * @param {Integer} params.aspectRatio - arrow aspect ratio, used for cylinder radius and cone length\n * @param {Integer} params.sphereDetail - sphere quality (icosahedron subdivisions)\n * @param {Integer} params.radialSegments - cylinder quality (number of segments)\n * @param {Boolean} params.disableImpostor - disable use of raycasted impostors for rendering\n * @param {Boolean} params.openEnded - capped or not\n * @param {TextBufferParameters} params.labelParams - label parameters\n */\n constructor (name = 'shape', params: Partial = {}) {\n this.name = name\n\n this.parameters = createParams(params, ShapeDefaultParameters)\n\n Primitives.forEach(P => {\n Object.keys(P.fields).forEach(name => {\n this._primitiveData[ P.getShapeKey(name) ] = []\n })\n this._primitiveData[ P.getShapeKey('name') ] = []\n })\n }\n\n /**\n * Add a buffer\n * @param {Buffer} buffer - buffer object\n * @return {Shape} this object\n */\n addBuffer (buffer: Buffer) {\n this.bufferList.push(buffer)\n\n const geometry = (buffer as any).geometry // TODO\n if (!geometry.boundingBox) {\n geometry.computeBoundingBox()\n }\n this.boundingBox.union(geometry.boundingBox)\n\n return this\n }\n\n /**\n * Add a mesh\n * @example\n * shape.addMesh(\n * [ 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1 ],\n * [ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 ]\n * );\n *\n * @param {Float32Array|Array} position - positions\n * @param {Float32Array|Array} color - colors\n * @param {Uint32Array|Uint16Array|Array} [index] - indices\n * @param {Float32Array|Array} [normal] - normals\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addMesh (position: Float32Array|number[], color:Float32Array|number[], index: Uint32Array|Uint16Array|number[], normal?: Float32Array|number[], name?: string) {\n position = ensureFloat32Array(position)\n color = ensureFloat32Array(color)\n\n if (Array.isArray(index)) {\n index = getUintArray(index, position.length)\n }\n if (normal) {\n normal = ensureFloat32Array(normal)\n }\n\n let data\n if (normal === undefined || normal.length == 0 ) {\n data = { position, color, index }\n } else {\n data = { position, color, index, normal }\n }\n //const data = { position, color, index, normal }\n const picking = new MeshPicker(\n this, Object.assign({ serial: this.meshCount, name }, data)\n )\n const meshBuffer = new MeshBuffer(\n Object.assign({ picking }, data) as any\n )\n this.bufferList.push(meshBuffer)\n\n tmpBox.setFromArray(position)\n this.boundingBox.union(tmpBox)\n this.meshCount += 1\n\n return this\n }\n\n /**\n * Add a sphere\n * @example\n * shape.addSphere([ 0, 0, 9 ], [ 1, 0, 0 ], 1.5);\n *\n * @param {Vector3|Array} position - position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} radius - radius value\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addSphere (position: Vector3|[number, number, number], color: Color|[number, number, number], radius: number, name: string) {\n SpherePrimitive.objectToShape(\n this, { position, color, radius, name }\n )\n return this\n }\n\n /**\n * Add an ellipsoid\n * @example\n * shape.addEllipsoid([ 6, 0, 0 ], [ 1, 0, 0 ], 1.5, [ 3, 0, 0 ], [ 0, 2, 0 ]);\n *\n * @param {Vector3|Array} position - position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} radius - radius value\n * @param {Vector3|Array} majorAxis - major axis vector or array\n * @param {Vector3|Array} minorAxis - minor axis vector or array\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addEllipsoid (position: Vector3|[number, number, number], color: Color|[number, number, number], radius: number, majorAxis: Vector3|[number, number, number], minorAxis: Vector3|[number, number, number], name: string) {\n EllipsoidPrimitive.objectToShape(\n this, { position, color, radius, majorAxis, minorAxis, name }\n )\n return this\n }\n\n /**\n * Add a torus\n * @example\n * shape.addTorus([ 6, 0, 0 ], [ 1, 0, 0 ], 1.5, [ 3, 0, 0 ], [ 0, 2, 0 ]);\n *\n * @param {Vector3|Array} position - position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} radius - radius value\n * @param {Vector3|Array} majorAxis - major axis vector or array\n * @param {Vector3|Array} minorAxis - minor axis vector or array\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addTorus (position: Vector3|[number, number, number], color: Color|[number, number, number], radius: number, majorAxis: Vector3|[number, number, number], minorAxis: Vector3|[number, number, number], name: string) {\n TorusPrimitive.objectToShape(\n this, { position, color, radius, majorAxis, minorAxis, name }\n )\n return this\n }\n\n /**\n * Add a cylinder\n * @example\n * shape.addCylinder([ 0, 2, 7 ], [ 0, 0, 9 ], [ 1, 1, 0 ], 0.5);\n *\n * @param {Vector3|Array} position1 - from position vector or array\n * @param {Vector3|Array} position2 - to position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} radius - radius value\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addCylinder (position1: Vector3|[number, number, number], position2: Vector3|[number, number, number], color: Color|[number, number, number], radius: number, name: string) {\n CylinderPrimitive.objectToShape(\n this, { position1, position2, color, radius, name }\n )\n return this\n }\n\n /**\n * Add a cone\n * @example\n * shape.addCone([ 0, 2, 7 ], [ 0, 3, 3 ], [ 1, 1, 0 ], 1.5);\n *\n * @param {Vector3|Array} position1 - from position vector or array\n * @param {Vector3|Array} position2 - to position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} radius - radius value\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addCone (position1: Vector3|[number, number, number], position2: Vector3|[number, number, number], color: Color|[number, number, number], radius: number, name: string) {\n ConePrimitive.objectToShape(\n this, { position1, position2, color, radius, name }\n )\n return this\n }\n\n /**\n * Add an arrow\n * @example\n * shape.addArrow([ 0, 2, 7 ], [ 0, 0, 9 ], [ 1, 1, 0 ], 0.5);\n *\n * @param {Vector3|Array} position1 - from position vector or array\n * @param {Vector3|Array} position2 - to position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} radius - radius value\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addArrow (position1: Vector3|[number, number, number], position2: Vector3|[number, number, number], color: Color|[number, number, number], radius: number, name: string) {\n ArrowPrimitive.objectToShape(\n this, { position1, position2, color, radius, name }\n )\n return this\n }\n\n /**\n * Add a box\n * @example\n * shape.addBox([ 0, 3, 0 ], [ 1, 0, 1 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]);\n *\n * @param {Vector3|Array} position - position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} size - size value\n * @param {Vector3|Array} heightAxis - height axis vector or array\n * @param {Vector3|Array} depthAxis - depth axis vector or array\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addBox (position: Vector3|[number, number, number], color: Color|[number, number, number], size: number, heightAxis: Vector3|[number, number, number], depthAxis: Vector3|[number, number, number], name: string) {\n BoxPrimitive.objectToShape(\n this, { position, color, size, heightAxis, depthAxis, name }\n )\n return this\n }\n\n /**\n * Add an octahedron\n * @example\n * shape.addOctahedron([ 0, 3, 0 ], [ 1, 0, 1 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]);\n *\n * @param {Vector3|Array} position - position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} size - size value\n * @param {Vector3|Array} heightAxis - height axis vector or array\n * @param {Vector3|Array} depthAxis - depth axis vector or array\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addOctahedron (position: Vector3|[number, number, number], color: Color|[number, number, number], size: number, heightAxis: Vector3|[number, number, number], depthAxis: Vector3|[number, number, number], name: string) {\n OctahedronPrimitive.objectToShape(\n this, { position, color, size, heightAxis, depthAxis, name }\n )\n return this\n }\n\n /**\n * Add a tetrahedron\n * @example\n * shape.addTetrahedron([ 0, 3, 0 ], [ 1, 0, 1 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]);\n *\n * @param {Vector3|Array} position - position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} size - size value\n * @param {Vector3|Array} heightAxis - height axis vector or array\n * @param {Vector3|Array} depthAxis - depth axis vector or array\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addTetrahedron (position: Vector3|[number, number, number], color: Color|[number, number, number], size: number, heightAxis: Vector3|[number, number, number], depthAxis: Vector3|[number, number, number], name: string) {\n TetrahedronPrimitive.objectToShape(\n this, { position, color, size, heightAxis, depthAxis, name }\n )\n return this\n }\n\n /**\n * Add text\n * @example\n * shape.addText([ 10, -2, 4 ], [ 0.2, 0.5, 0.8 ], 0.5, \"Hello\");\n *\n * @param {Vector3|Array} position - position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} size - size value\n * @param {String} text - text value\n * @return {Shape} this object\n */\n addText (position: Vector3|[number, number, number], color: Color|[number, number, number], size: number, text: string) {\n TextPrimitive.objectToShape(\n this, { position, color, size, text }\n )\n return this\n }\n\n /**\n * Add point\n * @example\n * shape.addPoint([ 10, -2, 4 ], [ 0.2, 0.5, 0.8 ]);\n *\n * @param {Vector3|Array} position - position vector or array\n * @param {Color|Array} color - color object or array\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addPoint (position: Vector3|[number, number, number], color: Color|[number, number, number], name: string) {\n PointPrimitive.objectToShape(\n this, { position, color, name }\n )\n return this\n }\n\n /**\n * Add a wideline\n * @example\n * shape.addWideline([ 0, 2, 7 ], [ 0, 0, 9 ], [ 1, 1, 0 ]);\n *\n * @param {Vector3|Array} position1 - from position vector or array\n * @param {Vector3|Array} position2 - to position vector or array\n * @param {Color|Array} color - color object or array\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addWideline (position1: Vector3|[number, number, number], position2: Vector3|[number, number, number], color: Color|[number, number, number], linewidth: number, name: string) {\n this.parameters.linewidth = linewidth\n WidelinePrimitive.objectToShape(\n this, { position1, position2, color, name }\n )\n return this\n }\n\n /**\n * Deprecated, use `.addText`\n */\n addLabel (position: Vector3|[number, number, number], color: Color|[number, number, number], size: number, text: string) {\n console.warn('Shape.addLabel is deprecated, use .addText instead')\n return this.addText(position, color, size, text)\n }\n\n getBufferList () {\n const buffers: Buffer[] = []\n\n Primitives.forEach(P => {\n if (this._primitiveData[ P.getShapeKey('color') ].length) {\n buffers.push(P.bufferFromShape(this, this.parameters))\n }\n })\n\n return this.bufferList.concat(buffers)\n }\n\n dispose () {\n this.bufferList.forEach(function (buffer) {\n buffer.dispose()\n })\n this.bufferList.length = 0\n\n Primitives.forEach(P => {\n Object.keys(P.fields).forEach(name => {\n this._primitiveData[ P.getShapeKey(name) ].length = 0\n })\n this._primitiveData[ P.getShapeKey('name') ].length = 0\n })\n }\n\n get center () {\n if (!this._center) {\n this._center = this.boundingBox.getCenter(new Vector3())\n }\n return this._center\n }\n\n get type () { return 'Shape' }\n}\n\nexport default Shape\n","/**\n * @file Buffer Representation\n * @author Alexander Rose \n * @private\n */\n\nimport Representation, { RepresentationParameters } from './representation'\nimport Viewer from '../viewer/viewer';\n\n/**\n * Representation for showing buffer objects. Good for efficiently showing\n * large amounts of geometric primitives e.g. spheres via {@link SphereBuffer}.\n * Smaller numbers of geometric primitives are more easily shown with help\n * from the {@link Shape} class.\n *\n * __Name:__ _buffer_\n *\n * @example\n * // add a single red sphere from a buffer to a shape instance\n * var shape = new NGL.Shape( \"shape\" );\n * var sphereBuffer = new NGL.SphereBuffer( {\n * position: new Float32Array( [ 0, 0, 0 ] ),\n * color: new Float32Array( [ 1, 0, 0 ] ),\n * radius: new Float32Array( [ 1 ] )\n * } );\n * shape.addBuffer( sphereBuffer );\n * var shapeComp = stage.addComponentFromObject( shape );\n * shapeComp.addRepresentation( \"buffer\" );\n *\n * @example\n * // add a single red sphere from a buffer to a structure component instance\n * stage.loadFile( \"rcsb://1crn\" ).then( function( o ){\n * var sphereBuffer = new NGL.SphereBuffer( {\n * position: new Float32Array( [ 0, 0, 0 ] ),\n * color: new Float32Array( [ 1, 0, 0 ] ),\n * radius: new Float32Array( [ 1 ] )\n * } );\n * o.addBufferRepresentation( sphereBuffer, { opacity: 0.5 } );\n * } );\n */\nclass BufferRepresentation extends Representation {\n buffer: Buffer[]\n /**\n * Create Buffer representation\n * @param {Buffer} buffer - a buffer object\n * @param {Viewer} viewer - a viewer object\n * @param {RepresentationParameters} params - representation parameters\n */\n constructor (buffer: Buffer|Buffer[], viewer: Viewer, params: Partial) {\n if (!Array.isArray(buffer)) {\n buffer = [ buffer ]\n }\n\n super(buffer, viewer, params)\n\n this.type = 'buffer'\n\n this.parameters = Object.assign({\n\n }, this.parameters, {\n\n colorScheme: null,\n colorScale: null,\n colorValue: null,\n colorDomain: null,\n colorMode: null\n\n })\n\n this.buffer = buffer\n\n this.init(params)\n }\n\n init (params: Partial) {\n super.init(params)\n\n this.build()\n }\n\n create () {\n this.bufferList.push.apply(this.bufferList, this.buffer)\n }\n\n attach (callback: ()=> void) {\n this.bufferList.forEach(buffer => {\n this.viewer.add(buffer)\n buffer.setParameters(this.getBufferParams())\n })\n this.setVisibility(this.visible)\n\n callback()\n }\n}\n\nexport default BufferRepresentation\n","/**\n * @file Geometry Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Vector3 required for declaration only\n import { Vector3, Matrix4, Matrix3, BufferGeometry } from 'three'\n\nimport { getUintArray } from '../utils'\nimport { serialBlockArray } from '../math/array-utils'\nimport { applyMatrix3toVector3array, applyMatrix4toVector3array } from '../math/vector-utils'\nimport MeshBuffer from './mesh-buffer'\nimport { BufferParameters, BufferData } from './buffer'\nimport {Log} from \"../globals\";\n\nconst matrix = new Matrix4()\nconst normalMatrix = new Matrix3()\n\nfunction getData(data: BufferData, geo: BufferGeometry){\n const geoPosition = (geo.attributes as any).position.array\n const geoIndex = geo.index ? geo.index.array : undefined\n\n const n = data.position!.length / 3\n const m = geoPosition.length / 3\n\n const size = n * m\n\n const meshPosition = new Float32Array(size * 3)\n const meshNormal = new Float32Array(size * 3)\n const meshColor = new Float32Array(size * 3)\n\n let meshIndex\n if (geoIndex) {\n meshIndex = getUintArray(n * geoIndex.length, size)\n }\n\n return {\n position: meshPosition,\n color: meshColor,\n index: meshIndex,\n normal: meshNormal,\n primitiveId: data.primitiveId || serialBlockArray(n, m) as Float32Array,\n picking: data.picking\n }\n}\n\n/**\n * Geometry buffer. Base class for geometry-based buffers. Used to draw\n * geometry primitives given a mesh.\n * @interface\n */\nabstract class GeometryBuffer extends MeshBuffer {\n updateNormals = false\n\n geoPosition: Float32Array\n geoNormal: Float32Array\n geoIndex?: Uint32Array|Uint16Array\n\n positionCount: number\n geoPositionCount: number\n\n transformedGeoPosition: Float32Array\n transformedGeoNormal: Float32Array\n\n meshPosition: Float32Array\n meshColor: Float32Array\n meshIndex: Uint32Array|Uint16Array\n meshNormal: Float32Array\n\n /**\n * @param {Object} data - buffer data\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} data.radius - radii\n * @param {Picker} [data.picking] - picking ids\n * @param {BufferParameters} [params] - parameters object\n * @param {BufferGeometry} geo - geometry object\n */\n constructor (data: BufferData, params: Partial = {}, geo: BufferGeometry) {\n super(getData(data, geo), params)\n\n const geoPosition = (geo.attributes as any).position.array\n const geoNormal = (geo.attributes as any).normal.array\n const geoIndex = geo.index ? (geo.index.array as Uint32Array|Uint16Array) : undefined\n\n this.geoPosition = geoPosition\n this.geoNormal = geoNormal\n this.geoIndex = geoIndex\n\n this.positionCount = data.position!.length / 3\n this.geoPositionCount = geoPosition.length / 3\n\n this.transformedGeoPosition = new Float32Array(this.geoPositionCount * 3)\n this.transformedGeoNormal = new Float32Array(this.geoPositionCount * 3)\n\n const attributes = this.geometry.attributes as any // TODO\n this.meshPosition = attributes.position.array\n this.meshColor = attributes.color.array\n this.meshNormal = attributes.normal.array\n\n this.setAttributes(data)\n\n if (geoIndex) {\n const index = this.geometry.getIndex()\n if (!index) { Log.error('Index is null'); return; }\n this.meshIndex = index.array as Uint32Array|Uint16Array\n this.makeIndex()\n }\n }\n\n abstract applyPositionTransform (matrix: Matrix4, i: number, i3?: number): void\n\n setAttributes (data: Partial = {}, initNormals = false) {\n const attributes = this.geometry.attributes as any // TODO\n\n let position, color\n let geoPosition, geoNormal\n let transformedGeoPosition, transformedGeoNormal\n let meshPosition, meshColor, meshNormal\n\n const updateNormals = this.updateNormals\n\n if (data.position) {\n position = data.position\n geoPosition = this.geoPosition\n meshPosition = this.meshPosition\n transformedGeoPosition = this.transformedGeoPosition\n attributes.position.needsUpdate = true\n if (updateNormals || initNormals) {\n geoNormal = this.geoNormal\n meshNormal = this.meshNormal\n transformedGeoNormal = this.transformedGeoNormal\n attributes.normal.needsUpdate = true\n }\n }\n\n if (data.color) {\n color = data.color\n meshColor = this.meshColor\n attributes.color.needsUpdate = true\n }\n\n const n = this.positionCount\n const m = this.geoPositionCount\n\n for (let i = 0; i < n; ++i) {\n let j, l\n const k = i * m * 3\n const i3 = i * 3\n\n if (position && transformedGeoPosition && meshPosition && meshNormal && geoPosition && geoNormal) {\n transformedGeoPosition.set(geoPosition)\n matrix.makeTranslation(\n position[ i3 ], position[ i3 + 1 ], position[ i3 + 2 ]\n )\n this.applyPositionTransform(matrix, i, i3)\n applyMatrix4toVector3array(matrix.elements as unknown as Float32Array,\n transformedGeoPosition)\n\n meshPosition.set(transformedGeoPosition, k)\n\n if (updateNormals && transformedGeoNormal) {\n transformedGeoNormal.set(geoNormal)\n normalMatrix.getNormalMatrix(matrix)\n applyMatrix3toVector3array(normalMatrix.elements as unknown as Float32Array,\n transformedGeoNormal)\n\n meshNormal.set(transformedGeoNormal, k)\n } else if (initNormals) {\n meshNormal.set(geoNormal, k)\n }\n }\n\n if (color && meshColor) {\n for (j = 0; j < m; ++j) {\n l = k + 3 * j\n\n meshColor[ l ] = color[ i3 ]\n meshColor[ l + 1 ] = color[ i3 + 1 ]\n meshColor[ l + 2 ] = color[ i3 + 2 ]\n }\n }\n }\n }\n\n makeIndex () {\n const geoIndex = this.geoIndex\n const meshIndex = this.meshIndex\n\n if (!geoIndex) return\n\n const n = this.positionCount\n const m = this.geoPositionCount\n const o = geoIndex.length / 3\n\n const o3 = o * 3\n\n for (let i = 0; i < n; ++i) {\n const j = i * o3\n const q = j + o3\n\n meshIndex.set(geoIndex, j)\n for (let p = j; p < q; ++p) meshIndex[ p ] += i * m\n }\n }\n}\n\nexport default GeometryBuffer\n","/**\n * @file Sphere Geometry Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { IcosahedronBufferGeometry, Vector3, Matrix4 } from 'three'\nimport { defaults } from '../utils'\nimport GeometryBuffer from './geometry-buffer'\nimport { SphereBufferData } from './sphere-buffer'\nimport { BufferDefaultParameters, BufferParameters } from './buffer'\n\nconst scale = new Vector3()\n\nexport const SphereGeometryBufferDefaultParameters = Object.assign({\n sphereDetail: 1\n}, BufferDefaultParameters)\nexport type SphereGeometryBufferParameters = BufferParameters & { sphereDetail: number }\n\n/**\n * Sphere geometry buffer.\n *\n * @example\n * var sphereGeometryBuffer = new SphereGeometryBuffer({\n * position: new Float32Array([ 0, 0, 0 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * radius: new Float32Array([ 1 ])\n * });\n */\nclass SphereGeometryBuffer extends GeometryBuffer {\n get defaultParameters() { return SphereGeometryBufferDefaultParameters }\n parameters: SphereGeometryBufferParameters\n\n private _radius: Float32Array\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} data.radius - radii\n * @param {Picker} [data.picking] - picking ids\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: SphereBufferData, params: Partial = {}) {\n super(data, params, new IcosahedronBufferGeometry(1, defaults(params.sphereDetail, 1)))\n\n this.setAttributes(data, true)\n }\n\n applyPositionTransform (matrix: Matrix4, i: number) {\n const r = this._radius[ i ]\n scale.set(r, r, r)\n matrix.scale(scale)\n }\n\n setAttributes (data: Partial = {}, initNormals?: boolean) {\n if (data.radius) this._radius = data.radius\n\n super.setAttributes(data, initNormals)\n }\n}\n\nexport default SphereGeometryBuffer\n","/**\n * @file Mapped Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { getUintArray } from '../utils'\nimport { calculateCenterArray, serialArray } from '../math/array-utils'\nimport Buffer, { BufferParameters, BufferData } from './buffer'\n\nexport type MappingType = 'v2'|'v3'\n\n/**\n * Mapped buffer. Sends mapping attribute to the GPU and repeats data in\n * others attributes. Used to render imposters.\n * @interface\n */\nabstract class MappedBuffer extends Buffer {\n index: Uint32Array|Uint16Array\n\n constructor (mappingType: MappingType, data: BufferData, params: Partial = {}) {\n super(data, params)\n\n this.index = getUintArray(this.indexSize, this.attributeSize)\n this.makeIndex()\n this.initIndex(this.index)\n\n this.addAttributes({\n 'mapping': { type: mappingType, value: null }\n })\n\n this.setAttributes({ primitiveId: serialArray(this.size) })\n }\n\n abstract get mapping (): Float32Array\n abstract get mappingIndices (): Uint32Array|Uint16Array\n abstract get mappingIndicesSize (): number\n abstract get mappingSize (): number\n abstract get mappingItemSize (): number\n\n get attributeSize () {\n return this.size * this.mappingSize\n }\n\n get indexSize () {\n return this.size * this.mappingIndicesSize\n }\n\n addAttributes (attributes: any) {\n const nullValueAttributes: any = {}\n for (const name in attributes) {\n const a = attributes[ name ]\n nullValueAttributes[ name ] = {\n type: a.type,\n value: null\n }\n }\n\n super.addAttributes(nullValueAttributes)\n }\n\n getAttributeIndex (dataIndex: number) {\n return dataIndex * 3 * this.mappingSize\n }\n\n setAttributes (data: any) { // TODO\n if (data && !data.position && data.position1 && data.position2) {\n data.position = calculateCenterArray(data.position1, data.position2)\n }\n\n const size = this.size\n const mappingSize = this.mappingSize\n const attributes = this.geometry.attributes as any // TODO\n\n let a, d, itemSize, array, n, i, j\n\n for (const name in data) {\n if (name === 'index' || name === 'picking') continue\n\n d = data[ name ]\n a = attributes[ name ]\n itemSize = a.itemSize\n array = a.array\n\n for (let k = 0; k < size; ++k) {\n n = k * itemSize\n i = n * mappingSize\n\n for (let l = 0; l < mappingSize; ++l) {\n j = i + (itemSize * l)\n\n for (let m = 0; m < itemSize; ++m) {\n array[ j + m ] = d[ n + m ]\n }\n }\n }\n\n a.needsUpdate = true\n }\n }\n\n makeMapping () {\n const size = this.size\n const mapping = this.mapping\n const mappingSize = this.mappingSize\n const mappingItemSize = this.mappingItemSize\n\n const attributes = this.geometry.attributes as any // TODO\n const aMapping = attributes.mapping.array\n\n for (let v = 0; v < size; v++) {\n aMapping.set(mapping, v * mappingItemSize * mappingSize)\n }\n }\n\n makeIndex () {\n const size = this.size\n const mappingSize = this.mappingSize\n const mappingIndices = this.mappingIndices\n const mappingIndicesSize = this.mappingIndicesSize\n\n const index = this.index\n\n for (let v = 0; v < size; v++) {\n const ix = v * mappingIndicesSize\n const it = v * mappingSize\n\n index.set(mappingIndices, ix)\n\n for (let s = 0; s < mappingIndicesSize; ++s) {\n index[ ix + s ] += it\n }\n }\n }\n}\n\nexport default MappedBuffer\n","/**\n * @file Mapped Quad Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { BufferParameters, BufferData } from './buffer'\nimport MappedBuffer from './mapped-buffer'\n\nconst mapping = new Float32Array([\n -1.0, 1.0,\n -1.0, -1.0,\n 1.0, 1.0,\n 1.0, -1.0\n])\n\nconst mappingIndices = new Uint16Array([\n 0, 1, 2,\n 1, 3, 2\n])\n\n/**\n * Mapped Quad buffer. Draws screen-aligned quads. Used to render impostors.\n * @interface\n */\nclass MappedQuadBuffer extends MappedBuffer {\n constructor(data: BufferData, params: Partial = {}) {\n super('v2', data, params)\n }\n get mapping () { return mapping }\n get mappingIndices () { return mappingIndices }\n get mappingIndicesSize () { return 6 }\n get mappingSize () { return 4 }\n get mappingItemSize () { return 2 }\n}\n\nexport default MappedQuadBuffer\n","/**\n * @file Sphere Impostor Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4 } from 'three'\n\nimport '../shader/SphereImpostor.vert'\nimport '../shader/SphereImpostor.frag'\n\nimport MappedQuadBuffer from './mappedquad-buffer'\nimport { SphereBufferData } from './sphere-buffer'\nimport { BufferParameters } from './buffer'\n\n/**\n * Sphere impostor buffer.\n *\n * @example\n * var sphereImpostorBuffer = new SphereImpostorBuffer({\n * position: new Float32Array([ 0, 0, 0 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * radius: new Float32Array([ 1 ])\n * });\n */\nclass SphereImpostorBuffer extends MappedQuadBuffer {\n isImpostor = true\n vertexShader = 'SphereImpostor.vert'\n fragmentShader = 'SphereImpostor.frag'\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} data.radius - radii\n * @param {Picker} [data.picking] - picking ids\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: SphereBufferData, params: Partial = {}) {\n super(data, params)\n\n this.addUniforms({\n 'projectionMatrixInverse': { value: new Matrix4() },\n 'ortho': { value: 0.0 }\n })\n\n this.addAttributes({\n 'radius': { type: 'f', value: null }\n })\n\n this.setAttributes(data)\n this.makeMapping()\n }\n}\n\nexport default SphereImpostorBuffer\n","/**\n * @file Sphere Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Vector3, Matrix4 required for declaration only \nimport { Vector3, Matrix4 } from 'three'\nimport { BufferRegistry, ExtensionFragDepth } from '../globals'\nimport SphereGeometryBuffer, { SphereGeometryBufferDefaultParameters, SphereGeometryBufferParameters } from './spheregeometry-buffer'\nimport SphereImpostorBuffer from './sphereimpostor-buffer'\nimport { BufferData } from './buffer'\n\nexport interface SphereBufferData extends BufferData {\n radius: Float32Array\n}\n\nexport const SphereBufferDefaultParameters = Object.assign({\n disableImpostor: false\n}, SphereGeometryBufferDefaultParameters)\nexport type SphereBufferParameters = SphereGeometryBufferParameters & { disableImpostor: boolean }\n\nclass SphereBufferImpl {\n /**\n * @param {Object} data - buffer data\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} data.radius - radii\n * @param {Picker} [data.picking] - picking ids\n * @param {BufferParameters} params - parameters object\n * @return {SphereGeometryBuffer|SphereImpostorBuffer} the buffer object\n */\n constructor (data: SphereBufferData, params: SphereBufferParameters) {\n if (!ExtensionFragDepth || (params && params.disableImpostor)) {\n return new SphereGeometryBuffer(data, params)\n } else {\n return new SphereImpostorBuffer(data, params)\n }\n }\n}\n\n/**\n * Sphere buffer. Depending on the value {@link ExtensionFragDepth} and\n * `params.disableImpostor` the constructor returns either a\n * {@link SphereGeometryBuffer} or a {@link SphereImpostorBuffer}\n * @implements {Buffer}\n *\n * @example\n * var sphereBuffer = new SphereBuffer( {\n * position: new Float32Array( [ 0, 0, 0 ] ),\n * color: new Float32Array( [ 1, 0, 0 ] ),\n * radius: new Float32Array( [ 1 ] )\n * } );\n */\n//@ts-expect-error Incompatible constructor signatures\nconst SphereBuffer: {\n new(data: SphereBufferData, params: SphereBufferParameters): SphereGeometryBuffer | SphereImpostorBuffer;\n} = SphereBufferImpl;\n\ntype SphereBuffer = SphereGeometryBuffer | SphereImpostorBuffer;\n\nBufferRegistry.add('sphere', SphereBuffer)\n\nexport default SphereBuffer\n","/**\n * @file Point Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Vector3, Matrix4 required for declaration only\nimport { DataTexture, Vector3, Matrix4 } from 'three'\n\nimport '../shader/Point.vert'\nimport '../shader/Point.frag'\n\nimport { BufferRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport { smoothstep } from '../math/math-utils'\nimport Buffer, { BufferDefaultParameters, BufferParameterTypes, BufferData, BufferTypes, BufferParameters } from './buffer'\n\nfunction distance (x0: number, y0: number, x1: number, y1: number) {\n const dx = x1 - x0\n const dy = y1 - y0\n return Math.sqrt(dx * dx + dy * dy)\n}\n\ninterface PointTextureParams {\n width?: number\n height?: number\n delta?: number\n}\n\nfunction makePointTexture (params: PointTextureParams) {\n const p = params || {}\n\n const width = defaults(p.width, 256)\n const height = defaults(p.height, 256)\n const center = [ width / 2, height / 2 ]\n const radius = Math.min(width / 2, height / 2)\n const delta = defaults(p.delta, 1 / (radius + 1)) * radius\n\n let x = 0\n let y = 0\n const data = new Uint8Array(width * height * 4)\n\n for (let i = 0, il = data.length; i < il; i += 4) {\n const dist = distance(x, y, center[ 0 ], center[ 1 ])\n const value = 1 - smoothstep(radius - delta, radius, dist)\n\n data[ i ] = value * 255\n data[ i + 1 ] = value * 255\n data[ i + 2 ] = value * 255\n data[ i + 3 ] = value * 255\n\n if (++x === width) {\n x = 0\n y++\n }\n }\n\n const tex = new DataTexture(data, width, height)\n tex.needsUpdate = true\n\n return tex\n}\n\nexport const PointBufferDefaultParameters = Object.assign({\n pointSize: 1,\n sizeAttenuation: true,\n sortParticles: false,\n alphaTest: 0.5,\n useTexture: false,\n forceTransparent: false,\n edgeBleach: 0.0\n}, BufferDefaultParameters)\nexport type PointBufferParameters = BufferParameters & {\n pointSize: number,\n sizeAttenuation: boolean,\n sortParticles: boolean,\n alphaTest: number,\n useTexture: boolean,\n forceTransparent: boolean,\n edgeBleach: number\n}\n\nconst PointBufferParameterTypes = Object.assign({\n pointSize: { uniform: 'size' },\n sizeAttenuation: { updateShader: true },\n sortParticles: {},\n alphaTest: { updateShader: true },\n useTexture: { updateShader: true },\n forceTransparent: {},\n edgeBleach: { uniform: true }\n}, BufferParameterTypes)\n\n/**\n * Point buffer. Draws points. Optionally textured.\n *\n * @example\n * var pointBuffer = new PointBuffer( {\n * position: new Float32Array( [ 0, 0, 0 ] ),\n * color: new Float32Array( [ 1, 0, 0 ] )\n * } );\n */\nclass PointBuffer extends Buffer {\n parameterTypes = PointBufferParameterTypes\n get defaultParameters() { return PointBufferDefaultParameters }\n parameters: PointBufferParameters\n\n vertexShader = 'Point.vert'\n fragmentShader ='Point.frag'\n\n isPoint = true\n tex: DataTexture\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.color - colors\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: BufferData, params: Partial = {}) {\n super(data, params)\n\n this.addUniforms({\n 'size': { value: this.parameters.pointSize },\n 'canvasHeight': { value: 1.0 },\n 'pixelRatio': { value: 1.0 },\n 'map': { value: null }\n })\n }\n\n makeMaterial () {\n super.makeMaterial()\n\n this.makeTexture()\n\n const m = this.material\n const wm = this.wireframeMaterial\n const pm = this.pickingMaterial\n\n m.uniforms.map.value = this.tex\n m.needsUpdate = true\n\n wm.uniforms.map.value = this.tex\n wm.needsUpdate = true\n\n pm.uniforms.map.value = this.tex\n pm.needsUpdate = true\n }\n\n makeTexture () {\n if (this.tex) this.tex.dispose()\n this.tex = makePointTexture({ delta: this.parameters.edgeBleach })\n }\n\n getDefines (type?: BufferTypes) {\n const defines = super.getDefines(type)\n\n if (this.parameters.sizeAttenuation) {\n defines.USE_SIZEATTENUATION = 1\n }\n\n if (this.parameters.useTexture) {\n defines.USE_MAP = 1\n }\n\n if (this.parameters.alphaTest > 0 && this.parameters.alphaTest <= 1) {\n defines.ALPHATEST = this.parameters.alphaTest.toPrecision(2)\n }\n\n return defines\n }\n\n setUniforms (data: any) {\n if (data && data.edgeBleach !== undefined) {\n this.makeTexture()\n data.map = this.tex\n }\n\n super.setUniforms(data)\n }\n\n dispose () {\n super.dispose()\n\n if (this.tex) this.tex.dispose()\n }\n}\n\nBufferRegistry.add('point', PointBuffer)\n\nexport default PointBuffer\n","/**\n * @file Dot Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { ExtensionFragDepth } from '../globals'\nimport { defaults } from '../utils'\nimport Representation, { RepresentationParameters } from './representation'\nimport Volume from '../surface/volume'\nimport FilteredVolume from '../surface/filtered-volume'\nimport SphereBuffer, { SphereBufferData, SphereBufferParameters } from '../buffer/sphere-buffer'\nimport PointBuffer from '../buffer/point-buffer'\nimport Surface from '../surface/surface';\nimport Viewer from '../viewer/viewer';\nimport SphereGeometryBuffer from '../buffer/spheregeometry-buffer';\n\nexport interface DotDataFields {\n color?: boolean,\n radius?: boolean,\n scale?: boolean\n}\n\n/**\n * Dot representation parameter object. Extends {@link RepresentationParameters}\n *\n * @typedef {Object} DotRepresentationParameters - dot representation parameters\n *\n * @property {String} thresholdType - Meaning of the threshold values. Either *value* for the literal value or *sigma* as a factor of the sigma of the data. For volume data only.\n * @property {Number} thresholdMin - Minimum value to be displayed. For volume data only.\n * @property {Number} thresholdMax - Maximum value to be displayed. For volume data only.\n * @property {Number} thresholdOut - Show only values falling outside of the treshold minumum and maximum. For volume data only.\n */\nexport interface DotRepresentationParameters extends RepresentationParameters {\n thresholdType: 'value'|'value'|'sigma'|'sigma'\n thresholdMin: number\n thresholdMax: number\n thresholdOut: boolean\n dotType: ''|'sphere'|'point'\n radiusType: ''|'value'|'abs-value'|'value-min'|'deviation'|'size'|'radius' //TODO had to add 'radius' because of test in line 333\n radius: number\n scale: number\n sphereDetail: number\n disableImpostor: boolean\n pointSize: number\n sizeAttenuation: boolean\n sortParticles: boolean\n useTexture: boolean\n alphaTest: number\n forceTransparent: boolean\n edgeBleach: number\n}\n/**\n * Dot representation\n */\nclass DotRepresentation extends Representation {\n protected thresholdType: 'value'|'value'|'sigma'|'sigma'\n protected thresholdMin: number\n protected thresholdMax: number\n protected thresholdOut: boolean\n protected dotType: ''|'sphere'|'point'\n protected radiusType: ''|'value'|'abs-value'|'value-min'|'deviation'|'size'|'radius' //TODO had to add 'radius' because of test in line 333\n protected radius: number\n protected scale: number\n protected sphereDetail: number\n protected disableImpostor: boolean\n protected pointSize: number\n protected sizeAttenuation: boolean\n protected sortParticles: boolean\n protected useTexture: boolean\n protected alphaTest: number\n protected forceTransparent: boolean\n protected edgeBleach: number\n\n protected surface: Surface|undefined\n protected volume: FilteredVolume|undefined\n protected dotBuffer: SphereBuffer|PointBuffer\n /**\n * Create Dot representation object\n * @param {Surface|Volume} surface - the surface or volume to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {DotRepresentationParameters} params - dot representation parameters\n */\n constructor (surface: Surface, viewer: Viewer, params: Partial) {\n super(surface, viewer, params)\n\n this.type = 'dot'\n\n this.parameters = Object.assign({\n\n thresholdType: {\n type: 'select',\n rebuild: true,\n options: {\n 'value': 'value', 'sigma': 'sigma'\n }\n },\n thresholdMin: {\n type: 'number', precision: 3, max: Infinity, min: -Infinity, rebuild: true\n },\n thresholdMax: {\n type: 'number', precision: 3, max: Infinity, min: -Infinity, rebuild: true\n },\n thresholdOut: {\n type: 'boolean', rebuild: true\n },\n dotType: {\n type: 'select',\n rebuild: true,\n options: {\n '': '',\n 'sphere': 'sphere',\n 'point': 'point'\n }\n },\n radiusType: {\n type: 'select',\n options: {\n '': '',\n 'value': 'value',\n 'abs-value': 'abs-value',\n 'value-min': 'value-min',\n 'deviation': 'deviation',\n 'size': 'size'\n }\n },\n radius: {\n type: 'number', precision: 3, max: 10.0, min: 0.001, property: 'size'\n },\n scale: {\n type: 'number', precision: 3, max: 10.0, min: 0.001\n },\n sphereDetail: true,\n disableImpostor: true,\n\n pointSize: {\n type: 'number', precision: 1, max: 100, min: 0, buffer: true\n },\n sizeAttenuation: {\n type: 'boolean', buffer: true\n },\n sortParticles: {\n type: 'boolean', rebuild: true\n },\n useTexture: {\n type: 'boolean', buffer: true\n },\n alphaTest: {\n type: 'range', step: 0.001, max: 1, min: 0, buffer: true\n },\n forceTransparent: {\n type: 'boolean', buffer: true\n },\n edgeBleach: {\n type: 'range', step: 0.001, max: 1, min: 0, buffer: true\n }\n\n }, this.parameters, {\n\n colorScheme: {\n type: 'select',\n update: 'color',\n options: {\n '': '',\n 'value': 'value',\n 'uniform': 'uniform',\n 'random': 'random'\n }\n }\n\n })\n\n if (surface instanceof Volume) {\n this.surface = undefined\n this.volume = new FilteredVolume(surface)\n } else {\n this.surface = surface\n this.volume = undefined\n }\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n p.colorScheme = defaults(p.colorScheme, 'uniform')\n p.colorValue = defaults(p.colorValue, 0xDDDDDD)\n\n this.thresholdType = defaults(p.thresholdType, 'sigma')\n this.thresholdMin = defaults(p.thresholdMin, 2.0)\n this.thresholdMax = defaults(p.thresholdMax, Infinity)\n this.thresholdOut = defaults(p.thresholdOut, false)\n this.dotType = defaults(p.dotType, 'point')\n this.radius = defaults(p.radius, 0.1)\n this.scale = defaults(p.scale, 1.0)\n\n this.pointSize = defaults(p.pointSize, 1)\n this.sizeAttenuation = defaults(p.sizeAttenuation, true)\n this.sortParticles = defaults(p.sortParticles, false)\n this.useTexture = defaults(p.useTexture, false)\n this.alphaTest = defaults(p.alphaTest, 0.5)\n this.forceTransparent = defaults(p.forceTransparent, false)\n this.edgeBleach = defaults(p.edgeBleach, 0.0)\n\n super.init(p)\n\n this.build()\n }\n\n attach (callback: () => void) {\n this.bufferList.forEach(buffer => {\n this.viewer.add(buffer)\n })\n this.setVisibility(this.visible)\n\n callback()\n }\n\n create () {\n var dotData: SphereBufferData|{} = {}\n\n if (this.volume) {\n var volume = this.volume\n var thresholdMin, thresholdMax\n\n if (this.thresholdType === 'sigma') {\n thresholdMin = volume.getValueForSigma(this.thresholdMin)\n thresholdMax = volume.getValueForSigma(this.thresholdMax)\n } else {\n thresholdMin = this.thresholdMin\n thresholdMax = this.thresholdMax\n }\n volume.setFilter(thresholdMin, thresholdMax, this.thresholdOut)\n\n Object.assign(dotData, {\n position: volume.getDataPosition(),\n color: volume.getDataColor(this.getColorParams())\n })\n if (this.dotType === 'sphere') {\n Object.assign(dotData, {\n radius: volume.getDataSize(this.radius, this.scale),\n picking: volume.getDataPicking()\n })\n }\n } else {\n var surface = this.surface\n Object.assign(dotData, {\n position: (surface as Surface).getPosition(),\n color: (surface as Surface).getColor(this.getColorParams())\n })\n if (this.dotType === 'sphere') {\n Object.assign(dotData, {\n radius: (surface as Surface).getSize(this.radius, this.scale),\n picking: (surface as Surface).getPicking()\n })\n }\n }\n\n if (this.dotType === 'sphere') {\n this.dotBuffer = new SphereBuffer(\n dotData as SphereBufferData,\n this.getBufferParams({\n sphereDetail: this.sphereDetail,\n disableImpostor: this.disableImpostor,\n dullInterior: false\n }) as SphereBufferParameters\n ) as SphereGeometryBuffer\n } else {\n this.dotBuffer = new PointBuffer(\n dotData,\n this.getBufferParams({\n pointSize: this.pointSize,\n sizeAttenuation: this.sizeAttenuation,\n sortParticles: this.sortParticles,\n useTexture: this.useTexture,\n alphaTest: this.alphaTest,\n forceTransparent: this.forceTransparent,\n edgeBleach: this.edgeBleach\n })\n )\n }\n\n this.bufferList.push(this.dotBuffer as SphereGeometryBuffer)\n }\n\n update (what: DotDataFields = {}) {\n if (this.bufferList.length === 0) return\n\n const dotData: SphereBufferData|{} = {}\n\n if (what.color) {\n if (this.volume) {\n Object.assign(dotData, {\n color: this.volume.getDataColor(\n this.getColorParams()\n )\n })\n } else {\n Object.assign(dotData, {\n color: (this.surface as Surface).getColor(\n this.getColorParams()\n )\n })\n }\n }\n\n if (this.dotType === 'sphere' && (what.radius || what.scale)) {\n if (this.volume) {\n Object.assign(dotData, {\n radius: this.volume.getDataSize(\n this.radius, this.scale\n )\n })\n } else {\n Object.assign(dotData, {\n radius: (this.surface as Surface).getSize(\n this.radius, this.scale\n )\n })\n }\n }\n\n (this.dotBuffer as SphereGeometryBuffer).setAttributes(dotData)\n }\n\n setParameters (params: Partial, what: DotDataFields = {}, rebuild: boolean) {\n \n if (params && params.thresholdType !== undefined &&\n this.volume instanceof Volume\n ) {\n if (this.thresholdType === 'value' &&\n params.thresholdType === 'sigma'\n ) {\n this.thresholdMin = this.volume.getSigmaForValue(\n this.thresholdMin\n )\n this.thresholdMax = this.volume.getSigmaForValue(\n this.thresholdMax\n )\n } else if (this.thresholdType === 'sigma' &&\n params.thresholdType === 'value'\n ) {\n this.thresholdMin = this.volume.getValueForSigma(\n this.thresholdMin\n )\n this.thresholdMax = this.volume.getValueForSigma(\n this.thresholdMax\n )\n }\n\n this.thresholdType = params.thresholdType\n }\n\n if (params && params.radiusType !== undefined) {\n if (params.radiusType === 'radius') {\n this.radius = 0.1\n } else {\n this.radius = parseFloat(params.radiusType)\n }\n what.radius = true\n if (this.dotType === 'sphere' &&\n (!ExtensionFragDepth || this.disableImpostor)\n ) {\n rebuild = true\n }\n }\n\n if (params && params.radius !== undefined) {\n what.radius = true\n if (this.dotType === 'sphere' &&\n (!ExtensionFragDepth || this.disableImpostor)\n ) {\n rebuild = true\n }\n }\n\n if (params && params.scale !== undefined) {\n what.scale = true\n if (this.dotType === 'sphere' &&\n (!ExtensionFragDepth || this.disableImpostor)\n ) {\n rebuild = true\n }\n }\n\n super.setParameters(params, what, rebuild)\n\n return this\n }\n}\n\nexport default DotRepresentation\n","/**\n * @file Image Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport {\n // @ts-ignore: unused import Vector3, Matrix4 required for declaration only\n Vector2, Vector3, Matrix4, BufferAttribute, DataTexture,\n NormalBlending, NearestFilter, LinearFilter\n} from 'three'\n\nimport '../shader/Image.vert'\nimport '../shader/Image.frag'\n\nimport { Picker } from '../utils/picker'\nimport Buffer, { BufferDefaultParameters, BufferParameterTypes, BufferTypes } from './buffer'\n\n\nconst quadIndices = new Uint16Array([\n 0, 1, 2,\n 1, 3, 2\n])\n\nconst quadUvs = new Float32Array([\n 0, 1,\n 0, 0,\n 1, 1,\n 1, 0\n])\n\ntype ImageFilterTypes = 'nearest'|'linear'|'cubic-bspline'|'cubic-catmulrom'|'cubic-mitchell'\n\nexport interface ImageBufferData {\n position: Float32Array\n imageData: Uint8Array\n width: number\n height: number\n\n picking?: Picker\n}\n\nexport const ImageBufferDefaultParameters = Object.assign({\n filter: 'nearest' as ImageFilterTypes,\n forceTransparent: true\n}, BufferDefaultParameters)\nexport type ImageBufferParameters = typeof ImageBufferDefaultParameters\n\nexport const ImageBufferParameterTypes = Object.assign({\n filter: { updateShader: true, uniform: true }\n}, BufferParameterTypes)\n\n/**\n * Image buffer. Draw a single image. Optionally interpolate.\n */\nclass ImageBuffer extends Buffer {\n parameterTypes = ImageBufferParameterTypes\n get defaultParameters() { return ImageBufferDefaultParameters }\n parameters: ImageBufferParameters\n\n alwaysTransparent = true\n hasWireframe = false\n vertexShader = 'Image.vert'\n fragmentShader = 'Image.frag'\n\n tex: DataTexture\n pickingTex: DataTexture\n\n /**\n * @param {Object} data - buffer data\n * @param {Float32Array} data.position - image position\n * @param {Float32Array} data.imageData - image data, rgba channels\n * @param {Float32Array} data.width - image width\n * @param {Float32Array} data.height - image height\n * @param {Picker} [data.picking] - picking ids\n * @param {BufferParameters} [params] - parameters object\n */\n constructor (data: ImageBufferData, params: ImageBufferParameters) {\n super({\n position: data.position,\n index: quadIndices,\n picking: data.picking\n }, params)\n\n const {imageData, width, height} = data\n\n const tex = new DataTexture(imageData, width, height)\n tex.flipY = true\n this.tex = tex\n\n const n = imageData.length\n const pickingData = new Uint8Array(n)\n for (let i = 0; i < n; i += 4) {\n const j = i / 4\n pickingData[ i ] = j >> 16 & 255\n pickingData[ i + 1 ] = j >> 8 & 255\n pickingData[ i + 2 ] = j & 255\n }\n\n const pickingTex = new DataTexture(pickingData, width, height)\n pickingTex.flipY = true\n pickingTex.minFilter = NearestFilter\n pickingTex.magFilter = NearestFilter\n this.pickingTex = pickingTex\n\n this.addUniforms({\n 'map': { value: tex },\n 'pickingMap': { value: pickingTex },\n 'mapSize': { value: new Vector2(width, height) }\n })\n\n this.geometry.setAttribute('uv', new BufferAttribute(quadUvs, 2))\n }\n\n getDefines (type: BufferTypes) {\n const defines = super.getDefines(type)\n const filter = this.parameters.filter\n\n if (filter.startsWith('cubic')) {\n defines.CUBIC_INTERPOLATION = 1\n if (filter.endsWith('bspline')) {\n defines.BSPLINE_FILTER = 1\n } else if (filter.endsWith('catmulrom')) {\n defines.CATMULROM_FILTER = 1\n } else if (filter.endsWith('mitchell')) {\n defines.MITCHELL_FILTER = 1\n }\n }\n\n return defines\n }\n\n updateTexture () {\n const tex = this.tex\n const filter = this.parameters.filter\n\n if (filter.startsWith('cubic')) {\n tex.minFilter = NearestFilter\n tex.magFilter = NearestFilter\n } else if (filter === 'linear') {\n tex.minFilter = LinearFilter\n tex.magFilter = LinearFilter\n } else { // filter === \"nearest\"\n tex.minFilter = NearestFilter\n tex.magFilter = NearestFilter\n }\n\n tex.needsUpdate = true\n this.pickingTex.needsUpdate = true\n }\n\n makeMaterial () {\n super.makeMaterial()\n this.updateTexture()\n\n const m = this.material\n m.uniforms.map.value = this.tex\n m.blending = NormalBlending\n m.needsUpdate = true\n\n const wm = this.wireframeMaterial\n wm.uniforms.map.value = this.tex\n wm.blending = NormalBlending\n wm.needsUpdate = true\n\n const pm = this.pickingMaterial\n pm.uniforms.map.value = this.tex\n pm.uniforms.pickingMap.value = this.pickingTex\n pm.blending = NormalBlending\n pm.needsUpdate = true\n }\n\n setUniforms (data: any) { // TODO\n if (data && data.filter !== undefined) {\n this.updateTexture()\n data.map = this.tex\n }\n\n super.setUniforms(data)\n }\n}\n\nexport default ImageBuffer\n","/**\n * @file Volume Slice\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { ColormakerRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport { SlicePicker } from '../utils/picker'\nimport { Volume } from '../ngl';\nimport { SliceRepresentationParameters } from '../representation/slice-representation';\n\nclass VolumeSlice {\n dimension: 'x'|'y'|'z'\n positionType: 'percent'|'coordinate'\n position: number\n thresholdType: 'sigma'|'value'\n thresholdMin: number\n thresholdMax: number\n normalize: boolean\n volume: Volume\n\n constructor (volume: Volume, params: Partial) {\n const p = params || {}\n\n this.dimension = defaults(p.dimension, 'x')\n this.positionType = defaults(p.positionType, 'percent')\n this.position = defaults(p.position, 30)\n this.thresholdType = defaults(p.thresholdType, 'sigma')\n this.thresholdMin = defaults(p.thresholdMin, -Infinity)\n this.thresholdMax = defaults(p.thresholdMax, Infinity)\n this.normalize = defaults(p.normalize, false)\n\n this.volume = volume\n }\n\n getPositionFromCoordinate (coord: number) {\n const dim = this.dimension\n const v = this.volume\n const m = v.matrix\n\n const mp = new Vector3().setFromMatrixPosition(m)[ dim ]\n const ms = new Vector3().setFromMatrixScale(m)[ dim ]\n\n let vn\n if (dim === 'x') {\n vn = v.nx\n } else if (dim === 'y') {\n vn = v.ny\n } else {\n vn = v.nz\n }\n\n return Math.round((((coord - mp) / (vn / 100)) + 1) / ms)\n }\n\n getData (params: any) {\n params = params || {}\n\n const v = this.volume\n const d = v.data\n const m = v.matrix\n\n let p: number\n if (this.positionType === 'coordinate') {\n p = this.getPositionFromCoordinate(this.position)\n } else {\n p = this.position\n }\n\n function pos (dimLen: number) {\n return Math.round((dimLen / 100) * (p - 1))\n }\n\n function index (x: number, y: number, z: number, i: number) {\n return (z * v.ny * v.nx + y * v.nx + x) * 3 + i\n }\n\n const position = new Float32Array(4 * 3)\n const vec = new Vector3()\n\n let width, height\n let x\n let y\n let z\n let x0 = 0\n let y0 = 0\n let z0 = 0\n let nx = v.nx\n let ny = v.ny\n let nz = v.nz\n\n function setVec (x: number, y: number, z: number, offset: number) {\n vec.set(x, y, z).applyMatrix4(m).toArray(position as any, offset)\n }\n\n if (this.dimension === 'x') {\n x = pos(v.nx)\n y = v.ny - 1\n z = v.nz - 1\n\n width = v.nz\n height = v.ny\n\n x0 = x\n nx = x0 + 1\n\n setVec(x, 0, 0, 0)\n setVec(x, y, 0, 3)\n setVec(x, 0, z, 6)\n setVec(x, y, z, 9)\n } else if (this.dimension === 'y') {\n x = v.nx - 1\n y = pos(v.ny)\n z = v.nz - 1\n\n width = v.nz\n height = v.nx\n\n y0 = y\n ny = y0 + 1\n\n setVec(0, y, 0, 0)\n setVec(x, y, 0, 3)\n setVec(0, y, z, 6)\n setVec(x, y, z, 9)\n } else if (this.dimension === 'z') {\n x = v.nx - 1\n y = v.ny - 1\n z = pos(v.nz)\n\n width = v.nx\n height = v.ny\n\n z0 = z\n nz = z0 + 1\n\n setVec(0, 0, z, 0)\n setVec(0, y, z, 3)\n setVec(x, 0, z, 6)\n setVec(x, y, z, 9)\n }\n\n let i = 0\n let j = 0\n const imageData = new Uint8Array(width * height * 4)\n const pickingArray = new Float32Array(width * height)\n\n let tMin, tMax\n if (this.thresholdType === 'sigma') {\n tMin = v.getValueForSigma(this.thresholdMin)\n tMax = v.getValueForSigma(this.thresholdMax)\n } else {\n tMin = this.thresholdMin\n tMax = this.thresholdMax\n }\n\n const cp = Object.assign({}, params.colorParams, { volume: v })\n if (this.normalize) {\n cp.domain = [ 0, 1 ]\n }\n const colormaker = ColormakerRegistry.getScheme(cp)\n const tmp = new Float32Array(3)\n const scale = colormaker.getScale()\n\n let min = 0, max, diff = 0\n if (this.normalize) {\n min = +Infinity\n max = -Infinity\n for (let iy = y0; iy < ny; ++iy) {\n for (let ix = x0; ix < nx; ++ix) {\n for (let iz = z0; iz < nz; ++iz) {\n const idx = index(ix, iy, iz, 0) / 3\n const val = d[ idx ]\n if (val < min) min = val\n if (val > max) max = val\n }\n }\n }\n diff = max - min\n }\n\n for (let iy = y0; iy < ny; ++iy) {\n for (let ix = x0; ix < nx; ++ix) {\n for (let iz = z0; iz < nz; ++iz) {\n const idx = index(ix, iy, iz, 0) / 3\n let val = d[ idx ]\n if (this.normalize) {\n val = (val - min) / diff\n }\n\n colormaker.colorToArray(scale(val), tmp)\n imageData[ i ] = Math.round(tmp[ 0 ] * 255)\n imageData[ i + 1 ] = Math.round(tmp[ 1 ] * 255)\n imageData[ i + 2 ] = Math.round(tmp[ 2 ] * 255)\n imageData[ i + 3 ] = (val > tMin && val < tMax) ? 255 : 0\n\n pickingArray[ j ] = idx\n\n ++j\n i += 4\n }\n }\n }\n\n const picking = new SlicePicker(pickingArray, v)\n\n return { position, imageData, width, height, picking }\n }\n}\n\nexport default VolumeSlice\n","/**\n * @file Slice Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport Representation, { RepresentationParameters } from './representation'\nimport ImageBuffer, { ImageBufferParameters, ImageBufferData } from '../buffer/image-buffer'\nimport VolumeSlice from '../surface/volume-slice'\nimport Viewer from '../viewer/viewer';\nimport { Volume } from '../ngl';\n\n/**\n * Slice representation parameter object. Extends {@link RepresentationParameters}\n *\n * @typedef {Object} SliceRepresentationParameters - slice representation parameters\n *\n * @property {String} filter - filter applied to map the volume data on the slice, one of \"nearest\", \"linear\", \"cubic-bspline\", \"cubic-catmulrom\", \"cubic-mitchell\".\n * @property {String} positionType - Meaning of the position value. Either \"percent\" od \"coordinate\".\n * @property {Number} position - position of the slice.\n * @property {String} dimension - one of \"x\", \"y\" or \"z\"\n * @property {String} thresholdType - Meaning of the threshold values. Either *value* for the literal value or *sigma* as a factor of the sigma of the data. For volume data only.\n * @property {Number} thresholdMin - Minimum value to be displayed. For volume data only.\n * @property {Number} thresholdMax - Maximum value to be displayed. For volume data only.\n * @property {Boolean} normalize - Flag indicating wheather to normalize the data in a slice when coloring.\n */\nexport interface SliceRepresentationParameters extends RepresentationParameters {\n filter: 'nearest'|'linear'|'cubic-bspline'|'cubic-catmulrom'|'cubic-mitchell'\n positionType: 'percent'|'coordinate'\n position: number\n dimension: 'x'|'y'|'z'\n thresholdType: 'value'|'sigma'\n thresholdMin: number\n thresholdMax: number\n normalize: boolean\n}\n/**\n * Slice representation\n */\nclass SliceRepresentation extends Representation {\n protected filter: 'nearest'|'linear'|'cubic-bspline'|'cubic-catmulrom'|'cubic-mitchell'\n protected positionType: 'percent'|'coordinate'\n protected position: number\n protected dimension: 'x'|'y'|'z'\n protected thresholdType: 'value'|'sigma'\n protected thresholdMin: number\n protected thresholdMax: number\n protected normalize: boolean\n protected volume: Volume\n /**\n * Create Slice representation object\n * @param {Volume} surface - the volume to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {SliceRepresentationParameters} params - slice representation parameters\n */\n constructor (volume: Volume, viewer: Viewer, params: Partial) {\n super(volume, viewer, params)\n\n this.type = 'slice'\n\n this.parameters = Object.assign({\n\n filter: {\n type: 'select',\n buffer: true,\n options: {\n 'nearest': 'nearest',\n 'linear': 'linear',\n 'cubic-bspline': 'cubic-bspline',\n 'cubic-catmulrom': 'cubic-catmulrom',\n 'cubic-mitchell': 'cubic-mitchell'\n }\n },\n positionType: {\n type: 'select',\n rebuild: true,\n options: {\n 'percent': 'percent', 'coordinate': 'coordinate'\n }\n },\n position: {\n type: 'range',\n step: 0.1,\n max: 100,\n min: 1,\n rebuild: true\n },\n dimension: {\n type: 'select',\n rebuild: true,\n options: {\n 'x': 'x', 'y': 'y', 'z': 'z'\n }\n },\n thresholdType: {\n type: 'select',\n rebuild: true,\n options: {\n 'value': 'value', 'sigma': 'sigma'\n }\n },\n thresholdMin: {\n type: 'number', precision: 3, max: Infinity, min: -Infinity, rebuild: true\n },\n thresholdMax: {\n type: 'number', precision: 3, max: Infinity, min: -Infinity, rebuild: true\n },\n normalize: {\n type: 'boolean', rebuild: true\n }\n\n }, this.parameters, {\n\n flatShaded: null,\n side: null,\n wireframe: null,\n linewidth: null,\n colorScheme: null,\n\n roughness: null,\n metalness: null,\n diffuse: null\n\n })\n\n this.volume = volume\n\n this.init(params)\n }\n\n init (params: Partial) {\n const v = this.volume\n const p = params || {}\n p.colorDomain = defaults(p.colorDomain, [ v.min, v.max ])\n p.colorScheme = defaults(p.colorScheme, 'value')\n p.colorScale = defaults(p.colorScale, 'Spectral')\n\n this.colorScheme = 'value'\n this.dimension = defaults(p.dimension, 'x')\n this.filter = defaults(p.filter, 'cubic-bspline')\n this.positionType = defaults(p.positionType, 'percent')\n this.position = defaults(p.position, 30)\n this.thresholdType = defaults(p.thresholdType, 'sigma')\n this.thresholdMin = defaults(p.thresholdMin, -Infinity)\n this.thresholdMax = defaults(p.thresholdMax, Infinity)\n this.normalize = defaults(p.normalize, false)\n\n super.init(p)\n\n this.build()\n }\n\n attach (callback: () => void) {\n this.bufferList.forEach(buffer => {\n this.viewer.add(buffer)\n })\n this.setVisibility(this.visible)\n\n callback()\n }\n\n create () {\n const volumeSlice = new VolumeSlice(this.volume, {\n positionType: this.positionType,\n position: this.position,\n dimension: this.dimension,\n thresholdType: this.thresholdType,\n thresholdMin: this.thresholdMin,\n thresholdMax: this.thresholdMax,\n normalize: this.normalize\n })\n\n const sliceBuffer = new ImageBuffer(\n volumeSlice.getData({ colorParams: this.getColorParams() }) as ImageBufferData,\n this.getBufferParams({\n filter: this.filter\n }) as ImageBufferParameters\n )\n\n this.bufferList.push(sliceBuffer)\n }\n}\n\nexport default SliceRepresentation\n","/**\n * @file Representation Utils\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, RepresentationRegistry } from '../globals'\n\nimport Viewer from '../viewer/viewer'\nimport Structure from '../structure/structure'\nimport Surface from '../surface/surface'\nimport Volume from '../surface/volume'\nimport Shape from '../geometry/shape'\n\nimport BufferRepresentation from './buffer-representation'\nimport SurfaceRepresentation from './surface-representation'\nimport DotRepresentation from './dot-representation'\nimport SliceRepresentation from './slice-representation'\n\nfunction logReprUnknown (type: string) {\n Log.error(`makeRepresentation: representation type ${type} unknown`)\n}\n\nexport function makeRepresentation (type: string, object: any, viewer: Viewer, params: any) { // TODO\n if (Debug) Log.time('makeRepresentation ' + type)\n\n var ReprClass\n\n if (object instanceof Structure) {\n ReprClass = RepresentationRegistry.get(type)\n\n if (!ReprClass) {\n logReprUnknown(type)\n return\n }\n } else if (object instanceof Surface) {\n if (type === 'surface') {\n ReprClass = SurfaceRepresentation\n } else if (type === 'dot') {\n ReprClass = DotRepresentation\n } else {\n logReprUnknown(type)\n return\n }\n } else if (object instanceof Volume) {\n if (type === 'surface') {\n ReprClass = SurfaceRepresentation\n } else if (type === 'dot') {\n ReprClass = DotRepresentation\n } else if (type === 'slice') {\n ReprClass = SliceRepresentation\n } else {\n logReprUnknown(type)\n return\n }\n } else if (object instanceof Shape) {\n ReprClass = BufferRepresentation\n object = object.getBufferList()\n } else if (type === 'buffer') {\n ReprClass = BufferRepresentation\n } else {\n Log.error('makeRepresentation: object ' + object + ' unknown')\n return\n }\n\n const repr = new ReprClass(object, viewer, params)\n\n if (Debug) Log.timeEnd('makeRepresentation ' + type)\n\n return repr\n}\n","/**\n * @file Element\n * @author Alexander Rose \n * @private\n */\n\nimport { Signal } from 'signals'\n\nimport { createParams } from '../utils'\nimport { generateUUID } from '../math/math-utils'\nimport Stage from '../stage/stage'\n\nexport const ElementDefaultParameters = {\n name: 'some element',\n status: ''\n}\nexport type ElementParameters = typeof ElementDefaultParameters\n\nexport interface ElementSignals {\n statusChanged: Signal // on status change\n nameChanged: Signal // on name change\n disposed: Signal // on dispose\n}\n\n/**\n * Element base class\n */\nabstract class Element {\n /**\n * Events emitted by the element\n */\n signals: ElementSignals = {\n statusChanged: new Signal(),\n nameChanged: new Signal(),\n disposed: new Signal()\n }\n readonly parameters: ElementParameters\n readonly uuid: string\n\n get defaultParameters() { return ElementDefaultParameters }\n\n /**\n * @param {Stage} stage - stage object the component belongs to\n * @param {ElementParameters} params - component parameters\n */\n constructor (readonly stage: Stage, params: Partial = {}) {\n this.parameters = createParams(params, this.defaultParameters)\n this.uuid = generateUUID()\n }\n\n abstract get type (): string\n\n get name () { return this.parameters.name }\n\n setStatus (value: string) {\n this.parameters.status = value\n this.signals.statusChanged.dispatch(value)\n\n return this\n }\n\n setName (value: string) {\n this.parameters.name = value\n this.signals.nameChanged.dispatch(value)\n\n return this\n }\n\n dispose () {\n this.signals.disposed.dispatch()\n }\n}\n\nexport default Element\n","/**\n * @file Representation Element\n * @author Alexander Rose \n * @private\n */\n\nimport { Signal } from 'signals'\nimport { Color } from 'three'\n\nimport Stage from '../stage/stage'\nimport Representation, { RepresentationParameters } from '../representation/representation'\nimport Component from './component'\nimport Element, { ElementDefaultParameters, ElementSignals } from './element'\n\nexport const RepresentationElementDefaultParameters = Object.assign({\n visible: true\n}, ElementDefaultParameters)\nexport type RepresentationElementParameters = typeof RepresentationElementDefaultParameters\n\nexport interface RepresentationElementSignals extends ElementSignals {\n visibilityChanged: Signal // on visibility change\n parametersChanged: Signal // on parameters change\n}\n\n/**\n * Element wrapping a {@link Representation} object\n */\nclass RepresentationElement extends Element {\n signals: RepresentationElementSignals\n parameters: RepresentationElementParameters\n get defaultParameters() { return RepresentationElementDefaultParameters }\n\n repr: Representation\n\n /**\n * Create representation component\n * @param {Stage} stage - stage object the component belongs to\n * @param {Representation} repr - representation object to wrap\n * @param {RepresentationParameters} [params] - component parameters\n * @param {Component} [parent] - parent component\n */\n constructor (stage: Stage, repr: Representation, params: Partial = {}, readonly parent: Component) {\n super(stage, Object.assign({ name: repr.type }, params))\n\n this.signals = Object.assign({\n visibilityChanged: new Signal(),\n parametersChanged: new Signal()\n }, this.signals)\n\n this.setRepresentation(repr)\n }\n\n get visible () { return this.parameters.visible }\n\n /**\n * Component type\n * @type {String}\n */\n get type () { return 'representation' }\n\n getType () {\n return this.repr.type\n }\n\n setRepresentation (repr: Representation) {\n this._disposeRepresentation()\n this.repr = repr\n // this.name = repr.type;\n this.stage.tasks.listen(this.repr.tasks)\n this.updateVisibility()\n }\n\n _disposeRepresentation () {\n if (this.repr) {\n this.stage.tasks.unlisten(this.repr.tasks)\n this.repr.dispose()\n }\n }\n\n dispose () {\n if (this.parent && this.parent.hasRepresentation(this)) {\n this.parent.removeRepresentation(this)\n } else {\n this._disposeRepresentation()\n this.signals.disposed.dispatch()\n }\n }\n\n /**\n * Set the visibility of the component, takes parent visibility into account\n * @param {Boolean} value - visibility flag\n * @return {RepresentationElement} this object\n */\n setVisibility (value: boolean) {\n this.parameters.visible = value\n this.updateVisibility()\n this.signals.visibilityChanged.dispatch(this.parameters.visible)\n\n return this\n }\n\n getVisibility () {\n if (this.parent) {\n return this.parent.parameters.visible && this.parameters.visible\n } else {\n return this.parameters.visible\n }\n }\n\n /**\n * Toggle visibility of the component, takes parent visibility into account\n * @return {RepresentationElement} this object\n */\n toggleVisibility () {\n return this.setVisibility(!this.parameters.visible)\n }\n\n updateVisibility () {\n this.repr.setVisibility(this.getVisibility())\n }\n\n /**\n * Set selection\n * @param {Object} what - flags indicating what attributes to update\n * @param {Boolean} what.position - update position attribute\n * @param {Boolean} what.color - update color attribute\n * @param {Boolean} what.radius - update radius attribute\n * @return {RepresentationElement} this object\n */\n update (what: any) { // TODO\n (this.repr as any).update(what) // TODO\n\n return this\n }\n\n build (params?: any) { // TODO\n this.repr.build(params)\n\n return this\n }\n\n /**\n * Set selection\n * @param {String} string - selection string\n * @return {RepresentationElement} this object\n */\n setSelection (string: string) {\n const repr: any = this.repr // TODO\n\n if (repr.setSelection) {\n repr.setSelection(string)\n }\n\n return this\n }\n\n /**\n * Set representation parameters\n * @param {RepresentationParameters} params - parameter object\n * @return {RepresentationElement} this object\n */\n setParameters (params: any) { // TODO\n this.repr.setParameters(params)\n this.signals.parametersChanged.dispatch(\n this.repr.getParameters()\n )\n\n return this\n }\n\n /**\n * Get representation parameters\n * @return {RepresentationParameters} parameter object\n */\n getParameters (): Partial {\n return this.repr.getParameters()\n }\n\n /**\n * Set color\n * @param {String|Color|Hex} value - color value\n * @return {RepresentationElement} this object\n */\n setColor (value: string|number|Color) {\n this.repr.setColor(value)\n\n return this\n }\n}\n\nexport default RepresentationElement\n","\n/**\n * @file Component\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Quaternion, Matrix4, Euler, Box3 } from 'three'\nimport { Signal } from 'signals'\n\nimport { defaults, createParams } from '../utils'\nimport { generateUUID } from '../math/math-utils'\nimport Annotation, { AnnotationParams } from '../component/annotation'\nimport ComponentControls from '../controls/component-controls'\nimport { makeRepresentation } from '../representation/representation-utils'\nimport RepresentationElement from './representation-element'\nimport Stage from '../stage/stage'\nimport Viewer from '../viewer/viewer'\n\nconst _m = new Matrix4()\nconst _v = new Vector3()\n\nexport const ComponentDefaultParameters = {\n name: '',\n status: '',\n visible: true\n}\nexport type ComponentParameters = typeof ComponentDefaultParameters\n\n\nexport interface ComponentSignals {\n representationAdded: Signal // when a representation is added\n representationRemoved: Signal // when a representation is removed\n visibilityChanged: Signal // on visibility change\n matrixChanged: Signal // on matrix change\n statusChanged: Signal // on status change\n nameChanged: Signal // on name change\n disposed: Signal // on dispose\n}\n\n/**\n * Base class for components\n */\nabstract class Component {\n /**\n * Events emitted by the component\n */\n readonly signals: ComponentSignals = {\n representationAdded: new Signal(),\n representationRemoved: new Signal(),\n visibilityChanged: new Signal(),\n matrixChanged: new Signal(),\n statusChanged: new Signal(),\n nameChanged: new Signal(),\n disposed: new Signal()\n }\n\n readonly parameters: ComponentParameters\n get defaultParameters () { return ComponentDefaultParameters }\n\n readonly uuid: string\n readonly viewer: Viewer\n\n reprList: RepresentationElement[] = []\n annotationList: Annotation[] = []\n\n matrix = new Matrix4()\n position = new Vector3()\n quaternion = new Quaternion()\n scale = new Vector3(1, 1, 1)\n transform = new Matrix4()\n\n controls: ComponentControls\n\n /**\n * @param {Stage} stage - stage object the component belongs to\n * @param {ComponentParameters} params - parameter object\n */\n constructor (readonly stage: Stage, readonly object: any, params: Partial = {}) {\n this.parameters = createParams(params, this.defaultParameters)\n this.uuid = generateUUID()\n this.viewer = stage.viewer\n\n this.controls = new ComponentControls(this)\n }\n\n abstract get type (): string\n\n get name () { return this.parameters.name }\n get status () { return this.parameters.status }\n get visible () { return this.parameters.visible }\n\n /**\n * Set position transform\n *\n * @example\n * // translate by 25 angstrom along x axis\n * component.setPosition([ 25, 0, 0 ]);\n *\n * @param {Vector3|Array} p - the coordinates\n * @return {Component} this object\n */\n setPosition (p: [number, number, number]|Vector3) {\n if (Array.isArray(p)) {\n this.position.fromArray(p)\n } else {\n this.position.copy(p)\n }\n this.updateMatrix()\n\n return this\n }\n\n /**\n * Set local rotation transform\n * (for global rotation use setTransform)\n *\n * @example\n * // rotate by 2 degree radians on x axis\n * component.setRotation( [ 2, 0, 0 ] );\n *\n * @param {Quaternion|Euler|Array} r - the rotation\n * @return {Component} this object\n */\n setRotation (r: [number, number, number]|Euler|Quaternion) {\n if (Array.isArray(r)) {\n if (r.length === 3) {\n const e = new Euler().fromArray(r)\n this.quaternion.setFromEuler(e)\n } else {\n this.quaternion.fromArray(r)\n }\n } else if (r instanceof Euler) {\n this.quaternion.setFromEuler(r)\n } else {\n this.quaternion.copy(r)\n }\n this.updateMatrix()\n\n return this\n }\n\n /**\n * Set scale transform\n *\n * @example\n * // scale by factor of two\n * component.setScale( 2 );\n *\n * @param {Number} s - the scale\n * @return {Component} this object\n */\n setScale (s: number) {\n this.scale.set(s, s, s)\n this.updateMatrix()\n\n return this\n }\n\n /**\n * Set general transform. Is applied before and in addition\n * to the position, rotation and scale transformations\n *\n * @example\n * component.setTransform( matrix );\n *\n * @param {Matrix4} m - the matrix\n * @return {Component} this object\n */\n setTransform (m: Matrix4) {\n this.transform.copy(m)\n this.updateMatrix()\n\n return this\n }\n\n updateMatrix () {\n const c = this.getCenterUntransformed(_v)\n this.matrix.makeTranslation(-c.x, -c.y, -c.z)\n\n _m.makeRotationFromQuaternion(this.quaternion)\n this.matrix.premultiply(_m)\n\n _m.makeScale(this.scale.x, this.scale.y, this.scale.z)\n this.matrix.premultiply(_m)\n\n const p = this.position\n _m.makeTranslation(p.x + c.x, p.y + c.y, p.z + c.z)\n this.matrix.premultiply(_m)\n\n this.matrix.premultiply(this.transform)\n\n this.updateRepresentationMatrices()\n\n this.stage.viewer.updateBoundingBox()\n\n this.signals.matrixChanged.dispatch(this.matrix)\n }\n\n /**\n * Propogates our matrix to each representation\n */\n updateRepresentationMatrices () {\n this.reprList.forEach(repr => {\n repr.setParameters({ matrix: this.matrix })\n })\n }\n\n /**\n * Add an anotation object\n * @param {Vector3} position - the 3d position\n * @param {String|Element} content - the HTML content\n * @param {Object} [params] - parameters\n * @param {Integer} params.offsetX - 2d offset in x direction\n * @param {Integer} params.offsetY - 2d offset in y direction\n * @return {Annotation} the added annotation object\n */\n addAnnotation (position: Vector3, content: string|HTMLElement, params: AnnotationParams) {\n const annotation = new Annotation(this, position, content, params)\n this.annotationList.push(annotation)\n\n return annotation\n }\n\n /**\n * Iterator over each annotation and executing the callback\n * @param {Function} callback - function to execute\n * @return {undefined}\n */\n eachAnnotation (callback: (a: Annotation) => void) {\n this.annotationList.slice().forEach(callback)\n }\n\n /**\n * Remove the give annotation from the component\n * @param {Annotation} annotation - the annotation to remove\n * @return {undefined}\n */\n removeAnnotation (annotation: Annotation) {\n const idx = this.annotationList.indexOf(annotation)\n if (idx !== -1) {\n this.annotationList.splice(idx, 1)\n annotation.dispose()\n }\n }\n\n /**\n * Remove all annotations from the component\n * @return {undefined}\n */\n removeAllAnnotations () {\n this.eachAnnotation(annotation => annotation.dispose())\n this.annotationList.length = 0\n }\n\n /**\n * Add a new representation to the component\n * @param {String} type - the name of the representation\n * @param {Object} object - the object on which the representation should be based\n * @param {RepresentationParameters} [params] - representation parameters\n * @return {RepresentationElement} the created representation wrapped into\n * a representation element object\n */\n protected _addRepresentation (type: string, object: any, params: any, hidden = false) { // TODO\n const p = params || {}\n const sp = this.stage.getParameters() as any // TODO\n p.matrix = this.matrix.clone()\n p.quality = p.quality || sp.quality\n p.disableImpostor = defaults(p.disableImpostor, !sp.impostor)\n p.useWorker = defaults(p.useWorker, sp.workerDefault)\n p.visible = defaults(p.visible, true)\n\n const p2 = Object.assign({}, p, { visible: this.parameters.visible && p.visible })\n const repr = makeRepresentation(type, object, this.viewer, p2)\n const reprElem = new RepresentationElement(this.stage, repr, p, this)\n\n if (!hidden) {\n this.reprList.push(reprElem)\n this.signals.representationAdded.dispatch(reprElem)\n }\n return reprElem\n }\n\n abstract addRepresentation (type: any, params: any): any\n\n addBufferRepresentation (buffer: any, params: any) { // TODO\n return this._addRepresentation.call(this, 'buffer', buffer, params)\n }\n\n hasRepresentation (repr: RepresentationElement) {\n return this.reprList.indexOf(repr) !== -1\n }\n\n /**\n * Iterator over each representation and executing the callback\n * @param {Function} callback - function to execute\n * @return {undefined}\n */\n eachRepresentation (callback: (repr: RepresentationElement) => void) {\n this.reprList.slice().forEach(callback)\n }\n\n /**\n * Removes a representation component\n * @param {RepresentationElement} repr - the representation element\n * @return {undefined}\n */\n removeRepresentation (repr: RepresentationElement) {\n const idx = this.reprList.indexOf(repr)\n if (idx !== -1) {\n this.reprList.splice(idx, 1)\n repr.dispose()\n this.signals.representationRemoved.dispatch(repr)\n }\n }\n\n updateRepresentations (what: any) { // TODO\n this.reprList.forEach(repr => repr.update(what))\n this.stage.viewer.requestRender()\n }\n\n /**\n * Removes all representation components\n * @return {undefined}\n */\n removeAllRepresentations () {\n this.eachRepresentation(repr => repr.dispose())\n }\n\n dispose () {\n this.removeAllAnnotations()\n this.removeAllRepresentations()\n\n this.reprList.length = 0\n\n this.signals.disposed.dispatch()\n }\n\n /**\n * Set the visibility of the component, including added representations\n * @param {Boolean} value - visibility flag\n * @return {Component} this object\n */\n setVisibility (value: boolean) {\n this.parameters.visible = value\n\n this.eachRepresentation((repr: RepresentationElement) => repr.updateVisibility())\n this.eachAnnotation((annotation: Annotation) => annotation.updateVisibility())\n\n this.signals.visibilityChanged.dispatch(value)\n\n return this\n }\n\n setStatus (value: string) {\n this.parameters.status = value\n this.signals.statusChanged.dispatch(value)\n\n return this\n }\n\n setName (value: string) {\n this.parameters.name = value\n this.signals.nameChanged.dispatch(value)\n\n return this\n }\n\n /**\n * @return {Box3} the component's bounding box\n */\n getBox (...args: any[]) {\n return this.getBoxUntransformed(...args)\n .clone().applyMatrix4(this.matrix)\n }\n\n /**\n * @return {Vector3} the component's center position\n */\n getCenter (...args: any[]) {\n return this.getCenterUntransformed(...args)\n .clone().applyMatrix4(this.matrix)\n }\n\n getZoom (...args: any[]) {\n return this.stage.getZoomForBox(this.getBox(...args))\n }\n\n /**\n * @abstract\n * @return {Box3} the untransformed component's bounding box\n */\n getBoxUntransformed (...args: any[]): Box3 {\n return new Box3()\n }\n\n getCenterUntransformed (...args: any[]) {\n return this.getBoxUntransformed().getCenter(new Vector3())\n }\n\n /**\n * Automatically center and zoom the component\n * @param {Integer} [duration] - duration of the animation, defaults to 0\n * @return {undefined}\n */\n autoView (duration?: number) {\n this.stage.animationControls.zoomMove(\n this.getCenter(),\n this.getZoom(),\n defaults(duration, 0)\n )\n }\n}\n\nexport default Component\n","/**\n * @file Collection\n * @author Alexander Rose \n * @private\n */\n\nimport Component from './component'\nimport Element from './element'\n\nclass Collection {\n constructor (readonly list: T[] = []) {\n // remove elements from list when they get disposed\n const n = list.length\n\n for (let i = 0; i < n; ++i) {\n const elm = list[ i ]\n elm.signals.disposed.add(this._remove, this)\n }\n }\n\n _remove (elm: T) {\n const idx = this.list.indexOf(elm)\n\n if (idx !== -1) {\n this.list.splice(idx, 1)\n }\n }\n\n get first () {\n return this.list.length > 0 ? this.list[0] : undefined\n }\n\n forEach (fn: (x: T) => any) {\n this.list.forEach(fn)\n\n return this\n }\n\n dispose () {\n return this.forEach((elm) => elm.dispose())\n }\n}\n\nexport default Collection\n","/**\n * @file Component Collection\n * @author Alexander Rose \n * @private\n */\n\nimport RepresentationElement from './representation-element'\nimport Collection from './collection'\nimport { GenericColor } from '../types'\n\nclass RepresentationCollection extends Collection {\n setParameters (params: any) {\n return this.forEach((repr) => repr.setParameters(params))\n }\n\n setVisibility (value: boolean) {\n return this.forEach((repr) => repr.setVisibility(value))\n }\n\n setSelection (string: string) {\n return this.forEach((repr) => repr.setSelection(string))\n }\n\n setColor (color: GenericColor) {\n return this.forEach((repr) => repr.setColor(color))\n }\n\n update (what: any) {\n return this.forEach((repr) => repr.update(what))\n }\n\n build (params?: any) {\n return this.forEach((repr) => repr.build(params))\n }\n\n dispose (params?: any) {\n return this.forEach((repr) => repr.dispose())\n }\n}\n\nexport default RepresentationCollection\n","/**\n * @file Trajectory Component\n * @author Alexander Rose \n * @private\n */\n\nimport { Signal } from 'signals'\n\nimport Element, { ElementSignals, ElementDefaultParameters } from './element'\nimport Stage from '../stage/stage'\nimport Trajectory, { TrajectoryParameters } from '../trajectory/trajectory'\nimport TrajectoryPlayer, {\n TrajectoryPlayerDirection, TrajectoryPlayerMode, TrajectoryPlayerInterpolateType\n} from '../trajectory/trajectory-player'\n\n/**\n * Trajectory component parameter object.\n * @typedef {Object} TrajectoryComponentParameters - component parameters\n *\n * @property {String} name - component name\n * @property {Integer} initialFrame - initial frame the trajectory is set to\n * @property {Integer} defaultStep - default step size to be used by trajectory players\n * @property {Integer} defaultTimeout - default timeout to be used by trajectory players\n * @property {String} defaultInterpolateType - one of \"\" (empty string), \"linear\" or \"spline\"\n * @property {Integer} defaultInterpolateStep - window size used for interpolation\n * @property {String} defaultMode - either \"loop\" or \"once\"\n * @property {String} defaultDirection - either \"forward\" or \"backward\"\n */\n\nexport const TrajectoryElementDefaultParameters = Object.assign({\n defaultStep: 1,\n defaultTimeout: 50,\n defaultInterpolateType: '' as TrajectoryPlayerInterpolateType,\n defaultInterpolateStep: 5,\n defaultMode: 'loop' as TrajectoryPlayerMode,\n defaultDirection: 'forward' as TrajectoryPlayerDirection,\n initialFrame: 0\n}, ElementDefaultParameters)\nexport type TrajectoryElementParameters = typeof TrajectoryElementDefaultParameters\n\nexport interface TrajectoryElementSignals extends ElementSignals {\n frameChanged: Signal // on frame change\n playerChanged: Signal // on player change\n countChanged: Signal // when frame count is available\n parametersChanged: Signal // on parameters change\n}\n\n/**\n * Component wrapping a {@link Trajectory} object\n */\nclass TrajectoryElement extends Element {\n signals: TrajectoryElementSignals\n parameters: TrajectoryElementParameters\n get defaultParameters () { return TrajectoryElementDefaultParameters }\n\n /**\n * @param {Stage} stage - stage object the component belongs to\n * @param {Trajectory} trajectory - the trajectory object\n * @param {TrajectoryComponentParameters} params - component parameters\n * @param {StructureComponent} parent - the parent structure\n */\n constructor (stage: Stage, readonly trajectory: Trajectory, params: Partial = {}) {\n super(stage, Object.assign({ name: trajectory.name }, params))\n\n this.signals = Object.assign(this.signals, {\n frameChanged: new Signal(),\n playerChanged: new Signal(),\n countChanged: new Signal(),\n parametersChanged: new Signal()\n })\n\n // signals\n\n trajectory.signals.frameChanged.add((i: number) => {\n this.signals.frameChanged.dispatch(i)\n })\n\n trajectory.signals.playerChanged.add((player: TrajectoryPlayer) => {\n this.signals.playerChanged.dispatch(player)\n })\n\n trajectory.signals.countChanged.add((n: number) => {\n this.signals.countChanged.dispatch(n)\n })\n\n //\n\n if (params.initialFrame !== undefined) {\n this.setFrame(params.initialFrame)\n }\n }\n\n /**\n * Component type\n * @type {String}\n */\n get type () { return 'trajectory' }\n\n /**\n * Set the frame of the trajectory\n * @param {Integer} i - frame number\n * @return {undefined}\n */\n setFrame (i: number) {\n this.trajectory.setFrame(i)\n }\n\n /**\n * Set trajectory parameters\n * @param {TrajectoryParameters} params - trajectory parameters\n * @return {undefined}\n */\n setParameters (params: Partial = {}) {\n this.trajectory.setParameters(params)\n this.signals.parametersChanged.dispatch(params)\n }\n\n dispose () {\n this.trajectory.dispose()\n super.dispose()\n }\n}\n\nexport default TrajectoryElement\n","/**\n * @file Frames\n * @author Alexander Rose \n * @private\n */\n\nexport default class Frames {\n coordinates = []\n boxes = []\n times = []\n\n timeOffset = 0\n deltaTime = 1\n\n constructor (readonly name: string, readonly path: string) {}\n\n get type () { return 'Frames' }\n}\n","/**\n * @file Superposition\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4 } from 'three'\nimport { Debug, Log } from '../globals'\nimport {\n Matrix, svd, meanRows, subRows, transpose,\n multiplyABt, invert3x3, multiply3x3, mat3x3determinant, multiply\n} from '../math/matrix-utils'\nimport Structure from '../structure/structure'\n\nclass Superposition {\n coords1t: Matrix\n coords2t: Matrix\n\n transformationMatrix: Matrix4\n\n mean1: number[]\n mean2: number[]\n\n A = new Matrix(3, 3)\n W = new Matrix(1, 3)\n U = new Matrix(3, 3)\n V = new Matrix(3, 3)\n VH = new Matrix(3, 3)\n R = new Matrix(3, 3)\n\n private tmp = new Matrix(3, 3)\n private c = new Matrix(3, 3)\n\n constructor (atoms1: Structure|Float32Array, atoms2: Structure|Float32Array) {\n // allocate & init data structures\n\n let n1\n if (atoms1 instanceof Structure) {\n n1 = atoms1.atomCount\n } else if (atoms1 instanceof Float32Array) {\n n1 = atoms1.length / 3\n } else {\n return\n }\n\n let n2\n if (atoms2 instanceof Structure) {\n n2 = atoms2.atomCount\n } else if (atoms2 instanceof Float32Array) {\n n2 = atoms2.length / 3\n } else {\n return\n }\n\n const n = Math.min(n1, n2)\n\n const coords1 = new Matrix(3, n)\n const coords2 = new Matrix(3, n)\n\n this.coords1t = new Matrix(n, 3)\n this.coords2t = new Matrix(n, 3)\n\n this.transformationMatrix = new Matrix4()\n\n this.c.data.set([ 1, 0, 0, 0, 1, 0, 0, 0, -1 ])\n\n // prep coords\n\n this.prepCoords(atoms1, coords1, n, false)\n this.prepCoords(atoms2, coords2, n, false)\n\n // superpose\n\n this._superpose(coords1, coords2)\n }\n\n _superpose (coords1: Matrix, coords2: Matrix) {\n this.mean1 = meanRows(coords1)\n this.mean2 = meanRows(coords2)\n\n subRows(coords1, this.mean1)\n subRows(coords2, this.mean2)\n\n transpose(this.coords1t, coords1)\n transpose(this.coords2t, coords2)\n\n multiplyABt(this.A, this.coords2t, this.coords1t)\n\n svd(this.A, this.W, this.U, this.V)\n\n invert3x3(this.V, this.VH)\n multiply3x3(this.R, this.U, this.VH)\n\n if (mat3x3determinant(this.R) < 0.0) {\n if (Debug) Log.log('R not a right handed system')\n\n multiply3x3(this.tmp, this.c, this.VH)\n multiply3x3(this.R, this.U, this.tmp)\n }\n\n //get the transformation matrix\n\n const transformMat_ = new Matrix(4,4)\n const tmp_1 = new Matrix(4,4)\n const tmp_2 = new Matrix(4,4)\n\n const sub = new Matrix(4,4)\n const mult = new Matrix(4,4)\n const add = new Matrix(4,4)\n\n const R = this.R.data\n const M1 = this.mean1\n const M2 = this.mean2\n\n sub.data.set([ 1, 0, 0, -M1[0],\n 0, 1, 0, -M1[1],\n 0, 0, 1, -M1[2],\n 0, 0, 0, 1 ])\n\n mult.data.set([ R[0], R[1], R[2], 0,\n R[3], R[4], R[5], 0,\n R[6], R[7], R[8], 0,\n 0, 0, 0, 1 ])\n\n add.data.set([ 1, 0, 0, M2[0],\n 0, 1, 0, M2[1],\n 0, 0, 1, M2[2],\n 0, 0, 0, 1 ])\n\n transpose(tmp_1,sub)\n multiplyABt(transformMat_,mult,tmp_1)\n transpose(tmp_2,transformMat_)\n multiplyABt(tmp_1,add,tmp_2)\n\n transpose(transformMat_,tmp_1)\n this.transformationMatrix.elements = transformMat_.data as unknown as number[]\n\n }\n\n prepCoords (atoms: Structure|Float32Array, coords: Matrix, n: number, is4X4: boolean) {\n let i = 0\n const cd = coords.data\n\n let c = 3\n let d = n * 3\n\n if (is4X4) {\n d = n * 4\n c = 4\n }\n if (atoms instanceof Structure) {\n atoms.eachAtom(function (a) {\n if (i < d) {\n cd[ i + 0 ] = a.x\n cd[ i + 1 ] = a.y\n cd[ i + 2 ] = a.z\n if (is4X4) cd[ i + 3 ] = 1\n\n i += c\n }\n })\n } else if (atoms instanceof Float32Array) {\n for (; i < d; i += c){\n if (i < d) {\n cd[ i ] = atoms[ i ]\n cd[ i + 1 ] = atoms[ i + 1 ]\n cd[ i + 2 ] = atoms[ i + 2 ]\n if (is4X4) cd[ i + 3 ] = 1\n }\n }\n } else {\n Log.warn('prepCoords: input type unknown')\n }\n }\n\n transform (atoms: Structure|Float32Array) {\n // allocate data structures\n\n let n\n if (atoms instanceof Structure) {\n n = atoms.atomCount\n } else if (atoms instanceof Float32Array) {\n n = atoms.length / 3\n } else {\n return\n }\n\n const coords = new Matrix(4, n)\n const tCoords = new Matrix(n,4)\n\n // prep coords\n\n this.prepCoords(atoms, coords, n, true)\n\n // check for transformation matrix correctness\n\n const transform = this.transformationMatrix\n const det = transform.determinant()\n if (!det){\n return det\n }\n\n // do transform\n\n const mult = new Matrix(4,4)\n mult.data = transform.elements as unknown as Float32Array\n multiply(tCoords,coords,mult)\n\n let i = 0\n const cd = tCoords.data\n if (atoms instanceof Structure) {\n atoms.eachAtom(function (a) {\n a.x = cd[ i ]\n a.y = cd[ i + 1 ]\n a.z = cd[ i + 2 ]\n i += 4\n })\n\n //update transformation matrices for each assembly\n\n const invertTrasform = new Matrix4()\n invertTrasform.getInverse(transform)\n\n const biomolDict = atoms.biomolDict\n\n for (let key in biomolDict) {\n\n if (biomolDict.hasOwnProperty(key)) {\n let assembly = biomolDict[key]\n\n assembly.partList.forEach(function(part){\n\n part.matrixList.forEach(function(mat){\n\n mat.premultiply(transform)\n mat.multiply(invertTrasform)\n\n })\n })\n }\n }\n } else if (atoms instanceof Float32Array) {\n\n const n4 = n * 4\n for (; i < n4; i += 4){\n\n atoms[ i ] = cd[ i ]\n atoms[ i + 1 ] = cd[ i + 1 ]\n atoms[ i + 2 ] = cd[ i + 2 ]\n\n }\n } else {\n Log.warn('transform: input type unknown')\n }\n\n return this.transformationMatrix\n }\n}\nexport default Superposition\n","/**\n * @file Trajectory Player\n * @author Alexander Rose \n * @private\n */\n\nimport { Signal } from 'signals'\n\nimport { defaults, createParams, updateParams } from '../utils'\nimport Trajectory from './trajectory'\n\nexport type TrajectoryPlayerInterpolateType = ''|'linear'|'spline'\nexport type TrajectoryPlayerMode = 'loop'|'once'\nexport type TrajectoryPlayerDirection = 'forward'|'backward'|'bounce'\n\nexport const TrajectoryPlayerDefaultParameters = {\n step: 1, // how many frames to advance when playing\n timeout: 50, // how many milliseconds to wait between playing frames\n start: 0, // first frame to play\n end: 0, // last frame to play\n interpolateType: '' as TrajectoryPlayerInterpolateType,\n interpolateStep: 5, // window size used for interpolation\n mode: 'loop' as TrajectoryPlayerMode,\n direction: 'forward' as TrajectoryPlayerDirection\n}\nexport type TrajectoryPlayerParameters = typeof TrajectoryPlayerDefaultParameters\n\nexport interface TrajectoryPlayerSignals {\n startedRunning: Signal\n haltedRunning: Signal\n}\n\n/**\n * Trajectory player for animating coordinate frames\n * @example\n * var player = new TrajectoryPlayer(trajectory, {step: 1, timeout: 50});\n * player.play();\n */\nclass TrajectoryPlayer {\n signals: TrajectoryPlayerSignals = {\n startedRunning: new Signal(),\n haltedRunning: new Signal()\n }\n\n parameters: TrajectoryPlayerParameters\n traj: Trajectory\n\n private _run = false\n private _previousTime = 0\n private _currentTime = 0\n private _currentStep = 1\n private _currentFrame: number|[number, number, number, number]\n private _direction: TrajectoryPlayerDirection\n\n /**\n * make trajectory player\n * @param {Trajectory} traj - the trajectory\n * @param {TrajectoryPlayerParameters} [params] - parameter object\n */\n constructor (traj: Trajectory, params: Partial = {}) {\n traj.signals.playerChanged.add((player: TrajectoryPlayer) => {\n if (player !== this) {\n this.pause()\n }\n }, this)\n\n const n = defaults(traj.frameCount, 1)\n\n this.traj = traj\n this.parameters = createParams(params, TrajectoryPlayerDefaultParameters)\n this.parameters.end = Math.min(defaults(params.end, n - 1), n - 1)\n this.parameters.step = defaults(params.step, Math.ceil((n + 1) / 100))\n\n this._currentFrame = this.parameters.start\n this._direction = this.parameters.direction === 'bounce' ? 'forward' : this.parameters.direction\n\n traj.signals.countChanged.add((n: number) => {\n this.parameters.end = Math.min(defaults(this.parameters.end, n - 1), n - 1)\n }, this)\n\n this._animate = this._animate.bind(this)\n }\n\n get isRunning () { return this._run }\n\n /**\n * set player parameters\n * @param {TrajectoryPlayerParameters} [params] - parameter object\n */\n setParameters (params: Partial = {}) {\n updateParams(this.parameters, params)\n\n if (params.direction !== undefined && this.parameters.direction !== 'bounce') {\n this._direction = this.parameters.direction\n }\n }\n\n _animate () {\n if (!this._run) return\n\n this._currentTime = window.performance.now()\n const dt = this._currentTime - this._previousTime\n const step = this.parameters.interpolateType ? this.parameters.interpolateStep : 1\n const timeout = this.parameters.timeout / step\n const traj = this.traj\n\n if (traj && traj.frameCount && !traj.inProgress && dt >= timeout) {\n if (this.parameters.interpolateType) {\n if (this._currentStep > this.parameters.interpolateStep) {\n this._currentStep = 1\n }\n if (this._currentStep === 1) {\n this._currentFrame = this._nextInterpolated()\n }\n if (traj.hasFrame(this._currentFrame)) {\n this._currentStep += 1\n const t = this._currentStep / (this.parameters.interpolateStep + 1)\n const [i, ip, ipp, ippp] = this._currentFrame as [number, number, number, number]\n traj.setFrameInterpolated(\n i, ip, ipp, ippp, t, this.parameters.interpolateType\n )\n this._previousTime = this._currentTime\n } else {\n traj.loadFrame(this._currentFrame)\n }\n } else {\n const i = this._next()\n if (traj.hasFrame(i)) {\n traj.setFrame(i)\n this._previousTime = this._currentTime\n } else {\n traj.loadFrame(i)\n }\n }\n }\n\n window.requestAnimationFrame(this._animate)\n }\n\n _next () {\n const p = this.parameters\n let i\n\n if (this._direction === 'forward') {\n i = this.traj.currentFrame + p.step\n } else {\n i = this.traj.currentFrame - p.step\n }\n\n if (i > p.end || i < p.start) {\n if (p.direction === 'bounce') {\n if (this._direction === 'forward') {\n this._direction = 'backward'\n } else {\n this._direction = 'forward'\n }\n }\n\n if (p.mode === 'once') {\n this.pause()\n\n if (p.direction === 'forward') {\n i = p.end\n } else if (p.direction === 'backward') {\n i = p.start\n } else {\n if (this._direction === 'forward') {\n i = p.start\n } else {\n i = p.end\n }\n }\n } else {\n if (this._direction === 'forward') {\n i = p.start\n if (p.interpolateType) {\n i = Math.min(p.end, i + p.step)\n }\n } else {\n i = p.end\n if (p.interpolateType) {\n i = Math.max(p.start, i - p.step)\n }\n }\n }\n }\n\n return i\n }\n\n _nextInterpolated () {\n const p = this.parameters\n const i = this._next()\n let ip, ipp, ippp\n\n if (this._direction === 'forward') {\n ip = Math.max(p.start, i - p.step)\n ipp = Math.max(p.start, i - 2 * p.step)\n ippp = Math.max(p.start, i - 3 * p.step)\n } else {\n ip = Math.min(p.end, i + p.step)\n ipp = Math.min(p.end, i + 2 * p.step)\n ippp = Math.min(p.end, i + 3 * p.step)\n }\n\n return [i, ip, ipp, ippp] as [number, number, number, number]\n }\n\n /**\n * toggle between playing and pausing the animation\n * @return {undefined}\n */\n toggle () {\n if (this._run) {\n this.pause()\n } else {\n this.play()\n }\n }\n\n /**\n * start the animation\n * @return {undefined}\n */\n play () {\n if (!this._run) {\n if (this.traj.player !== this) {\n this.traj.setPlayer(this)\n }\n this._currentStep = 1\n\n const p = this.parameters\n const frame = this.traj.currentFrame\n\n // snap to the grid implied by this.step division and multiplication\n // thus minimizing cache misses\n let i = Math.ceil(frame / p.step) * p.step\n // wrap when restarting from the limit (i.e. end or start)\n if (p.direction === 'forward' && frame >= p.end) {\n i = p.start\n } else if (p.direction === 'backward' && frame <= p.start) {\n i = p.end\n }\n\n this.traj.setFrame(i)\n\n this._run = true\n this._animate()\n this.signals.startedRunning.dispatch()\n }\n }\n\n /**\n * pause the animation\n * @return {undefined}\n */\n pause () {\n this._run = false\n this.signals.haltedRunning.dispatch()\n }\n\n /**\n * stop the animation (pause and go to start-frame)\n * @return {undefined}\n */\n stop () {\n this.pause()\n this.traj.setFrame(this.parameters.start)\n }\n}\n\nexport default TrajectoryPlayer\n","/**\n * @file Trajectory\n * @author Alexander Rose \n * @private\n */\n\nimport { Signal } from 'signals'\n\nimport { Log } from '../globals'\nimport { defaults } from '../utils'\nimport { NumberArray } from '../types'\nimport { circularMean, arrayMean } from '../math/array-utils'\nimport { lerp, spline } from '../math/math-utils'\nimport Selection from '../selection/selection'\nimport Superposition from '../align/superposition'\nimport Structure from '../structure/structure'\nimport AtomProxy from '../proxy/atom-proxy'\nimport TrajectoryPlayer, { TrajectoryPlayerInterpolateType } from './trajectory-player'\n\n\nfunction centerPbc (coords: NumberArray, mean: number[], box: ArrayLike) {\n if (box[ 0 ] === 0 || box[ 8 ] === 0 || box[ 4 ] === 0) {\n return\n }\n\n const n = coords.length\n\n const bx = box[ 0 ]\n const by = box[ 1 ]\n const bz = box[ 2 ]\n const mx = mean[ 0 ]\n const my = mean[ 1 ]\n const mz = mean[ 2 ]\n\n const fx = -mx + bx + bx / 2\n const fy = -my + by + by / 2\n const fz = -mz + bz + bz / 2\n\n for (let i = 0; i < n; i += 3) {\n coords[ i + 0 ] = (coords[ i + 0 ] + fx) % bx\n coords[ i + 1 ] = (coords[ i + 1 ] + fy) % by\n coords[ i + 2 ] = (coords[ i + 2 ] + fz) % bz\n }\n}\n\nfunction removePbc (x: NumberArray, box: ArrayLike) {\n if (box[ 0 ] === 0 || box[ 8 ] === 0 || box[ 4 ] === 0) {\n return\n }\n\n // ported from GROMACS src/gmxlib/rmpbc.c:rm_gropbc()\n // in-place\n\n const n = x.length\n\n for (let i = 3; i < n; i += 3) {\n for (let j = 0; j < 3; ++j) {\n const dist = x[ i + j ] - x[ i - 3 + j ]\n\n if (Math.abs(dist) > 0.9 * box[ j * 3 + j ]) {\n if (dist > 0) {\n for (let d = 0; d < 3; ++d) {\n x[ i + d ] -= box[ j * 3 + d ]\n }\n } else {\n for (let d = 0; d < 3; ++d) {\n x[ i + d ] += box[ j * 3 + d ]\n }\n }\n }\n }\n }\n\n return x\n}\n\nfunction removePeriodicity (x: NumberArray, box: ArrayLike, mean: number[]) {\n if (box[ 0 ] === 0 || box[ 8 ] === 0 || box[ 4 ] === 0) {\n return\n }\n\n const n = x.length\n for (let i = 3; i < n; i += 3) {\n for (let j = 0; j < 3; ++j) {\n const f = (x[ i + j ] - mean[ j ]) / box[ j * 3 + j ]\n if (Math.abs(f) > 0.5) {\n x[ i + j ] -= box[ j * 3 + j ] * Math.round(f)\n }\n }\n }\n\n return x\n}\n\nfunction circularMean3 (indices: NumberArray, coords: NumberArray, box: ArrayLike) {\n return [\n circularMean(coords, box[ 0 ], 3, 0, indices),\n circularMean(coords, box[ 1 ], 3, 1, indices),\n circularMean(coords, box[ 2 ], 3, 2, indices)\n ]\n}\n\nfunction arrayMean3 (coords: NumberArray) {\n return [\n arrayMean(coords, 3, 0),\n arrayMean(coords, 3, 1),\n arrayMean(coords, 3, 2)\n ]\n}\n\nfunction interpolateSpline (c: NumberArray, cp: NumberArray, cpp: NumberArray, cppp: NumberArray, t: number) {\n const m = c.length\n const coords = new Float32Array(m)\n\n for (let j0 = 0; j0 < m; j0 += 3) {\n const j1 = j0 + 1\n const j2 = j0 + 2\n coords[ j0 ] = spline(cppp[ j0 ], cpp[ j0 ], cp[ j0 ], c[ j0 ], t, 1)\n coords[ j1 ] = spline(cppp[ j1 ], cpp[ j1 ], cp[ j1 ], c[ j1 ], t, 1)\n coords[ j2 ] = spline(cppp[ j2 ], cpp[ j2 ], cp[ j2 ], c[ j2 ], t, 1)\n }\n\n return coords\n}\n\nfunction interpolateLerp (c: NumberArray, cp: NumberArray, t: number) {\n const m = c.length\n const coords = new Float32Array(m)\n\n for (let j0 = 0; j0 < m; j0 += 3) {\n const j1 = j0 + 1\n const j2 = j0 + 2\n coords[ j0 ] = lerp(cp[ j0 ], c[ j0 ], t)\n coords[ j1 ] = lerp(cp[ j1 ], c[ j1 ], t)\n coords[ j2 ] = lerp(cp[ j2 ], c[ j2 ], t)\n }\n\n return coords\n}\n\n/**\n * Trajectory parameter object.\n * @typedef {Object} TrajectoryParameters - parameters\n *\n * @property {Number} deltaTime - timestep between frames in picoseconds\n * @property {Number} timeOffset - starting time of frames in picoseconds\n * @property {String} sele - to restrict atoms used for superposition\n * @property {Boolean} centerPbc - center on initial frame\n * @property {Boolean} removePeriodicity - move atoms into the origin box\n * @property {Boolean} remo - try fixing periodic boundary discontinuities\n * @property {Boolean} superpose - superpose on initial frame\n */\n\n/**\n * @example\n * trajectory.signals.frameChanged.add( function(i){ ... } );\n *\n * @typedef {Object} TrajectorySignals\n * @property {Signal} countChanged - when the frame count is changed\n * @property {Signal} frameChanged - when the set frame is changed\n * @property {Signal} playerChanged - when the player is changed\n */\n\nexport interface TrajectoryParameters {\n deltaTime: number // timestep between frames in picoseconds\n timeOffset: number // starting time of frames in picoseconds\n sele: string // to restrict atoms used for superposition\n centerPbc: boolean // center on initial frame\n removePbc: boolean // move atoms into the origin box\n removePeriodicity: boolean // try fixing periodic boundary discontinuities\n superpose: boolean // superpose on initial frame\n}\n\nexport interface TrajectorySignals {\n countChanged: Signal\n frameChanged: Signal\n playerChanged: Signal\n}\n\n/**\n * Base class for trajectories, tying structures and coordinates together\n * @interface\n */\nclass Trajectory {\n signals: TrajectorySignals = {\n countChanged: new Signal(),\n frameChanged: new Signal(),\n playerChanged: new Signal()\n }\n\n deltaTime: number\n timeOffset: number\n sele: string\n centerPbc: boolean\n removePbc: boolean\n removePeriodicity: boolean\n superpose: boolean\n\n name: string\n frame: number\n trajPath: string\n\n initialCoords: Float32Array\n structureCoords: Float32Array\n selectionIndices: NumberArray\n backboneIndices: NumberArray\n\n coords1: Float32Array\n coords2: Float32Array\n\n frameCache: { [k: number]: Float32Array } = {}\n loadQueue: { [k: number]: boolean } = {}\n boxCache: { [k: number]: ArrayLike } = {}\n pathCache = {}\n frameCacheSize = 0\n\n atomCount: number\n inProgress: boolean\n\n selection: Selection // selection to restrict atoms used for superposition\n structure: Structure\n player: TrajectoryPlayer\n\n private _frameCount = 0\n private _currentFrame = -1\n private _disposed = false\n\n /**\n * @param {String} trajPath - trajectory source\n * @param {Structure} structure - the structure object\n * @param {TrajectoryParameters} params - trajectory parameters\n */\n constructor (trajPath: string, structure: Structure, params: Partial = {}) {\n this.deltaTime = defaults(params.deltaTime, 0)\n this.timeOffset = defaults(params.timeOffset, 0)\n this.centerPbc = defaults(params.centerPbc, false)\n this.removePbc = defaults(params.removePbc, false)\n this.removePeriodicity = defaults(params.removePeriodicity, false)\n this.superpose = defaults(params.superpose, false)\n\n this.name = trajPath.replace(/^.*[\\\\/]/, '')\n this.trajPath = trajPath\n\n this.selection = new Selection(\n defaults(params.sele, 'backbone and not hydrogen')\n )\n\n this.selection.signals.stringChanged.add(() => {\n this.selectionIndices = this.structure.getAtomIndices(this.selection)!\n this._resetCache()\n this._saveInitialCoords()\n this.setFrame(this._currentFrame)\n })\n }\n\n /**\n * Number of frames in the trajectory\n */\n get frameCount () {\n return this._frameCount\n }\n\n /**\n * Currently set frame of the trajectory\n */\n get currentFrame () {\n return this._currentFrame\n }\n\n _init (structure: Structure) {\n this.setStructure(structure)\n this._loadFrameCount()\n this.setPlayer(new TrajectoryPlayer(this))\n }\n\n _loadFrameCount () {}\n\n setStructure (structure: Structure) {\n this.structure = structure\n this.atomCount = structure.atomCount\n\n this.backboneIndices = this._getIndices(\n new Selection('backbone and not hydrogen')\n )\n this._makeAtomIndices()\n this._saveStructureCoords()\n\n this.selectionIndices = this._getIndices(this.selection)\n this._resetCache()\n this._saveInitialCoords()\n this.setFrame(this._currentFrame)\n }\n\n _saveInitialCoords () {\n if (this.structure.hasCoords()) {\n this.initialCoords = new Float32Array(this.structureCoords)\n this._makeSuperposeCoords()\n } else if (this.frameCache[0]) {\n this.initialCoords = new Float32Array(this.frameCache[0])\n this._makeSuperposeCoords()\n } else {\n this.loadFrame(0, () => this._saveInitialCoords())\n }\n }\n\n _saveStructureCoords () {\n const p = { what: { position: true } }\n this.structureCoords = this.structure.getAtomData(p).position!\n }\n\n setSelection (string: string) {\n this.selection.setString(string)\n return this\n }\n\n _getIndices (selection: Selection) {\n let i = 0\n const test = selection.test\n const indices: number[] = []\n\n if (test) {\n this.structure.eachAtom((ap: AtomProxy) => {\n if (test(ap)) indices.push(i)\n i += 1\n })\n }\n\n return indices\n }\n\n _makeSuperposeCoords () {\n const n = this.selectionIndices.length * 3\n\n this.coords1 = new Float32Array(n)\n this.coords2 = new Float32Array(n)\n\n const y = this.initialCoords\n const coords2 = this.coords2\n\n for (let i = 0; i < n; i += 3) {\n const j = this.selectionIndices[ i / 3 ] * 3\n\n coords2[ i + 0 ] = y[ j + 0 ]\n coords2[ i + 1 ] = y[ j + 1 ]\n coords2[ i + 2 ] = y[ j + 2 ]\n }\n }\n\n _makeAtomIndices () {\n Log.error('Trajectory._makeAtomIndices not implemented')\n }\n\n _resetCache () {\n this.frameCache = {}\n this.loadQueue = {}\n this.boxCache = {}\n this.pathCache = {}\n this.frameCacheSize = 0\n this.initialCoords = new Float32Array(0)\n }\n\n setParameters (params: Partial = {}) {\n let resetCache = false\n\n if (params.centerPbc !== undefined && params.centerPbc !== this.centerPbc) {\n this.centerPbc = params.centerPbc\n resetCache = true\n }\n\n if (params.removePeriodicity !== undefined && params.removePeriodicity !== this.removePeriodicity) {\n this.removePeriodicity = params.removePeriodicity\n resetCache = true\n }\n\n if (params.removePbc !== undefined && params.removePbc !== this.removePbc) {\n this.removePbc = params.removePbc\n resetCache = true\n }\n\n if (params.superpose !== undefined && params.superpose !== this.superpose) {\n this.superpose = params.superpose\n resetCache = true\n }\n\n this.deltaTime = defaults(params.deltaTime, this.deltaTime)\n this.timeOffset = defaults(params.timeOffset, this.timeOffset)\n\n if (resetCache) {\n this._resetCache()\n this.setFrame(this._currentFrame)\n }\n }\n\n /**\n * Check if a frame is available\n * @param {Integer|Integer[]} i - the frame index\n * @return {Boolean} frame availability\n */\n hasFrame (i: number|number[]) {\n if (Array.isArray(i)) {\n return i.every(j => !!this.frameCache[j])\n } else {\n return !!this.frameCache[i]\n }\n }\n\n /**\n * Set trajectory to a frame index\n * @param {Integer} i - the frame index\n * @param {Function} [callback] - fired when the frame has been set\n */\n setFrame (i: number, callback?: Function) {\n if (i === undefined) return this\n\n this.inProgress = true\n\n // i = parseInt(i) // TODO\n\n if (i === -1 || this.frameCache[ i ]) {\n this._updateStructure(i)\n if (callback) callback()\n } else {\n this.loadFrame(i, () => {\n this._updateStructure(i)\n if (callback) callback()\n })\n }\n\n return this\n }\n\n _interpolate (i: number, ip: number, ipp: number, ippp: number, t: number, type: TrajectoryPlayerInterpolateType) {\n const fc = this.frameCache\n\n let coords\n if (type === 'spline') {\n coords = interpolateSpline(fc[ i ], fc[ ip ], fc[ ipp ], fc[ ippp ], t)\n } else {\n coords = interpolateLerp(fc[ i ], fc[ ip ], t)\n }\n\n this.structure.updatePosition(coords)\n this._currentFrame = i\n this.signals.frameChanged.dispatch(i)\n }\n\n /**\n * Interpolated and set trajectory to frame indices\n * @param {Integer} i - the frame index\n * @param {Integer} ip - one before frame index\n * @param {Integer} ipp - two before frame index\n * @param {Integer} ippp - three before frame index\n * @param {Number} t - interpolation step [0,1]\n * @param {String} type - interpolation type, '', 'spline' or 'linear'\n * @param {Function} callback - fired when the frame has been set\n */\n setFrameInterpolated (i: number, ip: number, ipp: number, ippp: number, t: number, type: TrajectoryPlayerInterpolateType, callback?: Function) {\n if (i === undefined) return this\n\n const fc = this.frameCache\n const iList: number[] = []\n\n if (!fc[ ippp ]) iList.push(ippp)\n if (!fc[ ipp ]) iList.push(ipp)\n if (!fc[ ip ]) iList.push(ip)\n if (!fc[ i ]) iList.push(i)\n\n if (iList.length) {\n this.loadFrame(iList, () => {\n this._interpolate(i, ip, ipp, ippp, t, type)\n if (callback) callback()\n })\n } else {\n this._interpolate(i, ip, ipp, ippp, t, type)\n if (callback) callback()\n }\n\n return this\n }\n\n /**\n * Load frame index\n * @param {Integer|Integer[]} i - the frame index\n * @param {Function} callback - fired when the frame has been loaded\n */\n loadFrame (i: number|number[], callback?: Function) {\n if (Array.isArray(i)) {\n i.forEach(j => {\n if (!this.loadQueue[j] && !this.frameCache[j]) {\n this.loadQueue[j] = true\n this._loadFrame(j, () => {\n delete this.loadQueue[j]\n })\n }\n })\n } else {\n if (!this.loadQueue[i] && !this.frameCache[i]) {\n this.loadQueue[i] = true\n this._loadFrame(i, () => {\n delete this.loadQueue[i]\n if (callback) callback()\n })\n }\n }\n }\n\n /**\n * Load frame index\n * @abstract\n * @param {Integer} i - the frame index\n * @param {Function} callback - fired when the frame has been loaded\n */\n _loadFrame (i: number, callback?: Function) {\n Log.error('Trajectory._loadFrame not implemented', i, callback)\n }\n\n _updateStructure (i: number) {\n if (this._disposed) {\n console.error('updateStructure: traj disposed')\n return\n }\n\n if (i === -1) {\n if (this.structureCoords) {\n this.structure.updatePosition(this.structureCoords)\n }\n } else {\n this.structure.updatePosition(this.frameCache[ i ])\n }\n\n this.structure.trajectory = {\n name: this.trajPath,\n frame: i\n }\n\n this._currentFrame = i\n this.inProgress = false\n this.signals.frameChanged.dispatch(i)\n }\n\n _doSuperpose (x: Float32Array) {\n const n = this.selectionIndices.length * 3\n\n const coords1 = this.coords1\n const coords2 = this.coords2\n\n for (let i = 0; i < n; i += 3) {\n const j = this.selectionIndices[ i / 3 ] * 3\n\n coords1[ i + 0 ] = x[ j + 0 ]\n coords1[ i + 1 ] = x[ j + 1 ]\n coords1[ i + 2 ] = x[ j + 2 ]\n }\n\n // TODO re-use superposition object\n const sp = new Superposition(coords1, coords2)\n sp.transform(x)\n }\n\n _process (i: number, box: ArrayLike, coords: Float32Array, frameCount: number) {\n this._setFrameCount(frameCount)\n\n if (box) {\n if (this.backboneIndices.length > 0 && this.centerPbc) {\n const box2 = [ box[ 0 ], box[ 4 ], box[ 8 ] ]\n const circMean = circularMean3(this.backboneIndices, coords, box2)\n centerPbc(coords, circMean, box2)\n }\n\n if (this.removePeriodicity) {\n const mean = arrayMean3(coords)\n removePeriodicity(coords, box, mean)\n }\n\n if (this.removePbc) {\n removePbc(coords, box)\n }\n }\n\n if (this.selectionIndices.length > 0 && this.coords1 && this.superpose) {\n this._doSuperpose(coords)\n }\n\n this.frameCache[ i ] = coords\n this.boxCache[ i ] = box\n this.frameCacheSize += 1\n }\n\n _setFrameCount (n: number) {\n if (n !== this._frameCount) {\n this._frameCount = n\n this.signals.countChanged.dispatch(n)\n }\n }\n\n /**\n * Dispose of the trajectory object\n * @return {undefined}\n */\n dispose () {\n this._resetCache() // aid GC\n this._disposed = true\n if (this.player) this.player.stop()\n }\n\n /**\n * Set player for this trajectory\n * @param {TrajectoryPlayer} player - the player\n */\n setPlayer (player: TrajectoryPlayer) {\n this.player = player\n this.signals.playerChanged.dispatch(player)\n }\n\n /**\n * Get time for frame\n * @param {Integer} i - frame index\n * @return {Number} time in picoseconds\n */\n getFrameTime (i: number) {\n return this.timeOffset + i * this.deltaTime\n }\n}\n\nexport default Trajectory\n","/**\n * @file Frames Trajectory\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport Structure from '../structure/structure'\nimport Frames from './frames'\nimport Trajectory, { TrajectoryParameters } from './trajectory'\n\n/**\n * Frames trajectory class. Gets data from a frames object.\n */\nclass FramesTrajectory extends Trajectory {\n path: string\n\n frames: ArrayLike[]\n boxes: ArrayLike[]\n\n atomIndices?: ArrayLike\n\n constructor (frames: Frames, structure: Structure, params: TrajectoryParameters) {\n const p = params || {}\n p.timeOffset = defaults(p.timeOffset, frames.timeOffset)\n p.deltaTime = defaults(p.deltaTime, frames.deltaTime)\n\n super('', structure, p)\n\n this.name = frames.name\n this.path = frames.path\n\n this.frames = frames.coordinates\n this.boxes = frames.boxes\n\n this._init(structure)\n }\n\n get type () { return 'frames' }\n\n _makeAtomIndices () {\n if (this.structure.type === 'StructureView') {\n this.atomIndices = this.structure.getAtomIndices()\n } else {\n this.atomIndices = undefined\n }\n }\n\n _loadFrame (i: number, callback?: Function) {\n let coords\n const frame = this.frames[ i ]\n\n if (this.atomIndices) {\n const indices = this.atomIndices\n const m = indices.length\n\n coords = new Float32Array(m * 3)\n\n for (let j = 0; j < m; ++j) {\n const j3 = j * 3\n const idx3 = indices[ j ] * 3\n\n coords[ j3 + 0 ] = frame[ idx3 + 0 ]\n coords[ j3 + 1 ] = frame[ idx3 + 1 ]\n coords[ j3 + 2 ] = frame[ idx3 + 2 ]\n }\n } else {\n coords = new Float32Array(frame)\n }\n\n const box = this.boxes[ i ]\n const frameCount = this.frames.length\n\n this._process(i, box, coords, frameCount)\n\n if (typeof callback === 'function') {\n callback()\n }\n }\n\n _loadFrameCount () {\n if (this.frames) {\n this._setFrameCount(this.frames.length)\n }\n }\n}\n\nexport default FramesTrajectory\n","/**\n * @file Structure Trajectory\n * @author Alexander Rose \n * @private\n */\n\nimport Structure from '../structure/structure'\nimport Trajectory, { TrajectoryParameters } from './trajectory'\n\n/**\n * Structure trajectory class. Gets data from a structure object.\n */\nclass StructureTrajectory extends Trajectory {\n atomIndices?: ArrayLike\n\n constructor (trajPath: string, structure: Structure, params: TrajectoryParameters) {\n super('', structure, params)\n this._init(structure)\n }\n\n get type () { return 'structure' }\n\n _makeAtomIndices () {\n if (this.structure.atomSet && this.structure.atomSet.getSize() < this.structure.atomStore.count) {\n this.atomIndices = this.structure.getAtomIndices()\n } else {\n this.atomIndices = undefined\n }\n }\n\n _loadFrame (i: number, callback?: Function) {\n let coords\n const structure = this.structure\n const frame = structure.frames[ i ]\n\n if (this.atomIndices) {\n const indices = this.atomIndices\n const m = indices.length\n\n coords = new Float32Array(m * 3)\n\n for (let j = 0; j < m; ++j) {\n const j3 = j * 3\n const idx3 = indices[ j ] * 3\n\n coords[ j3 + 0 ] = frame[ idx3 + 0 ]\n coords[ j3 + 1 ] = frame[ idx3 + 1 ]\n coords[ j3 + 2 ] = frame[ idx3 + 2 ]\n }\n } else {\n coords = new Float32Array(frame)\n }\n\n const box = structure.boxes[ i ]\n const frameCount = structure.frames.length\n\n this._process(i, box, coords, frameCount)\n\n if (typeof callback === 'function') {\n callback()\n }\n }\n\n _loadFrameCount () {\n this._setFrameCount(this.structure.frames.length)\n }\n}\n\nexport default StructureTrajectory\n","/**\n * @file Remote Trajectory\n * @author Alexander Rose \n * @private\n */\n\nimport { Log, TrajectoryDatasource } from '../globals'\nimport Structure from '../structure/structure'\nimport Trajectory, { TrajectoryParameters } from './trajectory'\n\n/**\n * Remote trajectory class. Gets data from an MDsrv instance.\n */\nclass RemoteTrajectory extends Trajectory {\n atomIndices: number[][]\n\n constructor (trajPath: string, structure: Structure, params: TrajectoryParameters) {\n super(trajPath, structure, params)\n this._init(structure)\n }\n\n get type () { return 'remote' }\n\n _makeAtomIndices () {\n const atomIndices = []\n\n if (this.structure.type === 'StructureView') {\n const indices = this.structure.getAtomIndices()! // TODO\n const n = indices.length\n\n let p = indices[ 0 ]\n let q = indices[ 0 ]\n\n for (let i = 1; i < n; ++i) {\n const r = indices[ i ]\n\n if (q + 1 < r) {\n atomIndices.push([ p, q + 1 ])\n p = r\n }\n\n q = r\n }\n\n atomIndices.push([ p, q + 1 ])\n } else {\n atomIndices.push([ 0, this.atomCount ])\n }\n\n this.atomIndices = atomIndices\n }\n\n _loadFrame (i: number, callback?: Function) {\n // TODO implement max frameCache size, re-use arrays\n\n const request = new XMLHttpRequest()\n\n const url = TrajectoryDatasource.getFrameUrl(this.trajPath, i)\n const params = TrajectoryDatasource.getFrameParams(this.trajPath, this.atomIndices)\n\n request.open('POST', url, true)\n request.responseType = 'arraybuffer'\n request.setRequestHeader(\n 'Content-type', 'application/x-www-form-urlencoded'\n )\n\n request.addEventListener('load', () => {\n const arrayBuffer = request.response\n if (!arrayBuffer) {\n Log.error(`empty arrayBuffer for '${url}'`)\n return\n }\n\n const frameCount = new Int32Array(arrayBuffer, 0, 1)[ 0 ]\n // const time = new Float32Array( arrayBuffer, 1 * 4, 1 )[ 0 ];\n const box = new Float32Array(arrayBuffer, 2 * 4, 9)\n const coords = new Float32Array(arrayBuffer, 11 * 4)\n\n this._process(i, box, coords, frameCount)\n if (typeof callback === 'function') {\n callback()\n }\n }, false)\n\n request.send(params)\n }\n\n _loadFrameCount () {\n const request = new XMLHttpRequest()\n\n const url = TrajectoryDatasource.getCountUrl(this.trajPath)\n\n request.open('GET', url, true)\n request.addEventListener('load', () => {\n this._setFrameCount(parseInt(request.response))\n }, false)\n request.send()\n }\n}\n\nexport default RemoteTrajectory\n","/**\n * @file Callback Trajectory\n * @author Tarn W. Burton \n * @private\n */\n\nimport Structure from '../structure/structure'\nimport Trajectory, { TrajectoryParameters } from './trajectory'\n\ntype RequestCallback = (responseCallback: Function, i?: number, atomIndices?: number[][]) => void\n\n/**\n * Callback trajectory class. Gets data from an JavaScript function.\n */\nclass CallbackTrajectory extends Trajectory {\n atomIndices: number[][]\n requestCallback: RequestCallback\n\n constructor (requestCallback: RequestCallback, structure: Structure, params: TrajectoryParameters) {\n super('', structure, params)\n this.requestCallback = requestCallback;\n this._init(structure)\n }\n\n get type () { return 'callback' }\n\n _makeAtomIndices () {\n const atomIndices = []\n\n if (this.structure.type === 'StructureView') {\n const indices = this.structure.getAtomIndices()! // TODO\n const n = indices.length\n\n let p = indices[ 0 ]\n let q = indices[ 0 ]\n\n for (let i = 1; i < n; ++i) {\n const r = indices[ i ]\n\n if (q + 1 < r) {\n atomIndices.push([ p, q + 1 ])\n p = r\n }\n\n q = r\n }\n\n atomIndices.push([ p, q + 1 ])\n } else {\n atomIndices.push([ 0, this.atomCount ])\n }\n\n this.atomIndices = atomIndices\n }\n\n _loadFrame (i: number, callback?: Function) {\n this.requestCallback(\n (i: number, box: ArrayLike, coords: Float32Array, frameCount: number) => {\n this._process(i, box, coords, frameCount)\n if (typeof callback === 'function') {\n callback()\n }\n }, i, this.atomIndices)\n }\n\n _loadFrameCount () {\n this.requestCallback((count: number) => this._setFrameCount(count))\n }\n}\n\nexport default CallbackTrajectory\n\n","/**\n * @file Structure View\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Box3 } from 'three'\n\nimport { Debug, Log } from '../globals'\nimport Structure from './structure'\nimport Selection from '../selection/selection'\nimport BitArray from '../utils/bitarray'\n\nimport BondProxy from '../proxy/bond-proxy'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ResidueProxy from '../proxy/residue-proxy'\nimport ChainProxy from '../proxy/chain-proxy'\nimport ModelProxy from '../proxy/model-proxy'\nimport SpatialHash from '../geometry/spatial-hash';\nimport BondHash from '../store/bond-hash';\nimport ResidueMap from '../store/residue-map';\nimport AtomMap from '../store/atom-map';\nimport ModelStore from '../store/model-store';\nimport ChainStore from '../store/chain-store';\nimport ResidueStore from '../store/residue-store';\nimport AtomStore from '../store/atom-store';\nimport BondStore from '../store/bond-store';\nimport Validation from './validation';\nimport Unitcell from '../symmetry/unitcell';\nimport Entity from './entity';\nimport Assembly from '../symmetry/assembly';\nimport { Data } from './data';\n\n/**\n * Get view on structure restricted to the selection\n * @param {Selection} selection - the selection\n * @return {StructureView} the view on the structure\n */\nStructure.prototype.getView = function (this: Structure, selection: Selection) {\n // added here to avoid cyclic import dependency\n return new StructureView(this, selection)\n}\n\n/**\n * View on the structure, restricted to the selection\n */\nclass StructureView extends Structure {\n structure: Structure\n selection: Selection\n\n /**\n * @param {Structure} structure - the structure\n * @param {Selection} selection - the selection\n */\n constructor (structure: Structure, selection: Selection) {\n super()\n\n this.structure = structure\n this.selection = selection\n\n this.center = new Vector3()\n this.boundingBox = new Box3()\n\n this._bp = this.getBondProxy()\n this._ap = this.getAtomProxy()\n this._rp = this.getResidueProxy()\n this._cp = this.getChainProxy()\n\n if (this.selection) {\n this.selection.signals.stringChanged.add(this.refresh, this)\n }\n\n this.structure.signals.refreshed.add(this.refresh, this)\n\n this.refresh()\n }\n\n init () {}\n\n get type () { return 'StructureView' }\n\n get name () { return this.structure.name }\n get path () { return this.structure.path }\n get title () { return this.structure.title }\n get id () { return this.structure.id }\n get data (): Data { return this.structure.data }\n get atomSetDict () { return this.structure.atomSetDict }\n get biomolDict (): {[k: string]: Assembly} { return this.structure.biomolDict }\n get entityList (): Entity[] { return this.structure.entityList }\n get unitcell (): Unitcell|undefined { return this.structure.unitcell }\n get frames () { return this.structure.frames }\n get boxes () { return this.structure.boxes }\n get validation (): Validation|undefined { return this.structure.validation }\n get bondStore () { return this.structure.bondStore }\n get backboneBondStore () { return this.structure.backboneBondStore }\n get rungBondStore (): BondStore { return this.structure.rungBondStore }\n get atomStore (): AtomStore { return this.structure.atomStore }\n get residueStore (): ResidueStore { return this.structure.residueStore }\n get chainStore (): ChainStore { return this.structure.chainStore }\n get modelStore (): ModelStore { return this.structure.modelStore }\n get atomMap (): AtomMap { return this.structure.atomMap }\n get residueMap (): ResidueMap { return this.structure.residueMap }\n get bondHash (): BondHash|undefined { return this.structure.bondHash }\n get spatialHash (): SpatialHash|undefined { return this.structure.spatialHash }\n\n get _hasCoords () { return this.structure._hasCoords }\n set _hasCoords (value) { this.structure._hasCoords = value }\n\n /**\n * Updates atomSet, bondSet, atomSetCache, atomCount, bondCount, boundingBox, center.\n * @emits {Structure.signals.refreshed} when refreshed\n * @return {undefined}\n */\n refresh () {\n if (Debug) Log.time('StructureView.refresh')\n\n this.atomSetCache = {}\n const structure = this.structure\n\n if (this.selection.isAllSelection() &&\n structure !== this && structure.atomSet && structure.bondSet\n ) {\n this.atomSet = structure.atomSet.clone()\n this.bondSet = structure.bondSet.clone()\n\n for (let name in this.atomSetDict) {\n const atomSet = this.atomSetDict[ name ]\n this.atomSetCache[ '__' + name ] = atomSet.clone()\n }\n\n this.atomCount = structure.atomCount\n this.bondCount = structure.bondCount\n\n this.boundingBox.copy(structure.boundingBox)\n this.center.copy(structure.center)\n } else if (this.selection.isNoneSelection() &&\n structure !== this && structure.atomSet && structure.bondSet\n ) {\n this.atomSet = new BitArray(structure.atomCount)\n this.bondSet = new BitArray(structure.bondCount)\n\n for (let name in this.atomSetDict) {\n this.atomSetCache[ '__' + name ] = new BitArray(structure.atomCount)\n }\n\n this.atomCount = 0\n this.bondCount = 0\n\n this.boundingBox.makeEmpty()\n this.center.set(0, 0, 0)\n } else {\n this.atomSet = this.getAtomSet(this.selection, true)\n if (structure.atomSet) {\n this.atomSet = this.atomSet.intersection(structure.atomSet)\n }\n\n this.bondSet = this.getBondSet()\n\n for (let name in this.atomSetDict) {\n const atomSet = this.atomSetDict[ name ]\n this.atomSetCache[ '__' + name ] = atomSet.makeIntersection(this.atomSet)\n }\n\n this.atomCount = this.atomSet.getSize()\n this.bondCount = this.bondSet.getSize()\n\n this.boundingBox = this.getBoundingBox()\n this.center = this.boundingBox.getCenter(new Vector3())\n }\n\n if (Debug) Log.timeEnd('StructureView.refresh')\n\n this.signals.refreshed.dispatch()\n }\n\n //\n\n setSelection (selection: Selection) {\n this.selection = selection\n\n this.refresh()\n }\n\n getSelection (selection?: Selection) {\n const seleList: string[] = []\n\n if (selection && selection.string) {\n seleList.push(selection.string)\n }\n\n const parentSelection = this.structure.getSelection()\n if (parentSelection && parentSelection.string) {\n seleList.push(parentSelection.string)\n }\n\n if (this.selection && this.selection.string) {\n seleList.push(this.selection.string)\n }\n\n let sele = ''\n if (seleList.length > 0) {\n sele = `( ${seleList.join(' ) AND ( ')} )`\n }\n\n return new Selection(sele)\n }\n\n getStructure () {\n return this.structure.getStructure()\n }\n\n //\n\n eachBond (callback: (entity: BondProxy) => any, selection?: Selection) {\n this.structure.eachBond(callback, this.getSelection(selection))\n }\n\n eachAtom (callback: (entity: AtomProxy) => any, selection?: Selection) {\n const ap = this.getAtomProxy()\n const atomSet = this.getAtomSet(selection)\n const n = this.atomStore.count\n\n if (atomSet.getSize() < n) {\n atomSet.forEach(function (index) {\n ap.index = index\n callback(ap)\n })\n } else {\n for (let i = 0; i < n; ++i) {\n ap.index = i\n callback(ap)\n }\n }\n }\n\n eachResidue (callback: (entity: ResidueProxy) => any, selection?: Selection) {\n this.structure.eachResidue(callback, this.getSelection(selection))\n }\n\n /**\n * Not implemented\n * @alias StructureView#eachResidueN\n * @return {undefined}\n */\n eachResidueN (n: number, callback: (entity: ResidueProxy) => any) {\n console.error('StructureView.eachResidueN() not implemented')\n }\n\n eachChain (callback: (entity: ChainProxy) => any, selection?: Selection) {\n this.structure.eachChain(callback, this.getSelection(selection))\n }\n\n eachModel (callback: (entity: ModelProxy) => any, selection?: Selection) {\n this.structure.eachModel(callback, this.getSelection(selection))\n }\n\n //\n\n getAtomSet (selection?: boolean|Selection|BitArray, ignoreView = false) {\n let atomSet = this.structure.getAtomSet(selection)\n if (!ignoreView && this.atomSet) {\n atomSet = atomSet.makeIntersection(this.atomSet)\n }\n\n return atomSet\n }\n\n //\n\n getAtomIndices (selection?: Selection) {\n return this.structure.getAtomIndices(this.getSelection(selection))\n }\n\n refreshPosition () {\n return this.structure.refreshPosition()\n }\n\n //\n\n dispose () {\n if (this.selection) {\n this.selection.signals.stringChanged.remove(this.refresh, this)\n }\n\n this.structure.signals.refreshed.remove(this.refresh, this)\n\n this.structure = new Structure() // delete old data\n\n delete this.atomSet\n delete this.bondSet\n\n }\n}\n\nexport default StructureView\n","/**\n * @file Alignment\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log } from '../globals'\n\n// const nucleotides = 'ACTG';\nconst aminoacidsX = 'ACDEFGHIKLMNPQRSTVWY'\nconst aminoacids = 'ARNDCQEGHILKMFPSTWYVBZ?'\n\nconst blosum62x = [\n [4, 0, -2, -1, -2, 0, -2, -1, -1, -1, -1, -2, -1, -1, -1, 1, 0, 0, -3, -2], // A\n [0, 9, -3, -4, -2, -3, -3, -1, -3, -1, -1, -3, -3, -3, -3, -1, -1, -1, -2, -2], // C\n [-2, -3, 6, 2, -3, -1, -1, -3, -1, -4, -3, 1, -1, 0, -2, 0, -1, -3, -4, -3], // D\n [-1, -4, 2, 5, -3, -2, 0, -3, 1, -3, -2, 0, -1, 2, 0, 0, -1, -2, -3, -2], // E\n [-2, -2, -3, -3, 6, -3, -1, 0, -3, 0, 0, -3, -4, -3, -3, -2, -2, -1, 1, 3], // F\n [0, -3, -1, -2, -3, 6, -2, -4, -2, -4, -3, 0, -2, -2, -2, 0, -2, -3, -2, -3], // G\n [-2, -3, -1, 0, -1, -2, 8, -3, -1, -3, -2, 1, -2, 0, 0, -1, -2, -3, -2, 2], // H\n [-1, -1, -3, -3, 0, -4, -3, 4, -3, 2, 1, -3, -3, -3, -3, -2, -1, 3, -3, -1], // I\n [-1, -3, -1, 1, -3, -2, -1, -3, 5, -2, -1, 0, -1, 1, 2, 0, -1, -2, -3, -2], // K\n [-1, -1, -4, -3, 0, -4, -3, 2, -2, 4, 2, -3, -3, -2, -2, -2, -1, 1, -2, -1], // L\n [-1, -1, -3, -2, 0, -3, -2, 1, -1, 2, 5, -2, -2, 0, -1, -1, -1, 1, -1, -1], // M\n [-2, -3, 1, 0, -3, 0, 1, -3, 0, -3, -2, 6, -2, 0, 0, 1, 0, -3, -4, -2], // N\n [-1, -3, -1, -1, -4, -2, -2, -3, -1, -3, -2, -2, 7, -1, -2, -1, -1, -2, -4, -3], // P\n [-1, -3, 0, 2, -3, -2, 0, -3, 1, -2, 0, 0, -1, 5, 1, 0, -1, -2, -2, -1], // Q\n [-1, -3, -2, 0, -3, -2, 0, -3, 2, -2, -1, 0, -2, 1, 5, -1, -1, -3, -3, -2], // R\n [1, -1, 0, 0, -2, 0, -1, -2, 0, -2, -1, 1, -1, 0, -1, 4, 1, -2, -3, -2], // S\n [0, -1, -1, -1, -2, -2, -2, -1, -1, -1, -1, 0, -1, -1, -1, 1, 5, 0, -2, -2], // T\n [0, -1, -3, -2, -1, -3, -3, 3, -2, 1, 1, -3, -2, -2, -3, -2, 0, 4, -3, -1], // V\n [-3, -2, -4, -3, 1, -2, -2, -3, -3, -2, -1, -4, -4, -2, -3, -3, -2, -3, 11, 2], // W\n [-2, -2, -3, -2, 3, -3, 2, -1, -2, -1, -1, -2, -3, -1, -2, -2, -2, -1, 2, 7] // Y\n]\n\nconst blosum62 = [\n // A R N D C Q E G H I L K M F P S T W Y V B Z X\n [4, -1, -2, -2, 0, -1, -1, 0, -2, -1, -1, -1, -1, -2, -1, 1, 0, -3, -2, 0, -2, -1, 0], // A\n [-1, 5, 0, -2, -3, 1, 0, -2, 0, -3, -2, 2, -1, -3, -2, -1, -1, -3, -2, -3, -1, 0, -1], // R\n [-2, 0, 6, 1, -3, 0, 0, 0, 1, -3, -3, 0, -2, -3, -2, 1, 0, -4, -2, -3, 3, 0, -1], // N\n [-2, -2, 1, 6, -3, 0, 2, -1, -1, -3, -4, -1, -3, -3, -1, 0, -1, -4, -3, -3, 4, 1, -1], // D\n [0, -3, -3, -3, 9, -3, -4, -3, -3, -1, -1, -3, -1, -2, -3, -1, -1, -2, -2, -1, -3, -3, -2], // C\n [-1, 1, 0, 0, -3, 5, 2, -2, 0, -3, -2, 1, 0, -3, -1, 0, -1, -2, -1, -2, 0, 3, -1], // Q\n [-1, 0, 0, 2, -4, 2, 5, -2, 0, -3, -3, 1, -2, -3, -1, 0, -1, -3, -2, -2, 1, 4, -1], // E\n [0, -2, 0, -1, -3, -2, -2, 6, -2, -4, -4, -2, -3, -3, -2, 0, -2, -2, -3, -3, -1, -2, -1], // G\n [-2, 0, 1, -1, -3, 0, 0, -2, 8, -3, -3, -1, -2, -1, -2, -1, -2, -2, 2, -3, 0, 0, -1], // H\n [-1, -3, -3, -3, -1, -3, -3, -4, -3, 4, 2, -3, 1, 0, -3, -2, -1, -3, -1, 3, -3, -3, -1], // I\n [-1, -2, -3, -4, -1, -2, -3, -4, -3, 2, 4, -2, 2, 0, -3, -2, -1, -2, -1, 1, -4, -3, -1], // L\n [-1, 2, 0, -1, -3, 1, 1, -2, -1, -3, -2, 5, -1, -3, -1, 0, -1, -3, -2, -2, 0, 1, -1], // K\n [-1, -1, -2, -3, -1, 0, -2, -3, -2, 1, 2, -1, 5, 0, -2, -1, -1, -1, -1, 1, -3, -1, -1], // M\n [-2, -3, -3, -3, -2, -3, -3, -3, -1, 0, 0, -3, 0, 6, -4, -2, -2, 1, 3, -1, -3, -3, -1], // F\n [-1, -2, -2, -1, -3, -1, -1, -2, -2, -3, -3, -1, -2, -4, 7, -1, -1, -4, -3, -2, -2, -1, -2], // P\n [1, -1, 1, 0, -1, 0, 0, 0, -1, -2, -2, 0, -1, -2, -1, 4, 1, -3, -2, -2, 0, 0, 0], // S\n [0, -1, 0, -1, -1, -1, -1, -2, -2, -1, -1, -1, -1, -2, -1, 1, 5, -2, -2, 0, -1, -1, 0], // T\n [-3, -3, -4, -4, -2, -2, -3, -2, -2, -3, -2, -3, -1, 1, -4, -3, -2, 11, 2, -3, -4, -3, -2], // W\n [-2, -2, -2, -3, -2, -1, -2, -3, 2, -1, -1, -2, -1, 3, -3, -2, -2, 2, 7, -1, -3, -2, -1], // Y\n [0, -3, -3, -3, -1, -2, -2, -3, -3, 3, 1, -2, 1, -1, -2, -2, 0, -3, -1, 4, -3, -2, -1], // V\n [-2, -1, 3, 4, -3, 0, 1, -1, 0, -3, -4, 0, -3, -3, -2, 0, -1, -4, -3, -3, 4, 1, -1], // B\n [-1, 0, 0, 1, -3, 3, 4, -2, 0, -3, -3, 1, -1, -3, -1, 0, -1, -3, -2, -2, 1, 4, -1], // Z\n [0, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, 0, 0, -2, -1, -1, -1, -1, -1] // X\n]\n\nfunction prepareMatrix (cellNames: string, mat: number[][]) {\n let j: number\n let i = 0\n const matDict: { [k: string]: { [k: string]: number } } = {}\n mat.forEach(function (row) {\n j = 0\n const rowDict: { [k: string]: number } = {}\n row.forEach(function (elm) {\n rowDict[ cellNames[ j++ ] ] = elm\n })\n matDict[ cellNames[ i++ ] ] = rowDict\n })\n return matDict\n}\n\nconst SubstitutionMatrices = (function () {\n return {\n blosum62: prepareMatrix(aminoacids, blosum62),\n blosum62x: prepareMatrix(aminoacidsX, blosum62x)\n }\n}())\nexport type SubstitutionMatrix = ''|'blosum62'|'blosum62x'\n\nclass Alignment {\n substMatrix: { [k: string]: { [k: string]: number } }\n\n n: number\n m: number\n score?: number\n ali: string\n\n S: number[][]\n V: number[][]\n H: number[][]\n\n ali1: string\n ali2: string\n\n constructor (readonly seq1: string, readonly seq2: string, readonly gapPenalty = -10, readonly gapExtensionPenalty = -1, substMatrix: SubstitutionMatrix = 'blosum62') {\n // TODO try encoding seqs as integers and use array subst matrix, maybe faster\n\n if (substMatrix) {\n this.substMatrix = SubstitutionMatrices[ substMatrix ]\n }\n }\n\n initMatrices () {\n this.n = this.seq1.length\n this.m = this.seq2.length\n\n // Log.log(this.n, this.m);\n\n this.score = undefined\n this.ali = ''\n\n this.S = []\n this.V = []\n this.H = []\n\n for (let i = 0; i <= this.n; ++i) {\n this.S[ i ] = []\n this.V[ i ] = []\n this.H[ i ] = []\n\n for (let j = 0; j <= this.m; ++j) {\n this.S[ i ][ j ] = 0\n this.V[ i ][ j ] = 0\n this.H[ i ][ j ] = 0\n }\n }\n\n for (let i = 0; i <= this.n; ++i) {\n this.S[ i ][ 0 ] = this.gap(0)\n this.H[ i ][ 0 ] = -Infinity\n }\n\n for (let j = 0; j <= this.m; ++j) {\n this.S[ 0 ][ j ] = this.gap(0)\n this.V[ 0 ][ j ] = -Infinity\n }\n\n this.S[ 0 ][ 0 ] = 0\n\n // Log.log(this.S, this.V, this.H);\n }\n\n gap (len: number) {\n return this.gapPenalty + len * this.gapExtensionPenalty\n }\n\n makeScoreFn () {\n const seq1 = this.seq1\n const seq2 = this.seq2\n\n const substMatrix = this.substMatrix\n\n if (substMatrix) {\n return function score (i: number, j: number) {\n const c1 = seq1[ i ]\n const c2 = seq2[ j ]\n\n try {\n return substMatrix[ c1 ][ c2 ]\n } catch (e) {\n return -4\n }\n }\n } else {\n Log.warn('Alignment: no subst matrix')\n\n return function scoreNoSubstMat (i: number, j: number) {\n const c1 = seq1[ i ]\n const c2 = seq2[ j ]\n\n return c1 === c2 ? 5 : -3\n }\n }\n }\n\n calc () {\n if (Debug) Log.time('Alignment.calc')\n\n this.initMatrices()\n\n const gap0 = this.gap(0)\n const scoreFn = this.makeScoreFn()\n const gapExtensionPenalty = this.gapExtensionPenalty\n\n const V = this.V\n const H = this.H\n const S = this.S\n\n const n = this.n\n const m = this.m\n\n let Vi1, Si1, Vi, Hi, Si\n\n for (let i = 1; i <= n; ++i) {\n Si1 = S[ i - 1 ]\n Vi1 = V[ i - 1 ]\n\n Vi = V[ i ]\n Hi = H[ i ]\n Si = S[ i ]\n\n for (let j = 1; j <= m; ++j) {\n Vi[j] = Math.max(\n Si1[ j ] + gap0,\n Vi1[ j ] + gapExtensionPenalty\n )\n\n Hi[j] = Math.max(\n Si[ j - 1 ] + gap0,\n Hi[ j - 1 ] + gapExtensionPenalty\n )\n\n Si[j] = Math.max(\n Si1[ j - 1 ] + scoreFn(i - 1, j - 1), // match\n Vi[ j ], // del\n Hi[ j ] // ins\n )\n }\n }\n\n if (Debug) Log.timeEnd('Alignment.calc')\n\n if (Debug) Log.log(this.S, this.V, this.H)\n }\n\n trace () {\n if (Debug) Log.time('Alignment.trace')\n\n this.ali1 = ''\n this.ali2 = ''\n\n const scoreFn = this.makeScoreFn()\n\n let i = this.n\n let j = this.m\n let mat\n\n if (this.S[i][j] >= this.V[i][j]) {\n mat = 'S'\n this.score = this.S[i][j]\n } else if (this.V[i][j] >= this.H[i][j]) {\n mat = 'V'\n this.score = this.V[i][j]\n } else {\n mat = 'H'\n this.score = this.H[i][j]\n }\n\n if (Debug) Log.log('Alignment: SCORE', this.score)\n if (Debug) Log.log('Alignment: S, V, H', this.S[i][j], this.V[i][j], this.H[i][j])\n\n while (i > 0 && j > 0) {\n if (mat === 'S') {\n if (this.S[i][j] === this.S[i - 1][j - 1] + scoreFn(i - 1, j - 1)) {\n this.ali1 = this.seq1[i - 1] + this.ali1\n this.ali2 = this.seq2[j - 1] + this.ali2\n --i\n --j\n mat = 'S'\n } else if (this.S[i][j] === this.V[i][j]) {\n mat = 'V'\n } else if (this.S[i][j] === this.H[i][j]) {\n mat = 'H'\n } else {\n // Log.debug('Alignment: S');\n --i\n --j\n }\n } else if (mat === 'V') {\n if (this.V[i][j] === this.V[i - 1][j] + this.gapExtensionPenalty) {\n this.ali1 = this.seq1[i - 1] + this.ali1\n this.ali2 = '-' + this.ali2\n --i\n mat = 'V'\n } else if (this.V[i][j] === this.S[i - 1][j] + this.gap(0)) {\n this.ali1 = this.seq1[i - 1] + this.ali1\n this.ali2 = '-' + this.ali2\n --i\n mat = 'S'\n } else {\n // Log.debug('Alignment: V');\n --i\n }\n } else if (mat === 'H') {\n if (this.H[i][j] === this.H[i][j - 1] + this.gapExtensionPenalty) {\n this.ali1 = '-' + this.ali1\n this.ali2 = this.seq2[j - 1] + this.ali2\n --j\n mat = 'H'\n } else if (this.H[i][j] === this.S[i][j - 1] + this.gap(0)) {\n this.ali1 = '-' + this.ali1\n this.ali2 = this.seq2[j - 1] + this.ali2\n --j\n mat = 'S'\n } else {\n // Log.debug('Alignment: H');\n --j\n }\n } else {\n Log.error('Alignment: no matrix')\n }\n }\n\n while (i > 0) {\n this.ali1 = this.seq1[ i - 1 ] + this.ali1\n this.ali2 = '-' + this.ali2\n --i\n }\n\n while (j > 0) {\n this.ali1 = '-' + this.ali1\n this.ali2 = this.seq2[ j - 1 ] + this.ali2\n --j\n }\n\n if (Debug) Log.timeEnd('Alignment.trace')\n\n if (Debug) Log.log([this.ali1, this.ali2])\n }\n}\n\nexport default Alignment\n","/**\n * @file Align Utils\n * @author Alexander Rose \n * @private\n */\n\nimport Structure from '../structure/structure'\nimport Selection from '../selection/selection'\nimport Alignment from './alignment'\nimport Superposition from './superposition'\n\n/**\n * Perform structural superposition of two structures,\n * optionally guided by a sequence alignment\n * @param {Structure|StructureView} s1 - structure 1 which is superposed onto structure 2\n * @param {Structure|StructureView} s2 - structure 2 onto which structure 1 is superposed\n * @param {Boolean} [align] - guide the superposition by a sequence alignment\n * @param {String} [sele1] - selection string for structure 1\n * @param {String} [sele2] - selection string for structure 2\n * @return {undefined}\n */\nfunction superpose (s1: Structure, s2: Structure, align = false, sele1 = '', sele2 = '') {\n let i: number\n let j: number\n let n: number\n let atoms1\n let atoms2\n\n if (align) {\n let _s1 = s1\n let _s2 = s2\n\n if (sele1 && sele2) {\n _s1 = s1.getView(new Selection(sele1))\n _s2 = s2.getView(new Selection(sele2))\n }\n\n const seq1 = _s1.getSequence()\n const seq2 = _s2.getSequence()\n\n // Log.log( seq1.join(\"\") );\n // Log.log( seq2.join(\"\") );\n\n const ali = new Alignment(seq1.join(''), seq2.join(''))\n\n ali.calc()\n ali.trace()\n\n // Log.log( \"superpose alignment score\", ali.score );\n\n // Log.log( ali.ali1 );\n // Log.log( ali.ali2 );\n\n let _i, _j\n i = 0\n j = 0\n n = ali.ali1.length\n const aliIdx1: boolean[] = []\n const aliIdx2: boolean[] = []\n\n for (let l = 0; l < n; ++l) {\n const x = ali.ali1[ l ]\n const y = ali.ali2[ l ]\n\n _i = 0\n _j = 0\n\n if (x === '-') {\n aliIdx2[ j ] = false\n } else {\n aliIdx2[ j ] = true\n _i = 1\n }\n\n if (y === '-') {\n aliIdx1[ i ] = false\n } else {\n aliIdx1[ i ] = true\n _j = 1\n }\n\n i += _i\n j += _j\n }\n\n // Log.log( i, j );\n\n // Log.log( aliIdx1 );\n // Log.log( aliIdx2 );\n\n const _atoms1: number[] = []\n const _atoms2: number[] = []\n const ap1 = _s1.getAtomProxy()\n const ap2 = _s2.getAtomProxy()\n\n i = 0\n _s1.eachResidue(function (r) {\n if (r.traceAtomIndex === undefined ||\n r.traceAtomIndex !== r.getAtomIndexByName('CA')) return\n\n if (aliIdx1[ i ]) {\n ap1.index = r.getAtomIndexByName('CA')! // TODO\n _atoms1.push(ap1.x, ap1.y, ap1.z)\n }\n i += 1\n })\n\n i = 0\n _s2.eachResidue(function (r) {\n if (r.traceAtomIndex === undefined ||\n r.traceAtomIndex !== r.getAtomIndexByName('CA')) return\n\n if (aliIdx2[ i ]) {\n ap2.index = r.getAtomIndexByName('CA')! // TODO\n _atoms2.push(ap2.x, ap2.y, ap2.z)\n }\n i += 1\n })\n\n atoms1 = new Float32Array(_atoms1)\n atoms2 = new Float32Array(_atoms2)\n } else {\n const sviewCa1 = s1.getView(new Selection(`${sele1} and .CA`))\n const sviewCa2 = s2.getView(new Selection(`${sele2} and .CA`))\n\n atoms1 = sviewCa1\n atoms2 = sviewCa2\n }\n\n const superpose = new Superposition(atoms1, atoms2)\n const result = superpose.transform(s1)\n s1.refreshPosition()\n return result\n}\n\nexport {\n superpose\n}\n","/**\n * @file Sturucture Component\n * @author Alexander Rose \n * @private\n */\n\nimport { Signal } from 'signals'\n\nimport { ComponentRegistry, MeasurementDefaultParams } from '../globals'\nimport {\n defaults, /*deepEqual, */createRingBuffer, RingBuffer, createSimpleDict, SimpleDict\n} from '../utils'\nimport { smoothstep } from '../math/math-utils'\nimport Component, { ComponentSignals, ComponentDefaultParameters } from './component'\nimport RepresentationCollection from './representation-collection'\nimport TrajectoryElement from './trajectory-element'\nimport RepresentationElement from './representation-element'\nimport { makeTrajectory } from '../trajectory/trajectory-utils'\nimport { TrajectoryParameters } from '../trajectory/trajectory'\nimport Selection from '../selection/selection'\nimport Structure from '../structure/structure'\nimport StructureView from '../structure/structure-view'\nimport { superpose } from '../align/align-utils'\nimport Stage from '../stage/stage'\nimport StructureRepresentation, { StructureRepresentationParameters } from '../representation/structure-representation'\nimport AtomProxy from '../proxy/atom-proxy'\nimport { Vector3, Box3 } from 'three';\nimport { AngleRepresentationParameters } from '../representation/angle-representation';\nimport { AxesRepresentationParameters } from '../representation/axes-representation';\nimport { BallAndStickRepresentationParameters } from '../representation/ballandstick-representation';\nimport { CartoonRepresentationParameters } from '../representation/cartoon-representation';\nimport { ContactRepresentationParameters } from '../representation/contact-representation';\nimport { DihedralRepresentationParameters } from '../representation/dihedral-representation';\nimport { DihedralHistogramRepresentationParameters } from '../representation/dihedral-histogram-representation';\nimport { DistanceRepresentationParameters } from '../representation/distance-representation';\nimport { HyperballRepresentationParameters } from '../representation/hyperball-representation';\nimport { LabelRepresentationParameters } from '../representation/label-representation';\nimport { LineRepresentationParameters } from '../representation/line-representation';\nimport { PointRepresentationParameters } from '../representation/point-representation';\nimport { SurfaceRepresentationParameters } from '../representation/surface-representation';\nimport { RibbonRepresentationParameters } from '../representation/ribbon-representation';\nimport { RocketRepresentationParameters } from '../representation/rocket-representation';\nimport { TraceRepresentationParameters } from '../representation/trace-representation';\nimport { UnitcellRepresentationParameters } from '../representation/unitcell-representation';\nimport { SliceRepresentationParameters } from '../representation/slice-representation'\nimport { MolecularSurfaceRepresentationParameters } from '../representation/molecularsurface-representation'\nimport { DotRepresentationParameters } from '../representation/dot-representation'\n\nexport type StructureRepresentationType = keyof StructureRepresentationParametersMap\n\ninterface StructureRepresentationParametersMap {\n 'angle': AngleRepresentationParameters,\n 'axes' : AxesRepresentationParameters,\n 'backbone': BallAndStickRepresentationParameters,\n 'ball+stick': BallAndStickRepresentationParameters,\n 'base': BallAndStickRepresentationParameters,\n 'cartoon': CartoonRepresentationParameters,\n 'contact': ContactRepresentationParameters,\n 'dihedral': DihedralRepresentationParameters,\n 'dihedral-histogram': DihedralHistogramRepresentationParameters,\n 'distance': DistanceRepresentationParameters,\n 'dot': DotRepresentationParameters,\n 'helixorient': StructureRepresentationParameters,\n 'hyperball': HyperballRepresentationParameters,\n 'label': LabelRepresentationParameters,\n 'licorice': BallAndStickRepresentationParameters,\n 'line': LineRepresentationParameters,\n 'molecularsurface': MolecularSurfaceRepresentationParameters,\n 'point': PointRepresentationParameters,\n 'ribbon': RibbonRepresentationParameters,\n 'rocket': RocketRepresentationParameters,\n 'rope': CartoonRepresentationParameters,\n 'slice': SliceRepresentationParameters,\n 'spacefill': BallAndStickRepresentationParameters,\n 'surface': SurfaceRepresentationParameters,\n 'trace': TraceRepresentationParameters,\n 'tube': CartoonRepresentationParameters,\n 'unitcell': UnitcellRepresentationParameters,\n 'validation': StructureRepresentationParameters\n}\n\nexport const StructureComponentDefaultParameters = Object.assign({\n sele: '',\n defaultAssembly: ''\n}, ComponentDefaultParameters)\nexport type StructureComponentParameters = typeof StructureComponentDefaultParameters\n\nexport interface StructureComponentSignals extends ComponentSignals {\n trajectoryAdded: Signal // when a trajectory is added\n trajectoryRemoved: Signal // when a trajectory is removed\n defaultAssemblyChanged: Signal // on default assembly change\n}\n\n/**\n * Component wrapping a {@link Structure} object\n *\n * @example\n * // get a structure component by loading a structure file into the stage\n * stage.loadFile( \"rcsb://4opj\" ).then( function( structureComponent ){\n * structureComponent.addRepresentation( \"cartoon\" );\n * structureComponent.autoView();\n * } );\n */\nclass StructureComponent extends Component {\n readonly signals: StructureComponentSignals\n readonly parameters: StructureComponentParameters\n get defaultParameters () { return StructureComponentDefaultParameters }\n\n selection: Selection\n structureView: StructureView\n readonly trajList: TrajectoryElement[] = []\n\n pickBuffer: RingBuffer\n pickDict: SimpleDict\n lastPick?: number\n\n spacefillRepresentation: RepresentationElement\n distanceRepresentation: RepresentationElement\n angleRepresentation: RepresentationElement\n dihedralRepresentation: RepresentationElement\n\n measureRepresentations: RepresentationCollection\n\n constructor (stage: Stage, readonly structure: Structure, params: Partial = {}) {\n super(stage, structure, Object.assign({ name: structure.name }, params))\n\n this.signals = Object.assign(this.signals, {\n trajectoryAdded: new Signal(),\n trajectoryRemoved: new Signal(),\n defaultAssemblyChanged: new Signal()\n })\n\n this.initSelection(this.parameters.sele)\n\n //\n\n this.pickBuffer = createRingBuffer(4)\n this.pickDict = createSimpleDict()\n\n this.spacefillRepresentation = this.addRepresentation('spacefill', {\n sele: 'none',\n opacity: MeasurementDefaultParams.opacity,\n color: MeasurementDefaultParams.color,\n disablePicking: true,\n radiusType: 'data'\n }, true)\n\n this.distanceRepresentation = this.addRepresentation(\n 'distance', MeasurementDefaultParams, true\n )\n this.angleRepresentation = this.addRepresentation(\n 'angle', MeasurementDefaultParams, true\n )\n this.dihedralRepresentation = this.addRepresentation(\n 'dihedral', MeasurementDefaultParams, true\n )\n\n this.measureRepresentations = new RepresentationCollection([\n this.spacefillRepresentation,\n this.distanceRepresentation,\n this.angleRepresentation,\n this.dihedralRepresentation\n ])\n\n //\n\n this.setDefaultAssembly(this.parameters.defaultAssembly)\n\n this.structure.signals.refreshed.add(() => {\n this.updateRepresentations({ position: true })\n })\n }\n\n /**\n * Component type\n * @type {String}\n */\n get type () { return 'structure' }\n\n /**\n * Initialize selection\n * @private\n * @param {String} sele - selection string\n * @return {undefined}\n */\n initSelection (sele: string) {\n /**\n * Selection for {@link StructureComponent#structureView}\n * @private\n * @type {Selection}\n */\n this.selection = new Selection(sele)\n\n /**\n * View on {@link StructureComponent#structure}.\n * Change its selection via {@link StructureComponent#setSelection}.\n * @type {StructureView}\n */\n this.structureView = new StructureView(\n this.structure, this.selection\n )\n\n this.selection.signals.stringChanged.add(() => {\n this.structureView.setSelection(this.selection)\n\n this.rebuildRepresentations()\n this.rebuildTrajectories()\n })\n }\n\n /**\n * Set selection of {@link StructureComponent#structureView}\n * @param {String} string - selection string\n * @return {StructureComponent} this object\n */\n setSelection (string: string) {\n this.parameters.sele = string\n this.selection.setString(string)\n return this\n }\n\n /**\n * Set the default assembly\n * @param {String} value - assembly name\n * @return {undefined}\n */\n setDefaultAssembly (value:string) {\n // filter out non-exsisting assemblies\n if (this.structure.biomolDict[value] === undefined) value = ''\n // only set default assembly when changed\n if (this.parameters.defaultAssembly !== value) {\n const reprParams = { defaultAssembly: value }\n this.reprList.forEach(repr => repr.setParameters(reprParams))\n this.measureRepresentations.setParameters(reprParams)\n this.parameters.defaultAssembly = value\n this.signals.defaultAssemblyChanged.dispatch(value)\n }\n return this\n }\n\n /**\n * Rebuild all representations\n * @return {undefined}\n */\n rebuildRepresentations () {\n this.reprList.forEach((repr: RepresentationElement) => {\n repr.build()\n })\n this.measureRepresentations.build()\n }\n\n /**\n * Rebuild all trajectories\n * @return {undefined}\n */\n rebuildTrajectories () {\n this.trajList.forEach(trajComp => {\n trajComp.trajectory.setStructure(this.structureView)\n })\n }\n\n updateRepresentations (what: any) {\n super.updateRepresentations(what)\n this.measureRepresentations.update(what)\n }\n\n /**\n * Overrides {@link Component.updateRepresentationMatrices} \n * to also update matrix for measureRepresentations \n */\n updateRepresentationMatrices () {\n super.updateRepresentationMatrices()\n this.measureRepresentations.setParameters({ matrix: this.matrix })\n }\n\n addRepresentation (\n type: K,\n params: Partial|{defaultAssembly: string} = {},\n hidden = false\n ) {\n params.defaultAssembly = this.parameters.defaultAssembly\n\n const reprComp = this._addRepresentation(type, this.structureView, params, hidden)\n if (!hidden) {\n reprComp.signals.parametersChanged.add(() => this.measureUpdate())\n }\n return reprComp\n }\n\n /**\n * Add a new trajectory component to the structure\n */\n addTrajectory (trajPath = '', params: { [k: string]: any } = {}) {\n const traj = makeTrajectory(trajPath, this.structureView, params as TrajectoryParameters)\n\n const trajComp = new TrajectoryElement(this.stage, traj, params)\n this.trajList.push(trajComp)\n this.signals.trajectoryAdded.dispatch(trajComp)\n\n return trajComp\n }\n\n removeTrajectory (traj: TrajectoryElement) {\n const idx = this.trajList.indexOf(traj)\n if (idx !== -1) {\n this.trajList.splice(idx, 1)\n }\n\n traj.dispose()\n\n this.signals.trajectoryRemoved.dispatch(traj)\n }\n\n dispose () {\n // copy via .slice because side effects may change trajList\n this.trajList.slice().forEach(traj => traj.dispose())\n\n this.trajList.length = 0\n this.structure.dispose()\n this.measureRepresentations.dispose()\n\n super.dispose()\n }\n\n /**\n * Automatically center and zoom the component\n * @param {String|Integer} [sele] - selection string or duration if integer\n * @param {Integer} [duration] - duration of the animation, defaults to 0\n * @return {undefined}\n */\n autoView (sele?: string|number, duration?: number) {\n if (typeof sele === 'number') {\n duration = sele\n sele = ''\n }\n\n this.stage.animationControls.zoomMove(\n this.getCenter(sele),\n this.getZoom(sele),\n defaults(duration, 0)\n )\n }\n\n getBoxUntransformed (sele: string): Box3 {\n let bb\n\n if (sele) {\n bb = this.structureView.getBoundingBox(new Selection(sele))\n } else {\n bb = this.structureView.boundingBox\n }\n\n return bb\n }\n\n getCenterUntransformed (sele: string): Vector3 {\n if (sele && typeof sele === 'string') {\n return this.structure.atomCenter(new Selection(sele))\n } else {\n return this.structure.center\n }\n }\n\n superpose (component: StructureComponent, align: boolean, sele1: string, sele2: string) {\n superpose(\n this.structureView, component.structureView, align, sele1, sele2\n )\n\n this.updateRepresentations({ 'position': true })\n\n return this\n }\n\n getMaxRepresentationRadius (atomIndex: number) {\n let maxRadius = 0\n const atom = this.structure.getAtomProxy(atomIndex)\n this.eachRepresentation(reprElem => {\n if (reprElem.getVisibility()) {\n const repr: StructureRepresentation = reprElem.repr as any // TODO\n maxRadius = Math.max(repr.getAtomRadius(atom), maxRadius)\n }\n })\n return maxRadius\n }\n\n measurePick (atom: AtomProxy) {\n const pickCount = this.pickBuffer.count\n\n if (this.lastPick === atom.index && pickCount >= 1) {\n if (pickCount > 1) {\n const atomList = this.pickBuffer.data\n const atomListSorted = this.pickBuffer.data.sort()\n if (this.pickDict.has(atomListSorted)) {\n this.pickDict.del(atomListSorted)\n } else {\n this.pickDict.add(atomListSorted, atomList)\n }\n if (pickCount === 2) {\n this.distanceRepresentation.setParameters({\n atomPair: this.pickDict.values.filter(l => l.length === 2)\n })\n } else if (pickCount === 3) {\n this.angleRepresentation.setParameters({\n atomTriple: this.pickDict.values.filter(l => l.length === 3)\n })\n } else if (pickCount === 4) {\n this.dihedralRepresentation.setParameters({\n atomQuad: this.pickDict.values.filter(l => l.length === 4)\n })\n }\n }\n this.pickBuffer.clear()\n this.lastPick = undefined\n } else {\n if (!this.pickBuffer.has(atom.index)) {\n this.pickBuffer.push(atom.index)\n }\n this.lastPick = atom.index\n }\n\n this.measureUpdate()\n }\n\n measureClear () {\n this.pickBuffer.clear()\n this.lastPick = undefined\n this.spacefillRepresentation.setSelection('none')\n }\n\n measureBuild () {\n const md = this.measureData()\n this.distanceRepresentation.setParameters({ atomPair: md.distance })\n this.angleRepresentation.setParameters({ atomTriple: md.angle })\n this.dihedralRepresentation.setParameters({ atomQuad: md.dihedral })\n }\n\n measureUpdate () {\n const pickData = this.pickBuffer.data\n const radiusData: { [k: number]: number } = {}\n pickData.forEach(ai => {\n const r = Math.max(0.1, this.getMaxRepresentationRadius(ai))\n radiusData[ ai ] = r * (2.3 - smoothstep(0.1, 2, r))\n })\n this.spacefillRepresentation.setSelection(\n pickData.length ? ( '@' + pickData.join(',') ) : 'none'\n )\n if (pickData.length)\n this.spacefillRepresentation.setParameters({ radiusData })\n }\n\n measureData () {\n const pv = this.pickDict.values\n return {\n distance: pv.filter(l => l.length === 2),\n angle: pv.filter(l => l.length === 3),\n dihedral: pv.filter(l => l.length === 4)\n }\n }\n\n /**\n * Remove all measurements, optionally limit to distance, angle or dihedral\n */\n removeAllMeasurements (type?: MeasurementFlags) {\n const pd = this.pickDict\n const pv = pd.values\n const remove = function (len: number) {\n pv.filter(l => l.length === len).forEach(l => pd.del(l.slice().sort()))\n }\n if (!type || type & MeasurementFlags.Distance) remove(2)\n if (!type || type & MeasurementFlags.Angle) remove(3)\n if (!type || type & MeasurementFlags.Dihedral) remove(4)\n this.measureBuild()\n }\n\n /**\n * Remove a measurement given as a pair, triple, quad of atom indices\n */\n removeMeasurement (atomList: number[]) {\n this.pickDict.del(atomList.slice().sort())\n this.measureBuild()\n }\n\n /**\n * Add a measurement given as a pair, triple, quad of atom indices\n */\n addMeasurement (atomList: number[]) {\n if (atomList.length < 2 || atomList.length > 4) return\n const atomListSorted = atomList.slice().sort()\n if (!this.pickDict.has(atomListSorted)) {\n this.pickDict.add(atomListSorted, atomList)\n }\n this.measureBuild()\n }\n}\n\nexport const enum MeasurementFlags {\n Distance = 0x1,\n Angle = 0x2,\n Dihedral = 0x4\n}\n\nComponentRegistry.add('structure', StructureComponent)\nComponentRegistry.add('structureview', StructureComponent)\n\nexport default StructureComponent\n","/**\n * @file Trajectory Utils\n * @author Alexander Rose \n * @private\n */\n\nimport Structure from '../structure/structure'\nimport Frames from './frames'\nimport { TrajectoryParameters } from './trajectory'\nimport FramesTrajectory from './frames-trajectory'\nimport StructureTrajectory from './structure-trajectory'\nimport RemoteTrajectory from './remote-trajectory'\nimport CallbackTrajectory from './callback-trajectory'\n\nexport function makeTrajectory (trajSrc: string|Frames, structure: Structure, params: TrajectoryParameters) {\n let traj\n\n if (trajSrc && trajSrc instanceof Frames) {\n traj = new FramesTrajectory(trajSrc, structure, params)\n } else if (!trajSrc && structure.frames) {\n traj = new StructureTrajectory(trajSrc, structure, params)\n } else if (trajSrc && typeof trajSrc === 'function') {\n traj = new CallbackTrajectory(trajSrc, structure, params)\n } else {\n traj = new RemoteTrajectory(trajSrc, structure, params)\n }\n\n return traj\n}\n\n","/**\n * @file Surface Component\n * @author Alexander Rose \n * @private\n */\n\nimport { ComponentRegistry } from '../globals'\nimport Component, { ComponentParameters } from './component'\nimport Stage from '../stage/stage'\nimport Surface from '../surface/surface'\nimport { Vector3, Box3 } from 'three';\nimport RepresentationElement from './representation-element';\n\nexport type SurfaceRepresentationType = 'surface'|'dot'\n\n/**\n * Component wrapping a {@link Surface} object\n *\n * @example\n * // get a surface component by loading a surface file into the stage\n * stage.loadFile( \"url/for/surface\" ).then( function( surfaceComponent ){\n * surfaceComponent.addRepresentation( \"surface\" );\n * surfaceComponent.autoView();\n * } );\n */\nclass SurfaceComponent extends Component {\n /**\n * @param {Stage} stage - stage object the component belongs to\n * @param {Surface} surface - surface object to wrap\n * @param {ComponentParameters} params - component parameters\n */\n constructor (stage: Stage, readonly surface: Surface, params: Partial = {}) {\n super(stage, surface, Object.assign({ name: surface.name }, params))\n }\n\n /**\n * Component type\n * @type {String}\n */\n get type () { return 'surface' }\n\n /**\n * Add a new surface representation to the component\n * @param {String} type - the name of the representation, one of:\n * surface, dot.\n * @param {SurfaceRepresentationParameters} params - representation parameters\n * @return {RepresentationComponent} the created representation wrapped into\n * a representation component object\n */\n addRepresentation (type: SurfaceRepresentationType, params: { [k: string]: any } = {}): RepresentationElement {\n return this._addRepresentation(type, this.surface, params)\n }\n\n getBoxUntransformed (): Box3 {\n return this.surface.boundingBox\n }\n\n getCenterUntransformed (): Vector3 {\n return this.surface.center\n }\n\n dispose () {\n this.surface.dispose()\n super.dispose()\n }\n}\n\nComponentRegistry.add('surface', SurfaceComponent)\n\nexport default SurfaceComponent\n","/**\n * @file Volume Component\n * @author Alexander Rose \n * @private\n */\n\nimport { ComponentRegistry } from '../globals'\nimport Component, { ComponentParameters } from './component'\nimport Stage from '../stage/stage'\nimport Volume from '../surface/volume'\nimport { Box3, Vector3 } from 'three';\nimport RepresentationElement from './representation-element';\n\nexport type VolumeRepresentationType = 'surface'|'slice'|'dot'\n\n/**\n * Component wrapping a {@link Volume} object\n *\n * @example\n * // get a volume component by loading a volume file into the stage\n * stage.loadFile( \"url/for/volume\" ).then(function(volumeComponent){\n * volumeComponent.addRepresentation('surface');\n * volumeComponent.autoView();\n * });\n */\nclass VolumeComponent extends Component {\n /**\n * @param {Stage} stage - stage object the component belongs to\n * @param {Volume} volume - volume object to wrap\n * @param {ComponentParameters} params - component parameters\n */\n constructor (stage: Stage, readonly volume: Volume, params: Partial = {}) {\n super(stage, volume, Object.assign({ name: volume.name }, params))\n }\n\n /**\n * Component type\n * @type {String}\n */\n get type () { return 'volume' }\n\n /**\n * Add a new volume representation to the component\n */\n addRepresentation (type: VolumeRepresentationType, params: { [k: string]: any } = {}): RepresentationElement {\n return this._addRepresentation(type, this.volume, params)\n }\n\n getBoxUntransformed (): Box3 {\n return this.volume.boundingBox\n }\n\n getCenterUntransformed (): Vector3 {\n return this.volume.center\n }\n\n dispose () {\n this.volume.dispose()\n\n super.dispose()\n }\n}\n\nComponentRegistry.add('volume', VolumeComponent)\n\nexport default VolumeComponent\n","/**\n * @file Component Collection\n * @author Alexander Rose \n * @private\n */\n\nimport Component from './component'\nimport Collection from './collection'\n\nclass ComponentCollection extends Collection {\n addRepresentation (name: string, params: any) {\n \treturn this.forEach((comp) => comp.addRepresentation(name, params))\n }\n\n autoView (duration: number) {\n return this.forEach((comp) => comp.autoView(duration))\n }\n}\n\nexport default ComponentCollection\n","/**\n * @file Stage\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Box3 } from 'three'\nimport { Signal } from 'signals'\n\nimport {\n Debug, Log, Mobile, ComponentRegistry, ParserRegistry\n} from '../globals'\nimport { defaults, createParams, updateParams } from '../utils'\nimport { degToRad, clamp, pclamp } from '../math/math-utils'\nimport Counter from '../utils/counter'\nimport Viewer from '../viewer/viewer'\nimport { ImageParameters } from '../viewer/viewer-utils'\nimport MouseObserver from './mouse-observer'\n\nimport TrackballControls from '../controls/trackball-controls'\nimport PickingControls from '../controls/picking-controls'\nimport ViewerControls from '../controls/viewer-controls'\nimport AnimationControls from '../controls/animation-controls'\nimport MouseControls, { MouseControlPreset } from '../controls/mouse-controls'\nimport KeyControls from '../controls/key-controls'\n\nimport PickingBehavior from './picking-behavior'\nimport MouseBehavior from './mouse-behavior'\nimport AnimationBehavior from './animation-behavior'\nimport KeyBehavior from './key-behavior'\n\nimport Component, { ComponentParameters } from '../component/component'\nimport RepresentationElement from '../component/representation-element'\nimport StructureComponent from '../component/structure-component'\nimport SurfaceComponent from '../component/surface-component'\nimport VolumeComponent from '../component/volume-component'\nimport ComponentCollection from '../component/component-collection'\nimport RepresentationCollection from '../component/representation-collection'\nimport { autoLoad, getFileInfo, LoaderParameters } from '../loader/loader-utils'\nimport { ParserParams } from '../loader/parser-loader'\nimport AtomProxy from '../proxy/atom-proxy'\nimport Animation from '../animation/animation'\nimport Selection from '../selection/selection'\n\nimport Structure from '../structure/structure'\nimport Surface from '../surface/surface'\nimport Volume from '../surface/volume'\nimport Shape from '../geometry/shape'\nimport Script from '../script'\n\nfunction matchName (name: string|RegExp, object: { name: string }) {\n if (name instanceof RegExp) {\n return object.name.match(name) !== null\n } else {\n return object.name === name\n }\n}\n\nconst tmpZoomVector = new Vector3()\n\ndeclare global {\n interface Document {\n mozFullScreen: boolean\n mozFullScreenEnabled: boolean\n mozFullScreenElement: Element\n mozCancelFullScreen(): void\n\n msFullscreenEnabled: boolean\n msFullscreenElement: Element\n msExitFullscreen(): void\n }\n\n interface Element {\n mozRequestFullScreen(): void\n msRequestFullscreen(): void\n }\n}\n\n/**\n * Stage parameter object.\n * @typedef {Object} StageParameters - stage parameters\n * @property {Color} backgroundColor - background color\n * @property {Integer} sampleLevel - sampling level for antialiasing, between -1 and 5;\n * -1: no sampling, 0: only sampling when not moving\n * @property {Boolean} workerDefault - default value for useWorker parameter of representations\n * @property {Float} rotateSpeed - camera-controls rotation speed, between 0 and 10\n * @property {Float} zoomSpeed - camera-controls zoom speed, between 0 and 10\n * @property {Float} panSpeed - camera-controls pan speed, between 0 and 10\n * @property {Float} clipNear - position of camera near/front clipping plane\n * in percent of scene bounding box\n * @property {Float} clipFar - position of camera far/back clipping plane\n * in percent of scene bounding box\n * @property {Float} clipDist - camera clipping distance in Angstrom\n * @property {String} clipMode - how to interpret clipNear/Far and fogNear/Far values: \"scene\" for scene-relative, \"camera\" for camera-relative\n * @property {String} clipScale - \"relative\" or \"absolute\": interpret clipNear/Far and fogNear/Far as percentage of bounding box or absolute Angstroms (ignored when clipMode==camera)\n * @property {Float} fogNear - position of the start of the fog effect\n * in percent of scene bounding box\n * @property {Float} fogFar - position where the fog is in full effect\n * in percent of scene bounding box\n * @property {String} cameraType - type of camera, either 'persepective' or 'orthographic'\n * @property {Float} cameraFov - perspective camera field of view in degree, between 15 and 120\n * @property {Float} cameraEyeSep - stereo camera eye seperation\n * @property {Color} lightColor - point light color\n * @property {Float} lightIntensity - point light intensity\n * @property {Color} ambientColor - ambient light color\n * @property {Float} ambientIntensity - ambient light intensity\n * @property {Integer} hoverTimeout - timeout for hovering\n */\n\nexport interface StageSignals {\n parametersChanged: Signal\n fullscreenChanged: Signal\n componentAdded: Signal\n componentRemoved: Signal\n clicked: Signal\n hovered: Signal\n}\n\nexport type RenderQualityType = 'auto'|'low'|'medium'|'high'\n\nexport const StageDefaultParameters = {\n impostor: true,\n quality: 'medium' as RenderQualityType,\n workerDefault: true,\n sampleLevel: 0,\n backgroundColor: 'black' as string|number,\n rotateSpeed: 2.0,\n zoomSpeed: 1.2,\n panSpeed: 1.0,\n clipNear: 0,\n clipFar: 100,\n clipDist: 10,\n clipMode: 'scene',\n clipScale: 'relative',\n fogNear: 50,\n fogFar: 100,\n cameraFov: 40,\n cameraEyeSep: 0.3,\n cameraType: 'perspective' as 'perspective'|'orthographic'|'stereo',\n lightColor: 0xdddddd as string|number,\n lightIntensity: 1.0,\n ambientColor: 0xdddddd as string|number,\n ambientIntensity: 0.2,\n hoverTimeout: 0,\n tooltip: true,\n mousePreset: 'default' as MouseControlPreset\n}\nexport type StageParameters = typeof StageDefaultParameters\n\nexport interface StageLoadFileParams extends LoaderParameters {\n defaultRepresentation: boolean,\n assembly: string\n}\n\n/**\n * Stage class, central for creating molecular scenes with NGL.\n *\n * @example\n * var stage = new Stage( \"elementId\", { backgroundColor: \"white\" } );\n */\nclass Stage {\n signals: StageSignals = {\n parametersChanged: new Signal(),\n fullscreenChanged: new Signal(),\n componentAdded: new Signal(),\n componentRemoved: new Signal(),\n clicked: new Signal(),\n hovered: new Signal()\n }\n parameters: StageParameters\n\n /**\n * Counter that keeps track of various potentially long-running tasks,\n * including file loading and surface calculation.\n */\n tasks = new Counter()\n compList: Component[] = []\n defaultFileParams = {}\n logList: string[] = []\n\n transformComponent?: Component\n transformAtom?: AtomProxy\n\n viewer: Viewer\n tooltip: HTMLElement\n lastFullscreenElement: HTMLElement\n\n mouseObserver: MouseObserver\n viewerControls: ViewerControls\n trackballControls: TrackballControls\n pickingControls: PickingControls\n animationControls: AnimationControls\n mouseControls: MouseControls\n keyControls: KeyControls\n\n pickingBehavior: PickingBehavior\n mouseBehavior: MouseBehavior\n animationBehavior: AnimationBehavior\n keyBehavior: KeyBehavior\n\n spinAnimation: Animation\n rockAnimation: Animation\n\n constructor (idOrElement: string|HTMLElement, params: Partial = {}) {\n this.viewer = new Viewer(idOrElement)\n if (!this.viewer.renderer) return\n\n this.tooltip = document.createElement('div')\n Object.assign(this.tooltip.style, {\n display: 'none',\n position: 'fixed',\n zIndex: '1000000',\n pointerEvents: 'none',\n backgroundColor: 'rgba( 0, 0, 0, 0.6 )',\n color: 'lightgrey',\n padding: '8px',\n fontFamily: 'sans-serif'\n })\n this.viewer.container.appendChild(this.tooltip)\n\n this.mouseObserver = new MouseObserver(this.viewer.renderer.domElement)\n this.viewerControls = new ViewerControls(this)\n this.trackballControls = new TrackballControls(this)\n this.pickingControls = new PickingControls(this)\n this.animationControls = new AnimationControls(this)\n this.mouseControls = new MouseControls(this)\n this.keyControls = new KeyControls(this)\n\n this.pickingBehavior = new PickingBehavior(this)\n this.mouseBehavior = new MouseBehavior(this)\n this.animationBehavior = new AnimationBehavior(this)\n this.keyBehavior = new KeyBehavior(this)\n\n this.spinAnimation = this.animationControls.spin([ 0, 1, 0 ], 0.005)\n this.spinAnimation.pause(true)\n this.rockAnimation = this.animationControls.rock([ 0, 1, 0 ], 0.005)\n this.rockAnimation.pause(true)\n\n // must come after the viewer has been instantiated\n this.parameters = createParams(params, StageDefaultParameters)\n this.setParameters(this.parameters)\n\n this.viewer.animate()\n }\n\n /**\n * Set stage parameters\n */\n setParameters (params: Partial = {}) {\n updateParams(this.parameters, params)\n\n const p = params\n const tp = this.parameters\n\n const viewer = this.viewer\n const controls = this.trackballControls\n\n // apply parameters\n if (p.quality !== undefined) this.setQuality(tp.quality)\n if (p.impostor !== undefined) this.setImpostor(tp.impostor)\n if (p.rotateSpeed !== undefined) controls.rotateSpeed = tp.rotateSpeed\n if (p.zoomSpeed !== undefined) controls.zoomSpeed = tp.zoomSpeed\n if (p.panSpeed !== undefined) controls.panSpeed = tp.panSpeed\n if (p.mousePreset !== undefined) this.mouseControls.preset(tp.mousePreset)\n this.mouseObserver.setParameters({ hoverTimeout: tp.hoverTimeout })\n viewer.setClip(tp.clipNear, tp.clipFar, tp.clipDist, tp.clipMode, tp.clipScale)\n viewer.setFog(undefined, tp.fogNear, tp.fogFar)\n viewer.setCamera(tp.cameraType, tp.cameraFov, tp.cameraEyeSep)\n viewer.setSampling(tp.sampleLevel)\n viewer.setBackground(tp.backgroundColor)\n viewer.setLight(tp.lightColor, tp.lightIntensity, tp.ambientColor, tp.ambientIntensity)\n\n this.signals.parametersChanged.dispatch(this.getParameters())\n\n return this\n }\n\n log (msg: string) {\n console.log('STAGE LOG', msg)\n this.logList.push(msg)\n }\n\n /**\n * Get stage parameters\n */\n getParameters () {\n return Object.assign({}, this.parameters)\n }\n\n /**\n * Create default representations for the given component\n * @param {StructureComponent|SurfaceComponent} object - component to create the representations for\n * @return {undefined}\n */\n defaultFileRepresentation (component: Component) {\n if (component instanceof StructureComponent) {\n component.setSelection('/0')\n\n let atomCount, residueCount, instanceCount\n const structure = component.structure\n\n if (structure.biomolDict.BU1) {\n const assembly = structure.biomolDict.BU1\n atomCount = assembly.getAtomCount(structure)\n residueCount = assembly.getResidueCount(structure)\n instanceCount = assembly.getInstanceCount()\n component.setDefaultAssembly('BU1')\n } else {\n atomCount = structure.getModelProxy(0).atomCount\n residueCount = structure.getModelProxy(0).residueCount\n instanceCount = 1\n }\n\n let sizeScore = atomCount\n\n if (Mobile) {\n sizeScore *= 4\n }\n\n const backboneOnly = structure.atomStore.count / structure.residueStore.count < 2\n if (backboneOnly) {\n sizeScore *= 10\n }\n\n let colorScheme = 'chainname'\n let colorScale = 'RdYlBu'\n let colorReverse = false\n if (structure.getChainnameCount(new Selection('polymer and /0')) === 1) {\n colorScheme = 'residueindex'\n colorScale = 'Spectral'\n colorReverse = true\n }\n\n if (Debug) console.log(sizeScore, atomCount, instanceCount, backboneOnly)\n\n if (residueCount / instanceCount < 4) {\n component.addRepresentation('ball+stick', {\n colorScheme: 'element',\n radiusScale: 2.0,\n aspectRatio: 1.5,\n bondScale: 0.3,\n bondSpacing: 0.75,\n quality: 'auto'\n })\n } else if ((instanceCount > 5 && sizeScore > 15000) || sizeScore > 700000) {\n let scaleFactor = (\n Math.min(\n 2.0,\n Math.max(\n 0.1,\n 6000 / (sizeScore / instanceCount)\n )\n )\n )\n if (backboneOnly) scaleFactor = Math.min(scaleFactor, 0.5)\n\n component.addRepresentation('surface', {\n colorScheme, colorScale, colorReverse,\n sele: 'polymer',\n surfaceType: 'av',\n probeRadius: 1.4,\n scaleFactor: scaleFactor,\n useWorker: false\n })\n } else if (sizeScore > 250000) {\n component.addRepresentation('backbone', {\n colorScheme, colorScale, colorReverse,\n lineOnly: true\n })\n } else if (sizeScore > 100000) {\n component.addRepresentation('backbone', {\n colorScheme, colorScale, colorReverse,\n quality: 'low',\n disableImpostor: true,\n radiusScale: 2.0\n })\n } else if (sizeScore > 80000) {\n component.addRepresentation('backbone', {\n colorScheme, colorScale, colorReverse,\n radiusScale: 2.0\n })\n } else {\n component.addRepresentation('cartoon', {\n colorScheme, colorScale, colorReverse,\n radiusScale: 0.7,\n aspectRatio: 5,\n quality: 'auto'\n })\n if (sizeScore < 50000) {\n component.addRepresentation('base', {\n colorScheme, colorScale, colorReverse,\n quality: 'auto'\n })\n }\n component.addRepresentation('ball+stick', {\n sele: 'ligand',\n colorScheme: 'element',\n radiusScale: 2.0,\n aspectRatio: 1.5,\n bondScale: 0.3,\n bondSpacing: 0.75,\n quality: 'auto'\n })\n }\n\n // add frames as trajectory\n if (component.structure.frames.length) {\n component.addTrajectory()\n }\n } else if (component instanceof SurfaceComponent) {\n component.addRepresentation('surface')\n } else if (component instanceof VolumeComponent) {\n component.addRepresentation('surface')\n }\n\n this.tasks.onZeroOnce(this.autoView, this)\n }\n\n /**\n * Load a file onto the stage\n *\n * @example\n * // load from URL\n * stage.loadFile( \"http://files.rcsb.org/download/5IOS.cif\" );\n *\n * @example\n * // load binary data in CCP4 format via a Blob\n * var binaryBlob = new Blob( [ ccp4Data ], { type: 'application/octet-binary'} );\n * stage.loadFile( binaryBlob, { ext: \"ccp4\" } );\n *\n * @example\n * // load string data in PDB format via a Blob\n * var stringBlob = new Blob( [ pdbData ], { type: 'text/plain'} );\n * stage.loadFile( stringBlob, { ext: \"pdb\" } );\n *\n * @example\n * // load a File object\n * stage.loadFile( file );\n *\n * @example\n * // load from URL and add a 'ball+stick' representation with double/triple bonds\n * stage.loadFile( \"http://files.rcsb.org/download/1crn.cif\" ).then( function( comp ){\n * comp.addRepresentation( \"ball+stick\", { multipleBond: true } );\n * } );\n *\n * @param {String|File|Blob} path - either a URL or an object containing the file data\n * @param {LoaderParameters} params - loading parameters\n * @param {Boolean} params.asTrajectory - load multi-model structures as a trajectory\n * @return {Promise} A Promise object that resolves to a {@link StructureComponent},\n * a {@link SurfaceComponent} or a {@link ScriptComponent} object,\n * depending on the type of the loaded file.\n */\n loadFile (path: string|File|Blob, params: Partial = {}) {\n const p = Object.assign({}, this.defaultFileParams, params)\n const name = getFileInfo(path).name\n\n this.tasks.increment()\n this.log(`loading file '${name}'`)\n\n const onLoadFn = (object: Structure|Surface|Volume) => {\n this.log(`loaded '${name}'`)\n\n const component = this.addComponentFromObject(object, p)\n if (p.defaultRepresentation) {\n this.defaultFileRepresentation(component as Component)\n }\n this.tasks.decrement()\n\n return component\n }\n\n const onErrorFn = (e: Error|string) => {\n this.tasks.decrement()\n const errorMsg = `error loading file: '${e}'`\n this.log(errorMsg)\n throw errorMsg // throw so it can be catched\n }\n\n const ext = defaults(p.ext, getFileInfo(path).ext)\n let promise: Promise\n\n if (ParserRegistry.isTrajectory(ext)) {\n promise = Promise.reject(\n new Error(`loadFile: ext '${ext}' is a trajectory and must be loaded into a structure component`)\n )\n } else {\n promise = autoLoad(path, p)\n }\n\n return promise.then(onLoadFn, onErrorFn)\n }\n\n loadScript (path: string|File|Blob) {\n const name = getFileInfo(path).name\n\n this.log(`loading script '${name}'`)\n\n return autoLoad(path).then(\n (script: Script) => {\n this.tasks.increment()\n this.log(`running script '${name}'`)\n script.run(this).then(() => {\n this.tasks.decrement()\n this.log(`finished script '${name}'`)\n })\n this.log(`called script '${name}'`)\n },\n (error: Error|string) => {\n this.tasks.decrement()\n const errorMsg = `errored script '${name}' \"${error}\"`\n this.log(errorMsg)\n throw errorMsg // throw so it can be catched\n }\n )\n }\n\n /**\n * Add the given component to the stage\n * @param {Component} component - the component to add\n * @return {undefined}\n */\n addComponent (component: Component) {\n if (!component) {\n Log.warn('Stage.addComponent: no component given')\n return\n }\n\n this.compList.push(component)\n this.signals.componentAdded.dispatch(component)\n }\n\n /**\n * Create a component from the given object and add to the stage\n */\n addComponentFromObject (object: Structure|Surface|Volume|Shape, params: Partial = {}): void|Component {\n const CompClass = ComponentRegistry.get(object.type)\n\n if (CompClass) {\n const component = new CompClass(this, object, params)\n this.addComponent(component)\n return component\n }\n\n Log.warn('no component for object type', object.type)\n }\n\n /**\n * Remove the given component\n * @param {Component} component - the component to remove\n * @return {undefined}\n */\n removeComponent (component: Component) {\n const idx = this.compList.indexOf(component)\n if (idx !== -1) {\n this.compList.splice(idx, 1)\n component.dispose()\n this.signals.componentRemoved.dispatch(component)\n }\n }\n\n /**\n * Remove all components from the stage\n */\n removeAllComponents () {\n this.compList.slice().forEach(o => this.removeComponent(o))\n }\n\n /**\n * Handle any size-changes of the container element\n * @return {undefined}\n */\n handleResize () {\n this.viewer.handleResize()\n }\n\n /**\n * Set width and height\n * @param {String} width - CSS width value\n * @param {String} height - CSS height value\n * @return {undefined}\n */\n setSize (width: string, height: string) {\n const container = this.viewer.container\n\n if (container !== document.body) {\n if (width !== undefined) container.style.width = width\n if (height !== undefined) container.style.height = height\n this.handleResize()\n }\n }\n\n /**\n * Toggle fullscreen\n * @param {Element} [element] - document element to put into fullscreen,\n * defaults to the viewer container\n * @return {undefined}\n */\n toggleFullscreen (element: HTMLElement) {\n if (!document.fullscreenEnabled && !document.mozFullScreenEnabled &&\n !(document as any).webkitFullscreenEnabled && !document.msFullscreenEnabled\n ) {\n Log.log('fullscreen mode (currently) not possible')\n return\n }\n\n const self = this\n element = element || this.viewer.container\n this.lastFullscreenElement = element\n\n //\n\n function getFullscreenElement () {\n return document.fullscreenElement || document.mozFullScreenElement ||\n (document as any).webkitFullscreenElement || document.msFullscreenElement\n }\n\n function resizeElement () {\n if (!getFullscreenElement() && self.lastFullscreenElement) {\n const element = self.lastFullscreenElement\n element.style.width = element.dataset.normalWidth || ''\n element.style.height = element.dataset.normalHeight || ''\n\n document.removeEventListener('fullscreenchange', resizeElement)\n document.removeEventListener('mozfullscreenchange', resizeElement)\n document.removeEventListener('webkitfullscreenchange', resizeElement)\n document.removeEventListener('MSFullscreenChange', resizeElement)\n\n self.handleResize()\n self.signals.fullscreenChanged.dispatch(false)\n }\n }\n\n //\n\n if (!getFullscreenElement()) {\n element.dataset.normalWidth = element.style.width || ''\n element.dataset.normalHeight = element.style.height || ''\n element.style.width = window.screen.width + 'px'\n element.style.height = window.screen.height + 'px'\n\n if (element.requestFullscreen) {\n element.requestFullscreen()\n } else if (element.msRequestFullscreen) {\n element.msRequestFullscreen()\n } else if (element.mozRequestFullScreen) {\n element.mozRequestFullScreen()\n } else if ((element as any).webkitRequestFullscreen) {\n (element as any).webkitRequestFullscreen()\n }\n\n document.addEventListener('fullscreenchange', resizeElement)\n document.addEventListener('mozfullscreenchange', resizeElement)\n document.addEventListener('webkitfullscreenchange', resizeElement)\n document.addEventListener('MSFullscreenChange', resizeElement)\n\n this.handleResize()\n this.signals.fullscreenChanged.dispatch(true)\n\n // workaround for Safari\n setTimeout(function () { self.handleResize() }, 100)\n } else {\n if (document.exitFullscreen) {\n document.exitFullscreen()\n } else if (document.msExitFullscreen) {\n document.msExitFullscreen()\n } else if (document.mozCancelFullScreen) {\n document.mozCancelFullScreen()\n } else if ((document as any).webkitExitFullscreen) {\n (document as any).webkitExitFullscreen()\n }\n }\n }\n\n /**\n * Set spin\n * @param {Boolean} flag - if true start rocking and stop spinning\n * @return {undefined}\n */\n setSpin (flag: boolean) {\n if (flag) {\n this.spinAnimation.resume(true)\n this.rockAnimation.pause(true)\n } else {\n this.spinAnimation.pause(true)\n }\n }\n\n /**\n * Set rock\n * @param {Boolean} flag - if true start rocking and stop spinning\n * @return {undefined}\n */\n setRock (flag: boolean) {\n if (flag) {\n this.rockAnimation.resume(true)\n this.spinAnimation.pause(true)\n } else {\n this.rockAnimation.pause(true)\n }\n }\n\n /**\n * Toggle spin\n * @return {undefined}\n */\n toggleSpin () {\n this.setSpin(this.spinAnimation.paused)\n }\n\n /**\n * Toggle rock\n * @return {undefined}\n */\n toggleRock () {\n this.setRock(this.rockAnimation.paused)\n }\n\n /**\n * Get the current focus from the current clipNear value expressed\n * as 0 (full view) to 100 (completely clipped)\n * Negative values may be returned in some cases.\n *\n * In 'camera' clipMode focus isn't applicable, this method returns 0.0\n *\n * @return {number} focus\n */\n getFocus () : number {\n const p = this.parameters\n if (p.clipMode !== 'scene') return 0.0\n\n let clipNear = p.clipNear\n if (p.clipScale === 'absolute') {\n clipNear = this.viewer.absoluteToRelative(clipNear)\n }\n return clipNear * 2\n }\n\n\n /**\n * Set the focus, a value of 0 sets clipping planes to show full scene,\n * while a value of 100 will compltely clip the scene.\n *\n * @param {number} value focus\n */\n setFocus (value: number) {\n if (this.parameters.clipMode !== 'scene') return\n\n let clipNear\n let clipFar\n let fogNear\n let fogFar\n\n if (this.parameters.clipScale === 'relative') {\n clipNear = clamp(value / 2.0, 0.0, 49.9)\n clipFar = 100 - clipNear\n fogNear = 50\n fogFar = pclamp(2 * clipFar - 50)\n\n } else {\n clipNear = this.viewer.relativeToAbsolute(value / 2.0)\n clipFar = clipNear\n fogNear = 0\n fogFar = 2 * clipFar\n }\n\n this.setParameters({ clipNear, clipFar, fogNear, fogFar })\n }\n\n getZoomForBox (boundingBox: Box3) {\n const bbSize = boundingBox.getSize(tmpZoomVector)\n const maxSize = Math.max(bbSize.x, bbSize.y, bbSize.z)\n const minSize = Math.min(bbSize.x, bbSize.y, bbSize.z)\n let distance = maxSize + Math.sqrt(minSize)\n\n const fov = degToRad(this.viewer.perspectiveCamera.fov)\n const width = this.viewer.width\n const height = this.viewer.height\n const aspect = width / height\n const aspectFactor = (height < width ? 1 : aspect)\n\n distance = Math.abs(\n ((distance * 0.5) / aspectFactor) / Math.sin(fov / 2)\n )\n distance += this.parameters.clipDist\n return -distance\n }\n\n getBox () {\n return this.viewer.boundingBox\n }\n\n getZoom () {\n return this.getZoomForBox(this.getBox())\n }\n\n getCenter (optionalTarget?: Vector3) {\n return this.getBox().getCenter(optionalTarget || new Vector3())\n }\n\n /**\n * Add a zoom and a move animation with automatic targets\n * @param {Integer} duration - animation time in milliseconds\n * @return {undefined}\n */\n autoView (duration?: number) {\n this.animationControls.zoomMove(\n this.getCenter(),\n this.getZoom(),\n defaults(duration, 0)\n )\n }\n\n /**\n * Make image from what is shown in a viewer canvas\n */\n makeImage (params: Partial = {}) {\n return new Promise((resolve, reject) => {\n this.tasks.onZeroOnce(() => {\n this.tasks.increment()\n this.viewer.makeImage(params).then(blob => {\n this.tasks.decrement()\n resolve(blob)\n }).catch(e => {\n this.tasks.decrement()\n reject(e)\n })\n })\n })\n }\n\n setImpostor (value: boolean) {\n this.parameters.impostor = value\n\n const types = [\n 'spacefill', 'ball+stick', 'licorice', 'hyperball',\n 'backbone', 'rocket', 'helixorient', 'contact', 'distance',\n 'dot'\n ]\n\n this.eachRepresentation(function (reprElem) {\n if (!types.includes(reprElem.getType())) return\n\n const p = reprElem.getParameters() as any // TODO\n p.disableImpostor = !value\n reprElem.build(p)\n })\n }\n\n setQuality (value: RenderQualityType) {\n this.parameters.quality = value\n\n const types = [\n 'tube', 'cartoon', 'ribbon', 'trace', 'rope'\n ]\n\n const impostorTypes = [\n 'spacefill', 'ball+stick', 'licorice', 'hyperball',\n 'backbone', 'rocket', 'helixorient', 'contact', 'distance',\n 'dot'\n ]\n\n this.eachRepresentation(function (repr) {\n const p = repr.getParameters() as any // TODO\n\n if (!types.includes(repr.getType())) {\n if (!impostorTypes.includes(repr.getType())) return\n\n if (!p.disableImpostor) {\n (repr.repr as any).quality = value // TODO\n return\n }\n }\n\n p.quality = value\n repr.build(p)\n })\n }\n\n /**\n * Iterator over each component and executing the callback\n */\n eachComponent (callback: (comp: Component) => void, type?: string) {\n this.compList.slice().forEach(comp => {\n if (type === undefined || type === comp.type) callback(comp)\n })\n }\n\n /**\n * Iterator over each representation and executing the callback\n */\n eachRepresentation (callback: (reprElem: RepresentationElement, comp: Component) => void, type?: string) {\n this.eachComponent(comp => {\n comp.reprList.slice().forEach(reprElem => {\n if (type === undefined || type === reprElem.getType()) callback(reprElem, comp)\n })\n })\n }\n\n /**\n * Get collection of components by name\n */\n getComponentsByName (name: string|RegExp) {\n const compList: Component[] = []\n\n this.eachComponent(comp => {\n if (name === undefined || matchName(name, comp)) compList.push(comp)\n })\n\n return new ComponentCollection(compList)\n }\n\n /**\n * Get collection of components by object\n */\n getComponentsByObject (object: Structure|Surface|Volume|Shape) {\n const compList: Component[] = []\n\n this.eachComponent(comp => {\n if (comp.object === object) compList.push(comp)\n })\n\n return new ComponentCollection(compList)\n }\n\n /**\n * Get collection of representations by name\n */\n getRepresentationsByName (name: string|RegExp) {\n const reprList: RepresentationElement[] = []\n\n this.eachRepresentation((repr, comp) => {\n if (name === undefined || matchName(name, repr)) reprList.push(repr)\n })\n\n return new RepresentationCollection(reprList)\n }\n\n measureClear () {\n this.eachComponent((sc: StructureComponent) => sc.measureClear(), 'structure')\n }\n\n measureUpdate () {\n this.eachComponent((sc: StructureComponent) => sc.measureUpdate(), 'structure')\n }\n\n /**\n * Cleanup when disposing of a stage object\n */\n dispose () {\n this.tasks.dispose()\n this.viewer.dispose()\n this.mouseObserver.dispose()\n }\n}\n\nexport default Stage\n","/**\n * @file Shape Component\n * @author Alexander Rose \n * @private\n */\n\nimport { ComponentRegistry } from '../globals'\nimport Component, { ComponentParameters } from './component'\nimport Stage from '../stage/stage'\nimport Shape from '../geometry/shape'\nimport { Vector3, Box3 } from 'three';\nimport RepresentationElement from './representation-element';\n\nexport type ShapeRepresentationType = 'buffer'\n\n/**\n * Component wrapping a {@link Shape} object\n *\n * @example\n * // get a shape component by adding a shape object to the stage\n * var shape = new NGL.Shape( \"shape\" );\n * shape.addSphere( [ 0, 0, 0 ], [ 1, 0, 0 ], 1.5 );\n * var shapeComponent = stage.addComponentFromObject( shape );\n * shapeComponent.addRepresentation( \"buffer\" );\n */\nclass ShapeComponent extends Component {\n constructor (stage: Stage, readonly shape: Shape, params: Partial = {}) {\n super(stage, shape, Object.assign({ name: shape.name }, params))\n }\n\n /**\n * Component type\n * @type {String}\n */\n get type () { return 'shape' }\n\n /**\n * Add a new shape representation to the component\n * @param {String} type - the name of the representation, one of:\n * buffer.\n * @param {BufferRepresentationParameters} params - representation parameters\n * @return {RepresentationComponent} the created representation wrapped into\n * a representation component object\n */\n addRepresentation (type: ShapeRepresentationType, params: { [k: string]: any } = {}): RepresentationElement {\n return this._addRepresentation(type, this.shape, params)\n }\n\n getBoxUntransformed (): Box3 {\n return this.shape.boundingBox\n }\n\n getCenterUntransformed (): Vector3 {\n return this.shape.center\n }\n\n dispose () {\n this.shape.dispose()\n super.dispose()\n }\n}\n\nComponentRegistry.add('shape', ShapeComponent)\n\nexport default ShapeComponent\n","/******************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n var desc = Object.getOwnPropertyDescriptor(m, k);\r\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\r\n desc = { enumerable: true, get: function() { return m[k]; } };\r\n }\r\n Object.defineProperty(o, k2, desc);\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || Array.prototype.slice.call(from));\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n\r\nexport function __classPrivateFieldIn(state, receiver) {\r\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\r\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\r\n}\r\n","/**\n * @file Atomindex Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ModelProxy from '../proxy/model-proxy'\n\n/**\n * Color by atom index. The {@link AtomProxy.index} property is used for coloring.\n * Each {@link ModelProxy} of a {@link Structure} is colored seperately. The\n * `params.domain` parameter is ignored.\n *\n * __Name:__ _atomindex_\n *\n * @example\n * stage.loadFile( \"rcsb://1crn\" ).then( function( o ){\n * o.addRepresentation( \"ball+stick\", { colorScheme: \"atomindex\" } );\n * o.autoView();\n * } );\n */\nclass AtomindexColormaker extends Colormaker {\n scalePerModel: { [k: number]: ColormakerScale }\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'rainbow'\n this.parameters.reverse = defaults(params.reverse, true)\n }\n\n this.scalePerModel = {}\n\n params.structure.eachModel((mp: ModelProxy) => {\n this.parameters.domain = [ mp.atomOffset, mp.atomEnd ]\n this.scalePerModel[ mp.index ] = this.getScale() // TODO\n })\n }\n\n /**\n * get color for an atom\n * @param {AtomProxy} atom - atom to get color for\n * @return {Integer} hex atom color\n */\n @manageColor\n atomColor (atom: AtomProxy) {\n return this.scalePerModel[ atom.modelIndex ](atom.index)\n }\n}\n\nColormakerRegistry.add('atomindex', AtomindexColormaker)\n\nexport default AtomindexColormaker\n","/**\n * @file Bfactor Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport Selection from '../selection/selection'\n\n/**\n * Color by b-factor. The {@link AtomProxy.bfactor} property is used for coloring.\n * By default the min and max b-factor values are used for the scale`s domain.\n *\n * __Name:__ _bfactor_\n *\n * @example\n * stage.loadFile( \"rcsb://1crn\" ).then( function( o ){\n * o.addRepresentation( \"ball+stick\", { colorScheme: \"bfactor\" } );\n * o.autoView();\n * } );\n */\nclass BfactorColormaker extends Colormaker {\n bfactorScale: ColormakerScale\n\n constructor (params: { sele?: string } & StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'OrRd'\n }\n\n if (!params.domain) {\n let selection\n let min = Infinity\n let max = -Infinity\n\n if (params.sele) {\n selection = new Selection(params.sele)\n }\n\n params.structure.eachAtom(function (a) {\n const bfactor = a.bfactor\n min = Math.min(min, bfactor)\n max = Math.max(max, bfactor)\n }, selection)\n\n this.parameters.domain = [ min, max ]\n }\n\n this.bfactorScale = this.getScale()\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n return this.bfactorScale(a.bfactor)\n }\n}\n\nColormakerRegistry.add('bfactor', BfactorColormaker)\n\nexport default BfactorColormaker\n","/**\n * @file Chainid Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ChainProxy from '../proxy/chain-proxy'\nimport ModelProxy from '../proxy/model-proxy'\n\nexport type ChainidDict = { [k: string]: number }\n\n/**\n * Color by chain id\n */\nclass ChainidColormaker extends Colormaker {\n chainidDictPerModel: { [k: number]: ChainidDict } = {}\n scalePerModel: { [k: number]: ColormakerScale } = {}\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'Spectral'\n }\n\n params.structure.eachModel((mp: ModelProxy) => {\n let i = 0\n const chainidDict: ChainidDict = {}\n mp.eachChain(function (cp: ChainProxy) {\n if (chainidDict[ cp.chainid ] === undefined) {\n chainidDict[ cp.chainid ] = i\n i += 1\n }\n })\n this.parameters.domain = [ 0, i - 1 ]\n this.chainidDictPerModel[ mp.index ] = chainidDict\n this.scalePerModel[ mp.index ] = this.getScale()\n })\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n const chainidDict = this.chainidDictPerModel[ a.modelIndex ]\n return this.scalePerModel[ a.modelIndex ](chainidDict[ a.chainid ])\n }\n}\n\nColormakerRegistry.add('chainid', ChainidColormaker)\n\nexport default ChainidColormaker\n","/**\n * @file Chainindex Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ModelProxy from '../proxy/model-proxy'\n\n/**\n * Color by chain index\n */\nclass ChainindexColormaker extends Colormaker {\n scalePerModel: { [k: number]: ColormakerScale } = {}\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'Spectral'\n }\n\n params.structure.eachModel((mp: ModelProxy) => {\n this.parameters.domain = [ mp.chainOffset, mp.chainEnd ]\n this.scalePerModel[ mp.index ] = this.getScale()\n })\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n return this.scalePerModel[ a.modelIndex ](a.chainIndex)\n }\n}\n\nColormakerRegistry.add('chainindex', ChainindexColormaker)\n\nexport default ChainindexColormaker\n","/**\n * @file Chainname Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ChainProxy from '../proxy/chain-proxy'\nimport ModelProxy from '../proxy/model-proxy'\n\nexport type ChainnameDict = { [k: string]: number }\n\n/**\n * Color by chain name\n */\nclass ChainnameColormaker extends Colormaker {\n chainnameDictPerModel: { [k: number]: ChainnameDict } = {}\n scalePerModel: { [k: number]: ColormakerScale } = {}\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'Spectral'\n }\n\n params.structure.eachModel((mp: ModelProxy) => {\n let i = 0\n const chainnameDict: ChainnameDict = {}\n mp.eachChain(function (cp: ChainProxy) {\n if (chainnameDict[ cp.chainname ] === undefined) {\n chainnameDict[ cp.chainname ] = i\n i += 1\n }\n })\n this.parameters.domain = [ 0, i - 1 ]\n this.chainnameDictPerModel[ mp.index ] = chainnameDict\n this.scalePerModel[ mp.index ] = this.getScale()\n })\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n const chainnameDict = this.chainnameDictPerModel[ a.modelIndex ]\n return this.scalePerModel[ a.modelIndex ](chainnameDict[ a.chainname ])\n }\n}\n\nColormakerRegistry.add('chainname', ChainnameColormaker)\n\nexport default ChainnameColormaker\n","/**\n * @file Densityfit Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Color by validation density fit\n */\nclass DensityfitColormaker extends Colormaker {\n rsrzScale: ColormakerScale\n rsccScale: ColormakerScale\n\n rsrzDict: { [k: string]: number|undefined } = {}\n rsccDict: { [k: string]: number|undefined } = {}\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'RdYlBu'\n }\n\n this.rsrzScale = this.getScale({ domain: [ 2, 0 ] })\n this.rsccScale = this.getScale({ domain: [ 0.678, 1.0 ] })\n\n const val = params.structure.validation\n if (val) {\n this.rsrzDict = val.rsrzDict\n this.rsccDict = val.rsccDict\n }\n\n }\n\n @manageColor\n atomColor (atom: AtomProxy) {\n let sele = atom.resno + ''\n if (atom.inscode) sele += '^' + atom.inscode\n if (atom.chainname) sele += ':' + atom.chainname\n sele += '/' + atom.modelIndex\n\n const rsrz = this.rsrzDict[ sele ]\n if (rsrz !== undefined) {\n return this.rsrzScale(rsrz)\n }\n\n const rscc = this.rsccDict[ sele ]\n if (rscc !== undefined) {\n return this.rsccScale(rscc)\n }\n\n return 0x909090\n }\n}\n\nColormakerRegistry.add('densityfit', DensityfitColormaker)\n\nexport default DensityfitColormaker\n","/**\n * @file Atomindex Colormaker\n * @author Fred Ludlow \n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport SpatialHash from '../geometry/spatial-hash'\n\n// from CHARMM\nconst partialCharges: { [k: string]: { [k: string]: number } } = {\n 'ARG': {\n 'CD': 0.1,\n 'CZ': 0.5,\n 'NE': -0.1\n },\n 'ASN': {\n 'CG': 0.55,\n 'OD1': -0.55\n },\n 'ASP': {\n 'CB': -0.16,\n 'CG': 0.36,\n 'OD1': -0.6,\n 'OD2': -0.6\n },\n 'CYS': {\n 'CB': 0.19,\n 'SG': -0.19\n },\n 'GLN': {\n 'CD': 0.55,\n 'OE1': -0.55\n },\n 'GLU': {\n 'CD': 0.36,\n 'CG': -0.16,\n 'OE1': -0.6,\n 'OE2': -0.6\n },\n 'HIS': {\n 'CB': 0.1,\n 'CD2': 0.2,\n 'CE1': 0.45,\n 'CG': 0.15,\n 'ND1': 0.05,\n 'NE2': 0.05\n },\n 'LYS': {\n 'CE': 0.25,\n 'NZ': 0.75\n },\n 'MET': {\n 'CE': 0.06,\n 'CG': 0.06,\n 'SD': -0.12\n },\n 'PTR': {\n 'C': 0.55,\n 'CA': 0.1,\n 'CZ': 0.25,\n 'N': -0.35,\n 'O': -0.55,\n 'O1P': -0.85,\n 'O2P': -0.85,\n 'O3P': -0.85,\n 'OG1': -1.1,\n 'P': 1.4\n },\n 'SEP': {\n 'C': 0.55,\n 'CA': 0.1,\n 'CB': 0.25,\n 'N': -0.35,\n 'O': -0.55,\n 'O1P': -0.85,\n 'O2P': -0.85,\n 'O3P': -0.85,\n 'OG1': -1.1,\n 'P': 1.4\n },\n 'SER': {\n 'CB': 0.25,\n 'OG': -0.25\n },\n 'THR': {\n 'CB': 0.25,\n 'OG1': -0.25\n },\n 'TPO': {\n 'C': 0.55,\n 'CA': 0.1,\n 'CB': 0.25,\n 'N': -0.35,\n 'O': -0.55,\n 'OG1': -1.1,\n 'O1P': -0.85,\n 'O2P': -0.85,\n 'O3P': -0.85,\n 'P': 1.4\n },\n 'TRP': {\n 'CD1': 0.06,\n 'CD2': 0.1,\n 'CE2': -0.04,\n 'CE3': -0.03,\n 'CG': -0.03,\n 'NE1': -0.06\n },\n 'TYR': {\n 'CZ': 0.25,\n 'OH': -0.25\n },\n 'backbone': {\n 'C': 0.55,\n 'O': -0.55,\n 'N': -0.35,\n 'CA': 0.1\n }\n}\n\nconst maxRadius = 12.0\nconst nHBondDistance = 1.04\nconst nHCharge = 0.25\n\n/**\n * Populates position vector with location of implicit or explicit H\n * Returns position or undefined if not able to locate H\n *\n * @param {AtomProxy} ap - the nitrogen atom\n * @param {Vector3} [position] - optional target\n * @return {Vectors|undefined} the hydrogen atom position\n */\nfunction backboneNHPosition (ap: AtomProxy, position = new Vector3()) {\n let h = false\n let ca = false\n let c = false\n position.set(2 * ap.x, 2 * ap.y, 2 * ap.z)\n\n ap.eachBondedAtom(function (a2: AtomProxy) {\n // Any time we detect H, reset position and skip\n // future tests\n if (h) return\n if (a2.atomname === 'H') {\n position.set(a2.x, a2.y, a2.z)\n h = true\n return\n }\n if (!ca && a2.atomname === 'CA') {\n position.sub(a2 as any) // TODO\n ca = true\n } else if (!c && a2.atomname === 'C') {\n c = true\n position.sub(a2 as any) // TODO\n }\n })\n\n if (h) { return position }\n\n if (ca && c) {\n position.normalize()\n position.multiplyScalar(nHBondDistance)\n position.add(ap as any)\n return position\n }\n}\n\n/**\n * Takes an array of Vector3 objects and\n * converts to an object that looks like an AtomStore\n *\n * @param {Vector3[]} positions - array of positions\n * @return {Object} AtomStore-like object\n */\nfunction buildStoreLike (positions: Vector3[]) {\n const n = positions.length\n const x = new Float32Array(n)\n const y = new Float32Array(n)\n const z = new Float32Array(n)\n\n for (let i = 0; i < positions.length; i++) {\n const v = positions[ i ]\n x[ i ] = v.x\n y[ i ] = v.y\n z[ i ] = v.z\n }\n\n return { x: x, y: y, z: z, count: n }\n}\n\nfunction chargeForAtom (a: AtomProxy): number {\n if (a.partialCharge !== null) return a.partialCharge\n if (!a.isProtein()) { return 0.0 }\n return (\n (partialCharges[ a.resname ] &&\n partialCharges[ a.resname ][ a.atomname ]) ||\n partialCharges[ 'backbone' ][ a.atomname ] || 0.0\n )\n}\n\n/**\n * Color a surface by electrostatic charge. This is a highly approximate\n * calculation! The partial charges are CHARMM with hydrogens added to heavy\n * atoms and hydrogen positions generated for amides.\n *\n * __Name:__ _electrostatic_\n *\n * @example\n * stage.loadFile( \"rcsb://3dqb\" ).then( function( o ){\n * o.addRepresentation( \"surface\", { colorScheme: \"electrostatic\" } );\n * o.autoView();\n * } );\n */\nclass ElectrostaticColormaker extends Colormaker {\n scale: ColormakerScale\n hHash: SpatialHash\n hash: SpatialHash\n charges: Float32Array\n hStore: { x: Float32Array, y: Float32Array, z: Float32Array, count: number }\n atomProxy: AtomProxy\n\n delta = new Vector3()\n hCharges: number[] = []\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'rwb'\n }\n if (!params.domain) {\n this.parameters.domain = [ -50, 50 ]\n }\n\n this.scale = this.getScale()\n\n this.charges = new Float32Array(params.structure.atomCount)\n const hPositions: Vector3[] = []\n\n params.structure.eachAtom((ap: AtomProxy) => {\n this.charges[ ap.index ] = chargeForAtom(ap) * ap.occupancy\n if (ap.atomname === 'N') {\n\n // In the specific case where N forms two bonds to\n // CA and C, try and place a dummy hydrogen\n\n if (ap.bondCount >= 3) return; // Skip if 3 bonds already (e.g. PRO)\n\n if (ap.bondToElementCount(1)) return; // Skip if any H specificed\n\n const hPos = backboneNHPosition(ap)\n if (hPos !== undefined) {\n hPositions.push(hPos)\n this.hCharges.push(nHCharge * ap.occupancy)\n }\n }\n })\n\n const bbox = params.structure.getBoundingBox()\n bbox.expandByScalar(nHBondDistance) // Worst case\n\n // SpatialHash requires x,y,z and count\n this.hStore = buildStoreLike(hPositions)\n this.hHash = new SpatialHash(this.hStore as any, bbox) // TODO\n this.hash = new SpatialHash(params.structure.atomStore, bbox)\n }\n\n @manageColor\n positionColor (v: Vector3) {\n\n const charges = this.charges\n const hCharges = this.hCharges\n\n let p = 0.0\n this.hash.eachWithin(v.x, v.y, v.z, maxRadius, (atomIndex, dSq) => {\n const charge = charges[atomIndex]\n if (charge === 0.0) return\n p += charge / dSq\n })\n\n this.hHash.eachWithin(v.x, v.y, v.z, maxRadius, (atomIndex, dSq) => {\n const charge = hCharges[atomIndex]\n if (charge === 0.0) return\n p += charge / dSq\n })\n\n return this.scale(p * 332) // 332 to convert to kcal/mol\n }\n}\n\nColormakerRegistry.add('electrostatic', ElectrostaticColormaker)\n\nexport default ElectrostaticColormaker\n","/**\n * @file Element Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport Colormaker, { ColormakerParameters, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\n// from Jmol http://jmol.sourceforge.net/jscolors/ (or 0xFFFFFF)\nconst ElementColors: { [k: string]: number } = {\n 'H': 0xFFFFFF,\n 'HE': 0xD9FFFF,\n 'LI': 0xCC80FF,\n 'BE': 0xC2FF00,\n 'B': 0xFFB5B5,\n 'C': 0x909090,\n 'N': 0x3050F8,\n 'O': 0xFF0D0D,\n 'F': 0x90E050,\n 'NE': 0xB3E3F5,\n 'NA': 0xAB5CF2,\n 'MG': 0x8AFF00,\n 'AL': 0xBFA6A6,\n 'SI': 0xF0C8A0,\n 'P': 0xFF8000,\n 'S': 0xFFFF30,\n 'CL': 0x1FF01F,\n 'AR': 0x80D1E3,\n 'K': 0x8F40D4,\n 'CA': 0x3DFF00,\n 'SC': 0xE6E6E6,\n 'TI': 0xBFC2C7,\n 'V': 0xA6A6AB,\n 'CR': 0x8A99C7,\n 'MN': 0x9C7AC7,\n 'FE': 0xE06633,\n 'CO': 0xF090A0,\n 'NI': 0x50D050,\n 'CU': 0xC88033,\n 'ZN': 0x7D80B0,\n 'GA': 0xC28F8F,\n 'GE': 0x668F8F,\n 'AS': 0xBD80E3,\n 'SE': 0xFFA100,\n 'BR': 0xA62929,\n 'KR': 0x5CB8D1,\n 'RB': 0x702EB0,\n 'SR': 0x00FF00,\n 'Y': 0x94FFFF,\n 'ZR': 0x94E0E0,\n 'NB': 0x73C2C9,\n 'MO': 0x54B5B5,\n 'TC': 0x3B9E9E,\n 'RU': 0x248F8F,\n 'RH': 0x0A7D8C,\n 'PD': 0x006985,\n 'AG': 0xC0C0C0,\n 'CD': 0xFFD98F,\n 'IN': 0xA67573,\n 'SN': 0x668080,\n 'SB': 0x9E63B5,\n 'TE': 0xD47A00,\n 'I': 0x940094,\n 'XE': 0x940094,\n 'CS': 0x57178F,\n 'BA': 0x00C900,\n 'LA': 0x70D4FF,\n 'CE': 0xFFFFC7,\n 'PR': 0xD9FFC7,\n 'ND': 0xC7FFC7,\n 'PM': 0xA3FFC7,\n 'SM': 0x8FFFC7,\n 'EU': 0x61FFC7,\n 'GD': 0x45FFC7,\n 'TB': 0x30FFC7,\n 'DY': 0x1FFFC7,\n 'HO': 0x00FF9C,\n 'ER': 0x00E675,\n 'TM': 0x00D452,\n 'YB': 0x00BF38,\n 'LU': 0x00AB24,\n 'HF': 0x4DC2FF,\n 'TA': 0x4DA6FF,\n 'W': 0x2194D6,\n 'RE': 0x267DAB,\n 'OS': 0x266696,\n 'IR': 0x175487,\n 'PT': 0xD0D0E0,\n 'AU': 0xFFD123,\n 'HG': 0xB8B8D0,\n 'TL': 0xA6544D,\n 'PB': 0x575961,\n 'BI': 0x9E4FB5,\n 'PO': 0xAB5C00,\n 'AT': 0x754F45,\n 'RN': 0x428296,\n 'FR': 0x420066,\n 'RA': 0x007D00,\n 'AC': 0x70ABFA,\n 'TH': 0x00BAFF,\n 'PA': 0x00A1FF,\n 'U': 0x008FFF,\n 'NP': 0x0080FF,\n 'PU': 0x006BFF,\n 'AM': 0x545CF2,\n 'CM': 0x785CE3,\n 'BK': 0x8A4FE3,\n 'CF': 0xA136D4,\n 'ES': 0xB31FD4,\n 'FM': 0xB31FBA,\n 'MD': 0xB30DA6,\n 'NO': 0xBD0D87,\n 'LR': 0xC70066,\n 'RF': 0xCC0059,\n 'DB': 0xD1004F,\n 'SG': 0xD90045,\n 'BH': 0xE00038,\n 'HS': 0xE6002E,\n 'MT': 0xEB0026,\n 'DS': 0xFFFFFF,\n 'RG': 0xFFFFFF,\n 'CN': 0xFFFFFF,\n 'UUT': 0xFFFFFF,\n 'FL': 0xFFFFFF,\n 'UUP': 0xFFFFFF,\n 'LV': 0xFFFFFF,\n 'UUH': 0xFFFFFF,\n\n 'D': 0xFFFFC0,\n 'T': 0xFFFFA0\n}\nconst DefaultElementColor = 0xFFFFFF\n\n/**\n * Color by element\n */\nclass ElementColormaker extends Colormaker {\n constructor (params: ColormakerParameters) {\n params.value = defaults(params.value, ElementColors.C)\n\n super(params)\n }\n\n\n @manageColor\n atomColor (a: AtomProxy) {\n const element = a.element\n\n if (element === 'C') {\n return this.parameters.value\n } else {\n return ElementColors[ element ] || DefaultElementColor\n }\n }\n}\n\nColormakerRegistry.add('element', ElementColormaker)\n\nexport default ElementColormaker\n","/**\n * @file Entityindex Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Color by entity index\n */\nclass EntityindexColormaker extends Colormaker {\n entityindexScale: ColormakerScale\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'Spectral'\n }\n if (!params.domain) {\n this.parameters.domain = [ 0, params.structure.entityList.length - 1 ]\n }\n\n this.entityindexScale = this.getScale()\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n return this.entityindexScale(a.entityIndex)\n }\n}\n\nColormakerRegistry.add('entityindex', EntityindexColormaker)\n\nexport default EntityindexColormaker\n","/**\n * @file Entitytype Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\nimport {\n PolymerEntity, NonPolymerEntity, MacrolideEntity, WaterEntity\n} from '../structure/structure-constants'\n\n/**\n * Color by entity type\n */\nclass EntitytypeColormaker extends Colormaker {\n @manageColor\n atomColor (a: AtomProxy) {\n const e = a.entity\n const et = e ? e.entityType : undefined\n switch (et) {\n case PolymerEntity:\n return 0x7fc97f\n case NonPolymerEntity:\n return 0xfdc086\n case MacrolideEntity:\n return 0xbeaed4\n case WaterEntity:\n return 0x386cb0\n default:\n return 0xffff99\n }\n }\n}\n\nColormakerRegistry.add('entitytype', EntitytypeColormaker)\n\nexport default EntitytypeColormaker\n","/**\n * @file Geoquality Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport { countSetBits } from '../math/math-utils'\n\n/**\n * Color by validation gometry quality\n */\nclass GeoqualityColormaker extends Colormaker {\n geoAtomDict: { [k: string]: { [k: string]: number } } = {}\n geoDict: { [k: string]: number|undefined } = {}\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n const val = params.structure.validation\n if (val) {\n this.geoAtomDict = val.geoAtomDict\n this.geoDict = val.geoDict\n }\n }\n\n @manageColor\n atomColor (atom: AtomProxy) {\n let sele = atom.resno + ''\n if (atom.inscode) sele += '^' + atom.inscode\n if (atom.chainname) sele += ':' + atom.chainname\n sele += '/' + atom.modelIndex\n\n let geoProblemCount\n const geoAtom = this.geoAtomDict[ sele ]\n if (geoAtom !== undefined) {\n const atomProblems: number = geoAtom[ atom.atomname ] || 0\n geoProblemCount = countSetBits(atomProblems)\n } else {\n geoProblemCount = this.geoDict[ sele ] || 0\n }\n\n if (geoProblemCount === 0) {\n return 0x2166ac\n } else if (geoProblemCount === 1) {\n return 0xfee08b\n } else if (geoProblemCount === 2) {\n return 0xf46d43\n } else if (geoProblemCount >= 3) {\n return 0xa50026\n }\n return 0x909090\n }\n}\n\nColormakerRegistry.add('geoquality', GeoqualityColormaker)\n\nexport default GeoqualityColormaker\n","/**\n * @file Hydrophobicity Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { ColormakerParameters, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\nimport {\n ResidueHydrophobicity, DefaultResidueHydrophobicity\n} from '../structure/structure-constants'\n\n/**\n * Color by hydrophobicity\n */\nclass HydrophobicityColormaker extends Colormaker {\n hfScale: ColormakerScale\n resHF: { [k: string]: number } = {}\n defaultResidueHydrophobicity: number\n\n constructor (params: ColormakerParameters) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'RdYlGn'\n }\n\n const idx = 0 // 0: DGwif, 1: DGwoct, 2: Oct-IF\n\n for (const name in ResidueHydrophobicity) {\n this.resHF[ name ] = ResidueHydrophobicity[ name ][ idx ]\n }\n this.defaultResidueHydrophobicity = DefaultResidueHydrophobicity[idx]\n\n if (!params.domain) {\n let min = Infinity\n let max = -Infinity\n\n for (const name in this.resHF) {\n const val = this.resHF[ name ]\n min = Math.min(min, val)\n max = Math.max(max, val)\n }\n\n this.parameters.domain = [ min, 0, max ]\n }\n\n this.hfScale = this.getScale()\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n return this.hfScale(this.resHF[ a.resname ] || this.defaultResidueHydrophobicity)\n }\n}\n\nColormakerRegistry.add('hydrophobicity', HydrophobicityColormaker)\n\nexport default HydrophobicityColormaker\n","/**\n * @file Modelindex Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Color by model index\n */\nclass ModelindexColormaker extends Colormaker {\n modelindexScale: ColormakerScale\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'rainbow'\n }\n if (!params.domain) {\n this.parameters.domain = [ 0, params.structure.modelStore.count ]\n }\n\n this.modelindexScale = this.getScale()\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n return this.modelindexScale(a.modelIndex)\n }\n}\n\nColormakerRegistry.add('modelindex', ModelindexColormaker)\n\nexport default ModelindexColormaker\n","/**\n * @file Moleculetype Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\nimport {\n WaterType, IonType, ProteinType, RnaType, DnaType, SaccharideType\n} from '../structure/structure-constants'\n\n/**\n * Color by molecule type\n */\nclass MoleculetypeColormaker extends Colormaker {\n @manageColor\n atomColor (a: AtomProxy) {\n switch (a.residueType.moleculeType) {\n case WaterType:\n return 0x386cb0\n case IonType:\n return 0xf0027f\n case ProteinType:\n return 0xbeaed4\n case RnaType:\n return 0xfdc086\n case DnaType:\n return 0xbf5b17\n case SaccharideType:\n return 0x7fc97f\n default:\n return 0xffff99\n }\n }\n}\n\nColormakerRegistry.add('moleculetype', MoleculetypeColormaker)\n\nexport default MoleculetypeColormaker\n","/**\n * @file Occupancy Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { ColormakerParameters, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Color by occupancy\n */\nclass OccupancyColormaker extends Colormaker {\n occupancyScale: ColormakerScale\n\n constructor (params: ColormakerParameters) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'PuBu'\n }\n\n if (!params.domain) {\n this.parameters.domain = [ 0.0, 1.0 ]\n }\n\n this.occupancyScale = this.getScale()\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n return this.occupancyScale(a.occupancy)\n }\n}\n\nColormakerRegistry.add('occupancy', OccupancyColormaker)\n\nexport default OccupancyColormaker\n","/**\n * @file Partialcharge Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { ColormakerParameters, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Color by partial charge. The {@link AtomProxy.partialCharge} property is used for coloring.\n * The default domain is [-1, 1].\n *\n * __Name:__ _partialCharge_\n *\n * @example\n * stage.loadFile(\"rcsb://1crn\").then(function (o) {\n * o.addRepresentation(\"ball+stick\", {colorScheme: \"partialCharge\"});\n * o.autoView();\n * });\n */\nclass PartialchargeColormaker extends Colormaker {\n partialchargeScale: ColormakerScale\n\n constructor (params: ColormakerParameters) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'rwb'\n }\n\n if (!params.domain) {\n this.parameters.domain = [-1, 1]\n }\n\n this.partialchargeScale = this.getScale()\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n return this.partialchargeScale(a.partialCharge || 0)\n }\n}\n\nColormakerRegistry.add('partialcharge', PartialchargeColormaker)\n\nexport default PartialchargeColormaker\n","/**\n * @file Random Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { manageColor } from './colormaker'\n\nfunction randomColor () {\n return Math.random() * 0xFFFFFF\n}\n\n/**\n * Class by random color\n */\nclass RandomColormaker extends Colormaker {\n /**\n * get color for an atom\n * @return {Integer} random hex color\n */\n @manageColor\n atomColor () {\n return randomColor()\n }\n\n /**\n * get color for volume cell\n * @return {Integer} random hex color\n */\n @manageColor\n volumeColor () {\n return randomColor()\n }\n\n /**\n * get color for coordinates in space\n * @return {Integer} random hex color\n */\n @manageColor\n positionColor () {\n return randomColor()\n }\n}\n\nColormakerRegistry.add('random', RandomColormaker)\n\nexport default RandomColormaker\n","/**\n * @file Randomcoilindex Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Color by random coil index\n */\nclass RandomcoilindexColormaker extends Colormaker {\n rciScale: ColormakerScale\n rciDict: { [k: string]: number|undefined } = {}\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'RdYlBu'\n }\n\n this.rciScale = this.getScale({ domain: [ 0.6, 0 ] })\n\n const val = params.structure.validation\n if (val) this.rciDict = val.rciDict\n\n }\n\n @manageColor\n atomColor (atom: AtomProxy) {\n let sele = `[${atom.resname}]${atom.resno}`\n if (atom.chainname) sele += ':' + atom.chainname\n\n const rci = this.rciDict[ sele ]\n return rci !== undefined ? this.rciScale(rci) : 0x909090\n }\n}\n\nColormakerRegistry.add('randomcoilindex', RandomcoilindexColormaker)\n\nexport default RandomcoilindexColormaker\n","/**\n * @file Residueindex Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ChainProxy from '../proxy/chain-proxy'\n\n/**\n * Color by residue index\n */\nclass ResidueindexColormaker extends Colormaker {\n scalePerChain: { [k: number]: ColormakerScale } = {}\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'rainbow'\n this.parameters.reverse = defaults(params.reverse, true)\n }\n\n params.structure.eachChain((cp: ChainProxy) => {\n this.parameters.domain = [ cp.residueOffset, cp.residueEnd ]\n this.scalePerChain[ cp.index ] = this.getScale()\n })\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n return this.scalePerChain[ a.chainIndex ](a.residueIndex)\n }\n}\n\nColormakerRegistry.add('residueindex', ResidueindexColormaker)\n\nexport default ResidueindexColormaker\n","/**\n * @file Resname Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\n// protein colors from Jmol http://jmol.sourceforge.net/jscolors/\nconst ResidueColors: { [k: string]: number } = {\n 'ALA': 0x8CFF8C,\n 'ARG': 0x00007C,\n 'ASN': 0xFF7C70,\n 'ASP': 0xA00042,\n 'CYS': 0xFFFF70,\n 'GLN': 0xFF4C4C,\n 'GLU': 0x660000,\n 'GLY': 0xFFFFFF,\n 'HIS': 0x7070FF,\n 'ILE': 0x004C00,\n 'LEU': 0x455E45,\n 'LYS': 0x4747B8,\n 'MET': 0xB8A042,\n 'PHE': 0x534C52,\n 'PRO': 0x525252,\n 'SER': 0xFF7042,\n 'THR': 0xB84C00,\n 'TRP': 0x4F4600,\n 'TYR': 0x8C704C,\n 'VAL': 0xFF8CFF,\n\n 'ASX': 0xFF00FF,\n 'GLX': 0xFF00FF,\n 'ASH': 0xFF00FF,\n 'GLH': 0xFF00FF,\n\n 'A': 0xDC143C, // Crimson Red\n 'G': 0x32CD32, // Lime Green\n 'I': 0x9ACD32, // Yellow Green\n 'X': 0x7CFC00, // Lawn Green\n 'C': 0xFFD700, // Gold Yellow\n 'T': 0x4169E1, // Royal Blue\n 'U': 0x40E0D0, // Turquoise Cyan\n 'D': 0x008B8B, // Dark Cyan\n\n 'DA': 0xDC143C,\n 'DG': 0x32CD32,\n 'DI': 0x9ACD32,\n 'DX': 0x7CFC00,\n 'DC': 0xFFD700,\n 'DT': 0x4169E1,\n 'DU': 0x40E0D0,\n 'DD': 0x008B8B\n}\nconst DefaultResidueColor = 0xFF00FF\n\n/**\n * Color by residue name\n */\nclass ResnameColormaker extends Colormaker {\n @manageColor\n atomColor (a: AtomProxy) {\n return ResidueColors[ a.resname ] || DefaultResidueColor\n }\n}\n\nColormakerRegistry.add('resname', ResnameColormaker)\n\nexport default ResnameColormaker\n","/**\n * @file Sstruc Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ResidueProxy from '../proxy/residue-proxy'\n\n// from Jmol http://jmol.sourceforge.net/jscolors/ (shapely)\nconst StructureColors = {\n 'alphaHelix': 0xFF0080,\n 'threeTenHelix': 0xA00080,\n 'piHelix': 0x600080,\n 'betaStrand': 0xFFC800,\n 'betaTurn': 0x6080FF,\n 'coil': 0xFFFFFF,\n\n 'dna': 0xAE00FE,\n 'rna': 0xFD0162,\n\n 'carbohydrate': 0xA6A6FA\n}\nconst DefaultStructureColor = 0x808080\n\n/**\n * Color by secondary structure\n */\nclass SstrucColormaker extends Colormaker {\n residueProxy: ResidueProxy\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n this.residueProxy = params.structure.getResidueProxy()\n }\n\n @manageColor\n atomColor (ap: AtomProxy) {\n const sstruc = ap.sstruc\n const rp = this.residueProxy\n\n if (sstruc === 'h') {\n return StructureColors.alphaHelix\n } else if (sstruc === 'g') {\n return StructureColors.threeTenHelix\n } else if (sstruc === 'i') {\n return StructureColors.piHelix\n } else if (sstruc === 'e' || sstruc === 'b') {\n return StructureColors.betaStrand\n } else if (sstruc === 't') {\n return StructureColors.betaTurn\n } else {\n rp.index = ap.residueIndex\n if (rp.isDna()) {\n return StructureColors.dna\n } else if (rp.isRna()) {\n return StructureColors.rna\n } else if (rp.isSaccharide()) {\n return StructureColors.carbohydrate\n } else if (rp.isProtein() || sstruc === 's' || sstruc === 'l') {\n return StructureColors.coil\n } else {\n return DefaultStructureColor\n }\n }\n }\n}\n\nColormakerRegistry.add('sstruc', SstrucColormaker)\n\nexport default SstrucColormaker\n","/**\n * @file Colordata Colormaker\n * @author Fred Ludlow \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { ColorData, ColormakerScale, manageColor, StuctureColormakerParams } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport BondProxy from '../proxy/bond-proxy'\n\n\nclass StructuredataColormaker extends Colormaker {\n atomData?: ColorData['atomData']\n bondData?: ColorData['bondData']\n scale: ColormakerScale\n\n constructor(params: StuctureColormakerParams) {\n super(params)\n if (!params.scale) {\n this.parameters.scale = 'rwb'\n }\n this.atomData = this.parameters.data?.atomData\n this.bondData = this.parameters.data?.bondData\n this.scale = this.getScale(this.parameters)\n }\n\n @manageColor\n atomColor(a: AtomProxy) {\n const val = this.atomData?.[a.index]\n return (val !== undefined) ? this.scale(val) : this.parameters.value\n }\n\n @manageColor\n bondColor(bond: BondProxy, fromTo: boolean) {\n const val = this.bondData?.[bond.index]\n \n // Explicit bond data?\n if (val !== undefined) return this.scale(val)\n \n \n if (this.atomProxy) {\n this.atomProxy.index = fromTo ? bond.atomIndex1 : bond.atomIndex2\n return this.atomColor(this.atomProxy)\n } \n \n // Fallback\n return this.parameters.value\n }\n}\n\nColormakerRegistry.add('structuredata', StructuredataColormaker)\n\nexport default StructuredataColormaker","/**\n * @file Uniform Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { manageColor } from './colormaker'\n\n/**\n * Color by uniform color\n */\nclass UniformColormaker extends Colormaker {\n @manageColor\n atomColor () {\n return this.parameters.value\n }\n\n @manageColor\n bondColor () {\n return this.parameters.value\n }\n\n @manageColor\n valueColor () {\n return this.parameters.value\n }\n\n @manageColor\n volumeColor () {\n return this.parameters.value\n }\n}\n\nColormakerRegistry.add('uniform', UniformColormaker)\n\nexport default UniformColormaker\n","/**\n * @file Value Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { VolumeColormakerParams, ColormakerScale, manageColor } from './colormaker'\n\n/**\n * Color by volume value\n */\nclass ValueColormaker extends Colormaker {\n valueScale: ColormakerScale\n\n constructor (params: VolumeColormakerParams) {\n super(params)\n this.valueScale = this.getScale()\n }\n\n /**\n * return the color for a volume cell\n * @param {Integer} index - volume cell index\n * @return {Integer} hex cell color\n */\n @manageColor\n volumeColor (index: number) {\n return this.valueScale((this.parameters.volume! as any).data[ index ]) // TODO\n }\n}\n\nColormakerRegistry.add('value', ValueColormaker)\n\nexport default ValueColormaker\n","/**\n * @file Volume Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\nimport { lerp } from '../math/math-utils'\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { VolumeColormakerParams, ColormakerScale, manageColor } from './colormaker'\n\n/**\n * Color by volume position\n */\nclass VolumeColormaker extends Colormaker {\n valueScale: ColormakerScale\n vec = new Vector3()\n\n constructor (params: VolumeColormakerParams) {\n super(params)\n this.valueScale = this.getScale()\n }\n\n /**\n * return the color for coordinates in space\n * @param {Vector3} coords - xyz coordinates\n * @return {Integer} hex coords color\n */\n @manageColor\n positionColor (coords: Vector3) {\n const volume = this.parameters.volume as any // TODO\n\n if (!volume || !volume.inverseMatrix) {\n return this.parameters.value\n }\n\n const vec = this.vec\n const data = volume.data\n const nx = volume.nx\n const ny = volume.ny\n const nxy = nx * ny\n\n vec.copy(coords)\n vec.applyMatrix4(volume.inverseMatrix)\n\n // position of grid cell\n const x0 = Math.floor(vec.x)\n const y0 = Math.floor(vec.y)\n const z0 = Math.floor(vec.z)\n\n // Indices\n const i = ((((z0 * ny) + y0) * nx) + x0)\n const i1 = i + 1\n const iy = i + nx\n const iz = i + nxy\n const i1y = iy + 1\n const i1z = iz + 1\n const iyz = iy + nxy\n const i1yz = iyz + 1\n\n // Values\n const v = data[ i ]\n const v1 = data[ i1 ]\n const vy = data[ iy ]\n const vz = data[ iz ]\n const v1y = data[ i1y ]\n const v1z = data[ i1z ]\n const vyz = data[ iyz ]\n const v1yz = data[ i1yz ]\n\n // Position of point in fraction of grid\n const xd = vec.x - x0\n const yd = vec.y - y0\n const zd = vec.z - z0\n\n // 1st Dimension\n const c00 = lerp(v, v1, xd)\n const c01 = lerp(vz, v1z, xd)\n const c10 = lerp(vy, v1y, xd)\n const c11 = lerp(vyz, v1yz, xd)\n\n // 2nd Dimension\n const c0 = lerp(c00, c10, yd)\n const c1 = lerp(c01, c11, yd)\n\n // 3rd Dimension\n const c = lerp(c0, c1, zd)\n\n return this.valueScale(c)\n }\n}\n\nColormakerRegistry.add('volume', VolumeColormaker)\n\nexport default VolumeColormaker\n","/**\n * @file Structure Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { ExtensionFragDepth, Mobile } from '../globals'\nimport { defaults } from '../utils'\nimport { RepresentationParameters, default as Representation } from './representation'\nimport Selection from '../selection/selection'\nimport RadiusFactory, { RadiusFactoryTypes, RadiusType } from '../utils/radius-factory'\nimport Structure from '../structure/structure'\nimport Viewer from '../viewer/viewer'\n// @ts-ignore: unused import Volume required for declaration only\nimport { Assembly, Volume } from '../ngl';\nimport StructureView from '../structure/structure-view';\nimport AtomProxy from '../proxy/atom-proxy';\nimport Polymer from '../proxy/polymer';\nimport Buffer from '../buffer/buffer';\nimport { AtomDataFields, BondDataFields, AtomDataParams, BondDataParams } from '../structure/structure-data';\n// @ts-ignore: unused import Surface required for declaration only\nimport Surface from '../surface/surface'\n\n/**\n * Structure representation parameter object.\n * @typedef {Object} StructureRepresentationParameters - structure representation parameters\n * @mixes RepresentationParameters\n *\n * @property {String} radiusType - A list of possible sources of the radius used for rendering the representation. The radius can be based on the *vdW radius*, the *covalent radius* or the *B-factor* value of the corresponding atom. Additionally the radius can be based on the *secondary structure*. Alternatively, when set to *size*, the value from the *radius* parameter is used for all atoms.\n * @property {Float} radius - A number providing a fixed radius used for rendering the representation.\n * @property {Float} scale - A number that scales the value defined by the *radius* or the *radiusType* parameter.\n * @property {String} assembly - name of an assembly object. Included are the asymmetric unit (*AU*) corresponding to the coordinates given in the structure file, biological assemblies from *PDB*, *mmCIF* or *MMTF* files (*BU1*, *BU2*, ...), a filled (crystallographic) unitcell of a given space group (*UNITCELL*), a supercell consisting of a center unitcell and its 26 direct neighbors (*SUPERCELL*). Set to *default* to use the default asemmbly of the structure object.\n */\nexport interface StructureRepresentationParameters extends RepresentationParameters {\n radiusType: string\n radius: number\n scale: number\n assembly: string\n}\nexport interface StructureRepresentationData {\n bufferList: Buffer[]\n polymerList?: Polymer[]\n sview?: StructureView | Structure\n [k: string]: any\n}\n/**\n * Structure representation\n * @interface\n */\nabstract class StructureRepresentation extends Representation {\n\n protected selection: Selection\n protected dataList: StructureRepresentationData[]\n structure: Structure\n structureView: StructureView\n\n protected radiusType: RadiusType\n protected radiusData: {[k: number]: number}\n protected radiusSize: number\n protected radiusScale: number\n protected assembly: string\n protected defaultAssembly: string\n protected needsBuild: boolean\n\n /**\n * Create Structure representation object\n * @param {Structure} structure - the structure to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {StructureRepresentationParameters} params - structure representation parameters\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n const p = params || {}\n\n super(structure, viewer, p)\n\n this.type = 'structure'\n\n this.parameters = Object.assign({\n radiusType: {\n type: 'select', options: RadiusFactory.types\n },\n radiusData: {\n type: 'hidden'\n },\n radiusSize: {\n type: 'number', precision: 3, max: 10.0, min: 0.001\n },\n radiusScale: {\n type: 'number', precision: 3, max: 10.0, min: 0.001\n },\n assembly: null,\n defaultAssembly: {\n type: 'hidden'\n }\n }, this.parameters)\n\n /**\n * @type {Selection}\n * @private\n */\n this.selection = new Selection(p.sele)\n\n /**\n * @type {Array}\n * @private\n */\n this.dataList = []\n\n /**\n * @type {Structure}\n */\n this.structure = structure\n\n /**\n * @type {StructureView}\n */\n this.structureView = this.structure.getView(this.selection)\n\n if (structure.biomolDict) {\n const biomolOptions:{[key: string]: string} = {\n 'default': 'default',\n '': (structure.unitcell ? 'AU' : 'FULL')\n }\n Object.keys(structure.biomolDict).forEach(function (k) {\n biomolOptions[ k ] = k\n })\n this.parameters.assembly = {\n type: 'select',\n options: biomolOptions,\n rebuild: true\n }\n } else {\n this.parameters.assembly = null\n }\n }\n\n get defaultScale () {\n return {\n 'vdw': 1.0,\n 'covalent': 1.0,\n 'bfactor': 0.01,\n 'sstruc': 1.0\n }\n }\n\n init (params: Partial) {\n const p = params || {}\n p.colorScheme = defaults(p.colorScheme, 'element')\n\n this.setRadius(p.radius, p)\n\n this.radiusType = defaults(p.radiusType, 'vdw')\n this.radiusData = defaults(p.radiusData, {})\n this.radiusSize = defaults(p.radiusSize, 1.0)\n this.radiusScale = defaults(p.radiusScale, 1.0)\n this.assembly = defaults(p.assembly, 'default')\n this.defaultAssembly = defaults(p.defaultAssembly, '')\n\n if (p.quality === 'auto') {\n p.quality = this.getQuality()\n }\n\n super.init(p)\n\n this.selection.signals.stringChanged.add((/* sele */) => {\n this.build()\n })\n\n this.build()\n }\n\n setRadius (value: string | number | undefined, p: Partial) {\n const types = Object.keys(RadiusFactoryTypes)\n\n if (typeof value === 'string' && types.includes(value.toLowerCase())) {\n p.radiusType = value\n } else if (value !== undefined) {\n p.radiusType = 'size'\n p.radiusSize = value\n }\n\n return this\n }\n\n getAssembly (): Assembly {\n const name = this.assembly === 'default' ? this.defaultAssembly : this.assembly\n return this.structure.biomolDict[ name ]\n }\n\n getQuality () {\n let atomCount\n const s = this.structureView\n const assembly = this.getAssembly()\n if (assembly) {\n atomCount = assembly.getAtomCount(s)\n } else {\n atomCount = s.atomCount\n }\n if (Mobile) {\n atomCount *= 4\n }\n const backboneOnly = s.atomStore.count / s.residueStore.count < 2\n if (backboneOnly) {\n atomCount *= 10\n }\n\n if (atomCount < 15000) {\n return 'high'\n } else if (atomCount < 80000) {\n return 'medium'\n } else {\n return 'low'\n }\n }\n\n create () {\n if (this.structureView.atomCount === 0) return\n\n if (!this.structureView.hasCoords()) {\n this.needsBuild = true\n return\n } else {\n this.needsBuild = false\n }\n\n const assembly = this.getAssembly()\n\n if (assembly) {\n assembly.partList.forEach((part, i) => {\n const sview = part.getView(this.structureView)\n if (sview.atomCount === 0) return\n const data = this.createData(sview, i)\n if (data) {\n data.sview = sview\n data.instanceList = part.getInstanceList()\n this.dataList.push(data)\n }\n })\n } else {\n const data = this.createData(this.structureView, 0)\n if (data) {\n data.sview = this.structureView\n this.dataList.push(data)\n }\n }\n }\n\n abstract createData (sview: StructureView, k?: number): StructureRepresentationData|undefined\n\n update (what: AtomDataFields|BondDataFields) {\n if (this.lazy && !this.visible) {\n Object.assign(this.lazyProps.what, what)\n return\n }\n\n if (this.needsBuild) {\n this.build()\n return\n }\n\n this.dataList.forEach((data) => {\n if (data.bufferList.length > 0) {\n this.updateData(what, data)\n }\n }, this)\n }\n\n updateData (what?: AtomDataFields|BondDataFields, data?: any) {\n this.build()\n }\n\n getColorParams () {\n return {\n ...super.getColorParams(),\n structure: this.structure\n }\n }\n\n getRadiusParams (param?: any) {\n return {\n type: this.radiusType,\n scale: this.radiusScale,\n size: this.radiusSize,\n data: this.radiusData\n }\n }\n\n getAtomParams (what?: AtomDataFields, params?: AtomDataParams) {\n return Object.assign({\n what: what,\n colorParams: this.getColorParams(),\n radiusParams: this.getRadiusParams()\n }, params)\n }\n\n getBondParams (what?: BondDataFields, params?: BondDataParams) {\n return Object.assign({\n what: what,\n colorParams: this.getColorParams(),\n radiusParams: this.getRadiusParams()\n }, params)\n }\n\n getAtomRadius (atom: AtomProxy) {\n if (this.structureView.atomSet!.isSet(atom.index)) {\n const radiusFactory = new RadiusFactory(this.getRadiusParams())\n return radiusFactory.atomRadius(atom)\n }\n return 0\n }\n\n /**\n * Set representation parameters\n * @alias StructureRepresentation#setSelection\n * @param {String} string - selection string, see {@tutorial selection-language}\n * @param {Boolean} [silent] - don't trigger a change event in the selection\n * @return {StructureRepresentation} this object\n */\n setSelection (string: string, silent?: boolean) {\n this.selection.setString(string, silent)\n\n return this\n }\n\n /**\n * Set representation parameters\n * @alias StructureRepresentation#setParameters\n * @param {StructureRepresentationParameters} params - structure parameter object\n * @param {Object} [what] - buffer data attributes to be updated,\n * note that this needs to be implemented in the\n * derived classes. Generally it allows more\n * fine-grained control over updating than\n * forcing a rebuild.\n * @param {Boolean} what.position - update position data\n * @param {Boolean} what.color - update color data\n * @param {Boolean} [rebuild] - whether or not to rebuild the representation\n * @return {StructureRepresentation} this object\n */\n setParameters (params: Partial, what: AtomDataFields = {}, rebuild = false) {\n const p = params || {}\n\n this.setRadius(p.radius, p)\n\n if (p.radiusType !== undefined || p.radiusData !== undefined || p.radiusSize !== undefined || p.radiusScale !== undefined) {\n what.radius = true\n if (!ExtensionFragDepth || this.disableImpostor) {\n rebuild = true\n }\n }\n\n if (p.defaultAssembly !== undefined &&\n p.defaultAssembly !== this.defaultAssembly &&\n ((this.assembly === 'default' && p.assembly === undefined) ||\n p.assembly === 'default')\n ) {\n rebuild = true\n }\n\n super.setParameters(p, what, rebuild)\n\n return this\n }\n\n getParameters () {\n const params = Object.assign(\n super.getParameters(),\n {\n sele: this.selection ? this.selection.string : undefined,\n defaultAssembly: this.defaultAssembly\n }\n )\n\n return params\n }\n\n attach (callback: ()=> void) {\n const viewer = this.viewer\n const bufferList = this.bufferList\n\n this.dataList.forEach(function (data) {\n data.bufferList.forEach(function (buffer) {\n bufferList.push(buffer)\n viewer.add(buffer, data.instanceList)\n })\n })\n\n this.setVisibility(this.visible)\n callback()\n }\n\n clear () {\n this.dataList.length = 0\n\n super.clear()\n }\n\n dispose () {\n this.structureView.dispose()\n\n super.dispose()\n }\n}\n\nexport default StructureRepresentation\n","/**\n * @file Measurement Representation\n * @author Fred Ludlow \n * @private\n */\n\n// @ts-ignore: unused import Vector3, Matrix4 required for declaration only\nimport { Color, Vector3, Matrix4 } from 'three'\n\nimport Selection from '../selection/selection'\nimport { Browser } from '../globals'\nimport { defaults } from '../utils'\nimport StructureRepresentation, { StructureRepresentationParameters } from './structure-representation'\nimport { uniformArray, uniformArray3 } from '../math/array-utils'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport StructureView from '../structure/structure-view';\nimport { LabelRepresentationParameters } from './label-representation';\nimport TextBuffer, { TextBufferData } from '../buffer/text-buffer';\nimport { GenericColor } from '../types'\n\nexport interface LabelDataField {\n position?: boolean\n labelColor?: boolean\n labelSize?: boolean\n radius?: boolean\n labelText?: boolean\n}\n\n/**\n * Measurement representation parameter object.\n * @typedef {Object} MeasurementRepresentationParameters - measurement representation parameters\n * @mixes RepresentationParameters\n * @mixes StructureRepresentationParameters\n *\n * @property {Float} labelSize - size of the distance label\n * @property {Color} labelColor - color of the distance label\n * @property {Boolean} labelVisible - visibility of the distance label\n * @property {Float} labelZOffset - offset in z-direction (i.e. in camera direction)\n */\nexport interface MeasurementRepresentationParameters extends StructureRepresentationParameters {\n labelVisible: boolean\n labelSize: number\n labelColor: GenericColor\n labelType: 'atomname'|'atomindex'|'occupancy'|'bfactor'|'serial'|'element'|'atom'|'resname'|'resno'|'res'|'text'|'qualified'\n labelText: string\n labelFormat: string\n labelGrouping: 'atom'|'residue'\n labelFontFamily: 'sans-serif'|'monospace'|'serif'\n labelFontStyle: 'normal'|'italic'\n labelFontWeight: 'normal'|'bold'\n labelsdf: boolean\n labelXOffset: number\n labelYOffset: number\n labelZOffset: number\n labelAttachment: 'bottom-left'|'bottom-center'|'bottom-right'|'middle-left'|'middle-center'|'middle-right'|'top-left'|'top-center'|'top-right'\n labelBorder: boolean\n labelBorderColor: GenericColor\n labelBorderWidth: number\n labelBackground: boolean\n labelBackgroundColor: GenericColor\n labelBackgroundMargin: number\n labelBackgroundOpacity: number\n labelFixedSize: boolean\n lineOpacity: number\n linewidth: number\n}\n\n/**\n * Measurement representation\n * @interface\n */\nabstract class MeasurementRepresentation extends StructureRepresentation {\n protected n: number\n protected labelVisible: boolean\n protected labelSize: number\n protected labelColor: GenericColor\n protected labelType: 'atomname'|'atomindex'|'occupancy'|'bfactor'|'serial'|'element'|'atom'|'resname'|'resno'|'res'|'text'|'qualified'\n protected labelText: string\n protected labelFormat: string\n protected labelGrouping: 'atom'|'residue'\n protected labelFontFamily: 'sans-serif'|'monospace'|'serif'\n protected labelFontStyle: 'normal'|'italic'\n protected labelFontWeight: 'normal'|'bold'\n protected labelsdf: boolean\n protected labelXOffset: number\n protected labelYOffset: number\n protected labelZOffset: number\n protected labelAttachment: 'bottom-left'|'bottom-center'|'bottom-right'|'middle-left'|'middle-center'|'middle-right'|'top-left'|'top-center'|'top-right'\n protected labelBorder: boolean\n protected labelBorderColor: GenericColor\n protected labelBorderWidth: number\n protected labelBackground: boolean\n protected labelBackgroundColor: GenericColor\n protected labelBackgroundMargin: number\n protected labelBackgroundOpacity: number\n protected labelFixedSize: boolean\n protected lineOpacity: number\n protected linewidth: number\n protected lineVisible: boolean\n\n protected textBuffer: TextBuffer\n /**\n * Handles common label settings and position logic for\n * distance, angle and dihedral representations\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.n = 0 // Subclass create sets value\n this.parameters = Object.assign({\n labelVisible: {\n type: 'boolean'\n },\n labelSize: {\n type: 'number', precision: 3, max: 10.0, min: 0.001\n },\n labelColor: {\n type: 'color'\n },\n labelFontFamily: {\n type: 'select',\n options: {\n 'sans-serif': 'sans-serif',\n 'monospace': 'monospace',\n 'serif': 'serif'\n },\n buffer: 'fontFamily'\n },\n labelFontStyle: {\n type: 'select',\n options: {\n 'normal': 'normal',\n 'italic': 'italic'\n },\n buffer: 'fontStyle'\n },\n labelFontWeight: {\n type: 'select',\n options: {\n 'normal': 'normal',\n 'bold': 'bold'\n },\n buffer: 'fontWeight'\n },\n labelsdf: {\n type: 'boolean', buffer: 'sdf'\n },\n labelXOffset: {\n type: 'number', precision: 1, max: 20, min: -20, buffer: 'xOffset'\n },\n labelYOffset: {\n type: 'number', precision: 1, max: 20, min: -20, buffer: 'yOffset'\n },\n labelZOffset: {\n type: 'number', precision: 1, max: 20, min: -20, buffer: 'zOffset'\n },\n labelAttachment: {\n type: 'select',\n options: {\n 'bottom-left': 'bottom-left',\n 'bottom-center': 'bottom-center',\n 'bottom-right': 'bottom-right',\n 'middle-left': 'middle-left',\n 'middle-center': 'middle-center',\n 'middle-right': 'middle-right',\n 'top-left': 'top-left',\n 'top-center': 'top-center',\n 'top-right': 'top-right'\n },\n rebuild: true\n },\n labelBorder: {\n type: 'boolean', buffer: 'showBorder'\n },\n labelBorderColor: {\n type: 'color', buffer: 'borderColor'\n },\n labelBorderWidth: {\n type: 'number', precision: 2, max: 0.3, min: 0, buffer: 'borderWidth'\n },\n labelBackground: {\n type: 'boolean', rebuild: true\n },\n labelBackgroundColor: {\n type: 'color', buffer: 'backgroundColor'\n },\n labelBackgroundMargin: {\n type: 'number', precision: 2, max: 2, min: 0, rebuild: true\n },\n labelBackgroundOpacity: {\n type: 'range', step: 0.01, max: 1, min: 0, buffer: 'backgroundOpacity'\n },\n labelFixedSize: {\n type: 'boolean', buffer: 'fixedSize'\n },\n lineOpacity: {\n type: 'range', min: 0.0, max: 1.0, step: 0.01\n },\n linewidth: {\n type: 'integer', max: 50, min: 1, buffer: true\n }\n }, this.parameters, {\n flatShaded: null\n })\n }\n\n init (params: Partial) {\n const p = params || {}\n this.labelVisible = defaults(p.labelVisible, true)\n this.labelSize = defaults(p.labelSize, 2.0)\n this.labelColor = defaults(p.labelColor, 0xFFFFFF)\n this.labelFontFamily = defaults(p.labelFontFamily, 'sans-serif')\n this.labelFontStyle = defaults(p.labelFontstyle, 'normal')\n this.labelFontWeight = defaults(p.labelFontWeight, 'bold')\n this.labelsdf = defaults(p.labelsdf, Browser === 'Chrome')\n this.labelXOffset = defaults(p.labelXOffset, 0.0)\n this.labelYOffset = defaults(p.labelYOffset, 0.0)\n this.labelZOffset = defaults(p.labelZOffset, 0.5)\n this.labelAttachment = defaults(p.labelAttachment, 'bottom-left')\n this.labelBorder = defaults(p.labelBorder, false)\n this.labelBorderColor = defaults(p.labelBorderColor, 'lightgrey')\n this.labelBorderWidth = defaults(p.labelBorderWidth, 0.15)\n this.labelBackground = defaults(p.labelBackground, false)\n this.labelBackgroundColor = defaults(p.labelBackgroundColor, 'lightgrey')\n this.labelBackgroundMargin = defaults(p.labelBackgroundMargin, 0.5)\n this.labelBackgroundOpacity = defaults(p.labelBackgroundOpacity, 1.0)\n this.labelFixedSize = defaults(p.labelFixedSize, false)\n this.lineOpacity = defaults(p.lineOpacity, 1.0)\n this.linewidth = defaults(p.linewidth, 2)\n\n super.init(p)\n }\n\n // All measurements need to rebuild on position change\n update (what: LabelDataField) {\n if (what.position) {\n this.build()\n } else {\n super.update(what)\n }\n }\n\n updateData (what: LabelDataField & {[k: string]: any}, data: any) {\n const textData: TextBufferData | {} = {}\n if (!what || what.labelSize) {\n Object.assign(textData, {size: uniformArray(this.n, this.labelSize)})\n }\n\n if (!what || what.labelColor) {\n const c = new Color(this.labelColor)\n Object.assign(textData, {color: uniformArray3(this.n, c.r, c.g, c.b)})\n }\n\n this.textBuffer.setAttributes(textData as TextBufferData)\n }\n\n setParameters (params: Partial, what: LabelDataField = {}, rebuild = false) {\n if (params && params.labelSize) {\n what.labelSize = true\n }\n\n if (params && (params.labelColor || params.labelColor === 0x000000)) {\n what.labelColor = true\n rebuild = true\n }\n\n super.setParameters(params, what, rebuild)\n\n if (params && params.opacity !== undefined) {\n this.textBuffer.setParameters({ opacity: 1.0 }) // only opaque labels\n }\n\n if (params && params.labelVisible !== undefined) {\n this.setVisibility(this.visible)\n }\n\n return this\n }\n\n setVisibility (value: boolean, noRenderRequest?: boolean) {\n super.setVisibility(value, true)\n if (this.textBuffer) {\n this.textBuffer.setVisibility(\n this.labelVisible && this.visible\n )\n }\n\n if (!noRenderRequest) this.viewer.requestRender()\n\n return this\n }\n\n getLabelBufferParams (params: Partial = {}) {\n return super.getBufferParams(Object.assign({\n fontFamily: this.labelFontFamily,\n fontStyle: this.labelFontStyle,\n fontWeight: this.labelFontWeight,\n sdf: this.labelsdf,\n xOffset: this.labelXOffset,\n yOffset: this.labelYOffset,\n zOffset: this.labelZOffset,\n attachment: this.labelAttachment,\n showBorder: this.labelBorder,\n borderColor: this.labelBorderColor,\n borderWidth: this.labelBorderWidth,\n showBackground: this.labelBackground,\n backgroundColor: this.labelBackgroundColor,\n backgroundMargin: this.labelBackgroundMargin,\n backgroundOpacity: this.labelBackgroundOpacity,\n fixedSize: this.labelFixedSize,\n disablePicking: true,\n visible: this.labelVisible\n }, params, {\n opacity: 1.0 // only opaque labels\n }))\n }\n\n getAtomRadius () {\n return 0\n }\n}\n\n/**\n * MeasurementRepresentations take atom[Pair|Triple|Quad] parameters.\n *\n * Parses nested array of either integer atom indices or selection\n * expressions into a flat array of coordinates.\n *\n * @param {Structure} sview The structure to which the atoms refer\n * @param {Array} atoms Nested array of atom pairs|triples|quads as\n * Integer indices or selection expressions\n * @return {Float32Array} Flattened array of position coordinates\n */\nfunction parseNestedAtoms (sview: StructureView, atoms: (number|string)[][]) {\n const ap = sview.getAtomProxy()\n const sele = new Selection()\n\n const nSets = atoms.length\n if (nSets === 0) return new Float32Array(0)\n\n // Peek-ahead at first item to determine order and parse mode\n const order = atoms[ 0 ].length\n const selected = sview.getAtomSet()\n\n const a = new Float32Array(nSets * order * 3)\n\n let p = 0\n atoms.forEach(function (group) {\n let _break = false\n for (let j = 0; j < order; j++) {\n const value = group[ j ]\n if (typeof (value) === 'number' && Number.isInteger(value)) {\n if (selected.get(value)) {\n ap.index = value\n } else {\n _break = true\n break\n }\n } else {\n sele.setString(value as string)\n const atomIndices = sview.getAtomIndices(sele)\n if (atomIndices!.length) {\n ap.index = atomIndices![ 0 ]\n } else {\n _break = true\n break\n }\n }\n\n let offset = p + j * 3\n a[ offset++ ] = ap.x\n a[ offset++ ] = ap.y\n a[ offset++ ] = ap.z\n }\n if (!_break) p += 3 * order\n })\n\n return a.subarray(0, p)\n}\n\n/* out = v1 * cos(angle) + v2 * sin(angle) */\nfunction calcArcPoint (out: Float32Array, center: Float32Array, v1: Float32Array, v2: Float32Array, angle: number) {\n const x = Math.cos(angle)\n const y = Math.sin(angle)\n out[ 0 ] = center[ 0 ] + v1[ 0 ] * x + v2[ 0 ] * y\n out[ 1 ] = center[ 1 ] + v1[ 1 ] * x + v2[ 1 ] * y\n out[ 2 ] = center[ 2 ] + v1[ 2 ] * x + v2[ 2 ] * y\n}\n\nexport {\n MeasurementRepresentation as default,\n calcArcPoint,\n parseNestedAtoms\n}\n","/**\n * @file Edt\n * @author Alexander Rose \n * @private\n */\n\nimport { NumberArray } from '../types'\n\n// 2D Euclidean distance transform by Felzenszwalb & Huttenlocher https://cs.brown.edu/~pff/papers/dt-final.pdf\nexport function edt(data: NumberArray, width: number, height: number, f: NumberArray, d: NumberArray, v: NumberArray, z: NumberArray) {\n for (let x = 0; x < width; x++) {\n for (let y = 0; y < height; y++) {\n f[y] = data[y * width + x]\n }\n edt1d(f, d, v, z, height)\n for (let y = 0; y < height; y++) {\n data[y * width + x] = d[y]\n }\n }\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n f[x] = data[y * width + x]\n }\n edt1d(f, d, v, z, width)\n for (let x = 0; x < width; x++) {\n data[y * width + x] = Math.sqrt(d[x])\n }\n }\n}\n\n// 1D squared distance transform\nfunction edt1d(f: NumberArray, d: NumberArray, v: NumberArray, z: NumberArray, n: number) {\n v[0] = 0\n z[0] = Number.MIN_SAFE_INTEGER\n z[1] = Number.MAX_SAFE_INTEGER\n\n for (let q = 1, k = 0; q < n; q++) {\n let s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k])\n while (s <= z[k]) {\n k--\n s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k])\n }\n k++\n v[k] = q\n z[k] = s\n z[k + 1] = Number.MAX_SAFE_INTEGER\n }\n\n for (let q = 0, k = 0; q < n; q++) {\n while (z[k + 1] < q) k++\n d[q] = (q - v[k]) * (q - v[k]) + f[v[k]]\n }\n}\n","/**\n * @file Text Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Vector3, Matrix4 required for declaration only\nimport { Color, CanvasTexture, Vector3, Matrix4 } from 'three'\n\nimport '../shader/SDFFont.vert'\nimport '../shader/SDFFont.frag'\n\nimport { BufferRegistry } from '../globals'\nimport { createParams } from '../utils'\nimport MappedQuadBuffer from './mappedquad-buffer'\nimport { IgnorePicker } from '../utils/picker'\nimport { edt } from '../utils/edt'\nimport { BufferDefaultParameters, BufferParameterTypes, BufferData, BufferTypes, BufferParameters } from './buffer'\nimport { GenericColor } from '../types'\n\nconst TextAtlasCache: { [k: string]: TextAtlas } = {}\n\nfunction getTextAtlas (params: Partial) {\n const hash = JSON.stringify(params)\n if (TextAtlasCache[ hash ] === undefined) {\n TextAtlasCache[ hash ] = new TextAtlas(params)\n }\n return TextAtlasCache[ hash ]\n}\n\ntype TextFonts = 'sans-serif'|'monospace'|'serif'\ntype TextStyles = 'normal'|'italic'\ntype TextVariants = 'normal'\ntype TextWeights = 'normal'|'bold'\n\nexport const TextAtlasDefaultParams = {\n font: 'sans-serif' as TextFonts,\n size: 36,\n style: 'normal' as TextStyles,\n variant: 'normal' as TextVariants,\n weight: 'normal' as TextWeights,\n outline: 3,\n width: 1024,\n height: 1024\n}\nexport type TextAtlasParams = typeof TextAtlasDefaultParams\n\nexport type TextAtlasMap = { x: number, y: number, w: number, h: number }\n\nexport class TextAtlas {\n parameters: TextAtlasParams\n\n gamma = 1\n mapped: { [k: string]: TextAtlasMap } = {}\n scratchW = 0\n scratchH = 0\n currentX = 0\n currentY = 0\n\n cutoff = 0.25\n padding: number\n radius: number\n\n gridOuter: Float64Array\n gridInner: Float64Array\n f: Float64Array\n d: Float64Array\n z: Float64Array\n v: Int16Array\n\n paddedSize: number\n middle: number\n\n texture: CanvasTexture\n canvas: HTMLCanvasElement\n context: CanvasRenderingContext2D\n\n lineHeight: number\n maxWidth: number\n colors: string[]\n scratch: Uint8Array\n canvas2: HTMLCanvasElement\n context2: CanvasRenderingContext2D\n data: Uint8Array\n\n placeholder: TextAtlasMap\n\n constructor (params: Partial = {}) {\n this.parameters = createParams(params, TextAtlasDefaultParams)\n const p = this.parameters\n\n this.radius = p.size / 8\n this.padding = p.size / 3\n\n // Prepare line-height with room for outline and descenders/ascenders\n const lineHeight = this.lineHeight = p.size + 2 * p.outline + Math.round(p.size / 4)\n const maxWidth = this.maxWidth = p.width / 4\n\n // Prepare scratch canvas\n const canvas = this.canvas = document.createElement('canvas')\n canvas.width = maxWidth\n canvas.height = lineHeight\n\n const ctx = this.context = this.canvas.getContext('2d')!\n ctx.font = `${p.style} ${p.variant} ${p.weight} ${p.size}px ${p.font}`\n ctx.fillStyle = 'black'\n ctx.textAlign = 'left'\n ctx.textBaseline = 'bottom'\n ctx.lineJoin = 'round'\n\n // temporary arrays for the distance transform\n this.gridOuter = new Float64Array(lineHeight * maxWidth)\n this.gridInner = new Float64Array(lineHeight * maxWidth)\n this.f = new Float64Array(Math.max(lineHeight, maxWidth))\n this.d = new Float64Array(Math.max(lineHeight, maxWidth))\n this.z = new Float64Array(Math.max(lineHeight, maxWidth) + 1)\n this.v = new Int16Array(Math.max(lineHeight, maxWidth))\n\n //\n this.data = new Uint8Array(p.width * p.height * 4)\n this.canvas2 = document.createElement('canvas')\n this.canvas2.width = p.width\n this.canvas2.height = p.height\n this.context2 = this.canvas2.getContext('2d')!\n\n // Replacement Character\n this.placeholder = this.map(String.fromCharCode(0xFFFD))\n\n // Basic Latin (subset)\n for (let i = 0x0020; i <= 0x007E; ++i) {\n this.map(String.fromCharCode(i))\n }\n\n // TODO: to slow to always prepare them\n // // Latin-1 Supplement (subset)\n // for (let i = 0x00A1; i <= 0x00FF; ++i) {\n // this.map(String.fromCharCode(i))\n // }\n\n // Degree sign\n this.map(String.fromCharCode(0x00B0))\n\n // // Greek and Coptic (subset)\n // for (let i = 0x0391; i <= 0x03C9; ++i) {\n // this.map(String.fromCharCode(i))\n // }\n\n // // Cyrillic (subset)\n // for (let i = 0x0400; i <= 0x044F; ++i) {\n // this.map(String.fromCharCode(i))\n // }\n\n // Angstrom Sign\n this.map(String.fromCharCode(0x212B))\n\n this.texture = new CanvasTexture(this.canvas2)\n this.texture.flipY = false\n this.texture.needsUpdate = true\n }\n\n map (text: string) {\n const p = this.parameters\n\n if (this.mapped[ text ] === undefined) {\n this.draw(text)\n\n if (this.currentX + this.scratchW > p.width) {\n this.currentX = 0\n this.currentY += this.scratchH\n }\n if (this.currentY + this.scratchH > p.height) {\n console.warn('canvas to small')\n }\n\n this.mapped[ text ] = {\n x: this.currentX,\n y: this.currentY,\n w: this.scratchW,\n h: this.scratchH\n }\n\n this.context2.drawImage(\n this.canvas,\n 0, 0,\n this.scratchW, this.scratchH,\n this.currentX, this.currentY,\n this.scratchW, this.scratchH\n )\n\n this.currentX += this.scratchW\n }\n\n return this.mapped[ text ]\n }\n\n get (text: string) {\n return this.mapped[ text ] || this.placeholder\n }\n\n draw (text: string) {\n const p = this.parameters\n\n const h = this.lineHeight\n const o = p.outline\n const ctx = this.context\n // const dst = this.scratch\n const max = this.maxWidth\n // const colors = this.colors\n\n // Bottom aligned, take outline into account\n const x = o\n const y = h - p.outline\n\n // Measure text\n const m = ctx.measureText(text)\n const w = Math.min(max, Math.ceil(m.width + 2 * x + 1))\n\n const n = w * h\n\n // Clear scratch area\n ctx.clearRect(0, 0, w, h)\n\n // Draw text\n ctx.fillText(text, x, y)\n\n const imageData = ctx.getImageData(0, 0, w, h)\n const data = imageData.data\n\n for (let i = 0; i < n; i++) {\n const a = imageData.data[i * 4 + 3] / 255; // alpha value\n this.gridOuter[i] = a === 1 ? 0 : a === 0 ? Number.MAX_SAFE_INTEGER : Math.pow(Math.max(0, 0.5 - a), 2);\n this.gridInner[i] = a === 1 ? Number.MAX_SAFE_INTEGER : a === 0 ? 0 : Math.pow(Math.max(0, a - 0.5), 2);\n }\n\n edt(this.gridOuter, w, h, this.f, this.d, this.v, this.z);\n edt(this.gridInner, w, h, this.f, this.d, this.v, this.z);\n\n for (let i = 0; i < n; i++) {\n const d = this.gridOuter[i] - this.gridInner[i];\n data[i * 4 + 3] = Math.max(0, Math.min(255, Math.round(255 - 255 * (d / this.radius + this.cutoff))));\n }\n\n ctx.putImageData(imageData, 0, 0)\n this.scratchW = w\n this.scratchH = h\n }\n}\n\n/**\n * Text buffer parameter object.\n * @typedef {Object} TextBufferParameters - text buffer parameters\n *\n * @property {Float} opacity - translucency: 1 is fully opaque, 0 is fully transparent\n * @property {Integer} clipNear - position of camera near/front clipping plane\n * in percent of scene bounding box\n * @property {String} labelType - type of the label, one of:\n * \"atomname\", \"atomindex\", \"occupancy\", \"bfactor\",\n * \"serial\", \"element\", \"atom\", \"resname\", \"resno\",\n * \"res\", \"text\", \"qualified\". When set to \"text\", the\n * `labelText` list is used.\n * @property {String[]} labelText - list of label strings, must set `labelType` to \"text\"\n * to take effect\n * @property {String} fontFamily - font family, one of: \"sans-serif\", \"monospace\", \"serif\"\n * @property {String} fontStyle - font style, \"normal\" or \"italic\"\n * @property {String} fontWeight - font weight, \"normal\" or \"bold\"\n * @property {Float} xOffset - offset in x-direction\n * @property {Float} yOffset - offset in y-direction\n * @property {Float} zOffset - offset in z-direction (i.e. in camera direction)\n * @property {String} attachment - attachment of the label, one of:\n * \"bottom-left\", \"bottom-center\", \"bottom-right\",\n * \"middle-left\", \"middle-center\", \"middle-right\",\n * \"top-left\", \"top-center\", \"top-right\"\n * @property {Boolean} showBorder - show border/outline\n * @property {Color} borderColor - color of the border/outline\n * @property {Float} borderWidth - width of the border/outline\n * @property {Boolean} showBackground - show background rectangle\n * @property {Color} backgroundColor - color of the background\n * @property {Float} backgroundMargin - width of the background\n * @property {Float} backgroundOpacity - opacity of the background\n * @property {Boolean} fixedSize - show text with a fixed pixel size\n */\n\nexport interface TextBufferData extends BufferData {\n size: Float32Array\n text: string[]\n}\n\ntype TextAttachments = 'bottom-left'|'bottom-center'|'bottom-right'|'middle-left'|'middle-center'|'middle-right'|'top-left'|'top-center'|'top-right'\n\nexport const TextBufferDefaultParameters = Object.assign({\n fontFamily: 'sans-serif' as TextFonts,\n fontStyle: 'normal' as TextStyles,\n fontWeight: 'bold' as TextWeights,\n fontSize: 36,\n xOffset: 0.0,\n yOffset: 0.0,\n zOffset: 0.5,\n attachment: 'bottom-left' as TextAttachments,\n showBorder: false,\n borderColor: 'lightgrey' as number|string,\n borderWidth: 0.15,\n showBackground: false,\n backgroundColor: 'lightgrey' as number|string,\n backgroundMargin: 0.5,\n backgroundOpacity: 1.0,\n forceTransparent: true,\n fixedSize: false\n}, BufferDefaultParameters)\nexport type TextBufferParameters = BufferParameters & {\n fontFamily: TextFonts,\n fontStyle: TextStyles,\n fontWeight: TextWeights,\n fontSize: number,\n xOffset: number,\n yOffset: number,\n zOffset: number,\n attachment: TextAttachments,\n showBorder: boolean,\n borderColor: GenericColor,\n borderWidth: number,\n showBackground: boolean,\n backgroundColor: GenericColor,\n backgroundMargin: number,\n backgroundOpacity: number,\n forceTransparent: boolean,\n fixedSize: boolean\n}\n\nconst TextBufferParameterTypes = Object.assign({\n fontFamily: { uniform: true },\n fontStyle: { uniform: true },\n fontWeight: { uniform: true },\n fontSize: { uniform: true },\n xOffset: { uniform: true },\n yOffset: { uniform: true },\n zOffset: { uniform: true },\n showBorder: { uniform: true },\n borderColor: { uniform: true },\n borderWidth: { uniform: true },\n backgroundColor: { uniform: true },\n backgroundOpacity: { uniform: true },\n fixedSize: { updateShader: true }\n}, BufferParameterTypes)\n\nfunction getCharCount (data: TextBufferData, params: Partial) {\n const n = data.position!.length / 3\n let charCount = 0\n for (let i = 0; i < n; ++i) {\n charCount += data.text[ i ].length\n }\n if (params.showBackground) charCount += n\n\n return charCount\n}\n\n/**\n * Text buffer. Renders screen-aligned text strings.\n *\n * @example\n * var textBuffer = new TextBuffer({\n * position: new Float32Array([ 0, 0, 0 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * size: new Float32Array([ 2 ]),\n * text: [ \"Hello\" ]\n * });\n */\nclass TextBuffer extends MappedQuadBuffer {\n parameterTypes = TextBufferParameterTypes\n get defaultParameters() { return TextBufferDefaultParameters }\n parameters: TextBufferParameters\n\n alwaysTransparent = true\n hasWireframe = false\n isText = true\n vertexShader = 'SDFFont.vert'\n fragmentShader = 'SDFFont.frag'\n\n text: string[]\n positionCount: number\n texture: CanvasTexture\n textAtlas: TextAtlas\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} data.size - sizes\n * @param {String[]} data.text - text strings\n * @param {TextBufferParameters} params - parameters object\n */\n constructor (data: TextBufferData, params: Partial = {}) {\n super({\n position: new Float32Array(getCharCount(data, params) * 3),\n color: new Float32Array(getCharCount(data, params) * 3),\n picking: new IgnorePicker()\n }, params)\n\n this.text = data.text\n this.positionCount = data.position!.length / 3\n\n this.addUniforms({\n 'fontTexture': { value: null },\n 'xOffset': { value: this.parameters.xOffset },\n 'yOffset': { value: this.parameters.yOffset },\n 'zOffset': { value: this.parameters.zOffset },\n 'ortho': { value: false },\n 'showBorder': { value: this.parameters.showBorder },\n 'borderColor': { value: new Color(this.parameters.borderColor as number) },\n 'borderWidth': { value: this.parameters.borderWidth },\n 'backgroundColor': { value: new Color(this.parameters.backgroundColor as number) },\n 'backgroundOpacity': { value: this.parameters.backgroundOpacity },\n 'canvasHeight': { value: 1.0 },\n 'pixelRatio': { value: 1.0 }\n })\n\n this.addAttributes({\n 'inputTexCoord': { type: 'v2', value: null },\n 'inputSize': { type: 'f', value: null }\n })\n\n this.setAttributes(data)\n\n this.makeTexture()\n this.makeMapping()\n }\n\n makeMaterial () {\n super.makeMaterial()\n\n const tex = this.texture\n\n const m = this.material\n m.transparent = true\n m.extensions.derivatives = true\n m.lights = false\n m.uniforms.fontTexture.value = tex\n m.needsUpdate = true\n\n const wm = this.wireframeMaterial\n wm.transparent = true\n wm.extensions.derivatives = true\n wm.lights = false\n wm.uniforms.fontTexture.value = tex\n wm.needsUpdate = true\n\n const pm = this.pickingMaterial\n pm.extensions.derivatives = true\n pm.lights = false\n pm.uniforms.fontTexture.value = tex\n pm.needsUpdate = true\n }\n\n setAttributes (data: Partial = {}) {\n let position, size, color\n let aPosition, inputSize, aColor\n\n const text = this.text\n const attributes = this.geometry.attributes as any // TODO\n\n if (data.position) {\n position = data.position\n aPosition = attributes.position.array\n attributes.position.needsUpdate = true\n }\n\n if (data.size) {\n size = data.size\n inputSize = attributes.inputSize.array\n attributes.inputSize.needsUpdate = true\n }\n\n if (data.color) {\n color = data.color\n aColor = attributes.color.array\n attributes.color.needsUpdate = true\n }\n\n const n = this.positionCount\n\n let j, o\n let iCharAll = 0\n let txt, iChar, nChar\n\n for (let v = 0; v < n; ++v) {\n o = 3 * v\n txt = text[ v ]\n nChar = txt.length\n if (this.parameters.showBackground) nChar += 1\n\n for (iChar = 0; iChar < nChar; ++iChar, ++iCharAll) {\n for (let m = 0; m < 4; m++) {\n j = iCharAll * 4 * 3 + (3 * m)\n\n if (position) {\n aPosition[ j ] = position[ o ]\n aPosition[ j + 1 ] = position[ o + 1 ]\n aPosition[ j + 2 ] = position[ o + 2 ]\n }\n\n if (size) {\n inputSize[ (iCharAll * 4) + m ] = size[ v ]\n }\n\n if (color) {\n aColor[ j ] = color[ o ]\n aColor[ j + 1 ] = color[ o + 1 ]\n aColor[ j + 2 ] = color[ o + 2 ]\n }\n }\n }\n }\n }\n\n makeTexture () {\n this.textAtlas = getTextAtlas({\n font: this.parameters.fontFamily,\n style: this.parameters.fontStyle,\n weight: this.parameters.fontWeight,\n size: this.parameters.fontSize\n })\n\n this.texture = this.textAtlas.texture\n }\n\n makeMapping () {\n const ta = this.textAtlas\n const text = this.text\n const attachment = this.parameters.attachment\n const margin = (ta.lineHeight * this.parameters.backgroundMargin * 0.1) - 10\n\n const attribs = this.geometry.attributes as any // TODO\n const inputTexCoord = attribs.inputTexCoord.array\n const inputMapping = attribs.mapping.array\n\n const n = this.positionCount\n let iCharAll = 0\n let c, i, txt, xadvance, iChar, nChar, xShift, yShift\n\n for (let v = 0; v < n; ++v) {\n txt = text[ v ]\n xadvance = 0\n nChar = txt.length\n\n // calculate width\n for (iChar = 0; iChar < nChar; ++iChar) {\n c = ta.get(txt[ iChar ])\n xadvance += c.w - 2 * ta.parameters.outline\n }\n\n // attachment\n if (attachment.startsWith('top')) {\n yShift = ta.lineHeight / 1.25\n } else if (attachment.startsWith('middle')) {\n yShift = ta.lineHeight / 2.5\n } else {\n yShift = 0 // \"bottom\"\n }\n if (attachment.endsWith('right')) {\n xShift = xadvance\n } else if (attachment.endsWith('center')) {\n xShift = xadvance / 2\n } else {\n xShift = 0 // \"left\"\n }\n xShift += ta.parameters.outline\n yShift += ta.parameters.outline\n\n // background\n if (this.parameters.showBackground) {\n i = iCharAll * 2 * 4\n inputMapping[ i + 0 ] = -ta.lineHeight / 6 - xShift - margin // top left\n inputMapping[ i + 1 ] = ta.lineHeight - yShift + margin\n inputMapping[ i + 2 ] = -ta.lineHeight / 6 - xShift - margin // bottom left\n inputMapping[ i + 3 ] = 0 - yShift - margin\n inputMapping[ i + 4 ] = xadvance + ta.lineHeight / 6 - xShift + 2 * ta.parameters.outline + margin // top right\n inputMapping[ i + 5 ] = ta.lineHeight - yShift + margin\n inputMapping[ i + 6 ] = xadvance + ta.lineHeight / 6 - xShift + 2 * ta.parameters.outline + margin // bottom right\n inputMapping[ i + 7 ] = 0 - yShift - margin\n inputTexCoord[ i + 0 ] = 10\n inputTexCoord[ i + 2 ] = 10\n inputTexCoord[ i + 4 ] = 10\n inputTexCoord[ i + 6 ] = 10\n iCharAll += 1\n }\n\n xadvance = 0\n\n for (iChar = 0; iChar < nChar; ++iChar, ++iCharAll) {\n c = ta.get(txt[ iChar ])\n i = iCharAll * 2 * 4\n\n inputMapping[ i + 0 ] = xadvance - xShift // top left\n inputMapping[ i + 1 ] = c.h - yShift\n inputMapping[ i + 2 ] = xadvance - xShift // bottom left\n inputMapping[ i + 3 ] = 0 - yShift\n inputMapping[ i + 4 ] = xadvance + c.w - xShift // top right\n inputMapping[ i + 5 ] = c.h - yShift\n inputMapping[ i + 6 ] = xadvance + c.w - xShift // bottom right\n inputMapping[ i + 7 ] = 0 - yShift\n\n const texWidth = ta.parameters.width\n const texHeight = ta.parameters.height\n\n const texCoords = [\n c.x / texWidth, c.y / texHeight, // top left\n c.x / texWidth, (c.y + c.h) / texHeight, // bottom left\n (c.x + c.w) / texWidth, c.y / texHeight, // top right\n (c.x + c.w) / texWidth, (c.y + c.h) / texHeight // bottom right\n ]\n inputTexCoord.set(texCoords, i)\n\n xadvance += c.w - 2 * ta.parameters.outline\n }\n }\n\n attribs.inputTexCoord.needsUpdate = true\n attribs.mapping.needsUpdate = true\n }\n\n getDefines (type: BufferTypes) {\n const defines = super.getDefines(type)\n\n if (this.parameters.fixedSize) {\n defines.FIXED_SIZE = 1\n }\n\n return defines\n }\n\n setUniforms (data: any) { // TODO\n if (data && (\n data.fontFamily !== undefined ||\n data.fontStyle !== undefined ||\n data.fontWeight !== undefined ||\n data.fontSize !== undefined\n )) {\n this.makeTexture()\n this.makeMapping()\n this.texture.needsUpdate = true\n data.fontTexture = this.texture\n }\n\n super.setUniforms(data)\n }\n}\n\nBufferRegistry.add('text', TextBuffer)\n\nexport default TextBuffer\n","/**\n * @file Wide Line Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Vector3 required for declaration only\nimport { Vector2, Vector3, Matrix4 } from 'three'\n\nimport '../shader/WideLine.vert'\nimport '../shader/WideLine.frag'\n\nimport { BufferRegistry } from '../globals'\nimport MappedQuadBuffer from './mappedquad-buffer'\nimport { BufferDefaultParameters, BufferParameterTypes, BufferData, BufferParameters } from './buffer'\n\nexport interface WideLineBufferData extends BufferData {\n position1: Float32Array\n position2: Float32Array\n color2: Float32Array\n}\n\nexport const WideLineBufferDefaultParameters = Object.assign({\n linewidth: 2\n}, BufferDefaultParameters)\nexport type WideLineBufferParameters = BufferParameters & { linewidth: number }\n\nconst WideLineBufferParameterTypes = Object.assign({\n linewidth: { uniform: true }\n}, BufferParameterTypes)\n\n/**\n * Wide Line buffer. Draws lines with a fixed width in pixels.\n *\n * @example\n * var lineBuffer = new WideLineBuffer({\n * position1: new Float32Array([ 0, 0, 0 ]),\n * position2: new Float32Array([ 1, 1, 1 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * color2: new Float32Array([ 0, 1, 0 ])\n * });\n */\nclass WideLineBuffer extends MappedQuadBuffer {\n parameterTypes = WideLineBufferParameterTypes\n get defaultParameters() { return WideLineBufferDefaultParameters }\n parameters: WideLineBufferParameters\n\n vertexShader = 'WideLine.vert'\n fragmentShader ='WideLine.frag'\n\n constructor (data: Partial, params: Partial = {}) {\n super(data, params)\n\n if (!data.color2 && data.color) data.color2 = data.color\n\n this.addUniforms({\n 'linewidth': { value: this.parameters.linewidth },\n 'resolution': { value: new Vector2() },\n 'projectionMatrixInverse': { value: new Matrix4() }\n })\n\n this.addAttributes({\n 'position1': { type: 'v3', value: null },\n 'position2': { type: 'v3', value: null },\n 'color2': { type: 'c', value: null }\n })\n\n this.setAttributes(data)\n this.makeMapping()\n }\n\n setParameters (params: Partial) {\n super.setParameters(params)\n }\n}\n\nBufferRegistry.add('wideline', WideLineBuffer)\n\nexport default WideLineBuffer\n","/**\n * @file Angle Representation\n * @author Fred Ludlow \n * @private\n */\nimport { Color } from 'three'\n\nimport { RepresentationRegistry } from '../globals'\nimport MeasurementRepresentation, { parseNestedAtoms, calcArcPoint, MeasurementRepresentationParameters, LabelDataField } from './measurement-representation'\nimport { defaults } from '../utils'\n\nimport MeshBuffer from '../buffer/mesh-buffer'\nimport TextBuffer, { TextBufferData, TextBufferParameters } from '../buffer/text-buffer'\nimport WideLineBuffer, { WideLineBufferData } from '../buffer/wideline-buffer'\n\nimport { v3add, v3cross, v3dot, v3fromArray, v3length, v3new,\n v3normalize, v3sub, v3toArray } from '../math/vector-utils'\nimport { copyArray, uniformArray, uniformArray3 } from '../math/array-utils'\nimport { RAD2DEG } from '../math/math-constants'\nimport { getFixedLengthWrappedDashData } from '../geometry/dash'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport StructureView from '../structure/structure-view';\nimport { BufferData } from '../buffer/buffer';\nimport { StructureRepresentationData, StructureRepresentationParameters } from './structure-representation';\n\n/**\n * @typedef {Object} AngleRepresentationParameters - angle representation parameters\n * @mixes RepresentationParameters\n * @mixes StructureRepresentationParameters\n * @mixes MeasurementRepresentationParameters\n *\n * @property {String} atomTriple - list of triplets of selection strings\n * or atom indices\n * @property {Boolean} vectorVisible - Indicate the 3 points for each angle by drawing lines 1-2-3\n * @property {Boolean} arcVisible - Show the arc outline for each angle\n * @property {Number} lineOpacity - opacity for the line part of the representation\n * @property {Number} linewidth - width for line part of representation\n * @property {Boolean} sectorVisible - Show the filled arc for each angle\n */\n\nexport interface AngleRepresentationParameters extends MeasurementRepresentationParameters {\n atomTriple: (number|string)[][]\n vectorVisible: boolean\n arcVisible: boolean\n lineOpacity: number\n lineWidth: number\n sectorVisible: boolean\n}\n\n/**\n * Angle representation object\n *\n * Reperesentation consists of four parts, visibility can be set for each\n * label - the text label with the angle size\n * vectors - lines joining the three points\n * sector - triangles representing the angle\n * arc - line bordering the sector\n *\n * @param {Structure} structure - the structure to measure angles in\n * @param {Viewer} viewer - a viewer object\n * @param {AngleRepresentationParameters} params - angle representation parameters\n */\nclass AngleRepresentation extends MeasurementRepresentation {\n protected atomTriple: (number|string)[][]\n protected vectorVisible: boolean\n protected arcVisible: boolean\n protected lineOpacity: number\n protected lineWidth: number\n protected sectorVisible: boolean\n protected vectorBuffer: WideLineBuffer\n arcLength: number\n sectorLength: number\n arcBuffer: WideLineBuffer\n sectorBuffer: MeshBuffer\n\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'angle'\n\n this.parameters = Object.assign({\n atomTriple: {\n type: 'hidden', rebuild: true\n },\n vectorVisible: {\n type: 'boolean', default: true\n },\n arcVisible: {\n type: 'boolean', default: true\n },\n sectorVisible: {\n type: 'boolean', default: true\n }\n }, this.parameters)\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n p.side = defaults(p.side, 'double')\n p.opacity = defaults(p.opacity, 0.5)\n\n this.atomTriple = defaults(p.atomTriple, [])\n this.arcVisible = defaults(p.arcVisible, true)\n this.sectorVisible = defaults(p.sectorVisible, true)\n this.vectorVisible = defaults(p.vectorVisible, true)\n\n super.init(p)\n }\n\n createData (sview: StructureView) {\n if (!sview.atomCount || !this.atomTriple.length) return\n\n const atomPosition = atomTriplePositions(sview, this.atomTriple)\n const angleData = getAngleData(atomPosition)\n const n = this.n = angleData.labelPosition.length / 3\n\n const labelColor = new Color(this.labelColor)\n\n // Create buffers\n this.textBuffer = new TextBuffer({\n position: angleData.labelPosition,\n size: uniformArray(n, this.labelSize),\n color: uniformArray3(n, labelColor.r, labelColor.g, labelColor.b),\n text: angleData.labelText\n } as TextBufferData, this.getLabelBufferParams() as TextBufferParameters)\n\n const c = new Color(this.colorValue)\n\n this.vectorBuffer = new WideLineBuffer(\n getFixedLengthWrappedDashData({\n position1: angleData.vectorPosition1,\n position2: angleData.vectorPosition2,\n color: uniformArray3(2 * n, c.r, c.g, c.b),\n color2: uniformArray3(2 * n, c.r, c.g, c.b)\n } as WideLineBufferData),\n this.getBufferParams({\n linewidth: this.linewidth,\n visible: this.vectorVisible,\n opacity: this.lineOpacity\n })\n )\n\n this.arcLength = angleData.arcPosition1.length / 3\n\n this.arcBuffer = new WideLineBuffer(\n getFixedLengthWrappedDashData({\n position1: angleData.arcPosition1,\n position2: angleData.arcPosition2,\n color: uniformArray3(this.arcLength, c.r, c.g, c.b),\n color2: uniformArray3(this.arcLength, c.r, c.g, c.b)\n } as WideLineBufferData), this.getBufferParams({\n linewidth: this.linewidth,\n visible: this.arcVisible,\n opacity: this.lineOpacity\n }))\n\n this.sectorLength = angleData.sectorPosition.length / 3\n\n this.sectorBuffer = new MeshBuffer({\n position: angleData.sectorPosition,\n color: uniformArray3(this.sectorLength, c.r, c.g, c.b)\n } as BufferData, this.getBufferParams({\n visible: this.sectorVisible\n }))\n\n return {\n bufferList: [\n this.textBuffer,\n this.vectorBuffer,\n this.arcBuffer,\n this.sectorBuffer\n ]\n }\n }\n\n updateData (what: LabelDataField & {color?: boolean}, data: StructureRepresentationData) {\n super.updateData(what, data)\n const vectorData = {}\n const arcData = {}\n const sectorData = {}\n\n if (what.color) {\n const c = new Color(this.colorValue)\n Object.assign(vectorData, {\n color: uniformArray3(this.n * 2, c.r, c.g, c.b),\n color2: uniformArray3(this.n * 2, c.r, c.g, c.b)\n })\n Object.assign(arcData, {\n color: uniformArray3(this.arcLength, c.r, c.g, c.b),\n color2: uniformArray3(this.arcLength, c.r, c.g, c.b)\n })\n Object.assign(sectorData, {\n color: uniformArray3(this.sectorLength, c.r, c.g, c.b)\n })\n }\n\n // if (what.sectorOpacity) {\n // this.sectorBuffer.opacity = what.sectorOpacity\n // }\n\n this.vectorBuffer.setAttributes(vectorData)\n this.arcBuffer.setAttributes(arcData)\n this.sectorBuffer.setAttributes(sectorData)\n }\n\n setParameters (params: Partial) {\n var rebuild = false\n var what = {}\n\n super.setParameters(params, what, rebuild)\n\n if (params && (\n params.vectorVisible !== undefined ||\n params.arcVisible !== undefined ||\n params.sectorVisible !== undefined)) {\n this.setVisibility(this.visible)\n }\n\n if (params && params.lineOpacity) {\n this.vectorBuffer.setParameters({ opacity: params.lineOpacity })\n this.arcBuffer.setParameters({ opacity: params.lineOpacity })\n }\n\n if (params && params.opacity !== undefined) {\n this.vectorBuffer.setParameters({ opacity: this.lineOpacity })\n this.arcBuffer.setParameters({ opacity: this.lineOpacity })\n }\n\n if (params && params.linewidth) {\n this.vectorBuffer.setParameters({ linewidth: params.linewidth })\n this.arcBuffer.setParameters({ linewidth: params.linewidth })\n }\n\n return this\n }\n\n setVisibility (value: boolean, noRenderRequest?: boolean) {\n super.setVisibility(value, true)\n\n if (this.vectorBuffer) {\n this.vectorBuffer.setVisibility(this.vectorVisible && this.visible)\n }\n\n if (this.arcBuffer) {\n this.arcBuffer.setVisibility(this.arcVisible && this.visible)\n }\n\n if (this.sectorBuffer) {\n this.sectorBuffer.setVisibility(this.sectorVisible && this.visible)\n }\n\n if (!noRenderRequest) this.viewer.requestRender()\n\n return this\n }\n}\n\n/**\n * Ensure mid point does not coincide with first or second\n * @param {Float32Array} position 9*nAngle array of coordinates\n * @return {Float32Array} Filtered position array, may be shorter\n */\nfunction validatePositions (position: Float32Array) {\n const include = []\n const n = position.length / 9\n for (let i = 0; i < n; i++) {\n // Check that first point not same as second and that second not same as third\n let okay = true\n for (let j = i; j < i + 3; j += 3) {\n if (position[j] === position[j + 3] &&\n position[j + 1] === position[j + 4] &&\n position[j + 2] === position[j + 5]) {\n okay = false\n }\n }\n if (okay) include.push(i)\n }\n const outPosition = new Float32Array(include.length * 9)\n let outIdx = 0\n include.forEach(function (i) {\n copyArray(position, outPosition, i * 9, outIdx * 9, 9)\n outIdx++\n })\n return outPosition\n}\n\nfunction atomTriplePositions (sview: StructureView, atomTriple: (number|string)[][]) {\n return validatePositions(parseNestedAtoms(sview, atomTriple))\n}\n\n/**\n * Converts triple positions into data required to build various buffers.\n */\nfunction getAngleData (position: Float32Array, params: Partial = {}) {\n const angleStep = defaults(params.angleStep, Math.PI / 90)\n const n = position.length / 9\n const angles = new Float32Array(n)\n const labelPosition = new Float32Array(n * 3)\n const labelText = new Array(n)\n\n const vectorPosition1 = new Float32Array(n * 6) // Two lines per angle\n const vectorPosition2 = new Float32Array(n * 6)\n\n const arcPositionTmp1 = new Array(n) // Start points for arc lines\n const arcPositionTmp2 = new Array(n) // End points for arc lines\n const sectorPositionTmp = new Array(n) // Triangle points\n\n let totalSegments = 0\n\n // Re-used vectors etc\n const p1 = v3new() // Positions of points for each angel\n const p2 = v3new()\n const p3 = v3new()\n const v21 = v3new() // Vectors\n const v23 = v3new()\n const cross = v3new() // Cross product v21xv23\n const cross2 = v3new() // In-plane cross product v21 x (v21 x v23)\n const labelTmp = v3new()\n const arcPoint = v3new()\n\n for (var i = 0; i < n; i++) {\n let p = 9 * i\n v3fromArray(p1, position, p)\n v3fromArray(p2, position, p + 3)\n v3fromArray(p3, position, p + 6)\n\n let v = 6 * i\n v3toArray(p1, vectorPosition1, v)\n v3toArray(p2, vectorPosition2, v)\n v3toArray(p2, vectorPosition1, v + 3)\n v3toArray(p3, vectorPosition2, v + 3)\n\n v3sub(v21, p1, p2)\n v3sub(v23, p3, p2)\n\n v3normalize(v21, v21) // validatePositions ensures valid\n v3normalize(v23, v23)\n\n v3cross(cross, v21, v23)\n const crossLength = v3length(cross)\n const dot = v3dot(v21, v23)\n\n const angle = angles[i] = Math.atan2(crossLength, dot)\n labelText[i] = (RAD2DEG * angle).toFixed(1) + String.fromCharCode(0x00B0)\n\n if (v3length(cross) === 0.0) {\n // Angle exactly 0/180, pick an arbitrary direction\n cross[ 0 ] = 1.0\n cross[ 1 ] = 0.0\n cross[ 2 ] = 0.0\n }\n v3cross(cross2, cross, v21)\n v3normalize(cross2, cross2)\n\n calcArcPoint(labelTmp, p2, v21, cross2, angle / 2.0)\n // TODO: Scale label position?\n v3toArray(labelTmp, labelPosition, 3 * i)\n\n // Build the arc and sector\n\n const nSegments = Math.ceil(angle / angleStep)\n const sectorVertices = new Float32Array(nSegments * 9)\n sectorPositionTmp[ i ] = sectorVertices\n const arcVertices1 = new Float32Array(nSegments * 3)\n const arcVertices2 = new Float32Array(nSegments * 3)\n arcPositionTmp1[ i ] = arcVertices1\n arcPositionTmp2[ i ] = arcVertices2\n\n v3add(arcPoint, p2, v21) // Our initial arc point\n\n const appendArcSection = function (a: number, j: number) {\n const si = j * 9\n const ai = j * 3\n v3toArray(p2, sectorVertices, si)\n v3toArray(arcPoint, sectorVertices, si + 3)\n v3toArray(arcPoint, arcVertices1, ai)\n\n calcArcPoint(arcPoint, p2, v21, cross2, a)\n\n v3toArray(arcPoint, sectorVertices, si + 6)\n v3toArray(arcPoint, arcVertices2, ai)\n }\n\n let j = 0\n for (let a = angleStep; a < angle; a += angleStep) {\n appendArcSection(a, j)\n j++\n }\n appendArcSection(angle, j)\n totalSegments += nSegments\n }\n\n // Flatten nested arrays of arc/segment points\n const arcSize = totalSegments * 3\n const sectorSize = totalSegments * 9\n const arcPosition1 = new Float32Array(arcSize)\n const arcPosition2 = new Float32Array(arcSize)\n const sectorPosition = new Float32Array(sectorSize)\n\n let sectorOffset = 0\n let arcOffset = 0\n for (let i = 0; i < n; i++) {\n const ap1 = arcPositionTmp1[ i ]\n const ap2 = arcPositionTmp2[ i ]\n copyArray(ap1, arcPosition1, 0, arcOffset, ap1.length)\n copyArray(ap2, arcPosition2, 0, arcOffset, ap2.length)\n arcOffset += ap1.length // === ap2.length\n\n const sp = sectorPositionTmp[ i ]\n copyArray(sp, sectorPosition, 0, sectorOffset, sp.length)\n sectorOffset += sp.length\n }\n\n return {\n labelPosition,\n labelText,\n vectorPosition1,\n vectorPosition2,\n arcPosition1,\n arcPosition2,\n sectorPosition\n }\n}\n\nRepresentationRegistry.add('angle', AngleRepresentation)\n\nexport default AngleRepresentation\n","/**\n * @file Cylinder Geometry Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4, Vector3, CylinderBufferGeometry } from 'three'\n\nimport { defaults } from '../utils'\nimport { calculateCenterArray, serialBlockArray } from '../math/array-utils'\nimport GeometryBuffer from './geometry-buffer'\nimport { CylinderBufferData } from './cylinder-buffer'\nimport { BufferDefaultParameters, BufferParameters } from './buffer'\n\nconst scale = new Vector3()\nconst eye = new Vector3()\nconst target = new Vector3()\nconst up = new Vector3(0, 1, 0)\n\nexport const CylinderGeometryBufferDefaultParameters = Object.assign({\n radialSegments: 1,\n openEnded: true\n}, BufferDefaultParameters)\nexport type CylinderGeometryBufferParameters = BufferParameters & {radialSegments: number, openEnded: boolean}\n\nfunction getData (data: CylinderBufferData, params: Partial = {}) {\n const geo = getGeo(params)\n\n const n = data.position1.length\n\n const geoLength = (geo.attributes as any).position.array.length / 3\n const count = n / 3\n const primitiveId = new Float32Array(count * 2 * geoLength)\n serialBlockArray(count, geoLength, 0, primitiveId)\n serialBlockArray(count, geoLength, count * geoLength, primitiveId)\n\n const position = new Float32Array(n * 2)\n const color = new Float32Array(n * 2)\n\n return {\n position, color, primitiveId, picking: data.picking\n }\n}\n\nfunction getGeo (params: Partial = {}) {\n const radialSegments = defaults(params.radialSegments, 10)\n const openEnded = defaults(params.openEnded, true)\n const matrix = new Matrix4().makeRotationX(Math.PI / 2)\n\n const geo = new CylinderBufferGeometry(\n 1, // radiusTop,\n 1, // radiusBottom,\n 1, // height,\n radialSegments, // radialSegments,\n 1, // heightSegments,\n openEnded // openEnded\n )\n geo.applyMatrix4(matrix)\n\n return geo\n}\n\n/**\n * Cylinder geometry buffer.\n *\n * @example\n * var cylinderGeometryBuffer = new CylinderGeometryBuffer({\n * position1: new Float32Array([ 0, 0, 0 ]),\n * position2: new Float32Array([ 1, 1, 1 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * color2: new Float32Array([ 0, 1, 0 ]),\n * radius: new Float32Array([ 1 ])\n * });\n */\nclass CylinderGeometryBuffer extends GeometryBuffer {\n updateNormals = true\n\n get defaultParameters() { return CylinderGeometryBufferDefaultParameters }\n parameters: CylinderGeometryBufferParameters\n\n __center: Float32Array\n _position: Float32Array\n _color: Float32Array\n _from: Float32Array\n _to: Float32Array\n _radius: Float32Array\n\n /**\n * @param {Object} data - buffer data\n * @param {Float32Array} data.position1 - from positions\n * @param {Float32Array} data.position2 - to positions\n * @param {Float32Array} data.color - from colors\n * @param {Float32Array} data.color2 - to colors\n * @param {Float32Array} data.radius - radii\n * @param {Picker} [data.picking] - picking ids\n * @param {BufferParameters} [params] - parameters object\n */\n constructor (data: CylinderBufferData, params: Partial = {}) {\n super(getData(data, params), params, getGeo(params))\n\n const n = data.position1.length\n const m = data.radius.length\n\n this.__center = new Float32Array(n)\n this._position = new Float32Array(n * 2)\n this._color = new Float32Array(n * 2)\n this._from = new Float32Array(n * 2)\n this._to = new Float32Array(n * 2)\n this._radius = new Float32Array(m * 2)\n\n this.setAttributes(data, true)\n }\n\n applyPositionTransform (matrix: Matrix4, i: number, i3: number) {\n eye.fromArray(this._from as any, i3)\n target.fromArray(this._to as any, i3)\n matrix.lookAt(eye, target, up)\n\n const r = this._radius[ i ]\n scale.set(r, r, eye.distanceTo(target))\n matrix.scale(scale)\n }\n\n setAttributes (data: Partial = {}, initNormals?: boolean) {\n const meshData: Partial = {}\n\n if (data.position1 && data.position2) {\n calculateCenterArray(\n data.position1, data.position2, this.__center\n )\n calculateCenterArray(\n data.position1, this.__center, this._position\n )\n calculateCenterArray(\n this.__center, data.position2, this._position, data.position1.length\n )\n this._from.set(data.position1)\n this._from.set(this.__center, data.position1.length)\n this._to.set(this.__center)\n this._to.set(data.position2, this.__center.length)\n meshData.position = this._position\n }\n\n if (data.color && data.color2) {\n this._color.set(data.color)\n this._color.set(data.color2, data.color.length)\n meshData.color = this._color\n }\n\n if (data.radius) {\n this._radius.set(data.radius)\n this._radius.set(data.radius, data.radius.length)\n meshData.radius = this._radius\n }\n\n super.setAttributes(meshData, initNormals)\n }\n}\n\nexport default CylinderGeometryBuffer\n","/**\n * @file Mapped Aligned Box Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { BufferParameters, BufferData } from './buffer'\nimport MappedBuffer from './mapped-buffer'\n\n// +Y /\n// 0**********2\n// * | / **\n// * |/ * *\n// -----------3---- +X\n// * /| * *\n// * / | * *\n// 1/**|******4\n// / | * *\n// / | ** \n// +Z | 5 \nconst mapping = new Float32Array([\n -1.0, 1.0, -1.0,\n -1.0, -1.0, -1.0,\n 1.0, 1.0, -1.0,\n 1.0, 1.0, 1.0,\n 1.0, -1.0, -1.0,\n 1.0, -1.0, 1.0\n])\n\nconst mappingIndices = new Uint16Array([\n 0, 1, 2,\n 1, 4, 2,\n 2, 4, 3,\n 4, 5, 3\n])\n\n/**\n * Mapped Aligned box buffer. Draws boxes where one side is always screen-space aligned.\n * Used to render cylinder imposters.\n * @interface\n */\nclass MappedAlignedBoxBuffer extends MappedBuffer {\n constructor(data: BufferData, params: Partial = {}) {\n super('v3', data, params)\n }\n get mapping () { return mapping }\n get mappingIndices () { return mappingIndices }\n get mappingIndicesSize () { return 12 }\n get mappingSize () { return 6 }\n get mappingItemSize () { return 3 }\n}\n\nexport default MappedAlignedBoxBuffer\n","/**\n * @file Cylinder Impostor Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Vector3 required for declaration only\nimport { Matrix4, Vector3 } from 'three'\n\nimport '../shader/CylinderImpostor.vert'\nimport '../shader/CylinderImpostor.frag'\n\nimport MappedAlignedBoxBuffer from './mappedalignedbox-buffer'\nimport { BufferDefaultParameters, BufferParameters, BufferParameterTypes, BufferTypes } from './buffer'\nimport { CylinderBufferData } from './cylinder-buffer'\n\nexport const CylinderImpostorBufferDefaultParameters = Object.assign({\n openEnded: false\n}, BufferDefaultParameters)\nexport type CylinderImpostorBufferParameters = BufferParameters & { openEnded: boolean }\n\nconst CylinderImpostorBufferParameterTypes = Object.assign({\n openEnded: { updateShader: true }\n}, BufferParameterTypes)\n\n/**\n * Cylinder impostor buffer.\n *\n * @example\n * var cylinderimpostorBuffer = new CylinderImpostorBuffer({\n * position1: new Float32Array([ 0, 0, 0 ]),\n * position2: new Float32Array([ 1, 1, 1 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * color2: new Float32Array([ 0, 1, 0 ]),\n * radius: new Float32Array([ 1 ])\n * });\n */\nclass CylinderImpostorBuffer extends MappedAlignedBoxBuffer {\n parameterTypes = CylinderImpostorBufferParameterTypes\n get defaultParameters() { return CylinderImpostorBufferDefaultParameters }\n parameters: CylinderImpostorBufferParameters\n\n isImpostor = true\n vertexShader = 'CylinderImpostor.vert'\n fragmentShader = 'CylinderImpostor.frag'\n\n /**\n * make cylinder impostor buffer\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position1 - from positions\n * @param {Float32Array} data.position2 - to positions\n * @param {Float32Array} data.color - from colors\n * @param {Float32Array} data.color2 - to colors\n * @param {Float32Array} data.radius - radii\n * @param {Picker} data.picking - picking ids\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: CylinderBufferData, params: Partial = {}) {\n super(data, params)\n\n this.addUniforms({\n 'modelViewMatrixInverse': { value: new Matrix4() },\n 'ortho': { value: 0.0 }\n })\n\n this.addAttributes({\n 'position1': { type: 'v3', value: null },\n 'position2': { type: 'v3', value: null },\n 'color2': { type: 'c', value: null },\n 'radius': { type: 'f', value: null }\n })\n\n this.setAttributes(data)\n this.makeMapping()\n }\n\n getDefines (type?: BufferTypes) {\n const defines = MappedAlignedBoxBuffer.prototype.getDefines.call(this, type)\n\n if (!this.parameters.openEnded) {\n defines.CAP = 1\n }\n\n return defines\n }\n}\n\nexport default CylinderImpostorBuffer\n","/**\n * @file Cylinder Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import required for declaration only\nimport { Vector3, Matrix4 } from 'three'\nimport { BufferRegistry, ExtensionFragDepth } from '../globals'\nimport CylinderGeometryBuffer, { CylinderGeometryBufferDefaultParameters, CylinderGeometryBufferParameters } from './cylindergeometry-buffer'\nimport CylinderImpostorBuffer, { CylinderImpostorBufferDefaultParameters, CylinderImpostorBufferParameters } from './cylinderimpostor-buffer'\nimport { BufferData } from './buffer'\n\nexport interface CylinderBufferData extends BufferData {\n position1: Float32Array\n position2: Float32Array\n color2: Float32Array\n radius: Float32Array\n}\n\nexport const CylinderBufferDefaultParameters = Object.assign({\n disableImpostor: false\n}, CylinderGeometryBufferDefaultParameters, CylinderImpostorBufferDefaultParameters)\nexport type CylinderBufferParameters = (CylinderGeometryBufferParameters & {disableImpostor: boolean}) | (CylinderImpostorBufferParameters & {disableImpostor: boolean})\n\nclass CylinderBufferImpl {\n constructor (data: CylinderBufferData, params: Partial = {}) {\n if (!data.color2 && data.color) data.color2 = data.color\n if (!ExtensionFragDepth || (params && params.disableImpostor)) {\n return new CylinderGeometryBuffer(data, params)\n } else {\n return new CylinderImpostorBuffer(data, params)\n }\n }\n}\n\n/**\n * Cylinder buffer. Depending on the value {@link ExtensionFragDepth} and\n * `params.disableImpostor` the constructor returns either a\n * {@link CylinderGeometryBuffer} or a {@link CylinderImpostorBuffer}\n * @implements {Buffer}\n *\n * @example\n * var cylinderBuffer = new CylinderBuffer({\n * position1: new Float32Array([ 0, 0, 0 ]),\n * position2: new Float32Array([ 1, 1, 1 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * color2: new Float32Array([ 0, 1, 0 ]),\n * radius: new Float32Array([ 1 ])\n * });\n */\n//@ts-expect-error Incompatible constructor signatures\nconst CylinderBuffer: {\n new(data: CylinderBufferData, params: Partial): CylinderGeometryBuffer | CylinderImpostorBuffer;\n} = CylinderBufferImpl;\n\ntype CylinderBuffer = CylinderGeometryBuffer | CylinderImpostorBuffer;\n\nBufferRegistry.add('cylinder', CylinderBuffer)\n\nexport default CylinderBuffer\n","/**\n * @file Axes Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { Color, Vector3 } from 'three'\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport { AxesPicker } from '../utils/picker'\nimport { uniformArray, uniformArray3 } from '../math/array-utils'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport SphereBuffer, { SphereBufferData, SphereBufferParameters } from '../buffer/sphere-buffer'\nimport CylinderBuffer, { CylinderBufferData } from '../buffer/cylinder-buffer'\nimport StructureView from '../structure/structure-view';\nimport Viewer from '../viewer/viewer';\nimport { Structure } from '../ngl';\nimport { AtomDataFields } from '../structure/structure-data';\nimport SphereGeometryBuffer from '../buffer/spheregeometry-buffer';\nimport CylinderGeometryBuffer from '../buffer/cylindergeometry-buffer';\nimport PrincipalAxes from '../math/principal-axes';\n\nexport interface AxesRepresentationParameters extends StructureRepresentationParameters {\n showAxes: boolean\n showBox: boolean\n}\n\n/**\n * Axes representation. Show principal axes and/or a box aligned with them\n * that fits the structure or selection.\n *\n * __Name:__ _axes_\n *\n * @example\n * stage.loadFile( \"rcsb://3pqr\", {\n * assembly: \"BU1\"\n * } ).then( function( o ){\n * o.addRepresentation( \"cartoon\" );\n * o.addRepresentation( \"axes\", {\n * sele: \"RET\", showAxes: false, showBox: true, radius: 0.2\n * } );\n * o.addRepresentation( \"ball+stick\", { sele: \"RET\" } );\n * o.addRepresentation( \"axes\", {\n * sele: \":B and backbone\", showAxes: false, showBox: true, radius: 0.2\n * } );\n * stage.autoView();\n * var pa = o.structure.getPrincipalAxes();\n * stage.animationControls.rotate( pa.getRotationQuaternion(), 1500 );\n * } );\n */\nclass AxesRepresentation extends StructureRepresentation {\n \n protected showAxes: boolean\n protected showBox: boolean\n protected sphereBuffer: SphereBuffer\n protected cylinderBuffer: CylinderBuffer\n /**\n * @param {Structure} structure - the structure object\n * @param {Viewer} viewer - the viewer object\n * @param {StructureRepresentationParameters} params - parameters object\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'axes'\n\n this.parameters = Object.assign({\n\n radiusSize: {\n type: 'number', precision: 3, max: 10.0, min: 0.001\n },\n sphereDetail: true,\n radialSegments: true,\n disableImpostor: true,\n showAxes: {\n type: 'boolean', rebuild: true\n },\n showBox: {\n type: 'boolean', rebuild: true\n }\n\n }, this.parameters, {\n assembly: null\n })\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n p.radiusSize = defaults(p.radiusSize, 0.5)\n p.colorValue = defaults(p.colorValue, 'lightgreen')\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n this.showAxes = defaults(p.showAxes, true)\n this.showBox = defaults(p.showBox, false)\n\n super.init(p)\n }\n\n getPrincipalAxes (): PrincipalAxes {\n let selection\n const assembly = this.getAssembly()\n\n if (assembly) {\n selection = assembly.partList[ 0 ].getSelection()\n }\n\n return this.structureView.getPrincipalAxes(selection)\n }\n\n getAxesData (sview: StructureView) {\n const pa = this.getPrincipalAxes()\n const c = new Color(this.colorValue)\n\n let vn = 0\n let en = 0\n\n if (this.showAxes) {\n vn += 6\n en += 3\n }\n\n if (this.showBox) {\n vn += 8\n en += 12\n }\n\n const vertexPosition = new Float32Array(3 * vn)\n const vertexColor = uniformArray3(vn, c.r, c.g, c.b)\n const vertexRadius = uniformArray(vn, this.radiusSize)\n\n const edgePosition1 = new Float32Array(3 * en)\n const edgePosition2 = new Float32Array(3 * en)\n const edgeColor = uniformArray3(en, c.r, c.g, c.b)\n const edgeRadius = uniformArray(en, this.radiusSize)\n\n let offset = 0\n\n if (this.showAxes) {\n const addAxis = function (v1: Vector3, v2: Vector3) {\n v1.toArray(vertexPosition as any, offset * 2)\n v2.toArray(vertexPosition as any, offset * 2 + 3)\n v1.toArray(edgePosition1 as any, offset)\n v2.toArray(edgePosition2 as any, offset)\n offset += 3\n }\n\n addAxis(pa.begA, pa.endA)\n addAxis(pa.begB, pa.endB)\n addAxis(pa.begC, pa.endC)\n }\n\n if (this.showBox) {\n const v = new Vector3()\n const { d1a, d2a, d3a, d1b, d2b, d3b } = pa.getProjectedScaleForAtoms(sview)\n\n // console.log(d1a, d2a, d3a, d1b, d2b, d3b)\n\n let offset2 = offset * 2\n const addCorner = function (d1: number, d2: number, d3: number) {\n v.copy(pa.center)\n .addScaledVector(pa.normVecA, d1)\n .addScaledVector(pa.normVecB, d2)\n .addScaledVector(pa.normVecC, d3)\n v.toArray(vertexPosition as any, offset2)\n offset2 += 3\n }\n addCorner(d1a, d2a, d3a)\n addCorner(d1a, d2a, d3b)\n addCorner(d1a, d2b, d3b)\n addCorner(d1a, d2b, d3a)\n addCorner(d1b, d2b, d3b)\n addCorner(d1b, d2b, d3a)\n addCorner(d1b, d2a, d3a)\n addCorner(d1b, d2a, d3b)\n\n let edgeOffset = offset\n const addEdge = function (a: number, b: number) {\n v.fromArray(vertexPosition as any, offset * 2 + a * 3)\n .toArray(edgePosition1 as any, edgeOffset)\n v.fromArray(vertexPosition as any, offset * 2 + b * 3)\n .toArray(edgePosition2 as any, edgeOffset)\n edgeOffset += 3\n }\n addEdge(0, 1)\n addEdge(0, 3)\n addEdge(0, 6)\n addEdge(1, 2)\n addEdge(1, 7)\n addEdge(2, 3)\n addEdge(2, 4)\n addEdge(3, 5)\n addEdge(4, 5)\n addEdge(4, 7)\n addEdge(5, 6)\n addEdge(6, 7)\n }\n\n const picker = new AxesPicker(pa)\n\n return {\n vertex: {\n position: vertexPosition,\n color: vertexColor,\n radius: vertexRadius,\n picking: picker\n },\n edge: {\n position1: edgePosition1,\n position2: edgePosition2,\n color: edgeColor,\n color2: edgeColor,\n radius: edgeRadius,\n picking: picker\n }\n }\n }\n\n create () {\n const axesData = this.getAxesData(this.structureView)\n\n this.sphereBuffer = new SphereBuffer(\n axesData.vertex as SphereBufferData,\n this.getBufferParams({\n sphereDetail: this.sphereDetail,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n }) as SphereBufferParameters\n )\n\n this.cylinderBuffer = new CylinderBuffer(\n axesData.edge as CylinderBufferData,\n this.getBufferParams({\n openEnded: true,\n radialSegments: this.radialSegments,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n })\n )\n\n this.dataList.push({\n sview: this.structureView,\n bufferList: [ this.sphereBuffer as SphereGeometryBuffer, this.cylinderBuffer as CylinderGeometryBuffer]\n })\n }\n\n createData (sview: StructureView): undefined {\n return\n }\n\n updateData (what: AtomDataFields, data: StructureRepresentationData) {\n const axesData = this.getAxesData(data.sview as StructureView)\n const sphereData = {}\n const cylinderData = {}\n\n if (!what || what.position) {\n Object.assign(sphereData, {\n position: axesData.vertex.position\n })\n Object.assign(cylinderData, {\n position1: axesData.edge.position1,\n position2: axesData.edge.position2\n })\n }\n\n if (!what || what.color) {\n Object.assign(sphereData, {\n color: axesData.vertex.color as Float32Array\n })\n Object.assign(cylinderData, {\n color: axesData.edge.color as Float32Array,\n color2: axesData.edge.color as Float32Array\n })\n }\n\n if (!what || what.radius) {\n Object.assign(sphereData, {\n radius: axesData.vertex.radius as Float32Array\n })\n Object.assign(cylinderData, {\n radius: axesData.edge.radius as Float32Array\n })\n }\n\n (this.sphereBuffer as SphereGeometryBuffer).setAttributes(sphereData);\n (this.cylinderBuffer as CylinderGeometryBuffer).setAttributes(cylinderData)\n }\n}\n\nRepresentationRegistry.add('axes', AxesRepresentation)\n\nexport default AxesRepresentation\n","/**\n * @file Ball And Stick Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport { ExtensionFragDepth, RepresentationRegistry } from '../globals'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport SphereBuffer, { SphereBufferData, SphereBufferParameters } from '../buffer/sphere-buffer'\nimport CylinderBuffer, { CylinderBufferData } from '../buffer/cylinder-buffer'\nimport WideLineBuffer from '../buffer/wideline-buffer'\nimport Viewer from '../viewer/viewer';\n// @ts-ignore: unused import Volume required for declaration only\nimport { Structure, Volume } from '../ngl';\nimport AtomProxy from '../proxy/atom-proxy';\nimport { AtomDataParams, BondDataParams, BondDataFields, AtomDataFields, BondData, AtomData } from '../structure/structure-data';\nimport StructureView from '../structure/structure-view';\nimport CylinderGeometryBuffer from '../buffer/cylindergeometry-buffer';\nimport SphereGeometryBuffer from '../buffer/spheregeometry-buffer';\n// @ts-ignore: unused import Surface required for declaration only\nimport Surface from '../surface/surface';\n\nexport interface BallAndStickRepresentationParameters extends StructureRepresentationParameters {\n sphereDetail: number\n radialSegments: number\n openEnded: boolean\n disableImpostor: boolean\n aspectRatio: number\n lineOnly: boolean\n lineWidth: number\n cylinderOnly: boolean\n multipleBond: 'off' | 'symmetric' | 'offset'\n bondSpacing: number\n bondScale: number\n linewidth: number\n}\n\n/**\n * Ball And Stick representation parameter object. Extends {@link RepresentationParameters} and\n * {@link StructureRepresentationParameters}.\n *\n * @typedef {Object} BallAndStickRepresentationParameters - ball and stick representation parameters\n *\n * @property {Integer} sphereDetail - sphere quality (icosahedron subdivisions)\n * @property {Integer} radialSegments - cylinder quality (number of segments)\n * @property {Boolean} openEnded - capped or not\n * @property {Boolean} disableImpostor - disable use of raycasted impostors for rendering\n * @property {Float} aspectRatio - size difference between atom and bond radii\n * @property {Boolean} lineOnly - render only bonds, and only as lines\n * @property {Integer} linewidth - width of lines\n * @property {Boolean} cylinderOnly - render only bonds (no atoms)\n * @property {String} multipleBond - one off \"off\", \"symmetric\", \"offset\"\n * @property {Float} bondSpacing - spacing for multiple bond rendering\n * @property {Float} bondScale - scale/radius for multiple bond rendering\n */\n\n/**\n * Ball And Stick representation. Show atoms as spheres and bonds as cylinders.\n *\n * __Name:__ _ball+stick_\n *\n * @example\n * stage.loadFile( \"rcsb://1crn\" ).then( function( o ){\n * o.addRepresentation( \"ball+stick\" );\n * o.autoView();\n * } );\n */\nclass BallAndStickRepresentation extends StructureRepresentation {\n protected sphereDetail: number\n protected radialSegments: number\n protected openEnded: boolean\n protected disableImpostor: boolean\n protected aspectRatio: number\n protected lineOnly: boolean\n protected lineWidth: number\n protected cylinderOnly: boolean\n protected multipleBond: 'off' | 'symmetric' | 'offset'\n protected bondSpacing: number\n protected bondScale: number\n protected linewidth: number\n\n protected lineBuffer: WideLineBuffer\n /**\n * Create Ball And Stick representation object\n * @param {Structure} structure - the structure to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {BallAndStickRepresentationParameters} params - ball and stick representation parameters\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'ball+stick'\n\n this.parameters = Object.assign({\n\n sphereDetail: true,\n radialSegments: true,\n openEnded: true,\n disableImpostor: true,\n aspectRatio: {\n type: 'number', precision: 1, max: 10.0, min: 1.0\n },\n lineOnly: {\n type: 'boolean', rebuild: true\n },\n cylinderOnly: {\n type: 'boolean', rebuild: true\n },\n multipleBond: {\n type: 'select',\n rebuild: true,\n options: {\n 'off': 'off',\n 'symmetric': 'symmetric',\n 'offset': 'offset'\n }\n },\n bondScale: {\n type: 'number', precision: 2, max: 1.0, min: 0.01\n },\n bondSpacing: {\n type: 'number', precision: 2, max: 2.0, min: 0.5\n },\n linewidth: {\n type: 'integer', max: 50, min: 1, buffer: true\n }\n\n }, this.parameters)\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n p.radiusType = defaults(p.radiusType, 'size')\n p.radiusSize = defaults(p.radiusSize, 0.15)\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n this.aspectRatio = defaults(p.aspectRatio, 2.0)\n this.lineOnly = defaults(p.lineOnly, false)\n this.cylinderOnly = defaults(p.cylinderOnly, false)\n this.multipleBond = defaults(p.multipleBond, 'off')\n this.bondSpacing = defaults(p.bondSpacing, 1.0)\n this.bondScale = defaults(p.bondScale, 0.4)\n this.linewidth = defaults(p.linewidth, 2)\n\n super.init(p)\n }\n\n getAtomRadius (atom: AtomProxy) {\n return this.aspectRatio * super.getAtomRadius(atom)\n }\n\n getAtomParams (what?: AtomDataFields, params?: Partial) {\n var p = super.getAtomParams(what, params)\n p.radiusParams.scale *= this.aspectRatio\n\n return p\n }\n\n getAtomData (sview: StructureView, what?: AtomDataFields, params?: Partial): AtomData {\n return sview.getAtomData(this.getAtomParams(what, params))\n }\n\n getBondParams (what?: BondDataFields, params?: Partial) {\n params = Object.assign({\n multipleBond: this.multipleBond,\n bondSpacing: this.bondSpacing,\n bondScale: this.bondScale\n }, params)\n\n return super.getBondParams(what, params)\n }\n\n getBondData (sview: StructureView, what?: BondDataFields, params?: Partial): BondData {\n return sview.getBondData(this.getBondParams(what, params))\n }\n\n createData (sview: StructureView) {\n const bufferList: any[] = []\n\n if (this.lineOnly) {\n this.lineBuffer = new WideLineBuffer(\n this.getBondData(sview, { position: true, color: true, picking: true }),\n this.getBufferParams({ linewidth: this.linewidth })\n )\n\n bufferList.push(this.lineBuffer)\n } else {\n const cylinderBuffer = new CylinderBuffer(\n (this.getBondData(sview) as CylinderBufferData),\n this.getBufferParams({\n openEnded: this.openEnded,\n radialSegments: this.radialSegments,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n })\n )\n\n bufferList.push(cylinderBuffer as CylinderGeometryBuffer)\n\n if (!this.cylinderOnly) {\n const sphereBuffer = new SphereBuffer(\n (this.getAtomData(sview) as SphereBufferData),\n (this.getBufferParams({\n sphereDetail: this.sphereDetail,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n }) as SphereBufferParameters)\n )\n\n bufferList.push(sphereBuffer as SphereGeometryBuffer)\n }\n }\n\n return {\n bufferList: bufferList\n }\n }\n\n updateData (what: BondDataFields | AtomDataFields, data: StructureRepresentationData) {\n if (this.multipleBond !== 'off' && what && what.radius) {\n what.position = true\n }\n\n const bondData = this.getBondData(data.sview as StructureView, what)\n\n if (this.lineOnly) {\n const lineData:Partial = {}\n\n if (!what || what.position) {\n Object.assign(lineData, {\n position1: bondData.position1,\n position2: bondData.position2\n })\n }\n\n if (!what || what.color) {\n Object.assign(lineData, {\n color: bondData.color,\n color2: bondData.color2\n })\n }\n\n data.bufferList[ 0 ].setAttributes(lineData)\n } else {\n var cylinderData: Partial = {}\n\n if (!what || what.position) {\n Object.assign(cylinderData, {\n position1: bondData.position1,\n position2: bondData.position2\n })\n }\n\n if (!what || what.color) {\n Object.assign(cylinderData, {\n color: bondData.color,\n color2: bondData.color2\n })\n }\n\n if (!what || what.radius) {\n Object.assign(cylinderData, {\n radius: bondData.radius\n })\n }\n\n data.bufferList[ 0 ].setAttributes(cylinderData)\n\n if (!this.cylinderOnly) {\n var atomData = this.getAtomData(data.sview as StructureView, what)\n\n var sphereData: Partial = {}\n\n if (!what || what.position) {\n Object.assign(sphereData, {\n position: atomData.position\n })\n }\n\n if (!what || what.color) {\n Object.assign(sphereData, {\n color: atomData.color\n })\n }\n\n if (!what || what.radius) {\n Object.assign(sphereData, {\n radius: atomData.radius\n })\n }\n\n data.bufferList[ 1 ].setAttributes(sphereData)\n }\n }\n }\n\n setParameters (params: Partial = {}) {\n let rebuild = false\n const what: AtomDataFields = {}\n\n if (params.aspectRatio || params.bondSpacing || params.bondScale) {\n Object.assign(what, {radius: true})\n if (!ExtensionFragDepth || this.disableImpostor) {\n rebuild = true\n }\n }\n\n super.setParameters(params, what, rebuild)\n\n return this\n }\n}\n\nRepresentationRegistry.add('ball+stick', BallAndStickRepresentation)\n\nexport default BallAndStickRepresentation\n","/**\n * @file Backbone Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport BallAndStickRepresentation, { BallAndStickRepresentationParameters } from './ballandstick-representation'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport AtomProxy from '../proxy/atom-proxy';\nimport StructureView from '../structure/structure-view';\nimport { AtomDataFields, AtomDataParams, BondDataFields, BondDataParams, BondData, AtomData } from '../structure/structure-data';\n\n/**\n * Backbone representation. Show cylinders (or lines) connecting .CA (protein)\n * or .C4'/.C3' (RNA/DNA) of polymers.\n *\n * __Name:__ _backbone_\n *\n * @example\n * stage.loadFile( \"rcsb://1sfi\" ).then( function( o ){\n * o.addRepresentation( \"backbone\" );\n * o.autoView();\n * } );\n */\nclass BackboneRepresentation extends BallAndStickRepresentation {\n /**\n * @param {Structure} structure - the structure object\n * @param {Viewer} viewer - the viewer object\n * @param {BallAndStickRepresentationParameters} params - parameters object\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'backbone'\n\n this.parameters = Object.assign({\n\n }, this.parameters, {\n\n multipleBond: null,\n bondSpacing: null\n\n })\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n p.aspectRatio = defaults(p.aspectRatio, 1.0)\n p.radiusSize = defaults(p.radiusSize, 0.25)\n\n super.init(p)\n }\n\n getAtomRadius (atom: AtomProxy) {\n return atom.isTrace() ? super.getAtomRadius(atom) : 0\n }\n\n getAtomData (sview: StructureView, what?: AtomDataFields, params?: Partial): AtomData {\n return sview.getBackboneAtomData(this.getAtomParams(what, params))\n }\n\n getBondData (sview: StructureView, what?: BondDataFields, params?: Partial): BondData {\n return sview.getBackboneBondData(this.getBondParams(what, params))\n }\n}\n\nRepresentationRegistry.add('backbone', BackboneRepresentation)\n\nexport default BackboneRepresentation\n","/**\n * @file Base Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport BallAndStickRepresentation, { BallAndStickRepresentationParameters } from './ballandstick-representation'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport StructureView from '../structure/structure-view';\nimport { AtomDataFields, AtomDataParams, BondDataFields, BondDataParams, BondData, AtomData } from '../structure/structure-data';\n\n/**\n * Base representation. Show cylinders for RNA/DNA ladders.\n *\n * __Name:__ _base_\n *\n * @example\n * stage.loadFile( \"rcsb://1d66\" ).then( function( o ){\n * o.addRepresentation( \"cartoon\", { sele: \"nucleic\" } );\n * o.addRepresentation( \"base\", { color: \"resname\" } );\n * o.autoView( \"nucleic\" );\n * } );\n */\nclass BaseRepresentation extends BallAndStickRepresentation {\n /**\n * @param {Structure} structure - the structure object\n * @param {Viewer} viewer - the viewer object\n * @param {BallAndStickRepresentationParameters} params - parameters object\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'base'\n\n this.parameters = Object.assign({\n\n }, this.parameters, {\n\n multipleBond: null,\n bondSpacing: null\n\n })\n }\n\n init (params: Partial) {\n let p = params || {}\n p.aspectRatio = defaults(p.aspectRatio, 1.0)\n p.radiusSize = defaults(p.radiusSize, 0.3)\n\n super.init(p)\n }\n\n getAtomData (sview: StructureView, what?: AtomDataFields, params?: AtomDataParams): AtomData {\n return sview.getRungAtomData(this.getAtomParams(what, params))\n }\n\n getBondData (sview: StructureView, what?: BondDataFields, params?: BondDataParams): BondData {\n let p = this.getBondParams(what, params)\n Object.assign(p.colorParams, {rung: true})\n\n return sview.getRungBondData(p)\n }\n}\n\nRepresentationRegistry.add('base', BaseRepresentation)\n\nexport default BaseRepresentation\n","/**\n * @file Spline\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { ColormakerRegistry } from '../globals'\nimport { AtomPicker } from '../utils/picker'\nimport RadiusFactory, { RadiusParams } from '../utils/radius-factory'\nimport { copyArray } from '../math/array-utils'\nimport { spline } from '../math/math-utils'\nimport Polymer from '../proxy/polymer';\nimport AtomProxy from '../proxy/atom-proxy';\nimport { ColormakerParameters } from '../color/colormaker';\nimport { NumberArray } from '../types';\n\nexport class Interpolator {\n \n m: number\n tension: number\n dt: number\n delta: number\n vec1: Vector3\n vec2: Vector3\n vDir: Vector3 \n vTan: Vector3\n vNorm: Vector3\n vBin: Vector3\n m2: number\n\n constructor (m: number, tension: number) {\n this.m = m\n this.tension = tension\n this.dt = 1.0 / this.m\n this.delta = 0.0001\n\n this.vec1 = new Vector3()\n this.vec2 = new Vector3()\n\n this.vDir = new Vector3()\n this.vTan = new Vector3()\n this.vNorm = new Vector3()\n this.vBin = new Vector3()\n \n this.m2 = Math.ceil(this.m / 2)\n }\n\n private interpolateToArr (v0: Vector3, v1: Vector3, v2: Vector3, v3: Vector3, t: number, arr: Float32Array, offset: number) {\n arr[ offset + 0 ] = spline(v0.x, v1.x, v2.x, v3.x, t, this.tension)\n arr[ offset + 1 ] = spline(v0.y, v1.y, v2.y, v3.y, t, this.tension)\n arr[ offset + 2 ] = spline(v0.z, v1.z, v2.z, v3.z, t, this.tension)\n }\n\n private interpolateToVec (v0: Vector3, v1: Vector3, v2: Vector3, v3: Vector3, t: number, vec: Vector3) {\n vec.x = spline(v0.x, v1.x, v2.x, v3.x, t, this.tension)\n vec.y = spline(v0.y, v1.y, v2.y, v3.y, t, this.tension)\n vec.z = spline(v0.z, v1.z, v2.z, v3.z, t, this.tension)\n }\n\n private interpolatePosition (v0: Vector3, v1: Vector3, v2: Vector3, v3: Vector3, pos: Float32Array, offset: number) {\n for (var j = 0; j < this.m; ++j) {\n var l = offset + j * 3\n var d = this.dt * j\n this.interpolateToArr(v0, v1, v2, v3, d, pos, l)\n }\n }\n\n private interpolateTangent (v0: Vector3, v1: Vector3, v2: Vector3, v3: Vector3, tan: Float32Array, offset: number) {\n for (var j = 0; j < this.m; ++j) {\n var d = this.dt * j\n var d1 = d - this.delta\n var d2 = d + this.delta\n var l = offset + j * 3\n // capping as a precaution\n if (d1 < 0) d1 = 0\n if (d2 > 1) d2 = 1\n //\n this.interpolateToVec(v0, v1, v2, v3, d1, this.vec1)\n this.interpolateToVec(v0, v1, v2, v3, d2, this.vec2)\n //\n this.vec2.sub(this.vec1).normalize()\n this.vec2.toArray(tan as any, l)\n }\n }\n\n private vectorSubdivide (interpolationFn: (v0: Vector3, v1: Vector3, v2: Vector3, v3: Vector3, array: Float32Array, offset: number) => void,\n iterator: AtomIterator, array: Float32Array, offset: number, isCyclic: boolean) {\n let v0: Vector3\n let v1 = iterator.next()\n let v2 = iterator.next()\n let v3 = iterator.next()\n //\n const n = iterator.size\n const n1 = n - 1\n let k = offset || 0\n for (let i = 0; i < n1; ++i) {\n v0 = v1\n v1 = v2\n v2 = v3\n v3 = iterator.next()\n interpolationFn.apply(this, [v0, v1, v2, v3, array, k])\n k += 3 * this.m\n }\n if (isCyclic) {\n v0 = iterator.get(n - 2)\n v1 = iterator.get(n - 1)\n v2 = iterator.get(0)\n v3 = iterator.get(1)\n interpolationFn.apply(this, [v0, v1, v2, v3, array, k])\n k += 3 * this.m\n }\n }\n\n //\n\n public getPosition (iterator: AtomIterator, array: Float32Array, offset: number, isCyclic: boolean) {\n iterator.reset()\n this.vectorSubdivide(this.interpolatePosition, iterator, array, offset, isCyclic)\n var n1 = iterator.size - 1\n var k = n1 * this.m * 3\n if (isCyclic) k += this.m * 3\n var v = iterator.get(isCyclic ? 0 : n1)\n array[ k ] = v.x\n array[ k + 1 ] = v.y\n array[ k + 2 ] = v.z\n }\n\n public getTangent (iterator: AtomIterator, array: Float32Array, offset: number, isCyclic: boolean) {\n iterator.reset()\n this.vectorSubdivide(this.interpolateTangent, iterator, array, offset, isCyclic)\n const n1 = iterator.size - 1\n let k = n1 * this.m * 3\n if (isCyclic) k += this.m * 3\n copyArray(array, array, k - 3, k, 3)\n }\n\n private interpolateNormalDir (u0: Vector3, u1: Vector3, u2: Vector3, u3: Vector3,\n v0: Vector3, v1: Vector3, v2: Vector3, v3: Vector3,\n tan: Float32Array, norm: Float32Array, bin: Float32Array,\n offset: number, shift: boolean) {\n for (let j = 0; j < this.m; ++j) {\n let l = offset + j * 3\n if (shift) l += this.m2 * 3\n const d = this.dt * j\n this.interpolateToVec(u0, u1, u2, u3, d, this.vec1)\n this.interpolateToVec(v0, v1, v2, v3, d, this.vec2)\n this.vDir.subVectors(this.vec2, this.vec1).normalize()\n this.vTan.fromArray(tan as any, l)\n this.vBin.crossVectors(this.vDir, this.vTan).normalize()\n this.vBin.toArray(bin as any, l)\n this.vNorm.crossVectors(this.vTan, this.vBin).normalize()\n this.vNorm.toArray(norm as any, l)\n }\n }\n\n private interpolateNormal (vDir: Vector3, tan: Float32Array, norm: Float32Array, bin: Float32Array, offset: number) {\n for (var j = 0; j < this.m; ++j) {\n var l = offset + j * 3\n vDir.copy(this.vNorm)\n this.vTan.fromArray(tan as any, l)\n this.vBin.crossVectors(vDir, this.vTan).normalize()\n this.vBin.toArray(bin as any, l)\n this.vNorm.crossVectors(this.vTan, this.vBin).normalize()\n this.vNorm.toArray(norm as any, l)\n }\n }\n\n public getNormal (size: number, tan: Float32Array, norm: Float32Array, bin: Float32Array, offset: number, isCyclic: boolean) {\n this.vNorm.set(0, 0, 1)\n const n = size\n const n1 = n - 1\n let k = offset || 0\n for (var i = 0; i < n1; ++i) {\n this.interpolateNormal(this.vDir, tan, norm, bin, k)\n k += 3 * this.m\n }\n if (isCyclic) {\n this.interpolateNormal(this.vDir, tan, norm, bin, k)\n k += 3 * this.m\n }\n this.vBin.toArray(bin as any, k)\n this.vNorm.toArray(norm as any, k)\n }\n\n public getNormalDir (iterDir1: AtomIterator, iterDir2: AtomIterator, tan: Float32Array, norm: Float32Array, bin: Float32Array, offset: number, isCyclic: boolean, shift: boolean) {\n iterDir1.reset()\n iterDir2.reset()\n //\n const vSub1 = new Vector3()\n const vSub2 = new Vector3()\n const vSub3 = new Vector3()\n const vSub4 = new Vector3()\n //\n const d1v1 = new Vector3()\n const d1v2 = new Vector3().copy(iterDir1.next())\n const d1v3 = new Vector3().copy(iterDir1.next())\n const d1v4 = new Vector3().copy(iterDir1.next())\n const d2v1 = new Vector3()\n const d2v2 = new Vector3().copy(iterDir2.next())\n const d2v3 = new Vector3().copy(iterDir2.next())\n const d2v4 = new Vector3().copy(iterDir2.next())\n //\n this.vNorm.set(0, 0, 1)\n let n = iterDir1.size\n let n1 = n - 1\n let k = offset || 0\n for (var i = 0; i < n1; ++i) {\n d1v1.copy(d1v2)\n d1v2.copy(d1v3)\n d1v3.copy(d1v4)\n d1v4.copy(iterDir1.next())\n d2v1.copy(d2v2)\n d2v2.copy(d2v3)\n d2v3.copy(d2v4)\n d2v4.copy(iterDir2.next())\n //\n if (i === 0) {\n vSub1.subVectors(d2v1, d1v1)\n vSub2.subVectors(d2v2, d1v2)\n if (vSub1.dot(vSub2) < 0) {\n vSub2.multiplyScalar(-1)\n d2v2.addVectors(d1v2, vSub2)\n }\n vSub3.subVectors(d2v3, d1v3)\n if (vSub2.dot(vSub3) < 0) {\n vSub3.multiplyScalar(-1)\n d2v3.addVectors(d1v3, vSub3)\n }\n } else {\n vSub3.copy(vSub4)\n }\n vSub4.subVectors(d2v4, d1v4)\n if (vSub3.dot(vSub4) < 0) {\n vSub4.multiplyScalar(-1)\n d2v4.addVectors(d1v4, vSub4)\n }\n this.interpolateNormalDir(\n d1v1, d1v2, d1v3, d1v4,\n d2v1, d2v2, d2v3, d2v4,\n tan, norm, bin, k, shift\n )\n k += 3 * this.m\n }\n if (isCyclic) {\n d1v1.copy(iterDir1.get(n - 2))\n d1v2.copy(iterDir1.get(n - 1))\n d1v3.copy(iterDir1.get(0))\n d1v4.copy(iterDir1.get(1))\n d2v1.copy(iterDir2.get(n - 2))\n d2v2.copy(iterDir2.get(n - 1))\n d2v3.copy(iterDir2.get(0))\n d2v4.copy(iterDir2.get(1))\n //\n vSub3.copy(vSub4)\n vSub4.subVectors(d2v4, d1v4)\n if (vSub3.dot(vSub4) < 0) {\n vSub4.multiplyScalar(-1)\n d2v4.addVectors(d1v4, vSub4)\n }\n this.interpolateNormalDir(\n d1v1, d1v2, d1v3, d1v4,\n d2v1, d2v2, d2v3, d2v4,\n tan, norm, bin, k, shift\n )\n k += 3 * this.m\n }\n if (shift) {\n // FIXME shift requires data from one this.more preceeding residue\n this.vBin.fromArray(bin as any, this.m2 * 3)\n this.vNorm.fromArray(norm as any, this.m2 * 3)\n for (var j = 0; j < this.m2; ++j) {\n this.vBin.toArray(bin as any, j * 3)\n this.vNorm.toArray(norm as any, j * 3)\n }\n } else {\n this.vBin.toArray(bin as any, k)\n this.vNorm.toArray(norm as any, k)\n }\n }\n\n //\n\n private interpolateColor (item1: AtomProxy, item2: AtomProxy, colFn: (...arg: any[]) => void, col: any, offset: number) {\n var j, l\n for (j = 0; j < this.m2; ++j) {\n l = offset + j * 3\n colFn.apply(this, [item1, col, l]) // itemColorToArray\n }\n for (j = this.m2; j < this.m; ++j) {\n l = offset + j * 3\n colFn.apply(this, [item2, col, l]) // itemColorToArray\n }\n }\n\n public getColor (iterator: AtomIterator, colFn: (...arg: any[]) => void, col: any, offset: number, isCyclic: boolean) {\n iterator.reset()\n iterator.next() // first element not needed\n let i0: AtomProxy\n let i1 = iterator.next()\n //\n var n = iterator.size\n var n1 = n - 1\n var k = offset || 0\n for (var i = 0; i < n1; ++i) {\n i0 = i1\n i1 = iterator.next()\n this.interpolateColor(i0, i1, colFn, col, k)\n k += 3 * this.m\n }\n if (isCyclic) {\n i0 = iterator.get(n - 1)\n i1 = iterator.get(0)\n this.interpolateColor(i0, i1, colFn, col, k)\n k += 3 * this.m\n }\n //\n col[ k ] = col[ k - 3 ]\n col[ k + 1 ] = col[ k - 2 ]\n col[ k + 2 ] = col[ k - 1 ]\n }\n\n //\n\n private interpolatePicking (item1: AtomProxy, item2: AtomProxy, pickFn: (item: AtomProxy) => number, pick: Float32Array, offset: number) {\n var j\n for (j = 0; j < this.m2; ++j) {\n pick[ offset + j ] = pickFn.apply(this, [item1])\n }\n for (j = this.m2; j < this.m; ++j) {\n pick[ offset + j ] = pickFn.apply(this, [item2])\n }\n }\n\n public getPicking (iterator: AtomIterator, pickFn: (item: AtomProxy) => number, pick: Float32Array, offset: number, isCyclic: boolean) {\n iterator.reset()\n iterator.next() // first element not needed\n let i0: AtomProxy\n let i1 = iterator.next()\n //\n const n = iterator.size\n const n1 = n - 1\n let k = offset || 0\n for (var i = 0; i < n1; ++i) {\n i0 = i1\n i1 = iterator.next()\n this.interpolatePicking(i0, i1, pickFn, pick, k)\n k += this.m\n }\n if (isCyclic) {\n i0 = iterator.get(n - 1)\n i1 = iterator.get(0)\n this.interpolatePicking(i0, i1, pickFn, pick, k)\n k += this.m\n }\n //\n pick[ k ] = pick[ k - 1 ]\n }\n\n //\n\n private interpolateSize (item1: AtomProxy, item2: AtomProxy, sizeFn: (item: AtomProxy) => number, size: Float32Array, offset: number) {\n const s1: number = sizeFn.apply(this, [item1])\n const s2: number = sizeFn.apply(this, [item2])\n for (let j = 0; j < this.m; ++j) {\n // linear interpolation\n let t = j / this.m\n size[ offset + j ] = (1 - t) * s1 + t * s2\n }\n }\n\n public getSize (iterator: AtomIterator, sizeFn: (item: AtomProxy) => number, size: Float32Array, offset: number, isCyclic: boolean) {\n iterator.reset()\n iterator.next() // first element not needed\n let i0: AtomProxy\n let i1: AtomProxy = iterator.next()\n //\n const n = iterator.size\n const n1 = n - 1\n let k = offset || 0\n for (var i = 0; i < n1; ++i) {\n i0 = i1\n i1 = iterator.next()\n this.interpolateSize(i0, i1, sizeFn, size, k)\n k += this.m\n }\n if (isCyclic) {\n i0 = iterator.get(n - 1)\n i1 = iterator.get(0)\n this.interpolateSize(i0, i1, sizeFn, size, k)\n k += this.m\n }\n //\n size[ k ] = size[ k - 1 ]\n }\n}\n\nexport interface SplineParameters {\n directional?: boolean\n positionIterator?: boolean\n subdiv?: number\n smoothSheet?: boolean\n tension?: number\n}\nexport interface AtomIterator {\n size: number,\n next: () => AtomProxy | Vector3,\n get: (idx: number) => AtomProxy | Vector3,\n reset: () => void\n}\nclass Spline {\n\n polymer: Polymer\n size: number\n directional: boolean\n positionIterator: any\n subdiv: number\n smoothSheet: boolean\n tension: number\n interpolator: Interpolator\n\n constructor (polymer: Polymer, params?: SplineParameters) {\n this.polymer = polymer\n this.size = polymer.residueCount\n\n var p = params || {}\n this.directional = p.directional || false\n this.positionIterator = p.positionIterator || false\n this.subdiv = p.subdiv || 1\n this.smoothSheet = p.smoothSheet || false\n\n if (!p.tension) {\n this.tension = this.polymer.isNucleic() ? 0.5 : 0.9\n } else {\n this.tension = p.tension\n }\n\n this.interpolator = new Interpolator(this.subdiv, this.tension)\n }\n\n getAtomIterator (type: string, smooth?: boolean): AtomIterator {\n const polymer = this.polymer\n const structure = polymer.structure\n const n = polymer.residueCount\n\n let i = 0\n let j = -1\n\n const cache = [\n structure.getAtomProxy(),\n structure.getAtomProxy(),\n structure.getAtomProxy(),\n structure.getAtomProxy()\n ]\n\n const cache2 = [\n new Vector3(),\n new Vector3(),\n new Vector3(),\n new Vector3()\n ]\n\n function next () {\n var atomProxy = get(j)\n j += 1\n return atomProxy\n }\n\n var apPrev = structure.getAtomProxy()\n var apNext = structure.getAtomProxy()\n\n function get (idx: number) {\n var atomProxy = cache[ i % 4 ]\n atomProxy.index = polymer.getAtomIndexByType(idx, type) as number\n if (smooth && idx > 0 && idx < n && atomProxy.sstruc === 'e') {\n var vec = cache2[ i % 4 ]\n apPrev.index = polymer.getAtomIndexByType(idx + 1, type) as number\n apNext.index = polymer.getAtomIndexByType(idx - 1, type) as number\n vec.addVectors(apPrev as any, apNext as any)\n .add(atomProxy as any).add(atomProxy as any)\n .multiplyScalar(0.25)\n i += 1\n return vec\n }\n i += 1\n return atomProxy\n }\n\n function reset () {\n i = 0\n j = -1\n }\n\n return {\n size: n,\n next: next,\n get: get,\n reset: reset\n }\n }\n\n getSubdividedColor (params: {scheme: string, [k: string]: any } & ColormakerParameters) {\n var m = this.subdiv\n var polymer = this.polymer\n var n = polymer.residueCount\n var n1 = n - 1\n var nCol = n1 * m * 3 + 3\n if (polymer.isCyclic) nCol += m * 3\n\n var col = new Float32Array(nCol)\n var iterator = this.getAtomIterator('trace')\n\n var p = params || {}\n p.structure = polymer.structure\n\n var colormaker = ColormakerRegistry.getScheme(p)\n\n function colFn (item: AtomProxy, array: NumberArray, offset: number) {\n colormaker.atomColorToArray(item, array, offset)\n }\n\n this.interpolator.getColor(\n iterator, colFn, col, 0, polymer.isCyclic\n )\n\n return {\n 'color': col\n }\n }\n \n getSubdividedPicking () {\n var m = this.subdiv\n var polymer = this.polymer\n var n = polymer.residueCount\n var n1 = n - 1\n var nCol = n1 * m + 1\n if (polymer.isCyclic) nCol += m\n\n var structure = polymer.structure\n var iterator = this.getAtomIterator('trace')\n var pick = new Float32Array(nCol)\n\n function pickFn (item: AtomProxy) {\n return item.index\n }\n\n this.interpolator.getPicking(\n iterator, pickFn, pick, 0, polymer.isCyclic\n )\n\n return {\n 'picking': new AtomPicker(pick, structure)\n }\n }\n\n getSubdividedPosition () {\n var pos = this.getPosition()\n\n return {\n 'position': pos\n }\n }\n \n getSubdividedOrientation () {\n const tan = this.getTangent()\n const normals = this.getNormals(tan)\n\n return {\n 'tangent': tan,\n 'normal': normals.normal,\n 'binormal': normals.binormal\n }\n }\n\n getSubdividedSize (params: RadiusParams) {\n var m = this.subdiv\n var polymer = this.polymer\n var n = polymer.residueCount\n var n1 = n - 1\n var nSize = n1 * m + 1\n if (polymer.isCyclic) nSize += m\n\n var size = new Float32Array(nSize)\n var iterator = this.getAtomIterator('trace')\n\n var radiusFactory = new RadiusFactory(params)\n\n function sizeFn (item: AtomProxy) {\n return radiusFactory.atomRadius(item)\n }\n\n this.interpolator.getSize(\n iterator, sizeFn, size, 0, polymer.isCyclic\n )\n\n return {\n 'size': size\n }\n }\n\n getPosition () {\n const m = this.subdiv\n const polymer = this.polymer\n const n = polymer.residueCount\n const n1 = n - 1\n let nPos = n1 * m * 3 + 3\n if (polymer.isCyclic) nPos += m * 3\n\n const pos = new Float32Array(nPos)\n const iterator = this.positionIterator || this.getAtomIterator('trace', this.smoothSheet)\n\n this.interpolator.getPosition(iterator, pos, 0, polymer.isCyclic)\n\n return pos\n }\n\n getTangent () {\n const m = this.subdiv\n const polymer = this.polymer\n const n = this.size\n const n1 = n - 1\n let nTan = n1 * m * 3 + 3\n if (polymer.isCyclic) nTan += m * 3\n\n const tan = new Float32Array(nTan)\n const iterator = this.positionIterator || this.getAtomIterator('trace', this.smoothSheet)\n\n this.interpolator.getTangent(iterator, tan, 0, polymer.isCyclic)\n\n return tan\n }\n\n getNormals (tan: Float32Array) {\n const m = this.subdiv\n const polymer = this.polymer\n const isProtein = polymer.isProtein()\n const n = this.size\n const n1 = n - 1\n let nNorm = n1 * m * 3 + 3\n if (polymer.isCyclic) nNorm += m * 3\n\n const norm = new Float32Array(nNorm)\n const bin = new Float32Array(nNorm)\n\n if (this.directional && !this.polymer.isCg()) {\n const iterDir1 = this.getAtomIterator('direction1')\n const iterDir2 = this.getAtomIterator('direction2')\n this.interpolator.getNormalDir(\n iterDir1, iterDir2, tan, norm, bin, 0, polymer.isCyclic, isProtein\n )\n } else {\n this.interpolator.getNormal(\n n, tan, norm, bin, 0, polymer.isCyclic\n )\n }\n\n return {\n 'normal': norm,\n 'binormal': bin\n }\n }\n\n}\n\nexport default Spline\n","/**\n * @file Tube Mesh Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Matrix4 required for declaration only\nimport { Vector3, Matrix4 } from 'three'\n\nimport { defaults, getUintArray } from '../utils'\nimport { serialArray } from '../math/array-utils'\nimport MeshBuffer from './mesh-buffer'\nimport { BufferDefaultParameters, BufferData, BufferParameters } from './buffer'\nimport {Log} from \"../globals\";\n\nconst vTangent = new Vector3()\nconst vMeshNormal = new Vector3()\n\nexport interface TubeMeshBufferData extends BufferData {\n binormal: Float32Array\n tangent: Float32Array\n size: Float32Array\n}\n\nexport const TubeMeshBufferDefaultParameters = Object.assign({\n radialSegments: 4,\n capped: false,\n aspectRatio: 1.0\n}, BufferDefaultParameters)\nexport type TubeMeshBufferParameters = BufferParameters & {\n radialSegments: number,\n capped: boolean,\n aspectRatio: number\n}\n\nfunction getData (data: TubeMeshBufferData, params: Partial = {}) {\n const radialSegments = defaults(params.radialSegments, 4)\n const capped = defaults(params.capped, false)\n\n const capVertices = capped ? radialSegments : 0\n const capTriangles = capped ? radialSegments - 2 : 0\n\n const n = data.position!.length / 3\n const n1 = n - 1\n const x = n * radialSegments * 3 + 2 * capVertices * 3\n const xi = n1 * 2 * radialSegments * 3 + 2 * capTriangles * 3\n\n return {\n position: new Float32Array(x),\n color: new Float32Array(x),\n index: getUintArray(xi, x / 3),\n normal: new Float32Array(x),\n picking: data.picking\n }\n}\n\n/**\n * Tube mesh buffer. Draws a tube.\n */\nclass TubeMeshBuffer extends MeshBuffer {\n get defaultParameters() { return TubeMeshBufferDefaultParameters }\n parameters: TubeMeshBufferParameters\n\n capVertices: number\n capTriangles: number\n size2: number\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.normal - normals\n * @param {Float32Array} data.binormal - binormals\n * @param {Float32Array} data.tangent - tangents\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} data.size - sizes\n * @param {Picker} data.picking - picking ids\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: TubeMeshBufferData, params: Partial = {}) {\n super(getData(data, params), params)\n\n this.capVertices = this.parameters.capped ? this.parameters.radialSegments : 0\n this.capTriangles = this.parameters.capped ? this.parameters.radialSegments - 2 : 0\n\n this.size2 = data.position!.length / 3\n data.primitiveId = serialArray(this.size2)\n\n this.setAttributes(data)\n this.makeIndex()\n }\n\n setAttributes (data: Partial = {}) {\n const aspectRatio = this.parameters.aspectRatio\n\n const n = this.size2\n const n1 = n - 1\n const radialSegments = this.parameters.radialSegments\n\n const attributes = this.geometry.attributes as any\n\n let position, normal, binormal, tangent, color, size, primitiveId\n let meshPosition, meshColor, meshNormal, meshPrimitiveId\n\n if (data.position) {\n position = data.position\n normal = data.normal\n binormal = data.binormal\n tangent = data.tangent\n size = data.size\n\n meshPosition = attributes.position.array\n meshNormal = attributes.normal.array\n\n attributes.position.needsUpdate = true\n attributes.normal.needsUpdate = true\n }\n\n if (data.color) {\n color = data.color\n meshColor = attributes.color.array\n attributes.color.needsUpdate = true\n }\n\n if (data.primitiveId) {\n primitiveId = data.primitiveId\n meshPrimitiveId = attributes.primitiveId.array\n attributes.primitiveId.needsUpdate = true\n }\n\n let k, l\n let radius = 0\n\n let normX = 0\n let normY = 0\n let normZ = 0\n let biX = 0\n let biY = 0\n let biZ = 0\n let posX = 0\n let posY = 0\n let posZ = 0\n\n const cxArr = []\n const cyArr = []\n const cx1Arr = []\n const cy1Arr = []\n const cx2Arr = []\n const cy2Arr = []\n\n if (position) {\n for (let j = 0; j < radialSegments; ++j) {\n const v = (j / radialSegments) * 2 * Math.PI\n\n cxArr[ j ] = aspectRatio * Math.cos(v)\n cyArr[ j ] = Math.sin(v)\n\n cx1Arr[ j ] = aspectRatio * Math.cos(v - 0.01)\n cy1Arr[ j ] = Math.sin(v - 0.01)\n cx2Arr[ j ] = aspectRatio * Math.cos(v + 0.01)\n cy2Arr[ j ] = Math.sin(v + 0.01)\n }\n }\n\n for (let i = 0; i < n; ++i) {\n k = i * 3\n l = k * radialSegments\n\n if (position && tangent && normal && binormal && size) {\n vTangent.set(\n tangent[ k ], tangent[ k + 1 ], tangent[ k + 2 ]\n )\n\n normX = normal[ k ]\n normY = normal[ k + 1 ]\n normZ = normal[ k + 2 ]\n\n biX = binormal[ k ]\n biY = binormal[ k + 1 ]\n biZ = binormal[ k + 2 ]\n\n posX = position[ k ]\n posY = position[ k + 1 ]\n posZ = position[ k + 2 ]\n\n radius = size[ i ]\n }\n\n for (let j = 0; j < radialSegments; ++j) {\n const s = l + j * 3\n\n if (position) {\n const cx = -radius * cxArr[ j ] // TODO: Hack: Negating it so it faces outside.\n const cy = radius * cyArr[ j ]\n\n const cx1 = -radius * cx1Arr[ j ]\n const cy1 = radius * cy1Arr[ j ]\n const cx2 = -radius * cx2Arr[ j ]\n const cy2 = radius * cy2Arr[ j ]\n\n meshPosition[ s ] = posX + cx * normX + cy * biX\n meshPosition[ s + 1 ] = posY + cx * normY + cy * biY\n meshPosition[ s + 2 ] = posZ + cx * normZ + cy * biZ\n\n // TODO half of these are symmetric\n vMeshNormal.set(\n // ellipse tangent approximated as vector from/to adjacent points\n (cx2 * normX + cy2 * biX) - (cx1 * normX + cy1 * biX),\n (cx2 * normY + cy2 * biY) - (cx1 * normY + cy1 * biY),\n (cx2 * normZ + cy2 * biZ) - (cx1 * normZ + cy1 * biZ)\n ).cross(vTangent)\n\n meshNormal[ s ] = vMeshNormal.x\n meshNormal[ s + 1 ] = vMeshNormal.y\n meshNormal[ s + 2 ] = vMeshNormal.z\n }\n\n if (color) {\n meshColor[ s ] = color[ k ]\n meshColor[ s + 1 ] = color[ k + 1 ]\n meshColor[ s + 2 ] = color[ k + 2 ]\n }\n\n if (primitiveId) {\n meshPrimitiveId[ i * radialSegments + j ] = primitiveId[ i ]\n }\n }\n }\n\n // front cap\n\n k = 0\n l = n * 3 * radialSegments\n\n for (let j = 0; j < radialSegments; ++j) {\n const s = k + j * 3\n const t = l + j * 3\n\n if (position && tangent) {\n meshPosition[ t ] = meshPosition[ s ]\n meshPosition[ t + 1 ] = meshPosition[ s + 1 ]\n meshPosition[ t + 2 ] = meshPosition[ s + 2 ]\n\n meshNormal[ t ] = tangent[ k ]\n meshNormal[ t + 1 ] = tangent[ k + 1 ]\n meshNormal[ t + 2 ] = tangent[ k + 2 ]\n }\n\n if (color) {\n meshColor[ t ] = meshColor[ s ]\n meshColor[ t + 1 ] = meshColor[ s + 1 ]\n meshColor[ t + 2 ] = meshColor[ s + 2 ]\n }\n\n if (primitiveId) {\n meshPrimitiveId[ n * radialSegments + j ] = meshPrimitiveId[ 0 + j ]\n }\n }\n\n // back cap\n\n k = (n - 1) * 3 * radialSegments\n l = (n + 1) * 3 * radialSegments\n\n for (let j = 0; j < radialSegments; ++j) {\n const s = k + j * 3\n const t = l + j * 3\n\n if (position && tangent) {\n meshPosition[ t ] = meshPosition[ s ]\n meshPosition[ t + 1 ] = meshPosition[ s + 1 ]\n meshPosition[ t + 2 ] = meshPosition[ s + 2 ]\n\n meshNormal[ t ] = tangent[ n1 * 3 ]\n meshNormal[ t + 1 ] = tangent[ n1 * 3 + 1 ]\n meshNormal[ t + 2 ] = tangent[ n1 * 3 + 2 ]\n }\n\n if (color) {\n meshColor[ t ] = meshColor[ s ]\n meshColor[ t + 1 ] = meshColor[ s + 1 ]\n meshColor[ t + 2 ] = meshColor[ s + 2 ]\n }\n\n if (primitiveId) {\n meshPrimitiveId[ (n + 1) * radialSegments + j ] = meshPrimitiveId[ (n - 1) * radialSegments + j ]\n }\n }\n }\n\n makeIndex () {\n const index = this.geometry.getIndex()\n if (!index) { Log.error('Index is null'); return; }\n const meshIndex = index.array as Uint32Array|Uint16Array\n\n const n = this.size2\n const n1 = n - 1\n const capTriangles = this.capTriangles\n const radialSegments = this.parameters.radialSegments\n const radialSegments1 = this.parameters.radialSegments + 1\n\n let k, l\n\n for (let i = 0; i < n1; ++i) {\n const k = i * radialSegments * 3 * 2\n\n const irs = i * radialSegments\n const irs1 = (i + 1) * radialSegments\n\n for (let j = 0; j < radialSegments; ++j) {\n l = k + j * 3 * 2\n\n // meshIndex[ l + 0 ] = irs + ( ( j + 0 ) % radialSegments );\n meshIndex[ l ] = irs + j\n meshIndex[ l + 1 ] = irs + ((j + 1) % radialSegments)\n // meshIndex[ l + 2 ] = irs1 + ( ( j + 0 ) % radialSegments );\n meshIndex[ l + 2 ] = irs1 + j\n\n // meshIndex[ l + 3 ] = irs1 + ( ( j + 0 ) % radialSegments );\n meshIndex[ l + 3 ] = irs1 + j\n meshIndex[ l + 4 ] = irs + ((j + 1) % radialSegments)\n meshIndex[ l + 5 ] = irs1 + ((j + 1) % radialSegments)\n }\n }\n\n // capping\n\n const strip = [ 0 ]\n\n for (let j = 1; j < radialSegments1 / 2; ++j) {\n strip.push(j)\n if (radialSegments - j !== j) {\n strip.push(radialSegments - j)\n }\n }\n\n // front cap\n\n l = n1 * radialSegments * 3 * 2\n k = n * radialSegments\n\n for (let j = 0; j < strip.length - 2; ++j) {\n if (j % 2 === 0) {\n meshIndex[ l + j * 3 + 0 ] = k + strip[ j + 0 ]\n meshIndex[ l + j * 3 + 1 ] = k + strip[ j + 1 ]\n meshIndex[ l + j * 3 + 2 ] = k + strip[ j + 2 ]\n } else {\n meshIndex[ l + j * 3 + 0 ] = k + strip[ j + 2 ]\n meshIndex[ l + j * 3 + 1 ] = k + strip[ j + 1 ]\n meshIndex[ l + j * 3 + 2 ] = k + strip[ j + 0 ]\n }\n }\n\n // back cap\n\n l = n1 * radialSegments * 3 * 2 + 3 * capTriangles\n k = n * radialSegments + radialSegments\n\n for (let j = 0; j < strip.length - 2; ++j) {\n if (j % 2 === 0) {\n meshIndex[ l + j * 3 + 0 ] = k + strip[ j + 0 ]\n meshIndex[ l + j * 3 + 1 ] = k + strip[ j + 1 ]\n meshIndex[ l + j * 3 + 2 ] = k + strip[ j + 2 ]\n } else {\n meshIndex[ l + j * 3 + 0 ] = k + strip[ j + 2 ]\n meshIndex[ l + j * 3 + 1 ] = k + strip[ j + 1 ]\n meshIndex[ l + j * 3 + 2 ] = k + strip[ j + 0 ]\n }\n }\n }\n}\n\nexport default TubeMeshBuffer\n","/**\n * @file Cartoon Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport { Debug, Log, RepresentationRegistry } from '../globals'\nimport Spline from '../geometry/spline'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport TubeMeshBuffer from '../buffer/tubemesh-buffer'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport Polymer from '../proxy/polymer';\nimport AtomProxy from '../proxy/atom-proxy';\nimport StructureView from '../structure/structure-view';\nimport Buffer from '../buffer/buffer';\n\nexport interface CartoonRepresentationParameters extends StructureRepresentationParameters {\n aspectRatio: number\n subdiv: number\n radialSegments: number\n tension: number\n capped: boolean\n smoothSheet: boolean\n}\n\n/**\n * Cartoon representation. Show a thick ribbon that\n * smoothly connecting backbone atoms in polymers.\n *\n * __Name:__ _cartoon_\n *\n * @example\n * stage.loadFile( \"rcsb://1crn\" ).then( function( o ){\n * o.addRepresentation( \"cartoon\" );\n * o.autoView();\n * } );\n */\nclass CartoonRepresentation extends StructureRepresentation {\n protected aspectRatio: number\n protected tension: number\n protected capped: boolean\n protected smoothSheet: boolean\n protected subdiv: number\n \n /**\n * Create Cartoon representation object\n * @param {Structure} structure - the structure to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {StructureRepresentationParameters} params - representation parameters\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'cartoon'\n\n this.parameters = Object.assign({\n\n aspectRatio: {\n type: 'number', precision: 1, max: 10.0, min: 1.0, rebuild: true\n },\n subdiv: {\n type: 'integer', max: 50, min: 1, rebuild: true\n },\n radialSegments: {\n type: 'integer', max: 50, min: 1, rebuild: true\n },\n tension: {\n type: 'number', precision: 1, max: 1.0, min: 0.1\n },\n capped: {\n type: 'boolean', rebuild: true\n },\n smoothSheet: {\n type: 'boolean', rebuild: true\n }\n\n }, this.parameters)\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n p.colorScheme = defaults(p.colorScheme, 'chainname')\n p.colorScale = defaults(p.colorScale, 'RdYlBu')\n p.radiusType = defaults(p.radiusType, 'sstruc')\n p.radiusScale = defaults(p.radiusScale, 0.7)\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n this.aspectRatio = defaults(p.aspectRatio, 5.0)\n this.tension = defaults(p.tension, NaN)\n this.capped = defaults(p.capped, true)\n this.smoothSheet = defaults(p.smoothSheet, false)\n\n if (p.quality === 'low') {\n this.subdiv = 3\n this.radialSegments = 6\n } else if (p.quality === 'medium') {\n this.subdiv = 6\n } else if (p.quality === 'high') {\n this.subdiv = 12\n } else {\n this.subdiv = defaults(p.subdiv, 6)\n }\n\n super.init(p)\n }\n\n getSplineParams (params?: Partial) {\n return Object.assign({\n subdiv: this.subdiv,\n tension: this.tension,\n directional: this.aspectRatio !== 1.0,\n smoothSheet: this.smoothSheet\n }, params)\n }\n\n getSpline (polymer: Polymer): Spline {\n return new Spline(polymer, this.getSplineParams())\n }\n\n getAspectRatio (polymer: Polymer): number {\n return polymer.isCg() ? 1.0 : this.aspectRatio\n }\n\n getAtomRadius (atom: AtomProxy): number {\n return atom.isTrace() ? super.getAtomRadius(atom) : 0\n }\n\n createData (sview: StructureView) {\n let bufferList: Buffer[] = []\n let polymerList: Polymer[] = []\n\n this.structure.eachPolymer(polymer => {\n if (polymer.residueCount < 4) return\n polymerList.push(polymer)\n\n const spline = this.getSpline(polymer)\n const aspectRatio = this.getAspectRatio(polymer)\n\n const subPos = spline.getSubdividedPosition()\n const subOri = spline.getSubdividedOrientation()\n const subCol = spline.getSubdividedColor(this.getColorParams())\n const subPick = spline.getSubdividedPicking()\n const subSize = spline.getSubdividedSize(this.getRadiusParams())\n\n bufferList.push(\n new TubeMeshBuffer(\n Object.assign({}, subPos, subOri, subCol, subPick, subSize),\n this.getBufferParams({\n radialSegments: this.radialSegments,\n aspectRatio: aspectRatio,\n capped: this.capped\n })\n )\n )\n }, sview.getSelection())\n\n return {\n bufferList: bufferList,\n polymerList: polymerList\n }\n }\n\n updateData (what: any, data: StructureRepresentationData) {\n if (Debug) Log.time(this.type + ' repr update')\n\n what = what || {}\n\n for (var i = 0, il = data.polymerList!.length; i < il; ++i) {\n var bufferData: {[key: string]: any} = {}\n var polymer = data.polymerList![ i ]\n var spline = this.getSpline(polymer)\n var aspectRatio = this.getAspectRatio(polymer)\n\n Object.assign(data.bufferList[ i ], {aspectRatio: aspectRatio})\n\n if (what.position || what.radius) {\n var subPos = spline.getSubdividedPosition()\n var subOri = spline.getSubdividedOrientation()\n var subSize = spline.getSubdividedSize(this.getRadiusParams(aspectRatio))\n\n bufferData.position = subPos.position\n bufferData.normal = subOri.normal\n bufferData.binormal = subOri.binormal\n bufferData.tangent = subOri.tangent\n bufferData.size = subSize.size\n }\n\n if (what.color) {\n var subCol = spline.getSubdividedColor(this.getColorParams())\n bufferData.color = subCol.color\n }\n\n if (what.picking) {\n var subPick = spline.getSubdividedPicking()\n bufferData.picking = subPick.picking\n }\n\n data.bufferList[ i ].setAttributes(bufferData)\n }\n\n if (Debug) Log.timeEnd(this.type + ' repr update')\n }\n\n setParameters (params: Partial) {\n const rebuild = false\n var what: {[k: string]: any} = {}\n\n if (params && params.aspectRatio) {\n what.radius = true\n }\n\n if (params && params.tension) {\n what.position = true\n }\n\n super.setParameters(params, what, rebuild)\n\n return this\n }\n}\n\nRepresentationRegistry.add('cartoon', CartoonRepresentation)\n\nexport default CartoonRepresentation\n","/**\n * @file Contact Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport { RepresentationRegistry } from '../globals'\nimport StructureRepresentation, { StructureRepresentationParameters } from './structure-representation'\nimport { calculateContacts, getContactData, getLabelData } from '../chemistry/interactions/contact'\nimport CylinderBuffer from '../buffer/cylinder-buffer'\nimport TextBuffer from '../buffer/text-buffer'\nimport { getFixedCountDashData } from '../geometry/dash'\nimport Viewer from '../viewer/viewer';\nimport { Structure } from '../ngl';\nimport StructureView from '../structure/structure-view';\nimport CylinderGeometryBuffer from '../buffer/cylindergeometry-buffer';\nimport CylinderImpostorBuffer from '../buffer/cylinderimpostor-buffer';\n// @ts-ignore: unused import ContactPicker required for declaration only\nimport { ContactPicker } from '../utils/picker';\n\nexport interface ContactRepresentationParameters extends StructureRepresentationParameters {\n hydrogenBond: boolean\n weakHydrogenBond: boolean\n waterHydrogenBond: boolean\n backboneHydrogenBond: boolean\n hydrophobic: boolean\n halogenBond: boolean\n ionicInteraction: boolean\n metalCoordination: boolean\n cationPi: boolean\n piStacking: boolean\n filterSele: string|[string, string]\n maxHydrophobicDist: number\n maxHbondDist: number\n maxHbondSulfurDist: number\n maxHbondAccAngle: number\n maxHbondDonAngle: number\n maxHbondAccPlaneAngle: number\n maxHbondDonPlaneAngle: number\n maxPiStackingDist: number\n maxPiStackingOffset: number\n maxPiStackingAngle: number\n maxCationPiDist: number\n maxCationPiOffset: number\n maxIonicDist: number\n maxHalogenBondDist: number\n maxHalogenBondAngle: number\n maxMetalDist: number\n refineSaltBridges: boolean\n masterModelIndex: number\n lineOfSightDistFactor: number\n}\n\n/**\n * Contact representation.\n */\nclass ContactRepresentation extends StructureRepresentation {\n protected hydrogenBond: boolean\n protected weakHydrogenBond: boolean\n protected waterHydrogenBond: boolean\n protected backboneHydrogenBond: boolean\n protected hydrophobic: boolean\n protected halogenBond: boolean\n protected ionicInteraction: boolean\n protected metalCoordination: boolean\n protected cationPi: boolean\n protected piStacking: boolean\n protected filterSele: string|[string, string]\n protected maxHydrophobicDist: number\n protected maxHbondDist: number\n protected maxHbondSulfurDist: number\n protected maxHbondAccAngle: number\n protected maxHbondDonAngle: number\n protected maxHbondAccPlaneAngle: number\n protected maxHbondDonPlaneAngle: number\n protected maxPiStackingDist: number\n protected maxPiStackingOffset: number\n protected maxPiStackingAngle: number\n protected maxCationPiDist: number\n protected maxCationPiOffset: number\n protected maxIonicDist: number\n protected maxHalogenBondDist: number\n protected maxHalogenBondAngle: number\n protected maxMetalDist: number\n protected refineSaltBridges: boolean\n protected masterModelIndex: number\n protected lineOfSightDistFactor: number\n\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'contact'\n\n this.parameters = Object.assign({\n hydrogenBond: {\n type: 'boolean', rebuild: true\n },\n weakHydrogenBond: {\n type: 'boolean', rebuild: true\n },\n waterHydrogenBond: {\n type: 'boolean', rebuild: true\n },\n backboneHydrogenBond: {\n type: 'boolean', rebuild: true\n },\n hydrophobic: {\n type: 'boolean', rebuild: true\n },\n halogenBond: {\n type: 'boolean', rebuild: true\n },\n ionicInteraction: {\n type: 'boolean', rebuild: true\n },\n metalCoordination: {\n type: 'boolean', rebuild: true\n },\n cationPi: {\n type: 'boolean', rebuild: true\n },\n piStacking: {\n type: 'boolean', rebuild: true\n },\n\n filterSele: {\n type: 'text', rebuild: true\n },\n\n labelVisible: {\n type: 'boolean', rebuild: true\n },\n\n labelFixedSize: {\n type: 'boolean', buffer: 'fixedSize'\n },\n\n labelSize: {\n type: 'number', precision: 3, max: 10.0, min: 0.001, rebuild: true\n },\n\n labelUnit: {\n type: 'select',\n rebuild: true,\n options: { '': '', angstrom: 'angstrom', nm: 'nm' }\n },\n\n maxHydrophobicDist: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n maxHbondDist: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n maxHbondSulfurDist: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n maxHbondAccAngle: {\n type: 'integer', max: 180, min: 0, rebuild: true\n },\n maxHbondDonAngle: {\n type: 'integer', max: 180, min: 0, rebuild: true\n },\n maxHbondAccPlaneAngle: {\n type: 'integer', max: 90, min: 0, rebuild: true\n },\n maxHbondDonPlaneAngle: {\n type: 'integer', max: 90, min: 0, rebuild: true\n },\n maxPiStackingDist: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n maxPiStackingOffset: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n maxPiStackingAngle: {\n type: 'integer', max: 180, min: 0, rebuild: true\n },\n maxCationPiDist: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n maxCationPiOffset: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n maxIonicDist: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n maxHalogenBondDist: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n maxHalogenBondAngle: {\n type: 'integer', max: 180, min: 0, rebuild: true\n },\n maxMetalDist: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n refineSaltBridges: {\n type: 'boolean', rebuild: true\n },\n masterModelIndex: {\n type: 'integer', max: 1000, min: -1, rebuild: true\n },\n lineOfSightDistFactor: {\n type: 'number', precision: 1, max: 10, min: 0.0, rebuild: true\n },\n\n radialSegments: true,\n disableImpostor: true\n }, this.parameters)\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n p.radiusSize = defaults(p.radiusSize, 0.05)\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n this.hydrogenBond = defaults(p.hydrogenBond, true)\n this.weakHydrogenBond = defaults(p.weakHydrogenBond, false)\n this.waterHydrogenBond = defaults(p.waterHydrogenBond, false)\n this.backboneHydrogenBond = defaults(p.backboneHydrogenBond, false)\n this.hydrophobic = defaults(p.hydrophobic, false)\n this.halogenBond = defaults(p.halogenBond, true)\n this.ionicInteraction = defaults(p.ionicInteraction, true)\n this.metalCoordination = defaults(p.metalCoordination, true)\n this.cationPi = defaults(p.cationPi, true)\n this.piStacking = defaults(p.piStacking, true)\n\n this.filterSele = defaults(p.filterSele, '')\n this.labelVisible = defaults(p.labelVisible, false)\n this.labelFixedSize = defaults(p.labelFixedSize, false)\n this.labelSize = defaults(p.labelSize, 2.0)\n this.labelUnit = defaults(p.labelUnit, '')\n\n this.maxHydrophobicDist = defaults(p.maxHydrophobicDist, 4.0)\n this.maxHbondDist = defaults(p.maxHbondDist, 3.5)\n this.maxHbondSulfurDist = defaults(p.maxHbondSulfurDist, 4.1)\n this.maxHbondAccAngle = defaults(p.maxHbondAccAngle, 45)\n this.maxHbondDonAngle = defaults(p.maxHbondDonAngle, 45)\n this.maxHbondAccPlaneAngle = defaults(p.maxHbondAccPlaneAngle, 90)\n this.maxHbondDonPlaneAngle = defaults(p.maxHbondDonPlaneAngle, 30)\n this.maxPiStackingDist = defaults(p.maxPiStackingDist, 5.5)\n this.maxPiStackingOffset = defaults(p.maxPiStackingOffset, 2.0)\n this.maxPiStackingAngle = defaults(p.maxPiStackingAngle, 30)\n this.maxCationPiDist = defaults(p.maxCationPiDist, 6.0)\n this.maxCationPiOffset = defaults(p.maxCationPiOffset, 2.0)\n this.maxIonicDist = defaults(p.maxIonicDist, 5.0)\n this.maxHalogenBondDist = defaults(p.maxHalogenBondDist, 3.5)\n this.maxHalogenBondAngle = defaults(p.maxHalogenBondAngle, 30)\n this.maxMetalDist = defaults(p.maxMetalDist, 3.0)\n this.refineSaltBridges = defaults(p.refineSaltBridges, true)\n this.masterModelIndex = defaults(p.masterModelIndex, -1)\n this.lineOfSightDistFactor = defaults(p.lineOfSightDistFactor, 1.0)\n\n super.init(p)\n }\n\n getAtomRadius () {\n return 0\n }\n\n getContactData (sview: StructureView) {\n const params = {\n maxHydrophobicDist: this.maxHydrophobicDist,\n maxHbondDist: this.maxHbondDist,\n maxHbondSulfurDist: this.maxHbondSulfurDist,\n maxHbondAccAngle: this.maxHbondAccAngle,\n maxHbondDonAngle: this.maxHbondDonAngle,\n maxHbondAccPlaneAngle: this.maxHbondAccPlaneAngle,\n maxHbondDonPlaneAngle: this.maxHbondDonPlaneAngle,\n maxPiStackingDist: this.maxPiStackingDist,\n maxPiStackingOffset: this.maxPiStackingOffset,\n maxPiStackingAngle: this.maxPiStackingAngle,\n maxCationPiDist: this.maxCationPiDist,\n maxCationPiOffset: this.maxCationPiOffset,\n maxIonicDist: this.maxIonicDist,\n maxHalogenBondDist: this.maxHalogenBondDist,\n maxHalogenBondAngle: this.maxHalogenBondAngle,\n maxMetalDist: this.maxMetalDist,\n refineSaltBridges: this.refineSaltBridges,\n masterModelIndex: this.masterModelIndex,\n lineOfSightDistFactor: this.lineOfSightDistFactor\n }\n\n const dataParams = {\n hydrogenBond: this.hydrogenBond,\n weakHydrogenBond: this.weakHydrogenBond,\n waterHydrogenBond: this.waterHydrogenBond,\n backboneHydrogenBond: this.backboneHydrogenBond,\n hydrophobic: this.hydrophobic,\n halogenBond: this.halogenBond,\n ionicInteraction: this.ionicInteraction,\n metalCoordination: this.metalCoordination,\n cationPi: this.cationPi,\n piStacking: this.piStacking,\n radius: this.radiusSize * this.radiusScale,\n filterSele: this.filterSele\n }\n\n const contacts = calculateContacts(sview, params)\n return getContactData(contacts, sview, dataParams)\n }\n\n createData (sview: StructureView) {\n const contactData = this.getContactData(sview)\n\n const bufferList = [\n new CylinderBuffer(\n getFixedCountDashData(contactData),\n this.getBufferParams({\n sphereDetail: 1,\n dullInterior: true,\n disableImpostor: this.disableImpostor\n })\n ) as (CylinderGeometryBuffer | CylinderImpostorBuffer | TextBuffer)\n ]\n\n if (this.labelVisible) {\n const labelParams = {\n size: this.labelSize,\n unit: this.labelUnit\n }\n bufferList.push(new TextBuffer(\n getLabelData(contactData, labelParams),\n this.getBufferParams({fixedSize: this.labelFixedSize})\n ))\n }\n\n return { bufferList }\n }\n}\n\nRepresentationRegistry.add('contact', ContactRepresentation)\n\nexport default ContactRepresentation\n","/**\n * @file Dihedral Representation\n * @author Fred Ludlow \n * @private\n */\nimport { Color } from 'three'\n\nimport { RepresentationRegistry } from '../globals'\nimport MeasurementRepresentation, { calcArcPoint, parseNestedAtoms, MeasurementRepresentationParameters, LabelDataField } from './measurement-representation'\nimport { defaults } from '../utils'\n\nimport MeshBuffer from '../buffer/mesh-buffer'\nimport TextBuffer, { TextBufferData } from '../buffer/text-buffer'\nimport WideLineBuffer from '../buffer/wideline-buffer'\n\nimport { copyArray, uniformArray, uniformArray3 } from '../math/array-utils'\nimport { v3add, v3angle, v3cross, v3dot, v3multiplyScalar, v3fromArray, v3length,\n v3negate, v3new, v3normalize, v3sub, v3toArray } from '../math/vector-utils'\nimport { RAD2DEG } from '../math/math-constants'\nimport { getFixedLengthWrappedDashData } from '../geometry/dash'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport StructureView from '../structure/structure-view';\nimport { CylinderBufferData } from '../buffer/cylinder-buffer';\nimport { BufferData } from '../buffer/buffer';\nimport { StructureRepresentationData } from './structure-representation';\n\n/**\n * @typedef {Object} DihedralRepresentationParameters - dihedral representation parameters\n * @mixes RepresentationParameters\n * @mixes StructureRepresentationParameters\n * @mixes MeasurementRepresentationParameters\n *\n * @property {String} atomQuad - list of quadruplets of selection strings\n * or atom indices\n * @property {Boolean} extendLine - Extend lines in planes\n * @property {Number} lineOpacity - Opacity for the line part of the representation\n * @property {Boolean} lineVisible - Display the line part of the representation\n * @property {Number} linewidth - width for line part of representation\n * @property {Boolean} planeVisible - Display the two planes corresponding to dihedral\n * @property {Boolean} sectorVisible - Display the filled arc for each angle\n */\n\nexport interface DihedralRepresentationParameters extends MeasurementRepresentationParameters {\n atomQuad: (number|string)[][]\n extendLine: boolean\n lineOpacity: number\n lineVisible: boolean\n linewidth: number\n planeVisible: boolean\n sectorVisible: boolean\n}\n\n/**\n * Dihedral representation object\n *\n * Reperesentation consists of three parts, visibility can be set for each\n * label - text label indicating dihedral angle\n * line - line indicating four positions that define the dihedral\n * sector - filled arc section\n *\n * @param {Structure} structure - the structure to measure angles in\n * @param {Viewer} viewer - a viewer object\n * @param {AngleRepresentationParameters} params - angle representation parameters\n */\nclass DihedralRepresentation extends MeasurementRepresentation {\n protected atomQuad: (number|string)[][]\n protected extendLine: boolean\n protected lineOpacity: number\n protected lineVisible: boolean\n protected linewidth: number\n protected planeVisible: boolean\n protected sectorVisible: boolean\n\n protected lineLength: number\n protected planeLength: number\n protected sectorLength: number\n\n protected lineBuffer: WideLineBuffer\n protected planeBuffer: MeshBuffer\n protected sectorBuffer: MeshBuffer\n\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'dihedral'\n\n this.parameters = Object.assign({\n atomQuad: {\n type: 'hidden', rebuild: true\n },\n extendLine: {\n type: 'boolean', rebuild: true, default: true\n },\n lineVisible: {\n type: 'boolean', default: true\n },\n planeVisible: {\n type: 'boolean', default: true\n },\n sectorVisible: {\n type: 'boolean', default: true\n }\n }, this.parameters)\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n p.side = defaults(p.side, 'double')\n p.opacity = defaults(p.opacity, 0.5)\n\n this.atomQuad = defaults(p.atomQuad, [])\n this.extendLine = defaults(p.extendLine, true)\n this.lineVisible = defaults(p.lineVisible, true)\n this.planeVisible = defaults(p.planeVisible, true)\n this.sectorVisible = defaults(p.sectorVisible, true)\n\n super.init(p)\n }\n\n createData (sview: StructureView) {\n if (!sview.atomCount || !this.atomQuad.length) return\n\n const atomPosition = parseNestedAtoms(sview, this.atomQuad)\n const dihedralData = getDihedralData(\n atomPosition, {\n extendLine: this.extendLine\n }\n )\n\n const n = this.n = dihedralData.labelText.length\n const labelColor = new Color(this.labelColor)\n\n this.textBuffer = new TextBuffer({\n position: dihedralData.labelPosition,\n size: uniformArray(n, this.labelSize),\n color: uniformArray3(n, labelColor.r, labelColor.g, labelColor.b),\n text: dihedralData.labelText\n } as TextBufferData, this.getLabelBufferParams())\n\n const c = new Color(this.colorValue)\n this.lineLength = dihedralData.linePosition1.length / 3\n const lineColor = uniformArray3(this.lineLength, c.r, c.g, c.b)\n\n this.lineBuffer = new WideLineBuffer(\n getFixedLengthWrappedDashData({\n position1: dihedralData.linePosition1,\n position2: dihedralData.linePosition2,\n color: lineColor,\n color2: lineColor\n } as CylinderBufferData) ,\n this.getBufferParams({\n linewidth: this.linewidth,\n visible: this.lineVisible,\n opacity: this.lineOpacity\n })\n )\n\n this.planeLength = dihedralData.planePosition.length / 3\n this.planeBuffer = new MeshBuffer({\n position: dihedralData.planePosition,\n color: uniformArray3(this.planeLength, c.r, c.g, c.b)\n } as BufferData, this.getBufferParams({\n visible: this.planeVisible\n }))\n\n this.sectorLength = dihedralData.sectorPosition.length / 3\n this.sectorBuffer = new MeshBuffer({\n position: dihedralData.sectorPosition,\n color: uniformArray3(this.sectorLength, c.r, c.g, c.b)\n } as BufferData, this.getBufferParams({\n visible: this.sectorVisible\n }))\n\n return {\n bufferList: [\n this.textBuffer,\n this.lineBuffer,\n this.planeBuffer,\n this.sectorBuffer\n ]\n }\n }\n\n updateData (what: LabelDataField & {color?: boolean}, data: StructureRepresentationData) {\n super.updateData(what, data)\n const lineData = {}\n const planeData = {}\n const sectorData = {}\n\n if (what.color) {\n const c = new Color(this.colorValue)\n Object.assign(lineData, {\n color: uniformArray3(this.lineLength, c.r, c.g, c.b),\n color2: uniformArray3(this.lineLength, c.r, c.g, c.b)\n })\n Object.assign(planeData, {\n color: uniformArray3(this.planeLength, c.r, c.g, c.b)\n })\n Object.assign(sectorData, {\n color: uniformArray3(this.sectorLength, c.r, c.g, c.b)\n })\n }\n\n this.lineBuffer.setAttributes(lineData)\n this.planeBuffer.setAttributes(planeData)\n this.sectorBuffer.setAttributes(sectorData)\n }\n\n setParameters (params: Partial) {\n var rebuild = false\n var what = {}\n\n super.setParameters(params, what, rebuild)\n\n if (params && (\n params.lineVisible !== undefined ||\n params.sectorVisible !== undefined ||\n params.planeVisible !== undefined)) {\n this.setVisibility(this.visible)\n }\n\n if (params && params.lineOpacity) {\n this.lineBuffer.setParameters({ opacity: params.lineOpacity })\n }\n\n if (params && params.opacity !== undefined) {\n this.lineBuffer.setParameters({ opacity: this.lineOpacity })\n }\n\n if (params && params.linewidth) {\n this.lineBuffer.setParameters({ linewidth: params.linewidth })\n }\n\n return this\n }\n\n setVisibility (value: boolean, noRenderRequest?: boolean) {\n super.setVisibility(value, true)\n\n if (this.lineBuffer) {\n this.lineBuffer.setVisibility(this.lineVisible && this.visible)\n }\n\n if (this.planeBuffer) {\n this.planeBuffer.setVisibility(this.planeVisible && this.visible)\n }\n\n if (this.sectorBuffer) {\n this.sectorBuffer.setVisibility(this.sectorVisible && this.visible)\n }\n\n if (!noRenderRequest) this.viewer.requestRender()\n\n return this\n }\n}\n\n/**\n * Build the data required to create {Buffer} objects, given positions\n * @param {Float32Array} atomPosition 3*4*nDihedral array of coordinates\n * @return {Object} Arrays for building buffers\n */\nfunction getDihedralData (position: Float32Array, params: Partial = {}) {\n const angleStep = defaults(params.angleStep, Math.PI / 90)\n const nPos = position.length\n const n = position.length / 12\n const angles = new Float32Array(n)\n const labelPosition = new Float32Array(n * 3)\n const labelText = new Array(n)\n\n // Temporary arrays as don't know output length yet\n const lineTmp1 = new Array(n)\n const lineTmp2 = new Array(n)\n const sectorTmp = new Array(n)\n const planeTmp = new Array(n)\n\n // Eventual sizes of output arrays\n let totalLines = 0\n let totalSegments = 0\n let totalPlanes = 0\n\n const p1 = v3new()\n const p2 = v3new()\n const p3 = v3new()\n const p4 = v3new()\n\n const v21 = v3new()\n const v23 = v3new()\n const v34 = v3new()\n\n const tmp = v3new()\n const mid = v3new()\n const inPlane1 = v3new()\n const inPlane2 = v3new()\n const start = v3new()\n const end = v3new()\n\n const cross = v3new()\n const arcPoint = v3new()\n\n let i = 0 // Actual output index (after skipping inappropriate)\n\n for (var p = 0; p < nPos; p += 12) {\n // Set Positions\n v3fromArray(p1, position, p)\n v3fromArray(p2, position, p + 3)\n v3fromArray(p3, position, p + 6)\n v3fromArray(p4, position, p + 9)\n\n // Vectors between points\n v3sub(v21, p1, p2)\n v3sub(v23, p3, p2)\n if (v3length(v23) === 0.0) {\n continue // Can't define axis\n }\n\n v3sub(v34, p4, p3)\n\n v3multiplyScalar(tmp, v23, 0.5)\n v3add(mid, p2, tmp)\n\n v3normalize(v21, v21)\n v3normalize(v23, v23)\n v3normalize(v34, v34)\n\n // Which side of plane are p1, p4 (are we measuring something that\n // looks more like an improper? e.g. C, CA, CB, N)\n v3sub(tmp, p1, mid)\n const improperStart = v3dot(tmp, v23) > 0.0\n v3sub(tmp, p4, mid)\n const improperEnd = v3dot(tmp, v23) < 0.0\n\n // Calculate vectors perp to v23 (lying in plane (1,2,3) and (2,3,4))\n v3multiplyScalar(tmp, v23, v3dot(v23, v21))\n v3sub(inPlane1, v21, tmp)\n\n v3multiplyScalar(tmp, v23, v3dot(v23, v34))\n v3sub(inPlane2, v34, tmp)\n\n if (v3length(inPlane1) === 0.0 || v3length(inPlane2) === 0.0) {\n continue // Indeterminate angle\n }\n\n v3normalize(inPlane1, inPlane1)\n v3normalize(inPlane2, inPlane2)\n\n const angle = angles[ i ] = v3angle(inPlane1, inPlane2)\n labelText[ i ] = (RAD2DEG * angle).toFixed(1) + String.fromCharCode(0x00B0)\n\n v3cross(cross, inPlane1, v23)\n v3normalize(cross, cross)\n if (v3dot(cross, inPlane2) < 0.0) {\n v3negate(cross, cross) // Ensure cp faces correct way\n }\n\n calcArcPoint(tmp, mid, inPlane1, cross, angle / 2.0)\n v3toArray(tmp, labelPosition, 3 * i)\n\n const nSegments = Math.ceil(angle / angleStep)\n // For extended display mode, 4 straight lines plus arc/segment edge\n // For non-extended, 2 straight lines plus segment edge\n const nLines = nSegments + ((params.extendLine) ? 4 : 2)\n\n // Don't draw planes if not extending lines\n const nPlanes = params.extendLine ? 36 : 0\n\n const line1 = new Float32Array(nLines * 3)\n const line2 = new Float32Array(nLines * 3)\n const sector = new Float32Array(nSegments * 9)\n // 2 planes, 2 triangles each per dihedral (2*2*9)\n const plane = new Float32Array(nPlanes)\n\n lineTmp1[ i ] = line1\n lineTmp2[ i ] = line2\n sectorTmp[ i ] = sector\n planeTmp[ i ] = plane\n\n // Start points for lines/planes, only required\n // if extending lines\n if (params.extendLine) {\n if (improperStart) { // We'll start on the v3->1 line (tmp)\n v3sub(tmp, p1, p3)\n v3normalize(tmp, tmp)\n v3multiplyScalar(start, tmp, 1.0 / v3dot(inPlane1, tmp))\n v3add(start, start, p3)\n } else { // start on the 2->1 line\n v3multiplyScalar(start, v21, 1.0 / v3dot(inPlane1, v21))\n v3add(start, start, p2)\n }\n\n if (improperEnd) { // Finish on 2->4 line\n v3sub(tmp, p4, p2)\n v3normalize(tmp, tmp)\n v3multiplyScalar(end, tmp, 1.0 / v3dot(inPlane2, tmp))\n v3add(end, end, p2)\n } else { // end on the 3->4 line\n v3multiplyScalar(end, v34, 1.0 / v3dot(inPlane2, v34))\n v3add(end, end, p3)\n }\n }\n\n v3add(arcPoint, mid, inPlane1)\n\n // index into line1, line2\n let li = 0\n // If extending lines, there's a bit of stuff to do here\n // figuring out start and end positions\n if (params.extendLine) {\n v3toArray(p1, line1, li)\n v3toArray(start, line2, li)\n li += 3\n v3toArray(start, line1, li)\n v3toArray(arcPoint, line2, li)\n li += 3\n\n // Construct plane at start, if not extening lines\n // this is skipped\n v3toArray(start, plane, 0)\n v3toArray(arcPoint, plane, 3)\n v3toArray(improperStart ? p3 : p2, plane, 6)\n v3toArray(improperStart ? p3 : p2, plane, 9)\n v3toArray(arcPoint, plane, 12)\n v3toArray(mid, plane, 15)\n } else {\n // Not extending lines\n v3toArray(mid, line1, li)\n v3toArray(arcPoint, line2, li)\n li += 3\n }\n\n const appendArcSection = function (a: number, j: number) {\n const si = j * 9\n\n v3toArray(mid, sector, si)\n v3toArray(arcPoint, sector, si + 3)\n v3toArray(arcPoint, line1, li)\n\n calcArcPoint(arcPoint, mid, inPlane1, cross, a)\n\n v3toArray(arcPoint, sector, si + 6)\n v3toArray(arcPoint, line2, li)\n li += 3\n }\n\n let j = 0\n for (let a = angleStep; a < angle; a += angleStep) {\n appendArcSection(a, j++)\n }\n appendArcSection(angle, j++)\n\n if (params.extendLine) {\n v3toArray(arcPoint, line1, (nLines - 2) * 3)\n v3toArray(end, line2, (nLines - 2) * 3)\n v3toArray(end, line1, (nLines - 1) * 3)\n v3toArray(p4, line2, (nLines - 1) * 3)\n\n // Construct plane at end\n v3toArray(end, plane, 18)\n v3toArray(arcPoint, plane, 21)\n v3toArray(improperEnd ? p2 : p3, plane, 24)\n v3toArray(improperEnd ? p2 : p3, plane, 27)\n v3toArray(arcPoint, plane, 30)\n v3toArray(mid, plane, 33)\n } else {\n v3toArray(arcPoint, line1, li)\n v3toArray(mid, line2, li)\n li += 3\n }\n\n totalLines += nLines * 3\n totalSegments += nSegments * 9\n totalPlanes += nPlanes\n i += 1\n }\n\n const nSuccess = i\n\n const linePosition1 = new Float32Array(totalLines)\n const linePosition2 = new Float32Array(totalLines)\n const sectorPosition = new Float32Array(totalSegments)\n const planePosition = new Float32Array(totalPlanes)\n\n let lineOffset = 0\n let sectorOffset = 0\n let planeOffset = 0\n\n for (let i = 0; i < nSuccess; i++) {\n const lp1 = lineTmp1[ i ]\n const lp2 = lineTmp2[ i ]\n const sp = sectorTmp[ i ]\n const pp = planeTmp[ i ]\n\n copyArray(lp1, linePosition1, 0, lineOffset, lp1.length)\n copyArray(lp2, linePosition2, 0, lineOffset, lp2.length)\n copyArray(sp, sectorPosition, 0, sectorOffset, sp.length)\n copyArray(pp, planePosition, 0, planeOffset, pp.length)\n\n lineOffset += lp1.length\n sectorOffset += sp.length\n planeOffset += pp.length\n }\n\n return {\n labelPosition: labelPosition.subarray(0, nSuccess * 3),\n labelText: labelText.slice(0, nSuccess),\n linePosition1,\n linePosition2,\n planePosition,\n sectorPosition\n }\n}\n\nRepresentationRegistry.add('dihedral', DihedralRepresentation)\n\nexport default DihedralRepresentation\n","/**\n * @file Dihedral Histogram Representation\n * @author Rudolfs Petrovs \n * @private\n */\nimport { Color } from 'three'\n\nimport { calcArcPoint, parseNestedAtoms } from './measurement-representation'\nimport StructureRepresentation, { StructureRepresentationParameters } from './structure-representation'\n\nimport { RepresentationRegistry } from '../globals'\nimport { Structure } from '../ngl'\nimport { defaults } from '../utils'\n\nimport { BufferData } from '../buffer/buffer'\nimport MeshBuffer from '../buffer/mesh-buffer'\nimport WideLineBuffer, { WideLineBufferData } from '../buffer/wideline-buffer'\n\nimport { copyArray, uniformArray3, arraySum } from '../math/array-utils'\nimport {\n v3add, v3cross, v3dot, v3multiplyScalar, v3fromArray,\n v3negate, v3new, v3normalize, v3sub, v3toArray, v3length\n} from '../math/vector-utils'\n\nimport StructureView from '../structure/structure-view'\n\nimport Viewer from '../viewer/viewer'\n\n\nconst pointLength = 3 // One Point Length (number of coordinates of one point in 3D)\nconst pointsInTriangle = 3\n\ntype ColorDefinition = Color | string | number | undefined\n\ninterface HistogramColorParameters {\n histogramBinBorderColor: ColorDefinition\n adjacentBondArrowColor: ColorDefinition\n distantBondArrowColor: ColorDefinition\n frontHistogramColor: ColorDefinition\n backHistogramColor: ColorDefinition\n opaqueMiddleDiscColor: ColorDefinition\n}\n\ninterface HistogramInputData extends Partial {\n atomQuad: (number | string)[]\n histogram360: number[]\n}\n\ninterface HistogramData extends HistogramInputData {\n atomPositions: Float32Array\n histogram360Scaled: number[]\n}\n\ninterface WideLineData {\n startPoints: Float32Array\n endPoints: Float32Array\n startColors: Float32Array\n endColors: Float32Array\n}\n\ninterface MeshData {\n triangles: Float32Array\n triangleColors: Float32Array\n}\n\nfunction createUpdatedObject(o: Object, updateSource: Object) {\n function hasKey(obj: O, key: keyof any): key is keyof O {\n return key in obj\n }\n\n const result = { ...o } // Shallow copy\n for (const key in result) {\n if (hasKey(result, key) && hasKey(updateSource, key)) {\n result[key] = defaults(updateSource[key], result[key])\n }\n }\n return result\n}\n\nfunction createColorArray(color: ColorDefinition, arrayLength: number) {\n const colorValue = new Color(color)\n const targetArray = new Float32Array(arrayLength * 3)\n uniformArray3(arrayLength, colorValue.r, colorValue.g, colorValue.b, targetArray)\n return targetArray\n}\n\n/**\n * @typedef {Object} DihedralHistogramRepresentationParameters - dihedral representation parameters\n * @mixes RepresentationParameters\n * @mixes StructureRepresentationParameters\n *\n * @property {HistogramInputData[]} histogramsData\n * List of HistogramInputData objects, which properties specifies each particular\n * histogram, and can contain particular histogram-specific parameters.\n * Obligatory properties are:\n * atomQuad - Quadruplet of selection strings or atom indices\n * histogram360 - List of values, representing histogram from 0 to 360 degrees.\n * @property {Boolean} histogramBinBorderVisible - Display the lines that separate circular histogram bins\n * @property {Boolean} scaleBinToSectorArea - Should sector-based histogram bins'\n * area be proportional to the bins' value\n */\n\nexport interface DihedralHistogramRepresentationParameters extends StructureRepresentationParameters {\n histogramsData: HistogramInputData[]\n\n histogramBinBorderVisible: boolean\n scaleBinToSectorArea: boolean\n}\n\n/**\n * Dihedral Histogram representation object\n *\n * Reperesentation consists of several parts:\n * opaqueMiddleDisc - opaque disc in the middle of the dihedral between front and back histograms\n * frontHistogram - circular histogram from the adjacent bond viewpoint\n * backHistogram - circular histogram from the distant bond viewpoint\n * histogramBinBorder - lines, which separate histogram bins\n * bondArrows - lines, which show the actual angle on the histogram disc\n *\n * @param {Structure} structure - the structure to measure angles in\n * @param {Viewer} viewer - a viewer object\n * @param {DihedralHistogramRepresentationParameters} params - Dihedral histogram representation parameters\n */\nclass DihedralHistogramRepresentation extends StructureRepresentation {\n protected histogramsData: HistogramData[]\n\n protected histogramBinBorderVisible: boolean\n protected histogramBinBorderWidth: number\n protected histogramBinBorderColor: ColorDefinition\n protected histogramBinBorderOpacity: number\n\n protected bondArrowVisible: boolean\n protected bondArrowWidth: number\n protected bondArrowOpacity: number\n\n protected adjacentBondArrowColor: ColorDefinition\n protected distantBondArrowColor: ColorDefinition\n\n protected histogramOpacity: number\n protected frontHistogramColor: ColorDefinition\n protected backHistogramColor: ColorDefinition\n\n protected opaqueMiddleDiscVisible: boolean\n protected opaqueMiddleDiscColor: ColorDefinition\n protected opaqueMiddleDiscOpacity: number\n\n protected scaleBinToSectorArea: boolean\n\n constructor(structure: Structure, viewer: Viewer, params: DihedralHistogramRepresentationParameters) {\n super(structure, viewer, params)\n\n this.type = 'dihedral-histogram'\n\n this.parameters = Object.assign({\n histogramsData: {\n type: 'hidden', rebuild: true\n },\n histogramBinBorderVisible: {\n type: 'boolean', default: true\n },\n scaleBinToSectorArea: {\n type: 'boolean',\n rebuild: true,\n default: false\n }\n }, this.parameters)\n\n this.init(params)\n }\n\n init(params: Partial) {\n const p = params || {}\n\n const defaultColorData = {\n histogramBinBorderColor: 'grey',\n adjacentBondArrowColor: 'black',\n distantBondArrowColor: 'magenta',\n frontHistogramColor: 'green',\n backHistogramColor: 'blue',\n opaqueMiddleDiscColor: 'white'\n }\n\n const colorData = createUpdatedObject(defaultColorData, p)\n Object.assign(this, colorData)\n\n const defaultParameters = {\n histogramsData: [],\n histogramOpacity: 1.0,\n\n opaqueMiddleDiscVisible: true,\n opaqueMiddleDiscOpacity: 1.0,\n\n histogramBinBorderVisible: true,\n histogramBinBorderWidth: 1,\n histogramBinBorderOpacity: 0.5,\n\n bondArrowVisible: true,\n bondArrowWidth: 2,\n bondArrowOpacity: 1.0,\n\n scaleBinToSectorArea: false,\n }\n const parameters = createUpdatedObject(defaultParameters, p)\n Object.assign(this, parameters)\n\n this.histogramsData.forEach(x => {\n const specificColorData = createUpdatedObject(colorData, x)\n Object.assign(x, specificColorData)\n })\n\n p.side = defaults(p.side, 'double')\n p.opacity = defaults(p.opacity, 0.5)\n p.radiusType = defaults(p.radiusType, 'size')\n p.radiusSize = defaults(p.radiusSize, 0.15)\n\n super.init(p)\n }\n\n getHistogramBinBorderBufferParameters() {\n return this.getBufferParams({\n linewidth: this.histogramBinBorderWidth,\n visible: this.histogramBinBorderVisible,\n opacity: this.histogramBinBorderOpacity,\n })\n }\n\n getBondArrowsBufferParameters() {\n return this.getBufferParams({\n linewidth: this.bondArrowWidth,\n visible: this.bondArrowVisible,\n opacity: this.bondArrowOpacity,\n })\n }\n\n getOpaqueMiddleDiscBufferParameters() {\n return this.getBufferParams({\n visible: this.opaqueMiddleDiscVisible,\n opacity: this.opaqueMiddleDiscOpacity\n })\n }\n\n getHistogramBufferParameters() {\n return this.getBufferParams({\n visible: true,\n opacity: this.histogramOpacity,\n side: \"double\"\n })\n }\n\n createData(sview: StructureView) {\n if (!sview.atomCount || !this.histogramsData.length) return\n this.histogramsData.forEach(x => x.atomPositions = parseNestedAtoms(sview, [x.atomQuad]))\n const scaleData = this.scaleBinToSectorArea ? function (y: number) { return Math.sqrt(y) } : function (y: number) { return y }\n this.histogramsData.forEach(x => x.histogram360Scaled = x.histogram360.map(scaleData))\n function Float32Concat(arrays: Float32Array[]) {\n const lengths = arrays.map(x => x.length)\n const result = new Float32Array(arraySum(lengths))\n let accumulatedOffset = 0\n for (let i = 0; i < arrays.length; i++) {\n result.set(arrays[i], accumulatedOffset)\n accumulatedOffset += arrays[i].length\n }\n return result\n }\n\n function createWideLineBuffer(linesList: WideLineData[], params: {}) {\n return new WideLineBuffer(\n {\n position1: Float32Concat(linesList.map(x => x.startPoints)),\n position2: Float32Concat(linesList.map(x => x.endPoints)),\n color: Float32Concat(linesList.map(x => x.startColors)),\n color2: Float32Concat(linesList.map(x => x.endColors)),\n } as WideLineBufferData,\n params)\n }\n\n function createMeshBuffer(mesh: MeshData[], params: {}) {\n return new MeshBuffer(\n {\n position: Float32Concat(mesh.map(x => x.triangles)),\n color: Float32Concat(mesh.map(x => x.triangleColors))\n } as BufferData,\n params)\n }\n\n const dihedralDataArray = []\n\n for (let i = 0; i < this.histogramsData.length; i++) {\n let dihedralData = undefined\n let currentHistogramData = this.histogramsData[i]\n let currentHistogram360 = currentHistogramData.histogram360\n if (currentHistogram360.length >= 3) {\n dihedralData = calculateDihedralHistogram(currentHistogramData)\n }\n if (typeof dihedralData === \"undefined\") continue\n dihedralDataArray.push(dihedralData)\n }\n\n this.frontHistogramBinBordersBuffer = createWideLineBuffer(\n dihedralDataArray.map(x => x.frontHistogramBinBorders),\n this.getHistogramBinBorderBufferParameters()\n )\n\n this.backHistogramBinBordersBuffer = createWideLineBuffer(\n dihedralDataArray.map(x => x.backHistogramBinBorders),\n this.getHistogramBinBorderBufferParameters()\n )\n\n this.adjacentBondArrowsBuffer = createWideLineBuffer(\n dihedralDataArray.map(x => x.adjacentBondArrows),\n this.getBondArrowsBufferParameters()\n )\n\n this.distantBondArrowsBuffer = createWideLineBuffer(\n dihedralDataArray.map(x => x.distantBondArrows),\n this.getBondArrowsBufferParameters()\n )\n\n this.opaqueMiddleDiscBuffer = createMeshBuffer(\n dihedralDataArray.map(x => x.opaqueMiddleDisc),\n this.getOpaqueMiddleDiscBufferParameters()\n )\n\n this.frontHistogramBuffer = createMeshBuffer(\n dihedralDataArray.map(x => x.frontHistogram),\n this.getHistogramBufferParameters()\n )\n\n this.backHistogramBuffer = createMeshBuffer(\n dihedralDataArray.map(x => x.backHistogram),\n this.getHistogramBufferParameters()\n )\n\n return {\n bufferList: [].concat(\n this.frontHistogramBinBordersBuffer,\n this.backHistogramBinBordersBuffer,\n this.adjacentBondArrowsBuffer,\n this.distantBondArrowsBuffer,\n this.opaqueMiddleDiscBuffer,\n this.frontHistogramBuffer,\n this.backHistogramBuffer\n )\n }\n }\n\n setParameters(params: Partial) {\n const rebuild = false\n const what = {}\n super.setParameters(params, what, rebuild)\n\n if (params && (params.histogramBinBorderVisible !== undefined)) {\n this.setVisibility(this.visible)\n }\n return this\n }\n\n setVisibility(value: boolean, noRenderRequest?: boolean) {\n super.setVisibility(value, true)\n if (this.frontHistogramBinBordersBuffer) {\n this.frontHistogramBinBordersBuffer.setVisibility(this.histogramBinBorderVisible)\n }\n if (this.backHistogramBinBordersBuffer) {\n this.backHistogramBinBordersBuffer.setVisibility(this.histogramBinBorderVisible)\n }\n if (!noRenderRequest) this.viewer.requestRender()\n return this\n }\n}\n\n/**\n * Calculates the data required to create {Buffer} objects for one histogram, given positions\n * @param Float32Array positionOfDihedralAtoms 3*4 array of coordinates\n * @param NumberArray histogram array of coordinates\n * @return Arrays for building buffers\n */\nfunction calculateDihedralHistogram(histogramData: HistogramData) {\n const positionOfDihedralAtoms = histogramData.atomPositions\n const histogram = histogramData.histogram360Scaled;\n const totalSectorTrianglesInOpaqueMiddleDisc = histogram.length <= 180 ? 360 : histogram.length * 2\n const frontAndBack = 2\n\n const opaqueMiddleDisc = {\n triangles: new Float32Array(totalSectorTrianglesInOpaqueMiddleDisc * pointsInTriangle * pointLength),\n triangleColors: createColorArray(histogramData.opaqueMiddleDiscColor, totalSectorTrianglesInOpaqueMiddleDisc * pointsInTriangle)\n }\n\n const frontHistogram = {\n triangles: new Float32Array(histogram.length * pointsInTriangle * pointLength),\n triangleColors: createColorArray(histogramData.frontHistogramColor, histogram.length * pointsInTriangle)\n }\n\n const backHistogram = {\n triangles: new Float32Array(histogram.length * pointsInTriangle * pointLength),\n triangleColors: createColorArray(histogramData.backHistogramColor, histogram.length * pointsInTriangle)\n }\n\n const frontHistogramBinBorders = {\n startPoints: new Float32Array(histogram.length * pointLength),\n endPoints: new Float32Array(histogram.length * pointLength),\n startColors: createColorArray(histogramData.histogramBinBorderColor, histogram.length),\n endColors: createColorArray(histogramData.histogramBinBorderColor, histogram.length)\n }\n\n const backHistogramBinBorders = {\n startPoints: new Float32Array(histogram.length * pointLength),\n endPoints: new Float32Array(histogram.length * pointLength),\n startColors: createColorArray(histogramData.histogramBinBorderColor, histogram.length),\n endColors: createColorArray(histogramData.histogramBinBorderColor, histogram.length)\n }\n\n const adjacentBondArrows = {\n startPoints: new Float32Array(frontAndBack * pointLength),\n endPoints: new Float32Array(frontAndBack * pointLength),\n startColors: createColorArray(histogramData.adjacentBondArrowColor, histogram.length),\n endColors: createColorArray(histogramData.adjacentBondArrowColor, histogram.length)\n }\n const distantBondArrows = {\n startPoints: new Float32Array(frontAndBack * pointLength),\n endPoints: new Float32Array(frontAndBack * pointLength),\n startColors: createColorArray(histogramData.distantBondArrowColor, histogram.length),\n endColors: createColorArray(histogramData.distantBondArrowColor, histogram.length)\n }\n\n const p1 = v3new()\n const p2 = v3new()\n const p3 = v3new()\n const p4 = v3new()\n\n const v21 = v3new()\n const v23 = v3new()\n const v32 = v3new()\n const v34 = v3new()\n\n const mid = v3new()\n const inPlane1 = v3new()\n const inPlane2 = v3new()\n\n const cross1 = v3new()\n const cross2 = v3new()\n\n const arcPoint = v3new()\n const tmp = v3new()\n const tmp2 = v3new()\n\n // Set Atom Coordinates\n const dihedralAtomVectors = [p1, p2, p3, p4]\n\n for (let i = 0; i < dihedralAtomVectors.length; i++) {\n v3fromArray(dihedralAtomVectors[i], positionOfDihedralAtoms, i * pointLength)\n }\n\n // Vectors between points\n v3sub(v21, p1, p2)\n v3sub(v23, p3, p2)\n v3sub(v34, p4, p3)\n if (v3length(v23) === 0.0) {\n return // Can't define axis\n }\n\n v3multiplyScalar(tmp, v23, 0.5)\n v3add(mid, p2, tmp)\n\n v3normalize(v21, v21)\n v3normalize(v23, v23)\n v3normalize(v34, v34)\n\n v3negate(v32, v23)\n // Calculate vectors perp to v23 (lying in plane (1,2,3) and (2,3,4))\n v3multiplyScalar(tmp, v32, v3dot(v32, v21))\n v3sub(inPlane1, v21, tmp)\n\n v3multiplyScalar(tmp, v23, v3dot(v23, v34))\n v3sub(inPlane2, v34, tmp)\n\n if (v3length(inPlane1) === 0.0 || v3length(inPlane2) === 0.0) {\n return // Indeterminate angle\n }\n\n v3normalize(inPlane1, inPlane1)\n v3normalize(inPlane2, inPlane2)\n\n // Can use acos as normalized and non-zero\n const absAngle = Math.acos(v3dot(inPlane1, inPlane2))\n\n v3cross(cross1, v32, inPlane1)\n v3cross(cross2, v23, inPlane2)\n v3normalize(cross1, cross1)\n v3normalize(cross2, cross2)\n\n let angle = absAngle\n if (v3dot(cross1, inPlane2) < 0.0) {\n angle = -absAngle\n }\n\n v3add(arcPoint, mid, inPlane1)\n\n // Calculate necessary constants\n const maxHist = Math.max.apply(null, histogram)\n const histBinAngleStep = (Math.PI * 2) / histogram.length\n\n function setHistogramBinCoordinates(out: Float32Array, ind: number, zeroDegreeVector: Float32Array, crossVector: Float32Array, histBinAngleStep: number) {\n const startOffset = ind * pointsInTriangle * pointLength\n v3toArray(mid, out, startOffset)\n const scalingFactor = Number(histogram[ind]) / maxHist\n v3multiplyScalar(tmp, zeroDegreeVector, scalingFactor)\n v3multiplyScalar(tmp2, crossVector, scalingFactor)\n calcArcPoint(arcPoint, mid, tmp, tmp2, ind * histBinAngleStep)\n v3toArray(arcPoint, out, startOffset + 1 * pointLength)\n calcArcPoint(arcPoint, mid, tmp, tmp2, (ind + 1) * histBinAngleStep)\n v3toArray(arcPoint, out, startOffset + 2 * pointLength)\n }\n\n function setOneSideHistogram(discHistogram: MeshData, binBorders: { startPoints: Float32Array, endPoints: Float32Array }, ind: number, zeroDegreeVector: Float32Array, crossVector: Float32Array) {\n // Set Bond Arrows\n\n copyArray(mid, adjacentBondArrows.startPoints, 0, ind * pointLength, mid.length)\n calcArcPoint(tmp, mid, zeroDegreeVector, crossVector, 0 + histBinAngleStep * 0)\n copyArray(tmp, adjacentBondArrows.endPoints, 0, ind * pointLength, mid.length)\n\n copyArray(mid, distantBondArrows.startPoints, 0, ind * pointLength, mid.length)\n calcArcPoint(tmp, mid, zeroDegreeVector, crossVector, angle)\n copyArray(tmp, distantBondArrows.endPoints, 0, ind * pointLength, mid.length)\n\n // Set Histogram Bin Borders\n\n for (let i = 0; i < histogram.length; i++) {\n copyArray(mid, binBorders.startPoints, 0, i * 3, mid.length)\n calcArcPoint(tmp, mid, zeroDegreeVector, crossVector, 0 + histBinAngleStep * i)\n copyArray(tmp, binBorders.endPoints, 0, i * 3, tmp.length)\n }\n\n // Set Histogram Bins\n\n for (let sectionIndex = 0; sectionIndex < histogram.length; sectionIndex++) {\n setHistogramBinCoordinates(discHistogram.triangles, sectionIndex, zeroDegreeVector, crossVector, histBinAngleStep)\n }\n }\n\n // Opaque disc\n const opaqueCircleSectorAngleStep = Math.PI * 2 / totalSectorTrianglesInOpaqueMiddleDisc\n\n for (let sectionIndex = 0; sectionIndex < totalSectorTrianglesInOpaqueMiddleDisc; sectionIndex++) {\n const startOffset = sectionIndex * pointsInTriangle * pointLength\n v3toArray(mid, opaqueMiddleDisc.triangles, startOffset)\n calcArcPoint(arcPoint, mid, inPlane1, cross1, sectionIndex * opaqueCircleSectorAngleStep)\n v3toArray(arcPoint, opaqueMiddleDisc.triangles, startOffset + 1 * pointLength)\n calcArcPoint(arcPoint, mid, inPlane1, cross1, (sectionIndex + 1) * opaqueCircleSectorAngleStep)\n v3toArray(arcPoint, opaqueMiddleDisc.triangles, startOffset + 2 * pointLength)\n }\n\n // Front Histogram\n const distanceToOpaqueDisc = 0.01\n v3multiplyScalar(tmp, v23, -distanceToOpaqueDisc) // Get a vector to move \"mid\" just a bit from opaque disc\n v3add(mid, mid, tmp)\n setOneSideHistogram(frontHistogram, frontHistogramBinBorders, 0, inPlane1, cross1)\n\n // Back Histogram\n v3multiplyScalar(tmp, v23, 2 * distanceToOpaqueDisc) // Get a vector to move \"mid\" back and plus just a bit from opaque disc the other way\n v3add(mid, mid, tmp)\n setOneSideHistogram(backHistogram, backHistogramBinBorders, 1, inPlane2, cross2)\n\n return {\n opaqueMiddleDisc,\n frontHistogram,\n backHistogram,\n frontHistogramBinBorders,\n backHistogramBinBorders,\n adjacentBondArrows,\n distantBondArrows\n }\n}\n\nRepresentationRegistry.add('dihedral-histogram', DihedralHistogramRepresentation)\n\nexport default DihedralHistogramRepresentation\n","/**\n * @file Distance Representation\n * @author Alexander Rose \n * @author Fred Ludlow \n * @private\n */\n\nimport { Color } from 'three'\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport { DistancePicker } from '../utils/picker'\nimport { uniformArray, uniformArray3 } from '../math/array-utils'\nimport BitArray from '../utils/bitarray'\nimport MeasurementRepresentation, { MeasurementRepresentationParameters } from './measurement-representation'\nimport Selection from '../selection/selection'\nimport BondStore from '../store/bond-store'\nimport TextBuffer, { TextBufferData, TextBufferParameters } from '../buffer/text-buffer'\nimport WideLineBuffer from '../buffer/wideline-buffer'\nimport CylinderBuffer, { CylinderBufferData } from '../buffer/cylinder-buffer'\nimport { getFixedLengthDashData } from '../geometry/dash'\nimport Viewer from '../viewer/viewer';\nimport { Structure } from '../ngl';\nimport StructureView from '../structure/structure-view';\nimport { BondDataFields, BondDataParams, BondData } from '../structure/structure-data';\nimport { StructureRepresentationData } from './structure-representation';\nimport CylinderGeometryBuffer from '../buffer/cylindergeometry-buffer';\n\n/**\n * Distance representation parameter object.\n * @typedef {Object} DistanceRepresentationParameters - distance representation parameters\n * @mixes RepresentationParameters\n * @mixes StructureRepresentationParameters\n * @mixes MeasurementRepresentationParameters\n *\n * @property {String} labelUnit - distance unit (e.g. \"angstrom\" or \"nm\"). If set, a distance\n * symbol is appended to the label (i.e. 'nm' or '\\u00C5'). In case of 'nm', the\n * distance value is computed in nanometers instead of Angstroms.\n * @property {Array[]} atomPair - list of pairs of selection strings (see {@link Selection})\n * or pairs of atom indices. Using atom indices is much more\n * efficient when the representation is updated often, e.g. by\n * changing the selection or the atom positions, as there\n * are no selection strings to be evaluated.\n */\nexport interface DistanceRepresentationParameters extends MeasurementRepresentationParameters {\n labelUnit: string\n atomPair: AtomPair\n useCylinder: boolean\n}\nexport type AtomPair = (number|string)[][]\n/**\n * Distance representation\n */\nclass DistanceRepresentation extends MeasurementRepresentation {\n protected labelUnit: string\n protected atomPair: AtomPair\n protected useCylinder: boolean\n protected distanceBuffer: WideLineBuffer|CylinderGeometryBuffer\n /**\n * Create Distance representation object\n * @example\n * stage.loadFile( \"rcsb://1crn\" ).then( function( o ){\n * o.addRepresentation( \"cartoon\" );\n * // either give selections (uses first selected atom) ...\n * var atomPair = [ [ \"1.CA\", \"4.CA\" ], [ \"7.CA\", \"13.CA\" ] ];\n * // or atom indices\n * var atomPair = [ [ 8, 28 ], [ 173, 121 ] ];\n * o.addRepresentation( \"distance\", { atomPair: atomPair } );\n * stage.autoView();\n * } );\n * @param {Structure} structure - the structure to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {DistanceRepresentationParameters} params - distance representation parameters\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'distance'\n\n this.parameters = Object.assign({\n radialSegments: true,\n openEnded: true,\n disableImpostor: true,\n labelUnit: {\n type: 'select',\n rebuild: true,\n options: { '': '', angstrom: 'angstrom', nm: 'nm' }\n },\n useCylinder: {\n type: 'boolean', rebuild: true\n },\n atomPair: {\n type: 'hidden', rebuild: true\n }\n }, this.parameters)\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n p.linewidth = defaults(p.linewidth, 5.0)\n p.radiusType = defaults(p.radiusType, 'size')\n p.radiusSize = defaults(p.radiusSize, 0.2)\n\n this.labelUnit = defaults(p.labelUnit, '')\n this.useCylinder = defaults(p.useCylinder, false)\n this.atomPair = defaults(p.atomPair, [])\n\n super.init(p)\n }\n\n getDistanceData (sview: StructureView, atomPair: AtomPair) {\n let n = atomPair.length\n const text = new Array(n)\n let position = new Float32Array(n * 3)\n const sele1 = new Selection()\n const sele2 = new Selection()\n\n const bondStore = new BondStore()\n\n const ap1 = sview.getAtomProxy()\n const ap2 = sview.getAtomProxy()\n\n let j = 0 // Skipped pairs\n const selected = sview.getAtomSet()\n\n atomPair.forEach((pair, i) => {\n let v1 = pair[ 0 ]\n let v2 = pair[ 1 ]\n\n if (typeof(v1) === 'number' && Number.isInteger(v1) && typeof(v2) === 'number' && Number.isInteger(v2)) {\n if (selected.get(v1) && selected.get(v2)) {\n ap1.index = v1\n ap2.index = v2\n } else {\n j += 1\n return\n }\n } else {\n sele1.setString(v1 as string)\n sele2.setString(v2 as string)\n\n var atomIndices1 = sview.getAtomIndices(sele1)\n var atomIndices2 = sview.getAtomIndices(sele2)\n\n if (atomIndices1!.length && atomIndices2!.length) {\n ap1.index = atomIndices1![ 0 ]\n ap2.index = atomIndices2![ 0 ]\n } else {\n j += 1\n return\n }\n }\n\n bondStore.addBond(ap1, ap2, 1)\n\n i -= j\n var d = ap1.distanceTo(ap2)\n switch (this.labelUnit) {\n case 'angstrom':\n text[ i ] = d.toFixed(2) + ' ' + String.fromCharCode(0x212B)\n break\n case 'nm':\n text[ i ] = (d / 10).toFixed(2) + ' nm'\n break\n default:\n text[ i ] = d.toFixed(2)\n break\n }\n\n var i3 = i * 3\n position[ i3 + 0 ] = (ap1.x + ap2.x) / 2\n position[ i3 + 1 ] = (ap1.y + ap2.y) / 2\n position[ i3 + 2 ] = (ap1.z + ap2.z) / 2\n })\n\n if (j > 0) {\n n -= j\n position = position.subarray(0, n * 3)\n }\n\n var bondSet = new BitArray(bondStore.count, true)\n\n return {\n text: text,\n position: position,\n bondSet: bondSet,\n bondStore: bondStore\n }\n }\n\n getBondData (sview: StructureView, what: BondDataFields, params: BondDataParams): BondData {\n const bondData = sview.getBondData(this.getBondParams(what, params))\n if (bondData.picking) {\n bondData.picking = new DistancePicker(\n bondData.picking.array,\n bondData.picking.structure,\n params.bondStore!\n ) as any\n }\n return bondData\n }\n\n createData (sview: StructureView) {\n if (!sview.atomCount || !this.atomPair.length) return\n\n const n = this.atomPair.length\n const c = new Color(this.labelColor)\n const distanceData = this.getDistanceData(sview, this.atomPair)\n\n this.textBuffer = new TextBuffer({\n position: distanceData.position,\n size: uniformArray(n, this.labelSize),\n color: uniformArray3(n, c.r, c.g, c.b),\n text: distanceData.text\n } as TextBufferData, this.getLabelBufferParams() as TextBufferParameters)\n\n const bondParams = {\n bondSet: distanceData.bondSet,\n bondStore: distanceData.bondStore\n }\n\n const bondData = this.getBondData(\n sview,\n { position: true, color: true, picking: true, radius: this.useCylinder },\n bondParams\n )\n\n if (this.useCylinder) {\n this.distanceBuffer = new CylinderBuffer(\n bondData as CylinderBufferData,\n this.getBufferParams({\n openEnded: this.openEnded,\n radialSegments: this.radialSegments,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n }) \n ) as CylinderGeometryBuffer\n } else {\n this.distanceBuffer = new WideLineBuffer(\n getFixedLengthDashData(bondData as CylinderBufferData),\n this.getBufferParams({\n linewidth: this.linewidth,\n visible: this.lineVisible,\n opacity: this.lineOpacity\n })\n )\n }\n\n return {\n bondSet: distanceData.bondSet,\n bondStore: distanceData.bondStore,\n position: distanceData.position,\n bufferList: [ this.textBuffer, this.distanceBuffer ]\n }\n }\n\n updateData (what: BondDataFields, data: StructureRepresentationData) {\n super.updateData(what, data)\n\n const bondParams = {\n bondSet: data.bondSet,\n bondStore: data.bondStore\n }\n\n const bondData = this.getBondData(data.sview as StructureView, what, bondParams)\n const distanceData = {}\n\n if (!what || what.color) {\n Object.assign( distanceData, {\n color: bondData.color,\n color2: bondData.color2\n })\n }\n\n if (!what || what.radius) {\n Object.assign( distanceData, {radius: bondData.radius})\n }\n\n (this.distanceBuffer as CylinderGeometryBuffer).setAttributes(distanceData)\n }\n\n setParameters (params: Partial) {\n let rebuild = false\n const what = {}\n\n super.setParameters(params, what, rebuild)\n\n if (!this.useCylinder) {\n if (params && params.lineOpacity) {\n (this.distanceBuffer as WideLineBuffer).setParameters({ opacity: params.lineOpacity })\n }\n if (params && params.opacity !== undefined) {\n (this.distanceBuffer as WideLineBuffer).setParameters({ opacity: this.lineOpacity })\n }\n if (params && params.linewidth) {\n (this.distanceBuffer as WideLineBuffer).setParameters({ linewidth: params.linewidth })\n }\n }\n\n return this\n }\n}\n\nRepresentationRegistry.add('distance', DistanceRepresentation)\n\nexport default DistanceRepresentation\n","/**\n * @file Vector Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Vector3, Matrix4 required for declaration only\nimport { Color, Matrix4, Vector3 } from 'three'\n\nimport '../shader/Line.vert'\nimport '../shader/Line.frag'\n\nimport { uniformArray3 } from '../math/array-utils'\nimport Buffer, { BufferDefaultParameters, BufferData, BufferParameters } from './buffer'\nimport { GenericColor } from '../types'\n\nfunction getSize(data: BufferData){\n const n = data.position!.length / 3\n return n * 2 * 3\n}\n\nexport interface VectorBufferData extends BufferData {\n vector: Float32Array\n}\n\nexport const VectorBufferDefaultParameters = Object.assign({\n scale: 1,\n color: 'grey'\n}, BufferDefaultParameters)\nexport type VectorBufferParameters = BufferParameters & { scale: number, color: GenericColor }\n\n/**\n * Vector buffer. Draws vectors as lines.\n */\nclass VectorBuffer extends Buffer {\n get defaultParameters() { return VectorBufferDefaultParameters }\n parameters: VectorBufferParameters\n\n isLine = true\n vertexShader = 'Line.vert'\n fragmentShader = 'Line.frag'\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.vector - vectors\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: VectorBufferData, params: Partial = {}) {\n super({\n position: new Float32Array(getSize(data)),\n color: new Float32Array(getSize(data))\n }, params)\n\n const color = new Color(this.parameters.color)\n const attributes = this.geometry.attributes as any // TODO\n uniformArray3(getSize(data) / 3, color.r, color.g, color.b, attributes.color.array)\n\n this.setAttributes(data)\n }\n\n setAttributes (data: Partial = {}) {\n const attributes = this.geometry.attributes as any // TODO\n\n let position, vector\n let aPosition\n\n if (data.position && data.vector) {\n position = data.position\n vector = data.vector\n aPosition = attributes.position.array\n attributes.position.needsUpdate = true\n }\n\n const n = this.size / 2\n const scale = this.parameters.scale\n\n if (position && vector) {\n for (let v = 0; v < n; v++) {\n const i = v * 2 * 3\n const j = v * 3\n\n aPosition[ i + 0 ] = position[ j + 0 ]\n aPosition[ i + 1 ] = position[ j + 1 ]\n aPosition[ i + 2 ] = position[ j + 2 ]\n aPosition[ i + 3 ] = position[ j + 0 ] + vector[ j + 0 ] * scale\n aPosition[ i + 4 ] = position[ j + 1 ] + vector[ j + 1 ] * scale\n aPosition[ i + 5 ] = position[ j + 2 ] + vector[ j + 2 ] * scale\n }\n }\n }\n}\n\nexport default VectorBuffer\n","/**\n * @file Helixorient Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport Helixorient from '../geometry/helixorient'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport SphereBuffer, { SphereBufferParameters } from '../buffer/sphere-buffer'\nimport VectorBuffer from '../buffer/vector-buffer'\nimport Viewer from '../viewer/viewer';\nimport { Structure } from '../ngl';\nimport StructureView from '../structure/structure-view';\nimport Polymer from '../proxy/polymer';\nimport { AtomDataFields } from '../structure/structure-data';\nimport SphereGeometryBuffer from '../buffer/spheregeometry-buffer';\nimport SphereImpostorBuffer from '../buffer/sphereimpostor-buffer';\nimport { BufferData } from '../buffer/buffer';\n\n/**\n * Helixorient Representation\n */\nclass HelixorientRepresentation extends StructureRepresentation {\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'helixorient'\n\n this.parameters = Object.assign({\n sphereDetail: true,\n disableImpostor: true\n }, this.parameters)\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n p.colorScheme = defaults(p.colorScheme, 'sstruc')\n p.radiusType = defaults(p.radiusType, 'size')\n p.radiusSize = defaults(p.radiusSize, 0.15)\n p.radiusScale = defaults(p.radiusScale, 1.0)\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n super.init(p)\n }\n\n createData (sview: StructureView) {\n const bufferList: (SphereBuffer|VectorBuffer)[] = []\n const polymerList: Polymer[] = []\n\n this.structure.eachPolymer(polymer => {\n if (polymer.residueCount < 4) return\n polymerList.push(polymer)\n\n const helixorient = new Helixorient(polymer)\n const position = helixorient.getPosition()\n const color = helixorient.getColor(this.getColorParams())\n const size = helixorient.getSize(this.getRadiusParams())\n const picking = helixorient.getPicking()\n\n bufferList.push(\n new SphereBuffer(\n {\n position: position.center,\n color: color.color,\n radius: size.size,\n picking: picking.picking\n },\n this.getBufferParams({\n sphereDetail: this.sphereDetail,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n }) as SphereBufferParameters\n ),\n new VectorBuffer(\n {\n position: position.center,\n vector: position.axis\n },\n this.getBufferParams({\n color: 'skyblue',\n scale: 1\n })\n ),\n new VectorBuffer(\n {\n position: position.center,\n vector: position.resdir\n },\n this.getBufferParams({\n color: 'lightgreen',\n scale: 1\n })\n )\n )\n }, sview.getSelection())\n\n return {\n bufferList: bufferList as (SphereGeometryBuffer|SphereImpostorBuffer|VectorBuffer)[],\n polymerList: polymerList\n }\n }\n\n updateData (what: AtomDataFields, data: StructureRepresentationData) {\n if (Debug) Log.time(this.type + ' repr update')\n\n what = what || {}\n\n for (let i = 0, il = data.polymerList!.length; i < il; ++i) {\n const j = i * 3\n\n const bufferData: Partial = {}\n const polymer = data.polymerList![ i ]\n const helixorient = new Helixorient(polymer)\n\n if (what.position) {\n const position = helixorient.getPosition()\n\n Object.assign(bufferData, {position: position.center})\n\n data.bufferList[ j + 1 ].setAttributes({\n 'position': position.center,\n 'vector': position.axis\n })\n data.bufferList[ j + 2 ].setAttributes({\n 'position': position.center,\n 'vector': position.resdir\n })\n }\n\n data.bufferList[ j ].setAttributes(bufferData)\n }\n\n if (Debug) Log.timeEnd(this.type + ' repr update')\n }\n}\n\nRepresentationRegistry.add('helixorient', HelixorientRepresentation)\n\nexport default HelixorientRepresentation\n","/**\n * @file Licorice Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport BallAndStickRepresentation, { BallAndStickRepresentationParameters } from './ballandstick-representation'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\n\n/**\n * Licorice representation object ({@link BallAndStickRepresentation} with `aspectRatio` fixed at 1.0)\n */\nclass LicoriceRepresentation extends BallAndStickRepresentation {\n /**\n * Create Licorice representation object\n * @param {Structure} structure - the structure to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {BallAndStickRepresentationParameters} params - ball and stick representation parameters\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'licorice'\n\n this.parameters = Object.assign(\n {}, this.parameters, { aspectRatio: null }\n )\n }\n\n init (params: Partial) {\n var p = params || {}\n p.aspectRatio = 1.0\n\n super.init(p)\n }\n}\n\nRepresentationRegistry.add('licorice', LicoriceRepresentation)\n\nexport default LicoriceRepresentation\n","/**\n * @file Mapped Box Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { BufferParameters, BufferData } from './buffer'\nimport MappedBuffer from './mapped-buffer'\n\nconst mapping = new Float32Array([\n -1.0, -1.0, -1.0,\n 1.0, -1.0, -1.0,\n 1.0, -1.0, 1.0,\n -1.0, -1.0, 1.0,\n -1.0, 1.0, -1.0,\n 1.0, 1.0, -1.0,\n 1.0, 1.0, 1.0,\n -1.0, 1.0, 1.0\n])\n\nconst mappingIndices = new Uint16Array([\n 0, 1, 2,\n 0, 2, 3,\n 1, 5, 6,\n 1, 6, 2,\n 4, 6, 5,\n 4, 7, 6,\n 0, 7, 4,\n 0, 3, 7,\n 0, 5, 1,\n 0, 4, 5,\n 3, 2, 6,\n 3, 6, 7\n])\n\n/**\n * Mapped Box buffer. Draws boxes. Used to render general imposters.\n * @interface\n */\nclass MappedBoxBuffer extends MappedBuffer {\n constructor(data: BufferData, params: Partial = {}) {\n super('v3', data, params)\n }\n get mapping () { return mapping }\n get mappingIndices () { return mappingIndices }\n get mappingIndicesSize () { return 36 }\n get mappingSize () { return 8 }\n get mappingItemSize () { return 3 }\n}\n\nexport default MappedBoxBuffer\n","/**\n * @file Hyperball Stick Impostor Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Vector3 required for declaration only\nimport { Matrix4, Vector3 } from 'three'\n\nimport '../shader/HyperballStickImpostor.vert'\nimport '../shader/HyperballStickImpostor.frag'\n\nimport MappedBoxBuffer from './mappedbox-buffer'\nimport { BufferDefaultParameters, BufferParameterTypes, BufferData, BufferParameters } from './buffer'\n\nexport interface HyperballStickImpostorBufferData extends BufferData {\n position1: Float32Array\n position2: Float32Array\n color2: Float32Array\n radius: Float32Array\n radius2: Float32Array\n}\n\nexport const HyperballStickImpostorBufferDefaultParameters = Object.assign({\n shrink: 0.14\n}, BufferDefaultParameters)\nexport type HyperballStickImpostorBufferParameters = BufferParameters & { shrink: number }\n\nconst HyperballStickImpostorBufferParameterTypes = Object.assign({\n shrink: { uniform: true }\n}, BufferParameterTypes)\n\n/**\n * Hyperball stick impostor buffer.\n *\n * @example\n * var hyperballStickImpostorBuffer = new HyperballStickImpostorBuffer({\n * position1: new Float32Array([ 0, 0, 0 ]),\n * position2: new Float32Array([ 2, 2, 2 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * color2: new Float32Array([ 0, 1, 0 ]),\n * radius: new Float32Array([ 1 ]),\n * radius2: new Float32Array([ 2 ])\n * });\n */\nclass HyperballStickImpostorBuffer extends MappedBoxBuffer {\n parameterTypes = HyperballStickImpostorBufferParameterTypes\n get defaultParameters() { return HyperballStickImpostorBufferDefaultParameters }\n parameters: HyperballStickImpostorBufferParameters\n\n isImpostor = true\n vertexShader = 'HyperballStickImpostor.vert'\n fragmentShader = 'HyperballStickImpostor.frag'\n\n constructor (data: HyperballStickImpostorBufferData, params: Partial = {}) {\n super(data, params)\n\n this.addUniforms({\n 'modelViewProjectionMatrix': { value: new Matrix4() },\n 'modelViewProjectionMatrixInverse': { value: new Matrix4() },\n 'modelViewMatrixInverseTranspose': { value: new Matrix4() },\n 'shrink': { value: this.parameters.shrink }\n })\n\n this.addAttributes({\n 'position1': { type: 'v3', value: null },\n 'position2': { type: 'v3', value: null },\n 'color2': { type: 'c', value: null },\n 'radius': { type: 'f', value: null },\n 'radius2': { type: 'f', value: null }\n })\n\n this.setAttributes(data)\n this.makeMapping()\n }\n}\n\nexport default HyperballStickImpostorBuffer\n","/**\n * @file Hyperball Stick Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import required for declaration only\nimport { Vector3, Matrix4 } from 'three'\nimport { ExtensionFragDepth } from '../globals'\nimport { calculateMinArray } from '../math/array-utils'\nimport CylinderGeometryBuffer, { CylinderGeometryBufferDefaultParameters, CylinderGeometryBufferParameters } from './cylindergeometry-buffer'\nimport HyperballStickImpostorBuffer, { HyperballStickImpostorBufferDefaultParameters, HyperballStickImpostorBufferParameters } from './hyperballstickimpostor-buffer'\nimport { BufferData } from './buffer'\n\nexport interface HyperballStickBufferData extends BufferData {\n position1: Float32Array\n position2: Float32Array\n color2: Float32Array\n radius: Float32Array\n radius2: Float32Array\n}\n\nexport const HyperballStickBufferDefaultParameters = Object.assign({\n disableImpostor: false\n}, CylinderGeometryBufferDefaultParameters, HyperballStickImpostorBufferDefaultParameters)\nexport type HyperballStickBufferParameters = HyperballStickImpostorBufferParameters & CylinderGeometryBufferParameters & { disableImpostor: boolean }\n\nclass HyperballStickBufferImpl {\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position1 - from positions\n * @param {Float32Array} data.position2 - to positions\n * @param {Float32Array} data.color - from colors\n * @param {Float32Array} data.color2 - to colors\n * @param {Float32Array} data.radius - from radii\n * @param {Float32Array} data.radius2 - to radii\n * @param {Float32Array} data.picking - picking ids\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: HyperballStickBufferData, params: Partial = {}) {\n if (!ExtensionFragDepth || (params && params.disableImpostor)) {\n data.radius = calculateMinArray(data.radius, data.radius2)\n return new CylinderGeometryBuffer(data, params)\n } else {\n return new HyperballStickImpostorBuffer(data, params)\n }\n }\n}\n\n/**\n * Hyperball stick buffer. Depending on the value {@link ExtensionFragDepth} and\n * `params.disableImpostor` the constructor returns either a\n * {@link CylinderGeometryBuffer} or a {@link HyperballStickImpostorBuffer}\n * @implements {Buffer}\n *\n * @example\n * var hyperballStickBuffer = new HyperballStickBuffer({\n * position1: new Float32Array([ 0, 0, 0 ]),\n * position2: new Float32Array([ 2, 2, 2 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * color2: new Float32Array([ 0, 1, 0 ]),\n * radius: new Float32Array([ 1 ]),\n * radius2: new Float32Array([ 2 ])\n * });\n */\n//@ts-expect-error Incompatible constructor signatures\nconst HyperballStickBuffer: {\n new(data: HyperballStickBufferData, params: Partial): CylinderGeometryBuffer | HyperballStickImpostorBuffer;\n} = HyperballStickBufferImpl;\n\ntype HyperballStickBuffer = CylinderGeometryBuffer | HyperballStickImpostorBuffer;\n\nexport default HyperballStickBuffer\n","/**\n * @file Hyperball Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport { calculateCenterArray } from '../math/array-utils'\nimport LicoriceRepresentation from './licorice-representation'\nimport SphereBuffer, { SphereBufferData, SphereBufferParameters } from '../buffer/sphere-buffer'\nimport HyperballStickBuffer, { HyperballStickBufferData } from '../buffer/hyperballstick-buffer'\nimport { BallAndStickRepresentationParameters } from './ballandstick-representation';\n// @ts-ignore: unused import Volume required for declaration only\nimport { Structure, Volume } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport { BondDataParams, BondDataFields, AtomDataFields } from '../structure/structure-data';\nimport StructureView from '../structure/structure-view';\nimport { StructureRepresentationData } from './structure-representation';\nimport SphereGeometryBuffer from '../buffer/spheregeometry-buffer';\n// @ts-ignore: unused import Surface required for declaration only\nimport Surface from '../surface/surface';\n\nexport interface HyperballRepresentationParameters extends BallAndStickRepresentationParameters {\n shrink: number\n}\n\n/**\n * Hyperball Representation\n */\nclass HyperballRepresentation extends LicoriceRepresentation {\n protected shrink: number\n protected __center: Float32Array\n \n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'hyperball'\n\n this.parameters = Object.assign({\n\n shrink: {\n type: 'number', precision: 3, max: 1.0, min: 0.001, buffer: true\n }\n\n }, this.parameters, {\n\n multipleBond: null,\n bondSpacing: null\n\n })\n }\n\n init (params: Partial) {\n var p = params || {}\n p.radiusScale = defaults(p.radiusScale, 0.2)\n p.radiusType = defaults(p.radiusType, 'vdw')\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n this.shrink = defaults(p.shrink, 0.12)\n\n super.init(p)\n }\n\n getBondParams (what?: BondDataFields, params?: BondDataParams) {\n if (!what || what.radius) {\n params = Object.assign({ radius2: true }, params)\n }\n\n return super.getBondParams(what, params)\n }\n\n createData (sview: StructureView) {\n var sphereBuffer = new SphereBuffer(\n (sview.getAtomData(this.getAtomParams()) as SphereBufferData),\n this.getBufferParams({\n sphereDetail: this.sphereDetail,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n }) as SphereBufferParameters\n ) as SphereGeometryBuffer\n\n this.__center = new Float32Array(sview.bondCount * 3)\n\n var stickBuffer = new HyperballStickBuffer(\n sview.getBondData(this.getBondParams()) as HyperballStickBufferData,\n this.getBufferParams({\n shrink: this.shrink,\n radialSegments: this.radialSegments,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n })\n )\n\n return {\n bufferList: [ sphereBuffer, stickBuffer ]\n }\n }\n\n updateData (what: AtomDataFields, data: StructureRepresentationData) {\n var atomData = data.sview!.getAtomData(this.getAtomParams())\n var bondData = data.sview!.getBondData(this.getBondParams())\n var sphereData = {}\n var stickData = {}\n\n if (!what || what.position) {\n Object.assign(sphereData, {position: atomData.position})\n var from = bondData.position1\n var to = bondData.position2\n Object.assign(stickData, {\n position: calculateCenterArray(from!, to!, this.__center),\n position1: from,\n position2: to\n })\n }\n\n if (!what || what.color) {\n Object.assign(sphereData, {color: atomData.color})\n Object.assign(stickData, {\n color: bondData.color,\n color2: bondData.color2\n })\n }\n\n if (!what || what.radius) {\n Object.assign(sphereData, {radius: atomData.radius})\n Object.assign(stickData, {\n radius: bondData.radius,\n radius2: bondData.radius2\n })\n }\n\n data.bufferList[ 0 ].setAttributes(sphereData)\n data.bufferList[ 1 ].setAttributes(stickData)\n }\n}\n\nRepresentationRegistry.add('hyperball', HyperballRepresentation)\n\nexport default HyperballRepresentation\n","/**\n * @file Label Factory\n * @author Alexander Rose \n * @private\n */\n\nimport { AA1 } from '../structure/structure-constants'\nimport AtomProxy from '../proxy/atom-proxy'\nimport { sprintf } from 'sprintf-js'\n\nexport const LabelFactoryTypes = {\n '': '',\n 'atomname': 'atom name',\n 'atomindex': 'atom index',\n 'occupancy': 'occupancy',\n 'bfactor': 'b-factor',\n 'serial': 'serial',\n 'element': 'element',\n 'atom': 'atom name + index',\n 'resname': 'residue name',\n 'resno': 'residue no',\n 'res': 'one letter code + no',\n 'residue': '[residue name] + no + inscode',\n 'text': 'text',\n 'format': 'format',\n 'qualified': 'qualified name'\n}\nexport type LabelType = keyof typeof LabelFactoryTypes\n\nclass LabelFactory {\n\n static types = LabelFactoryTypes\n errorLogged: boolean = false\n\n constructor(readonly type: LabelType, readonly text: { [k: number]: string } = {},\n readonly format: string = '') {}\n\n atomLabel (a: AtomProxy) {\n const type = this.type\n\n let l\n\n switch (type) {\n case 'atomname':\n l = a.atomname\n break\n\n case 'atomindex':\n l = `${a.index}`\n break\n\n case 'occupancy':\n l = a.occupancy.toFixed(2)\n break\n\n case 'bfactor':\n l = a.bfactor.toFixed(2)\n break\n\n case 'serial':\n l = `${a.serial}`\n break\n\n case 'element':\n l = a.element\n break\n\n case 'atom':\n l = `${a.atomname}|${a.index}`\n break\n\n case 'resname':\n l = a.resname\n break\n\n case 'resno':\n l = `${a.resno}`\n break\n\n case 'res':\n l = `${(AA1[ a.resname.toUpperCase() ] || a.resname)}${a.resno}`\n break\n\n case 'residue':\n const aa1 = AA1[ a.resname.toUpperCase() ]\n if (aa1 && !a.inscode) {\n l = `${aa1}${a.resno}`\n } else {\n l = `[${a.resname}]${a.resno}${a.inscode}`\n }\n break\n\n case 'text':\n l = this.text[ a.index ]\n break\n\n case 'format':\n try {\n l = sprintf(this.format, a)\n } catch (e) {\n if (!this.errorLogged) {\n this.errorLogged = true\n console.log(e.message)\n }\n }\n break\n\n // case \"qualified\":\n default:\n l = a.qualifiedName()\n break\n }\n\n return l === undefined ? '' : l\n }\n}\n\nexport default LabelFactory\n","/**\n * @file Label Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry, ColormakerRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport LabelFactory, { LabelType } from '../utils/label-factory'\nimport RadiusFactory from '../utils/radius-factory'\nimport StructureRepresentation, { StructureRepresentationData } from './structure-representation'\nimport TextBuffer, { TextBufferData } from '../buffer/text-buffer'\nimport { RepresentationParameters } from './representation';\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport StructureView from '../structure/structure-view';\nimport { GenericColor } from '../types'\n\nexport interface TextDataField {\n position?: boolean\n color?: boolean\n radius?: boolean\n text?: boolean\n}\n\n/**\n * Label representation parameter object. Extends {@link RepresentationParameters} and\n * {@link StructureRepresentationParameters}.\n *\n * @typedef {Object} LabelRepresentationParameters - label representation parameters\n *\n * @property {Integer} clipNear - position of camera near/front clipping plane\n * in percent of scene bounding box\n * @property {Float} opacity - translucency: 1 is fully opaque, 0 is fully transparent\n * @property {String} labelType - type of the label, one of:\n * \"atomname\", \"atomindex\", \"occupancy\", \"bfactor\",\n * \"serial\", \"element\", \"atom\", \"resname\", \"resno\",\n * \"res\", \"text\", \"qualified\". When set to \"text\", the\n * `labelText` list is used.\n * @property {String[]} labelText - list of label strings, must set `labelType` to \"text\"\n * to take effect\n * @property {String} labelFormat - sprintf-js format string, any attribute of\n * {@link AtomProxy} can be used\n * @property {String} labelGrouping - grouping of the label, one of:\n * \"atom\", \"residue\".\n * @property {String} fontFamily - font family, one of: \"sans-serif\", \"monospace\", \"serif\"\n * @property {String} fontStyle - font style, \"normal\" or \"italic\"\n * @property {String} fontWeight - font weight, \"normal\" or \"bold\"\n * @property {Float} xOffset - offset in x-direction\n * @property {Float} yOffset - offset in y-direction\n * @property {Float} zOffset - offset in z-direction (i.e. in camera direction)\n * @property {String} attachment - attachment of the label, one of:\n * \"bottom-left\", \"bottom-center\", \"bottom-right\",\n * \"middle-left\", \"middle-center\", \"middle-right\",\n * \"top-left\", \"top-center\", \"top-right\"\n * @property {Boolean} showBorder - show border/outline\n * @property {Color} borderColor - color of the border/outline\n * @property {Float} borderWidth - width of the border/outline\n * @property {Boolean} showBackground - show background rectangle\n * @property {Color} backgroundColor - color of the background\n * @property {Float} backgroundMargin - width of the background\n * @property {Float} backgroundOpacity - opacity of the background\n * @property {Boolean} fixedSize - show text with a fixed pixel size\n */\nexport interface LabelRepresentationParameters extends RepresentationParameters {\n labelType: LabelType\n labelText: string[]\n labelFormat: string\n labelGrouping: 'atom'|'residue'\n fontFamily: 'sans-serif'|'monospace'|'serif'\n fontStyle: 'normal'|'italic'\n fontWeight: 'normal'|'bold'\n xOffset: number\n yOffset: number\n zOffset: number\n attachment: 'bottom-left'|'bottom-center'|'bottom-right'|'middle-left'|'middle-center'|'middle-right'|'top-left'|'top-center'|'top-right'\n showBorder: boolean\n borderColor: GenericColor\n borderWidth: number\n showBackground: boolean\n backgroundColor: GenericColor\n backgroundMargin: number\n backgroundOpacity: number\n fixedSize: boolean\n}\n/**\n * Label representation\n */\nclass LabelRepresentation extends StructureRepresentation {\n\n protected labelType: LabelType\n protected labelText: string[]\n protected labelFormat: string\n protected labelGrouping: 'atom'|'residue'\n protected fontFamily: 'sans-serif'|'monospace'|'serif'\n protected fontStyle: 'normal'|'italic'\n protected fontWeight: 'normal'|'bold'\n protected xOffset: number\n protected yOffset: number\n protected zOffset: number\n protected attachment: 'bottom-left'|'bottom-center'|'bottom-right'|'middle-left'|'middle-center'|'middle-right'|'top-left'|'top-center'|'top-right'\n protected showBorder: boolean\n protected borderColor: GenericColor\n protected borderWidth: number\n protected showBackground: boolean\n protected backgroundColor: GenericColor\n protected backgroundMargin: number\n protected backgroundOpacity: number\n protected fixedSize: boolean\n\n /**\n * Create Label representation object\n * @param {Structure} structure - the structure to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {LabelRepresentationParameters} params - label representation parameters\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'label'\n\n this.parameters = Object.assign({\n\n labelType: {\n type: 'select', options: LabelFactory.types, rebuild: true\n },\n labelText: {\n type: 'hidden', rebuild: true\n },\n labelFormat: {\n type: 'text', rebuild: true\n },\n labelGrouping: {\n type: 'select',\n options: {\n 'atom': 'atom',\n 'residue': 'residue'\n },\n rebuild: true\n },\n fontFamily: {\n type: 'select',\n options: {\n 'sans-serif': 'sans-serif',\n 'monospace': 'monospace',\n 'serif': 'serif'\n },\n buffer: true\n },\n fontStyle: {\n type: 'select',\n options: {\n 'normal': 'normal',\n 'italic': 'italic'\n },\n buffer: true\n },\n fontWeight: {\n type: 'select',\n options: {\n 'normal': 'normal',\n 'bold': 'bold'\n },\n buffer: true\n },\n xOffset: {\n type: 'number', precision: 1, max: 20, min: -20, buffer: true\n },\n yOffset: {\n type: 'number', precision: 1, max: 20, min: -20, buffer: true\n },\n zOffset: {\n type: 'number', precision: 1, max: 20, min: -20, buffer: true\n },\n attachment: {\n type: 'select',\n options: {\n 'bottom-left': 'bottom-left',\n 'bottom-center': 'bottom-center',\n 'bottom-right': 'bottom-right',\n 'middle-left': 'middle-left',\n 'middle-center': 'middle-center',\n 'middle-right': 'middle-right',\n 'top-left': 'top-left',\n 'top-center': 'top-center',\n 'top-right': 'top-right'\n },\n rebuild: true\n },\n showBorder: {\n type: 'boolean', buffer: true\n },\n borderColor: {\n type: 'color', buffer: true\n },\n borderWidth: {\n type: 'number', precision: 2, max: 0.3, min: 0, buffer: true\n },\n showBackground: {\n type: 'boolean', rebuild: true\n },\n backgroundColor: {\n type: 'color', buffer: true\n },\n backgroundMargin: {\n type: 'number', precision: 2, max: 2, min: 0, rebuild: true\n },\n backgroundOpacity: {\n type: 'range', step: 0.01, max: 1, min: 0, buffer: true\n },\n fixedSize: {\n type: 'boolean', buffer: true\n }\n\n }, this.parameters, {\n\n side: null,\n flatShaded: null,\n wireframe: null,\n linewidth: null,\n\n roughness: null,\n metalness: null,\n diffuse: null\n\n })\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n\n this.labelType = defaults(p.labelType, 'res')\n this.labelText = defaults(p.labelText, {})\n this.labelFormat = defaults(p.labelFormat, '')\n this.labelGrouping = defaults(p.labelGrouping, 'atom')\n this.fontFamily = defaults(p.fontFamily, 'sans-serif')\n this.fontStyle = defaults(p.fontStyle, 'normal')\n this.fontWeight = defaults(p.fontWeight, 'bold')\n this.xOffset = defaults(p.xOffset, 0.0)\n this.yOffset = defaults(p.yOffset, 0.0)\n this.zOffset = defaults(p.zOffset, 0.5)\n this.attachment = defaults(p.attachment, 'bottom-left')\n this.showBorder = defaults(p.showBorder, false)\n this.borderColor = defaults(p.borderColor, 'lightgrey')\n this.borderWidth = defaults(p.borderWidth, 0.15)\n this.showBackground = defaults(p.showBackground, false)\n this.backgroundColor = defaults(p.backgroundColor, 'lightgrey')\n this.backgroundMargin = defaults(p.backgroundMargin, 0.5)\n this.backgroundOpacity = defaults(p.backgroundOpacity, 1.0)\n this.fixedSize = defaults(p.fixedSize, false)\n\n super.init(p)\n }\n\n getTextData (sview: StructureView, what?: TextDataField) {\n const p = this.getAtomParams(what)\n const labelFactory = new LabelFactory(this.labelType, this.labelText, this.labelFormat)\n let position: Float32Array, size: Float32Array, color: Float32Array, text: string[],\n positionN: number[], sizeN: number[], colorN: number[]\n if (this.labelGrouping === 'atom') {\n const atomData = sview.getAtomData(p)\n position = atomData.position as Float32Array\n size = atomData.radius as Float32Array\n color = atomData.color as Float32Array\n if (!what || what.text) {\n text = []\n sview.eachAtom(ap => text.push(labelFactory.atomLabel(ap)))\n }\n } else if (this.labelGrouping === 'residue') {\n if (!what || what.position) positionN = []\n if (!what || what.color) colorN = []\n if (!what || what.radius) sizeN = []\n if (!what || what.text) text = []\n if (p.colorParams) p.colorParams.structure = sview.getStructure()\n const colormaker = ColormakerRegistry.getScheme(p.colorParams)\n const radiusFactory = new RadiusFactory(p.radiusParams)\n const ap1 = sview.getAtomProxy()\n\n let i = 0\n sview.eachResidue(rp => {\n const i3 = i * 3\n if (rp.isProtein() || rp.isNucleic()) {\n ap1.index = rp.traceAtomIndex\n if (!what || what.position) {\n ap1.positionToArray(positionN, i3)\n }\n } else {\n ap1.index = rp.atomOffset\n if (!what || what.position) {\n rp.positionToArray(positionN, i3)\n }\n }\n if (!what || what.color) {\n colormaker.atomColorToArray(ap1, colorN, i3)\n }\n if (!what || what.radius) {\n sizeN[ i ] = radiusFactory.atomRadius(ap1)\n }\n if (!what || what.text) {\n text.push(labelFactory.atomLabel(ap1))\n }\n ++i\n })\n\n if (!what || what.position) position = new Float32Array(positionN!)\n if (!what || what.color) color = new Float32Array(colorN!)\n if (!what || what.radius) size = new Float32Array(sizeN!)\n }\n\n return { position: position!, size: size!, color: color!, text: text! }\n }\n\n createData (sview: StructureView) {\n const what: TextDataField = { position: true, color: true, radius: true, text: true }\n\n const textBuffer = new TextBuffer(\n this.getTextData(sview, what) as TextBufferData,\n this.getBufferParams({\n fontFamily: this.fontFamily,\n fontStyle: this.fontStyle,\n fontWeight: this.fontWeight,\n xOffset: this.xOffset,\n yOffset: this.yOffset,\n zOffset: this.zOffset,\n attachment: this.attachment,\n showBorder: this.showBorder,\n borderColor: this.borderColor,\n borderWidth: this.borderWidth,\n showBackground: this.showBackground,\n backgroundColor: this.backgroundColor,\n backgroundMargin: this.backgroundMargin,\n backgroundOpacity: this.backgroundOpacity,\n fixedSize: this.fixedSize\n })\n )\n\n return { bufferList: [ textBuffer ] }\n }\n\n updateData (what: TextDataField, data: StructureRepresentationData) {\n data.bufferList[ 0 ].setAttributes(this.getTextData(data.sview as StructureView, what))\n }\n\n getAtomRadius () {\n return 0\n }\n}\n\nRepresentationRegistry.add('label', LabelRepresentation)\n\nexport default LabelRepresentation\n","/**\n * @file Line Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport { RepresentationRegistry } from '../globals'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport WideLineBuffer from '../buffer/wideline-buffer'\nimport { AtomPicker } from '../utils/picker'\n// @ts-ignore: unused import Volume required for declaration only\nimport { Structure, Volume } from '../ngl';\nimport StructureView from '../structure/structure-view';\nimport Viewer from '../viewer/viewer';\nimport AtomProxy from '../proxy/atom-proxy';\n// @ts-ignore: unused import Surface required for declaration only\nimport Surface from '../surface/surface';\n// @ts-ignore: unused import BondDataFields, BondDataParams required for declaration only\nimport { BondDataFields, BondDataParams } from '../structure/structure-data';\n\n/**\n * Determine which atoms in a Structure[View] form no bonds to any other atoms\n * in that Structure.\n *\n * This differs from setting the selection to \"nonbonded\" as it finds atoms\n * that have no bonds within the current selection.\n * @param {Structure} structure - The Structure or StructureView object\n * @return {AtomSet} AtomSet of lone atoms\n */\nfunction getLoneAtomSet (structure: Structure | StructureView) {\n const atomSet = structure.getAtomSet()\n const bondSet = structure.getBondSet()\n const bp = structure.getBondProxy()\n bondSet.forEach(function (idx) {\n bp.index = idx\n atomSet.clear(bp.atomIndex1)\n atomSet.clear(bp.atomIndex2)\n })\n return atomSet\n}\n\nexport interface LineRepresentationParameters extends StructureRepresentationParameters {\n multipleBond: 'off' | 'symmetric' | 'offset'\n bondSpacing: number\n linewidth: number\n lines: boolean\n crosses: 'off' | 'all' | 'lone'\n crossSize: number\n}\n\nexport interface CrossData {\n position1?: Float32Array\n position2?: Float32Array\n color?: Float32Array\n color2?: Float32Array\n picking?: AtomPicker\n}\n\n/**\n * Line representation\n */\nclass LineRepresentation extends StructureRepresentation {\n protected multipleBond: 'off' | 'symmetric' | 'offset'\n protected bondSpacing: number\n protected linewidth: number\n protected lines: boolean\n protected crosses: 'off' | 'all' | 'lone'\n protected crossSize: number\n /**\n * Create Line representation object\n * @param {Structure} structure - the structure to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {RepresentationParameters} params - representation parameters, plus the properties listed below\n * @property {String} multipleBond - one off \"off\", \"symmetric\", \"offset\"\n * @param {Float} params.bondSpacing - spacing for multiple bond rendering\n * @param {Integer} params.linewidth - width of lines\n * @param {Boolean} params.lines - render bonds as lines\n * @param {String} params.crosses - render atoms as crosses: \"off\", \"all\" or \"lone\" (default)\n * @param {Float} params.crossSize - size of cross\n * @param {null} params.flatShaded - not available\n * @param {null} params.side - not available\n * @param {null} params.wireframe - not available\n * @param {null} params.roughness - not available\n * @param {null} params.metalness - not available\n * @param {null} params.diffuse - not available\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'line'\n\n this.parameters = Object.assign({\n\n multipleBond: {\n type: 'select',\n rebuild: true,\n options: {\n 'off': 'off',\n 'symmetric': 'symmetric',\n 'offset': 'offset'\n }\n },\n bondSpacing: {\n type: 'number', precision: 2, max: 2.0, min: 0.5\n },\n linewidth: {\n type: 'integer', max: 50, min: 1, buffer: true\n },\n lines: {\n type: 'boolean', rebuild: true\n },\n crosses: {\n type: 'select',\n rebuild: true,\n options: {\n 'off': 'off',\n 'lone': 'lone',\n 'all': 'all'\n }\n },\n crossSize: {\n type: 'number', precision: 2, max: 2.0, min: 0.1\n }\n\n }, this.parameters, {\n\n flatShaded: null,\n side: null,\n wireframe: null,\n\n roughness: null,\n metalness: null\n\n })\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n\n this.multipleBond = defaults(p.multipleBond, 'off')\n this.bondSpacing = defaults(p.bondSpacing, 1.0)\n this.linewidth = defaults(p.linewidth, 2)\n this.lines = defaults(p.lines, true)\n this.crosses = defaults(p.crosses, 'lone')\n this.crossSize = defaults(p.crossSize, 0.4)\n\n super.init(p)\n }\n\n getAtomRadius (atom:AtomProxy) {\n return 0.1\n }\n\n getBondParams (what: any, params?: Partial) {\n params = Object.assign({\n multipleBond: this.multipleBond,\n bondSpacing: this.bondSpacing,\n radiusParams: { 'type': 'size', 'size': 0.1, 'scale': 1 }\n }, params)\n\n return super.getBondParams(what, params)\n }\n\n _crossData (what: any, sview: StructureView) {\n if (what) {\n if (!what.position && !what.color) return\n }\n\n const p = {}\n if (this.crosses === 'lone') {\n Object.assign(p, {atomSet : getLoneAtomSet(sview)})\n }\n\n const atomData = sview.getAtomData(this.getAtomParams(what, p))\n const crossData: CrossData = {}\n const position = atomData.position\n const color = atomData.color\n const picking = atomData.picking\n\n const size = (position! || color).length\n const attrSize = size * 3\n\n let cPosition1 = new Float32Array(0)\n let cPosition2 = new Float32Array(0)\n let cColor = new Float32Array(0)\n let cColor2 = new Float32Array(0)\n let cOffset: number = 0\n\n let pickingArray = new Float32Array(0)\n\n if (!what || what.position) {\n cPosition1 = crossData.position1 = new Float32Array(attrSize)\n cPosition2 = crossData.position2 = new Float32Array(attrSize)\n cOffset = this.crossSize / 2\n }\n if (!what || what.color) {\n cColor = crossData.color = new Float32Array(attrSize)\n cColor2 = crossData.color2 = new Float32Array(attrSize)\n }\n if (!what || what.picking) {\n pickingArray = new Float32Array(atomData.picking!.array!.length * 3) // Needs padding??\n }\n\n for (let v = 0; v < size; v++) {\n const j = v * 3\n const i = j * 3\n\n if (!what || what.position) {\n const x = position![ j ]\n const y = position![ j + 1 ]\n const z = position![ j + 2 ]\n\n cPosition1[ i ] = x - cOffset!\n cPosition1[ i + 1 ] = y\n cPosition1[ i + 2 ] = z\n cPosition2[ i ] = x + cOffset\n cPosition2[ i + 1 ] = y\n cPosition2[ i + 2 ] = z\n\n cPosition1[ i + 3 ] = x\n cPosition1[ i + 4 ] = y - cOffset\n cPosition1[ i + 5 ] = z\n cPosition2[ i + 3 ] = x\n cPosition2[ i + 4 ] = y + cOffset\n cPosition2[ i + 5 ] = z\n\n cPosition1[ i + 6 ] = x\n cPosition1[ i + 7 ] = y\n cPosition1[ i + 8 ] = z - cOffset\n cPosition2[ i + 6 ] = x\n cPosition2[ i + 7 ] = y\n cPosition2[ i + 8 ] = z + cOffset\n }\n\n if (!what || what.color) {\n const cimax = i + 9\n for (let ci = i; ci < cimax; ci += 3) {\n cColor[ ci ] = cColor2[ ci ] = color![ j ]\n cColor[ ci + 1 ] = cColor2[ ci + 1 ] = color![ j + 1 ]\n cColor[ ci + 2 ] = cColor2[ ci + 2 ] = color![ j + 2 ]\n }\n }\n\n if (!what || what.picking) {\n pickingArray[ j ] =\n pickingArray[ j + 1 ] =\n pickingArray[ j + 2 ] = picking!.array![ v ]\n }\n }\n\n if (!what || what.picking) {\n crossData.picking = new AtomPicker(\n pickingArray, picking!.structure\n )\n }\n\n return crossData\n }\n\n createData (sview: StructureView) {\n const what = { position: true, color: true, picking: true }\n\n const bufferList = []\n\n if (this.lines) {\n const bondData = sview.getBondData(this.getBondParams(what))\n\n const lineBuffer = new WideLineBuffer(\n bondData, this.getBufferParams({ linewidth: this.linewidth })\n )\n\n bufferList.push(lineBuffer)\n }\n\n if (this.crosses !== 'off') {\n const crossBuffer = new WideLineBuffer(\n (this._crossData(what, sview) as CrossData),\n this.getBufferParams({linewidth: this.linewidth})\n )\n bufferList.push(crossBuffer)\n }\n\n return {\n bufferList: bufferList\n }\n }\n\n updateData (what: any, data: StructureRepresentationData) {\n let bufferIdx = 0\n\n if (this.lines) {\n const bondData = data.sview!.getBondData(this.getBondParams(what))\n const lineAttributes = {}\n\n if (!what || what.position) {\n Object.assign(lineAttributes, {\n position1: bondData.position1,\n position2: bondData.position2\n })\n }\n\n if (!what || what.color) {\n Object.assign(lineAttributes, {\n color: bondData.color,\n color2: bondData.color2\n })\n }\n\n data.bufferList[ bufferIdx++ ].setAttributes(lineAttributes)\n }\n\n if (this.crosses !== 'off') {\n const crossData = this._crossData(what, (data.sview as StructureView))\n const crossAttributes = {}\n\n if (!what || what.position) {\n Object.assign(crossAttributes, {\n position1: crossData!.position1,\n position2: crossData!.position2\n })\n }\n if (!what || what.color) {\n Object.assign(crossAttributes, {\n color: crossData!.color,\n color2: crossData!.color2\n })\n }\n\n data.bufferList[ bufferIdx++ ].setAttributes(crossAttributes)\n }\n }\n\n setParameters (params: Partial) {\n var rebuild = false\n var what = {}\n\n if (params && (params.bondSpacing || params.crossSize)) {\n Object.assign(what, { position: true })\n }\n\n super.setParameters(params, what, rebuild)\n\n return this\n }\n}\n\nRepresentationRegistry.add('line', LineRepresentation)\n\nexport default LineRepresentation\n","import { NumberArray, TypedArray } from \"../types\";\n\n/**\n * @file Grid\n * @author Alexander Rose \n * @private\n */\nexport interface iGrid {\n data: TypedArray\n index: (x: number, y: number, z: number) => number\n set: (x: number, y: number, z: number, ...arg: number[]) => void\n toArray: (x: number, y: number, z: number, array?: NumberArray, offset?: number) => void\n fromArray: (x: number, y: number, z: number, array: NumberArray, offset?: number) => void\n copy: (grid: iGrid) => void\n // clone: () => iGrid\n}\n\nfunction makeGrid (length: number, width: number, height: number, DataCtor: any, elemSize: number) : iGrid {\n DataCtor = DataCtor || Int32Array\n elemSize = elemSize || 1\n\n const data = new DataCtor(length * width * height * elemSize)\n\n function index (x: number, y: number, z: number) {\n return ((((x * width) + y) * height) + z) * elemSize\n }\n\n function set (x: number, y: number, z: number, ...args: number[]) {\n const i = index(x, y, z)\n\n for (let j = 0; j < elemSize; ++j) {\n data[ i + j ] = args[ j ]\n }\n }\n\n function toArray (x: number, y: number, z: number, array: NumberArray = [], offset: number = 0) {\n const i = index(x, y, z)\n\n for (let j = 0; j < elemSize; ++j) {\n array[ offset + j ] = data[ i + j ]\n }\n }\n\n function fromArray(x: number, y: number, z: number, array: NumberArray, offset: number = 0) {\n const i = index(x, y, z)\n\n for (let j = 0; j < elemSize; ++j) {\n data[ i + j ] = array[ offset + j ]\n }\n }\n\n function copy(grid: iGrid) {\n data.set(grid.data)\n }\n\n // function clone() {\n // return makeGrid(\n // length, width, height, DataCtor, elemSize\n // ).copy(this)\n // }\n return { data, index, set, toArray, fromArray, copy }\n}\n\nexport { makeGrid }","/**\n * @file EDT Surface\n * @author Alexander Rose \n * @private\n */\n\nimport { VolumeSurface } from './volume'\nimport { iGrid, makeGrid } from '../geometry/grid'\nimport { computeBoundingBox } from '../math/vector-utils'\nimport { getRadiusDict, getSurfaceGrid } from './surface-utils'\nimport { TypedArray } from '../types';\n\ninterface EDTSurface {\n getVolume: (type: string, probeRadius: number, scaleFactor: number, cutoff: number, setAtomID: boolean) => {\n data: TypedArray\n nx: number\n ny: number\n nz: number\n atomindex: TypedArray\n }\n getSurface: (type: string, probeRadius: number, scaleFactor: number, cutoff: number, setAtomID: boolean, smooth: number, contour: boolean) => any\n}\n\nfunction EDTSurface (this: EDTSurface, coordList: Float32Array, radiusList: Float32Array, indexList: Uint16Array|Uint32Array) {\n // based on D. Xu, Y. Zhang (2009) Generating Triangulated Macromolecular\n // Surfaces by Euclidean Distance Transform. PLoS ONE 4(12): e8140.\n //\n // Permission to use, copy, modify, and distribute this program for\n // any purpose, with or without fee, is hereby granted, provided that\n // the notices on the head, the reference information, and this\n // copyright notice appear in all copies or substantial portions of\n // the Software. It is provided \"as is\" without express or implied\n // warranty.\n //\n // ported to JavaScript by biochem_fan (http://webglmol.sourceforge.jp/)\n // refactored by dkoes (https://github.com/dkoes)\n //\n // adapted to NGL by Alexander Rose\n\n var radiusDict = getRadiusDict(radiusList as any)\n var bbox = computeBoundingBox(coordList)\n if (coordList.length === 0) {\n bbox[ 0 ].set([ 0, 0, 0 ])\n bbox[ 1 ].set([ 0, 0, 0 ])\n }\n var min = bbox[ 0 ]\n var max = bbox[ 1 ]\n\n var probeRadius: number, scaleFactor: number, cutoff: number\n var pLength: number, pWidth: number, pHeight: number\n var matrix: Float32Array, ptran: Float32Array\n var depty: {[k: string]: TypedArray}, widxz: {[k: string]: number}\n var cutRadius: number\n var setAtomID: boolean\n var vpBits: TypedArray, vpDistance: TypedArray, vpAtomID: TypedArray\n\n function init (btype: boolean, _probeRadius: number, _scaleFactor: number, _cutoff: number, _setAtomID: boolean) {\n probeRadius = _probeRadius || 1.4\n scaleFactor = _scaleFactor || 2.0\n setAtomID = _setAtomID || true\n\n var maxRadius = 0\n for (var radius in radiusDict) {\n maxRadius = Math.max(maxRadius, radius as any)\n }\n\n var grid = getSurfaceGrid(\n min, max, maxRadius, scaleFactor, btype ? probeRadius : 0\n )\n\n pLength = grid.dim[0]\n pWidth = grid.dim[1]\n pHeight = grid.dim[2]\n\n matrix = grid.matrix\n ptran = grid.tran\n scaleFactor = grid.scaleFactor\n\n // boundingatom caches\n depty = {}\n widxz = {}\n boundingatom(btype)\n\n cutRadius = probeRadius * scaleFactor\n\n if (_cutoff) {\n cutoff = _cutoff\n } else {\n // cutoff = Math.max( 0.1, -1.2 + scaleFactor * probeRadius );\n cutoff = probeRadius / scaleFactor\n }\n\n vpBits = new Uint8Array(pLength * pWidth * pHeight)\n if (btype) {\n vpDistance = new Float64Array(pLength * pWidth * pHeight)\n }\n if (setAtomID) {\n vpAtomID = new Int32Array(pLength * pWidth * pHeight)\n }\n }\n\n // constants for vpBits bitmasks\n var INOUT = 1\n var ISDONE = 2\n var ISBOUND = 4\n\n var nb = [\n new Int32Array([ 1, 0, 0 ]), new Int32Array([ -1, 0, 0 ]),\n new Int32Array([ 0, 1, 0 ]), new Int32Array([ 0, -1, 0 ]),\n new Int32Array([ 0, 0, 1 ]), new Int32Array([ 0, 0, -1 ]),\n new Int32Array([ 1, 1, 0 ]), new Int32Array([ 1, -1, 0 ]),\n new Int32Array([ -1, 1, 0 ]), new Int32Array([ -1, -1, 0 ]),\n new Int32Array([ 1, 0, 1 ]), new Int32Array([ 1, 0, -1 ]),\n new Int32Array([ -1, 0, 1 ]), new Int32Array([ -1, 0, -1 ]),\n new Int32Array([ 0, 1, 1 ]), new Int32Array([ 0, 1, -1 ]),\n new Int32Array([ 0, -1, 1 ]), new Int32Array([ 0, -1, -1 ]),\n new Int32Array([ 1, 1, 1 ]), new Int32Array([ 1, 1, -1 ]),\n new Int32Array([ 1, -1, 1 ]), new Int32Array([ -1, 1, 1 ]),\n new Int32Array([ 1, -1, -1 ]), new Int32Array([ -1, -1, 1 ]),\n new Int32Array([ -1, 1, -1 ]), new Int32Array([ -1, -1, -1 ])\n ]\n\n //\n\n this.getVolume = function (type: string, probeRadius: number, scaleFactor: number, cutoff: number, setAtomID: boolean) {\n console.time('EDTSurface.getVolume')\n\n var btype = type !== 'vws'\n\n init(btype, probeRadius, scaleFactor, cutoff, setAtomID)\n\n fillvoxels(btype)\n buildboundary()\n\n if (type === 'ms' || type === 'ses') {\n fastdistancemap()\n }\n\n if (type === 'ses') {\n boundingatom(false)\n fillvoxelswaals()\n }\n\n marchingcubeinit(type)\n\n // set atomindex in the volume data\n for (var i = 0, il = vpAtomID.length; i < il; ++i) {\n vpAtomID[ i ] = indexList[ vpAtomID[ i ] ]\n }\n\n console.timeEnd('EDTSurface.getVolume')\n\n return {\n data: vpBits,\n nx: pHeight,\n ny: pWidth,\n nz: pLength,\n atomindex: vpAtomID\n }\n }\n\n this.getSurface = function (type: string, probeRadius: number, scaleFactor: number, cutoff: number, setAtomID: boolean, smooth: number, contour: boolean) {\n var vd = this.getVolume(\n type, probeRadius, scaleFactor, cutoff, setAtomID\n )\n\n var volsurf = new (VolumeSurface as any)(\n vd.data, vd.nx, vd.ny, vd.nz, vd.atomindex\n ) as VolumeSurface\n\n return (volsurf!.getSurface as any)(1, smooth, undefined, matrix, contour)\n }\n\n function boundingatom (btype: boolean) {\n var r\n var j\n var k\n var txz\n var tdept\n var sradius\n var tradius\n var widxzR\n var deptyName\n var indx\n\n for (var name in radiusDict) {\n r = parseFloat(name)\n\n if (depty[ name ]) continue\n\n if (!btype) {\n tradius = r * scaleFactor + 0.5\n } else {\n tradius = (r + probeRadius) * scaleFactor + 0.5\n }\n\n sradius = tradius * tradius\n widxzR = Math.floor(tradius) + 1\n deptyName = new Int32Array(widxzR * widxzR)\n indx = 0\n\n for (j = 0; j < widxzR; ++j) {\n for (k = 0; k < widxzR; ++k) {\n txz = j * j + k * k\n\n if (txz > sradius) {\n deptyName[ indx ] = -1\n } else {\n tdept = Math.sqrt(sradius - txz)\n deptyName[ indx ] = Math.floor(tdept)\n }\n\n ++indx\n }\n }\n\n widxz[ name ] = widxzR\n depty[ name ] = deptyName\n }\n }\n\n function fillatom (idx: number) {\n var ci = idx * 3\n var ri = idx\n\n var cx, cy, cz, ox, oy, oz, mi, mj, mk, i, j, k, si, sj, sk\n var ii, jj, kk\n\n cx = Math.floor(0.5 + scaleFactor * (coordList[ ci ] + ptran[0]))\n cy = Math.floor(0.5 + scaleFactor * (coordList[ ci + 1 ] + ptran[1]))\n cz = Math.floor(0.5 + scaleFactor * (coordList[ ci + 2 ] + ptran[2]))\n\n var at = radiusList[ ri ]\n var deptyAt = depty[ at ]\n var nind = 0\n var pWH = pWidth * pHeight\n var n = widxz[ at ]\n\n var deptyAtNind\n\n for (i = 0; i < n; ++i) {\n for (j = 0; j < n; ++j) {\n deptyAtNind = deptyAt[ nind ]\n\n if (deptyAtNind !== -1) {\n for (ii = -1; ii < 2; ++ii) {\n for (jj = -1; jj < 2; ++jj) {\n for (kk = -1; kk < 2; ++kk) {\n if (ii !== 0 && jj !== 0 && kk !== 0) {\n mi = ii * i\n mk = kk * j\n\n for (k = 0; k <= deptyAtNind; ++k) {\n mj = k * jj\n si = cx + mi\n sj = cy + mj\n sk = cz + mk\n\n if (si < 0 || sj < 0 || sk < 0 ||\n si >= pLength || sj >= pWidth || sk >= pHeight\n ) {\n continue\n }\n\n var index = si * pWH + sj * pHeight + sk\n\n if (!setAtomID) {\n vpBits[ index ] |= INOUT\n } else {\n if (!(vpBits[ index ] & INOUT)) {\n vpBits[ index ] |= INOUT\n vpAtomID[ index ] = idx\n } else if (vpBits[ index ] & INOUT) {\n var ci2 = vpAtomID[ index ]\n\n if (ci2 !== ci) {\n ox = cx + mi - Math.floor(0.5 + scaleFactor * (coordList[ci2] + ptran[0]))\n oy = cy + mj - Math.floor(0.5 + scaleFactor * (coordList[ci2 + 1] + ptran[1]))\n oz = cz + mk - Math.floor(0.5 + scaleFactor * (coordList[ci2 + 2] + ptran[2]))\n\n if (mi * mi + mj * mj + mk * mk < ox * ox + oy * oy + oz * oz) {\n vpAtomID[ index ] = idx\n }\n }\n }\n }\n } // k\n } // if\n } // kk\n } // jj\n } // ii\n } // if\n\n nind++\n } // j\n } // i\n }\n\n function fillvoxels (btype: boolean) {\n console.time('EDTSurface fillvoxels')\n\n var i, il\n\n for (i = 0, il = vpBits.length; i < il; ++i) {\n vpBits[ i ] = 0\n if (btype) vpDistance[ i ] = -1.0\n if (setAtomID) vpAtomID[ i ] = -1\n }\n\n for (i = 0, il = coordList.length / 3; i < il; ++i) {\n fillatom(i)\n }\n\n for (i = 0, il = vpBits.length; i < il; ++i) {\n if (vpBits[ i ] & INOUT) {\n vpBits[ i ] |= ISDONE\n }\n }\n\n console.timeEnd('EDTSurface fillvoxels')\n }\n\n function fillAtomWaals (idx: number) {\n var ci = idx * 3\n var ri = idx\n\n var cx\n var cy\n var cz\n var ox\n var oy\n var oz\n var nind = 0\n\n var mi\n var mj\n var mk\n var si\n var sj\n var sk\n var i\n var j\n var k\n var ii\n var jj\n var kk\n var n\n\n cx = Math.floor(0.5 + scaleFactor * (coordList[ ci ] + ptran[0]))\n cy = Math.floor(0.5 + scaleFactor * (coordList[ ci + 1 ] + ptran[1]))\n cz = Math.floor(0.5 + scaleFactor * (coordList[ ci + 2 ] + ptran[2]))\n\n var at = radiusList[ ri ]\n var pWH = pWidth * pHeight\n\n for (i = 0, n = widxz[at]; i < n; ++i) {\n for (j = 0; j < n; ++j) {\n if (depty[ at ][ nind ] !== -1) {\n for (ii = -1; ii < 2; ++ii) {\n for (jj = -1; jj < 2; ++jj) {\n for (kk = -1; kk < 2; ++kk) {\n if (ii !== 0 && jj !== 0 && kk !== 0) {\n mi = ii * i\n mk = kk * j\n\n for (k = 0; k <= depty[ at ][ nind ]; ++k) {\n mj = k * jj\n si = cx + mi\n sj = cy + mj\n sk = cz + mk\n\n if (si < 0 || sj < 0 || sk < 0 ||\n si >= pLength || sj >= pWidth || sk >= pHeight\n ) {\n continue\n }\n\n var index = si * pWH + sj * pHeight + sk\n\n if (!(vpBits[ index ] & ISDONE)) {\n vpBits[ index ] |= ISDONE\n if (setAtomID) vpAtomID[ index ] = idx\n } else if (setAtomID) {\n var ci2 = vpAtomID[ index ]\n\n ox = Math.floor(0.5 + scaleFactor * (coordList[ ci2 ] + ptran[0]))\n oy = Math.floor(0.5 + scaleFactor * (coordList[ ci2 + 1 ] + ptran[1]))\n oz = Math.floor(0.5 + scaleFactor * (coordList[ ci2 + 2 ] + ptran[2]))\n\n if (mi * mi + mj * mj + mk * mk < ox * ox + oy * oy + oz * oz) {\n vpAtomID[ index ] = idx\n }\n }\n } // k\n } // if\n } // kk\n } // jj\n } // ii\n } // if\n\n nind++\n } // j\n } // i\n }\n\n function fillvoxelswaals () {\n var i, il\n\n for (i = 0, il = vpBits.length; i < il; ++i) {\n vpBits[ i ] &= ~ISDONE // not isdone\n }\n\n for (i = 0, il = coordList.length / 3; i < il; ++i) {\n fillAtomWaals(i)\n }\n }\n\n function buildboundary () {\n var i, j, k\n var pWH = pWidth * pHeight\n\n for (i = 0; i < pLength; ++i) {\n for (j = 0; j < pHeight; ++j) {\n for (k = 0; k < pWidth; ++k) {\n var index = i * pWH + k * pHeight + j\n\n if (vpBits[ index ] & INOUT) {\n // var flagbound = false;\n var ii = 0\n\n // while( !flagbound && ii < 26 ){\n while (ii < 26) {\n var ti = i + nb[ ii ][ 0 ]\n var tj = j + nb[ ii ][ 2 ]\n var tk = k + nb[ ii ][ 1 ]\n\n if (ti > -1 && ti < pLength &&\n tk > -1 && tk < pWidth &&\n tj > -1 && tj < pHeight &&\n !(vpBits[ ti * pWH + tk * pHeight + tj ] & INOUT)\n ) {\n vpBits[ index ] |= ISBOUND\n // flagbound = true;\n break\n } else {\n ii++\n }\n }\n }\n } // k\n } // j\n } // i\n }\n\n function fastdistancemap () {\n console.time('EDTSurface fastdistancemap')\n\n var i, j, k, n\n\n var boundPoint = makeGrid(\n pLength, pWidth, pHeight, Uint16Array, 3\n )\n var pWH = pWidth * pHeight\n var cutRSq = cutRadius * cutRadius\n\n var totalsurfacevox = 0\n // var totalinnervox = 0;\n\n var index\n\n for (i = 0; i < pLength; ++i) {\n for (j = 0; j < pWidth; ++j) {\n for (k = 0; k < pHeight; ++k) {\n index = i * pWH + j * pHeight + k\n\n vpBits[ index ] &= ~ISDONE\n\n if (vpBits[ index ] & INOUT) {\n if (vpBits[ index ] & ISBOUND) {\n boundPoint.set(\n i, j, k,\n i, j, k\n )\n\n vpDistance[ index ] = 0\n vpBits[ index ] |= ISDONE\n\n totalsurfacevox += 1\n }/* else{\n totalinnervox += 1;\n } */\n }\n }\n }\n }\n\n var inarray = new Int32Array(3 * totalsurfacevox)\n var positin = 0\n var outarray = new Int32Array(3 * totalsurfacevox)\n var positout = 0\n\n for (i = 0; i < pLength; ++i) {\n for (j = 0; j < pWidth; ++j) {\n for (k = 0; k < pHeight; ++k) {\n index = i * pWH + j * pHeight + k\n\n if (vpBits[ index ] & ISBOUND) {\n inarray[ positin ] = i\n inarray[ positin + 1 ] = j\n inarray[ positin + 2 ] = k\n positin += 3\n\n vpBits[ index ] &= ~ISBOUND\n }\n }\n }\n }\n\n do {\n positout = fastoneshell(inarray, boundPoint, positin, outarray)\n positin = 0\n\n for (i = 0, n = positout; i < n; i += 3) {\n index = pWH * outarray[ i ] + pHeight * outarray[ i + 1 ] + outarray[ i + 2 ]\n vpBits[ index ] &= ~ISBOUND\n\n if (vpDistance[ index ] <= 1.0404 * cutRSq) {\n // if( vpDistance[ index ] <= 1.02 * cutRadius ){\n\n inarray[ positin ] = outarray[ i ]\n inarray[ positin + 1 ] = outarray[ i + 1 ]\n inarray[ positin + 2 ] = outarray[ i + 2 ]\n positin += 3\n }\n }\n } while (positin > 0)\n\n // var cutsf = Math.max( 0, scaleFactor - 0.5 );\n // cutoff = cutRadius - 0.5 / ( 0.1 + cutsf );\n var cutoffSq = cutoff * cutoff\n\n var index2\n var bp = new Uint16Array(3)\n\n for (i = 0; i < pLength; ++i) {\n for (j = 0; j < pWidth; ++j) {\n for (k = 0; k < pHeight; ++k) {\n index = i * pWH + j * pHeight + k\n vpBits[ index ] &= ~ISBOUND\n\n // ses solid\n\n if (vpBits[ index ] & INOUT) {\n if (!(vpBits[ index ] & ISDONE) ||\n ((vpBits[ index ] & ISDONE) && vpDistance[ index ] >= cutoffSq)\n ) {\n vpBits[ index ] |= ISBOUND\n\n if (setAtomID && (vpBits[ index ] & ISDONE)) {\n boundPoint.toArray(i, j, k, bp)\n index2 = bp[ 0 ] * pWH + bp[ 1 ] * pHeight + bp[ 2 ]\n\n vpAtomID[ index ] = vpAtomID[ index2 ]\n }\n }\n }\n }\n }\n }\n\n console.timeEnd('EDTSurface fastdistancemap')\n }\n\n function fastoneshell (inarray: Int32Array, boundPoint: iGrid, positin: number, outarray: Int32Array) {\n // *allocout,voxel2\n // ***boundPoint, int*\n // outnum, int *elimi)\n var tx, ty, tz\n var dx, dy, dz\n var i, j, n\n var square\n var index\n var nbj\n var bp = new Uint16Array(3)\n var positout = 0\n\n if (positin === 0) {\n return positout\n }\n\n var tnvix = -1\n var tnviy = -1\n var tnviz = -1\n\n var pWH = pWidth * pHeight\n\n for (i = 0, n = positin; i < n; i += 3) {\n tx = inarray[ i ]\n ty = inarray[ i + 1 ]\n tz = inarray[ i + 2 ]\n boundPoint.toArray(tx, ty, tz, bp)\n\n for (j = 0; j < 6; ++j) {\n nbj = nb[ j ]\n tnvix = tx + nbj[ 0 ]\n tnviy = ty + nbj[ 1 ]\n tnviz = tz + nbj[ 2 ]\n\n if (tnvix < pLength && tnvix > -1 &&\n tnviy < pWidth && tnviy > -1 &&\n tnviz < pHeight && tnviz > -1\n ) {\n index = tnvix * pWH + pHeight * tnviy + tnviz\n\n if ((vpBits[ index ] & INOUT) && !(vpBits[ index ] & ISDONE)) {\n boundPoint.fromArray(tnvix, tnviy, tnviz, bp)\n dx = tnvix - bp[ 0 ]\n dy = tnviy - bp[ 1 ]\n dz = tnviz - bp[ 2 ]\n square = dx * dx + dy * dy + dz * dz\n // square = Math.sqrt( square );\n\n vpDistance[ index ] = square\n vpBits[ index ] |= ISDONE\n vpBits[ index ] |= ISBOUND\n\n outarray[ positout ] = tnvix\n outarray[ positout + 1 ] = tnviy\n outarray[ positout + 2 ] = tnviz\n positout += 3\n } else if ((vpBits[ index ] & INOUT) && (vpBits[ index ] & ISDONE)) {\n dx = tnvix - bp[ 0 ]\n dy = tnviy - bp[ 1 ]\n dz = tnviz - bp[ 2 ]\n square = dx * dx + dy * dy + dz * dz\n // square = Math.sqrt( square );\n\n if (square < vpDistance[ index ]) {\n boundPoint.fromArray(tnvix, tnviy, tnviz, bp)\n vpDistance[ index ] = square\n\n if (!(vpBits[ index ] & ISBOUND)) {\n vpBits[ index ] |= ISBOUND\n\n outarray[ positout ] = tnvix\n outarray[ positout + 1 ] = tnviy\n outarray[ positout + 2 ] = tnviz\n positout += 3\n }\n }\n }\n }\n }\n }\n\n for (i = 0, n = positin; i < n; i += 3) {\n tx = inarray[ i ]\n ty = inarray[ i + 1 ]\n tz = inarray[ i + 2 ]\n boundPoint.toArray(tx, ty, tz, bp)\n\n for (j = 6; j < 18; j++) {\n nbj = nb[ j ]\n tnvix = tx + nbj[ 0 ]\n tnviy = ty + nbj[ 1 ]\n tnviz = tz + nbj[ 2 ]\n\n if (tnvix < pLength && tnvix > -1 &&\n tnviy < pWidth && tnviy > -1 &&\n tnviz < pHeight && tnviz > -1\n ) {\n index = tnvix * pWH + pHeight * tnviy + tnviz\n\n if ((vpBits[index] & INOUT) && !(vpBits[index] & ISDONE)) {\n boundPoint.fromArray(tnvix, tnviy, tnviz, bp)\n dx = tnvix - bp[ 0 ]\n dy = tnviy - bp[ 1 ]\n dz = tnviz - bp[ 2 ]\n square = dx * dx + dy * dy + dz * dz\n // square = Math.sqrt( square );\n\n vpDistance[index] = square\n vpBits[index] |= ISDONE\n vpBits[index] |= ISBOUND\n\n outarray[ positout ] = tnvix\n outarray[ positout + 1 ] = tnviy\n outarray[ positout + 2 ] = tnviz\n positout += 3\n } else if ((vpBits[index] & INOUT) && (vpBits[index] & ISDONE)) {\n dx = tnvix - bp[ 0 ]\n dy = tnviy - bp[ 1 ]\n dz = tnviz - bp[ 2 ]\n square = dx * dx + dy * dy + dz * dz\n // square = Math.sqrt( square );\n\n if (square < vpDistance[index]) {\n boundPoint.fromArray(tnvix, tnviy, tnviz, bp)\n vpDistance[index] = square\n\n if (!(vpBits[index] & ISBOUND)) {\n vpBits[index] |= ISBOUND\n\n outarray[ positout ] = tnvix\n outarray[ positout + 1 ] = tnviy\n outarray[ positout + 2 ] = tnviz\n positout += 3\n }\n }\n }\n }\n }\n }\n\n for (i = 0, n = positin; i < n; i += 3) {\n tx = inarray[ i ]\n ty = inarray[ i + 1 ]\n tz = inarray[ i + 2 ]\n boundPoint.toArray(tx, ty, tz, bp)\n\n for (j = 18; j < 26; j++) {\n nbj = nb[ j ]\n tnvix = tx + nbj[ 0 ]\n tnviy = ty + nbj[ 1 ]\n tnviz = tz + nbj[ 2 ]\n\n if (tnvix < pLength && tnvix > -1 &&\n tnviy < pWidth && tnviy > -1 &&\n tnviz < pHeight && tnviz > -1\n ) {\n index = tnvix * pWH + pHeight * tnviy + tnviz\n\n if ((vpBits[index] & INOUT) && !(vpBits[index] & ISDONE)) {\n boundPoint.fromArray(tnvix, tnviy, tnviz, bp)\n dx = tnvix - bp[ 0 ]\n dy = tnviy - bp[ 1 ]\n dz = tnviz - bp[ 2 ]\n square = dx * dx + dy * dy + dz * dz\n // square = Math.sqrt( square );\n\n vpDistance[index] = square\n vpBits[index] |= ISDONE\n vpBits[index] |= ISBOUND\n\n outarray[ positout ] = tnvix\n outarray[ positout + 1 ] = tnviy\n outarray[ positout + 2 ] = tnviz\n positout += 3\n } else if ((vpBits[index] & INOUT) && (vpBits[index] & ISDONE)) {\n dx = tnvix - bp[ 0 ]\n dy = tnviy - bp[ 1 ]\n dz = tnviz - bp[ 2 ]\n square = dx * dx + dy * dy + dz * dz\n // square = Math.sqrt( square );\n\n if (square < vpDistance[index]) {\n boundPoint.fromArray(tnvix, tnviy, tnviz, bp)\n vpDistance[index] = square\n\n if (!(vpBits[index] & ISBOUND)) {\n vpBits[index] |= ISBOUND\n\n outarray[ positout ] = tnvix\n outarray[ positout + 1 ] = tnviy\n outarray[ positout + 2 ] = tnviz\n positout += 3\n }\n }\n }\n }\n }\n }\n\n return positout\n }\n\n function marchingcubeinit (stype: string) {\n var i\n var n = vpBits.length\n\n if (stype === 'vws') {\n for (i = 0; i < n; ++i) {\n vpBits[ i ] &= ~ISBOUND\n vpBits[ i ] = (vpBits[ i ] & ISDONE) ? 1 : 0\n }\n } else if (stype === 'ms') { // ses without vdw => ms\n for (i = 0; i < n; ++i) {\n vpBits[ i ] &= ~ISDONE\n if (vpBits[ i ] & ISBOUND) {\n vpBits[ i ] |= ISDONE\n }\n vpBits[ i ] &= ~ISBOUND\n vpBits[ i ] = (vpBits[ i ] & ISDONE) ? 1 : 0\n }\n } else if (stype === 'ses') {\n for (i = 0; i < n; ++i) {\n if ((vpBits[ i ] & ISBOUND) && (vpBits[ i ] & ISDONE)) {\n vpBits[ i ] &= ~ISBOUND\n } else if ((vpBits[ i ] & ISBOUND) && !(vpBits[ i ] & ISDONE)) {\n vpBits[ i ] |= ISDONE\n }\n vpBits[ i ] = (vpBits[ i ] & ISDONE) ? 1 : 0\n }\n } else if (stype === 'sas') {\n for (i = 0; i < n; ++i) {\n vpBits[ i ] &= ~ISBOUND\n vpBits[ i ] = (vpBits[ i ] & ISDONE) ? 1 : 0\n }\n }\n }\n}\nObject.assign(EDTSurface, {__deps: [\n getSurfaceGrid, getRadiusDict, VolumeSurface, computeBoundingBox, makeGrid\n]})\n\nexport default EDTSurface\n","/**\n * @file AV Surface\n * @author Fred Ludlow \n * @private\n */\n\nimport { getSurfaceGrid } from './surface-utils'\nimport { VolumeSurface } from './volume'\nimport { uniformArray } from '../math/array-utils'\nimport {\n computeBoundingBox, v3multiplyScalar, v3cross, v3normalize\n} from '../math/vector-utils'\nimport { defaults } from '../utils'\nimport { NumberArray } from '../types';\n\n\n/**\n * Modifed from SpatialHash\n *\n * Main differences are:\n * - Optimized grid size to ensure we only ever need to look +/-1 cell\n * - Aware of atomic radii and will only output atoms within rAtom + rExtra\n * (see withinRadii method)\n *\n * (Uses rounding rather than bitshifting as consequence of arbitrary grid size)\n * @class\n * @param {Float32Array} atomsX - x coordinates\n * @param {Float32Array} atomsY - y coordinates\n * @param {Float32Array} atomsZ - z coordinates\n * @param {Float32Array} atomsR - atom radii\n * @param {Float32Array} min - xyz min coordinates\n * @param {Float32Array} max - xyz max coordinates\n * @param {Float} maxDistance - max distance\n */\nexport interface iAVHash {\n neighbourListLength: number\n withinRadii: (x: number, y: number, z: number, rExtra: number, out: Int32Array) => void\n}\n\n\nfunction makeAVHash (atomsX: Float32Array, atomsY: Float32Array, atomsZ: Float32Array, atomsR: Float32Array, min: Float32Array, max: Float32Array, maxDistance: number): iAVHash {\n maxDistance = Math.max(0.1, maxDistance) // Avoid maxDistance of zero, see #802\n var nAtoms = atomsX.length\n\n var minX = min[ 0 ]\n var minY = min[ 1 ]\n var minZ = min[ 2 ]\n\n var maxX = max[ 0 ]\n var maxY = max[ 1 ]\n var maxZ = max[ 2 ]\n\n function hashFunc (w: number, minW: number) {\n return Math.floor((w - minW) / maxDistance)\n }\n\n var iDim = hashFunc(maxX, minX) + 1\n var jDim = hashFunc(maxY, minY) + 1\n var kDim = hashFunc(maxZ, minZ) + 1\n\n var nCells = iDim * jDim * kDim\n\n var jkDim = jDim * kDim\n\n /* Get cellID for cartesian x,y,z */\n var cellID = function (x: number, y: number, z: number) {\n return (((hashFunc(x, minX) * jDim) + hashFunc(y, minY)) * kDim) + hashFunc(z, minZ)\n }\n\n /* Initial building, could probably be optimized further */\n var preHash = [] // preHash[ cellID ] = [ atomId1, atomId2 ];\n\n for (var i = 0; i < nAtoms; i++) {\n var cid = cellID(atomsX[ i ], atomsY[ i ], atomsZ[ i ])\n\n if (preHash[ cid ] === undefined) {\n preHash[ cid ] = [ i ]\n } else {\n preHash[ cid ].push(i)\n }\n }\n\n var cellOffsets = new Uint32Array(nCells)\n var cellLengths = new Uint16Array(nCells)\n var data = new Uint32Array(nAtoms)\n\n var offset = 0\n var maxCellLength = 0\n\n for (i = 0; i < nCells; i++) {\n var start = cellOffsets[ i ] = offset\n\n var subArray = preHash[ i ]\n\n if (subArray !== undefined) {\n for (var j = 0; j < subArray.length; j++) {\n data[ offset ] = subArray[ j ]\n offset++\n }\n }\n\n var cellLength = offset - start\n cellLengths[ i ] = cellLength\n\n if (cellLength > maxCellLength) { maxCellLength = cellLength }\n }\n\n // Maximum number of neighbours we could ever produce (27 adjacent cells of equal population)\n const neighbourListLength = (27 * maxCellLength) + 1\n\n /**\n * Populate the supplied out array with atom indices that are within rAtom + rExtra\n * of x,y,z\n *\n * -1 in out array indicates the end of the list\n *\n * @param {Float} x - x coordinate\n * @param {Float} y - y coordinate\n * @param {Float} z - z coordinate\n * @param {Float} rExtra - additional radius\n * @param {Float32Array} out - pre-allocated output array\n * @return {undefined}\n */\n const withinRadii = function (x: number, y: number, z: number, rExtra: number, out: Int32Array) {\n var outIdx = 0\n\n var nearI = hashFunc(x, minX)\n var nearJ = hashFunc(y, minY)\n var nearK = hashFunc(z, minZ)\n\n var loI = Math.max(0, nearI - 1)\n var loJ = Math.max(0, nearJ - 1)\n var loK = Math.max(0, nearK - 1)\n\n var hiI = Math.min(iDim, nearI + 2)\n var hiJ = Math.min(jDim, nearJ + 2)\n var hiK = Math.min(kDim, nearK + 2)\n\n for (var i = loI; i < hiI; ++i) {\n var iOffset = i * jkDim\n\n for (var j = loJ; j < hiJ; ++j) {\n var jOffset = j * kDim\n\n for (var k = loK; k < hiK; ++k) {\n var cid = iOffset + jOffset + k\n\n var cellStart = cellOffsets[ cid ]\n var cellEnd = cellStart + cellLengths[ cid ]\n\n for (var dataIndex = cellStart; dataIndex < cellEnd; dataIndex++) {\n var atomIndex = data[ dataIndex ]\n var dx = atomsX[ atomIndex ] - x\n var dy = atomsY[ atomIndex ] - y\n var dz = atomsZ[ atomIndex ] - z\n var rSum = atomsR[ atomIndex ] + rExtra\n\n if ((dx * dx + dy * dy + dz * dz) <= (rSum * rSum)) {\n out[ outIdx++ ] = data[ dataIndex ]\n }\n }\n }\n }\n }\n // Add terminator\n out[ outIdx ] = -1\n }\n return {\n neighbourListLength: neighbourListLength,\n withinRadii: withinRadii\n }\n}\n\ninterface AVSurface {\n getSurface: (type: string, probeRadius: number, scaleFactor: number, cutoff: number, setAtomID: boolean, smooth: number, contour: boolean) => any\n}\nfunction AVSurface (this: AVSurface, coordList: Float32Array, radiusList: Float32Array, indexList: Uint16Array|Uint32Array) {\n // Field generation method adapted from AstexViewer (Mike Hartshorn)\n // by Fred Ludlow.\n // Other parts based heavily on NGL (Alexander Rose) EDT Surface class\n //\n // Should work as a drop-in alternative to EDTSurface (though some of\n // the EDT paramters are not relevant in this method).\n\n const nAtoms = radiusList.length\n\n const x = new Float32Array(nAtoms)\n const y = new Float32Array(nAtoms)\n const z = new Float32Array(nAtoms)\n\n for (let i = 0; i < nAtoms; i++) {\n const ci = 3 * i\n x[ i ] = coordList[ ci ]\n y[ i ] = coordList[ ci + 1 ]\n z[ i ] = coordList[ ci + 2 ]\n }\n\n let bbox = computeBoundingBox(coordList)\n if (coordList.length === 0) {\n bbox[ 0 ].set([ 0, 0, 0 ])\n bbox[ 1 ].set([ 0, 0, 0 ])\n }\n const min = bbox[0]\n const max = bbox[1]\n\n let r: Float32Array, r2: Float32Array // Atom positions, expanded radii (squared)\n let maxRadius: number\n\n // Parameters\n let probeRadius: number, scaleFactor: number, setAtomID: boolean, probePositions: number\n\n // Cache last value for obscured test\n let lastClip = -1\n\n // Grid params\n let dim: Float32Array, matrix: Float32Array, grid: NumberArray, atomIndex: Int32Array\n\n // grid indices -> xyz coords\n let gridx: Float32Array, gridy: Float32Array, gridz: Float32Array\n\n // Lookup tables:\n let sinTable: Float32Array, cosTable: Float32Array\n\n // Spatial Hash\n let hash: iAVHash\n\n // Neighbour array to be filled by hash\n let neighbours: Int32Array\n\n // Vectors for Torus Projection\n const atob = new Float32Array([ 0.0, 0.0, 0.0 ])\n const mid = new Float32Array([ 0.0, 0.0, 0.0 ])\n const n1 = new Float32Array([ 0.0, 0.0, 0.0 ])\n const n2 = new Float32Array([ 0.0, 0.0, 0.0 ])\n\n let ngTorus: number\n\n function init (_probeRadius?: number, _scaleFactor?: number, _setAtomID?: boolean, _probePositions?: number) {\n probeRadius = defaults(_probeRadius, 1.4)\n scaleFactor = defaults(_scaleFactor, 2.0)\n setAtomID = defaults(_setAtomID, true)\n probePositions = defaults(_probePositions, 30)\n\n r = new Float32Array(nAtoms)\n r2 = new Float32Array(nAtoms)\n\n for (let i = 0; i < r.length; ++i) {\n var rExt = radiusList[ i ] + probeRadius\n r[ i ] = rExt\n r2[ i ] = rExt * rExt\n }\n\n maxRadius = 0\n for (let j = 0; j < r.length; ++j) {\n if (r[ j ] > maxRadius) maxRadius = r[ j ]\n }\n\n initializeGrid()\n initializeAngleTables()\n initializeHash()\n\n lastClip = -1\n }\n\n function fillGridDim (a: Float32Array, start: number, step: number) {\n for (let i = 0; i < a.length; i++) {\n a[i] = start + (step * i)\n }\n }\n\n function initializeGrid () {\n const surfGrid = getSurfaceGrid(\n min, max, maxRadius, scaleFactor, 0.0\n )\n\n scaleFactor = surfGrid.scaleFactor\n dim = surfGrid.dim\n matrix = surfGrid.matrix\n\n ngTorus = Math.max(5, 2 + Math.floor(probeRadius * scaleFactor))\n\n grid = uniformArray(dim[0] * dim[1] * dim[2], -1001.0)\n\n atomIndex = new Int32Array(grid.length)\n\n gridx = new Float32Array(dim[0])\n gridy = new Float32Array(dim[1])\n gridz = new Float32Array(dim[2])\n\n fillGridDim(gridx, min[0], 1 / scaleFactor)\n fillGridDim(gridy, min[1], 1 / scaleFactor)\n fillGridDim(gridz, min[2], 1 / scaleFactor)\n }\n\n function initializeAngleTables () {\n var theta = 0.0\n var step = 2 * Math.PI / probePositions\n\n cosTable = new Float32Array(probePositions)\n sinTable = new Float32Array(probePositions)\n for (var i = 0; i < probePositions; i++) {\n cosTable[ i ] = Math.cos(theta)\n sinTable[ i ] = Math.sin(theta)\n theta += step\n }\n }\n\n function initializeHash () {\n hash = makeAVHash(x, y, z, r, min, max, 2.01 * maxRadius)\n neighbours = new Int32Array(hash.neighbourListLength)\n }\n\n function obscured (x: number, y: number, z: number, a: number, b: number) {\n // Is the point at x,y,z obscured by any of the atoms\n // specifeid by indices in neighbours. Ignore indices\n // a and b (these are the relevant atoms in projectPoints/Torii)\n\n // Cache the last clipped atom (as very often the same one in\n // subsequent calls)\n let ai: number\n\n if (lastClip !== -1) {\n ai = lastClip\n if (ai !== a && ai !== b && singleAtomObscures(ai, x, y, z)) {\n return ai\n } else {\n lastClip = -1\n }\n }\n\n var ni = 0\n ai = neighbours[ ni ]\n while (ai >= 0) {\n if (ai !== a && ai !== b && singleAtomObscures(ai, x, y, z)) {\n lastClip = ai\n return ai\n }\n ai = neighbours[ ++ni ]\n }\n\n lastClip = -1\n\n return -1\n }\n\n function singleAtomObscures (ai: number, x: number, y: number, z: number) {\n var ci = 3 * ai\n var ra2 = r2[ ai ]\n var dx = coordList[ ci ] - x\n var dy = coordList[ ci + 1 ] - y\n var dz = coordList[ ci + 2 ] - z\n var d2 = dx * dx + dy * dy + dz * dz\n\n return d2 < ra2\n }\n\n function projectPoints () {\n // For each atom:\n // Iterate over a subsection of the grid, for each point:\n // If current value < 0.0, unvisited, set positive\n //\n // In any case: Project this point onto surface of the atomic sphere\n // If this projected point is not obscured by any other atom\n // Calcualte delta distance and set grid value to minimum of\n // itself and delta\n\n // Should we alias frequently accessed closure variables??\n // Assume JS engine capable of optimizing this\n // anyway...\n\n for (var i = 0; i < nAtoms; i++) {\n var ax = x[ i ]\n var ay = y[ i ]\n var az = z[ i ]\n var ar = r[ i ]\n var ar2 = r2[ i ]\n\n hash.withinRadii(ax, ay, az, ar, neighbours)\n\n // Number of grid points, round this up...\n var ng = Math.ceil(ar * scaleFactor)\n\n // Center of the atom, mapped to grid points (take floor)\n var iax = Math.floor(scaleFactor * (ax - min[ 0 ]))\n var iay = Math.floor(scaleFactor * (ay - min[ 1 ]))\n var iaz = Math.floor(scaleFactor * (az - min[ 2 ]))\n\n // Extents of grid to consider for this atom\n var minx = Math.max(0, iax - ng)\n var miny = Math.max(0, iay - ng)\n var minz = Math.max(0, iaz - ng)\n\n // Add two to these points:\n // - iax are floor'd values so this ensures coverage\n // - these are loop limits (exclusive)\n var maxx = Math.min(dim[ 0 ], iax + ng + 2)\n var maxy = Math.min(dim[ 1 ], iay + ng + 2)\n var maxz = Math.min(dim[ 2 ], iaz + ng + 2)\n\n for (var ix = minx; ix < maxx; ix++) {\n var dx = gridx[ ix ] - ax\n var xoffset = dim[ 1 ] * dim[ 2 ] * ix\n\n for (var iy = miny; iy < maxy; iy++) {\n var dy = gridy[ iy ] - ay\n var dxy2 = dx * dx + dy * dy\n var xyoffset = xoffset + dim[ 2 ] * iy\n\n for (var iz = minz; iz < maxz; iz++) {\n var dz = gridz[ iz ] - az\n var d2 = dxy2 + dz * dz\n\n if (d2 < ar2) {\n var idx = iz + xyoffset\n\n if (grid[idx] < 0.0) {\n // Unvisited, make positive\n grid[ idx ] = -grid[ idx ]\n }\n // Project on to the surface of the sphere\n // sp is the projected point ( dx, dy, dz ) * ( ra / d )\n var d = Math.sqrt(d2)\n var ap = ar / d\n var spx = dx * ap\n var spy = dy * ap\n var spz = dz * ap\n\n spx += ax\n spy += ay\n spz += az\n\n if (obscured(spx, spy, spz, i, -1) === -1) {\n var dd = ar - d\n if (dd < grid[ idx ]) {\n grid[ idx ] = dd\n if (setAtomID) atomIndex[ idx ] = i\n }\n }\n }\n }\n }\n }\n }\n }\n\n function projectTorii () {\n for (var i = 0; i < nAtoms; i++) {\n hash.withinRadii(x[ i ], y[ i ], z[ i ], r[ i ], neighbours)\n var ia = 0\n var ni = neighbours[ ia ]\n while (ni >= 0) {\n if (i < ni) {\n projectTorus(i, ni)\n }\n ni = neighbours[ ++ia ]\n }\n }\n }\n\n function projectTorus (a: number, b: number) {\n var r1 = r[ a ]\n var r2 = r[ b ]\n var dx = atob[ 0 ] = x[ b ] - x[ a ]\n var dy = atob[ 1 ] = y[ b ] - y[ a ]\n var dz = atob[ 2 ] = z[ b ] - z[ a ]\n var d2 = dx * dx + dy * dy + dz * dz\n\n // This check now redundant as already done in AVHash.withinRadii\n // if( d2 > (( r1 + r2 ) * ( r1 + r2 )) ){ return; }\n\n var d = Math.sqrt(d2)\n\n // Find angle between a->b vector and the circle\n // of their intersection by cosine rule\n var cosA = (r1 * r1 + d * d - r2 * r2) / (2.0 * r1 * d)\n\n // distance along a->b at intersection\n var dmp = r1 * cosA\n\n v3normalize(atob, atob)\n\n // Create normal to line\n normalToLine(n1 as any, atob)\n v3normalize(n1, n1)\n\n // Cross together for second normal vector\n v3cross(n2, atob, n1)\n v3normalize(n2, n2)\n\n // r is radius of circle of intersection\n var rInt = Math.sqrt(r1 * r1 - dmp * dmp)\n\n v3multiplyScalar(n1, n1, rInt)\n v3multiplyScalar(n2, n2, rInt)\n v3multiplyScalar(atob, atob, dmp)\n\n mid[ 0 ] = atob[ 0 ] + x[ a ]\n mid[ 1 ] = atob[ 1 ] + y[ a ]\n mid[ 2 ] = atob[ 2 ] + z[ a ]\n\n lastClip = -1\n\n var ng = ngTorus\n\n for (var i = 0; i < probePositions; i++) {\n var cost = cosTable[ i ]\n var sint = sinTable[ i ]\n\n var px = mid[ 0 ] + cost * n1[ 0 ] + sint * n2[ 0 ]\n var py = mid[ 1 ] + cost * n1[ 1 ] + sint * n2[ 1 ]\n var pz = mid[ 2 ] + cost * n1[ 2 ] + sint * n2[ 2 ]\n\n if (obscured(px, py, pz, a, b) === -1) {\n // As above, iterate over our grid...\n // px, py, pz in grid coords\n var iax = Math.floor(scaleFactor * (px - min[ 0 ]))\n var iay = Math.floor(scaleFactor * (py - min[ 1 ]))\n var iaz = Math.floor(scaleFactor * (pz - min[ 2 ]))\n\n var minx = Math.max(0, iax - ng)\n var miny = Math.max(0, iay - ng)\n var minz = Math.max(0, iaz - ng)\n\n var maxx = Math.min(dim[ 0 ], iax + ng + 2)\n var maxy = Math.min(dim[ 1 ], iay + ng + 2)\n var maxz = Math.min(dim[ 2 ], iaz + ng + 2)\n\n for (var ix = minx; ix < maxx; ix++) {\n dx = px - gridx[ ix ]\n var xoffset = dim[ 1 ] * dim[ 2 ] * ix\n\n for (var iy = miny; iy < maxy; iy++) {\n dy = py - gridy[ iy ]\n var dxy2 = dx * dx + dy * dy\n var xyoffset = xoffset + dim[ 2 ] * iy\n\n for (var iz = minz; iz < maxz; iz++) {\n dz = pz - gridz[ iz ]\n d2 = dxy2 + dz * dz\n var idx = iz + xyoffset\n var current = grid[ idx ]\n\n if (current > 0.0 && d2 < (current * current)) {\n grid[ idx ] = Math.sqrt(d2)\n if (setAtomID) {\n // Is this grid point closer to a or b?\n // Take dot product of atob and gridpoint->p (dx, dy, dz)\n const dp = dx * atob[ 0 ] + dy * atob [ 1 ] + dz * atob[ 2 ]\n atomIndex[ idx ] = dp < 0.0 ? b : a\n }\n }\n }\n }\n }\n }\n }\n }\n\n function normalToLine (out: Int32Array, p: Float32Array) {\n out[ 0 ] = out[ 1 ] = out[ 2 ] = 1.0\n if (p[ 0 ] !== 0) {\n out[ 0 ] = (p[ 1 ] + p[ 2 ]) / -p[ 0 ]\n } else if (p[ 1 ] !== 0) {\n out[ 1 ] = (p[ 0 ] + p[ 2 ]) / -p[ 1 ]\n } else if (p[ 2 ] !== 0) {\n out[ 2 ] = (p[ 0 ] + p[ 1 ]) / -p[ 2 ]\n }\n return out\n }\n\n function fixNegatives () {\n for (var i = 0; i < grid.length; i++) {\n if (grid[ i ] < 0) grid[ i ] = 0\n }\n }\n\n function fixAtomIDs () {\n for (var i = 0; i < atomIndex.length; i++) {\n atomIndex[ i ] = indexList[ atomIndex[ i ] ]\n }\n }\n\n function getVolume (probeRadius: number, scaleFactor: number, setAtomID: boolean) {\n // Basic steps are:\n // 1) Initialize\n // 2) Project points\n // 3) Project torii\n\n console.time('AVSurface.getVolume')\n\n console.time('AVSurface.init')\n init(probeRadius, scaleFactor, setAtomID)\n console.timeEnd('AVSurface.init')\n\n console.time('AVSurface.projectPoints')\n projectPoints()\n console.timeEnd('AVSurface.projectPoints')\n\n console.time('AVSurface.projectTorii')\n projectTorii()\n console.timeEnd('AVSurface.projectTorii')\n fixNegatives()\n fixAtomIDs()\n\n console.timeEnd('AVSurface.getVolume')\n }\n\n this.getSurface = function (type: string, probeRadius: number, scaleFactor: number, cutoff: number, setAtomID: boolean, smooth: number, contour: boolean) {\n // type and cutoff left in for compatibility with EDTSurface.getSurface\n // function signature\n\n getVolume(probeRadius, scaleFactor, setAtomID)\n\n var volsurf = new (VolumeSurface as any)(\n grid, dim[ 2 ], dim[ 1 ], dim[ 0 ], atomIndex\n ) as VolumeSurface\n\n return volsurf.getSurface!(probeRadius, false, undefined, matrix, contour)\n }\n}\nObject.assign(AVSurface, {__deps: [\n getSurfaceGrid, VolumeSurface, uniformArray, computeBoundingBox,\n v3multiplyScalar, v3cross, v3normalize,\n makeAVHash,\n defaults\n]})\n\nexport { AVSurface, makeAVHash }\n","/**\n * @file Molecular Surface\n * @author Alexander Rose \n * @private\n */\n\nimport { WorkerRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport Worker from '../worker/worker'\nimport EDTSurface from './edt-surface'\nimport { AVSurface } from './av-surface'\nimport Surface, { SurfaceData } from './surface'\nimport { Structure } from '../ngl';\nimport { AtomData, RadiusParams } from '../structure/structure-data';\n\nWorkerRegistry.add('molsurf', function func (e: any, callback: (data: any, buffers: any[])=> void) {\n const a = e.data.args\n const p = e.data.params\n if (a && p) {\n const SurfClass = (p.type === 'av') ? AVSurface : EDTSurface\n const surf = new (SurfClass as any)(a.coordList, a.radiusList, a.indexList) as AVSurface|EDTSurface\n const sd = surf.getSurface(\n p.type, p.probeRadius, p.scaleFactor, p.cutoff, true, p.smooth, p.contour\n ) as SurfaceData\n const transferList = [ sd.position.buffer, sd.index!.buffer ]\n if (sd.normal) transferList.push(sd.normal.buffer)\n if (sd.atomindex) transferList.push(sd.atomindex.buffer)\n const data = {\n sd: sd,\n p: p\n }\n callback(data, transferList)\n }\n}, [ EDTSurface, AVSurface ])\n\n/**\n * Molecular surface parameter object.\n * @typedef {Object} MolecularSurfaceParameters - stage parameters\n * @property {String} type - \"av\" or \"edt\"\n * @property {Number} probeRadius - probe radius\n * @property {Number} scaleFactor - higher for better quality\n * @property {Integer} smooth - number of smoothing cycles to apply\n * @property {String} name - name for created surface\n */\nexport interface MolecularSurfaceParameters {\n type: 'av'|'edt'\n probeRadius: number\n scaleFactor: number\n smooth: number\n name: string\n cutoff: number\n contour: boolean,\n radiusParams: RadiusParams\n}\n/**\n * Create Molecular surfaces\n */\nclass MolecularSurface {\n structure: Structure\n worker: Worker|undefined\n\n constructor (structure: Structure) {\n this.structure = structure\n }\n\n _getAtomData (params: Partial): AtomData {\n return this.structure.getAtomData({\n what: { position: true, radius: true, index: true },\n radiusParams: defaults(params.radiusParams, {\n type: 'vdw', scale: 1.0\n })\n })\n }\n\n _makeSurface (sd: SurfaceData, p: Partial) {\n var surface = new Surface(p.name!, '', sd)\n\n surface.info.type = p.type\n surface.info.probeRadius = p.probeRadius\n surface.info.scaleFactor = p.scaleFactor\n surface.info.smooth = p.smooth\n surface.info.cutoff = p.cutoff\n\n return surface\n }\n\n /**\n * Get molecular surface\n * @param {MolecularSurfaceParameters} params - parameters for surface creation\n * @return {Surface} the surface\n */\n getSurface (params: Partial) {\n const p = params || {}\n\n const atomData = this._getAtomData(params)\n const coordList = atomData.position\n const radiusList = atomData.radius\n const indexList = atomData.index\n\n const SurfClass = (p.type === 'av') ? AVSurface : EDTSurface\n const surf = new (SurfClass as any)(coordList, radiusList, indexList) as AVSurface|EDTSurface\n const sd = surf.getSurface(\n p.type!, p.probeRadius!, p.scaleFactor!, p.cutoff!, true, p.smooth!, p.contour!\n )\n\n return this._makeSurface(sd, p)\n }\n\n /**\n * Get molecular surface asynchronous\n * @param {MolecularSurfaceParameters} params - parameters for surface creation\n * @param {function(surface: Surface)} callback - function to be called after surface is created\n * @return {undefined}\n */\n getSurfaceWorker (params: MolecularSurfaceParameters, callback: (s: Surface) => void) {\n const p = Object.assign({}, params)\n\n if (window.hasOwnProperty('Worker')) {\n if (this.worker === undefined) {\n this.worker = new Worker('molsurf')\n }\n\n const atomData = this._getAtomData(params)\n const coordList = atomData.position\n const radiusList = atomData.radius\n const indexList = atomData.index\n\n const msg = {\n args: {\n coordList: coordList,\n radiusList: radiusList,\n indexList: indexList\n },\n params: p\n }\n\n const transferList = [\n coordList!.buffer, radiusList!.buffer, indexList!.buffer\n ]\n\n this.worker.post(msg, transferList,\n\n (e: any) => {\n callback(this._makeSurface(e.data.sd, p))\n },\n\n (e: string) => {\n console.warn(\n 'MolecularSurface.getSurfaceWorker error - trying without worker', e\n )\n this.worker!.terminate()\n this.worker = undefined\n const surface = this.getSurface(p)\n callback(surface)\n }\n\n )\n } else {\n const surface = this.getSurface(p)\n callback(surface)\n }\n }\n\n /**\n * Cleanup\n * @return {undefined}\n */\n dispose () {\n if (this.worker) this.worker.terminate()\n }\n}\n\nexport default MolecularSurface\n","/**\n * @file Molecular Surface Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport MolecularSurface, { MolecularSurfaceParameters } from '../surface/molecular-surface'\nimport SurfaceBuffer from '../buffer/surface-buffer'\nimport ContourBuffer from '../buffer/contour-buffer'\nimport DoubleSidedBuffer from '../buffer/doublesided-buffer'\nimport Selection from '../selection/selection'\nimport Viewer from '../viewer/viewer';\n// @ts-ignore: unused import Volume required for declaration only\nimport { Structure, Vector3, Volume } from '../ngl';\nimport StructureView from '../structure/structure-view';\nimport { SurfaceDataFields } from './surface-representation';\nimport Surface, {SurfaceData} from '../surface/surface';\n\nexport interface MolecularSurfaceRepresentationParameters extends StructureRepresentationParameters {\n surfaceType: 'vws'|'sas'|'ms'|'ses'|'av'\n probeRadius: number\n smooth: number\n scaleFactor: number\n cutoff: number\n contour: boolean\n background: boolean\n opaqueBack: boolean\n filterSele: string\n colorVolume: any\n useWorker: boolean\n}\n\nexport interface MolecularSurfaceInfo {\n molsurf?: MolecularSurface\n sele?: string\n surface?: Surface\n}\n\n/**\n * Molecular Surface Representation\n */\nclass MolecularSurfaceRepresentation extends StructureRepresentation {\n protected surfaceType: 'vws'|'sas'|'ms'|'ses'|'av'\n protected probeRadius: number\n protected smooth: number\n protected scaleFactor: number\n protected cutoff: number\n protected contour: boolean\n protected background: boolean\n protected opaqueBack: boolean\n protected filterSele: string\n protected colorVolume: any\n protected useWorker: boolean\n\n protected __infoList: MolecularSurfaceInfo[]\n protected __forceNewMolsurf: boolean\n protected __sele: string\n protected __surfaceParams: string\n\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'surface'\n\n this.parameters = Object.assign({\n\n surfaceType: {\n type: 'select',\n rebuild: true,\n options: {\n 'vws': 'vws',\n 'sas': 'sas',\n 'ms': 'ms',\n 'ses': 'ses',\n 'av': 'av'\n }\n },\n probeRadius: {\n type: 'number',\n precision: 1,\n max: 20,\n min: 0,\n rebuild: true\n },\n smooth: {\n type: 'integer',\n precision: 1,\n max: 10,\n min: 0,\n rebuild: true\n },\n scaleFactor: {\n type: 'number',\n precision: 1,\n max: 5,\n min: 0,\n rebuild: true\n },\n cutoff: {\n type: 'number',\n precision: 2,\n max: 50,\n min: 0,\n rebuild: true\n },\n contour: {\n type: 'boolean', rebuild: true\n },\n background: {\n type: 'boolean', rebuild: true // FIXME\n },\n opaqueBack: {\n type: 'boolean', buffer: true\n },\n filterSele: {\n type: 'text', rebuild: true\n },\n colorVolume: {\n type: 'hidden'\n },\n useWorker: {\n type: 'boolean', rebuild: true\n }\n\n }, this.parameters, {\n\n radius: null,\n scale: null\n\n })\n\n this.__infoList = []\n\n // TODO find a more direct way\n this.structure.signals.refreshed.add(() => {\n this.__forceNewMolsurf = true\n })\n\n this.toBePrepared = true\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n p.colorScheme = defaults(p.colorScheme, 'uniform')\n p.colorValue = defaults(p.colorValue, 0xDDDDDD)\n p.disablePicking = defaults(p.disablePicking, true)\n\n this.surfaceType = defaults(p.surfaceType, 'ms')\n this.probeRadius = defaults(p.probeRadius, 1.4)\n this.smooth = defaults(p.smooth, 2)\n this.scaleFactor = defaults(p.scaleFactor, 2.0)\n this.cutoff = defaults(p.cutoff, 0.0)\n this.contour = defaults(p.contour, false)\n this.background = defaults(p.background, false)\n this.opaqueBack = defaults(p.opaqueBack, true)\n this.filterSele = defaults(p.filterSele, '')\n this.colorVolume = defaults(p.colorVolume, undefined)\n this.useWorker = defaults(p.useWorker, true)\n\n super.init(params)\n }\n\n prepareData (sview: StructureView, i: number, callback: (i: number) => void) {\n let info: MolecularSurfaceInfo = this.__infoList[ i ]\n if (!info) {\n info = {}\n this.__infoList[ i ] = info\n }\n\n if (!info.molsurf || info.sele !== sview.selection.string) {\n if (this.filterSele) {\n const sviewFilter = sview.structure.getView(new Selection(this.filterSele))\n const bbSize = sviewFilter.boundingBox.getSize(new Vector3())\n const maxDim = Math.max(bbSize.x, bbSize.y, bbSize.z)\n const asWithin = sview.getAtomSetWithinPoint(sviewFilter.center, (maxDim / 2) + 6.0)\n sview = sview.getView(\n new Selection(sview.getAtomSetWithinSelection(asWithin, 3).toSeleString())\n )\n if (sview.atomCount === 0) {\n callback(i)\n return\n }\n }\n\n info.sele = sview.selection.string\n info.molsurf = new MolecularSurface(sview)\n\n const p = this.getSurfaceParams()\n const onSurfaceFinish = (surface: Surface) => {\n info.surface = surface\n callback(i)\n }\n\n if (this.useWorker) {\n info.molsurf.getSurfaceWorker(p as MolecularSurfaceParameters, onSurfaceFinish)\n } else {\n onSurfaceFinish(info.molsurf.getSurface(p as {name: string, type: 'av'|'edt' } & MolecularSurfaceRepresentationParameters))\n }\n } else {\n callback(i)\n }\n }\n\n prepare (callback: () => void) {\n if (this.__forceNewMolsurf || this.__sele !== this.selection.string ||\n this.__surfaceParams !== JSON.stringify(this.getSurfaceParams())) {\n this.__infoList.forEach((info: MolecularSurfaceInfo) => {\n if (info && info.molsurf) {\n info.molsurf.dispose()\n }\n })\n this.__infoList.length = 0\n }\n\n if (this.structureView.atomCount === 0) {\n callback()\n return\n }\n\n const after = () => {\n this.__sele = this.selection.string\n this.__surfaceParams = JSON.stringify(this.getSurfaceParams())\n this.__forceNewMolsurf = false\n callback()\n }\n\n const name = this.assembly === 'default' ? this.defaultAssembly : this.assembly\n const assembly = this.structure.biomolDict[ name ]\n\n if (assembly) {\n assembly.partList.forEach((part, i) => {\n const sview = part.getView(this.structureView)\n this.prepareData(sview as StructureView, i, (_i) => {\n if (_i === assembly.partList.length - 1) after()\n })\n })\n } else {\n this.prepareData(this.structureView, 0, after)\n }\n }\n\n createData (sview: StructureView, i: number) {\n const info = this.__infoList[ i ]\n const surface = info.surface\n\n if (!surface) {\n // Surface creation bailed (no surface generated for this sview)\n return\n }\n\n const surfaceData = {\n position: surface!.getPosition(),\n color: surface!.getColor(this.getColorParams()),\n index: surface!.getFilteredIndex(this.filterSele, sview)\n }\n\n const bufferList = []\n\n if (surface.contour) {\n const contourBuffer = new ContourBuffer(\n surfaceData,\n this.getBufferParams({\n wireframe: false\n })\n )\n\n bufferList.push(contourBuffer)\n } else {\n Object.assign(surfaceData, {\n normal: surface.getNormal(),\n picking: surface.getPicking(sview.getStructure())\n })\n\n const surfaceBuffer = new SurfaceBuffer(\n surfaceData,\n this.getBufferParams({\n background: this.background,\n opaqueBack: this.opaqueBack,\n dullInterior: false\n })\n )\n\n if (this.getBufferParams().side == 'double') {\n const doubleSidedBuffer = new DoubleSidedBuffer(surfaceBuffer)\n bufferList.push(doubleSidedBuffer)\n }\n else {\n bufferList.push(surfaceBuffer)\n }\n }\n\n return { bufferList, info } as StructureRepresentationData\n }\n\n updateData (what: SurfaceDataFields, data: StructureRepresentationData) {\n const surfaceData: Partial = {}\n\n if (what.position || what.radius) {\n this.__forceNewMolsurf = true\n this.build()\n return\n }\n\n if (what.color) {\n surfaceData.color = data.info.surface.getColor(this.getColorParams())\n }\n\n if (what.index) {\n surfaceData.index = data.info.surface.getFilteredIndex(this.filterSele, data.sview)\n }\n\n data.bufferList[ 0 ].setAttributes(surfaceData)\n }\n\n setParameters (params: Partial, what: Partial = {}, rebuild?: boolean) {\n if (params && params.filterSele) {\n what.index = true\n }\n\n if (params && params.colorVolume !== undefined) {\n what.color = true\n }\n\n // forbid setting wireframe to true when contour is true\n if (params && params.wireframe && (\n params.contour || (params.contour === undefined && this.contour)\n )\n ) {\n params.wireframe = false\n }\n\n super.setParameters(params, what, rebuild)\n\n return this\n }\n\n getSurfaceParams (params: Partial = {}) {\n const p = Object.assign({\n type: this.surfaceType as string,\n probeRadius: this.probeRadius as number,\n scaleFactor: this.scaleFactor as number,\n smooth: this.smooth && !this.contour,\n cutoff: this.cutoff as number,\n contour: this.contour as boolean,\n useWorker: this.useWorker as boolean,\n radiusParams: this.getRadiusParams()\n }, params)\n\n return p\n }\n\n getColorParams () {\n const p = super.getColorParams()\n\n p.volume = this.colorVolume\n\n return p\n }\n\n getAtomRadius () {\n return 0\n }\n\n clear () {\n super.clear()\n }\n\n dispose () {\n this.__infoList.forEach((info: MolecularSurfaceInfo) => {\n if (info && info.molsurf) {\n info.molsurf.dispose()\n }\n })\n this.__infoList.length = 0\n\n super.dispose()\n }\n}\n\nRepresentationRegistry.add('surface', MolecularSurfaceRepresentation)\n\nexport default MolecularSurfaceRepresentation\n","/**\n * @file Point Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport PointBuffer from '../buffer/point-buffer'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport StructureView from '../structure/structure-view';\nimport { AtomDataFields } from '../structure/structure-data';\n\nexport interface PointRepresentationParameters extends StructureRepresentationParameters {\n pointSize: number\n sizeAttenuation: boolean\n sortParticles: boolean\n useTexture: boolean\n alphaTest: number\n forceTransparent: boolean\n edgeBleach: number\n}\n\n/**\n * Point Representation\n */\nclass PointRepresentation extends StructureRepresentation {\n protected pointSize: number\n protected sizeAttenuation: boolean\n protected sortParticles: boolean\n protected useTexture: boolean\n protected alphaTest: number\n protected forceTransparent: boolean\n protected edgeBleach: number\n\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'point'\n\n this.parameters = Object.assign({\n\n pointSize: {\n type: 'number', precision: 1, max: 100, min: 0, buffer: true\n },\n sizeAttenuation: {\n type: 'boolean', buffer: true\n },\n sortParticles: {\n type: 'boolean', rebuild: true\n },\n useTexture: {\n type: 'boolean', buffer: true\n },\n alphaTest: {\n type: 'range', step: 0.001, max: 1, min: 0, buffer: true\n },\n forceTransparent: {\n type: 'boolean', buffer: true\n },\n edgeBleach: {\n type: 'range', step: 0.001, max: 1, min: 0, buffer: true\n }\n\n }, this.parameters, {\n\n flatShaded: null,\n wireframe: null,\n linewidth: null,\n side: null,\n\n roughness: null,\n metalness: null\n\n })\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n\n this.pointSize = defaults(p.pointSize, 1)\n this.sizeAttenuation = defaults(p.sizeAttenuation, true)\n this.sortParticles = defaults(p.sortParticles, false)\n this.useTexture = defaults(p.useTexture, false)\n this.alphaTest = defaults(p.alphaTest, 0.5)\n this.forceTransparent = defaults(p.forceTransparent, false)\n this.edgeBleach = defaults(p.edgeBleach, 0.0)\n\n super.init(p)\n }\n\n createData (sview: StructureView) {\n var what = { position: true, color: true, picking: true }\n var atomData = sview.getAtomData(this.getAtomParams(what))\n\n var pointBuffer = new PointBuffer(\n atomData,\n this.getBufferParams({\n pointSize: this.pointSize,\n sizeAttenuation: this.sizeAttenuation,\n sortParticles: this.sortParticles,\n useTexture: this.useTexture,\n alphaTest: this.alphaTest,\n forceTransparent: this.forceTransparent,\n edgeBleach: this.edgeBleach\n })\n )\n\n return {\n bufferList: [ pointBuffer ]\n }\n }\n\n updateData (what: AtomDataFields, data: StructureRepresentationData) {\n var atomData = data.sview!.getAtomData(this.getAtomParams(what))\n var pointData = {}\n\n if (!what || what.position) {\n Object.assign(pointData, {position: atomData.position})\n }\n\n if (!what || what.color) {\n Object.assign(pointData, {color: atomData.color})\n }\n\n data.bufferList[ 0 ].setAttributes(pointData)\n }\n\n getAtomRadius () {\n return 0.1\n }\n}\n\nRepresentationRegistry.add('point', PointRepresentation)\n\nexport default PointRepresentation\n","/**\n * @file Ribbon Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport '../shader/Ribbon.vert'\n\nimport { getUintArray } from '../utils'\nimport { serialArray } from '../math/array-utils'\nimport MeshBuffer from './mesh-buffer'\nimport { BufferParameters, BufferData } from './buffer'\nimport {Log} from \"../globals\";\n\nconst quadIndices = new Uint16Array([\n 0, 1, 2,\n 1, 3, 2\n])\n\nexport interface RibbonBufferData extends BufferData {\n normal: Float32Array\n dir: Float32Array\n size: Float32Array\n}\n\nfunction getSize(data: RibbonBufferData){\n const n = (data.position!.length / 3) - 1\n const n4 = n * 4\n const x = n4 * 3\n return x\n}\n\n/**\n * Ribbon buffer. Draws a thin ribbon.\n */\nclass RibbonBuffer extends MeshBuffer {\n vertexShader = 'Ribbon.vert'\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.normal - normals\n * @param {Float32Array} data.dir - binormals\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} data.size - sizes\n * @param {Picker} data.picking - picking ids\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: RibbonBufferData, params: Partial = {}) {\n super({\n position: new Float32Array(getSize(data)),\n color: new Float32Array(getSize(data)),\n index: getUintArray(getSize(data), getSize(data) / 3),\n normal: new Float32Array(getSize(data)),\n picking: data.picking\n }, params)\n\n const n = (data.position!.length / 3) - 1\n const n4 = n * 4\n const x = n4 * 3\n\n this.addAttributes({\n 'dir': { type: 'v3', value: new Float32Array(x) }\n })\n this.addAttributes({\n 'size': { type: 'f', value: new Float32Array(n4) }\n })\n\n data.primitiveId = serialArray(n)\n this.setAttributes(data)\n\n this.makeIndex()\n }\n\n setAttributes (data: Partial = {}) {\n const n4 = this.size\n const n = n4 / 4\n\n const attributes = this.geometry.attributes as any // TODO\n\n let position, normal, size, dir, color, primitiveId\n let aPosition, aNormal, aSize, aDir, aColor, aPrimitiveId\n\n if (data.position) {\n position = data.position\n aPosition = attributes.position.array\n attributes.position.needsUpdate = true\n }\n\n if (data.normal) {\n normal = data.normal\n aNormal = attributes.normal.array\n attributes.normal.needsUpdate = true\n }\n\n if (data.size) {\n size = data.size\n aSize = attributes.size.array\n attributes.size.needsUpdate = true\n }\n\n if (data.dir) {\n dir = data.dir\n aDir = attributes.dir.array\n attributes.dir.needsUpdate = true\n }\n\n if (data.color) {\n color = data.color\n aColor = attributes.color.array\n attributes.color.needsUpdate = true\n }\n\n if (data.primitiveId) {\n primitiveId = data.primitiveId\n aPrimitiveId = attributes.primitiveId.array\n attributes.primitiveId.needsUpdate = true\n }\n\n let v, i, k, p, l, v3\n let currSize\n let prevSize = size ? size[ 0 ] : null\n\n for (v = 0; v < n; ++v) {\n v3 = v * 3\n k = v * 3 * 4\n l = v * 4\n\n if (position) {\n aPosition[ k ] = aPosition[ k + 3 ] = position[ v3 ]\n aPosition[ k + 1 ] = aPosition[ k + 4 ] = position[ v3 + 1 ]\n aPosition[ k + 2 ] = aPosition[ k + 5 ] = position[ v3 + 2 ]\n\n aPosition[ k + 6 ] = aPosition[ k + 9 ] = position[ v3 + 3 ]\n aPosition[ k + 7 ] = aPosition[ k + 10 ] = position[ v3 + 4 ]\n aPosition[ k + 8 ] = aPosition[ k + 11 ] = position[ v3 + 5 ]\n }\n\n if (normal) {\n aNormal[ k ] = aNormal[ k + 3 ] = -normal[ v3 ]\n aNormal[ k + 1 ] = aNormal[ k + 4 ] = -normal[ v3 + 1 ]\n aNormal[ k + 2 ] = aNormal[ k + 5 ] = -normal[ v3 + 2 ]\n\n aNormal[ k + 6 ] = aNormal[ k + 9 ] = -normal[ v3 + 3 ]\n aNormal[ k + 7 ] = aNormal[ k + 10 ] = -normal[ v3 + 4 ]\n aNormal[ k + 8 ] = aNormal[ k + 11 ] = -normal[ v3 + 5 ]\n }\n\n for (i = 0; i < 4; ++i) {\n p = k + 3 * i\n\n if (color) {\n aColor[ p ] = color[ v3 ]\n aColor[ p + 1 ] = color[ v3 + 1 ]\n aColor[ p + 2 ] = color[ v3 + 2 ]\n }\n\n if (primitiveId) {\n aPrimitiveId[ l + i ] = primitiveId[ v ]\n }\n }\n\n if (size) {\n currSize = size[ v ]\n\n if (prevSize !== size[ v ]) {\n aSize[ l ] = prevSize\n aSize[ l + 1 ] = prevSize\n aSize[ l + 2 ] = currSize\n aSize[ l + 3 ] = currSize\n } else {\n aSize[ l ] = currSize\n aSize[ l + 1 ] = currSize\n aSize[ l + 2 ] = currSize\n aSize[ l + 3 ] = currSize\n }\n\n prevSize = currSize\n }\n\n if (dir) {\n aDir[ k ] = dir[ v3 ]\n aDir[ k + 1 ] = dir[ v3 + 1 ]\n aDir[ k + 2 ] = dir[ v3 + 2 ]\n\n aDir[ k + 3 ] = -dir[ v3 ]\n aDir[ k + 4 ] = -dir[ v3 + 1 ]\n aDir[ k + 5 ] = -dir[ v3 + 2 ]\n\n aDir[ k + 6 ] = dir[ v3 + 3 ]\n aDir[ k + 7 ] = dir[ v3 + 4 ]\n aDir[ k + 8 ] = dir[ v3 + 5 ]\n\n aDir[ k + 9 ] = -dir[ v3 + 3 ]\n aDir[ k + 10 ] = -dir[ v3 + 4 ]\n aDir[ k + 11 ] = -dir[ v3 + 5 ]\n }\n }\n }\n\n makeIndex () {\n const index = this.geometry.getIndex()\n if (!index) { Log.error('Index is null'); return; }\n const meshIndex = index.array as Uint32Array|Uint16Array\n const n = meshIndex.length / 4 / 3\n\n for (let v = 0; v < n; ++v) {\n const ix = v * 6\n const it = v * 4\n\n meshIndex.set(quadIndices, ix)\n for (let s = 0; s < 6; ++s) {\n meshIndex[ ix + s ] += it\n }\n }\n }\n}\n\nexport default RibbonBuffer\n","/**\n * @file Ribbon Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport Spline, { SplineParameters } from '../geometry/spline'\nimport StructureRepresentation, { StructureRepresentationParameters } from './structure-representation'\nimport RibbonBuffer from '../buffer/ribbon-buffer'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport AtomProxy from '../proxy/atom-proxy';\nimport StructureView from '../structure/structure-view';\nimport Polymer from '../proxy/polymer';\n\nexport interface RibbonRepresentationParameters extends StructureRepresentationParameters {\n subdiv: number\n tension: number\n smoothSheet: boolean\n}\n\n/**\n * Ribbon Representation\n */\nclass RibbonRepresentation extends StructureRepresentation {\n protected subdiv: number\n protected tension: number\n protected smoothSheet: boolean\n \n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'ribbon'\n\n this.parameters = Object.assign({\n\n subdiv: {\n type: 'integer', max: 50, min: 1, rebuild: true\n },\n tension: {\n type: 'number', precision: 1, max: 1.0, min: 0.1\n },\n smoothSheet: {\n type: 'boolean', rebuild: true\n }\n\n }, this.parameters, {\n\n side: null,\n wireframe: null,\n linewidth: null\n\n })\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n p.colorScheme = defaults(p.colorScheme, 'chainname')\n p.colorScale = defaults(p.colorScale, 'RdYlBu')\n p.radiusType = defaults(p.radiusType, 'sstruc')\n p.radiusScale = defaults(p.radiusScale, 4.0)\n\n if (p.quality === 'low') {\n this.subdiv = 3\n } else if (p.quality === 'medium') {\n this.subdiv = 6\n } else if (p.quality === 'high') {\n this.subdiv = 12\n } else {\n this.subdiv = defaults(p.subdiv, 6)\n }\n\n this.tension = defaults(p.tension, NaN)\n this.smoothSheet = defaults(p.smoothSheet, false)\n\n super.init(p)\n }\n\n getSplineParams (params?: Partial) {\n return Object.assign({\n subdiv: this.subdiv,\n tension: this.tension,\n directional: true,\n smoothSheet: this.smoothSheet\n }, params)\n }\n\n getAtomRadius (atom: AtomProxy) {\n return atom.isTrace() ? super.getAtomRadius(atom) : 0\n }\n\n createData (sview: StructureView) {\n var bufferList: RibbonBuffer[] = []\n var polymerList: Polymer[] = []\n\n this.structure.eachPolymer(polymer => {\n if (polymer.residueCount < 4) return\n polymerList.push(polymer)\n\n var spline = new Spline(polymer, this.getSplineParams())\n var subPos = spline.getSubdividedPosition()\n var subOri = spline.getSubdividedOrientation()\n var subCol = spline.getSubdividedColor(this.getColorParams())\n var subPick = spline.getSubdividedPicking()\n var subSize = spline.getSubdividedSize(this.getRadiusParams())\n\n bufferList.push(\n new RibbonBuffer(\n ({\n position: subPos.position,\n normal: subOri.binormal,\n dir: subOri.normal,\n color: subCol.color,\n size: subSize.size,\n picking: subPick.picking\n }),\n this.getBufferParams()\n )\n )\n }, sview.getSelection())\n\n return {\n bufferList: bufferList,\n polymerList: polymerList\n }\n }\n\n updateData (what: {position?: boolean, radius?: boolean, scale?: boolean, color?: boolean}, data: {polymerList: Polymer[], bufferList: RibbonBuffer[]}) {\n what = what || {}\n\n var i = 0\n var n = data.polymerList.length\n\n for (i = 0; i < n; ++i) {\n var bufferData = {}\n var spline = new Spline(data.polymerList[ i ], this.getSplineParams())\n\n if (what.position) {\n var subPos = spline.getSubdividedPosition()\n var subOri = spline.getSubdividedOrientation()\n Object.assign(bufferData, {\n position: subPos.position,\n normal: subOri.binormal,\n dir: subOri.normal\n })\n }\n\n if (what.radius || what.scale) {\n var subSize = spline.getSubdividedSize(this.getRadiusParams())\n Object.assign(bufferData, {size: subSize.size})\n }\n\n if (what.color) {\n var subCol = spline.getSubdividedColor(this.getColorParams())\n Object.assign(bufferData, {color: subCol.color})\n }\n\n data.bufferList[ i ].setAttributes(bufferData)\n }\n }\n\n setParameters (params: Partial) {\n var rebuild = false\n var what = {}\n\n if (params && params.tension) {\n Object.assign(what, {position: true})\n }\n\n super.setParameters(params, what, rebuild)\n\n return this\n }\n}\n\nRepresentationRegistry.add('ribbon', RibbonRepresentation)\n\nexport default RibbonRepresentation\n","/**\n * @file Rocket Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport { AtomPicker } from '../utils/picker'\nimport StructureRepresentation, { StructureRepresentationParameters } from './structure-representation'\nimport Helixbundle, { Axis } from '../geometry/helixbundle'\nimport CylinderBuffer from '../buffer/cylinder-buffer'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport StructureView from '../structure/structure-view';\nimport CylinderGeometryBuffer from '../buffer/cylindergeometry-buffer';\nimport CylinderImpostorBuffer from '../buffer/cylinderimpostor-buffer';\n\nexport interface RocketRepresentationParameters extends StructureRepresentationParameters {\n localAngle: number\n centerDist: number\n ssBorder: boolean\n radialSegments: number\n openEnded: boolean\n disableImpostor: boolean\n}\n\nexport interface AxisData {\n begin: Float32Array\n end: Float32Array\n size: Float32Array\n color: Float32Array\n picking: AtomPicker\n}\n\n/**\n * Rocket Representation\n */\nclass RocketRepresentation extends StructureRepresentation {\n\n protected localAngle: number\n protected centerDist: number\n protected ssBorder: boolean\n protected radialSegments: number\n protected openEnded: boolean\n protected disableImpostor: boolean\n // protected helixbundleList: Helixbundle[]\n\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'rocket'\n\n this.parameters = Object.assign({\n\n localAngle: {\n type: 'integer', max: 180, min: 0, rebuild: true\n },\n centerDist: {\n type: 'number', precision: 1, max: 10, min: 0, rebuild: true\n },\n ssBorder: {\n type: 'boolean', rebuild: true\n },\n radialSegments: true,\n openEnded: true,\n disableImpostor: true\n\n }, this.parameters)\n\n // this.helixbundleList = []\n\n this.init(params)\n }\n\n init (params: Partial) {\n let p = params || {}\n p.colorScheme = defaults(p.colorScheme, 'sstruc')\n p.radiusSize = defaults(p.radiusSize, 1.5)\n p.radiusScale = defaults(p.radiusScale, 1.0)\n p.openEnded = defaults(p.openEnded, false)\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n this.localAngle = defaults(p.localAngle, 30)\n this.centerDist = defaults(p.centerDist, 2.5)\n this.ssBorder = defaults(p.ssBorder, false)\n\n super.init(p)\n }\n\n createData (sview: StructureView) {\n let length = 0\n const axisList:Axis[] = []\n const helixbundleList:Helixbundle[] = []\n\n this.structure.eachPolymer(polymer => {\n if (polymer.residueCount < 4 || polymer.isNucleic()) return\n\n const helixbundle = new Helixbundle(polymer)\n const axis = helixbundle.getAxis(\n this.localAngle, this.centerDist, this.ssBorder,\n this.getColorParams(), this.getRadiusParams()\n )\n\n length += axis.size.length\n axisList.push(axis)\n helixbundleList.push(helixbundle)\n }, sview.getSelection())\n\n const axisData = {\n begin: new Float32Array(length * 3),\n end: new Float32Array(length * 3),\n size: new Float32Array(length),\n color: new Float32Array(length * 3),\n picking: {}\n }\n\n let picking = new Float32Array(length)\n\n let offset = 0\n\n axisList.forEach(function (axis) {\n axisData.begin.set(axis.begin, offset * 3)\n axisData.end.set(axis.end, offset * 3)\n axisData.size.set(axis.size, offset)\n axisData.color.set(axis.color, offset * 3)\n picking.set(axis.picking.array!, offset)\n offset += axis.size.length\n })\n\n if (length) {\n axisData.picking = new AtomPicker(\n picking, sview.getStructure()\n )\n }\n\n const cylinderBuffer = new CylinderBuffer(\n {\n position1: axisData.begin,\n position2: axisData.end,\n color: axisData.color,\n color2: axisData.color,\n radius: axisData.size,\n picking: axisData.picking\n },\n this.getBufferParams({\n openEnded: this.openEnded,\n radialSegments: this.radialSegments,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n })\n )\n\n return {\n bufferList: [ cylinderBuffer as CylinderGeometryBuffer|CylinderImpostorBuffer ],\n axisList: axisList,\n helixbundleList: helixbundleList,\n axisData: axisData\n }\n }\n\n \n updateData (what: any, data: {bufferList: CylinderBuffer[], helixbundleList: Helixbundle[], axisList: Axis[], axisData: AxisData}) {\n what = what || {}\n\n if (what.position) {\n this.build()\n return\n }\n\n var cylinderData = {}\n\n if (what.color || what.radius) {\n var offset = 0\n\n data.helixbundleList.forEach((helixbundle) => {\n var axis = helixbundle.getAxis(\n this.localAngle, this.centerDist, this.ssBorder,\n this.getColorParams(), this.getRadiusParams()\n )\n if (what.color) {\n data.axisData.color.set(axis.color, offset * 3)\n }\n if (what.radius || what.scale) {\n data.axisData.size.set(axis.size, offset)\n }\n offset += axis.size.length\n })\n\n if (what.color) {\n Object.assign(cylinderData, {\n color: data.axisData.color,\n color2: data.axisData.color\n })\n }\n\n if (what.radius || what.scale) {\n Object.assign(cylinderData, {\n radius: data.axisData.size\n })\n }\n }\n\n (data.bufferList[ 0 ] as CylinderGeometryBuffer).setAttributes(cylinderData)\n }\n}\n\nRepresentationRegistry.add('rocket', RocketRepresentation)\n\nexport default RocketRepresentation\n","/**\n * @file Rope Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport CartoonRepresentation, { CartoonRepresentationParameters } from './cartoon-representation'\nimport Helixorient from '../geometry/helixorient'\nimport Spline from '../geometry/spline'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport Polymer from '../proxy/polymer';\n\n/**\n * Rope Representation\n */\nclass RopeRepresentation extends CartoonRepresentation {\n protected smooth: number\n \n constructor (structure: Structure, viewer: Viewer, params: Partial&{smooth: number}) {\n super(structure, viewer, params)\n\n this.type = 'rope'\n\n this.parameters = Object.assign({\n\n smooth: {\n type: 'integer', max: 15, min: 0, rebuild: true\n }\n\n }, this.parameters, {\n aspectRatio: null,\n smoothSheet: null\n })\n }\n\n init (params: Partial) {\n var p = params || {}\n p.aspectRatio = 1.0\n p.tension = defaults(p.tension, 0.5)\n p.radiusScale = defaults(p.radiusScale, 5.0)\n p.smoothSheet = false\n\n this.smooth = defaults(p.smooth, 2)\n\n super.init(p)\n }\n\n getSpline (polymer: Polymer) {\n var helixorient = new Helixorient(polymer)\n\n return new Spline(polymer, this.getSplineParams({\n directional: false,\n positionIterator: helixorient.getCenterIterator(this.smooth)\n }))\n }\n}\n\nRepresentationRegistry.add('rope', RopeRepresentation)\n\nexport default RopeRepresentation\n","/**\n * @file Spacefill Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport { RepresentationRegistry } from '../globals'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport SphereBuffer, { SphereBufferData, SphereBufferParameters } from '../buffer/sphere-buffer'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport StructureView from '../structure/structure-view';\nimport SphereGeometryBuffer from '../buffer/spheregeometry-buffer';\nimport { AtomDataFields } from '../structure/structure-data';\nimport SphereImpostorBuffer from '../buffer/sphereimpostor-buffer';\n\n/**\n * Spacefill Representation\n */\nclass SpacefillRepresentation extends StructureRepresentation {\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'spacefill'\n\n this.parameters = Object.assign({\n sphereDetail: true,\n disableImpostor: true\n }, this.parameters)\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n super.init(p)\n }\n\n createData (sview: StructureView) {\n var sphereBuffer = new SphereBuffer(\n (sview.getAtomData(this.getAtomParams()) as SphereBufferData),\n (this.getBufferParams({\n sphereDetail: this.sphereDetail,\n dullInterior: true,\n disableImpostor: this.disableImpostor\n }) as SphereBufferParameters)\n )\n\n return {\n bufferList: [ sphereBuffer as SphereGeometryBuffer|SphereImpostorBuffer ]\n }\n }\n\n updateData (what: AtomDataFields, data: StructureRepresentationData) {\n var atomData = data.sview!.getAtomData(this.getAtomParams(what))\n var sphereData: Partial = {}\n\n if (!what || what.position) {\n Object.assign(sphereData, {position: atomData.position})\n }\n\n if (!what || what.color) {\n Object.assign(sphereData, {color: atomData.color})\n }\n\n if (!what || what.radius) {\n Object.assign(sphereData, {radius: atomData.radius})\n }\n\n data.bufferList[ 0 ].setAttributes(sphereData)\n }\n}\n\nRepresentationRegistry.add('spacefill', SpacefillRepresentation)\n\nexport default SpacefillRepresentation\n","/**\n * @file Trace Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport '../shader/Line.vert'\nimport '../shader/Line.frag'\n\nimport { Log } from '../globals'\nimport Buffer, { BufferParameters, BufferData } from './buffer'\n\nfunction getSize(data: BufferData){\n const n = data.position!.length / 3\n const n1 = n - 1\n return n1 * 3 * 2\n}\n\n/**\n * Trace buffer. Draws a series of lines.\n */\nclass TraceBuffer extends Buffer {\n isLine = true\n vertexShader = 'Line.vert'\n fragmentShader = 'Line.frag'\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.color - colors\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: BufferData, params: Partial = {}) {\n super({\n position: new Float32Array(getSize(data)),\n color: new Float32Array(getSize(data))\n }, params)\n\n this.setAttributes(data)\n }\n\n setAttributes (data: Partial) {\n let position, color\n let linePosition, lineColor\n\n const attributes = this.geometry.attributes as any // TODO\n\n if (data.position) {\n position = data.position\n linePosition = attributes.position.array\n attributes.position.needsUpdate = true\n }\n\n if (data.color) {\n color = data.color\n lineColor = attributes.color.array\n attributes.color.needsUpdate = true\n }\n\n if (!position && !color) {\n Log.warn('TraceBuffer.prototype.setAttributes no data')\n return\n }\n\n let v, v2\n const n = this.size\n const n1 = n - 1\n\n for (let i = 0; i < n1; ++i) {\n v = 3 * i\n v2 = 3 * i * 2\n\n if (position) {\n linePosition[ v2 ] = position[ v ]\n linePosition[ v2 + 1 ] = position[ v + 1 ]\n linePosition[ v2 + 2 ] = position[ v + 2 ]\n\n linePosition[ v2 + 3 ] = position[ v + 3 ]\n linePosition[ v2 + 4 ] = position[ v + 4 ]\n linePosition[ v2 + 5 ] = position[ v + 5 ]\n }\n\n if (color) {\n lineColor[ v2 ] = color[ v ]\n lineColor[ v2 + 1 ] = color[ v + 1 ]\n lineColor[ v2 + 2 ] = color[ v + 2 ]\n\n lineColor[ v2 + 3 ] = color[ v + 3 ]\n lineColor[ v2 + 4 ] = color[ v + 4 ]\n lineColor[ v2 + 5 ] = color[ v + 5 ]\n }\n }\n }\n}\n\nexport default TraceBuffer\n","/**\n * @file Trace Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport Spline from '../geometry/spline'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport TraceBuffer from '../buffer/trace-buffer'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport AtomProxy from '../proxy/atom-proxy';\nimport StructureView from '../structure/structure-view';\nimport Polymer from '../proxy/polymer';\n\nexport interface TraceRepresentationParameters extends StructureRepresentationParameters {\n subdiv: number\n tension: number\n smoothSheet: boolean\n}\n/**\n * Trace Representation\n */\nclass TraceRepresentation extends StructureRepresentation {\n protected subdiv: number\n protected tension: number\n protected smoothSheet: boolean\n \n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'trace'\n\n this.parameters = Object.assign({\n\n subdiv: {\n type: 'integer', max: 50, min: 1, rebuild: true\n },\n tension: {\n type: 'number', precision: 1, max: 1.0, min: 0.1\n },\n smoothSheet: {\n type: 'boolean', rebuild: true\n }\n\n }, this.parameters, {\n\n flatShaded: null,\n side: null,\n wireframe: null\n\n })\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n p.colorScheme = defaults(p.colorScheme, 'chainname')\n p.colorScale = defaults(p.colorScale, 'RdYlBu')\n\n if (p.quality === 'low') {\n this.subdiv = 3\n } else if (p.quality === 'medium') {\n this.subdiv = 6\n } else if (p.quality === 'high') {\n this.subdiv = 12\n } else {\n this.subdiv = defaults(p.subdiv, 6)\n }\n\n this.tension = defaults(p.tension, NaN)\n this.smoothSheet = defaults(p.smoothSheet, false)\n\n super.init(p)\n }\n\n getSplineParams (params?: {[k:string]: any}) {\n return Object.assign({\n subdiv: this.subdiv,\n tension: this.tension,\n directional: false,\n smoothSheet: this.smoothSheet\n }, params)\n }\n\n getAtomRadius (atom: AtomProxy) {\n return atom.isTrace() ? 0.1 : 0\n }\n\n createData (sview: StructureView) {\n var bufferList: TraceBuffer[] = []\n var polymerList: Polymer[] = []\n\n this.structure.eachPolymer(polymer => {\n if (polymer.residueCount < 4) return\n polymerList.push(polymer)\n\n var spline = new Spline(polymer, this.getSplineParams())\n var subPos = spline.getSubdividedPosition()\n var subCol = spline.getSubdividedColor(this.getColorParams())\n\n bufferList.push(\n new TraceBuffer(\n Object.assign({}, subPos, subCol),\n this.getBufferParams()\n )\n )\n }, sview.getSelection())\n\n return {\n bufferList: bufferList,\n polymerList: polymerList\n }\n }\n\n updateData (what: any, data: StructureRepresentationData) {\n what = what || {}\n\n var i = 0\n var n = data.polymerList!.length\n\n for (i = 0; i < n; ++i) {\n var bufferData = {}\n var spline = new Spline(data.polymerList![ i ], this.getSplineParams())\n\n if (what.position) {\n var subPos = spline.getSubdividedPosition()\n Object.assign(bufferData, { position: subPos.position })\n }\n\n if (what.color) {\n var subCol = spline.getSubdividedColor(this.getColorParams())\n Object.assign(bufferData, { color: subCol.color })\n }\n\n data.bufferList[ i ].setAttributes(bufferData)\n }\n }\n\n setParameters (params: Partial) {\n var rebuild = false\n var what = {}\n\n if (params && params.tension) {\n Object.assign(what, {position: true})\n }\n\n super.setParameters(params, what, rebuild)\n\n return this\n }\n}\n\nRepresentationRegistry.add('trace', TraceRepresentation)\n\nexport default TraceRepresentation\n","/**\n * @file Tube Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport CartoonRepresentation, {CartoonRepresentationParameters} from './cartoon-representation'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\n\n/**\n * Tube Representation\n */\nclass TubeRepresentation extends CartoonRepresentation {\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'tube'\n\n this.parameters = Object.assign(\n {}, this.parameters, { aspectRatio: null }\n )\n }\n\n init (params: Partial) {\n var p = params || {}\n p.aspectRatio = 1.0\n p.radiusScale = defaults(p.radiusScale, 2.0)\n\n if (p.quality === 'low') {\n this.radialSegments = 5\n }\n\n super.init(p)\n }\n\n getSplineParams (/* params */) {\n return super.getSplineParams({\n directional: false\n })\n }\n}\n\nRepresentationRegistry.add('tube', TubeRepresentation)\n\nexport default TubeRepresentation\n","/**\n * @file Unitcell Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport SphereBuffer, { SphereBufferData, SphereBufferParameters } from '../buffer/sphere-buffer'\nimport CylinderBuffer, { CylinderBufferData } from '../buffer/cylinder-buffer'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport { AtomDataFields } from '../structure/structure-data';\nimport StructureView from '../structure/structure-view';\nimport SphereGeometryBuffer from '../buffer/spheregeometry-buffer';\nimport CylinderGeometryBuffer from '../buffer/cylindergeometry-buffer';\n// @ts-ignore: unused import UnitcellPicker required for declaration only\nimport { UnitcellPicker } from '../utils/picker';\n\nexport interface UnitcellRepresentationParameters extends StructureRepresentationParameters {\n radiusSize: number\n sphereDetail: number\n radialSegments: number\n disableImpostor: boolean\n}\n\n/**\n * Unitcell Representation\n */\nclass UnitcellRepresentation extends StructureRepresentation {\n sphereBuffer: SphereBuffer\n cylinderBuffer: CylinderBuffer\n\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'unitcell'\n\n this.parameters = Object.assign({\n\n radiusSize: {\n type: 'number', precision: 3, max: 10.0, min: 0.001\n },\n sphereDetail: true,\n radialSegments: true,\n disableImpostor: true\n\n }, this.parameters, {\n assembly: null\n })\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n\n let defaultRadius = 0.5\n if (this.structure.unitcell) {\n defaultRadius = Math.cbrt(this.structure.unitcell.volume) / 200\n }\n\n p.radiusSize = defaults(p.radiusSize, defaultRadius)\n p.colorValue = defaults(p.colorValue, 'orange')\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n super.init(p)\n }\n\n getUnitcellData (structure: Structure) {\n return structure.unitcell!.getData(structure)\n }\n\n create () {\n const structure = this.structureView.getStructure()\n if (!structure.unitcell) return\n const unitcellData = this.getUnitcellData(structure)\n\n this.sphereBuffer = new SphereBuffer(\n unitcellData.vertex as SphereBufferData,\n this.getBufferParams({\n sphereDetail: this.sphereDetail,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n }) as SphereBufferParameters\n )\n\n this.cylinderBuffer = new CylinderBuffer(\n unitcellData.edge as CylinderBufferData,\n this.getBufferParams({\n openEnded: true,\n radialSegments: this.radialSegments,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n })\n )\n\n this.dataList.push({\n sview: this.structureView,\n bufferList: [ this.sphereBuffer as SphereGeometryBuffer, this.cylinderBuffer as CylinderGeometryBuffer ]\n })\n }\n\n createData (sview: StructureView): undefined {\n return\n }\n\n updateData (what: AtomDataFields, data: StructureRepresentationData) {\n const structure = data.sview!.getStructure()\n if (!structure.unitcell) return\n const unitcellData = this.getUnitcellData(structure)\n const sphereData: Partial = {}\n const cylinderData: Partial = {}\n\n if (!what || what.position) {\n Object.assign(sphereData, {position: unitcellData.vertex.position})\n Object.assign(cylinderData, {\n position1: unitcellData.edge.position1,\n position2: unitcellData.edge.position2\n })\n }\n\n if (!what || what.color) {\n Object.assign(sphereData, {color: unitcellData.vertex.color})\n Object.assign(cylinderData, {\n color: unitcellData.edge.color,\n color2: unitcellData.edge.color2\n })\n }\n\n if (!what || what.radius) {\n Object.assign(sphereData, {radius: unitcellData.vertex.radius})\n Object.assign(cylinderData, {radius: unitcellData.edge.radius})\n }\n\n (this.sphereBuffer as SphereGeometryBuffer).setAttributes(sphereData);\n (this.cylinderBuffer as CylinderGeometryBuffer).setAttributes(cylinderData)\n }\n}\n\nRepresentationRegistry.add('unitcell', UnitcellRepresentation)\n\nexport default UnitcellRepresentation\n","/**\n * @file Validation Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport StructureRepresentation, { StructureRepresentationParameters } from './structure-representation'\nimport CylinderBuffer from '../buffer/cylinder-buffer'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport StructureView from '../structure/structure-view';\nimport CylinderGeometryBuffer from '../buffer/cylindergeometry-buffer';\nimport CylinderImpostorBuffer from '../buffer/cylinderimpostor-buffer';\n\n/**\n * Validation representation\n */\nclass ValidationRepresentation extends StructureRepresentation {\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'validation'\n\n this.parameters = Object.assign({\n\n }, this.parameters, {\n radiusType: null,\n radiusSize: null,\n radiusScale: null\n })\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n p.colorValue = defaults(p.colorValue, '#f0027f')\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n super.init(p)\n }\n\n createData (sview: StructureView) {\n if (!sview.validation) return\n\n const clashData = sview.validation.getClashData({\n structure: sview,\n color: this.colorValue\n })\n\n const cylinderBuffer = new CylinderBuffer(\n clashData, this.getBufferParams({ openEnded: false })\n )\n\n return {\n bufferList: [ cylinderBuffer as CylinderGeometryBuffer|CylinderImpostorBuffer ]\n }\n }\n}\n\nRepresentationRegistry.add('validation', ValidationRepresentation)\n\nexport default ValidationRepresentation\n","/**\n * @file Cone Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4, Vector3, ConeBufferGeometry } from 'three'\n\nimport { BufferRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport { calculateCenterArray } from '../math/array-utils'\nimport GeometryBuffer from './geometry-buffer'\nimport { BufferData, BufferDefaultParameters } from './buffer'\n\nconst scale = new Vector3()\nconst eye = new Vector3()\nconst target = new Vector3()\nconst up = new Vector3(0, 1, 0)\n\nfunction getGeo (params: Partial = {}) {\n const geo = new ConeBufferGeometry(\n 1, // radius\n 1, // height\n defaults(params.radialSegments, 60), // radialSegments\n 1, // heightSegments\n defaults(params.openEnded, false) // openEnded\n )\n geo.applyMatrix4(new Matrix4().makeRotationX(-Math.PI / 2))\n\n return geo\n}\n\nexport interface ConeBufferData extends BufferData {\n position1: Float32Array\n position2: Float32Array\n radius: Float32Array\n}\n\nexport const ConeBufferDefaultParameters = Object.assign({\n radialSegments: 60,\n openEnded: false\n}, BufferDefaultParameters)\nexport type ConeBufferParameters = typeof ConeBufferDefaultParameters\n\n\n/**\n * Cone geometry buffer.\n *\n * @example\n * var coneBuffer = new ConeBuffer({\n * position1: new Float32Array([ 0, 0, 0 ]),\n * position2: new Float32Array([ 1, 1, 1 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * color2: new Float32Array([ 0, 1, 0 ]),\n * radius: new Float32Array([ 1 ])\n * });\n */\nclass ConeBuffer extends GeometryBuffer {\n updateNormals = true\n\n get defaultParameters() { return ConeBufferDefaultParameters }\n parameters: ConeBufferParameters\n\n _position: Float32Array\n _position1: Float32Array\n _position2: Float32Array\n _radius: Float32Array\n\n /**\n * @param {Object} data - buffer data\n * @param {Float32Array} data.position1 - from positions\n * @param {Float32Array} data.position2 - to positions\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} data.radius - radii\n * @param {Picker} [data.picking] - picking ids\n * @param {BufferParameters} [params] - parameters object\n */\n constructor (data: ConeBufferData, params: Partial = {}) {\n super({\n position: new Float32Array(data.position1.length),\n color: data.color,\n picking: data.picking\n }, params, getGeo(params))\n\n this._position = new Float32Array(data.position1.length)\n\n this.setAttributes(data, true)\n }\n\n applyPositionTransform (matrix: Matrix4, i: number, i3: number) {\n eye.fromArray(this._position1 as any, i3)\n target.fromArray(this._position2 as any, i3)\n matrix.lookAt(eye, target, up)\n\n const r = this._radius[ i ]\n scale.set(r, r, eye.distanceTo(target))\n matrix.scale(scale)\n }\n\n setAttributes (data: Partial = {}, initNormals?: boolean) {\n if (data.position1 && data.position2) {\n calculateCenterArray(data.position1, data.position2, this._position)\n this._position1 = data.position1\n this._position2 = data.position2\n data.position = this._position\n }\n if (data.radius) this._radius = data.radius\n\n super.setAttributes(data, initNormals)\n }\n}\n\nBufferRegistry.add('cone', ConeBuffer)\n\nexport default ConeBuffer\n","/**\n * @file Geometry Group\n * @author Alexander Rose \n * @private\n */\n\nimport { Box3, BufferGeometry } from 'three'\n\nclass GeometryGroup {\n geometryList: BufferGeometry[]\n boundingBox: Box3\n\n constructor (geometryList: BufferGeometry[] = []) {\n this.geometryList = geometryList\n }\n\n computeBoundingBox () {\n if (!this.boundingBox) {\n this.boundingBox = new Box3()\n } else {\n this.boundingBox.empty()\n }\n\n this.geometryList.forEach(geo => {\n if (!geo.boundingBox) geo.computeBoundingBox()\n this.boundingBox.union(geo.boundingBox as Box3)\n })\n }\n}\n\nexport default GeometryGroup\n","/**\n * @file Arrow Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4, Vector3, Group } from 'three'\n\nimport { BufferRegistry } from '../globals'\nimport { createParams, defaults } from '../utils'\nimport { Picker } from '../utils/picker'\nimport Buffer from './buffer'\nimport CylinderBuffer, { CylinderBufferData } from './cylinder-buffer'\nimport CylinderGeometryBuffer from './cylindergeometry-buffer'\nimport ConeBuffer, { ConeBufferData } from './cone-buffer'\nimport GeometryGroup from '../viewer/geometry-group'\nimport { BufferData, BufferDefaultParameters } from './buffer'\n\nexport interface ArrowBufferData extends BufferData {\n position1: Float32Array\n position2: Float32Array\n radius: Float32Array\n}\n\nexport const ArrowBufferDefaultParameters = Object.assign({\n aspectRatio: 1.5,\n radialSegments: 50,\n openEnded: false,\n disableImpostor: false\n}, BufferDefaultParameters)\nexport type ArrowBufferParameters = typeof ArrowBufferDefaultParameters\n\n/**\n * Arrow buffer. Draws arrows made from a cylinder and a cone.\n * @implements {Buffer}\n *\n * @example\n * var arrowBuffer = new ArrowBuffer({\n * position1: new Float32Array([ 0, 0, 0 ]),\n * position2: new Float32Array([ 10, 1, 1 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * radius: new Float32Array([ 1 ])\n * });\n */\nclass ArrowBuffer {\n parameters: ArrowBufferParameters\n get defaultParameters() { return ArrowBufferDefaultParameters }\n\n cylinderBuffer: CylinderGeometryBuffer\n coneBuffer: ConeBuffer\n\n splitPosition: Float32Array\n cylinderRadius: Float32Array\n\n geometry: GeometryGroup\n picking?: Picker\n\n group = new Group()\n wireframeGroup = new Group()\n pickingGroup = new Group()\n\n visible = true\n\n /**\n * @param {Object} data - buffer data\n * @param {Float32Array} data.position1 - from positions\n * @param {Float32Array} data.position2 - to positions\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} data.radius - radii\n * @param {Picker} [data.picking] - picking ids\n * @param {BufferParameters} [params] - parameters object\n */\n constructor (data: ArrowBufferData, params: Partial = {}) {\n this.parameters = createParams(params, this.defaultParameters)\n\n this.splitPosition = new Float32Array(data.position1.length)\n this.cylinderRadius = new Float32Array(data.radius.length)\n\n const attr = this.makeAttributes(data)\n const bufferParams = {\n radialSegments: this.parameters.radialSegments,\n openEnded: this.parameters.openEnded,\n disableImpostor: this.parameters.disableImpostor\n }\n\n this.cylinderBuffer = new CylinderBuffer(\n attr.cylinder as CylinderBufferData, bufferParams\n ) as CylinderGeometryBuffer\n this.coneBuffer = new ConeBuffer(\n attr.cone as ConeBufferData, bufferParams\n )\n\n this.geometry = new GeometryGroup([\n this.cylinderBuffer.geometry,\n this.coneBuffer.geometry\n ])\n\n // requires Group objects to be present\n this.matrix = defaults(params.matrix, new Matrix4())\n\n this.picking = data.picking\n }\n\n set matrix (m) {\n Buffer.prototype.setMatrix.call(this, m)\n }\n get matrix () {\n return this.group.matrix.clone()\n }\n\n get pickable () {\n return !!this.picking\n }\n\n makeAttributes (data: Partial = {}) {\n const splitPosition = this.splitPosition\n const cylinderRadius = this.cylinderRadius\n\n const aspectRatio = this.parameters.aspectRatio\n\n let i, il\n const cylinder: Partial = {}\n const cone: Partial = {}\n\n if (data.radius) {\n for (i = 0, il = cylinderRadius.length; i < il; ++i) {\n cylinderRadius[ i ] = data.radius[ i ] / aspectRatio\n }\n cylinder.radius = cylinderRadius\n cone.radius = data.radius\n }\n\n if (data.position1 && data.position2) {\n const vFrom = new Vector3()\n const vTo = new Vector3()\n const vDir = new Vector3()\n const vSplit = new Vector3()\n for (i = 0, il = splitPosition.length; i < il; i += 3) {\n vFrom.fromArray(data.position1 as any, i)\n vTo.fromArray(data.position2 as any, i)\n vDir.subVectors(vFrom, vTo)\n const fullLength = vDir.length()\n const coneLength = cylinderRadius[ i / 3 ] * aspectRatio * 2\n const length = Math.min(fullLength, coneLength)\n vDir.setLength(length)\n vSplit.copy(vTo).add(vDir)\n vSplit.toArray(splitPosition as any, i)\n }\n cylinder.position1 = data.position1\n cylinder.position2 = splitPosition\n cone.position1 = splitPosition\n cone.position2 = data.position2\n }\n\n if (data.color) {\n cylinder.color = data.color\n cylinder.color2 = data.color\n cone.color = data.color\n }\n\n return {\n cylinder: cylinder,\n cone: cone\n }\n }\n\n getMesh () {\n return new Group().add(\n this.cylinderBuffer.getMesh(),\n this.coneBuffer.getMesh()\n )\n }\n\n getWireframeMesh () {\n return new Group().add(\n this.cylinderBuffer.getWireframeMesh(),\n this.coneBuffer.getWireframeMesh()\n )\n }\n\n getPickingMesh () {\n return new Group().add(\n this.cylinderBuffer.getPickingMesh(),\n this.coneBuffer.getPickingMesh()\n )\n }\n\n setAttributes (data: Partial = {}) {\n const attr = this.makeAttributes(data)\n\n this.cylinderBuffer.setAttributes(attr.cylinder)\n this.coneBuffer.setAttributes(attr.cone)\n }\n\n /**\n * Set buffer parameters\n * @param {BufferParameters} params - buffer parameters object\n * @return {undefined}\n */\n setParameters (params: Partial = {}) {\n params = Object.assign({}, params)\n\n if (params && params.matrix !== undefined) {\n this.matrix = params.matrix\n }\n delete params.matrix\n\n if (params && params.wireframe !== undefined) {\n this.parameters.wireframe = params.wireframe\n this.setVisibility(this.visible)\n }\n\n this.cylinderBuffer.setParameters(params)\n this.coneBuffer.setParameters(params)\n }\n\n setVisibility (value: boolean) {\n Buffer.prototype.setVisibility.call(this, value)\n }\n\n dispose () {\n this.cylinderBuffer.dispose()\n this.coneBuffer.dispose()\n }\n}\n\nBufferRegistry.add('arrow', ArrowBuffer)\n\nexport default ArrowBuffer\n","/**\n * @file Box Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { BoxBufferGeometry, Vector3, Matrix4 } from 'three'\n\nimport { BufferRegistry } from '../globals'\nimport GeometryBuffer from './geometry-buffer'\nimport { BufferData, BufferParameters } from './buffer'\n\nconst scale = new Vector3()\nconst target = new Vector3()\nconst up = new Vector3()\nconst eye = new Vector3(0, 0, 0)\n\nexport interface BoxBufferData extends BufferData {\n heightAxis: Float32Array\n depthAxis: Float32Array\n size: Float32Array\n}\n\n/**\n * Box buffer. Draws boxes.\n *\n * @example\n * var boxBuffer = new BoxBuffer({\n * position: new Float32Array([ 0, 3, 0, -2, 0, 0 ]),\n * color: new Float32Array([ 1, 0, 1, 0, 1, 0 ]),\n * size: new Float32Array([ 2, 1.5 ]),\n * heightAxis: new Float32Array([ 0, 1, 1, 0, 2, 0 ]),\n * depthAxis: new Float32Array([ 1, 0, 1, 0, 0, 2 ])\n * })\n */\nclass BoxBuffer extends GeometryBuffer {\n updateNormals = true\n\n _heightAxis: Float32Array\n _depthAxis: Float32Array\n _size: Float32Array\n\n constructor (data: BoxBufferData, params: Partial = {}) {\n super(data, params, new BoxBufferGeometry(1, 1, 1))\n\n this.setAttributes(data, true)\n }\n\n applyPositionTransform (matrix: Matrix4, i: number, i3: number) {\n target.fromArray(this._heightAxis as any, i3)\n up.fromArray(this._depthAxis as any, i3)\n matrix.lookAt(eye, target, up)\n\n scale.set(this._size[ i ], up.length(), target.length())\n matrix.scale(scale)\n }\n\n setAttributes (data: Partial = {}, initNormals?: boolean) {\n if (data.size) this._size = data.size\n if (data.heightAxis) this._heightAxis = data.heightAxis\n if (data.depthAxis) this._depthAxis = data.depthAxis\n\n super.setAttributes(data, initNormals)\n }\n}\n\nBufferRegistry.add('box', BoxBuffer)\n\nexport default BoxBuffer\n","/**\n * @file Ellipsoid Geometry Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { IcosahedronBufferGeometry, Vector3, Matrix4 } from 'three'\n\nimport { BufferRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport GeometryBuffer from './geometry-buffer'\nimport { BufferData, BufferDefaultParameters } from './buffer'\n\nconst scale = new Vector3()\nconst target = new Vector3()\nconst up = new Vector3()\nconst eye = new Vector3(0, 0, 0)\n\nexport interface EllipsoidBufferData extends BufferData {\n majorAxis: Float32Array\n minorAxis: Float32Array\n radius: Float32Array\n}\n\nexport const EllipsoidBufferDefaultParameters = Object.assign({\n sphereDetail: 2,\n}, BufferDefaultParameters)\nexport type EllipsoidBufferParameters = typeof EllipsoidBufferDefaultParameters\n\n/**\n * Ellipsoid buffer. Draws ellipsoids.\n *\n * @example\n * var ellipsoidBuffer = new EllipsoidBuffer({\n * position: new Float32Array([ 0, 0, 0 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * radius: new Float32Array([ 1 ]),\n * majorAxis: new Float32Array([ 1, 1, 0 ]),\n * minorAxis: new Float32Array([ 0.5, 0, 0.5 ]),\n * });\n */\nclass EllipsoidBuffer extends GeometryBuffer {\n updateNormals = true\n\n get defaultParameters() { return EllipsoidBufferDefaultParameters }\n parameters: EllipsoidBufferParameters\n\n _majorAxis: Float32Array\n _minorAxis: Float32Array\n _radius: Float32Array\n\n constructor (data: EllipsoidBufferData, params: Partial = {}) {\n super(data, params, new IcosahedronBufferGeometry(1, defaults(params.sphereDetail, 2)))\n\n this.setAttributes(data, true)\n }\n\n applyPositionTransform (matrix: Matrix4, i: number, i3: number) {\n target.fromArray(this._majorAxis as any, i3)\n up.fromArray(this._minorAxis as any, i3)\n matrix.lookAt(eye, target, up)\n\n scale.set(this._radius[ i ], up.length(), target.length())\n matrix.scale(scale)\n }\n\n setAttributes (data: Partial = {}, initNormals?: boolean) {\n if (data.radius) this._radius = data.radius\n if (data.majorAxis) this._majorAxis = data.majorAxis\n if (data.minorAxis) this._minorAxis = data.minorAxis\n\n super.setAttributes(data, initNormals)\n }\n}\n\nBufferRegistry.add('ellipsoid', EllipsoidBuffer)\n\nexport default EllipsoidBuffer\n","/**\n * @file Octahedron Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { OctahedronBufferGeometry, Vector3, Matrix4 } from 'three'\nimport { BufferRegistry } from '../globals'\nimport GeometryBuffer from './geometry-buffer'\nimport { BufferData, BufferParameters } from './buffer'\n\nconst scale = new Vector3()\nconst target = new Vector3()\nconst up = new Vector3()\nconst eye = new Vector3(0, 0, 0)\n\nexport interface OctahedronBufferData extends BufferData {\n heightAxis: Float32Array\n depthAxis: Float32Array\n size: Float32Array\n}\n\n/**\n * Octahedron buffer. Draws octahedrons.\n *\n * @example\n * var octahedronBuffer = new OctahedronBuffer({\n * position: new Float32Array([ 0, 3, 0, -2, 0, 0 ]),\n * color: new Float32Array([ 1, 0, 1, 0, 1, 0 ]),\n * size: new Float32Array([ 2, 1.5 ]),\n * heightAxis: new Float32Array([ 0, 1, 1, 0, 2, 0 ]),\n * depthAxis: new Float32Array([ 1, 0, 1, 0, 0, 2 ])\n * })\n */\nclass OctahedronBuffer extends GeometryBuffer {\n updateNormals = true\n\n _heightAxis: Float32Array\n _depthAxis: Float32Array\n _size: Float32Array\n\n constructor (data: OctahedronBufferData, params: Partial = {}) {\n super(data, params, new OctahedronBufferGeometry(1, 0))\n\n this.setAttributes(data, true)\n }\n\n applyPositionTransform (matrix: Matrix4, i: number, i3: number) {\n target.fromArray(this._heightAxis as any, i3)\n up.fromArray(this._depthAxis as any, i3)\n matrix.lookAt(eye, target, up)\n\n scale.set(this._size[ i ], up.length(), target.length())\n matrix.scale(scale)\n }\n\n setAttributes (data: Partial = {}, initNormals?: boolean) {\n if (data.size) this._size = data.size\n if (data.heightAxis) this._heightAxis = data.heightAxis\n if (data.depthAxis) this._depthAxis = data.depthAxis\n\n super.setAttributes(data, initNormals)\n }\n}\n\nBufferRegistry.add('octahedron', OctahedronBuffer)\n\nexport default OctahedronBuffer\n","/**\n * @file Tetrahedron Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { TetrahedronBufferGeometry, Vector3, Matrix4 } from 'three'\nimport { BufferRegistry } from '../globals'\nimport GeometryBuffer from './geometry-buffer'\nimport { BufferData, BufferParameters } from './buffer'\n\nconst scale = new Vector3()\nconst target = new Vector3()\nconst up = new Vector3()\nconst eye = new Vector3(0, 0, 0)\n\nexport interface TetrahedronBufferData extends BufferData {\n heightAxis: Float32Array\n depthAxis: Float32Array\n size: Float32Array\n}\n\n/**\n * Tetrahedron buffer. Draws tetrahedrons.\n *\n * @example\n * var tetrahedronBuffer = new TetrahedronBuffer({\n * position: new Float32Array([ 0, 3, 0, -2, 0, 0 ]),\n * color: new Float32Array([ 1, 0, 1, 0, 1, 0 ]),\n * size: new Float32Array([ 2, 1.5 ]),\n * heightAxis: new Float32Array([ 0, 1, 1, 0, 2, 0 ]),\n * depthAxis: new Float32Array([ 1, 0, 1, 0, 0, 2 ])\n * })\n */\nclass TetrahedronBuffer extends GeometryBuffer {\n updateNormals = true\n\n _heightAxis: Float32Array\n _depthAxis: Float32Array\n _size: Float32Array\n\n constructor (data: TetrahedronBufferData, params: Partial = {}) {\n super(data, params, new TetrahedronBufferGeometry(1, 0))\n\n this.setAttributes(data, true)\n }\n\n applyPositionTransform (matrix: Matrix4, i: number, i3: number) {\n target.fromArray(this._heightAxis as any, i3)\n up.fromArray(this._depthAxis as any, i3)\n matrix.lookAt(eye, target, up)\n\n scale.set(this._size[ i ], up.length(), target.length())\n matrix.scale(scale)\n }\n\n setAttributes (data: Partial = {}, initNormals?: boolean) {\n if (data.size) this._size = data.size\n if (data.heightAxis) this._heightAxis = data.heightAxis\n if (data.depthAxis) this._depthAxis = data.depthAxis\n\n super.setAttributes(data, initNormals)\n }\n}\n\nBufferRegistry.add('tetrahedron', TetrahedronBuffer)\n\nexport default TetrahedronBuffer\n","/**\n * @file Tetrahedron Geometry Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { TorusBufferGeometry, Vector3, Matrix4 } from 'three'\n\nimport { BufferRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport GeometryBuffer from './geometry-buffer'\nimport { BufferDefaultParameters, BufferData } from './buffer'\n\nconst scale = new Vector3()\nconst target = new Vector3()\nconst up = new Vector3()\nconst eye = new Vector3(0, 0, 0)\n\nexport interface TorusBufferData extends BufferData {\n majorAxis: Float32Array\n minorAxis: Float32Array\n radius: Float32Array\n}\n\nexport const TorusBufferDefaultParameters = Object.assign({\n radiusRatio: 0.2,\n radialSegments: 16,\n tubularSegments: 32\n}, BufferDefaultParameters)\nexport type TorusBufferParameters = typeof TorusBufferDefaultParameters\n\n/**\n * Torus geometry buffer. Draws torii.\n *\n * @example\n * var torusBuffer = new TorusBuffer({\n * position: new Float32Array([ 0, 0, 0 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * radius: new Float32Array([ 1 ]),\n * majorAxis: new Float32Array([ 1, 1, 0 ]),\n * minorAxis: new Float32Array([ 0.5, 0, 0.5 ]),\n * });\n */\nclass TorusBuffer extends GeometryBuffer {\n updateNormals = true\n\n get defaultParameters() { return TorusBufferDefaultParameters }\n parameters: TorusBufferParameters\n\n _majorAxis: Float32Array\n _minorAxis: Float32Array\n _radius: Float32Array\n\n constructor (data: TorusBufferData, params: Partial = {}) {\n super(data, params, new TorusBufferGeometry(\n 1,\n defaults(params.radiusRatio, 0.2),\n defaults(params.radialSegments, 16),\n defaults(params.tubularSegments, 32)\n ))\n\n this.setAttributes(data, true)\n }\n\n applyPositionTransform (matrix: Matrix4, i: number, i3: number) {\n target.fromArray(this._majorAxis as any, i3)\n up.fromArray(this._minorAxis as any, i3)\n matrix.lookAt(eye, target, up)\n\n const r = this._radius[ i ]\n scale.set(r, r, r)\n matrix.scale(scale)\n }\n\n setAttributes (data: Partial = {}, initNormals?: boolean) {\n if (data.radius) this._radius = data.radius\n if (data.majorAxis) this._majorAxis = data.majorAxis\n if (data.minorAxis) this._minorAxis = data.minorAxis\n\n super.setAttributes(data, initNormals)\n }\n}\n\nBufferRegistry.add('torus', TorusBuffer)\n\nexport default TorusBuffer\n","/**\n * @file Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log } from '../globals'\nimport { defaults } from '../utils'\nimport Streamer from '../streamer/streamer';\n\nexport interface ParserParameters {\n name: string\n path: string\n}\n\nclass Parser {\n streamer: Streamer\n name: string\n path: string\n [k: string]: any\n \n constructor (streamer: Streamer, params?: Partial) {\n var p = params || {}\n\n this.streamer = streamer\n\n this.name = defaults(p.name, '')\n this.path = defaults(p.path, '')\n }\n\n get type () { return '' }\n get __objName () { return '' }\n get isBinary () { return false }\n get isJson () { return false }\n get isXml () { return false }\n\n parse () {\n return this.streamer.read().then(() => {\n this._beforeParse()\n this._parse()\n this._afterParse()\n return this[ this.__objName ]\n })\n }\n\n _parse () {}\n\n _beforeParse () {}\n\n _afterParse () {\n if (Debug) Log.log(this[ this.__objName ])\n }\n}\n\nexport default Parser\n","/**\n * @file Structure Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport Parser, { ParserParameters } from './parser'\nimport Structure from '../structure/structure'\nimport StructureBuilder from '../structure/structure-builder'\nimport Streamer from '../streamer/streamer';\n\nexport interface StructureParserParameters extends ParserParameters {\n firstModelOnly: boolean\n asTrajectory: boolean\n cAlphaOnly: boolean\n}\nclass StructureParser extends Parser {\n\n structureBuilder: StructureBuilder\n\n constructor (streamer: Streamer, params?: Partial) {\n var p = params || {}\n\n super(streamer, p)\n\n this.firstModelOnly = defaults(p.firstModelOnly, false)\n this.asTrajectory = defaults(p.asTrajectory, false)\n this.cAlphaOnly = defaults(p.cAlphaOnly, false)\n\n this.structure = new Structure(this.name, this.path)\n this.structureBuilder = new StructureBuilder(this.structure)\n }\n\n get type () { return 'structure' }\n get __objName () { return 'structure' }\n}\n\nexport default StructureParser\n","/**\n * @file Entity\n * @author Alexander Rose \n * @private\n */\n\nimport Structure from './structure'\nimport {\n UnknownEntity, PolymerEntity, NonPolymerEntity, MacrolideEntity, WaterEntity\n} from './structure-constants'\nimport ChainProxy from '../proxy/chain-proxy'\n\nfunction entityTypeFromString (string: string) {\n string = string.toLowerCase()\n switch (string) {\n case 'polymer':\n return PolymerEntity\n case 'non-polymer':\n return NonPolymerEntity\n case 'macrolide':\n return MacrolideEntity\n case 'water':\n return WaterEntity\n default:\n return UnknownEntity\n }\n}\n\nfunction entityFromType (type: number) {\n switch (type) {\n case PolymerEntity:\n return 'polymer'\n case NonPolymerEntity:\n return 'non-polymer'\n case MacrolideEntity:\n return 'macrolide'\n case WaterEntity:\n return 'water'\n default:\n return undefined\n }\n}\n\nexport const EntityTypeString = {\n 'polymer': PolymerEntity,\n 'non-polymer': NonPolymerEntity,\n 'macrolide': MacrolideEntity,\n 'water': WaterEntity,\n}\nexport type EntityTypeString = keyof typeof EntityTypeString\n\n/**\n * Entity of a {@link Structure}\n */\nexport default class Entity {\n structure: Structure\n index: number\n description: string\n entityType: number\n chainIndexList: number[]\n\n /**\n * @param {Structure} structure - structure the entity belongs to\n * @param {Integer} index - index within structure.entityList\n * @param {String} description - entity description\n * @param {String} type - entity type\n * @param {Array} chainIndexList - entity chainIndexList\n */\n constructor (structure: Structure, index: number, description = '', type?: EntityTypeString, chainIndexList: number[] = []) {\n this.structure = structure\n this.index = index\n this.description = description\n this.entityType = entityTypeFromString(type || '')\n this.chainIndexList = chainIndexList\n\n chainIndexList.forEach(function (ci: number) {\n structure.chainStore.entityIndex[ ci ] = index\n })\n }\n\n get type () { return entityFromType(this.entityType) }\n\n getEntityType () {\n return this.entityType\n }\n\n isPolymer () {\n return this.entityType === PolymerEntity\n }\n\n isNonPolymer () {\n return this.entityType === NonPolymerEntity\n }\n\n isMacrolide () {\n return this.entityType === MacrolideEntity\n }\n\n isWater () {\n return this.entityType === WaterEntity\n }\n\n eachChain (callback: (cp: ChainProxy) => any) {\n const cp = this.structure.getChainProxy()\n\n this.chainIndexList.forEach(function (index) {\n cp.index = index\n callback(cp)\n })\n }\n}","/**\n * @file Unitcell\n * @author Alexander Rose \n * @private\n */\n\nimport { Color, Vector3, Matrix4 } from 'three'\n\nimport { defaults } from '../utils'\nimport { degToRad } from '../math/math-utils'\nimport {\n uniformArray, uniformArray3, centerArray3\n} from '../math/array-utils'\nimport { UnitcellPicker } from '../utils/picker'\nimport Structure from '../structure/structure'\n\nexport interface UnitcellParams {\n a: number\n b: number\n c: number\n alpha: number\n beta: number\n gamma: number\n spacegroup: string\n cartToFrac?: Matrix4\n}\n\nconst DefaultBoxParams = {\n a: 1,\n b: 1,\n c: 1,\n alpha: 90,\n beta: 90,\n gamma: 90,\n spacegroup: 'P 1'\n}\n\nexport interface UnitcellDataParams {\n colorValue?: string|number,\n radius?: number\n}\n\n/**\n * Unitcell class\n */\nclass Unitcell {\n a: number\n b: number\n c: number\n alpha: number\n beta: number\n gamma: number\n\n spacegroup: string\n\n cartToFrac = new Matrix4()\n fracToCart = new Matrix4()\n\n volume: number\n\n /**\n * @param {Object} params - unitcell parameters\n * @param {Number} params.a - length a\n * @param {Number} params.b - length b\n * @param {Number} params.c - length c\n * @param {Number} params.alpha - angle alpha\n * @param {Number} params.beta - angle beta\n * @param {Number} params.gamma - angle gamma\n * @param {String} params.spacegroup - spacegroup\n * @param {Matrix4} [params.cartToFrac] - transformation matrix from\n * cartesian to fractional coordinates\n * @param {Matrix4} [params.scale] - alias for `params.cartToFrac`\n */\n constructor (params: UnitcellParams = DefaultBoxParams) {\n this.a = params.a\n this.b = params.b\n this.c = params.c\n this.alpha = params.alpha\n this.beta = params.beta\n this.gamma = params.gamma\n this.spacegroup = params.spacegroup\n\n const alphaRad = degToRad(this.alpha)\n const betaRad = degToRad(this.beta)\n const gammaRad = degToRad(this.gamma)\n const cosAlpha = Math.cos(alphaRad)\n const cosBeta = Math.cos(betaRad)\n const cosGamma = Math.cos(gammaRad)\n const sinBeta = Math.sin(betaRad)\n const sinGamma = Math.sin(gammaRad)\n\n this.volume = (\n this.a * this.b * this.c *\n Math.sqrt(\n 1 - cosAlpha * cosAlpha - cosBeta * cosBeta - cosGamma * cosGamma +\n 2.0 * cosAlpha * cosBeta * cosGamma\n )\n )\n\n if (params.cartToFrac === undefined) {\n // https://github.com/biojava/biojava/blob/master/biojava-structure/src/main/java/org/biojava/nbio/structure/xtal/CrystalCell.java\n\n const cStar = (this.a * this.b * sinGamma) / this.volume\n const cosAlphaStar = (\n (cosBeta * cosGamma - cosAlpha) / (sinBeta * sinGamma)\n )\n\n this.fracToCart.set(\n this.a, 0, 0, 0,\n this.b * cosGamma, this.b * sinGamma, 0, 0,\n this.c * cosBeta, -this.c * sinBeta * cosAlphaStar, 1.0 / cStar, 0,\n 0, 0, 0, 1\n ).transpose()\n this.cartToFrac.getInverse(this.fracToCart)\n } else {\n this.cartToFrac.copy(params.cartToFrac)\n this.fracToCart.getInverse(this.cartToFrac)\n }\n }\n\n getPosition (structure: Structure): Float32Array {\n const vertexPosition = new Float32Array(3 * 8)\n\n if (structure.unitcell) {\n const uc = structure.unitcell\n const centerFrac = structure.center.clone().applyMatrix4(uc.cartToFrac).floor()\n const v = new Vector3()\n\n let cornerOffset = 0\n const addCorner = function (x: number, y: number, z: number) {\n v.set(x, y, z)\n .add(centerFrac)\n .applyMatrix4(uc.fracToCart)\n .toArray(vertexPosition as any, cornerOffset)\n cornerOffset += 3\n }\n addCorner(0, 0, 0)\n addCorner(1, 0, 0)\n addCorner(0, 1, 0)\n addCorner(0, 0, 1)\n addCorner(1, 1, 0)\n addCorner(1, 0, 1)\n addCorner(0, 1, 1)\n addCorner(1, 1, 1)\n }\n\n return vertexPosition\n }\n\n getCenter (structure: Structure) {\n return centerArray3(this.getPosition(structure))\n }\n\n getData (structure: Structure, params: UnitcellDataParams = {}) {\n const colorValue = defaults(params.colorValue, 'orange')\n const radius = defaults(params.radius, Math.cbrt(this.volume) / 200)\n\n const c = new Color(colorValue)\n const v = new Vector3()\n\n const vertexPosition = this.getPosition(structure)\n const vertexColor = uniformArray3(8, c.r, c.g, c.b)\n const vertexRadius = uniformArray(8, radius)\n\n const edgePosition1 = new Float32Array(3 * 12)\n const edgePosition2 = new Float32Array(3 * 12)\n const edgeColor = uniformArray3(12, c.r, c.g, c.b)\n const edgeRadius = uniformArray(12, radius)\n\n let edgeOffset = 0\n function addEdge (a: number, b: number) {\n v.fromArray(vertexPosition as any, a * 3)\n .toArray(edgePosition1 as any, edgeOffset)\n v.fromArray(vertexPosition as any, b * 3)\n .toArray(edgePosition2 as any, edgeOffset)\n edgeOffset += 3\n }\n addEdge(0, 1)\n addEdge(0, 2)\n addEdge(0, 3)\n addEdge(1, 4)\n addEdge(1, 5)\n addEdge(2, 6)\n addEdge(3, 5)\n addEdge(4, 7)\n addEdge(5, 7)\n addEdge(2, 4)\n addEdge(7, 6)\n addEdge(3, 6)\n\n const picker = new UnitcellPicker(this, structure)\n\n return {\n vertex: {\n position: vertexPosition,\n color: vertexColor,\n radius: vertexRadius,\n picking: picker\n },\n edge: {\n position1: edgePosition1,\n position2: edgePosition2,\n color: edgeColor,\n color2: edgeColor,\n radius: edgeRadius,\n picking: picker\n }\n }\n }\n}\n\nexport default Unitcell\n","/**\n * @file Pdb Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4 } from 'three'\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport StructureParser from './structure-parser'\nimport Entity, { EntityTypeString } from '../structure/entity'\nimport Unitcell, { UnitcellParams } from '../symmetry/unitcell'\nimport Assembly, { AssemblyPart } from '../symmetry/assembly'\nimport { PDBQTSpecialElements, WaterNames } from '../structure/structure-constants'\nimport {\n assignSecondaryStructure, InferBondsOptions, buildUnitcellAssembly,\n calculateBonds, calculateChainnames, calculateSecondaryStructure\n} from '../structure/structure-utils'\nimport Streamer from '../streamer/streamer';\nimport { ParserParameters } from './parser';\nimport { NumberArray } from '../types';\nimport { Structure } from '../ngl';\n\n// PDB helix record encoding\nconst HelixTypes: {[k: number]: string} = {\n 1: 'h', // Right-handed alpha (default)\n 2: 'h', // Right-handed omega\n 3: 'i', // Right-handed pi\n 4: 'h', // Right-handed gamma\n 5: 'g', // Right-handed 310\n 6: 'h', // Left-handed alpha\n 7: 'h', // Left-handed omega\n 8: 'h', // Left-handed gamma\n 9: 'h', // 27 ribbon/helix\n 10: 'h', // Polyproline\n 0: 'h' //Used to be ''\n}\n\nconst dAminoAcids = [\n 'DAL', // D-ALANINE\n 'DAR', // D-ARGININE\n 'DSG', // D-ASPARAGINE\n 'DAS', // D-ASPARTIC ACID\n 'DCY', // D-CYSTEINE\n 'DGL', // D-GLUTAMIC ACID\n 'DGN', // D-GLUTAMINE\n 'DHI', // D-HISTIDINE\n 'DIL', // D-ISOLEUCINE\n 'DLE', // D-LEUCINE\n 'DLY', // D-LYSINE\n 'MED', // D-METHIONINE\n 'DPN', // D-PHENYLALANINE\n 'DPR', // D-PROLINE\n 'DSN', // D-SERINE\n 'DTH', // D-THREONINE\n 'DTR', // D-TRYPTOPHAN\n 'DTY', // D-TYROSINE\n 'DVA', // D-VALINE\n\n 'DNE' // D-NORLEUCINE\n\n // ??? // D-SELENOCYSTEINE\n]\n\nconst entityKeyList = [\n 'MOL_ID', 'MOLECULE', 'CHAIN', 'FRAGMENT', 'SYNONYM',\n 'EC', 'ENGINEERED', 'MUTATION', 'OTHER_DETAILS'\n]\n\nconst reWhitespace = /\\s+/\n\nfunction getModresId (resno: number, chainname?: string, inscode?: string) {\n let id = `${resno}`\n if (chainname) id += `:${chainname}`\n if (inscode) id += `^${inscode}`\n return id\n}\n\nexport interface PdbParserParameters extends ParserParameters {\n hex: boolean\n inferBonds: InferBondsOptions\n}\n\nclass PdbParser extends StructureParser {\n\n hex: boolean\n inferBonds: InferBondsOptions\n\n /**\n * Create a pdb parser\n * @param {Streamer} streamer - streamer object\n * @param {Object} params - params object\n * @param {Boolean} params.hex - hexadecimal parsing of\n * atom numbers >99.999 and\n * residue numbers >9.999\n * @param {InferBondsOptions} params.inferBonds: 'all': use explicit bonds and detect by distance\n * 'auto': If a hetgroup residue has explicit bonds, don't auto-detect\n * 'none': Don't add any bonds automatically\n * @return {undefined}\n */\n constructor (streamer: Streamer, params?: Partial) {\n const p = params || {}\n\n super(streamer, p)\n\n this.hex = defaults(p.hex, false)\n this.inferBonds = defaults(p.inferBonds, 'all')\n }\n\n get type () { return 'pdb' }\n\n _parse () {\n // http://www.wwpdb.org/documentation/file-format.php\n\n if (Debug) Log.time('PdbParser._parse ' + this.name)\n\n let isLegacy = false\n const headerLine = this.streamer.peekLines(1)[ 0 ]\n const headerId = headerLine.substr(62, 4)\n const legacyId = headerLine.substr(72, 4)\n if (headerId === legacyId && legacyId.trim()) {\n isLegacy = true\n }\n\n const isPqr = this.type === 'pqr'\n const isPdbqt = this.type === 'pdbqt'\n\n const s: Structure = this.structure\n const sb = this.structureBuilder\n\n const hex = this.hex\n let serialRadix = 10\n let resnoRadix = 10\n\n const firstModelOnly = this.firstModelOnly\n const asTrajectory = this.asTrajectory\n const cAlphaOnly = this.cAlphaOnly\n\n const frames = s.frames\n const boxes = s.boxes\n let doFrames = false\n let currentFrame: NumberArray, currentCoord: number\n\n const biomolDict = s.biomolDict\n let currentBiomol: Assembly\n let currentPart: AssemblyPart\n let currentMatrix: Matrix4\n\n let line, recordName\n let serial, chainname: string, resno: number, resname: string, occupancy: number\n let inscode: string, atomname, hetero: boolean, bfactor: number, altloc\n let formalCharge: number\n\n let startChain, startResi, startIcode\n let endChain, endResi, endIcode\n\n let serialDict: {[k: number]: number} = {}\n const unitcellDict: Partial<{\n origx: Matrix4\n scale: Matrix4\n a: number\n b: number\n c: number\n alpha: number\n beta: number\n gamma: number\n spacegroup: string\n }> = {}\n const bondDict: {[k: string]: boolean} = {}\n\n const entityDataList: {chainList: string[], name: string}[] = []\n let currentEntityData: {chainList: string[], name: string}\n let currentEntityKey: 'MOL_ID'|'MOLECULE'|'CHAIN'|'FRAGMENT'|'SYNONYM'|'EC'|'ENGINEERED'|'MUTATION'|'OTHER_DETAILS'\n // MOL_ID Numbers each component; also used in SOURCE to associate\n // the information.\n // MOLECULE Name of the macromolecule.\n // CHAIN Comma-separated list of chain identifier(s).\n // FRAGMENT Specifies a domain or region of the molecule.\n // SYNONYM Comma-separated list of synonyms for the MOLECULE.\n // EC The Enzyme Commission number associated with the molecule.\n // If there is more than one EC number, they are presented\n // as a comma-separated list.\n // ENGINEERED Indicates that the molecule was produced using\n // recombinant technology or by purely chemical synthesis.\n // MUTATION Indicates if there is a mutation.\n // OTHER_DETAILS Additional comments.\n\n const hetnameDict: {[k: string]: string} = {}\n const modresDict: {[k: string]: any} = {}\n\n const chainDict: {[k: string]: number} = {}\n let chainIdx: number, chainid: string, newChain: boolean\n let currentChainname: string, currentResno: number, currentResname: string, currentInscode: string\n\n const seqresDict: {[k: string]: string[]} = {}\n let currentSeqresChainname: string\n\n const secStruct = {\n helices: [] as any[],\n sheets: [] as any[]\n }\n const helices = secStruct.helices\n const sheets = secStruct.sheets\n\n const atomMap = s.atomMap\n const atomStore = s.atomStore\n atomStore.resize(Math.round(this.streamer.data.length / 80))\n if (isPqr || isPdbqt) atomStore.addField('partialCharge', 1, 'float32')\n if (isPqr) atomStore.addField('radius', 1, 'float32')\n\n const ap1 = s.getAtomProxy()\n const ap2 = s.getAtomProxy()\n\n let idx = 0\n let modelIdx = 0\n let pendingStart = true\n\n function _parseChunkOfLines (_i: number, _n: number, lines: string[]) {\n for (let i = _i; i < _n; ++i) {\n line = lines[ i ]\n recordName = line.substr(0, 6)\n\n if (recordName === 'ATOM ' || recordName === 'HETATM') {\n // http://www.wwpdb.org/documentation/file-format-content/format33/sect9.html#ATOM\n // PQR: Field_name Atom_number Atom_name Residue_name Chain_ID Residue_number X Y Z Charge Radius\n\n if (pendingStart) {\n if (asTrajectory) {\n if (doFrames) {\n currentFrame = new Float32Array(atomStore.count * 3)\n frames.push(currentFrame)\n } else {\n currentFrame = []\n }\n currentCoord = 0\n } else {\n if (!firstModelOnly) serialDict = {}\n }\n\n chainIdx = 1\n chainid = chainIdx.toString()\n newChain = true\n\n pendingStart = false\n }\n\n if (firstModelOnly && modelIdx > 0) continue\n\n let x, y, z, ls: string[], dd = 0\n\n if (isPqr) {\n ls = line.split(reWhitespace)\n dd = ls.length === 10 ? 1 : 0\n\n atomname = ls[ 2 ]\n if (cAlphaOnly && atomname !== 'CA') continue\n\n x = parseFloat(ls[ 6 - dd ])\n y = parseFloat(ls[ 7 - dd ])\n z = parseFloat(ls[ 8 - dd ])\n } else {\n atomname = line.substr(12, 4).trim()\n if (cAlphaOnly && atomname !== 'CA') continue\n\n x = parseFloat(line.substr(30, 8))\n y = parseFloat(line.substr(38, 8))\n z = parseFloat(line.substr(46, 8))\n }\n\n if (asTrajectory) {\n const j = currentCoord * 3\n\n currentFrame[ j + 0 ] = x\n currentFrame[ j + 1 ] = y\n currentFrame[ j + 2 ] = z\n\n currentCoord += 1\n\n if (doFrames) continue\n }\n\n let element\n\n if (isPqr) {\n serial = parseInt(ls![ 1 ])\n element = ''\n hetero = (line[ 0 ] === 'H')\n chainname = dd ? '' : ls![ 4 ]\n resno = parseInt(ls![ 5 - dd! ])\n inscode = ''\n resname = ls![ 3 ]\n altloc = ''\n occupancy = 1.0\n } else {\n serial = parseInt(line.substr(6, 5), serialRadix)\n if (hex && serial === 99999) {\n serialRadix = 16\n }\n hetero = (line[ 0 ] === 'H')\n chainname = line[ 21 ].trim()\n resno = parseInt(line.substr(22, 4), resnoRadix)\n if (hex && resno === 9999) {\n resnoRadix = 16\n }\n inscode = line[ 26 ].trim()\n resname = line.substr(17, 4).trim() || 'MOL'\n bfactor = parseFloat(line.substr(60, 6))\n altloc = line[ 16 ].trim()\n occupancy = parseFloat(line.substr(54, 6))\n\n if (!isLegacy) {\n if (isPdbqt) {\n element = line.substr(76, 3).trim()\n // @ts-expect-error TS limitation on narrowing indexes types with `in`\n if (element in PDBQTSpecialElements) element = PDBQTSpecialElements[element]\n } else {\n element = line.substr(76, 2).trim()\n if (!chainname) {\n chainname = line.substr(72, 4).trim() // segid\n }\n }\n // Where specified, formalCharge is of form \"2-\" or \"1+\"\n formalCharge = parseInt((line.substr(79,1) + line.substr(78, 1)).trim())\n }\n }\n\n atomStore.growIfFull()\n atomStore.atomTypeId[ idx ] = atomMap.add(atomname, element)\n\n atomStore.x[ idx ] = x\n atomStore.y[ idx ] = y\n atomStore.z[ idx ] = z\n atomStore.serial[ idx ] = serial\n atomStore.altloc[ idx ] = altloc.charCodeAt(0)\n atomStore.occupancy[ idx ] = isNaN(occupancy) ? 0 : occupancy\n\n if (isPqr) {\n atomStore.partialCharge![ idx ] = parseFloat(ls![ 9 - dd! ])\n atomStore.radius[ idx ] = parseFloat(ls![ 10 - dd! ])\n } else {\n atomStore.bfactor[ idx ] = isNaN(bfactor) ? 0 : bfactor\n if (isPdbqt) {\n atomStore.partialCharge![ idx ] = parseFloat(line.substr(70, 6))\n }\n // isFinite check will reject undefined (in legacy case) and NaN values\n if (isFinite(formalCharge)) {\n if (!atomStore.formalCharge) {\n atomStore.addField('formalCharge', 1, 'int8')\n }\n atomStore.formalCharge![ idx ] = formalCharge\n }\n }\n\n const modresId = getModresId(resno, chainname, inscode)\n\n // TODO instead of looking at MODRES look at SEQRES and\n // missing residues in REMARK 465\n if (hetero && !modresDict[modresId] && !dAminoAcids.includes(resname)) {\n if (currentChainname !== chainname || currentResname !== resname ||\n (!WaterNames.includes(resname) &&\n (currentResno !== resno || currentInscode !== inscode))\n ) {\n chainIdx += 1\n chainid = chainIdx.toString()\n\n currentResno = resno\n currentResname = resname\n currentInscode = inscode\n }\n } else if (!newChain && currentChainname !== chainname) {\n chainIdx += 1\n chainid = chainIdx.toString()\n }\n\n sb.addAtom(modelIdx, chainname, chainid, resname, resno, hetero, undefined, inscode)\n\n serialDict[ serial ] = idx\n idx += 1\n newChain = false\n currentChainname = chainname\n } else if (recordName === 'CONECT') {\n const fromIdx = serialDict[ parseInt(line.substr(6, 5)) ]\n const pos = [ 11, 16, 21, 26 ]\n const bondIndex: {[k: number]: number} = {}\n\n if (fromIdx === undefined) {\n // Log.log( \"missing CONNECT serial\" );\n continue\n }\n\n for (let j = 0; j < 4; ++j) {\n let toIdx = parseInt(line.substr(pos[ j ], 5))\n if (Number.isNaN(toIdx)) continue\n toIdx = serialDict[ toIdx ]\n if (toIdx === undefined) {\n // Log.log( \"missing CONNECT serial\" );\n continue\n }/* else if( toIdx < fromIdx ){\n // likely a duplicate in standard PDB format\n // but not necessarily, so better remove duplicates\n // in a pass after parsing (and auto bonding)\n continue;\n } */\n\n if (fromIdx < toIdx) {\n ap1.index = fromIdx\n ap2.index = toIdx\n } else {\n ap1.index = toIdx\n ap2.index = fromIdx\n }\n\n // interpret records where a 'toIdx' atom is given multiple times\n // as double/triple bonds, e.g. CONECT 1529 1528 1528 is a double bond\n if (bondIndex[ toIdx ] !== undefined) {\n s.bondStore.bondOrder[ bondIndex[ toIdx ] ] += 1\n } else {\n const hash = ap1.index + '|' + ap2.index\n if (bondDict[ hash ] === undefined) {\n bondDict[ hash ] = true\n bondIndex[ toIdx ] = s.bondStore.count\n s.bondStore.addBond(ap1, ap2, 1) // start/assume with single bond\n }\n }\n }\n } else if (recordName === 'HELIX ') {\n startChain = line[ 19 ].trim()\n startResi = parseInt(line.substr(21, 4))\n startIcode = line[ 25 ].trim()\n endChain = line[ 31 ].trim()\n endResi = parseInt(line.substr(33, 4))\n endIcode = line[ 37 ].trim()\n let helixType = parseInt(line.substr(39, 1))\n helixType = (HelixTypes[ helixType ] || HelixTypes[0]).charCodeAt(0)\n helices.push([\n startChain, startResi, startIcode,\n endChain, endResi, endIcode,\n helixType\n ])\n } else if (recordName === 'SHEET ') {\n startChain = line[ 21 ].trim()\n startResi = parseInt(line.substr(22, 4))\n startIcode = line[ 26 ].trim()\n endChain = line[ 32 ].trim()\n endResi = parseInt(line.substr(33, 4))\n endIcode = line[ 37 ].trim()\n sheets.push([\n startChain, startResi, startIcode,\n endChain, endResi, endIcode\n ])\n } else if (recordName === 'HETNAM') {\n hetnameDict[ line.substr(11, 3) ] = line.substr(15).trim()\n } else if (recordName === 'SEQRES') {\n const seqresChainname = line[11].trim()\n if (seqresChainname !== currentSeqresChainname) {\n seqresDict[ seqresChainname ] = []\n currentSeqresChainname = seqresChainname\n }\n seqresDict[ seqresChainname ].push(\n ...line.substr(19).trim().split(reWhitespace)\n )\n } else if (recordName === 'MODRES') {\n // MODRES 2SRC PTR A 527 TYR O-PHOSPHOTYROSINE\n const resname = line.substr(12, 3).trim()\n const chainname = line[16].trim()\n const inscode = line[22].trim()\n const resno = parseInt(line.substr(18, 4).trim())\n const id = getModresId(resno, chainname, inscode)\n modresDict[ id ] = { resname, chainname, inscode, resno }\n } else if (recordName === 'COMPND') {\n const comp = line.substr(10, 70).trim()\n const keyEnd = comp.indexOf(':')\n const key = comp.substring(0, keyEnd)\n let value\n\n if (entityKeyList.includes(key)) {\n currentEntityKey = key as 'MOL_ID'|'MOLECULE'|'CHAIN'|'FRAGMENT'|'SYNONYM'|'EC'|'ENGINEERED'|'MUTATION'|'OTHER_DETAILS'\n value = comp.substring(keyEnd + 2)\n } else {\n value = comp\n }\n value = value.replace(/;$/, '')\n\n if (currentEntityKey === 'MOL_ID') {\n currentEntityData = {\n chainList: [],\n name: ''\n }\n entityDataList.push(currentEntityData)\n } else if (currentEntityKey === 'MOLECULE') {\n if (currentEntityData.name) currentEntityData.name += ' '\n currentEntityData.name += value\n } else if (currentEntityKey === 'CHAIN') {\n Array.prototype.push.apply(\n currentEntityData.chainList,\n value.split(/\\s*,\\s*/)\n )\n }\n } else if (line.startsWith('TER')) {\n const cp = s.getChainProxy(s.chainStore.count - 1)\n chainDict[ cp.chainname ] = cp.index\n chainIdx += 1\n chainid = chainIdx.toString()\n newChain = true\n } else if (recordName === 'REMARK' && line.substr(7, 3) === '350') {\n if (line.substr(11, 12) === 'BIOMOLECULE:') {\n let name = line.substr(23).trim()\n if (/^(0|[1-9][0-9]*)$/.test(name)) name = 'BU' + name\n\n currentBiomol = new Assembly(name)\n biomolDict[ name ] = currentBiomol\n } else if (line.substr(13, 5) === 'BIOMT') {\n const biomt = line.split(/\\s+/)\n const row = parseInt(line[ 18 ]) - 1\n\n if (row === 0) {\n currentMatrix = new Matrix4()\n currentPart.matrixList.push(currentMatrix)\n }\n\n const biomtElms = currentMatrix.elements\n\n biomtElms[ 4 * 0 + row ] = parseFloat(biomt[ 4 ])\n biomtElms[ 4 * 1 + row ] = parseFloat(biomt[ 5 ])\n biomtElms[ 4 * 2 + row ] = parseFloat(biomt[ 6 ])\n biomtElms[ 4 * 3 + row ] = parseFloat(biomt[ 7 ])\n } else if (\n line.substr(11, 30) === 'APPLY THE FOLLOWING TO CHAINS:' ||\n line.substr(11, 30) === ' AND CHAINS:'\n ) {\n if (line.substr(11, 5) === 'APPLY') {\n currentPart = currentBiomol.addPart()\n }\n\n const chainList = line.substr(41, 30).split(',')\n for (let j = 0, jl = chainList.length; j < jl; ++j) {\n const c = chainList[ j ].trim()\n if (c) currentPart.chainList.push(c)\n }\n }\n } else if (recordName === 'HEADER') {\n s.id = line.substr(62, 4)\n } else if (recordName === 'TITLE ') {\n s.title += (s.title ? ' ' : '') + line.substr(10, 70).trim()\n } else if (recordName === 'MODEL ') {\n pendingStart = true\n } else if (recordName === 'ENDMDL' || line.trim() === 'END') {\n if (pendingStart) continue\n\n if (asTrajectory && !doFrames) {\n frames.push(new Float32Array(currentFrame))\n doFrames = true\n }\n\n modelIdx += 1\n pendingStart = true\n } else if (line.substr(0, 5) === 'MTRIX') {\n // ignore 'given' operators\n if (line[ 59 ] === '1') continue\n\n if (!currentBiomol || currentBiomol.name !== 'NCS') {\n const ncsName = 'NCS'\n currentBiomol = new Assembly(ncsName)\n biomolDict[ ncsName ] = currentBiomol\n currentPart = currentBiomol.addPart()\n }\n\n const ncs = line.split(/\\s+/)\n const ncsRow = parseInt(line[ 5 ]) - 1\n\n if (ncsRow === 0) {\n currentMatrix = new Matrix4()\n currentPart.matrixList.push(currentMatrix)\n }\n\n const ncsElms = currentMatrix.elements\n\n ncsElms[ 4 * 0 + ncsRow ] = parseFloat(ncs[ 2 ])\n ncsElms[ 4 * 1 + ncsRow ] = parseFloat(ncs[ 3 ])\n ncsElms[ 4 * 2 + ncsRow ] = parseFloat(ncs[ 4 ])\n ncsElms[ 4 * 3 + ncsRow ] = parseFloat(ncs[ 5 ])\n } else if (line.substr(0, 5) === 'ORIGX') {\n if (!unitcellDict.origx) {\n unitcellDict.origx = new Matrix4()\n }\n\n const orgix = line.split(/\\s+/)\n const origxRow = parseInt(line[ 5 ]) - 1\n const origxElms = unitcellDict.origx.elements\n\n origxElms[ 4 * 0 + origxRow ] = parseFloat(orgix[ 1 ])\n origxElms[ 4 * 1 + origxRow ] = parseFloat(orgix[ 2 ])\n origxElms[ 4 * 2 + origxRow ] = parseFloat(orgix[ 3 ])\n origxElms[ 4 * 3 + origxRow ] = parseFloat(orgix[ 4 ])\n } else if (line.substr(0, 5) === 'SCALE') {\n if (!unitcellDict.scale) {\n unitcellDict.scale = new Matrix4()\n }\n\n const scale = line.split(/\\s+/)\n const scaleRow = parseInt(line[ 5 ]) - 1\n const scaleElms = unitcellDict.scale.elements\n\n scaleElms[ 4 * 0 + scaleRow ] = parseFloat(scale[ 1 ])\n scaleElms[ 4 * 1 + scaleRow ] = parseFloat(scale[ 2 ])\n scaleElms[ 4 * 2 + scaleRow ] = parseFloat(scale[ 3 ])\n scaleElms[ 4 * 3 + scaleRow ] = parseFloat(scale[ 4 ])\n } else if (recordName === 'CRYST1') {\n // CRYST1 55.989 55.989 55.989 90.00 90.00 90.00 P 1 1\n // 7 - 15 Real(9.3) a (Angstroms)\n // 16 - 24 Real(9.3) b (Angstroms)\n // 25 - 33 Real(9.3) c (Angstroms)\n // 34 - 40 Real(7.2) alpha alpha (degrees).\n // 41 - 47 Real(7.2) beta beta (degrees).\n // 48 - 54 Real(7.2) gamma gamma (degrees).\n // 56 - 66 LString sGroup Space group.\n // 67 - 70 Integer z Z value.\n\n const aLength = parseFloat(line.substr(6, 9))\n const bLength = parseFloat(line.substr(15, 9))\n const cLength = parseFloat(line.substr(24, 9))\n\n const alpha = parseFloat(line.substr(33, 7))\n const beta = parseFloat(line.substr(40, 7))\n const gamma = parseFloat(line.substr(47, 7))\n\n const sGroup = line.substr(55, 11).trim()\n // const zValue = parseInt( line.substr( 66, 4 ) );\n\n const box = new Float32Array(9)\n box[ 0 ] = aLength\n box[ 4 ] = bLength\n box[ 8 ] = cLength\n boxes.push(box)\n\n if (modelIdx === 0) {\n unitcellDict.a = aLength\n unitcellDict.b = bLength\n unitcellDict.c = cLength\n unitcellDict.alpha = alpha\n unitcellDict.beta = beta\n unitcellDict.gamma = gamma\n unitcellDict.spacegroup = sGroup\n }\n }\n }\n }\n\n this.streamer.eachChunkOfLines(function (lines/*, chunkNo, chunkCount */) {\n _parseChunkOfLines(0, lines.length, lines)\n })\n\n\n // finalize ensures resname will be defined for all rp.resname\n // (required in entity handling below)\n sb.finalize()\n\n //\n\n const en = entityDataList.length\n\n if (en) {\n s.eachChain(function (cp) {\n cp.entityIndex = en\n })\n\n entityDataList.forEach(function (e, i) {\n const chainIndexList = e.chainList.map(function (chainname) {\n return chainDict[ chainname ]\n })\n s.entityList.push(new Entity(\n s, i, e.name, 'polymer', chainIndexList\n ))\n })\n\n let ei = entityDataList.length\n const rp = s.getResidueProxy()\n const residueDict: {[k: string]: number[]} = {}\n\n s.eachChain(function (cp) {\n if (cp.entityIndex === en) {\n rp.index = cp.residueOffset\n if (!residueDict[ rp.resname ]) {\n residueDict[ rp.resname ] = []\n }\n residueDict[ rp.resname ].push(cp.index)\n }\n })\n\n Object.keys(residueDict).forEach(function (resname) {\n const chainList = residueDict[ resname ]\n let type: EntityTypeString = 'non-polymer'\n let name = hetnameDict[ resname ] || resname\n if (WaterNames.includes(resname)) {\n name = 'water'\n type = 'water'\n }\n s.entityList.push(new Entity(\n s, ei, name, type, chainList\n ))\n ei += 1\n })\n }\n\n //\n\n if (unitcellDict.a !== undefined) {\n s.unitcell = new Unitcell(unitcellDict as UnitcellParams)\n } else {\n s.unitcell = undefined\n }\n\n if (helices.length || sheets.length) {\n assignSecondaryStructure(s, secStruct)\n }\n\n s.finalizeAtoms()\n if (!isLegacy) calculateChainnames(s)\n calculateBonds(s, this.inferBonds)\n s.finalizeBonds()\n\n if (!helices.length && !sheets.length) {\n calculateSecondaryStructure(s)\n }\n buildUnitcellAssembly(s)\n\n if (Debug) Log.timeEnd('PdbParser._parse ' + this.name)\n }\n}\n\nParserRegistry.add('pdb', PdbParser)\nParserRegistry.add('pdb1', PdbParser)\nParserRegistry.add('ent', PdbParser)\n\nexport default PdbParser\n\nexport {\n HelixTypes\n}\n","/**\n * @file Cif Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Matrix4 } from 'three'\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport StructureParser from './structure-parser'\nimport { HelixTypes } from './pdb-parser'\nimport Entity from '../structure/entity'\nimport Unitcell, { UnitcellParams } from '../symmetry/unitcell'\nimport Assembly from '../symmetry/assembly'\nimport Selection from '../selection/selection'\nimport {\n assignResidueTypeBonds, assignSecondaryStructure, buildUnitcellAssembly,\n calculateBonds, calculateSecondaryStructure\n} from '../structure/structure-utils'\nimport { Structure } from '../ngl';\nimport StructureBuilder from '../structure/structure-builder';\nimport { NumberArray } from '../types';\n\nconst reWhitespace = /\\s+/\nconst reQuotedWhitespace = /'((?:(?!'\\s).)*)'|\"((?:(?!\"\\s).)*)\"|(\\S+)/g\nconst reDoubleQuote = /\"/g\nconst reTrimQuotes = /^['\"]+|['\"]+$/g\nconst reAtomSymbol = /^\\D{1,2}/ // atom symbol in atom_site_label\n\ninterface Cif {[k: string]: any}\n\nfunction trimQuotes (str: string) {\n if (str && str[0] === str[ str.length - 1 ] && (str[0] === \"'\" || str[0] === '\"')) {\n return str.substring(1, str.length - 1)\n } else {\n return str\n }\n}\n\nfunction ensureArray (dict: {[k: string]: any[]}, field: string) {\n if (!Array.isArray(dict[ field ])) {\n Object.keys(dict).forEach(function (key) {\n dict[ key ] = [ dict[ key ] ]\n })\n }\n}\n\nfunction hasValue (d: string) {\n return d !== '?'\n}\n\nfunction cifDefaults (value: string, defaultValue: string) {\n return hasValue(value) ? value : defaultValue\n}\n\nfunction getBondOrder (valueOrder: string) {\n switch (valueOrder.toLowerCase()) {\n case '?': // assume single bond\n case 'sing':\n return 1\n case 'doub':\n return 2\n case 'trip':\n return 3\n case 'quad':\n return 4\n }\n return 0\n}\n\nfunction parseChemComp (cif: Cif, structure: Structure, structureBuilder: StructureBuilder) {\n const atomStore = structure.atomStore\n const atomMap = structure.atomMap\n\n let i, n\n const cc = cif.chem_comp\n const cca = cif.chem_comp_atom\n const ccb = cif.chem_comp_bond\n\n if (cc) {\n if (cc.name) {\n structure.title = cc.name.trim().replace(reTrimQuotes, '')\n }\n if (cc.id) {\n structure.id = cc.id.trim().replace(reTrimQuotes, '')\n }\n }\n\n var atomnameDict: {[k: string]: number} = {}\n\n if (cca) {\n ensureArray(cca, 'comp_id')\n\n var atomname, element, resname, resno\n n = cca.comp_id.length\n\n for (i = 0; i < n; ++i) {\n atomStore.growIfFull()\n\n atomname = cca.atom_id[ i ].replace(reDoubleQuote, '')\n element = cca.type_symbol[ i ]\n\n atomnameDict[ atomname ] = i\n atomStore.atomTypeId[ i ] = atomMap.add(atomname, element)\n\n atomStore.x[ i ] = cca.model_Cartn_x[ i ]\n atomStore.y[ i ] = cca.model_Cartn_y[ i ]\n atomStore.z[ i ] = cca.model_Cartn_z[ i ]\n atomStore.serial[ i ] = i\n\n resname = cca.pdbx_component_comp_id[ i ]\n resno = cca.pdbx_residue_numbering ? cca.pdbx_residue_numbering[ i ] : 1\n\n structureBuilder.addAtom(0, '', '', resname, resno, true)\n }\n\n for (i = 0; i < n; ++i) {\n var j = i + n\n\n atomStore.growIfFull()\n\n atomname = cca.atom_id[ i ].replace(reDoubleQuote, '')\n element = cca.type_symbol[ i ]\n\n atomStore.atomTypeId[ j ] = atomMap.add(atomname, element)\n\n atomStore.x[ j ] = cca.pdbx_model_Cartn_x_ideal[ i ]\n atomStore.y[ j ] = cca.pdbx_model_Cartn_y_ideal[ i ]\n atomStore.z[ j ] = cca.pdbx_model_Cartn_z_ideal[ i ]\n atomStore.serial[ j ] = j\n\n resname = cca.pdbx_component_comp_id[ i ]\n resno = cca.pdbx_residue_numbering ? cca.pdbx_residue_numbering[ i ] : 1\n\n structureBuilder.addAtom(1, '', '', resname, resno, true)\n }\n }\n\n if (cca && ccb) {\n ensureArray(ccb, 'comp_id')\n\n var atomname1, atomname2, bondOrder\n n = ccb.comp_id.length\n var na = cca.comp_id.length\n\n var ap1 = structure.getAtomProxy()\n var ap2 = structure.getAtomProxy()\n\n for (i = 0; i < n; ++i) {\n atomname1 = ccb.atom_id_1[ i ].replace(reDoubleQuote, '')\n atomname2 = ccb.atom_id_2[ i ].replace(reDoubleQuote, '')\n bondOrder = getBondOrder(ccb.value_order[ i ])\n\n ap1.index = atomnameDict[ atomname1 ]\n ap2.index = atomnameDict[ atomname2 ]\n structure.bondStore.growIfFull()\n structure.bondStore.addBond(ap1, ap2, bondOrder)\n\n ap1.index += na\n ap2.index += na\n structure.bondStore.growIfFull()\n structure.bondStore.addBond(ap1, ap2, bondOrder)\n }\n }\n}\n\nfunction parseCore (cif: Cif, structure: Structure, structureBuilder: StructureBuilder) {\n var atomStore = structure.atomStore\n var atomMap = structure.atomMap\n\n if (cif.data) {\n structure.id = cif.data\n structure.name = cif.data\n }\n\n structure.unitcell = new Unitcell({\n a: parseFloat(cif.cell_length_a),\n b: parseFloat(cif.cell_length_b),\n c: parseFloat(cif.cell_length_c),\n alpha: parseFloat(cif.cell_angle_alpha),\n beta: parseFloat(cif.cell_angle_beta),\n gamma: parseFloat(cif.cell_angle_gamma),\n spacegroup: trimQuotes(cif['symmetry_space_group_name_H-M'])\n })\n\n const v = new Vector3()\n const c = new Vector3()\n const n = cif.atom_site_type_symbol.length\n\n const typeSymbolMap: Record = {}\n\n for (let i = 0; i < n; ++i) {\n atomStore.growIfFull()\n\n const atomname = cif.atom_site_label[ i ]\n const typeSymbol = cif.atom_site_type_symbol[ i ]\n\n // typeSymbol can be like `Al2.5+`. Retain element symbol only.\n let element = typeSymbolMap[typeSymbol]\n if (!element) {\n const match = typeSymbol.match(reAtomSymbol)\n typeSymbolMap[typeSymbol] = element = match?.[0] ?? typeSymbol\n }\n\n atomStore.atomTypeId[ i ] = atomMap.add(atomname, element)\n\n v.set(\n cif.atom_site_fract_x[ i ],\n cif.atom_site_fract_y[ i ],\n cif.atom_site_fract_z[ i ]\n )\n v.applyMatrix4(structure.unitcell.fracToCart)\n c.add(v)\n\n atomStore.x[ i ] = v.x\n atomStore.y[ i ] = v.y\n atomStore.z[ i ] = v.z\n if (cif.atom_site_occupancy) {\n atomStore.occupancy[ i ] = parseFloat(cif.atom_site_occupancy[ i ])\n }\n atomStore.serial[ i ] = i\n\n structureBuilder.addAtom(0, '', '', 'HET', 1, true)\n }\n\n c.divideScalar(n)\n structure.center = c\n buildUnitcellAssembly(structure)\n\n const v2 = new Vector3()\n const v3 = new Vector3()\n const ml = structure.biomolDict.SUPERCELL.partList[ 0 ].matrixList\n\n let k = n\n\n function covalent (idx: number) {\n return atomMap.get(atomStore.atomTypeId[ idx ]).covalent\n }\n const identityMatrix = new Matrix4()\n\n for (let i = 0; i < n; ++i) {\n const covalentI = covalent(i)\n\n v.set(\n atomStore.x[ i ],\n atomStore.y[ i ],\n atomStore.z[ i ]\n )\n\n ml.forEach(function (m) {\n if (identityMatrix.equals(m)) return\n\n v2.copy(v)\n v2.applyMatrix4(m)\n\n for (let j = 0; j < n; ++j) {\n v3.set(\n atomStore.x[ j ],\n atomStore.y[ j ],\n atomStore.z[ j ]\n )\n\n const distSquared = v2.distanceToSquared(v3)\n const d = covalent(j) + covalentI\n const d1 = d + 0.3\n const d2 = d - 0.5\n\n if (distSquared < (d1 * d1) && distSquared > (d2 * d2)) {\n atomStore.growIfFull()\n\n atomStore.atomTypeId[ k ] = atomStore.atomTypeId[ i ]\n atomStore.x[ k ] = v2.x\n atomStore.y[ k ] = v2.y\n atomStore.z[ k ] = v2.z\n atomStore.occupancy[ k ] = atomStore.occupancy[ i ]\n atomStore.serial[ k ] = k\n atomStore.altloc[ k ] = 'A'.charCodeAt(0)\n\n structureBuilder.addAtom(0, '', '', 'HET', 1, true)\n\n k += 1\n return\n }\n }\n })\n }\n}\n\nfunction processSecondaryStructure (cif: Cif, structure: Structure, asymIdDict: {[k: string]: string}) {\n var helices: [string, number, string, string, number, string, number][] = []\n var sheets: [string, number, string, string, number, string][] = []\n\n var i, il, begIcode, endIcode\n\n // get helices\n var sc = cif.struct_conf\n\n if (sc?.pdbx_PDB_helix_class) {\n ensureArray(sc, 'id')\n\n for (i = 0, il = sc.beg_auth_seq_id.length; i < il; ++i) {\n var helixType = parseInt(sc.pdbx_PDB_helix_class[ i ])\n if (!Number.isNaN(helixType)) {\n begIcode = sc.pdbx_beg_PDB_ins_code[ i ]\n endIcode = sc.pdbx_end_PDB_ins_code[ i ]\n helices.push([\n asymIdDict[ sc.beg_label_asym_id[ i ] ],\n parseInt(sc.beg_auth_seq_id[ i ]),\n cifDefaults(begIcode, ''),\n asymIdDict[ sc.end_label_asym_id[ i ] ],\n parseInt(sc.end_auth_seq_id[ i ]),\n cifDefaults(endIcode, ''),\n (HelixTypes[ helixType ] || HelixTypes[0]).charCodeAt(0)\n ])\n }\n }\n }\n\n // get sheets\n var ssr = cif.struct_sheet_range\n\n if (ssr) {\n ensureArray(ssr, 'id')\n\n for (i = 0, il = ssr.beg_auth_seq_id.length; i < il; ++i) {\n begIcode = ssr.pdbx_beg_PDB_ins_code[ i ]\n endIcode = ssr.pdbx_end_PDB_ins_code[ i ]\n sheets.push([\n asymIdDict[ ssr.beg_label_asym_id[ i ] ],\n parseInt(ssr.beg_auth_seq_id[ i ]),\n cifDefaults(begIcode, ''),\n asymIdDict[ ssr.end_label_asym_id[ i ] ],\n parseInt(ssr.end_auth_seq_id[ i ]),\n cifDefaults(endIcode, '')\n ])\n }\n }\n\n if (sc || ssr) {\n return {\n helices: helices,\n sheets: sheets\n }\n } else {\n return false\n }\n}\n\nfunction processSymmetry (cif: Cif, structure: Structure, asymIdDict: {[k: string]: string}) {\n // biomol & ncs processing\n var operDict: {[k: string]: Matrix4} = {}\n var biomolDict = structure.biomolDict\n\n if (cif.pdbx_struct_oper_list) {\n var biomolOp = cif.pdbx_struct_oper_list\n ensureArray(biomolOp, 'id')\n\n biomolOp.id.forEach(function (id: number, i: number) {\n var m = new Matrix4()\n var elms = m.elements\n\n elms[ 0 ] = parseFloat(biomolOp[ 'matrix[1][1]' ][ i ])\n elms[ 1 ] = parseFloat(biomolOp[ 'matrix[1][2]' ][ i ])\n elms[ 2 ] = parseFloat(biomolOp[ 'matrix[1][3]' ][ i ])\n\n elms[ 4 ] = parseFloat(biomolOp[ 'matrix[2][1]' ][ i ])\n elms[ 5 ] = parseFloat(biomolOp[ 'matrix[2][2]' ][ i ])\n elms[ 6 ] = parseFloat(biomolOp[ 'matrix[2][3]' ][ i ])\n\n elms[ 8 ] = parseFloat(biomolOp[ 'matrix[3][1]' ][ i ])\n elms[ 9 ] = parseFloat(biomolOp[ 'matrix[3][2]' ][ i ])\n elms[ 10 ] = parseFloat(biomolOp[ 'matrix[3][3]' ][ i ])\n\n elms[ 3 ] = parseFloat(biomolOp[ 'vector[1]' ][ i ])\n elms[ 7 ] = parseFloat(biomolOp[ 'vector[2]' ][ i ])\n elms[ 11 ] = parseFloat(biomolOp[ 'vector[3]' ][ i ])\n\n m.transpose()\n\n operDict[ id ] = m\n })\n }\n\n if (cif.pdbx_struct_assembly_gen) {\n var gen = cif.pdbx_struct_assembly_gen\n ensureArray(gen, 'assembly_id')\n\n var getMatrixDict = function (expr: string) {\n var matDict: {[k: string]: Matrix4} = {}\n\n var l = expr.replace(/[()']/g, '').split(',')\n\n l.forEach(function (e) {\n if (e.includes('-')) {\n var es = e.split('-')\n\n var j = parseInt(es[ 0 ])\n var m = parseInt(es[ 1 ])\n\n for (; j <= m; ++j) {\n matDict[ j ] = operDict[ j ]\n }\n } else {\n matDict[ e ] = operDict[ e ]\n }\n })\n\n return matDict\n }\n\n gen.assembly_id.forEach(function (id: string, i: number) {\n var md:{[k: string]: Matrix4} = {}\n var oe = gen.oper_expression[ i ].replace(/['\"]\\(|['\"]/g, '')\n\n if (oe.includes(')(') || oe.indexOf('(') > 0) {\n oe = oe.split('(')\n\n var md1 = getMatrixDict(oe[ 0 ])\n var md2 = getMatrixDict(oe[ 1 ])\n\n Object.keys(md1).forEach(function (k1) {\n Object.keys(md2).forEach(function (k2) {\n var mat = new Matrix4()\n\n mat.multiplyMatrices(md1[ k1 ], md2[ k2 ])\n md[ k1 + 'x' + k2 ] = mat\n })\n })\n } else {\n md = getMatrixDict(oe)\n }\n\n var matrixList = []\n for (var k in md) {\n matrixList.push(md[ k ])\n }\n\n var name = id\n if (/^(0|[1-9][0-9]*)$/.test(name)) name = 'BU' + name\n\n var chainList = gen.asym_id_list[ i ].split(',')\n for (var j = 0, jl = chainList.length; j < jl; ++j) {\n chainList[ j ] = asymIdDict[ chainList[ j ] ]\n }\n\n if (biomolDict[ name ] === undefined) {\n biomolDict[ name ] = new Assembly(name)\n }\n biomolDict[ name ].addPart(matrixList, chainList)\n })\n }\n\n // non-crystallographic symmetry operations\n if (cif.struct_ncs_oper) {\n var ncsOp = cif.struct_ncs_oper\n ensureArray(ncsOp, 'id')\n\n var ncsName = 'NCS'\n biomolDict[ ncsName ] = new Assembly(ncsName)\n var ncsPart = biomolDict[ ncsName ].addPart()\n\n ncsOp.id.forEach(function (id: string, i: number) {\n // ignore 'given' operators\n if (ncsOp.code[ i ] === 'given') return\n\n var m = new Matrix4()\n var elms = m.elements\n\n elms[ 0 ] = parseFloat(ncsOp[ 'matrix[1][1]' ][ i ])\n elms[ 1 ] = parseFloat(ncsOp[ 'matrix[1][2]' ][ i ])\n elms[ 2 ] = parseFloat(ncsOp[ 'matrix[1][3]' ][ i ])\n\n elms[ 4 ] = parseFloat(ncsOp[ 'matrix[2][1]' ][ i ])\n elms[ 5 ] = parseFloat(ncsOp[ 'matrix[2][2]' ][ i ])\n elms[ 6 ] = parseFloat(ncsOp[ 'matrix[2][3]' ][ i ])\n\n elms[ 8 ] = parseFloat(ncsOp[ 'matrix[3][1]' ][ i ])\n elms[ 9 ] = parseFloat(ncsOp[ 'matrix[3][2]' ][ i ])\n elms[ 10 ] = parseFloat(ncsOp[ 'matrix[3][3]' ][ i ])\n\n elms[ 3 ] = parseFloat(ncsOp[ 'vector[1]' ][ i ])\n elms[ 7 ] = parseFloat(ncsOp[ 'vector[2]' ][ i ])\n elms[ 11 ] = parseFloat(ncsOp[ 'vector[3]' ][ i ])\n\n m.transpose()\n\n ncsPart.matrixList.push(m)\n })\n\n if (ncsPart.matrixList.length === 0) {\n delete biomolDict[ ncsName ]\n }\n }\n\n // cell & symmetry\n const unitcellDict: {\n a?: number\n b?: number\n c?: number\n alpha?: number\n beta?: number\n gamma?: number\n spacegroup?: string\n origx?: Matrix4\n scale?: Matrix4\n } = {}\n\n if (cif.cell) {\n const cell = cif.cell\n\n const a = parseFloat(cell.length_a)\n const b = parseFloat(cell.length_b)\n const c = parseFloat(cell.length_c)\n\n const box = new Float32Array(9)\n box[ 0 ] = a\n box[ 4 ] = b\n box[ 8 ] = c\n structure.boxes.push(box)\n\n unitcellDict.a = a\n unitcellDict.b = b\n unitcellDict.c = c\n unitcellDict.alpha = parseFloat(cell.angle_alpha)\n unitcellDict.beta = parseFloat(cell.angle_beta)\n unitcellDict.gamma = parseFloat(cell.angle_gamma)\n }\n\n if (cif.symmetry) {\n unitcellDict.spacegroup = trimQuotes(\n cif.symmetry[ 'space_group_name_H-M' ]\n )\n }\n\n // origx\n var origx = new Matrix4()\n\n if (cif.database_PDB_matrix) {\n var origxMat = cif.database_PDB_matrix\n var origxElms = origx.elements\n\n origxElms[ 0 ] = parseFloat(origxMat[ 'origx[1][1]' ])\n origxElms[ 1 ] = parseFloat(origxMat[ 'origx[1][2]' ])\n origxElms[ 2 ] = parseFloat(origxMat[ 'origx[1][3]' ])\n\n origxElms[ 4 ] = parseFloat(origxMat[ 'origx[2][1]' ])\n origxElms[ 5 ] = parseFloat(origxMat[ 'origx[2][2]' ])\n origxElms[ 6 ] = parseFloat(origxMat[ 'origx[2][3]' ])\n\n origxElms[ 8 ] = parseFloat(origxMat[ 'origx[3][1]' ])\n origxElms[ 9 ] = parseFloat(origxMat[ 'origx[3][2]' ])\n origxElms[ 10 ] = parseFloat(origxMat[ 'origx[3][3]' ])\n\n origxElms[ 3 ] = parseFloat(origxMat[ 'origx_vector[1]' ])\n origxElms[ 7 ] = parseFloat(origxMat[ 'origx_vector[2]' ])\n origxElms[ 11 ] = parseFloat(origxMat[ 'origx_vector[3]' ])\n\n origx.transpose()\n\n unitcellDict.origx = origx\n }\n\n // scale\n var scale = new Matrix4()\n\n if (cif.atom_sites) {\n var scaleMat = cif.atom_sites\n var scaleElms = scale.elements\n\n scaleElms[ 0 ] = parseFloat(scaleMat[ 'fract_transf_matrix[1][1]' ])\n scaleElms[ 1 ] = parseFloat(scaleMat[ 'fract_transf_matrix[1][2]' ])\n scaleElms[ 2 ] = parseFloat(scaleMat[ 'fract_transf_matrix[1][3]' ])\n\n scaleElms[ 4 ] = parseFloat(scaleMat[ 'fract_transf_matrix[2][1]' ])\n scaleElms[ 5 ] = parseFloat(scaleMat[ 'fract_transf_matrix[2][2]' ])\n scaleElms[ 6 ] = parseFloat(scaleMat[ 'fract_transf_matrix[2][3]' ])\n\n scaleElms[ 8 ] = parseFloat(scaleMat[ 'fract_transf_matrix[3][1]' ])\n scaleElms[ 9 ] = parseFloat(scaleMat[ 'fract_transf_matrix[3][2]' ])\n scaleElms[ 10 ] = parseFloat(scaleMat[ 'fract_transf_matrix[3][3]' ])\n\n scaleElms[ 3 ] = parseFloat(scaleMat[ 'fract_transf_vector[1]' ])\n scaleElms[ 7 ] = parseFloat(scaleMat[ 'fract_transf_vector[2]' ])\n scaleElms[ 11 ] = parseFloat(scaleMat[ 'fract_transf_vector[3]' ])\n\n scale.transpose()\n\n unitcellDict.scale = scale\n }\n\n if (unitcellDict.a !== undefined) {\n structure.unitcell = new Unitcell(unitcellDict as UnitcellParams)\n } else {\n structure.unitcell = undefined\n }\n}\n\nfunction processConnections (cif: Cif, structure: Structure, asymIdDict: {[k: string]: string}) {\n // add connections\n var sc = cif.struct_conn\n\n if (sc) {\n ensureArray(sc, 'id')\n\n var reDoubleQuote = /\"/g\n var ap1 = structure.getAtomProxy()\n var ap2 = structure.getAtomProxy()\n var atomIndicesCache: {[k: string]: Uint32Array|undefined} = {}\n\n for (var i = 0, il = sc.id.length; i < il; ++i) {\n // ignore:\n // hydrog - hydrogen bond\n // mismat - mismatched base pairs\n // saltbr - ionic interaction\n\n var connTypeId = sc.conn_type_id[ i ]\n if (connTypeId === 'hydrog' ||\n connTypeId === 'mismat' ||\n connTypeId === 'saltbr') continue\n\n // ignore bonds between symmetry mates\n if (sc.ptnr1_symmetry[ i ] !== '1_555' ||\n sc.ptnr2_symmetry[ i ] !== '1_555') continue\n\n // process:\n // covale - covalent bond\n // covale_base -\n // covalent modification of a nucleotide base\n // covale_phosphate -\n // covalent modification of a nucleotide phosphate\n // covale_sugar -\n // covalent modification of a nucleotide sugar\n // disulf - disulfide bridge\n // metalc - metal coordination\n // modres - covalent residue modification\n\n var inscode1 = sc.pdbx_ptnr1_PDB_ins_code[ i ]\n var altloc1 = sc.pdbx_ptnr1_label_alt_id[ i ]\n var sele1 = (\n sc.ptnr1_auth_seq_id[ i ] +\n (hasValue(inscode1) ? ('^' + inscode1) : '') +\n ':' + asymIdDict[ sc.ptnr1_label_asym_id[ i ] ] +\n '.' + sc.ptnr1_label_atom_id[ i ].replace(reDoubleQuote, '') +\n (hasValue(altloc1) ? ('%' + altloc1) : '')\n )\n var atomIndices1 = atomIndicesCache[ sele1 ]\n if (!atomIndices1) {\n var selection1 = new Selection(sele1)\n if (selection1.selection.error) {\n if (Debug) Log.warn('invalid selection for connection', sele1)\n continue\n }\n atomIndices1 = structure.getAtomIndices(selection1)\n atomIndicesCache[ sele1 ] = atomIndices1\n }\n\n var inscode2 = sc.pdbx_ptnr2_PDB_ins_code[ i ]\n var altloc2 = sc.pdbx_ptnr2_label_alt_id[ i ]\n var sele2 = (\n sc.ptnr2_auth_seq_id[ i ] +\n (hasValue(inscode2) ? ('^' + inscode2) : '') +\n ':' + asymIdDict[ sc.ptnr2_label_asym_id[ i ] ] +\n '.' + sc.ptnr2_label_atom_id[ i ].replace(reDoubleQuote, '') +\n (hasValue(altloc2) ? ('%' + altloc2) : '')\n )\n var atomIndices2 = atomIndicesCache[ sele2 ]\n if (!atomIndices2) {\n var selection2 = new Selection(sele2)\n if (selection2.selection.error) {\n if (Debug) Log.warn('invalid selection for connection', sele2)\n continue\n }\n atomIndices2 = structure.getAtomIndices(selection2)\n atomIndicesCache[ sele2 ] = atomIndices2\n }\n\n // cases with more than one atom per selection\n // - #altloc1 to #altloc2\n // - #model to #model\n // - #altloc1 * #model to #altloc2 * #model\n\n var k = atomIndices1!.length\n var l = atomIndices2!.length\n\n if (k > l) {\n var tmpA = k\n k = l\n l = tmpA\n var tmpB = atomIndices1\n atomIndices1 = atomIndices2\n atomIndices2 = tmpB\n }\n\n // console.log( k, l );\n\n if (k === 0 || l === 0) {\n if (Debug) Log.warn('no atoms found for', sele1, sele2)\n continue\n }\n\n for (var j = 0; j < l; ++j) {\n ap1.index = atomIndices1![ j % k ]\n ap2.index = atomIndices2![ j ]\n\n if (ap1 && ap2) {\n structure.bondStore.addBond(\n ap1, ap2, getBondOrder(sc.pdbx_value_order[ i ])\n )\n } else {\n Log.log('atoms for connection not found')\n }\n }\n }\n }\n}\n\nfunction processEntities (cif: Cif, structure: Structure, chainIndexDict: {[k: string]: Set}) {\n if (cif.entity) {\n ensureArray(cif.entity, 'id')\n var e = cif.entity\n var n = e.id.length\n for (var i = 0; i < n; ++i) {\n var description = e.pdbx_description[ i ]\n var type = e.type[ i ]\n var chainIndexList: number[] = Array.from(chainIndexDict[ e.id[ i ] ])\n structure.entityList[ i ] = new Entity(\n structure, i, description, type, chainIndexList\n )\n }\n }\n}\n\n//\n\nclass CifParser extends StructureParser {\n get type () { return 'cif' }\n\n _parse () {\n // http://mmcif.wwpdb.org/\n\n Log.time('CifParser._parse ' + this.name)\n\n var s = this.structure\n var sb = this.structureBuilder\n\n var firstModelOnly = this.firstModelOnly\n var asTrajectory = this.asTrajectory\n var cAlphaOnly = this.cAlphaOnly\n\n var frames = s.frames\n var currentFrame: NumberArray, currentCoord: number\n\n var rawline, line\n\n //\n\n var cif: Cif = {}\n var asymIdDict: {[k: string]: string} = {}\n var chainIndexDict:{[k: string]: Set} = {}\n\n var pendingString = false\n var currentString: string|null = null\n var pendingValue = false\n var pendingLoop = false\n var pendingName = false\n var loopPointers: string[][] = []\n var currentLoopIndex: number|null = null\n var currentCategory: string|null = null\n var currentName: string|boolean|null = null\n var first: boolean|null = null\n var pointerNames: string[] = []\n\n var authAsymId: number, authSeqId: number, labelSeqId: number,\n labelAtomId: number, labelCompId: number, labelAsymId: number, labelEntityId: number, labelAltId: number,\n groupPDB: number, id: number, typeSymbol: number, pdbxPDBmodelNum: number, pdbxPDBinsCode: number,\n CartnX: number, CartnY: number, CartnZ: number, bIsoOrEquiv: number, occupancy: number\n\n //\n\n var atomMap = s.atomMap\n var atomStore = s.atomStore\n atomStore.resize(this.streamer.data.length / 100)\n\n var idx = 0\n var modelIdx = 0\n var modelNum: number\n\n function _parseChunkOfLines (_i: number, _n: number, lines: string[]) {\n for (var i = _i; i < _n; ++i) {\n rawline = lines[i]\n line = rawline.trim()\n\n if ((!line && !pendingString && !pendingLoop) || line[0] === '#') {\n // Log.log( \"NEW BLOCK\" );\n\n pendingString = false\n pendingLoop = false\n pendingValue = false\n loopPointers.length = 0\n currentLoopIndex = null\n currentCategory = null\n currentName = null\n first = null\n pointerNames.length = 0\n } else if (line.substring(0, 5) === 'data_') {\n cif.data = line.substring(5).trim()\n\n // Log.log( \"DATA\", data );\n } else if (line[0] === ';') {\n if (pendingString) {\n // Log.log( \"STRING END\", currentString );\n\n if (pendingLoop) {\n if (currentLoopIndex === loopPointers.length) {\n currentLoopIndex = 0\n }\n loopPointers[ currentLoopIndex as number ].push(currentString as string);\n (currentLoopIndex as number) += 1\n } else {\n if (currentName === false) {\n cif[ currentCategory as string ] = currentString\n } else {\n cif[ currentCategory as string ][ currentName as string ] = currentString //TODO currentname can equals null\n }\n }\n\n pendingString = false\n currentString = null\n } else {\n // Log.log( \"STRING START\" );\n\n pendingString = true\n currentString = line.substring(1)\n }\n } else if (line === 'loop_') {\n // Log.log( \"LOOP START\" );\n\n pendingLoop = true\n pendingName = true\n loopPointers.length = 0\n pointerNames.length = 0\n currentLoopIndex = 0\n } else if (line[0] === '_') {\n var keyParts, category, name\n\n if (pendingLoop && !pendingName) {\n pendingLoop = false\n }\n\n if (pendingLoop) {\n // Log.log( \"LOOP KEY\", line );\n\n keyParts = line.split('.')\n category = keyParts[ 0 ].substring(1)\n name = keyParts[ 1 ]\n\n if (keyParts.length === 1) {\n name = false\n if (!cif[ category ]) cif[ category ] = []\n loopPointers.push(cif[ category ])\n } else {\n if (!cif[ category ]) cif[ category ] = {}\n if (cif[ category ][ name ]) {\n if (Debug) Log.warn(category, name, 'already exists')\n } else {\n cif[ category ][ name ] = []\n loopPointers.push(cif[ category ][ name ])\n pointerNames.push(name)\n }\n }\n\n currentCategory = category\n currentName = name\n first = true\n } else {\n var keyValuePair = line.match(reQuotedWhitespace)\n var key = keyValuePair![ 0 ]\n var value = keyValuePair![ 1 ]\n keyParts = key.split('.')\n category = keyParts[ 0 ].substring(1)\n name = keyParts[ 1 ]\n\n if (keyParts.length === 1) {\n name = false\n cif[ category ] = value\n } else {\n if (!cif[ category ]) cif[ category ] = {}\n\n if (cif[ category ][ name ]) {\n if (Debug) Log.warn(category, name, 'already exists')\n } else {\n cif[ category ][ name ] = value\n }\n }\n\n if (!value) pendingValue = true\n\n currentCategory = category\n currentName = name\n }\n } else {\n if (pendingString) {\n // Log.log( \"STRING VALUE\", line );\n\n currentString += rawline\n } else if (pendingLoop) {\n // Log.log( \"LOOP VALUE\", line );\n\n if (!line) {\n continue\n } else if (currentCategory === 'atom_site') {\n const ls = line.split(reWhitespace)\n\n if (first) {\n authAsymId = pointerNames.indexOf('auth_asym_id')\n authSeqId = pointerNames.indexOf('auth_seq_id')\n labelSeqId = pointerNames.indexOf('label_seq_id')\n labelAtomId = pointerNames.indexOf('label_atom_id')\n labelCompId = pointerNames.indexOf('label_comp_id')\n labelAsymId = pointerNames.indexOf('label_asym_id')\n labelEntityId = pointerNames.indexOf('label_entity_id')\n labelAltId = pointerNames.indexOf('label_alt_id')\n CartnX = pointerNames.indexOf('Cartn_x')\n CartnY = pointerNames.indexOf('Cartn_y')\n CartnZ = pointerNames.indexOf('Cartn_z')\n id = pointerNames.indexOf('id')\n typeSymbol = pointerNames.indexOf('type_symbol')\n groupPDB = pointerNames.indexOf('group_PDB')\n bIsoOrEquiv = pointerNames.indexOf('B_iso_or_equiv')\n pdbxPDBmodelNum = pointerNames.indexOf('pdbx_PDB_model_num')\n\n pdbxPDBinsCode = pointerNames.indexOf('pdbx_PDB_ins_code')\n occupancy = pointerNames.indexOf('occupancy')\n\n first = false\n\n modelNum = parseInt(ls[ pdbxPDBmodelNum ])\n\n if (asTrajectory) {\n currentFrame = []\n currentCoord = 0\n }\n }\n\n //\n\n const _modelNum = parseInt(ls[ pdbxPDBmodelNum ])\n\n if (modelNum !== _modelNum) {\n if (asTrajectory) {\n if (modelIdx === 0) {\n frames.push(new Float32Array(currentFrame))\n }\n\n currentFrame = new Float32Array(atomStore.count * 3)\n frames.push(currentFrame)\n currentCoord = 0\n }\n\n modelIdx += 1\n }\n\n modelNum = _modelNum\n\n if (firstModelOnly && modelIdx > 0) continue\n\n //\n\n const atomname = ls[ labelAtomId ].replace(reDoubleQuote, '')\n if (cAlphaOnly && atomname !== 'CA') continue\n\n const x = parseFloat(ls[ CartnX ])\n const y = parseFloat(ls[ CartnY ])\n const z = parseFloat(ls[ CartnZ ])\n\n if (asTrajectory) {\n const frameOffset = currentCoord * 3\n\n currentFrame[ frameOffset + 0 ] = x\n currentFrame[ frameOffset + 1 ] = y\n currentFrame[ frameOffset + 2 ] = z\n\n currentCoord += 1\n\n if (modelIdx > 0) continue\n }\n\n //\n\n const resname = ls[ labelCompId ]\n const resno = parseInt(ls[ authSeqId !== -1 ? authSeqId : labelSeqId ])\n let inscode = ls[ pdbxPDBinsCode ]\n inscode = (inscode === '?') ? '' : inscode\n const chainname = ls[ authAsymId ]\n const chainid = ls[ labelAsymId ]\n const hetero = (ls[ groupPDB ][ 0 ] === 'H')\n\n //\n\n const element = ls[ typeSymbol ]\n const bfactor = parseFloat(ls[ bIsoOrEquiv ])\n const occ = parseFloat(ls[ occupancy ])\n let altloc = ls[ labelAltId ]\n altloc = (altloc === '.') ? '' : altloc\n\n atomStore.growIfFull()\n atomStore.atomTypeId[ idx ] = atomMap.add(atomname, element)\n\n atomStore.x[ idx ] = x\n atomStore.y[ idx ] = y\n atomStore.z[ idx ] = z\n atomStore.serial[ idx ] = parseInt(ls[ id ])\n atomStore.bfactor[ idx ] = isNaN(bfactor) ? 0 : bfactor\n atomStore.occupancy[ idx ] = isNaN(occ) ? 0 : occ\n atomStore.altloc[ idx ] = altloc.charCodeAt(0)\n\n sb.addAtom(modelIdx, chainname, chainid, resname, resno, hetero, undefined, inscode)\n\n if (Debug) {\n // check if one-to-many (chainname-asymId) relationship is\n // actually a many-to-many mapping\n const assignedChainname = asymIdDict[ chainid ]\n if (assignedChainname !== undefined && assignedChainname !== chainname) {\n if (Debug) Log.warn(assignedChainname, chainname)\n }\n }\n // chainname mapping: label_asym_id -> auth_asym_id\n asymIdDict[ chainid ] = chainname\n\n // entity mapping: chainIndex -> label_entity_id\n const entityId = ls[ labelEntityId ]\n if (!chainIndexDict[ entityId ]) {\n chainIndexDict[ entityId ] = new Set()\n }\n chainIndexDict[ entityId ].add(s.chainStore.count - 1)\n\n idx += 1\n } else {\n const ls = line.match(reQuotedWhitespace)\n const nn = ls!.length\n\n if (currentLoopIndex === loopPointers.length) {\n currentLoopIndex = 0\n }/* else if( currentLoopIndex + nn > loopPointers.length ){\n Log.warn( \"cif parsing error, wrong number of loop data entries\", nn, loopPointers.length );\n } */\n\n for (let j = 0; j < nn; ++j) {\n loopPointers[ currentLoopIndex + j ].push(ls![ j ])\n }\n\n (currentLoopIndex) += nn\n }\n\n pendingName = false\n } else if (line[0] === \"'\" && line[line.length - 1] === \"'\") {\n // Log.log( \"NEWLINE STRING\", line );\n\n const str = line.substring(1, line.length - 1)\n\n if (currentName === false) {\n cif[ currentCategory as string ] = str\n } else {\n cif[ currentCategory as string ][ currentName as string ] = str\n }\n } else if (pendingValue) {\n // Log.log( \"NEWLINE VALUE\", line );\n\n if (currentName === false) {\n cif[ currentCategory as string ] = line\n } else {\n cif[ currentCategory as string ][ currentName as string ] = line\n }\n } else {\n if (Debug) Log.log('CifParser._parse: unknown state', line)\n }\n }\n }\n }\n\n this.streamer.eachChunkOfLines(function (lines/*, chunkNo, chunkCount */) {\n _parseChunkOfLines(0, lines.length, lines)\n })\n\n if (cif.chem_comp && cif.chem_comp_atom && !cif.struct) {\n parseChemComp(cif, s, sb)\n sb.finalize()\n s.finalizeAtoms()\n s.finalizeBonds()\n assignResidueTypeBonds(s)\n } else if (cif.atom_site_type_symbol && cif.atom_site_label && cif.atom_site_fract_x) {\n parseCore(cif, s, sb)\n sb.finalize()\n s.finalizeAtoms()\n calculateBonds(s)\n s.finalizeBonds()\n // assignResidueTypeBonds( s );\n } else {\n var secStruct = processSecondaryStructure(cif, s, asymIdDict)\n processSymmetry(cif, s, asymIdDict)\n processConnections(cif, s, asymIdDict)\n processEntities(cif, s, chainIndexDict)\n\n if (cif.struct && cif.struct.title) {\n s.title = cif.struct.title.trim().replace(reTrimQuotes, '')\n }\n if (cif.entry && cif.entry.id) {\n s.id = cif.entry.id.trim().replace(reTrimQuotes, '')\n }\n\n // structure header (mimicking biojava)\n if (cif.pdbx_audit_revision_history) {\n if (cif.pdbx_audit_revision_history.revision_date) {\n ensureArray(cif.pdbx_audit_revision_history, 'revision_date')\n const dates = cif.pdbx_audit_revision_history.revision_date.filter(hasValue)\n if (dates.length) {\n s.header.releaseDate = dates[ 0 ]\n }\n }\n if (cif.pdbx_database_status.recvd_initial_deposition_date) {\n ensureArray(cif.pdbx_database_status, 'recvd_initial_deposition_date')\n const depDates = cif.pdbx_database_status.recvd_initial_deposition_date.filter(hasValue)\n if (depDates.length) {\n s.header.depositionDate = depDates[ 0 ]\n }\n }\n } else if (cif.database_PDB_rev) {\n if (cif.database_PDB_rev.date) {\n ensureArray(cif.database_PDB_rev, 'date')\n const dates = cif.database_PDB_rev.date.filter(hasValue)\n if (dates.length) {\n s.header.releaseDate = dates[ 0 ]\n }\n }\n if (cif.database_PDB_rev.date_original) {\n ensureArray(cif.database_PDB_rev, 'date_original')\n const depDates = cif.database_PDB_rev.date_original.filter(hasValue)\n if (depDates.length) {\n s.header.depositionDate = depDates[ 0 ]\n }\n }\n }\n if (cif.reflns && cif.reflns.d_resolution_high) {\n if (hasValue(cif.reflns.d_resolution_high)) {\n s.header.resolution = parseFloat(cif.reflns.d_resolution_high)\n }\n } else if (cif.refine && cif.refine.ls_d_res_high) {\n if (hasValue(cif.refine.ls_d_res_high)) {\n s.header.resolution = parseFloat(cif.refine.ls_d_res_high)\n }\n }\n if (cif.refine && cif.refine.ls_R_factor_R_free) {\n if (hasValue(cif.refine.ls_R_factor_R_free)) {\n s.header.rFree = parseFloat(cif.refine.ls_R_factor_R_free)\n }\n }\n if (cif.refine && cif.refine.ls_R_factor_R_work) {\n if (hasValue(cif.refine.ls_R_factor_R_work)) {\n s.header.rWork = parseFloat(cif.refine.ls_R_factor_R_work)\n }\n }\n if (cif.exptl && cif.exptl.method) {\n ensureArray(cif.exptl, 'method')\n s.header.experimentalMethods = cif.exptl.method.map(function (m: string) {\n return m.replace(reTrimQuotes, '')\n })\n }\n\n sb.finalize()\n s.finalizeAtoms()\n calculateBonds(s)\n s.finalizeBonds()\n\n if (!secStruct) {\n calculateSecondaryStructure(s)\n } else {\n assignSecondaryStructure(s, secStruct)\n }\n buildUnitcellAssembly(s)\n\n s.extraData.cif = cif\n }\n\n if (Debug) Log.timeEnd('CifParser._parse ' + this.name)\n }\n}\n\nParserRegistry.add('cif', CifParser)\nParserRegistry.add('mcif', CifParser)\nParserRegistry.add('mmcif', CifParser)\n\nexport default CifParser\n","/**\n * @file Gro Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport StructureParser from './structure-parser'\nimport {\n calculateBonds, calculateChainnames, calculateSecondaryStructure\n} from '../structure/structure-utils'\n\nclass GroParser extends StructureParser {\n get type () { return 'gro' }\n\n _parse () {\n // http://manual.gromacs.org/current/online/gro.html\n\n if (Debug) Log.time('GroParser._parse ' + this.name)\n\n var s = this.structure\n var sb = this.structureBuilder\n\n var firstModelOnly = this.firstModelOnly\n var asTrajectory = this.asTrajectory\n var cAlphaOnly = this.cAlphaOnly\n\n var frames = s.frames\n var boxes = s.boxes\n var currentFrame: Float32Array, currentCoord: number\n\n var firstLines = this.streamer.peekLines(3)\n\n s.title = firstLines[ 0 ].trim()\n\n // determine number of decimal places\n var ndec = firstLines[ 2 ].length - firstLines[ 2 ].lastIndexOf('.') - 1\n var lpos = 5 + ndec\n var xpos = 20\n var ypos = 20 + lpos\n var zpos = 20 + 2 * lpos\n\n //\n\n var atomname, resname, resno, serial\n\n var atomCount = parseInt(firstLines[ 1 ])\n var modelLineCount = atomCount + 3\n\n var atomMap = s.atomMap\n var atomStore = s.atomStore\n atomStore.resize(atomCount)\n\n var idx = 0\n var modelIdx = 0\n var lineNo = 0\n\n function _parseChunkOfLines (_i: number, _n: number, lines: string[]) {\n for (var i = _i; i < _n; ++i) {\n ++lineNo\n var l = lineNo - 1\n\n var line = lines[ i ]\n\n if (!line) continue\n\n if (l % modelLineCount === 0) {\n // Log.log( \"title\", line )\n\n if (asTrajectory) {\n currentFrame = new Float32Array(atomCount * 3)\n frames.push(currentFrame)\n currentCoord = 0\n }\n } else if (l % modelLineCount === 1) {\n\n // Log.log( \"atomCount\", line )\n\n } else if (l % modelLineCount === modelLineCount - 1) {\n var str = line.trim().split(/\\s+/)\n var box = new Float32Array(9)\n box[ 0 ] = parseFloat(str[ 0 ]) * 10\n box[ 4 ] = parseFloat(str[ 1 ]) * 10\n box[ 8 ] = parseFloat(str[ 2 ]) * 10\n boxes.push(box)\n\n if (firstModelOnly) {\n return true\n }\n\n modelIdx += 1\n } else {\n atomname = line.substr(10, 5).trim()\n if (cAlphaOnly && atomname !== 'CA') continue\n\n var x = parseFloat(line.substr(xpos, lpos)) * 10\n var y = parseFloat(line.substr(ypos, lpos)) * 10\n var z = parseFloat(line.substr(zpos, lpos)) * 10\n\n if (asTrajectory) {\n var j = currentCoord * 3\n\n currentFrame[ j + 0 ] = x\n currentFrame[ j + 1 ] = y\n currentFrame[ j + 2 ] = z\n\n currentCoord += 1\n\n if (l > modelLineCount) continue\n }\n\n resname = line.substr(5, 5).trim()\n resno = parseInt(line.substr(0, 5))\n serial = parseInt(line.substr(15, 5))\n\n atomStore.growIfFull()\n atomStore.atomTypeId[ idx ] = atomMap.add(atomname)\n\n atomStore.x[ idx ] = x\n atomStore.y[ idx ] = y\n atomStore.z[ idx ] = z\n atomStore.serial[ idx ] = serial\n\n sb.addAtom(modelIdx, '', '', resname, resno, false, 'l')\n\n idx += 1\n }\n }\n }\n\n this.streamer.eachChunkOfLines(function (lines/*, chunkNo, chunkCount */) {\n _parseChunkOfLines(0, lines.length, lines)\n })\n\n sb.finalize()\n s.finalizeAtoms()\n calculateChainnames(s)\n calculateBonds(s)\n s.finalizeBonds()\n\n calculateSecondaryStructure(s)\n\n if (Debug) Log.timeEnd('GroParser._parse ' + this.name)\n }\n}\n\nParserRegistry.add('gro', GroParser)\n\nexport default GroParser\n","/**\n * @file utf8-utils\n * @private\n * @author Alexander Rose \n * mostly copied from https://github.com/creationix/msgpack-js-browser\n * by Tim Caswell , MIT License, Copyright (c) 2013\n */\n\n\n// Encode string as utf8 into dataview at offset\nfunction utf8Write(view, offset, string) {\n var byteLength = view.byteLength;\n for(var i = 0, l = string.length; i < l; i++) {\n var codePoint = string.charCodeAt(i);\n\n // One byte of UTF-8\n if (codePoint < 0x80) {\n view.setUint8(offset++, codePoint >>> 0 & 0x7f | 0x00);\n continue;\n }\n\n // Two bytes of UTF-8\n if (codePoint < 0x800) {\n view.setUint8(offset++, codePoint >>> 6 & 0x1f | 0xc0);\n view.setUint8(offset++, codePoint >>> 0 & 0x3f | 0x80);\n continue;\n }\n\n // Three bytes of UTF-8.\n if (codePoint < 0x10000) {\n view.setUint8(offset++, codePoint >>> 12 & 0x0f | 0xe0);\n view.setUint8(offset++, codePoint >>> 6 & 0x3f | 0x80);\n view.setUint8(offset++, codePoint >>> 0 & 0x3f | 0x80);\n continue;\n }\n\n // Four bytes of UTF-8\n if (codePoint < 0x110000) {\n view.setUint8(offset++, codePoint >>> 18 & 0x07 | 0xf0);\n view.setUint8(offset++, codePoint >>> 12 & 0x3f | 0x80);\n view.setUint8(offset++, codePoint >>> 6 & 0x3f | 0x80);\n view.setUint8(offset++, codePoint >>> 0 & 0x3f | 0x80);\n continue;\n }\n throw new Error(\"bad codepoint \" + codePoint);\n }\n}\n\nfunction utf8ByteCount(string) {\n var count = 0;\n for(var i = 0, l = string.length; i < l; i++) {\n var codePoint = string.charCodeAt(i);\n if (codePoint < 0x80) {\n count += 1;\n continue;\n }\n if (codePoint < 0x800) {\n count += 2;\n continue;\n }\n if (codePoint < 0x10000) {\n count += 3;\n continue;\n }\n if (codePoint < 0x110000) {\n count += 4;\n continue;\n }\n throw new Error(\"bad codepoint \" + codePoint);\n }\n return count;\n}\n\n/**\n * encode data value (recursively) into binary encoded MessagePack v5 (http://msgpack.org/)\n * @param {Object|Array|String|Number|Boolean|null} value [description]\n * @param {DataView} view [description]\n * @param {Integer} offset [description]\n * @return {Integer} number of bytes written into view\n */\nfunction encode$1(value, view, offset) {\n var type = typeof value;\n\n // Strings Bytes\n if (type === \"string\") {\n var length = utf8ByteCount(value);\n // fix str\n if (length < 0x20) {\n view.setUint8(offset, length | 0xa0);\n utf8Write(view, offset + 1, value);\n return 1 + length;\n }\n // str 8\n if (length < 0x100) {\n view.setUint8(offset, 0xd9);\n view.setUint8(offset + 1, length);\n utf8Write(view, offset + 2, value);\n return 2 + length;\n }\n // str 16\n if (length < 0x10000) {\n view.setUint8(offset, 0xda);\n view.setUint16(offset + 1, length);\n utf8Write(view, offset + 3, value);\n return 3 + length;\n }\n // str 32\n if (length < 0x100000000) {\n view.setUint8(offset, 0xdb);\n view.setUint32(offset + 1, length);\n utf8Write(view, offset + 5, value);\n return 5 + length;\n }\n }\n\n if (value instanceof Uint8Array) {\n var length = value.byteLength;\n var bytes = new Uint8Array(view.buffer);\n // bin 8\n if (length < 0x100) {\n view.setUint8(offset, 0xc4);\n view.setUint8(offset + 1, length);\n bytes.set(value, offset + 2);\n return 2 + length;\n }\n // bin 16\n if (length < 0x10000) {\n view.setUint8(offset, 0xc5);\n view.setUint16(offset + 1, length);\n bytes.set(value, offset + 3);\n return 3 + length;\n }\n // bin 32\n if (length < 0x100000000) {\n view.setUint8(offset, 0xc6);\n view.setUint32(offset + 1, length);\n bytes.set(value, offset + 5);\n return 5 + length;\n }\n }\n\n if (type === \"number\") {\n if (!isFinite(value)) {\n throw new Error(\"Number not finite: \" + value);\n }\n\n // Floating point\n if (Math.floor(value) !== value) {\n view.setUint8(offset, 0xcb);\n view.setFloat64(offset + 1, value);\n return 9;\n }\n\n // Integers\n if (value >=0) {\n // positive fixnum\n if (value < 0x80) {\n view.setUint8(offset, value);\n return 1;\n }\n // uint 8\n if (value < 0x100) {\n view.setUint8(offset, 0xcc);\n view.setUint8(offset + 1, value);\n return 2;\n }\n // uint 16\n if (value < 0x10000) {\n view.setUint8(offset, 0xcd);\n view.setUint16(offset + 1, value);\n return 3;\n }\n // uint 32\n if (value < 0x100000000) {\n view.setUint8(offset, 0xce);\n view.setUint32(offset + 1, value);\n return 5;\n }\n throw new Error(\"Number too big 0x\" + value.toString(16));\n }\n // negative fixnum\n if (value >= -0x20) {\n view.setInt8(offset, value);\n return 1;\n }\n // int 8\n if (value >= -0x80) {\n view.setUint8(offset, 0xd0);\n view.setInt8(offset + 1, value);\n return 2;\n }\n // int 16\n if (value >= -0x8000) {\n view.setUint8(offset, 0xd1);\n view.setInt16(offset + 1, value);\n return 3;\n }\n // int 32\n if (value >= -0x80000000) {\n view.setUint8(offset, 0xd2);\n view.setInt32(offset + 1, value);\n return 5;\n }\n throw new Error(\"Number too small -0x\" + (-value).toString(16).substr(1));\n }\n\n // null\n if (value === null) {\n view.setUint8(offset, 0xc0);\n return 1;\n }\n\n // Boolean\n if (type === \"boolean\") {\n view.setUint8(offset, value ? 0xc3 : 0xc2);\n return 1;\n }\n\n // Container Types\n if (type === \"object\") {\n var length, size = 0;\n var isArray = Array.isArray(value);\n\n if (isArray) {\n length = value.length;\n }\n else {\n var keys = Object.keys(value);\n length = keys.length;\n }\n\n var size;\n if (length < 0x10) {\n view.setUint8(offset, length | (isArray ? 0x90 : 0x80));\n size = 1;\n }\n else if (length < 0x10000) {\n view.setUint8(offset, isArray ? 0xdc : 0xde);\n view.setUint16(offset + 1, length);\n size = 3;\n }\n else if (length < 0x100000000) {\n view.setUint8(offset, isArray ? 0xdd : 0xdf);\n view.setUint32(offset + 1, length);\n size = 5;\n }\n\n if (isArray) {\n for (var i = 0; i < length; i++) {\n size += encode$1(value[i], view, offset + size);\n }\n }\n else {\n for (var i = 0; i < length; i++) {\n var key = keys[i];\n size += encode$1(key, view, offset + size);\n size += encode$1(value[key], view, offset + size);\n }\n }\n\n return size;\n }\n throw new Error(\"Unknown type \" + type);\n}\n\nfunction encodedSize(value) {\n var type = typeof value;\n\n // Raw Bytes\n if (type === \"string\") {\n var length = utf8ByteCount(value);\n if (length < 0x20) {\n return 1 + length;\n }\n if (length < 0x100) {\n return 2 + length;\n }\n if (length < 0x10000) {\n return 3 + length;\n }\n if (length < 0x100000000) {\n return 5 + length;\n }\n }\n\n if (value instanceof Uint8Array) {\n var length = value.byteLength;\n if (length < 0x100) {\n return 2 + length;\n }\n if (length < 0x10000) {\n return 3 + length;\n }\n if (length < 0x100000000) {\n return 5 + length;\n }\n }\n\n if (type === \"number\") {\n // Floating Point\n // double\n if (Math.floor(value) !== value) return 9;\n\n // Integers\n if (value >=0) {\n // positive fixnum\n if (value < 0x80) return 1;\n // uint 8\n if (value < 0x100) return 2;\n // uint 16\n if (value < 0x10000) return 3;\n // uint 32\n if (value < 0x100000000) return 5;\n throw new Error(\"Number too big 0x\" + value.toString(16));\n }\n // negative fixnum\n if (value >= -0x20) return 1;\n // int 8\n if (value >= -0x80) return 2;\n // int 16\n if (value >= -0x8000) return 3;\n // int 32\n if (value >= -0x80000000) return 5;\n throw new Error(\"Number too small -0x\" + value.toString(16).substr(1));\n }\n\n // Boolean, null\n if (type === \"boolean\" || value === null) return 1;\n\n // Container Types\n if (type === \"object\") {\n var length, size = 0;\n if (Array.isArray(value)) {\n length = value.length;\n for (var i = 0; i < length; i++) {\n size += encodedSize(value[i]);\n }\n }\n else {\n var keys = Object.keys(value);\n length = keys.length;\n for (var i = 0; i < length; i++) {\n var key = keys[i];\n size += encodedSize(key) + encodedSize(value[key]);\n }\n }\n if (length < 0x10) {\n return 1 + size;\n }\n if (length < 0x10000) {\n return 3 + size;\n }\n if (length < 0x100000000) {\n return 5 + size;\n }\n throw new Error(\"Array or object too long 0x\" + length.toString(16));\n }\n throw new Error(\"Unknown type \" + type);\n}\n\nfunction encodeMsgpack(value) {\n var buffer = new ArrayBuffer(encodedSize(value));\n var view = new DataView(buffer);\n encode$1(value, view, 0);\n return new Uint8Array(buffer);\n}\n\n/**\n * @file mmtf-constants\n * @private\n * @author Alexander Rose \n */\n\n\nvar PassThroughFields = [\n \"mmtfVersion\", \"mmtfProducer\",\n \"unitCell\", \"spaceGroup\", \"structureId\", \"title\",\n \"depositionDate\", \"releaseDate\",\n \"experimentalMethods\", \"resolution\", \"rFree\", \"rWork\",\n \"bioAssemblyList\", \"ncsOperatorList\", \"entityList\", \"groupList\",\n \"numBonds\", \"numAtoms\", \"numGroups\", \"numChains\", \"numModels\",\n \"groupsPerChain\", \"chainsPerModel\",\n];\n\nvar EncodedFields = [\n\t// required\n \"xCoordList\", \"yCoordList\", \"zCoordList\",\n \"groupIdList\", \"groupTypeList\",\n \"chainIdList\",\n // optional\n \"bFactorList\", \"atomIdList\", \"altLocList\", \"occupancyList\",\n \"secStructList\", \"insCodeList\", \"sequenceIndexList\",\n \"chainNameList\",\n \"bondAtomList\", \"bondOrderList\"\n];\n\nvar AllFields = PassThroughFields.concat( EncodedFields );\n\n/**\n * @file mmtf-utils\n * @private\n * @author Alexander Rose \n */\n\n/**\n * mmtf utils module.\n * @module MmtfUtils\n */\n\n\nfunction getView( ctor, typedArray, elemSize ){\n return typedArray ? new ctor(\n typedArray.buffer,\n typedArray.byteOffset,\n typedArray.byteLength / ( elemSize || 1 )\n ) : undefined;\n}\n\nfunction getDataView( typedArray ){\n return getView( DataView, typedArray );\n}\n\n/**\n * get an Uint8Array view on the input array memory\n * @static\n * @param {TypedArray} dataArray - input array\n * @return {Uint8Array} new view on the input array memory\n */\nfunction getUint8View( typedArray ){\n return getView( Uint8Array, typedArray );\n}\n\n/**\n * get an Int8Array view on the input array memory\n * @static\n * @param {TypedArray} dataArray - input array\n * @return {Int8Array} new view on the input array memory\n */\nfunction getInt8View( typedArray ){\n return getView( Int8Array, typedArray );\n}\n\n/**\n * get an Int32Array view on the input array memory\n * @static\n * @param {TypedArray} dataArray - input array\n * @return {Int32Array} new view on the input array memory\n */\nfunction getInt32View( typedArray ){\n return getView( Int32Array, typedArray, 4 );\n}\n\nfunction getFloat32View( typedArray ){\n return getView( Float32Array, typedArray, 4 );\n}\n\n\n/**\n * get an Int16Array copy of the the input array data\n * @static\n * @param {TypedArray} view - input data in big endian format\n * @param {Int16Array} [dataArray] - pre-allocated output array\n * @return {Int16Array} copy of the input array data\n */\nfunction decodeInt16( bytes, output ){\n var n = bytes.length / 2;\n if( !output ) output = new Int16Array( n );\n for( var i = 0, i2 = 0; i < n; ++i, i2 += 2 ){\n output[ i ] = bytes[ i2 ] << 8 ^ bytes[ i2 + 1 ] << 0;\n }\n return output;\n}\n\n/**\n * make big endian buffer of an int16 array\n * @static\n * @param {Array|TypedArray} array - array of int16 values\n * @return {ArrayBuffer} big endian buffer\n */\nfunction encodeInt16( array, output ){\n var n = array.length;\n if( !output ) output = new Uint8Array( 2 * n );\n var dv = getDataView( output );\n for( var i = 0; i < n; ++i ){\n dv.setInt16( 2 * i, array[ i ] );\n }\n return getUint8View( output );\n}\n\n/**\n * get an Int32Array copy of the the input array data\n * @static\n * @param {TypedArray} view - input data in big endian format\n * @param {Int32Array} [dataArray] - pre-allocated output array\n * @return {Int32Array} copy of the input array data\n */\nfunction decodeInt32( bytes, output ){\n var n = bytes.length / 4;\n if( !output ) output = new Int32Array( n );\n for( var i = 0, i4 = 0; i < n; ++i, i4 += 4 ){\n output[ i ] = (\n bytes[ i4 ] << 24 ^ bytes[ i4 + 1 ] << 16 ^\n bytes[ i4 + 2 ] << 8 ^ bytes[ i4 + 3 ] << 0\n );\n }\n return output;\n}\n\n/**\n * make big endian buffer of an int32 array\n * @static\n * @param {Array|TypedArray} array - array of int32 values\n * @return {ArrayBuffer} big endian buffer\n */\nfunction encodeInt32( array, output ){\n var n = array.length;\n if( !output ) output = new Uint8Array( 4 * n );\n var dv = getDataView( output );\n for( var i = 0; i < n; ++i ){\n dv.setInt32( 4 * i, array[ i ] );\n }\n return getUint8View( output );\n}\n\nfunction decodeFloat32( bytes, output ){\n var n = bytes.length;\n if( !output ) output = new Float32Array( n / 4 );\n var dvOut = getDataView( output );\n var dvIn = getDataView( bytes );\n for( var i = 0, i4 = 0, il = n / 4; i < il; ++i, i4 += 4 ){\n dvOut.setFloat32( i4, dvIn.getFloat32( i4 ), true );\n }\n return output;\n}\n\n/**\n * decode integers into floats using given divisor\n * example:\n * intArray: [ 12, 34, 543, 687, 2, 0, 4689 ]\n * divisor: 100\n * return: [ 0.12, 0.34, 5.43, 6.87, 0.02, 0.00, 46.89 ]\n * @static\n * @param {TypedArray|Array} intArray - input array containing integers\n * @param {Number} divisor - number to devide the integers to obtain floats\n * @param {Float32Array} [dataArray] - pre-allocated output array\n * @return {Float32Array} decoded array\n */\nfunction decodeInteger( intArray, divisor, output ){\n var n = intArray.length;\n var invDiv = 1/divisor;\n if( !output ) output = new Float32Array( n );\n for( var i = 0; i < n; ++i ){\n // multiply by inverse of the divisor which is faster then division\n output[ i ] = intArray[ i ] * invDiv;\n }\n return output;\n}\n\nfunction encodeInteger( floatArray, factor, output ){\n var n = floatArray.length;\n if( !output ) output = new Int32Array( n );\n for( var i = 0; i < n; ++i ){\n output[ i ] = Math.round( floatArray[ i ] * factor );\n }\n return output;\n}\n\n\n\n/**\n * perform run-length decoding of input array\n * example:\n * array: [ 0, 2, 3, 5 ] // pairs of values and length of a run\n * return: [ 0, 0, 3, 3, 3, 3, 3 ]\n * @static\n * @param {TypedArray|Array} array - run-length encoded input array\n * @param {TypedArray|Array} [dataArray] - pre-allocated output array\n * @return {TypedArray|Array} decoded array\n */\nfunction decodeRun( array, output ){\n var i, il;\n if( !output ){\n // calculate the length the decoded array will have\n var fullLength = 0;\n for( i = 0, il = array.length; i < il; i+=2 ){\n fullLength += array[ i + 1 ];\n }\n // create a new array of the same type of the input array\n output = new array.constructor( fullLength );\n }\n var dataOffset = 0;\n for( i = 0, il = array.length; i < il; i+=2 ){\n var value = array[ i ]; // value to be repeated\n var length = array[ i + 1 ]; // number of repeats\n for( var j = 0; j < length; ++j ){\n output[ dataOffset ] = value;\n ++dataOffset;\n }\n }\n return output;\n}\n\nfunction encodeRun( array ){\n if( array.length === 0 ) return new Int32Array();\n var i, il;\n // calculate output size\n var fullLength = 2;\n for( i = 1, il = array.length; i < il; ++i ){\n if( array[ i - 1 ] !== array[ i ] ){\n fullLength += 2;\n }\n }\n var output = new Int32Array( fullLength );\n var offset = 0;\n var runLength = 1;\n for( i = 1, il = array.length; i < il; ++i ){\n if( array[ i - 1 ] !== array[ i ] ){\n output[ offset ] = array[ i - 1 ];\n output[ offset + 1 ] = runLength;\n runLength = 1;\n offset += 2;\n }else{\n ++runLength;\n }\n }\n output[ offset ] = array[ array.length - 1 ];\n output[ offset + 1 ] = runLength;\n return output;\n}\n\n\n\n/**\n * perform delta decoding of the input array\n * by iterativly adding the ith element's value to the i+1th\n * example:\n * dataArray: [ 0, 2, 1, 2, 1, 1, -4, -2, 9 ]\n * return: [ 0, 2, 3, 5, 6, 7, 3, 1, 10 ]\n * @static\n * @param {TypedArray|Array} dataArray - delta encoded input array\n * @return {TypedArray|Array} decoded array\n */\nfunction decodeDelta( array, output ){\n var n = array.length;\n if( !output ) output = new array.constructor( n );\n if( n ) output[ 0 ] = array[ 0 ];\n for( var i = 1; i < n; ++i ){\n output[ i ] = array[ i ] + output[ i - 1 ];\n }\n return output;\n}\n\nfunction encodeDelta( array, output ){\n var n = array.length;\n if( !output ) output = new array.constructor( n );\n output[ 0 ] = array[ 0 ];\n for( var i = 1; i < n; ++i ){\n output[ i ] = array[ i ] - array[ i - 1 ];\n }\n return output;\n}\n\n\n\n/**\n * [decodePacking description]\n * @param {Int16Array|Int8Array} int16or8 [description]\n * @param {Int32Array} output [description]\n * @return {Int32Array} [description]\n */\nfunction decodePacking( int16or8, output ){\n var upperLimit = int16or8 instanceof Int8Array ? 0x7F : 0x7FFF;\n var lowerLimit = -upperLimit - 1;\n var n = int16or8.length;\n var i, j;\n if( !output ){\n var fullLength = 0;\n for( i = 0; i < n; ++i ){\n if( int16or8[ i ] < upperLimit && int16or8[ i ] > lowerLimit ){\n ++fullLength;\n }\n }\n output = new Int32Array( fullLength );\n }\n i = 0;\n j = 0;\n while( i < n ){\n var value = 0;\n while( int16or8[ i ] === upperLimit || int16or8[ i ] === lowerLimit ){\n value += int16or8[ i ];\n ++i;\n }\n value += int16or8[ i ];\n ++i;\n output[ j ] = value;\n ++j;\n }\n return output;\n}\n\n/**\n * integer packing using recursive indexing\n * @param {Array|TyepedArray} intArray [description]\n * @param {Boolean} useInt8 [description]\n * @return {Int16Array|Int8Array} [description]\n */\nfunction encodePacking( intArray, useInt8 ){\n var upperLimit = useInt8 ? 0x7F : 0x7FFF;\n var lowerLimit = -upperLimit - 1;\n var i;\n var n = intArray.length;\n var size = 0;\n for( i = 0; i < n; ++i ){\n var value = intArray[ i ];\n if( value === 0 ){\n ++size;\n }else if( value === upperLimit || value === lowerLimit ){\n size += 2;\n }else if( value > 0) {\n size += Math.ceil( value / upperLimit );\n }else {\n size += Math.ceil( value / lowerLimit );\n }\n }\n var output = useInt8 ? new Int8Array( size ) : new Int16Array( size );\n var j = 0;\n for( i = 0; i < n; ++i ){\n var value = intArray[ i ];\n if( value >= 0) {\n while( value >= upperLimit ){\n output[ j ] = upperLimit;\n ++j;\n value -= upperLimit;\n }\n }else{\n while( value <= lowerLimit ){\n output[ j ] = lowerLimit;\n ++j;\n value -= lowerLimit;\n }\n }\n output[ j ] = value;\n ++j;\n }\n return output;\n}\n\n\n\nfunction decodeDeltaRun( array, output ){\n return decodeDelta( decodeRun( array ), output );\n}\n\nfunction encodeDeltaRun( array ){\n return encodeRun( encodeDelta( array ) );\n}\n\n\n\n/**\n * perform run-length decoding followed (@see decodeRunLength)\n * by decoding integers into floats using given divisor (@see decodeIntegerToFloat)\n * example:\n * array: [ 320, 3, 100, 2 ]\n * divisor: 100\n * return: [ 3.20, 3.20, 3.20, 1.00, 1.00 ]\n * @static\n * @param {Uint8Array} array - run-length encoded int32 array as bytes in big endian format\n * @param {Integer} divisor - number to devide the integers to obtain floats\n * @param {Float32Array} dataArray - pre-allocated output array\n * @return {Float32Array} decoded array\n */\nfunction decodeIntegerRun( intArray, divisor, output ){\n return decodeInteger(\n decodeRun( intArray, getInt32View( output ) ), divisor, output\n );\n}\n\nfunction encodeIntegerRun( floatArray, factor ){\n return encodeRun( encodeInteger( floatArray, factor ) );\n}\n\n\n\nfunction decodeIntegerDelta( intArray, divisor, output ){\n return decodeInteger(\n decodeDelta( intArray, getInt32View( output ) ), divisor, output\n );\n}\n\nfunction encodeIntegerDelta( floatArray, factor, output ){\n return encodeDelta( encodeInteger( floatArray, factor ), output );\n}\n\n\n\nfunction decodeIntegerPacking( int16or8, divisor, output ){\n return decodeInteger(\n decodePacking( int16or8, getInt32View( output ) ), divisor, output\n );\n}\n\nfunction decodeIntegerDeltaPacking( int16or8, divisor, output ){\n var unpacked = decodePacking( int16or8, getInt32View( output ) );\n return decodeIntegerDelta( unpacked, divisor, getFloat32View( unpacked ) );\n}\n\nfunction encodeIntegerDeltaPacking( floatArray, factor, useInt8 ){\n return encodePacking( encodeIntegerDelta( floatArray, factor ), useInt8 );\n}\n\n\n\nfunction decodeBytes( bytes ){\n var dv = getDataView( bytes );\n var type = dv.getInt32( 0 );\n var size = dv.getInt32( 4 );\n var param = bytes.subarray( 8, 12 );\n var bytes = bytes.subarray( 12 );\n return [ type, bytes, size, param ];\n}\n\nfunction encodeBytes( type, size, param, bytes ){\n var buffer = new ArrayBuffer( 12 + bytes.byteLength );\n var out = new Uint8Array( buffer );\n var dv = new DataView( buffer );\n dv.setInt32( 0, type );\n dv.setInt32( 4, size );\n if( param ) out.set( param, 8 );\n out.set( bytes, 12 );\n return out;\n}\n\nfunction passInt8( int8 ){\n var size = int8.length;\n var bytes = getUint8View( int8 );\n return encodeBytes( 2, size, undefined, bytes );\n}\n\nfunction passInt32( int32 ){\n var size = int32.length;\n var bytes = encodeInt32( int32 );\n return encodeBytes( 4, size, undefined, bytes );\n}\n\nfunction passString( stringBytes, length ){\n var size = stringBytes.length / length;\n var param = encodeInt32([ length ]);\n var bytes = getUint8View( stringBytes );\n return encodeBytes( 5, size, param, bytes );\n}\n\nfunction runChar( charBytes ){\n var size = charBytes.length;\n var bytes = encodeInt32( encodeRun( charBytes ) );\n return encodeBytes( 6, size, undefined, bytes );\n}\n\nfunction deltaRun( int32 ){\n var size = int32.length;\n var bytes = encodeInt32( encodeDeltaRun( int32 ) );\n return encodeBytes( 8, size, undefined, bytes );\n}\n\nfunction integerRun( float32, factor ){\n var size = float32.length;\n var param = encodeInt32([ factor ]);\n var bytes = encodeInt32( encodeIntegerRun( float32, factor ) );\n return encodeBytes( 9, size, param, bytes );\n}\n\nfunction integerDeltaPacking16( float32, factor ){\n var size = float32.length;\n var param = encodeInt32([ factor ]);\n var bytes = encodeInt16( encodeIntegerDeltaPacking( float32, factor ) );\n return encodeBytes( 10, size, param, bytes );\n}\n\nfunction encodeMmtf( inputDict ){\n\n var outputDict = {};\n\n // copy some fields over from the input dict\n PassThroughFields.forEach( function( name ){\n if( inputDict[ name ] !== undefined ){\n outputDict[ name ] = inputDict[ name ];\n }\n } );\n\n //////////////\n // bond data\n\n // encode inter group bond atom indices, i.e. get bytes in big endian order\n if( inputDict.bondAtomList ){\n outputDict.bondAtomList = passInt32( inputDict.bondAtomList );\n }\n\n // encode inter group bond orders, i.e. get bytes\n if( inputDict.bondOrderList ){\n outputDict.bondOrderList = passInt8( inputDict.bondOrderList );\n }\n\n //////////////\n // atom data\n\n // split-list delta & integer encode x, y, z atom coords\n outputDict.xCoordList = integerDeltaPacking16( inputDict.xCoordList, 1000 );\n outputDict.yCoordList = integerDeltaPacking16( inputDict.yCoordList, 1000 );\n outputDict.zCoordList = integerDeltaPacking16( inputDict.zCoordList, 1000 );\n\n // split-list delta & integer encode b-factors\n if( inputDict.bFactorList ){\n outputDict.bFactorList = integerDeltaPacking16( inputDict.bFactorList, 100 );\n }\n\n // delta & run-length encode atom ids\n if( inputDict.atomIdList ){\n outputDict.atomIdList = deltaRun( inputDict.atomIdList );\n }\n\n // run-length encode alternate labels\n if( inputDict.altLocList ){\n outputDict.altLocList = runChar( inputDict.altLocList );\n }\n\n // run-length & integer encode occupancies\n if( inputDict.occupancyList ){\n outputDict.occupancyList = integerRun( inputDict.occupancyList, 100 );\n }\n\n ///////////////\n // group data\n\n // run-length & delta encode group numbers\n outputDict.groupIdList = deltaRun( inputDict.groupIdList );\n\n // encode group types, i.e. get int32 array\n outputDict.groupTypeList = passInt32( inputDict.groupTypeList );\n\n // encode secondary structure, i.e. get bytes\n if( inputDict.secStructList ){\n outputDict.secStructList = passInt8( inputDict.secStructList, 1 );\n }\n\n // run-length encode insertion codes\n if( inputDict.insCodeList ){\n outputDict.insCodeList = runChar( inputDict.insCodeList );\n }\n\n // run-length & delta encode sequence indices\n if( inputDict.sequenceIndexList ){\n outputDict.sequenceIndexList = deltaRun( inputDict.sequenceIndexList );\n }\n\n ///////////////\n // chain data\n\n // encode chain ids, i.e. get bytes\n outputDict.chainIdList = passString( inputDict.chainIdList, 4 );\n\n // encode chain names, i.e. get bytes\n if( inputDict.chainNameList ){\n outputDict.chainNameList = passString( inputDict.chainNameList, 4 );\n }\n\n return outputDict;\n\n}\n\n/**\n * @file msgpack-decode\n * @private\n * @author Alexander Rose \n */\n\n/**\n * msgpack decode module.\n * @module MsgpackDecode\n */\n\n/**\n * decode binary encoded MessagePack v5 (http://msgpack.org/) data\n * @static\n * @param {Uint8Array} buffer - binary encoded MessagePack data\n * @return {Object|Array|String|Number|Boolean|null} decoded Messagepack data\n */\nfunction decodeMsgpack(buffer) {\n // Loosely based on\n // The MIT License (MIT)\n // Copyright (c) 2013 Tim Caswell \n // https://github.com/creationix/msgpack-js\n var offset = 0;\n var dataView = new DataView(buffer.buffer);\n\n /**\n * decode all key-value pairs of a map into an object\n * @param {Integer} length - number of key-value pairs\n * @return {Object} decoded map\n */\n function map(length) {\n var value = {};\n for (var i = 0; i < length; i++) {\n var key = parse();\n value[key] = parse();\n }\n return value;\n }\n\n /**\n * decode binary array\n * @param {Integer} length - number of elements in the array\n * @return {Uint8Array} decoded array\n */\n function bin(length) {\n var value = buffer.subarray(offset, offset + length);\n offset += length;\n return value;\n }\n\n /**\n * decode string\n * @param {Integer} length - number string characters\n * @return {String} decoded string\n */\n function str(length) {\n var array = buffer.subarray(offset, offset + length);\n offset += length;\n // limit number of arguments to String.fromCharCode to something\n // browsers can handle, see http://stackoverflow.com/a/22747272\n var chunkSize = 0xffff;\n if(length > chunkSize){\n var c = [];\n for(var i = 0; i < array.length; i += chunkSize) {\n c.push(String.fromCharCode.apply(\n null, array.subarray(i, i + chunkSize)\n ));\n }\n return c.join(\"\");\n }else{\n return String.fromCharCode.apply(null, array);\n }\n }\n\n /**\n * decode array\n * @param {Integer} length - number of array elements\n * @return {Array} decoded array\n */\n function array(length) {\n var value = new Array(length);\n for (var i = 0; i < length; i++) {\n value[i] = parse();\n }\n return value;\n }\n\n /**\n * recursively parse the MessagePack data\n * @return {Object|Array|String|Number|Boolean|null} decoded MessagePack data\n */\n function parse() {\n var type = buffer[offset];\n var value, length, extType;\n // Positive FixInt\n if ((type & 0x80) === 0x00) {\n offset++;\n return type;\n }\n // FixMap\n if ((type & 0xf0) === 0x80) {\n length = type & 0x0f;\n offset++;\n return map(length);\n }\n // FixArray\n if ((type & 0xf0) === 0x90) {\n length = type & 0x0f;\n offset++;\n return array(length);\n }\n // FixStr\n if ((type & 0xe0) === 0xa0) {\n length = type & 0x1f;\n offset++;\n return str(length);\n }\n // Negative FixInt\n if ((type & 0xe0) === 0xe0) {\n value = dataView.getInt8(offset);\n offset++;\n return value;\n }\n switch (type) {\n // nil\n case 0xc0:\n offset++;\n return null;\n // 0xc1: (never used, could be employed for padding)\n // false\n case 0xc2:\n offset++;\n return false;\n // true\n case 0xc3:\n offset++;\n return true;\n // bin 8\n case 0xc4:\n length = dataView.getUint8(offset + 1);\n offset += 2;\n return bin(length);\n // bin 16\n case 0xc5:\n length = dataView.getUint16(offset + 1);\n offset += 3;\n return bin(length);\n // bin 32\n case 0xc6:\n length = dataView.getUint32(offset + 1);\n offset += 5;\n return bin(length);\n // // ext 8\n // case 0xc7:\n // length = dataView.getUint8(offset + 1);\n // extType = dataView.getUint8(offset + 2);\n // offset += 3;\n // return [extType, bin(length)];\n // // ext 16\n // case 0xc8:\n // length = dataView.getUint16(offset + 1);\n // extType = dataView.getUint8(offset + 3);\n // offset += 4;\n // return [extType, bin(length)];\n // // ext 32\n // case 0xc9:\n // length = dataView.getUint32(offset + 1);\n // extType = dataView.getUint8(offset + 5);\n // offset += 6;\n // return [extType, bin(length)];\n // float 32\n case 0xca:\n value = dataView.getFloat32(offset + 1);\n offset += 5;\n return value;\n // float 64\n case 0xcb:\n value = dataView.getFloat64(offset + 1);\n offset += 9;\n return value;\n // uint8\n case 0xcc:\n value = buffer[offset + 1];\n offset += 2;\n return value;\n // uint 16\n case 0xcd:\n value = dataView.getUint16(offset + 1);\n offset += 3;\n return value;\n // uint 32\n case 0xce:\n value = dataView.getUint32(offset + 1);\n offset += 5;\n return value;\n // // uint64\n // case 0xcf:\n // // FIXME not available/representable in JS\n // // largest possible int in JS is 2^53\n // // value = dataView.getUint64(offset + 1);\n // offset += 9;\n // return 0;\n // int 8\n case 0xd0:\n value = dataView.getInt8(offset + 1);\n offset += 2;\n return value;\n // int 16\n case 0xd1:\n value = dataView.getInt16(offset + 1);\n offset += 3;\n return value;\n // int 32\n case 0xd2:\n value = dataView.getInt32(offset + 1);\n offset += 5;\n return value;\n // // int 64\n // case 0xd3:\n // // FIXME not available/representable in JS\n // // largest possible int in JS is 2^53\n // // value = dataView.getInt64(offset + 1);\n // offset += 9;\n // return 0;\n\n // // fixext 1\n // case 0xd4:\n // extType = dataView.getUint8(offset + 1);\n // offset += 2;\n // return [extType, bin(1)];\n // // fixext 2\n // case 0xd5:\n // extType = dataView.getUint8(offset + 1);\n // offset += 2;\n // return [extType, bin(2)];\n // // fixext 4\n // case 0xd6:\n // extType = dataView.getUint8(offset + 1);\n // offset += 2;\n // return [extType, bin(4)];\n // // fixext 8\n // case 0xd7:\n // extType = dataView.getUint8(offset + 1);\n // offset += 2;\n // return [extType, bin(8)];\n // // fixext 16\n // case 0xd8:\n // extType = dataView.getUint8(offset + 1);\n // offset += 2;\n // return [extType, bin(16)];\n // str 8\n case 0xd9:\n length = dataView.getUint8(offset + 1);\n offset += 2;\n return str(length);\n // str 16\n case 0xda:\n length = dataView.getUint16(offset + 1);\n offset += 3;\n return str(length);\n // str 32\n case 0xdb:\n length = dataView.getUint32(offset + 1);\n offset += 5;\n return str(length);\n // array 16\n case 0xdc:\n length = dataView.getUint16(offset + 1);\n offset += 3;\n return array(length);\n // array 32\n case 0xdd:\n length = dataView.getUint32(offset + 1);\n offset += 5;\n return array(length);\n // map 16:\n case 0xde:\n length = dataView.getUint16(offset + 1);\n offset += 3;\n return map(length);\n // map 32\n case 0xdf:\n length = dataView.getUint32(offset + 1);\n offset += 5;\n return map(length);\n }\n\n throw new Error(\"Unknown type 0x\" + type.toString(16));\n }\n\n // start the recursive parsing\n return parse();\n}\n\n/**\n * Fields shared in encoded and decoded mmtf data objects.\n * @typedef {Object} module:MmtfDecode.SharedMmtfData\n * @property {String} mmtfVersion - MMTF specification version\n * @property {String} mmtfProducer - Program that created the file\n * @property {Float[]} [unitCell] - Crystallographic unit cell\n * @property {Float} unitCell.0 - x length\n * @property {Float} unitCell.1 - y length\n * @property {Float} unitCell.2 - z length\n * @property {Float} unitCell.3 - alpha angle\n * @property {Float} unitCell.4 - beta angle\n * @property {Float} unitCell.5 - gamma angle\n * @property {String} [spaceGroup] - Hermann-Mauguin symbol\n * @property {String} [structureId] - Some reference, e.g. a PDB ID\n * @property {String} [title] - Short description\n * @property {String} [depositionDate] - Deposition date in YYYY-MM-DD format\n * @property {String} [releaseDate] - Release date in YYYY-MM-DD format\n * @property {String[]} [experimentalMethods] - Structure determination methods\n * @property {Float} [resolution] - Resolution in Å\n * @property {Float} [rFree] - R-free value\n * @property {Float} [rWork] - R-work value\n * @property {Integer} numBonds - Number of bonds\n * @property {Integer} numAtoms - Number of atoms\n * @property {Integer} numGroups - Number of groups (residues)\n * @property {Integer} numChains - Number of chains\n * @property {Integer} numModels - Number of models\n * @property {Integer[]} chainsPerModel - List of number of chains in each model\n * @property {Integer[]} groupsPerChain - List of number of groups in each chain\n * @property {Entity[]} [entityList] - List of entity objects\n * @property {Integer[]} entityList.chainIndexList - Pointers into chain data fields\n * @property {String} entityList.description - Description of the entity\n * @property {String} entityList.type - Name of the entity type\n * @property {String} entityList.sequence - One letter code sequence\n * @property {Assembly[]} [bioAssemblyList] - List of assembly objects\n * @property {Transform[]} bioAssemblyList.transformList - List of transform objects\n * @property {Integer[]} bioAssemblyList.transformList.chainIndexList - Pointers into chain data fields\n * @property {Float[]} bioAssemblyList.transformList.matrix - 4x4 transformation matrix\n * @property {Array[]} [ncsOperatorList] - List of ncs operator matrices\n * @property {Float[]} ncsOperatorList. - 4x4 transformation matrix\n * @property {GroupType[]} groupList - List of groupType objects\n * @property {Integer[]} groupList.formalChargeList - List of atom formal charges\n * @property {String[]} groupList.elementList - List of elements\n * @property {String[]} groupList.atomNameList - List of atom names\n * @property {Integer[]} groupList.bondAtomList - List of bonded atom indices\n * @property {Integer[]} groupList.bondOrderList - List of bond orders\n * @property {String} groupList.groupName - The name of the group\n * @property {String} groupList.singleLetterCode - The single letter code\n * @property {String} groupList.chemCompType - The chemical component type\n */\n\n/**\n * Encoded mmtf data object. Also includes the fields from {@link module:MmtfDecode.SharedMmtfData}. See MMTF specification on how they are encoded.\n * @typedef {Object} module:MmtfDecode.EncodedMmtfData\n * @mixes module:MmtfDecode.SharedMmtfData\n * @property {Uint8Array} [bondAtomList] - Encoded bonded atom indices\n * @property {Uint8Array} [bondOrderList] - Encoded bond orders\n * @property {Uint8Array} xCoordBig - Encoded x coordinates in Å, part 1\n * @property {Uint8Array} xCoordSmall - Encoded x coordinates in Å, part 2\n * @property {Uint8Array} yCoordBig - Encoded y coordinates in Å, part 1\n * @property {Uint8Array} yCoordSmall - Encoded y coordinates in Å, part 2\n * @property {Uint8Array} yCoordBig - Encoded y coordinates in Å, part 1\n * @property {Uint8Array} yCoordSmall - Encoded y coordinates in Å, part 2\n * @property {Uint8Array} [bFactorBig] - Encoded B-factors in Å^2, part 1\n * @property {Uint8Array} [bFactorSmall] - Encoded B-factors in Å^2, part 2\n * @property {Uint8Array} [atomIdList] - Encoded atom ids\n * @property {Uint8Array} [altLocList] - Encoded alternate location labels\n * @property {Uint8Array} [occupancyList] - Encoded occupancies\n * @property {Uint8Array} groupIdList - Encoded group ids\n * @property {Uint8Array} groupTypeList - Encoded group types\n * @property {Uint8Array} [secStructList] - Encoded secondary structure codes\n * @property {Uint8Array} [insCodeList] - Encoded insertion codes\n * @property {Uint8Array} [seuenceIdList] - Encoded sequence ids\n * @property {Uint8Array} chainIdList - Encoded chain ids\n * @property {Uint8Array} [chainNameList] - Encoded chain names\n */\n\n/**\n * Decoded mmtf data object. Also includes fields the from {@link module:MmtfDecode.SharedMmtfData}.\n * @typedef {Object} module:MmtfDecode.MmtfData\n * @mixes module:MmtfDecode.SharedMmtfData\n * @property {Int32Array} [bondAtomList] - List of bonded atom indices\n * @property {Uint8Array} [bondOrderList] - List of bond orders\n * @property {Float32Array} xCoordList - List of x coordinates in Å\n * @property {Float32Array} yCoordList - List of y coordinates in Å\n * @property {Float32Array} zCoordList - List of z coordinates in Å\n * @property {Float32Array} [bFactorList] - List of B-factors in Å^2\n * @property {Int32Array} [atomIdList] - List of atom ids\n * @property {Uint8Array} [altLocList] - List of alternate location labels\n * @property {Float32Array} [occupancyList] - List of occupancies\n * @property {Int32Array} groupIdList - List of group ids\n * @property {Int32Array} groupTypeList - List of group types\n * @property {Int8Array} [secStructList] - List of secondary structure codes, encoding\n * 0: pi helix, 1: bend, 2: alpha helix, 3: extended,\n * 4: 3-10 helix, 5: bridge, 6: turn, 7: coil, -1: undefined\n * @property {Uint8Array} [insCodeList] - List of insertion codes\n * @property {Int32Array} [seuenceIdList] - List of sequence ids\n * @property {Uint8Array} chainIdList - List of chain ids\n * @property {Uint8Array} [chainNameList] - List of chain names\n */\n\n\n/**\n * [performDecoding description]\n * @param {Integer} bytes [description]\n * @param {Integer} size [description]\n * @param {Uint8Array} param [description]\n * @return {TypedArray} [description]\n */\nfunction performDecoding( type, bytes, size, param ){\n\n switch( type ){\n case 1:\n return decodeFloat32( bytes );\n case 2:\n return getInt8View( bytes );\n case 3:\n return decodeInt16( bytes );\n case 4:\n return decodeInt32( bytes );\n case 5:\n // var length = decodeInt32( param )[ 0 ];\n return getUint8View( bytes ); // interpret as string array\n case 6:\n // interpret as char array\n return decodeRun( decodeInt32( bytes ), new Uint8Array( size ) );\n case 7:\n return decodeRun( decodeInt32( bytes ) )\n case 8:\n return decodeDeltaRun( decodeInt32( bytes ) );\n case 9:\n return decodeIntegerRun( decodeInt32( bytes ), decodeInt32( param )[ 0 ] );\n case 10:\n return decodeIntegerDeltaPacking( decodeInt16( bytes ), decodeInt32( param )[ 0 ] );\n case 11:\n return decodeInteger( decodeInt16( bytes ), decodeInt32( param )[ 0 ] );\n case 12:\n return decodeIntegerPacking( decodeInt16( bytes ), decodeInt32( param )[ 0 ] );\n case 13:\n return decodeIntegerPacking( getInt8View( bytes ), decodeInt32( param )[ 0 ] );\n case 14:\n return decodePacking( decodeInt16( bytes ) );\n case 15:\n return decodePacking( getInt8View( bytes ) );\n }\n\n};\n\n\n/**\n * Decode MMTF fields\n * @static\n * @param {Object} inputDict - encoded MMTF data\n * @param {Object} [params] - decoding parameters\n * @param {String[]} params.ignoreFields - names of optional fields not to decode\n * @return {module:MmtfDecode.MmtfData} mmtfData\n */\nfunction decodeMmtf( inputDict, params ){\n\n params = params || {};\n var ignoreFields = params.ignoreFields;\n var outputDict = {};\n\n AllFields.forEach( function( name ){\n var ignore = ignoreFields ? ignoreFields.indexOf( name ) !== -1 : false;\n var data = inputDict[ name ];\n if( !ignore && data !== undefined ){\n if( data instanceof Uint8Array ){\n outputDict[ name ] = performDecoding.apply( null, decodeBytes( data ) );\n }else{\n outputDict[ name ] = data;\n }\n }\n } );\n\n return outputDict;\n\n}\n\n/**\n * @file mmtf-traverse\n * @private\n * @author Alexander Rose \n */\n\n/**\n * mmtf traverse module.\n * @module MmtfTraverse\n */\n\n/**\n * Converts an array of ASCII codes trimming '\\0' bytes\n * @private\n * @param {Array} charCodeArray - array of ASCII char codes\n * @return {String} '\\0' trimmed string\n */\nfunction fromCharCode( charCodeArray ){\n return String.fromCharCode.apply( null, charCodeArray ).replace(/\\0/g, '');\n}\n\n\n/**\n * @callback module:MmtfTraverse.onModel\n * @param {Object} modelData\n * @param {Integer} modelData.chainCount - number of chains in the model\n * @param {Integer} modelData.modelIndex - index of the model\n */\n\n/**\n * @callback module:MmtfTraverse.onChain\n * @param {Object} chainData\n * @param {Integer} chainData.groupCount - number of groups in the chain\n * @param {Integer} chainData.chainIndex - index of the chain\n * @param {Integer} chainData.modelIndex - index of the parent model\n * @param {String} chainData.chainId - chain id\n * @param {?String} chainData.chainName - additional chain name\n */\n\n/**\n * @callback module:MmtfTraverse.onGroup\n * @param {Object} groupData\n * @param {Integer} groupData.atomCount - number of atoms in the group\n * @param {Integer} groupData.groupIndex - index of the group\n * @param {Integer} groupData.chainIndex - index of the parent chain\n * @param {Integer} groupData.modelIndex - index of the parent model\n * @param {Integer} groupData.groupId - group id (residue number)\n * @param {Integer} groupData.groupType - index to an entry in {@link module:MmtfDecode.MmtfData}#groupList\n * @param {String} groupData.groupName - name of the group, 0 to 5 characters\n * @param {Char} groupData.singleLetterCode - IUPAC single letter code, otherwise 'X', 1 character\n * @param {String} groupData.chemCompType - chemical component type from the mmCIF dictionary\n * @param {?Integer} groupData.secStruct - sencoded secondary structure |\n * 0: pi helix, 1: bend, 2: alpha helix, 3: extended,\n * 4: 3-10 helix, 5: bridge, 6: turn, 7: coil, -1: undefined\n * @param {?Char} groupData.insCode - insertion code\n * @param {?Integer} groupData.sequenceIndex - index to the `sequence` property of\n * the corresponding entity, -1 when the entity has no sequence\n */\n\n/**\n * @callback module:MmtfTraverse.onAtom\n * @param {Object} atomData\n * @param {Integer} atomData.atomIndex - index of the atom\n * @param {Integer} atomData.groupIndex - index of the parent group\n * @param {Integer} atomData.chainIndex - index of the parent chain\n * @param {Integer} atomData.modelIndex - index of the parent model\n * @param {?Integer} atomData.atomId - atom id\n * @param {String} atomData.element - IUPAC element name, 0 to 3 characters\n * @param {String} atomData.atomName - name of the atom, 0 to 5 characters\n * @param {Integer} atomData.formalCharge - formal charge of the atom\n * @param {Float} atomData.xCoord - x coordinate in Å\n * @param {Float} atomData.yCoord - y coordinate in Å\n * @param {Float} atomData.zCoord - z coordinate in Å\n * @param {?Float} atomData.bFactor - B-factor in in Å^2\n * @param {?Char} atomData.altLoc - alternate location identifier\n * @param {?Float} atomData.occupancy - occupancy of the atom\n */\n\n/**\n * @callback module:MmtfTraverse.onBond\n * @param {Object} bondData\n * @param {Integer} bondData.atomIndex1 - index of the first atom\n * @param {Integer} bondData.atomIndex2 - index of the secound atom\n * @param {Integer} bondData.bondOrder - bond order, allowed values are 1 to 3\n */\n\n\n/**\n * Traverse the MMTF structure data.\n * @static\n * @param {module:MmtfDecode.MmtfData} mmtfData - decoded mmtf data\n * @param {Object} eventCallbacks\n * @param {module:MmtfTraverse.onModel} [eventCallbacks.onModel] - called for each model\n * @param {module:MmtfTraverse.onChain} [eventCallbacks.onChain] - called for each chain\n * @param {module:MmtfTraverse.onGroup} [eventCallbacks.onGroup] - called for each group\n * @param {module:MmtfTraverse.onAtom} [eventCallbacks.onAtom] - called for each atom\n * @param {module:MmtfTraverse.onBond} [eventCallbacks.onBond] - called for each bond\n * @param {Object} [params] - traversal parameters\n * @param {Boolean} [params.firstModelOnly] - traverse only the first model\n */\nfunction traverseMmtf( mmtfData, eventCallbacks, params ){\n\n params = params || {};\n\n var firstModelOnly = params.firstModelOnly;\n\n // setup callbacks\n var onModel = eventCallbacks.onModel;\n var onChain = eventCallbacks.onChain;\n var onGroup = eventCallbacks.onGroup;\n var onAtom = eventCallbacks.onAtom;\n var onBond = eventCallbacks.onBond;\n\n // setup index counters\n var modelIndex = 0;\n var chainIndex = 0;\n var groupIndex = 0;\n var atomIndex = 0;\n\n var modelFirstAtomIndex = 0;\n var modelLastAtomIndex = -1;\n\n // setup optional fields\n var chainNameList = mmtfData.chainNameList;\n var secStructList = mmtfData.secStructList;\n var insCodeList = mmtfData.insCodeList;\n var sequenceIndexList = mmtfData.sequenceIndexList;\n var atomIdList = mmtfData.atomIdList;\n var bFactorList = mmtfData.bFactorList;\n var altLocList = mmtfData.altLocList;\n var occupancyList = mmtfData.occupancyList;\n var bondAtomList = mmtfData.bondAtomList;\n var bondOrderList = mmtfData.bondOrderList;\n\n // hoisted loop variables\n var o, ol, i, j, k, kl;\n\n // loop over all models\n for( o = 0, ol = mmtfData.chainsPerModel.length; o < ol; ++o ){\n\n if( firstModelOnly && modelIndex > 0 ) break;\n\n var modelChainCount = mmtfData.chainsPerModel[ modelIndex ];\n\n if( onModel ){\n onModel({\n chainCount: modelChainCount,\n modelIndex: modelIndex\n });\n }\n\n for( i = 0; i < modelChainCount; ++i ){\n\n var chainGroupCount = mmtfData.groupsPerChain[ chainIndex ];\n if( onChain ){\n var chainId = fromCharCode(\n mmtfData.chainIdList.subarray( chainIndex * 4, chainIndex * 4 + 4 )\n );\n var chainName = null;\n if( chainNameList ){\n chainName = fromCharCode(\n chainNameList.subarray( chainIndex * 4, chainIndex * 4 + 4 )\n );\n }\n onChain({\n groupCount: chainGroupCount,\n chainIndex: chainIndex,\n modelIndex: modelIndex,\n chainId: chainId,\n chainName: chainName\n });\n }\n\n for( j = 0; j < chainGroupCount; ++j ){\n\n var groupData = mmtfData.groupList[ mmtfData.groupTypeList[ groupIndex ] ];\n var groupAtomCount = groupData.atomNameList.length;\n if( onGroup ){\n var secStruct = null;\n if( secStructList ){\n secStruct = secStructList[ groupIndex ];\n }\n var insCode = null;\n if( mmtfData.insCodeList ){\n insCode = String.fromCharCode( insCodeList[ groupIndex ] );\n }\n var sequenceIndex = null;\n if( sequenceIndexList ){\n sequenceIndex = sequenceIndexList[ groupIndex ];\n }\n onGroup({\n atomCount: groupAtomCount,\n groupIndex: groupIndex,\n chainIndex: chainIndex,\n modelIndex: modelIndex,\n groupId: mmtfData.groupIdList[ groupIndex ],\n groupType: mmtfData.groupTypeList[ groupIndex ],\n groupName: groupData.groupName,\n singleLetterCode: groupData.singleLetterCode,\n chemCompType: groupData.chemCompType,\n secStruct: secStruct,\n insCode: insCode,\n sequenceIndex: sequenceIndex\n });\n }\n\n for( k = 0; k < groupAtomCount; ++k ){\n\n if( onAtom ){\n var atomId = null;\n if( atomIdList ){\n atomId = atomIdList[ atomIndex ];\n }\n var bFactor = null;\n if( bFactorList ){\n bFactor = bFactorList[ atomIndex ];\n }\n var altLoc = null;\n if( altLocList ){\n altLoc = String.fromCharCode( altLocList[ atomIndex ] );\n }\n var occupancy = null;\n if( occupancyList ){\n occupancy = occupancyList[ atomIndex ];\n }\n onAtom({\n atomIndex: atomIndex,\n groupIndex: groupIndex,\n chainIndex: chainIndex,\n modelIndex: modelIndex,\n atomId: atomId,\n element: groupData.elementList[ k ],\n atomName: groupData.atomNameList[ k ],\n formalCharge: groupData.formalChargeList[ k ],\n xCoord: mmtfData.xCoordList[ atomIndex ],\n yCoord: mmtfData.yCoordList[ atomIndex ],\n zCoord: mmtfData.zCoordList[ atomIndex ],\n bFactor: bFactor,\n altLoc: altLoc,\n occupancy: occupancy\n });\n }\n\n atomIndex += 1;\n }\n\n if( onBond ){\n // intra group bonds\n var groupBondAtomList = groupData.bondAtomList;\n for( k = 0, kl = groupData.bondOrderList.length; k < kl; ++k ){\n onBond({\n atomIndex1: atomIndex - groupAtomCount + groupBondAtomList[ k * 2 ],\n atomIndex2: atomIndex - groupAtomCount + groupBondAtomList[ k * 2 + 1 ],\n bondOrder: groupData.bondOrderList[ k ]\n });\n }\n }\n\n groupIndex += 1;\n }\n\n chainIndex += 1;\n }\n\n modelFirstAtomIndex = modelLastAtomIndex + 1;\n modelLastAtomIndex = atomIndex - 1; // subtract one as it already has been incremented\n\n if( onBond ){\n // inter group bonds\n if( bondAtomList ){\n for( k = 0, kl = bondAtomList.length; k < kl; k += 2 ){\n var atomIndex1 = bondAtomList[ k ];\n var atomIndex2 = bondAtomList[ k + 1 ];\n if( ( atomIndex1 >= modelFirstAtomIndex && atomIndex1 <= modelLastAtomIndex ) ||\n ( atomIndex2 >= modelFirstAtomIndex && atomIndex2 <= modelLastAtomIndex )\n ){\n onBond({\n atomIndex1: atomIndex1,\n atomIndex2: atomIndex2,\n bondOrder: bondOrderList ? bondOrderList[ k / 2 ] : null\n });\n }\n }\n }\n }\n\n modelIndex += 1;\n }\n\n}\n\n/**\n * Version name\n * @static\n * @type {String}\n */\nvar version = \"v1.1.0dev\";\n\n/**\n * Version name\n * @private\n * @type {String}\n */\nvar baseUrl = \"//mmtf.rcsb.org/v1.0/\";\n\n/**\n * URL of the RCSB webservice to obtain MMTF files\n * @static\n * @type {String}\n */\nvar fetchUrl = baseUrl + \"full/\";\n\n/**\n * URL of the RCSB webservice to obtain reduced MMTF files\n * @static\n * @type {String}\n */\nvar fetchReducedUrl = baseUrl + \"reduced/\";\n\n/**\n * Encode MMTF fields\n * @static\n * @param {module:MmtfDecode.MmtfData} mmtfData - mmtf data\n * @return {Uint8Array} encoded MMTF fields\n */\nfunction encode( mmtfData ){\n return encodeMsgpack( encodeMmtf( mmtfData ) );\n}\n\n/**\n * Decode MMTF fields\n * @static\n * @example\n * // bin is Uint8Array containing the mmtf msgpack\n * var mmtfData = MMTF.decode( bin );\n * console.log( mmtfData.numAtoms );\n *\n * @param {Uint8Array|ArrayBuffer|module:MmtfDecode.EncodedMmtfData} binOrDict - binary MessagePack or encoded MMTF data\n * @param {Object} [params] - decoding parameters\n * @param {String[]} params.ignoreFields - names of optional fields not to decode\n * @return {module:MmtfDecode.MmtfData} mmtfData\n */\nfunction decode( binOrDict, params ){\n\t// make sure binOrDict is not a plain Arraybuffer\n if( binOrDict instanceof ArrayBuffer ){\n binOrDict = new Uint8Array( binOrDict );\n }\n\n var inputDict;\n if( binOrDict instanceof Uint8Array ){\n // get dict from msgpack\n inputDict = decodeMsgpack( binOrDict );\n }else{\n // already a dict\n inputDict = binOrDict;\n }\n\n return decodeMmtf( inputDict, params );\n}\n\n/**\n * @callback module:MMTF.onLoad\n * @param {module:MmtfDecode.MmtfData} mmtfData - decoded mmtf data object\n */\n\n/**\n * helper method to fetch binary files from an URL\n * @private\n * @param {String} pdbid - PDB ID to fetch\n * @param {String} baseUrl - URL to fetch from\n * @param {module:MMTF.onLoad} onLoad - callback( mmtfData )\n * @param {Function} onError - callback( error )\n * @return {undefined}\n */\nfunction _fetch( pdbid, baseUrl, onLoad, onError ){\n var xhr = new XMLHttpRequest();\n function _onLoad(){\n try{\n var mmtfData = decode( xhr.response );\n onLoad( mmtfData );\n }catch( error ){\n onError( error );\n }\n }\n xhr.addEventListener( \"load\", _onLoad, true );\n xhr.addEventListener( \"error\", onError, true );\n xhr.responseType = \"arraybuffer\";\n xhr.open( \"GET\", baseUrl + pdbid.toUpperCase() );\n xhr.send();\n}\n\n/**\n * Fetch MMTF file from RCSB webservice which contains\n * @static\n * @example\n * MMTF.fetch(\n * \"3PQR\",\n * // onLoad callback\n * function( mmtfData ){ console.log( mmtfData ) },\n * // onError callback\n * function( error ){ console.error( error ) }\n * );\n *\n * @param {String} pdbid - PDB ID to fetch\n * @param {module:MMTF.onLoad} onLoad - callback( mmtfData )\n * @param {Function} onError - callback( error )\n * @return {undefined}\n */\nfunction fetch( pdbid, onLoad, onError ){\n _fetch( pdbid, fetchUrl, onLoad, onError );\n}\n\n/**\n * Fetch reduced MMTF file from RCSB webservice which contains\n * protein C-alpha, nucleotide phosphate and ligand atoms\n * @static\n * @example\n * MMTF.fetchReduced(\n * \"3PQR\",\n * // onLoad callback\n * function( mmtfData ){ console.log( mmtfData ) },\n * // onError callback\n * function( error ){ console.error( error ) }\n * );\n *\n * @param {String} pdbid - PDB ID to fetch\n * @param {module:MMTF.onLoad} onLoad - callback( mmtfData )\n * @param {Function} onError - callback( error )\n * @return {undefined}\n */\nfunction fetchReduced( pdbid, onLoad, onError ){\n _fetch( pdbid, fetchReducedUrl, onLoad, onError );\n}\n\nexport { encode, decode, traverseMmtf as traverse, fetch, fetchReduced, version, fetchUrl, fetchReducedUrl, encodeMsgpack, encodeMmtf, decodeMsgpack, decodeMmtf };","/**\n * @file Mmtf Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4 } from 'three'\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport StructureParser from './structure-parser'\nimport {\n buildUnitcellAssembly, calculateBondsBetween, calculateBondsWithin\n} from '../structure/structure-utils'\nimport { ChemCompHetero } from '../structure/structure-constants'\nimport Entity from '../structure/entity'\nimport Unitcell from '../symmetry/unitcell'\nimport Assembly, { AssemblyPart } from '../symmetry/assembly'\n\nimport { decodeMsgpack, decodeMmtf } from '../../lib/mmtf.es6'\n\nconst SstrucMap: {[k: string]: number} = {\n '0': 'i'.charCodeAt(0), // pi helix\n '1': 's'.charCodeAt(0), // bend\n '2': 'h'.charCodeAt(0), // alpha helix\n '3': 'e'.charCodeAt(0), // extended\n '4': 'g'.charCodeAt(0), // 3-10 helix\n '5': 'b'.charCodeAt(0), // bridge\n '6': 't'.charCodeAt(0), // turn\n '7': 'l'.charCodeAt(0), // coil\n '-1': ''.charCodeAt(0) // NA\n}\n\nclass MmtfParser extends StructureParser {\n get type () { return 'mmtf' }\n get isBinary () { return true }\n\n _parse () {\n // https://github.com/rcsb/mmtf\n\n if (Debug) Log.time('MmtfParser._parse ' + this.name)\n\n let i, il, j, jl, groupData\n\n const s = this.structure\n const sd: {[k: string]: any} = decodeMmtf(decodeMsgpack(this.streamer.data))\n\n // structure header\n const headerFields = [\n 'depositionDate', 'releaseDate', 'resolution',\n 'rFree', 'rWork', 'experimentalMethods'\n ]\n headerFields.forEach(function (name) {\n if (sd[ name ] !== undefined) {\n s.header[ name ] = sd[ name ]\n }\n })\n\n let numBonds, numAtoms, numGroups, numChains, numModels\n let chainsPerModel\n\n s.id = sd.structureId\n s.title = sd.title\n\n s.atomStore.addField('formalCharge', 1, 'int8')\n\n if (this.firstModelOnly || this.asTrajectory) {\n numModels = 1\n numChains = sd.chainsPerModel[ 0 ]\n\n numGroups = 0\n for (i = 0, il = numChains; i < il; ++i) {\n numGroups += sd.groupsPerChain[ i ]\n }\n\n numAtoms = 0\n for (i = 0, il = numGroups; i < il; ++i) {\n groupData = sd.groupList[ sd.groupTypeList[ i ] ]\n numAtoms += groupData.atomNameList.length\n }\n\n numBonds = sd.numBonds\n\n chainsPerModel = [ numChains ]\n } else {\n numBonds = sd.numBonds\n numAtoms = sd.numAtoms\n numGroups = sd.numGroups\n numChains = sd.numChains\n numModels = sd.numModels\n\n chainsPerModel = sd.chainsPerModel\n }\n\n numBonds += numGroups // add numGroups to have space for polymer bonds\n\n //\n\n if (this.asTrajectory) {\n for (i = 0, il = sd.numModels; i < il; ++i) {\n const frame = new Float32Array(numAtoms * 3)\n const frameAtomOffset = numAtoms * i\n\n for (j = 0; j < numAtoms; ++j) {\n const j3 = j * 3\n const offset = j + frameAtomOffset\n frame[ j3 ] = sd.xCoordList[ offset ]\n frame[ j3 + 1 ] = sd.yCoordList[ offset ]\n frame[ j3 + 2 ] = sd.zCoordList[ offset ]\n }\n\n s.frames.push(frame)\n }\n }\n\n // bondStore\n const bAtomIndex1 = new Uint32Array(numBonds)\n const bAtomIndex2 = new Uint32Array(numBonds)\n const bBondOrder = new Uint8Array(numBonds)\n\n const aGroupIndex = new Uint32Array(numAtoms)\n const aFormalCharge = new Int8Array(numAtoms)\n\n const gChainIndex = new Uint32Array(numGroups)\n const gAtomOffset = new Uint32Array(numGroups)\n const gAtomCount = new Uint16Array(numGroups)\n\n const cModelIndex = new Uint16Array(numChains)\n const cGroupOffset = new Uint32Array(numChains)\n const cGroupCount = new Uint32Array(numChains)\n\n const mChainOffset = new Uint32Array(numModels)\n const mChainCount = new Uint32Array(numModels)\n\n // set-up model-chain relations\n let chainOffset = 0\n for (i = 0, il = numModels; i < il; ++i) {\n const modelChainCount = chainsPerModel[ i ]\n mChainOffset[ i ] = chainOffset\n mChainCount[ i ] = modelChainCount\n for (j = 0; j < modelChainCount; ++j) {\n cModelIndex[ j + chainOffset ] = i\n }\n chainOffset += modelChainCount\n }\n\n // set-up chain-residue relations\n const groupsPerChain = sd.groupsPerChain\n let groupOffset = 0\n for (i = 0, il = numChains; i < il; ++i) {\n const chainGroupCount = groupsPerChain[ i ]\n cGroupOffset[ i ] = groupOffset\n cGroupCount[ i ] = chainGroupCount\n for (j = 0; j < chainGroupCount; ++j) {\n gChainIndex[ j + groupOffset ] = i\n }\n groupOffset += chainGroupCount\n }\n\n /// ///\n // get data from group map\n\n let atomOffset = 0\n let bondOffset = 0\n\n for (i = 0, il = numGroups; i < il; ++i) {\n groupData = sd.groupList[ sd.groupTypeList[ i ] ]\n const groupAtomCount = groupData.atomNameList.length\n const groupFormalChargeList = groupData.formalChargeList\n\n const groupBondAtomList = groupData.bondAtomList\n const groupBondOrderList = groupData.bondOrderList\n\n for (j = 0, jl = groupBondOrderList.length; j < jl; ++j) {\n bAtomIndex1[ bondOffset ] = atomOffset + groupBondAtomList[ j * 2 ]\n bAtomIndex2[ bondOffset ] = atomOffset + groupBondAtomList[ j * 2 + 1 ]\n bBondOrder[ bondOffset ] = groupBondOrderList[ j ]\n bondOffset += 1\n }\n\n //\n\n gAtomOffset[ i ] = atomOffset\n gAtomCount[ i ] = groupAtomCount\n\n for (j = 0; j < groupAtomCount; ++j) {\n aGroupIndex[ atomOffset ] = i\n aFormalCharge[ atomOffset ] = groupFormalChargeList[ j ]\n atomOffset += 1\n }\n }\n\n // extra bonds\n\n const bondAtomList = sd.bondAtomList\n if (bondAtomList) {\n if (sd.bondOrderList) {\n bBondOrder.set(sd.bondOrderList, bondOffset)\n }\n\n for (i = 0, il = bondAtomList.length; i < il; i += 2) {\n const atomIndex1 = bondAtomList[ i ]\n const atomIndex2 = bondAtomList[ i + 1 ]\n if (atomIndex1 < numAtoms && atomIndex2 < numAtoms) {\n bAtomIndex1[ bondOffset ] = atomIndex1\n bAtomIndex2[ bondOffset ] = atomIndex2\n bondOffset += 1\n }\n }\n }\n\n //\n\n s.bondStore.length = bBondOrder.length\n s.bondStore.count = bondOffset\n s.bondStore.atomIndex1 = bAtomIndex1\n s.bondStore.atomIndex2 = bAtomIndex2\n s.bondStore.bondOrder = bBondOrder\n\n s.atomStore.length = numAtoms\n s.atomStore.count = numAtoms\n s.atomStore.residueIndex = aGroupIndex\n s.atomStore.atomTypeId = new Uint16Array(numAtoms)\n s.atomStore.x = sd.xCoordList.subarray(0, numAtoms)\n s.atomStore.y = sd.yCoordList.subarray(0, numAtoms)\n s.atomStore.z = sd.zCoordList.subarray(0, numAtoms)\n s.atomStore.serial = sd.atomIdList.subarray(0, numAtoms)\n s.atomStore.bfactor = sd.bFactorList.subarray(0, numAtoms)\n s.atomStore.altloc = sd.altLocList.subarray(0, numAtoms)\n s.atomStore.occupancy = sd.occupancyList.subarray(0, numAtoms)\n s.atomStore.formalCharge = aFormalCharge\n\n s.residueStore.length = numGroups\n s.residueStore.count = numGroups\n s.residueStore.chainIndex = gChainIndex\n s.residueStore.residueTypeId = sd.groupTypeList\n s.residueStore.atomOffset = gAtomOffset\n s.residueStore.atomCount = gAtomCount\n s.residueStore.resno = sd.groupIdList.subarray(0, numGroups)\n s.residueStore.sstruc = sd.secStructList.subarray(0, numGroups)\n s.residueStore.inscode = sd.insCodeList.subarray(0, numGroups)\n\n s.chainStore.length = numChains\n s.chainStore.count = numChains\n s.chainStore.entityIndex = new Uint16Array(numChains)\n s.chainStore.modelIndex = cModelIndex\n s.chainStore.residueOffset = cGroupOffset\n s.chainStore.residueCount = cGroupCount\n s.chainStore.chainname = sd.chainNameList.subarray(0, numChains * 4)\n s.chainStore.chainid = sd.chainIdList.subarray(0, numChains * 4)\n\n s.modelStore.length = numModels\n s.modelStore.count = numModels\n s.modelStore.chainOffset = mChainOffset\n s.modelStore.chainCount = mChainCount\n\n //\n\n let groupTypeDict: {[k: number]: any} = {}\n for (i = 0, il = sd.groupList.length; i < il; ++i) {\n const groupType = sd.groupList[ i ]\n const atomTypeIdList: number[] = []\n for (j = 0, jl = groupType.atomNameList.length; j < jl; ++j) {\n const element = groupType.elementList[ j ].toUpperCase()\n const atomname = groupType.atomNameList[ j ]\n atomTypeIdList.push(s.atomMap.add(atomname, element))\n }\n const chemCompType = groupType.chemCompType.toUpperCase()\n const hetFlag = ChemCompHetero.includes(chemCompType)\n\n const numGroupBonds = groupType.bondOrderList.length\n const atomIndices1 = new Array(numGroupBonds)\n const atomIndices2 = new Array(numGroupBonds)\n for (j = 0; j < numGroupBonds; ++j) {\n atomIndices1[ j ] = groupType.bondAtomList[ j * 2 ]\n atomIndices2[ j ] = groupType.bondAtomList[ j * 2 + 1 ]\n }\n const bonds = {\n atomIndices1: atomIndices1,\n atomIndices2: atomIndices2,\n bondOrders: groupType.bondOrderList\n }\n\n groupTypeDict[ i ] = s.residueMap.add(\n groupType.groupName, atomTypeIdList, hetFlag, chemCompType, bonds\n )\n }\n\n for (i = 0, il = numGroups; i < il; ++i) {\n s.residueStore.residueTypeId[ i ] = groupTypeDict[ s.residueStore.residueTypeId[ i ] ]\n }\n\n for (i = 0, il = s.atomStore.count; i < il; ++i) {\n const residueIndex = s.atomStore.residueIndex[ i ]\n const residueType = s.residueMap.list[ s.residueStore.residueTypeId[ residueIndex ] ]\n const resAtomOffset = s.residueStore.atomOffset[ residueIndex ]\n s.atomStore.atomTypeId[ i ] = residueType.atomTypeIdList[ i - resAtomOffset ]\n }\n\n if (sd.secStructList) {\n const secStructLength: number = sd.secStructList.length\n for (i = 0, il = s.residueStore.count; i < il; ++i) {\n // with ( i % secStructLength ) secStruct entries are reused\n const sstruc = SstrucMap[ s.residueStore.sstruc[ i % secStructLength ] ]\n if (sstruc !== undefined) s.residueStore.sstruc[ i ] = sstruc\n }\n }\n\n //\n\n if (sd.entityList) {\n sd.entityList.forEach(function (e: Entity, i: number) {\n s.entityList[ i ] = new Entity(\n s, i, e.description, e.type, e.chainIndexList\n )\n })\n }\n\n if (sd.bioAssemblyList) {\n sd.bioAssemblyList.forEach(function (_assembly: any, k: number) {\n const id = k + 1\n const assembly = new Assembly('' + id)\n s.biomolDict[ 'BU' + id ] = assembly\n let chainToPart: {[k: string]: AssemblyPart} = {}\n _assembly.transformList.forEach(function (_transform: any) {\n const matrix = new Matrix4().fromArray(_transform.matrix).transpose()\n const chainList: string[] = _transform.chainIndexList.map(function (chainIndex: number) {\n let chainname = ''\n for (let k = 0; k < 4; ++k) {\n const code = sd.chainNameList[ chainIndex * 4 + k ]\n if (code) {\n chainname += String.fromCharCode(code)\n } else {\n break\n }\n }\n return chainname\n })\n const part = chainToPart[ chainList.toString() ]\n if (part) {\n part.matrixList.push(matrix)\n } else {\n chainToPart[ chainList.toString() ] = assembly.addPart([ matrix ], chainList)\n }\n })\n })\n }\n\n if (sd.ncsOperatorList) {\n const ncsName = 'NCS'\n const ncsAssembly = new Assembly(ncsName)\n const ncsPart = ncsAssembly.addPart()\n sd.ncsOperatorList.forEach(function (_operator: number[]) {\n const matrix = new Matrix4().fromArray(_operator).transpose()\n ncsPart.matrixList.push(matrix)\n })\n if (ncsPart.matrixList.length > 0) {\n s.biomolDict[ ncsName ] = ncsAssembly\n }\n }\n\n const uc = sd.unitCell\n if (uc && Array.isArray(uc) && uc[ 0 ]) {\n s.unitcell = new Unitcell({\n a: uc[ 0 ],\n b: uc[ 1 ],\n c: uc[ 2 ],\n alpha: uc[ 3 ],\n beta: uc[ 4 ],\n gamma: uc[ 5 ],\n spacegroup: sd.spaceGroup\n })\n } else {\n s.unitcell = undefined\n }\n\n // calculate backbone bonds\n calculateBondsBetween(s, true)\n\n // calculate rung bonds\n calculateBondsWithin(s, true)\n\n s.finalizeAtoms()\n s.finalizeBonds()\n\n buildUnitcellAssembly(s)\n\n if (Debug) Log.timeEnd('MmtfParser._parse ' + this.name)\n }\n}\n\nParserRegistry.add('mmtf', MmtfParser)\n\nexport default MmtfParser\n","/**\n * @file Mol2 Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport {\n assignResidueTypeBonds,\n calculateChainnames, calculateSecondaryStructure,\n calculateBondsBetween, calculateBondsWithin\n} from '../structure/structure-utils'\nimport StructureParser from './structure-parser'\n\nconst reWhitespace = /\\s+/\nconst bondTypes: {[k: string]: number} = {\n '1': 1,\n '2': 2,\n '3': 3,\n 'am': 1, // amide\n 'ar': 1, // aromatic\n 'du': 1, // dummy\n 'un': 1, // unknown\n 'nc': 0 // not connected\n}\n\nclass Mol2Parser extends StructureParser {\n get type () { return 'mol2' }\n\n _parse () {\n // http://paulbourke.net/dataformats/mol2/\n\n if (Debug) Log.time('Mol2Parser._parse ' + this.name)\n\n const s = this.structure\n const sb = this.structureBuilder\n\n const firstModelOnly = this.firstModelOnly\n const asTrajectory = this.asTrajectory\n\n const frames = s.frames\n let doFrames = false\n let currentFrame: Float32Array, currentCoord: number\n\n const atomMap = s.atomMap\n const atomStore = s.atomStore\n atomStore.resize(Math.round(this.streamer.data.length / 60))\n atomStore.addField('partialCharge', 1, 'float32')\n\n let idx = 0\n let moleculeLineNo = 0\n let modelAtomIdxStart = 0\n let modelIdx = -1\n let numAtoms = 0\n\n let currentRecordType = 0\n let moleculeRecordType = 1\n let atomRecordType = 2\n let bondRecordType = 3\n\n const ap1 = s.getAtomProxy()\n const ap2 = s.getAtomProxy()\n\n function _parseChunkOfLines (_i: number, _n: number, lines: string[]) {\n for (let i = _i; i < _n; ++i) {\n const line = lines[ i ].trim()\n\n if (line === '' || line[ 0 ] === '#') continue\n\n if (line[ 0 ] === '@') {\n if (line === '@MOLECULE') {\n currentRecordType = moleculeRecordType\n moleculeLineNo = 0\n\n ++modelIdx\n } else if (line === '@ATOM') {\n currentRecordType = atomRecordType\n modelAtomIdxStart = atomStore.count\n\n if (asTrajectory) {\n currentCoord = 0\n currentFrame = new Float32Array(numAtoms * 3)\n frames.push(currentFrame)\n\n if (modelIdx > 0) doFrames = true\n }\n } else if (line === '@BOND') {\n currentRecordType = bondRecordType\n } else {\n currentRecordType = 0\n }\n } else if (currentRecordType === moleculeRecordType) {\n if (moleculeLineNo === 0) {\n s.title = line\n s.id = line\n } else if (moleculeLineNo === 1) {\n const ls = line.split(reWhitespace)\n numAtoms = parseInt(ls[ 0 ])\n // num_atoms [num_bonds [num_subst [num_feat [num_sets]]]]\n } else if (moleculeLineNo === 2) {\n\n // const molType = line;\n // SMALL, BIOPOLYMER, PROTEIN, NUCLEIC_ACID, SACCHARIDE\n\n } else if (moleculeLineNo === 3) {\n\n // const chargeType = line;\n // NO_CHARGES, DEL_RE, GASTEIGER, GAST_HUCK, HUCKEL,\n // PULLMAN, GAUSS80_CHARGES, AMPAC_CHARGES,\n // MULLIKEN_CHARGES, DICT_ CHARGES, MMFF94_CHARGES,\n // USER_CHARGES\n\n } else if (moleculeLineNo === 4) {\n\n // const statusBits = line;\n\n } else if (moleculeLineNo === 5) {\n\n // const molComment = line;\n\n }\n\n ++moleculeLineNo\n } else if (currentRecordType === atomRecordType) {\n const ls = line.split(reWhitespace)\n\n if (firstModelOnly && modelIdx > 0) continue\n\n const x = parseFloat(ls[ 2 ])\n const y = parseFloat(ls[ 3 ])\n const z = parseFloat(ls[ 4 ])\n\n if (asTrajectory) {\n const j = currentCoord * 3\n\n currentFrame[ j + 0 ] = x\n currentFrame[ j + 1 ] = y\n currentFrame[ j + 2 ] = z\n\n currentCoord += 1\n\n if (doFrames) continue\n }\n\n const serial = ls[ 0 ]\n const atomname = ls[ 1 ]\n const element = ls[ 5 ].split('.')[ 0 ]\n const resno = ls[ 6 ] ? parseInt(ls[ 6 ]) : 1\n const resname = ls[ 7 ] ? ls[ 7 ] : ''\n const partialCharge = ls[ 8 ] ? parseFloat(ls[ 8 ]) : 0.0\n\n atomStore.growIfFull()\n atomStore.atomTypeId[ idx ] = atomMap.add(atomname, element)\n\n atomStore.x[ idx ] = x\n atomStore.y[ idx ] = y\n atomStore.z[ idx ] = z\n atomStore.serial[ idx ] = serial\n atomStore.partialCharge[ idx ] = partialCharge\n\n sb.addAtom(modelIdx, '', '', resname, resno, true)\n\n idx += 1\n } else if (currentRecordType === bondRecordType) {\n if (firstModelOnly && modelIdx > 0) continue\n if (asTrajectory && modelIdx > 0) continue\n\n const ls = line.split(reWhitespace)\n\n // ls[ 0 ] is bond id\n ap1.index = parseInt(ls[ 1 ]) - 1 + modelAtomIdxStart\n ap2.index = parseInt(ls[ 2 ]) - 1 + modelAtomIdxStart\n const order = bondTypes[ ls[ 3 ] ]\n\n s.bondStore.addBond(ap1, ap2, order)\n }\n }\n }\n\n this.streamer.eachChunkOfLines(function (lines/*, chunkNo, chunkCount */) {\n _parseChunkOfLines(0, lines.length, lines)\n })\n\n sb.finalize()\n s.finalizeAtoms()\n calculateChainnames(s)\n calculateBondsWithin(s, true)\n calculateBondsBetween(s, true)\n s.finalizeBonds()\n assignResidueTypeBonds(s)\n calculateSecondaryStructure(s)\n\n if (Debug) Log.timeEnd('Mol2Parser._parse ' + this.name)\n }\n}\n\nParserRegistry.add('mol2', Mol2Parser)\n\nexport default Mol2Parser\n","/**\n * @file Pdbqt Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { ParserRegistry } from '../globals'\nimport PdbParser from './pdb-parser'\n\n// autodock variant of PDB format with\n// - atom partial charges (empty column in pdb format)\n// - atom types (bfactor column in pdb format)\n// http://autodock.scripps.edu/faqs-help/faq/what-is-the-format-of-a-pdbqt-file\n\nclass PdbqtParser extends PdbParser {\n get type () { return 'pdbqt' }\n}\n\nParserRegistry.add('pdbqt', PdbqtParser)\n\nexport default PdbqtParser\n","/**\n * @file Pqr Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { ParserRegistry } from '../globals'\nimport PdbParser from './pdb-parser'\n\n// http://www.poissonboltzmann.org/docs/file-format-info/\n\nclass PqrParser extends PdbParser {\n get type () { return 'pqr' }\n}\n\nParserRegistry.add('pqr', PqrParser)\n\nexport default PqrParser\n","/**\n * @file Sdf Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport { assignResidueTypeBonds } from '../structure/structure-utils'\nimport StructureParser from './structure-parser'\n\nconst reItem = /> +<(.+)>/\n\nclass SdfParser extends StructureParser {\n get type () { return 'sdf' }\n\n _parse () {\n // https://en.wikipedia.org/wiki/Chemical_table_file#SDF\n // http://download.accelrys.com/freeware/ctfile-formats/ctfile-formats.zip\n\n if (Debug) Log.time('SdfParser._parse ' + this.name)\n\n const s = this.structure\n const sb = this.structureBuilder\n\n const firstModelOnly = this.firstModelOnly\n const asTrajectory = this.asTrajectory\n\n const headerLines = this.streamer.peekLines(2)\n\n s.id = headerLines[ 0 ].trim()\n s.title = headerLines[ 1 ].trim()\n\n const frames = s.frames\n let doFrames = false\n let currentFrame: Float32Array, currentCoord: number\n\n const atomMap = s.atomMap\n const atomStore = s.atomStore\n atomStore.resize(Math.round(this.streamer.data.length / 50))\n atomStore.addField('formalCharge', 1, 'int8')\n\n const ap1 = s.getAtomProxy()\n const ap2 = s.getAtomProxy()\n\n let idx = 0\n let lineNo = 0 // for V2000: current line number in currently parsed Mol file\n let modelIdx = 0\n let modelAtomIdxStart = 0\n\n const sdfData: {[k: string]: string[]}[] = []\n let currentItem: string|boolean = false\n let currentData: {[k: string]: string[]} = {}\n let mItem: RegExpMatchArray | null\n s.extraData.sdf = sdfData\n\n let atomCount, bondCount, atomStart: number, atomEnd: number, bondStart: number, bondEnd: number, x: number, y: number, z: number, atomname: string, element: string, atomindex: number, order: number\n let isV3000 = false, isAtomBlock = false, isBondBlock = false\n let tokens: string[] = [], acc: string[] = []\n const atomindexToStoreindex = new Map()\n\n function _parseChunkOfLines (_i: number, _n: number, lines: string[]) {\n for (let i = _i; i < _n; ++i) {\n const line = lines[ i ]\n\n if (isV3000 && line) {\n tokens = line.substring(7).split(' ')\n\n // Entity properties may extend over multiple lines (hanging line finishes with '-')\n // Tokens are accumulated to be processed at the same time for a given entity\n if (acc.length) {\n tokens = [...acc, ...tokens]\n acc = []\n }\n if (tokens[tokens.length - 1] === '-') {\n tokens.pop();\n acc = tokens;\n continue;\n }\n }\n\n if (line.substr(0, 4) === '$$$$') {\n lineNo = -1\n ++modelIdx\n modelAtomIdxStart = atomStore.count\n sdfData.push(currentData)\n currentData = {}\n currentItem = false\n isV3000 = false\n } else if (lineNo === 3) {\n isV3000 = line.indexOf(' V3000') > -1\n\n if (isV3000) {\n atomindexToStoreindex.clear()\n } else {\n\n atomCount = parseInt(line.substr(0, 3))\n bondCount = parseInt(line.substr(3, 3))\n\n atomStart = 4\n atomEnd = atomStart + atomCount\n bondStart = atomEnd\n bondEnd = bondStart + bondCount\n\n if (asTrajectory) {\n currentCoord = 0\n currentFrame = new Float32Array(atomCount * 3)\n frames.push(currentFrame)\n\n if (modelIdx > 0) doFrames = true\n }\n }\n } else if (isV3000 && tokens[0] === 'COUNTS') {\n atomCount = parseInt(tokens[1]);\n\n if (asTrajectory) {\n currentCoord = 0\n currentFrame = new Float32Array(atomCount * 3)\n frames.push(currentFrame)\n\n if (modelIdx > 0) doFrames = true\n }\n } else if (isV3000 && tokens.length == 2) {\n if (tokens[1] === 'ATOM') {\n if (tokens[0] === 'BEGIN') isAtomBlock = true\n else if (tokens[0] === 'END') isAtomBlock = false\n } else if (tokens[1] === 'BOND') {\n if (tokens[0] === 'BEGIN') isBondBlock = true\n else if (tokens[0] === 'END') isBondBlock = false\n }\n } else if (\n isAtomBlock \n || (!isV3000 && lineNo >= atomStart && lineNo < atomEnd)\n ) {\n if (firstModelOnly && modelIdx > 0) continue\n\n let charge = 0\n if (isV3000) {\n x = parseFloat(tokens[2])\n y = parseFloat(tokens[3])\n z = parseFloat(tokens[4])\n\n element = tokens[1]\n atomindex = parseInt(tokens[0])\n atomindexToStoreindex.set(atomindex, idx)\n atomname = element + atomindex\n\n if (tokens.length > 6) {\n let chgTok = tokens.slice(6).find(t => t.indexOf('CHG=') === 0);\n if (chgTok) {\n charge = parseInt(chgTok.substring(4))\n }\n }\n } else {\n x = parseFloat(line.substr(0, 10))\n y = parseFloat(line.substr(10, 10))\n z = parseFloat(line.substr(20, 10))\n\n element = line.substr(31, 3).trim()\n atomname = element + (idx - modelAtomIdxStart + 1)\n }\n\n if (asTrajectory) {\n const j = currentCoord * 3\n\n currentFrame[ j + 0 ] = x\n currentFrame[ j + 1 ] = y\n currentFrame[ j + 2 ] = z\n\n currentCoord += 1\n\n if (doFrames) continue\n }\n\n atomStore.growIfFull()\n atomStore.atomTypeId[ idx ] = atomMap.add(atomname, element)\n\n atomStore.x[ idx ] = x\n atomStore.y[ idx ] = y\n atomStore.z[ idx ] = z\n atomStore.serial[ idx ] = isV3000 ? atomindex : idx\n atomStore.formalCharge[ idx ] = charge\n\n sb.addAtom(modelIdx, '', '', 'HET', 1, true)\n\n idx += 1\n } else if (\n isBondBlock \n || (!isV3000 && lineNo >= bondStart && lineNo < bondEnd)\n ) {\n if (firstModelOnly && modelIdx > 0) continue\n if (asTrajectory && modelIdx > 0) continue\n\n if (isV3000) {\n ap1.index = atomindexToStoreindex.get(parseInt(tokens[2]))\n ap2.index = atomindexToStoreindex.get(parseInt(tokens[3]))\n order = parseInt(tokens[1])\n } else {\n ap1.index = parseInt(line.substr(0, 3)) - 1 + modelAtomIdxStart\n ap2.index = parseInt(line.substr(3, 3)) - 1 + modelAtomIdxStart\n order = parseInt(line.substr(6, 3))\n }\n\n s.bondStore.addBond(ap1, ap2, order)\n } else if (line.substr(0, 6) === 'M CHG') {\n const chargeCount = parseInt(line.substr(6, 3))\n for (let ci = 0, coffset = 10; ci < chargeCount; ++ci, coffset += 8) {\n const aToken = parseInt(line.substr(coffset, 3))\n const atomIdx = aToken - 1 + modelAtomIdxStart\n const cToken = parseInt(line.substr(coffset + 4, 3))\n atomStore.formalCharge[ atomIdx ] = cToken\n }\n // eslint-disable-next-line no-cond-assign\n } else if (line.charAt(0) === '>' && (mItem = line.match(reItem))) {\n currentItem = mItem[ 1 ]\n currentData[ currentItem ] = []\n } else if (currentItem !== false && line) {\n currentData[ currentItem ].push(line)\n }\n\n ++lineNo\n }\n }\n\n this.streamer.eachChunkOfLines(function (lines/*, chunkNo, chunkCount */) {\n _parseChunkOfLines(0, lines.length, lines)\n })\n\n sb.finalize()\n s.finalizeAtoms()\n s.finalizeBonds()\n assignResidueTypeBonds(s)\n\n if (Debug) Log.timeEnd('SdfParser._parse ' + this.name)\n }\n\n _postProcess () {\n assignResidueTypeBonds(this.structure)\n }\n}\n\nParserRegistry.add('sdf', SdfParser)\nParserRegistry.add('sd', SdfParser)\nParserRegistry.add('mol', SdfParser)\n\nexport default SdfParser\n","/**\n * @file Prmtop Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport StructureParser from './structure-parser'\nimport {\n assignResidueTypeBonds, calculateBondsBetween,\n calculateBondsWithin, calculateChainnames\n} from '../structure/structure-utils'\n\nconst amberChargeUnitFactor = 18.2223\n\nconst enum Mode {\n Title,\n Pointers,\n AtomName,\n Charge,\n Mass,\n ResidueLabel,\n ResiduePointer,\n BondsIncHydrogen,\n BondsWithoutHydrogen,\n Radii\n}\n\nfunction parseIntSubstr (line: string, start: number, length: number) {\n return parseInt(line.substr(start, length).trim())\n}\n\nclass PrmtopParser extends StructureParser {\n get type () { return 'prmtop' }\n\n _parse () {\n // http://ambermd.org/prmtop.pdf\n // http://ambermd.org/formats.html#topology\n\n if (Debug) Log.time('PrmtopParser._parse ' + this.name)\n\n const s = this.structure\n const sb = this.structureBuilder\n\n //\n\n const atomMap = s.atomMap\n const atomStore = s.atomStore\n atomStore.addField('partialCharge', 1, 'float32')\n atomStore.addField('radius', 1, 'float32')\n\n const title: string[] = []\n const pointersDict: {[k: string]: number} = {}\n const pointers = [\n 'NATOM', 'NTYPES', 'NBONH', 'MBONA', 'NTHETH', 'MTHETA',\n 'NPHIH', 'MPHIA', 'NHPARM', 'NPARM', 'NNB', 'NRES',\n 'NBONA', 'NTHETA', 'NPHIA', 'NUMBND', 'NUMANG', 'NPTRA',\n 'NATYP', 'NPHB', 'IFPERT', 'NBPER', 'NGPER', 'NDPER',\n 'MBPER', 'MGPER', 'MDPER', 'IFBOX', 'NMXRS', 'IFCAP',\n 'NUMEXTRA', 'NCOPY'\n ]\n pointers.forEach(name => { pointersDict[ name ] = 0 })\n\n let atomNames: string[]\n let charges: Float32Array\n let radii: Float32Array\n let bAtomIndex1: Uint32Array\n let bAtomIndex2: Uint32Array\n let bBondOrder: Uint8Array = new Uint8Array(0)\n let residueLabels: string[]\n let residuePointers: Uint32Array\n\n let mode: number|undefined\n // let currentFormat\n let curIdx: number\n let bondIdx: number\n\n function _parseChunkOfLines (_i: number, _n: number, lines: string[]) {\n for (let i = _i; i < _n; ++i) {\n const line = lines[ i ]\n const lt = line.trim()\n\n if (!lt) {\n continue\n } else if (line.startsWith('%FORMAT')) {\n // currentFormat = lt.substring(8, lt.length - 1)\n } else if (line.startsWith('%FLAG')) {\n const flag = line.substr(5).trim()\n curIdx = 0\n\n if (flag === 'TITLE') {\n mode = Mode.Title\n } else if (flag === 'POINTERS') {\n mode = Mode.Pointers\n } else if (flag === 'ATOM_NAME') {\n mode = Mode.AtomName\n } else if (flag === 'CHARGE') {\n mode = Mode.Charge\n } else if (flag === 'MASS') {\n mode = Mode.Mass\n } else if (flag === 'RESIDUE_LABEL') {\n mode = Mode.ResidueLabel\n } else if (flag === 'RESIDUE_POINTER') {\n mode = Mode.ResiduePointer\n } else if (flag === 'BONDS_INC_HYDROGEN') {\n bondIdx = 0\n mode = Mode.BondsIncHydrogen\n } else if (flag === 'BONDS_WITHOUT_HYDROGEN') {\n bondIdx = pointersDict['NBONH']\n mode = Mode.BondsWithoutHydrogen\n } else if (flag === 'RADII') {\n mode = Mode.Radii\n } else {\n mode = undefined\n }\n } else if (mode === Mode.Title) {\n title.push(lt)\n } else if (mode === Mode.Pointers) {\n const n = Math.min(curIdx + 10, 32)\n for (let i = 0; curIdx < n; ++i, ++curIdx) {\n pointersDict[pointers[curIdx]] = parseInt(\n line.substr(i * 8, 8).trim()\n )\n }\n atomNames = new Array(pointersDict.NATOM)\n charges = new Float32Array(pointersDict.NATOM)\n radii = new Float32Array(pointersDict.NATOM)\n atomStore.resize(pointersDict.NATOM)\n const bondCount = pointersDict.NBONH + pointersDict.MBONA\n bAtomIndex1 = new Uint32Array(bondCount)\n bAtomIndex2 = new Uint32Array(bondCount)\n bBondOrder = new Uint8Array(bondCount)\n residueLabels = new Array(pointersDict.NRES)\n residuePointers = new Uint32Array(pointersDict.NRES)\n } else if (mode === Mode.AtomName) {\n const n = Math.min(curIdx + 20, pointersDict.NATOM)\n for (let i = 0; curIdx < n; ++i, ++curIdx) {\n atomNames[curIdx] = line.substr(i * 4, 4).trim()\n }\n } else if (mode === Mode.Charge) {\n const n = Math.min(curIdx + 5, pointersDict.NATOM)\n for (let i = 0; curIdx < n; ++i, ++curIdx) {\n charges[curIdx] = parseFloat(line.substr(i * 16, 16)) / amberChargeUnitFactor\n }\n } else if (mode === Mode.Mass) {\n\n // not currently used\n\n } else if (mode === Mode.ResidueLabel) {\n const n = Math.min(curIdx + 20, pointersDict.NRES)\n for (let i = 0; curIdx < n; ++i, ++curIdx) {\n residueLabels[curIdx] = line.substr(i * 4, 4).trim()\n }\n } else if (mode === Mode.ResiduePointer) {\n const n = Math.min(curIdx + 10, pointersDict.NRES)\n for (let i = 0; curIdx < n; ++i, ++curIdx) {\n residuePointers[curIdx] = parseIntSubstr(line, i * 8, 8)\n }\n } else if (mode === Mode.BondsIncHydrogen) {\n const n = Math.min(curIdx + 10, pointersDict.NBONH * 3)\n for (let i = 0; curIdx < n; ++i, ++curIdx) {\n const r = curIdx % 3\n if (r === 0) {\n bAtomIndex1[bondIdx] = parseIntSubstr(line, i * 8, 8) / 3\n } if (r === 1) {\n bAtomIndex2[bondIdx] = parseIntSubstr(line, i * 8, 8) / 3\n bBondOrder[bondIdx] = 1\n ++bondIdx\n }\n }\n } else if (mode === Mode.BondsWithoutHydrogen) {\n const n = Math.min(curIdx + 10, pointersDict.MBONA * 3)\n for (let i = 0; curIdx < n; ++i, ++curIdx) {\n const r = curIdx % 3\n if (r === 0) {\n bAtomIndex1[bondIdx] = parseIntSubstr(line, i * 8, 8) / 3\n } if (r === 1) {\n bAtomIndex2[bondIdx] = parseIntSubstr(line, i * 8, 8) / 3\n bBondOrder[bondIdx] = 1\n ++bondIdx\n }\n }\n } else if (mode === Mode.Radii) {\n const n = Math.min(curIdx + 5, pointersDict.NATOM)\n for (let i = 0; curIdx < n; ++i, ++curIdx) {\n radii[curIdx] = parseFloat(line.substr(i * 16, 16))\n }\n }\n }\n }\n\n this.streamer.eachChunkOfLines(function (lines/*, chunkNo, chunkCount */) {\n _parseChunkOfLines(0, lines.length, lines)\n })\n\n s.title = title.join(' ')\n\n const atomCount = pointersDict.NATOM\n let curResIdx = 0\n let curResname = residueLabels![0]\n let curResno = 1\n for (let i = 0; i < atomCount; ++i) {\n if (i + 1 === residuePointers![curResIdx + 1]) {\n ++curResIdx\n curResname = residueLabels![curResIdx]\n curResno = curResIdx + 1\n }\n atomStore.atomTypeId[i] = atomMap.add(atomNames![i])\n atomStore.serial[i] = i + 1\n sb.addAtom(0, '', '', curResname, curResno, false)\n }\n\n atomStore.partialCharge.set(charges!)\n atomStore.radius.set(radii!)\n\n s.bondStore.length = bBondOrder!.length\n s.bondStore.count = bBondOrder!.length\n s.bondStore.atomIndex1 = bAtomIndex1!\n s.bondStore.atomIndex2 = bAtomIndex2!\n s.bondStore.bondOrder = bBondOrder\n\n sb.finalize()\n s.finalizeAtoms()\n s.finalizeBonds()\n calculateBondsWithin(s, true)\n calculateBondsBetween(s, true, true)\n calculateChainnames(s, true)\n assignResidueTypeBonds(s)\n\n if (Debug) Log.timeEnd('PrmtopParser._parse ' + this.name)\n }\n}\n\nParserRegistry.add('prmtop', PrmtopParser)\nParserRegistry.add('parm7', PrmtopParser)\n\nexport default PrmtopParser\n","/**\n * @file Psf Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport StructureParser from './structure-parser'\nimport {\n assignResidueTypeBonds, calculateBondsBetween,\n calculateBondsWithin, getChainname\n} from '../structure/structure-utils'\n\nconst TitleMode = 1\nconst AtomMode = 2\nconst BondMode = 3\nconst AngleMode = 4\nconst DihedralMode = 5\nconst ImproperMode = 6\n\nconst reWhitespace = /\\s+/\nconst reTitle = /(^\\*|REMARK)*/\n\nclass PsfParser extends StructureParser {\n get type () { return 'psf' }\n\n _parse () {\n // http://www.ks.uiuc.edu/Training/Tutorials/namd/namd-tutorial-unix-html/node23.html\n\n if (Debug) Log.time('PsfParser._parse ' + this.name)\n\n const s = this.structure\n const sb = this.structureBuilder\n\n //\n\n const atomMap = s.atomMap\n const atomStore = s.atomStore\n atomStore.addField('partialCharge', 1, 'float32')\n\n const title: string[] = []\n\n let mode: number|undefined\n let chainid: string\n let lastSegid: string\n let idx = 0\n let chainIdx = 0\n let bondIdx = 0\n let bAtomIndex1: Uint32Array, bAtomIndex2: Uint32Array, bBondOrder: Uint8Array\n\n function _parseChunkOfLines (_i: number, _n: number, lines: string[]) {\n for (let i = _i; i < _n; ++i) {\n const line = lines[ i ].trim()\n\n if (!line) {\n mode = undefined\n continue\n }\n\n if (mode === AtomMode) {\n const ls = line.split(reWhitespace)\n\n const serial = parseInt(ls[ 0 ])\n const segid = ls[ 1 ]\n const resno = parseInt(ls[ 2 ])\n const resname = ls[ 3 ]\n const atomname = ls[ 4 ]\n const charge = parseFloat(ls[ 6 ])\n\n if (segid !== lastSegid) {\n chainid = getChainname(chainIdx)\n ++chainIdx\n }\n\n atomStore.growIfFull()\n atomStore.atomTypeId[ idx ] = atomMap.add(atomname)\n\n atomStore.serial[ idx ] = serial\n atomStore.partialCharge[ idx ] = charge\n\n sb.addAtom(0, chainid, chainid, resname, resno, false)\n\n idx += 1\n lastSegid = segid\n } else if (mode === BondMode) {\n const ls = line.split(reWhitespace)\n\n for (let j = 0, m = ls.length; j < m; j += 2) {\n bAtomIndex1[ bondIdx ] = parseInt(ls[ j ]) - 1\n bAtomIndex2[ bondIdx ] = parseInt(ls[ j + 1 ]) - 1\n bBondOrder[ bondIdx ] = 1\n bondIdx += 1\n }\n } else if (mode === TitleMode) {\n title.push(line.replace(reTitle, '').trim())\n } else if (mode === AngleMode) {\n\n // currently not used\n\n } else if (mode === DihedralMode) {\n\n // currently not used\n\n } else if (mode === ImproperMode) {\n\n // currently not used\n\n } else if (line.includes('!NATOM')) {\n mode = AtomMode\n\n const numAtoms = parseInt(line.split(reWhitespace)[ 0 ])\n atomStore.resize(numAtoms)\n } else if (line.includes('!NBOND')) {\n mode = BondMode\n\n const numBonds = parseInt(line.split(reWhitespace)[ 0 ])\n bAtomIndex1 = new Uint32Array(numBonds)\n bAtomIndex2 = new Uint32Array(numBonds)\n bBondOrder = new Uint8Array(numBonds)\n } else if (line.includes('!NTITLE')) {\n mode = TitleMode\n } else if (line.includes('!NTHETA')) {\n mode = AngleMode\n } else if (line.includes('!NPHI')) {\n mode = DihedralMode\n } else if (line.includes('!NIMPHI')) {\n mode = ImproperMode\n }\n }\n }\n\n this.streamer.eachChunkOfLines(function (lines/*, chunkNo, chunkCount */) {\n _parseChunkOfLines(0, lines.length, lines)\n })\n\n s.title = title.join(' ')\n\n s.bondStore.length = bBondOrder!.length\n s.bondStore.count = bondIdx\n s.bondStore.atomIndex1 = bAtomIndex1!\n s.bondStore.atomIndex2 = bAtomIndex2!\n s.bondStore.bondOrder = bBondOrder!\n\n sb.finalize()\n s.finalizeAtoms()\n s.finalizeBonds()\n calculateBondsWithin(s, true)\n calculateBondsBetween(s, true, true)\n assignResidueTypeBonds(s)\n\n if (Debug) Log.timeEnd('PsfParser._parse ' + this.name)\n }\n}\n\nParserRegistry.add('psf', PsfParser)\n\nexport default PsfParser\n","/**\n * @file Top Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport StructureParser from './structure-parser'\nimport { WaterNames } from '../structure/structure-constants'\nimport {\n assignResidueTypeBonds, calculateBondsBetween,\n calculateBondsWithin, getChainname\n} from '../structure/structure-utils'\n\nconst enum Mode {\n System,\n Molecules,\n Moleculetype,\n Atoms,\n Bonds\n}\n\nconst reField = /\\[ (.+) \\]/\nconst reWhitespace = /\\s+/\n\nclass TopParser extends StructureParser {\n get type () { return 'top' }\n\n _parse () {\n // http://manual.gromacs.org/online/top.html\n\n if (Debug) Log.time('TopParser._parse ' + this.name)\n\n const s = this.structure\n const sb = this.structureBuilder\n\n //\n\n const atomMap = s.atomMap\n const bondStore = s.bondStore\n\n const atomStore = s.atomStore\n atomStore.addField('partialCharge', 1, 'float32')\n\n const molecules: [string, number][] = []\n const moleculetypeDict: {[k: string]: {atoms: any[], bonds: any[] }} = {}\n\n let currentMoleculetype: {\n atoms: [number, string, string, number][],\n bonds: [number, number][]\n }\n let mode: number|undefined\n\n function _parseChunkOfLines (_i: number, _n: number, lines: string[]) {\n for (let i = _i; i < _n; ++i) {\n const line = lines[ i ]\n let lt = line.trim()\n\n if (!lt || lt[0] === '*' || lt[0] === ';') {\n continue\n }\n\n if (lt.startsWith('#include')) {\n throw new Error('TopParser: #include statements not allowed')\n }\n\n const fieldMatch = line.match(reField)\n if (fieldMatch !== null) {\n const name = fieldMatch[1]\n if (name === 'moleculetype') {\n mode = Mode.Moleculetype\n currentMoleculetype = {\n atoms: [],\n bonds: []\n }\n } else if (name === 'atoms') {\n mode = Mode.Atoms\n } else if (name === 'bonds') {\n mode = Mode.Bonds\n } else if (name === 'system') {\n mode = Mode.System\n } else if (name === 'molecules') {\n mode = Mode.Molecules\n } else {\n mode = undefined\n }\n continue\n }\n\n const cIdx = lt.indexOf(';')\n if (cIdx !== -1) {\n lt = lt.substring(0, cIdx).trim()\n }\n if (mode === Mode.Moleculetype) {\n const molName = lt.split(reWhitespace)[0]\n moleculetypeDict[molName] = currentMoleculetype\n } else if (mode === Mode.Atoms) {\n const ls = lt.split(reWhitespace)\n currentMoleculetype.atoms.push([\n parseInt(ls[2]), // resnr\n ls[3], // residue\n ls[4], // atom\n parseFloat(ls[6]) // charge\n ])\n } else if (mode === Mode.Bonds) {\n const ls = lt.split(reWhitespace)\n currentMoleculetype.bonds.push([\n parseInt(ls[0]), // ai\n parseInt(ls[1]) // aj\n ])\n } else if (mode === Mode.System) {\n s.title = lt\n } else if (mode === Mode.Molecules) {\n const ls = lt.split(reWhitespace)\n molecules.push([\n ls[0], // name\n parseInt(ls[1]) // count\n ])\n }\n }\n }\n\n this.streamer.eachChunkOfLines(function (lines/*, chunkNo, chunkCount */) {\n _parseChunkOfLines(0, lines.length, lines)\n })\n\n let atomCount = 0\n let bondCount = 0\n molecules.forEach(function (val) {\n const [name, molCount] = val\n const molType = moleculetypeDict[name]\n atomCount += molCount * molType.atoms.length\n bondCount += molCount * molType.bonds.length\n })\n\n atomStore.resize(atomCount)\n bondStore.resize(bondCount)\n\n let atomIdx = 0\n let resIdx = 0\n let chainidIdx = 0\n let chainnameIdx = 0\n let bondIdx = 0\n let atomOffset = 0\n let lastResno: number\n\n molecules.forEach(function (val) {\n const [name, molCount] = val\n const molType = moleculetypeDict[name]\n const chainname = getChainname(chainnameIdx)\n for (let i = 0; i < molCount; ++i) {\n lastResno = -1\n const chainid = WaterNames.includes(name) ? chainname : getChainname(chainidIdx)\n molType.atoms.forEach(function (atomData) {\n const [resno, resname, atomname, charge] = atomData\n if (resno !== lastResno) {\n ++resIdx\n }\n atomStore.atomTypeId[atomIdx] = atomMap.add(atomname)\n atomStore.serial[atomIdx] = atomIdx + 1\n atomStore.partialCharge[atomIdx] = charge\n sb.addAtom(0, chainname, chainid, resname, resIdx + 1, false)\n ++atomIdx\n lastResno = resno\n })\n molType.bonds.forEach(function (bondData) {\n bondStore.atomIndex1[bondIdx] = atomOffset + bondData[0] - 1\n bondStore.atomIndex2[bondIdx] = atomOffset + bondData[1] - 1\n ++bondIdx\n })\n ++chainidIdx\n atomOffset += molType.atoms.length\n }\n ++chainnameIdx\n })\n\n bondStore.count = bondCount\n\n sb.finalize()\n s.finalizeAtoms()\n s.finalizeBonds()\n calculateBondsWithin(s, true)\n calculateBondsBetween(s, true, true)\n assignResidueTypeBonds(s)\n\n if (Debug) Log.timeEnd('TopParser._parse ' + this.name)\n }\n}\n\nParserRegistry.add('top', TopParser)\n\nexport default TopParser\n","/**\n * @file Trajectory Parser\n * @author Alexander Rose \n * @private\n */\n\nimport Parser, { ParserParameters } from './parser'\nimport Frames from '../trajectory/frames'\nimport Streamer from '../streamer/streamer';\n\nclass TrajectoryParser extends Parser {\n constructor (streamer: Streamer, params?: Partial) {\n super(streamer, params)\n\n this.frames = new Frames(this.name, this.path)\n }\n\n get type () { return 'trajectory' }\n get __objName () { return 'frames' }\n}\n\nexport default TrajectoryParser\n","/**\n * @file Netcdf Reader\n * @author Alexander Rose \n * @private\n *\n * Adapted from https://github.com/cheminfo-js/netcdfjs\n * MIT License, Copyright (c) 2016 cheminfo\n */\n\nimport IOBuffer from './io-buffer'\n\nexport interface NetCDFRecordDimension {\n length: number,\n id?: number,\n name?: string,\n recordStep?: number\n}\n\nexport interface NetCDFHeader {\n recordDimension: NetCDFRecordDimension,\n version: number,\n dimensions: any[],\n globalAttributes: any[],\n variables: any[]\n}\n\nexport interface NetCDFDimension {\n name: string,\n size: number\n}\n\n/**\n * Throws a non-valid NetCDF exception if the statement it's true\n * @ignore\n * @param {boolean} statement - Throws if true\n * @param {string} reason - Reason to throw\n */\nfunction notNetcdf (statement: boolean, reason: string) {\n if (statement) {\n throw new TypeError('Not a valid NetCDF v3.x file: ' + reason)\n }\n}\n\n/**\n * Moves 1, 2, or 3 bytes to next 4-byte boundary\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n */\nfunction padding (buffer: IOBuffer) {\n if ((buffer.offset % 4) !== 0) {\n buffer.skip(4 - (buffer.offset % 4))\n }\n}\n\n/**\n * Reads the name\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @return {string} - Name\n */\nfunction readName (buffer: IOBuffer) {\n // Read name\n const nameLength = buffer.readUint32()\n const name = buffer.readChars(nameLength)\n\n // validate name\n // TODO\n\n // Apply padding\n padding(buffer)\n return name\n}\n\nconst types = {\n BYTE: 1,\n CHAR: 2,\n SHORT: 3,\n INT: 4,\n FLOAT: 5,\n DOUBLE: 6\n}\n\n/**\n * Parse a number into their respective type\n * @ignore\n * @param {number} type - integer that represents the type\n * @return {string} - parsed value of the type\n */\nfunction num2str (type: number) {\n switch (Number(type)) {\n case types.BYTE:\n return 'byte'\n case types.CHAR:\n return 'char'\n case types.SHORT:\n return 'short'\n case types.INT:\n return 'int'\n case types.FLOAT:\n return 'float'\n case types.DOUBLE:\n return 'double'\n default:\n return 'undefined'\n }\n}\n\n/**\n * Parse a number type identifier to his size in bytes\n * @ignore\n * @param {number} type - integer that represents the type\n * @return {number} -size of the type\n */\nfunction num2bytes (type: number) {\n switch (Number(type)) {\n case types.BYTE:\n return 1\n case types.CHAR:\n return 1\n case types.SHORT:\n return 2\n case types.INT:\n return 4\n case types.FLOAT:\n return 4\n case types.DOUBLE:\n return 8\n default:\n return -1\n }\n}\n\n/**\n * Reverse search of num2str\n * @ignore\n * @param {string} type - string that represents the type\n * @return {number} - parsed value of the type\n */\nfunction str2num (type: string) {\n switch (String(type)) {\n case 'byte':\n return types.BYTE\n case 'char':\n return types.CHAR\n case 'short':\n return types.SHORT\n case 'int':\n return types.INT\n case 'float':\n return types.FLOAT\n case 'double':\n return types.DOUBLE\n default:\n return -1\n }\n}\n\n/**\n * Auxiliary function to read numeric data\n * @ignore\n * @param {number} size - Size of the element to read\n * @param {function} bufferReader - Function to read next value\n * @return {Array|number}\n */\nfunction readNumber (size: number, bufferReader: Function) {\n if (size !== 1) {\n const numbers = new Array(size)\n for (let i = 0; i < size; i++) {\n numbers[i] = bufferReader()\n }\n return numbers\n } else {\n return bufferReader()\n }\n}\n\n/**\n * Given a type and a size reads the next element\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @param {number} type - Type of the data to read\n * @param {number} size - Size of the element to read\n * @return {string|Array|number}\n */\nfunction readType (buffer: IOBuffer, type: number, size: number) {\n switch (type) {\n case types.BYTE:\n return buffer.readBytes(size)\n case types.CHAR:\n return trimNull(buffer.readChars(size))\n case types.SHORT:\n return readNumber(size, buffer.readInt16.bind(buffer))\n case types.INT:\n return readNumber(size, buffer.readInt32.bind(buffer))\n case types.FLOAT:\n return readNumber(size, buffer.readFloat32.bind(buffer))\n case types.DOUBLE:\n return readNumber(size, buffer.readFloat64.bind(buffer))\n default:\n notNetcdf(true, 'non valid type ' + type)\n return undefined\n }\n}\n\n/**\n * Removes null terminate value\n * @ignore\n * @param {string} value - String to trim\n * @return {string} - Trimmed string\n */\nfunction trimNull (value: string) {\n if (value.charCodeAt(value.length - 1) === 0) {\n return value.substring(0, value.length - 1)\n }\n return value\n}\n\n// const STREAMING = 4294967295;\n\n/**\n * Read data for the given non-record variable\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @param {object} variable - Variable metadata\n * @return {Array} - Data of the element\n */\nfunction nonRecord (buffer: IOBuffer, variable: {type: string, size: number}) {\n // variable type\n const type = str2num(variable.type)\n\n // size of the data\n const size = variable.size / num2bytes(type)\n\n // iterates over the data\n const data = new Array(size)\n for (let i = 0; i < size; i++) {\n data[i] = readType(buffer, type, 1)\n }\n\n return data\n}\n\n/**\n * Read data for the given record variable\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @param {object} variable - Variable metadata\n * @param {object} recordDimension - Record dimension metadata\n * @return {Array} - Data of the element\n */\nfunction record (buffer:IOBuffer, variable: {type: string, size: number}, recordDimension: NetCDFRecordDimension) {\n // variable type\n const type = str2num(variable.type)\n const width = variable.size ? variable.size / num2bytes(type) : 1\n\n // size of the data\n // TODO streaming data\n const size = recordDimension.length\n\n // iterates over the data\n const data = new Array(size)\n const step = recordDimension.recordStep\n\n for (let i = 0; i < size; i++) {\n const currentOffset = buffer.offset\n data[i] = readType(buffer, type, width)\n buffer.seek(currentOffset + step!)\n }\n\n return data\n}\n\n// Grammar constants\nconst ZERO = 0\nconst NC_DIMENSION = 10\nconst NC_VARIABLE = 11\nconst NC_ATTRIBUTE = 12\n\n/**\n * Read the header of the file\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @param {number} version - Version of the file\n * @return {object} - Object with the fields:\n * * `recordDimension`: Number with the length of record dimension\n * * `dimensions`: List of dimensions\n * * `globalAttributes`: List of global attributes\n * * `variables`: List of variables\n */\nfunction header (buffer: IOBuffer, version: number) {\n // Length of record dimension\n // sum of the varSize's of all the record variables.\n const header: Partial = {recordDimension: {length: buffer.readUint32()}}\n\n // Version\n header.version = version\n\n // List of dimensions\n const dimList = dimensionsList(buffer) as {dimensions: NetCDFDimension[], recordId: number, recordName: string}\n header.recordDimension!.id = dimList.recordId\n header.recordDimension!.name = dimList.recordName\n header.dimensions = dimList.dimensions\n\n // List of global attributes\n header.globalAttributes = attributesList(buffer)\n\n // List of variables\n const variables = variablesList(buffer, dimList.recordId, version) as {variables: any[], recordStep: number}\n header.variables = variables.variables\n header.recordDimension!.recordStep = variables.recordStep\n\n return header\n}\n\n/**\n * List of dimensions\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @return {object} - List of dimensions and record dimension with:\n * * `name`: String with the name of the dimension\n * * `size`: Number with the size of the dimension\n */\nfunction dimensionsList (buffer: IOBuffer) {\n let dimensions: NetCDFDimension[], recordId, recordName\n const dimList = buffer.readUint32()\n if (dimList === ZERO) {\n notNetcdf((buffer.readUint32() !== ZERO), 'wrong empty tag for list of dimensions')\n return []\n } else {\n notNetcdf((dimList !== NC_DIMENSION), 'wrong tag for list of dimensions')\n\n // Length of dimensions\n const dimensionSize = buffer.readUint32()\n dimensions = new Array(dimensionSize)\n for (let dim = 0; dim < dimensionSize; dim++) {\n // Read name\n const name = readName(buffer)\n\n // Read dimension size\n const size = buffer.readUint32()\n if (size === 0) {\n recordId = dim\n recordName = name\n }\n\n dimensions[dim] = {\n name: name,\n size: size\n }\n }\n return {\n dimensions: dimensions,\n recordId: recordId,\n recordName: recordName\n }\n }\n}\n\n/**\n * List of attributes\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @return {Array} - List of attributes with:\n * * `name`: String with the name of the attribute\n * * `type`: String with the type of the attribute\n * * `value`: A number or string with the value of the attribute\n */\nfunction attributesList (buffer: IOBuffer) {\n let attributes\n const gAttList = buffer.readUint32()\n if (gAttList === ZERO) {\n notNetcdf((buffer.readUint32() !== ZERO), 'wrong empty tag for list of attributes')\n return []\n } else {\n notNetcdf((gAttList !== NC_ATTRIBUTE), 'wrong tag for list of attributes')\n\n // Length of attributes\n const attributeSize = buffer.readUint32()\n attributes = new Array(attributeSize)\n for (let gAtt = 0; gAtt < attributeSize; gAtt++) {\n // Read name\n const name = readName(buffer)\n\n // Read type\n const type = buffer.readUint32()\n notNetcdf(((type < 1) || (type > 6)), 'non valid type ' + type)\n\n // Read attribute\n const size = buffer.readUint32()\n const value = readType(buffer, type, size)\n\n // Apply padding\n padding(buffer)\n\n attributes[gAtt] = {\n name: name,\n type: num2str(type),\n value: value\n }\n }\n }\n return attributes\n}\n\n/**\n * List of variables\n * @ignore\n * @param {IOBuffer} buffer - Buffer for the file data\n * @param {number} recordId - Id if the record dimension\n * @param {number} version - Version of the file\n * @return {object} - Number of recordStep and list of variables with:\n * * `name`: String with the name of the variable\n * * `dimensions`: Array with the dimension IDs of the variable\n * * `attributes`: Array with the attributes of the variable\n * * `type`: String with the type of the variable\n * * `size`: Number with the size of the variable\n * * `offset`: Number with the offset where of the variable begins\n * * `record`: True if is a record variable, false otherwise\n */\nfunction variablesList (buffer: IOBuffer, recordId: number, version: number) {\n const varList = buffer.readUint32()\n let recordStep = 0\n let variables\n if (varList === ZERO) {\n notNetcdf(\n (buffer.readUint32() !== ZERO),\n 'wrong empty tag for list of variables'\n )\n return []\n } else {\n notNetcdf((varList !== NC_VARIABLE), 'wrong tag for list of variables')\n\n // Length of variables\n const variableSize = buffer.readUint32()\n variables = new Array(variableSize)\n for (let v = 0; v < variableSize; v++) {\n // Read name\n const name = readName(buffer)\n\n // Read dimensionality of the variable\n const dimensionality = buffer.readUint32()\n\n // Index into the list of dimensions\n const dimensionsIds = new Array(dimensionality)\n for (let dim = 0; dim < dimensionality; dim++) {\n dimensionsIds[dim] = buffer.readUint32()\n }\n\n // Read variables size\n const attributes = attributesList(buffer)\n\n // Read type\n const type = buffer.readUint32()\n notNetcdf(((type < 1) && (type > 6)), 'non valid type ' + type)\n\n // Read variable size\n // The 32-bit varSize field is not large enough to contain the\n // size of variables that require more than 2^32 - 4 bytes,\n // so 2^32 - 1 is used in the varSize field for such variables.\n const varSize = buffer.readUint32()\n\n // Read offset\n let offset = buffer.readUint32()\n if (version === 2) {\n notNetcdf((offset > 0), 'offsets larger than 4GB not supported')\n offset = buffer.readUint32()\n }\n\n // Count amount of record variables\n if (dimensionsIds[0] === recordId) {\n recordStep += varSize\n }\n\n variables[v] = {\n name: name,\n dimensions: dimensionsIds,\n attributes: attributes,\n type: num2str(type),\n size: varSize,\n offset: offset,\n record: (dimensionsIds[0] === recordId)\n }\n }\n }\n\n return {\n variables: variables,\n recordStep: recordStep\n }\n}\n\n/**\n * Reads a NetCDF v3.x file\n * https://www.unidata.ucar.edu/software/netcdf/docs/file_format_specifications.html\n */\nclass NetcdfReader {\n header: Partial\n buffer: IOBuffer\n /**\n * @param {ArrayBuffer} data - ArrayBuffer or any Typed Array with the data\n */\n constructor (data: ArrayBuffer) {\n const buffer = new IOBuffer(data)\n buffer.setBigEndian()\n\n // Validate that it's a NetCDF file\n notNetcdf((buffer.readChars(3) !== 'CDF'), 'should start with CDF')\n\n // Check the NetCDF format\n const version = buffer.readByte()\n notNetcdf((version > 2), 'unknown version')\n\n // Read the header\n this.header = header(buffer, version)\n this.buffer = buffer\n }\n\n /**\n * @return {string} - Version for the NetCDF format\n */\n get version () {\n if (this.header.version === 1) {\n return 'classic format'\n } else {\n return '64-bit offset format'\n }\n }\n\n /**\n * @return {object} - Metadata for the record dimension\n * * `length`: Number of elements in the record dimension\n * * `id`: Id number in the list of dimensions for the record dimension\n * * `name`: String with the name of the record dimension\n * * `recordStep`: Number with the record variables step size\n */\n get recordDimension () {\n return this.header.recordDimension\n }\n\n /**\n * @return {Array} - List of dimensions with:\n * * `name`: String with the name of the dimension\n * * `size`: Number with the size of the dimension\n */\n get dimensions () {\n return this.header.dimensions\n }\n\n /**\n * @return {Array} - List of global attributes with:\n * * `name`: String with the name of the attribute\n * * `type`: String with the type of the attribute\n * * `value`: A number or string with the value of the attribute\n */\n get globalAttributes () {\n return this.header.globalAttributes\n }\n\n /**\n * @return {Array} - List of variables with:\n * * `name`: String with the name of the variable\n * * `dimensions`: Array with the dimension IDs of the variable\n * * `attributes`: Array with the attributes of the variable\n * * `type`: String with the type of the variable\n * * `size`: Number with the size of the variable\n * * `offset`: Number with the offset where of the variable begins\n * * `record`: True if is a record variable, false otherwise\n */\n get variables () {\n return this.header.variables\n }\n\n /**\n * Checks if a variable is available\n * @param {string|object} variableName - Name of the variable to check\n * @return {Boolean} - Variable existence\n */\n hasDataVariable (variableName: string) {\n return this.header.variables!.findIndex(function (val) {\n return val.name === variableName\n }) !== -1\n }\n\n /**\n * Retrieves the data for a given variable\n * @param {string|object} variableName - Name of the variable to search or variable object\n * @return {Array} - List with the variable values\n */\n getDataVariable (variableName: string|{}) {\n let variable\n if (typeof variableName === 'string') {\n // search the variable\n variable = this.header.variables!.find(function (val) {\n return val.name === variableName\n })\n } else {\n variable = variableName\n }\n\n // throws if variable not found\n notNetcdf((variable === undefined), 'variable not found')\n\n // go to the offset position\n this.buffer.seek(variable.offset)\n\n if (variable.record) {\n // record variable case\n return record(this.buffer, variable, this.header.recordDimension!)\n } else {\n // non-record variable case\n return nonRecord(this.buffer, variable)\n }\n }\n}\n\nexport default NetcdfReader\n","/**\n * @file Dcd Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport { uint8ToString, ensureBuffer } from '../utils'\nimport TrajectoryParser from './trajectory-parser'\n\nconst charmmTimeUnitFactor = 20.45482949774598\n\ninterface DcdHeader {\n NSET: number,\n ISTART: number,\n NSAVC: number,\n NAMNF: number,\n DELTA: number,\n TITLE: string,\n NATOM: number\n}\n\nclass DcdParser extends TrajectoryParser {\n get type () { return 'dcd' }\n get isBinary () { return true }\n\n _parse () {\n // http://www.ks.uiuc.edu/Research/vmd/plugins/molfile/dcdplugin.html\n\n // The DCD format is structured as follows\n // (FORTRAN UNFORMATTED, with Fortran data type descriptions):\n // HDR NSET ISTRT NSAVC 5-ZEROS NATOM-NFREAT DELTA 9-ZEROS\n // `CORD' #files step 1 step zeroes (zero) timestep (zeroes)\n // interval\n // C*4 INT INT INT 5INT INT DOUBLE 9INT\n // ==========================================================================\n // NTITLE TITLE\n // INT (=2) C*MAXTITL\n // (=32)\n // ==========================================================================\n // NATOM\n // #atoms\n // INT\n // ==========================================================================\n // X(I), I=1,NATOM (DOUBLE)\n // Y(I), I=1,NATOM\n // Z(I), I=1,NATOM\n // ==========================================================================\n\n if (Debug) Log.time('DcdParser._parse ' + this.name)\n\n const bin = ensureBuffer(this.streamer.data)\n const dv = new DataView(bin)\n\n const f = this.frames\n const coordinates = f.coordinates\n const boxes = f.boxes\n const header: Partial = {}\n\n let nextPos = 0\n\n // header block\n\n const intView = new Int32Array(bin, 0, 23)\n const ef = intView[ 0 ] !== dv.getInt32(0) // endianess flag\n // swap byte order when big endian (84 indicates little endian)\n if (intView[ 0 ] !== 84) {\n const n = bin.byteLength\n for (let i = 0; i < n; i += 4) {\n dv.setFloat32(i, dv.getFloat32(i), true)\n }\n }\n if (intView[ 0 ] !== 84) {\n Log.error('dcd bad format, header block start')\n }\n // format indicator, should read 'CORD'\n const formatString = String.fromCharCode(\n dv.getUint8(4), dv.getUint8(5),\n dv.getUint8(6), dv.getUint8(7)\n )\n if (formatString !== 'CORD') {\n Log.error('dcd bad format, format string')\n }\n let isCharmm = false\n let extraBlock = false\n let fourDims = false\n // version field in charmm, unused in X-PLOR\n if (intView[ 22 ] !== 0) {\n isCharmm = true\n if (intView[ 12 ] !== 0) extraBlock = true\n if (intView[ 13 ] === 1) fourDims = true\n }\n header.NSET = intView[ 2 ]\n header.ISTART = intView[ 3 ]\n header.NSAVC = intView[ 4 ]\n header.NAMNF = intView[ 10 ]\n if (isCharmm) {\n header.DELTA = dv.getFloat32(44, ef)\n } else {\n header.DELTA = dv.getFloat64(44, ef)\n }\n if (intView[ 22 ] !== 84) {\n Log.error('dcd bad format, header block end')\n }\n nextPos = nextPos + 21 * 4 + 8\n\n // title block\n\n const titleLength = dv.getInt32(nextPos, ef)\n const titlePos = nextPos + 1\n if ((titleLength - 4) % 80 !== 0) {\n Log.error('dcd bad format, title block start')\n }\n header.TITLE = uint8ToString(\n new Uint8Array(bin, titlePos, titleLength)\n )\n if (dv.getInt32(titlePos + titleLength + 4 - 1, ef) !== titleLength) {\n Log.error('dcd bad format, title block end')\n }\n nextPos = nextPos + titleLength + 8\n\n // natom block\n\n if (dv.getInt32(nextPos, ef) !== 4) {\n Log.error('dcd bad format, natom block start')\n }\n header.NATOM = dv.getInt32(nextPos + 4, ef)\n if (dv.getInt32(nextPos + 8, ef) !== 4) {\n Log.error('dcd bad format, natom block end')\n }\n nextPos = nextPos + 4 + 8\n\n // fixed atoms block\n\n if (header.NAMNF > 0) {\n // TODO read coordinates and indices of fixed atoms\n Log.error('dcd format with fixed atoms unsupported, aborting')\n return\n }\n\n // frames\n\n const natom = header.NATOM\n const natom4 = natom * 4\n\n for (let i = 0, n = header.NSET; i < n; ++i) {\n if (extraBlock) {\n nextPos += 4 // block start\n // unitcell: A, alpha, B, beta, gamma, C (doubles)\n const box = new Float32Array(9)\n box[ 0 ] = dv.getFloat64(nextPos, ef)\n box[ 4 ] = dv.getFloat64(nextPos + 2 * 8, ef)\n box[ 8 ] = dv.getFloat64(nextPos + 5 * 8, ef)\n boxes.push(box)\n nextPos += 48\n nextPos += 4 // block end\n }\n\n // xyz coordinates\n const coord = new Float32Array(natom * 3)\n for (let j = 0; j < 3; ++j) {\n if (dv.getInt32(nextPos, ef) !== natom4) {\n Log.error('dcd bad format, coord block start', i, j)\n }\n nextPos += 4 // block start\n const c = new Float32Array(bin, nextPos, natom)\n for (let k = 0; k < natom; ++k) {\n coord[ 3 * k + j ] = c[ k ]\n }\n nextPos += natom4\n if (dv.getInt32(nextPos, ef) !== natom4) {\n Log.error('dcd bad format, coord block end', i, j)\n }\n nextPos += 4 // block end\n }\n coordinates.push(coord)\n\n if (fourDims) {\n const bytes = dv.getInt32(nextPos, ef)\n nextPos += 4 + bytes + 4 // block start + skip + block end\n }\n }\n\n if (header.DELTA) {\n f.deltaTime = header.DELTA * charmmTimeUnitFactor\n }\n if (header.ISTART >= 1) {\n f.timeOffset = (header.ISTART - 1) * f.deltaTime\n }\n\n // console.log(header)\n // console.log(header.TITLE)\n // console.log('isCharmm', isCharmm, 'extraBlock', extraBlock, 'fourDims, fourDims)\n\n if (Debug) Log.timeEnd('DcdParser._parse ' + this.name)\n }\n}\n\nParserRegistry.add('dcd', DcdParser)\n\nexport default DcdParser\n","/**\n * @file Nctraj Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport TrajectoryParser from './trajectory-parser'\nimport NetcdfReader from '../utils/netcdf-reader'\n\nclass NctrajParser extends TrajectoryParser {\n get type () { return 'nctraj' }\n get isBinary () { return true }\n\n _parse () {\n // http://ambermd.org/netcdf/nctraj.xhtml\n\n if (Debug) Log.time('NctrajParser._parse ' + this.name)\n\n const netcdfReader = new NetcdfReader(this.streamer.data)\n\n const f = this.frames\n const coordinates = f.coordinates\n const boxes = f.boxes\n const times = f.times\n\n netcdfReader.getDataVariable('coordinates').forEach(function (c) {\n coordinates.push(new Float32Array(c))\n })\n\n if (netcdfReader.hasDataVariable('cell_lengths')) {\n netcdfReader.getDataVariable('cell_lengths').forEach(function (b) {\n boxes.push(new Float32Array(b))\n })\n }\n\n if (netcdfReader.hasDataVariable('time')) {\n netcdfReader.getDataVariable('time').forEach(function (t) {\n times.push(t)\n })\n }\n\n if (times.length >= 1) {\n f.timeOffset = times[0]\n }\n if (times.length >= 2) {\n f.deltaTime = times[1] - times[0]\n }\n\n if (Debug) Log.timeEnd('NctrajParser._parse ' + this.name)\n }\n}\n\nParserRegistry.add('nctraj', NctrajParser)\nParserRegistry.add('ncdf', NctrajParser)\nParserRegistry.add('nc', NctrajParser)\n\nexport default NctrajParser\n","/**\n * @file Trr Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport { ensureBuffer } from '../utils'\nimport TrajectoryParser from './trajectory-parser'\n\nclass TrrParser extends TrajectoryParser {\n get type () { return 'trr' }\n get isBinary () { return true }\n\n _parse () {\n // https://github.com/gromacs/gromacs/blob/master/src/gromacs/fileio/trrio.cpp\n\n if (Debug) Log.time('TrrParser._parse ' + this.name)\n\n const bin = ensureBuffer(this.streamer.data)\n const dv = new DataView(bin)\n\n const f = this.frames\n const coordinates = f.coordinates\n const boxes = f.boxes\n const times = f.times\n\n let offset = 0\n\n while (true) {\n // const magicnum = dv.getInt32(offset)\n // const i1 = dv.getFloat32(offset + 4)\n offset += 8\n\n const versionSize = dv.getInt32(offset)\n offset += 4\n offset += versionSize\n\n // const irSize = dv.getInt32(offset)\n // const eSize = dv.getInt32(offset + 4)\n const boxSize = dv.getInt32(offset + 8)\n const virSize = dv.getInt32(offset + 12)\n const presSize = dv.getInt32(offset + 16)\n // const topSize = dv.getInt32(offset + 20)\n // const symSize = dv.getInt32(offset + 24)\n const coordSize = dv.getInt32(offset + 28)\n const velocitySize = dv.getInt32(offset + 32)\n const forceSize = dv.getInt32(offset + 36)\n const natoms = dv.getInt32(offset + 40)\n // const step = dv.getInt32(offset + 44)\n // const nre = dv.getInt32(offset + 48)\n offset += 52\n\n const floatSize = boxSize / 9\n const natoms3 = natoms * 3\n\n // let lambda\n if (floatSize === 8) {\n times.push(dv.getFloat64(offset))\n // lambda = dv.getFloat64(offset + 8)\n } else {\n times.push(dv.getFloat32(offset))\n // lambda = dv.getFloat32(offset + 4)\n }\n offset += 2 * floatSize\n\n if (boxSize) {\n const box = new Float32Array(9)\n if (floatSize === 8) {\n for (let i = 0; i < 9; ++i) {\n box[i] = dv.getFloat64(offset) * 10\n offset += 8\n }\n } else {\n for (let i = 0; i < 9; ++i) {\n box[i] = dv.getFloat32(offset) * 10\n offset += 4\n }\n }\n boxes.push(box)\n }\n\n // ignore, unused\n offset += virSize\n\n // ignore, unused\n offset += presSize\n\n if (coordSize) {\n let frameCoords\n if (floatSize === 8) {\n frameCoords = new Float32Array(natoms3)\n for (let i = 0; i < natoms3; ++i) {\n frameCoords[i] = dv.getFloat64(offset) * 10\n offset += 8\n }\n } else {\n const tmp = new Uint32Array(bin, offset, natoms3)\n for (let i = 0; i < natoms3; ++i) {\n const value = tmp[i]\n tmp[i] = (\n ((value & 0xFF) << 24) | ((value & 0xFF00) << 8) |\n ((value >> 8) & 0xFF00) | ((value >> 24) & 0xFF)\n )\n }\n frameCoords = new Float32Array(bin, offset, natoms3)\n for (let i = 0; i < natoms3; ++i) {\n frameCoords[i] *= 10\n offset += 4\n }\n }\n coordinates.push(frameCoords)\n }\n\n // ignore, unused\n offset += velocitySize\n\n // ignore, unused\n offset += forceSize\n\n if (offset >= bin.byteLength) break\n }\n\n if (times.length >= 1) {\n f.timeOffset = times[0]\n }\n if (times.length >= 2) {\n f.deltaTime = times[1] - times[0]\n }\n\n if (Debug) Log.timeEnd('TrrParser._parse ' + this.name)\n }\n}\n\nParserRegistry.add('trr', TrrParser)\n\nexport default TrrParser\n","/**\n * @file Xtc Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport { ensureBuffer } from '../utils'\nimport TrajectoryParser from './trajectory-parser'\nimport { NumberArray } from '../types';\n\nconst MagicInts = new Uint32Array([\n 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 10, 12, 16, 20, 25, 32, 40, 50, 64,\n 80, 101, 128, 161, 203, 256, 322, 406, 512, 645, 812, 1024, 1290,\n 1625, 2048, 2580, 3250, 4096, 5060, 6501, 8192, 10321, 13003,\n 16384, 20642, 26007, 32768, 41285, 52015, 65536, 82570, 104031,\n 131072, 165140, 208063, 262144, 330280, 416127, 524287, 660561,\n 832255, 1048576, 1321122, 1664510, 2097152, 2642245, 3329021,\n 4194304, 5284491, 6658042, 8388607, 10568983, 13316085, 16777216\n])\nconst FirstIdx = 9\n// const LastIdx = MagicInts.length\n\nfunction sizeOfInt (size: number) {\n let num = 1\n let numOfBits = 0\n while (size >= num && numOfBits < 32) {\n numOfBits++\n num <<= 1\n }\n return numOfBits\n}\n\nconst _tmpBytes = new Uint8Array(32)\n\nfunction sizeOfInts (numOfInts: number, sizes: Int32Array) {\n let numOfBytes = 1\n let numOfBits = 0\n _tmpBytes[0] = 1\n for (let i = 0; i < numOfInts; i++) {\n let bytecnt\n let tmp = 0\n for (bytecnt = 0; bytecnt < numOfBytes; bytecnt++) {\n tmp += _tmpBytes[bytecnt] * sizes[i]\n _tmpBytes[bytecnt] = tmp & 0xff\n tmp >>= 8\n }\n while (tmp !== 0) {\n _tmpBytes[bytecnt++] = tmp & 0xff\n tmp >>= 8\n }\n numOfBytes = bytecnt\n }\n let num = 1\n numOfBytes--\n while (_tmpBytes[numOfBytes] >= num) {\n numOfBits++\n num *= 2\n }\n return numOfBits + numOfBytes * 8\n}\n\nfunction decodeBits (buf: Int32Array, cbuf: Uint8Array, numOfBits: number, buf2: Uint32Array) {\n const mask = (1 << numOfBits) - 1\n let lastBB0 = buf2[1]\n let lastBB1 = buf2[2]\n let cnt = buf[0]\n let num = 0\n\n while (numOfBits >= 8) {\n lastBB1 = (lastBB1 << 8) | cbuf[cnt++]\n num |= (lastBB1 >> lastBB0) << (numOfBits - 8)\n numOfBits -= 8\n }\n\n if (numOfBits > 0) {\n if (lastBB0 < numOfBits) {\n lastBB0 += 8\n lastBB1 = (lastBB1 << 8) | cbuf[cnt++]\n }\n lastBB0 -= numOfBits\n num |= (lastBB1 >> lastBB0) & ((1 << numOfBits) - 1)\n }\n\n num &= mask\n buf[0] = cnt\n buf[1] = lastBB0\n buf[2] = lastBB1\n\n return num\n}\n\nconst _tmpIntBytes = new Int32Array(32)\n\nfunction decodeInts (buf: Int32Array, cbuf: Uint8Array, numOfInts: number, numOfBits: number, sizes: NumberArray, nums: Float32Array, buf2: Uint32Array) {\n let numOfBytes = 0\n _tmpIntBytes[1] = 0\n _tmpIntBytes[2] = 0\n _tmpIntBytes[3] = 0\n\n while (numOfBits > 8) {\n // this is inversed??? why??? because of the endiannness???\n _tmpIntBytes[numOfBytes++] = decodeBits(buf, cbuf, 8, buf2)\n numOfBits -= 8\n }\n\n if (numOfBits > 0) {\n _tmpIntBytes[numOfBytes++] = decodeBits(buf, cbuf, numOfBits, buf2)\n }\n\n for (let i = numOfInts - 1; i > 0; i--) {\n let num = 0\n for (let j = numOfBytes - 1; j >= 0; j--) {\n num = (num << 8) | _tmpIntBytes[j]\n const p = (num / sizes[i]) | 0\n _tmpIntBytes[j] = p\n num = num - p * sizes[i]\n }\n nums[i] = num\n }\n nums[0] = (\n _tmpIntBytes[0] |\n (_tmpIntBytes[1] << 8) |\n (_tmpIntBytes[2] << 16) |\n (_tmpIntBytes[3] << 24)\n )\n}\n\nclass XtcParser extends TrajectoryParser {\n get type () { return 'xtc' }\n get isBinary () { return true }\n\n _parse () {\n // https://github.com/gromacs/gromacs/blob/master/src/gromacs/fileio/xtcio.cpp\n // https://github.com/gromacs/gromacs/blob/master/src/gromacs/fileio/libxdrf.cpp\n\n if (Debug) Log.time('XtcParser._parse ' + this.name)\n\n const bin = ensureBuffer(this.streamer.data)\n const dv = new DataView(bin)\n\n const f = this.frames\n const coordinates = f.coordinates\n const boxes = f.boxes\n const times = f.times\n\n const minMaxInt = new Int32Array(6)\n const sizeint = new Int32Array(3)\n const bitsizeint = new Int32Array(3)\n const sizesmall = new Uint32Array(3)\n const thiscoord = new Float32Array(3)\n const prevcoord = new Float32Array(3)\n\n let offset = 0\n const buf = new Int32Array(3)\n const buf2 = new Uint32Array(buf.buffer)\n\n while (true) {\n let frameCoords: NumberArray\n\n // const magicnum = dv.getInt32(offset)\n const natoms = dv.getInt32(offset + 4)\n // const step = dv.getInt32(offset + 8)\n offset += 12\n\n const natoms3 = natoms * 3\n\n times.push(dv.getFloat32(offset))\n offset += 4\n\n const box = new Float32Array(9)\n for (let i = 0; i < 9; ++i) {\n box[i] = dv.getFloat32(offset) * 10\n offset += 4\n }\n boxes.push(box)\n\n if (natoms <= 9) { // no compression\n frameCoords = new Float32Array(natoms)\n for (let i = 0; i < natoms; ++i) {\n frameCoords[i] = dv.getFloat32(offset)\n offset += 4\n }\n } else {\n buf[0] = buf[1] = buf[2] = 0.0\n sizeint[0] = sizeint[1] = sizeint[2] = 0\n sizesmall[0] = sizesmall[1] = sizesmall[2] = 0\n bitsizeint[0] = bitsizeint[1] = bitsizeint[2] = 0\n thiscoord[0] = thiscoord[1] = thiscoord[2] = 0\n prevcoord[0] = prevcoord[1] = prevcoord[2] = 0\n\n frameCoords = new Float32Array(natoms3)\n let lfp = 0\n\n const lsize = dv.getInt32(offset)\n offset += 4\n const precision = dv.getFloat32(offset)\n offset += 4\n\n minMaxInt[0] = dv.getInt32(offset)\n minMaxInt[1] = dv.getInt32(offset + 4)\n minMaxInt[2] = dv.getInt32(offset + 8)\n minMaxInt[3] = dv.getInt32(offset + 12)\n minMaxInt[4] = dv.getInt32(offset + 16)\n minMaxInt[5] = dv.getInt32(offset + 20)\n sizeint[0] = minMaxInt[3] - minMaxInt[0] + 1\n sizeint[1] = minMaxInt[4] - minMaxInt[1] + 1\n sizeint[2] = minMaxInt[5] - minMaxInt[2] + 1\n offset += 24\n\n let bitsize\n if ((sizeint[0] | sizeint[1] | sizeint[2]) > 0xffffff) {\n bitsizeint[0] = sizeOfInt(sizeint[0])\n bitsizeint[1] = sizeOfInt(sizeint[1])\n bitsizeint[2] = sizeOfInt(sizeint[2])\n bitsize = 0 // flag the use of large sizes\n } else {\n bitsize = sizeOfInts(3, sizeint)\n }\n\n let smallidx = dv.getInt32(offset)\n offset += 4\n // if (smallidx == 0) {alert(\"Undocumented error 1\"); return;}\n\n // let tmpIdx = smallidx + 8\n // const maxidx = (LastIdx < tmpIdx) ? LastIdx : tmpIdx\n // const minidx = maxidx - 8 // often this equal smallidx\n let tmpIdx = smallidx - 1\n tmpIdx = (FirstIdx > tmpIdx) ? FirstIdx : tmpIdx\n let smaller = (MagicInts[tmpIdx] / 2) | 0\n let smallnum = (MagicInts[smallidx] / 2) | 0\n\n sizesmall[0] = sizesmall[1] = sizesmall[2] = MagicInts[smallidx]\n // larger = MagicInts[maxidx]\n\n let adz = Math.ceil(dv.getInt32(offset) / 4) * 4\n offset += 4\n // if (tmpIdx == 0) {alert(\"Undocumented error 2\"); return;}\n\n // buf = new Int32Array(bin, offset);\n // buf8 = new Uint8Array(bin, offset);\n\n // tmpIdx += 3; rndup = tmpIdx%4;\n // for (i=tmpIdx+rndup-1; i>=tmpIdx; i--) buf8[i] = 0;\n\n // now unpack buf2...\n\n const invPrecision = 1.0 / precision\n let run = 0\n let i = 0\n\n const buf8 = new Uint8Array(bin, offset) // 229...\n\n thiscoord[0] = thiscoord[1] = thiscoord[2] = 0\n\n while (i < lsize) {\n if (bitsize === 0) {\n thiscoord[0] = decodeBits(buf, buf8, bitsizeint[0], buf2)\n thiscoord[1] = decodeBits(buf, buf8, bitsizeint[1], buf2)\n thiscoord[2] = decodeBits(buf, buf8, bitsizeint[2], buf2)\n } else {\n decodeInts(buf, buf8, 3, bitsize, sizeint, thiscoord, buf2)\n }\n\n i++\n\n thiscoord[0] += minMaxInt[0]\n thiscoord[1] += minMaxInt[1]\n thiscoord[2] += minMaxInt[2]\n\n prevcoord[0] = thiscoord[0]\n prevcoord[1] = thiscoord[1]\n prevcoord[2] = thiscoord[2]\n\n const flag = decodeBits(buf, buf8, 1, buf2)\n let isSmaller = 0\n\n if (flag === 1) {\n run = decodeBits(buf, buf8, 5, buf2)\n isSmaller = run % 3\n run -= isSmaller\n isSmaller--\n }\n\n // if ((lfp-ptrstart)+run > size3){\n // fprintf(stderr, \"(xdrfile error) Buffer overrun during decompression.\\n\");\n // return 0;\n // }\n\n if (run > 0) {\n thiscoord[0] = thiscoord[1] = thiscoord[2] = 0\n\n for (let k = 0; k < run; k += 3) {\n decodeInts(buf, buf8, 3, smallidx, sizesmall, thiscoord, buf2)\n i++\n\n thiscoord[0] += prevcoord[0] - smallnum\n thiscoord[1] += prevcoord[1] - smallnum\n thiscoord[2] += prevcoord[2] - smallnum\n\n if (k === 0) {\n // interchange first with second atom for\n // better compression of water molecules\n let tmpSwap = thiscoord[0]\n thiscoord[0] = prevcoord[0]\n prevcoord[0] = tmpSwap\n\n tmpSwap = thiscoord[1]\n thiscoord[1] = prevcoord[1]\n prevcoord[1] = tmpSwap\n\n tmpSwap = thiscoord[2]\n thiscoord[2] = prevcoord[2]\n prevcoord[2] = tmpSwap\n\n frameCoords[lfp++] = prevcoord[0] * invPrecision\n frameCoords[lfp++] = prevcoord[1] * invPrecision\n frameCoords[lfp++] = prevcoord[2] * invPrecision\n } else {\n prevcoord[0] = thiscoord[0]\n prevcoord[1] = thiscoord[1]\n prevcoord[2] = thiscoord[2]\n }\n frameCoords[lfp++] = thiscoord[0] * invPrecision\n frameCoords[lfp++] = thiscoord[1] * invPrecision\n frameCoords[lfp++] = thiscoord[2] * invPrecision\n }\n } else {\n frameCoords[lfp++] = thiscoord[0] * invPrecision\n frameCoords[lfp++] = thiscoord[1] * invPrecision\n frameCoords[lfp++] = thiscoord[2] * invPrecision\n }\n\n smallidx += isSmaller\n\n if (isSmaller < 0) {\n smallnum = smaller\n if (smallidx > FirstIdx) {\n smaller = (MagicInts[smallidx - 1] / 2) | 0\n } else {\n smaller = 0\n }\n } else if (isSmaller > 0) {\n smaller = smallnum\n smallnum = (MagicInts[smallidx] / 2) | 0\n }\n sizesmall[0] = sizesmall[1] = sizesmall[2] = MagicInts[smallidx]\n\n if (sizesmall[0] === 0 || sizesmall[1] === 0 || sizesmall[2] === 0) {\n console.error('(xdrfile error) Undefined error.')\n return\n }\n }\n offset += adz\n }\n\n for (let c = 0; c < natoms3; c++) {\n frameCoords[c] *= 10\n }\n\n coordinates.push(frameCoords)\n\n if (offset >= bin.byteLength) break\n }\n\n if (times.length >= 1) {\n f.timeOffset = times[0]\n }\n if (times.length >= 2) {\n f.deltaTime = times[1] - times[0]\n }\n\n if (Debug) Log.timeEnd('XtcParser._parse ' + this.name)\n }\n}\n\nParserRegistry.add('xtc', XtcParser)\n\nexport default XtcParser\n","/**\n * @file Volume Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4 } from 'three'\n\nimport { defaults } from '../utils'\nimport Parser, { ParserParameters } from './parser'\nimport Volume from '../surface/volume'\nimport Streamer from '../streamer/streamer';\n\nexport interface VolumeParserParameters extends ParserParameters {\n voxelSize: number\n}\n\nclass VolumeParser extends Parser {\n constructor (streamer: Streamer, params?: Partial) {\n const p = params || {}\n\n super(streamer, p)\n\n this.volume = new Volume(this.name, this.path)\n this.voxelSize = defaults(p.voxelSize, 1)\n }\n\n get type () { return 'volume' }\n get __objName () { return 'volume' }\n\n _afterParse () {\n this.volume.setMatrix(this.getMatrix())\n super._afterParse()\n }\n\n getMatrix () {\n return new Matrix4()\n }\n}\n\nexport default VolumeParser\n","/**\n * @file Cube Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4, Vector3 } from 'three'\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport VolumeParser from './volume-parser'\n\n// @author Johanna Tiemann \n// @author Alexander Rose \n\nconst reWhitespace = /\\s+/\nconst reScientificNotation = /-?\\d+(?:\\.\\d*)?(?:[eE][+-]?\\d+)?/g\nconst bohrToAngstromFactor = 0.529177210859\ninterface Header {\n atomCount: number,\n originX: number,\n originY: number,\n originZ: number,\n NVX: number,\n NVY: number,\n NVZ: number,\n basisX: Vector3,\n basisY: Vector3,\n basisZ: Vector3\n}\n\nclass CubeParser extends VolumeParser {\n get type () { return 'cube' }\n\n _parse () {\n // http://paulbourke.net/dataformats/cube/\n\n if (Debug) Log.time('CubeParser._parse ' + this.name)\n\n const v = this.volume\n const headerLines = this.streamer.peekLines(6)\n const header: Partial
= {}\n\n const scaleFactor = bohrToAngstromFactor * this.voxelSize\n\n function h (k: number, l: number) {\n var field = headerLines[ k ].trim().split(reWhitespace)[ l ]\n return parseFloat(field)\n }\n\n header.atomCount = Math.abs(h(2, 0)) // Number of atoms\n header.originX = h(2, 1) * bohrToAngstromFactor // Position of origin of volumetric data\n header.originY = h(2, 2) * bohrToAngstromFactor\n header.originZ = h(2, 3) * bohrToAngstromFactor\n header.NVX = h(3, 0) // Number of voxels\n header.NVY = h(4, 0)\n header.NVZ = h(5, 0)\n\n header.basisX = new Vector3(h(3, 1), h(3, 2), h(3, 3))\n .multiplyScalar(scaleFactor)\n header.basisY = new Vector3(h(4, 1), h(4, 2), h(4, 3))\n .multiplyScalar(scaleFactor)\n header.basisZ = new Vector3(h(5, 1), h(5, 2), h(5, 3))\n .multiplyScalar(scaleFactor)\n\n const data = new Float32Array(header.NVX * header.NVY * header.NVZ)\n let count = 0\n let lineNo = 0\n const oribitalFlag = h(2, 0) > 0 ? 0 : 1\n\n function _parseChunkOfLines (_i: number, _n: number, lines: string[]) {\n for (let i = _i; i < _n; ++i) {\n const line = lines[ i ].trim()\n\n if (line !== '' && lineNo >= header.atomCount! + 6 + oribitalFlag) {\n const m = line.match(reScientificNotation) as RegExpMatchArray\n for (let j = 0, lj = m.length; j < lj; ++j) {\n data[ count ] = parseFloat(m[ j ])\n ++count\n }\n }\n\n ++lineNo\n }\n }\n\n this.streamer.eachChunkOfLines(function (lines/*, chunkNo, chunkCount */) {\n _parseChunkOfLines(0, lines.length, lines)\n })\n\n v.header = header\n v.setData(data, header.NVZ, header.NVY, header.NVX)\n\n if (Debug) Log.timeEnd('CubeParser._parse ' + this.name)\n }\n\n getMatrix () {\n const h = this.volume.header\n const matrix = new Matrix4()\n\n matrix.multiply(\n new Matrix4().makeTranslation(\n h.originX, h.originY, h.originZ\n )\n )\n\n matrix.multiply(\n new Matrix4().makeBasis(\n h.basisZ, h.basisY, h.basisX\n )\n )\n\n return matrix\n }\n}\n\nParserRegistry.add('cub', CubeParser)\nParserRegistry.add('cube', CubeParser)\n\nexport default CubeParser\n","/**\n * @file Dsn6 Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4 } from 'three'\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport { ensureBuffer } from '../utils'\nimport { degToRad } from '../math/math-utils'\nimport VolumeParser from './volume-parser'\n\ninterface Dsn6Header {\n xStart: number,\n yStart: number,\n zStart: number,\n xExtent: number,\n yExtent: number,\n zExtent: number,\n xRate: number,\n yRate: number,\n zRate: number,\n xlen: number,\n ylen: number,\n zlen: number,\n alpha: number,\n beta: number,\n gamma: number,\n sigma: number\n}\n\nclass Dsn6Parser extends VolumeParser {\n get type () { return 'dsn6' }\n get isBinary () { return true }\n\n _parse () {\n // DSN6 http://www.uoxray.uoregon.edu/tnt/manual/node104.html\n // BRIX http://svn.cgl.ucsf.edu/svn/chimera/trunk/libs/VolumeData/dsn6/brix-1.html\n\n if (Debug) Log.time('Dsn6Parser._parse ' + this.name)\n\n const v = this.volume\n const header: Partial = {}\n let divisor, summand\n\n const bin = ensureBuffer(this.streamer.data)\n const intView = new Int16Array(bin)\n const byteView = new Uint8Array(bin)\n const brixStr = String.fromCharCode.apply(null, byteView.subarray(0, 512))\n\n if (brixStr.startsWith(':-)')) {\n header.xStart = parseInt(brixStr.substr(10, 5)) // NXSTART\n header.yStart = parseInt(brixStr.substr(15, 5))\n header.zStart = parseInt(brixStr.substr(20, 5))\n\n header.xExtent = parseInt(brixStr.substr(32, 5)) // NX\n header.yExtent = parseInt(brixStr.substr(38, 5))\n header.zExtent = parseInt(brixStr.substr(42, 5))\n\n header.xRate = parseInt(brixStr.substr(52, 5)) // MX\n header.yRate = parseInt(brixStr.substr(58, 5))\n header.zRate = parseInt(brixStr.substr(62, 5))\n\n header.xlen = parseFloat(brixStr.substr(73, 10)) * this.voxelSize\n header.ylen = parseFloat(brixStr.substr(83, 10)) * this.voxelSize\n header.zlen = parseFloat(brixStr.substr(93, 10)) * this.voxelSize\n\n header.alpha = parseFloat(brixStr.substr(103, 10))\n header.beta = parseFloat(brixStr.substr(113, 10))\n header.gamma = parseFloat(brixStr.substr(123, 10))\n\n divisor = parseFloat(brixStr.substr(138, 12)) / 100\n summand = parseInt(brixStr.substr(155, 8))\n\n header.sigma = parseFloat(brixStr.substr(170, 12)) * 100\n } else {\n // swap byte order when big endian\n if (intView[ 18 ] !== 100) {\n for (let i = 0, n = intView.length; i < n; ++i) {\n const val = intView[ i ]\n intView[ i ] = ((val & 0xff) << 8) | ((val >> 8) & 0xff)\n }\n }\n\n header.xStart = intView[ 0 ] // NXSTART\n header.yStart = intView[ 1 ]\n header.zStart = intView[ 2 ]\n\n header.xExtent = intView[ 3 ] // NX\n header.yExtent = intView[ 4 ]\n header.zExtent = intView[ 5 ]\n\n header.xRate = intView[ 6 ] // MX\n header.yRate = intView[ 7 ]\n header.zRate = intView[ 8 ]\n\n const factor = 1 / intView[ 17 ]\n const scalingFactor = factor * this.voxelSize\n\n header.xlen = intView[ 9 ] * scalingFactor\n header.ylen = intView[ 10 ] * scalingFactor\n header.zlen = intView[ 11 ] * scalingFactor\n\n header.alpha = intView[ 12 ] * factor\n header.beta = intView[ 13 ] * factor\n header.gamma = intView[ 14 ] * factor\n\n divisor = intView[ 15 ] / 100\n summand = intView[ 16 ]\n header.gamma = intView[ 14 ] * factor\n }\n\n v.header = header\n\n if (Debug) Log.log(header, divisor, summand)\n\n const data = new Float32Array(\n header.xExtent * header.yExtent * header.zExtent\n )\n\n let offset = 512\n const xBlocks = Math.ceil(header.xExtent / 8)\n const yBlocks = Math.ceil(header.yExtent / 8)\n const zBlocks = Math.ceil(header.zExtent / 8)\n\n // loop over blocks\n for (var zz = 0; zz < zBlocks; ++zz) {\n for (var yy = 0; yy < yBlocks; ++yy) {\n for (var xx = 0; xx < xBlocks; ++xx) {\n // loop inside block\n for (var k = 0; k < 8; ++k) {\n var z = 8 * zz + k\n for (var j = 0; j < 8; ++j) {\n var y = 8 * yy + j\n for (var i = 0; i < 8; ++i) {\n var x = 8 * xx + i\n\n // check if remaining slice-part contains data\n if (x < header.xExtent && y < header.yExtent && z < header.zExtent) {\n var idx = ((((x * header.yExtent) + y) * header.zExtent) + z)\n data[ idx ] = (byteView[ offset ] - summand) / divisor\n ++offset\n } else {\n offset += 8 - i\n break\n }\n }\n }\n }\n }\n }\n }\n\n v.setData(data, header.zExtent, header.yExtent, header.xExtent)\n if (header.sigma) {\n v.setStats(undefined, undefined, undefined, header.sigma)\n }\n\n if (Debug) Log.timeEnd('Dsn6Parser._parse ' + this.name)\n }\n\n getMatrix () {\n const h: Dsn6Header = this.volume.header\n\n const basisX = [\n h.xlen as number,\n 0,\n 0\n ]\n\n const basisY = [\n h.ylen * Math.cos(Math.PI / 180.0 * h.gamma),\n h.ylen * Math.sin(Math.PI / 180.0 * h.gamma),\n 0\n ]\n\n const basisZ = [\n h.zlen * Math.cos(Math.PI / 180.0 * h.beta),\n h.zlen * (\n Math.cos(Math.PI / 180.0 * h.alpha) -\n Math.cos(Math.PI / 180.0 * h.gamma) *\n Math.cos(Math.PI / 180.0 * h.beta)\n ) / Math.sin(Math.PI / 180.0 * h.gamma),\n 0\n ]\n basisZ[ 2 ] = Math.sqrt(\n h.zlen * h.zlen * Math.sin(Math.PI / 180.0 * h.beta) *\n Math.sin(Math.PI / 180.0 * h.beta) - basisZ[ 1 ] * basisZ[ 1 ]\n )\n\n const basis = [ [], basisX, basisY, basisZ ]\n const nxyz = [ 0, h.xRate, h.yRate, h.zRate ]\n const mapcrs = [ 0, 1, 2, 3 ]\n\n const matrix = new Matrix4()\n\n matrix.set(\n basis[ mapcrs[1] ][0] / nxyz[ mapcrs[1] ],\n basis[ mapcrs[2] ][0] / nxyz[ mapcrs[2] ],\n basis[ mapcrs[3] ][0] / nxyz[ mapcrs[3] ],\n 0,\n basis[ mapcrs[1] ][1] / nxyz[ mapcrs[1] ],\n basis[ mapcrs[2] ][1] / nxyz[ mapcrs[2] ],\n basis[ mapcrs[3] ][1] / nxyz[ mapcrs[3] ],\n 0,\n basis[ mapcrs[1] ][2] / nxyz[ mapcrs[1] ],\n basis[ mapcrs[2] ][2] / nxyz[ mapcrs[2] ],\n basis[ mapcrs[3] ][2] / nxyz[ mapcrs[3] ],\n 0,\n 0, 0, 0, 1\n )\n\n matrix.multiply(\n new Matrix4().makeRotationY(degToRad(90))\n )\n\n matrix.multiply(new Matrix4().makeTranslation(\n -h.zStart, h.yStart, h.xStart\n ))\n\n matrix.multiply(new Matrix4().makeScale(\n -1, 1, 1\n ))\n\n return matrix\n }\n}\n\nParserRegistry.add('dsn6', Dsn6Parser)\nParserRegistry.add('brix', Dsn6Parser)\n\nexport default Dsn6Parser\n","/**\n * @file Dx Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4 } from 'three'\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport { degToRad } from '../math/math-utils'\nimport VolumeParser from './volume-parser'\n\nconst reWhitespace = /\\s+/\n\ninterface DxHeader {\n nx: number,\n ny: number,\n nz: number,\n xmin: number,\n ymin: number,\n zmin: number,\n hx: number,\n hy: number,\n hz: number\n}\n\nclass DxParser extends VolumeParser {\n get type () { return 'dx' }\n\n _parse () {\n // http://apbs.readthedocs.io/en/latest/formats/opendx.html\n\n if (Debug) Log.time('DxParser._parse ' + this.name)\n\n const v = this.volume\n const headerLines = this.streamer.peekLines(30)\n const headerInfo = this.parseHeaderLines(headerLines)\n const header = this.volume.header\n const dataLineStart = headerInfo.dataLineStart\n\n const size = header.nx * header.ny * header.nz\n const data = new Float32Array(size)\n let count = 0\n let lineNo = 0\n\n function _parseChunkOfLines (_i: number, _n: number, lines: string []) {\n for (let i = _i; i < _n; ++i) {\n if (count < size && lineNo > dataLineStart) {\n const line = lines[ i ].trim()\n\n if (line !== '') {\n const ls = line.split(reWhitespace)\n\n for (let j = 0, lj = ls.length; j < lj; ++j) {\n data[ count ] = parseFloat(ls[ j ])\n ++count\n }\n }\n }\n\n ++lineNo\n }\n }\n\n this.streamer.eachChunkOfLines(function (lines/*, chunkNo, chunkCount */) {\n _parseChunkOfLines(0, lines.length, lines)\n })\n\n v.setData(data, header.nz, header.ny, header.nx)\n\n if (Debug) Log.timeEnd('DxParser._parse ' + this.name)\n }\n\n parseHeaderLines (headerLines: string []) {\n const header: Partial = {}\n const n = headerLines.length\n\n let dataLineStart = 0\n let headerByteCount = 0\n let deltaLineCount = 0\n\n for (let i = 0; i < n; ++i) {\n let ls\n const line = headerLines[ i ]\n\n if (line.startsWith('object 1')) {\n ls = line.split(reWhitespace)\n\n header.nx = parseInt(ls[ 5 ])\n header.ny = parseInt(ls[ 6 ])\n header.nz = parseInt(ls[ 7 ])\n } else if (line.startsWith('origin')) {\n ls = line.split(reWhitespace)\n\n header.xmin = parseFloat(ls[ 1 ])\n header.ymin = parseFloat(ls[ 2 ])\n header.zmin = parseFloat(ls[ 3 ])\n } else if (line.startsWith('delta')) {\n ls = line.split(reWhitespace)\n\n if (deltaLineCount === 0) {\n header.hx = parseFloat(ls[ 1 ]) * this.voxelSize\n } else if (deltaLineCount === 1) {\n header.hy = parseFloat(ls[ 2 ]) * this.voxelSize\n } else if (deltaLineCount === 2) {\n header.hz = parseFloat(ls[ 3 ]) * this.voxelSize\n }\n\n deltaLineCount += 1\n } else if (line.startsWith('object 3')) {\n dataLineStart = i\n headerByteCount += line.length + 1\n break\n }\n\n headerByteCount += line.length + 1\n }\n\n this.volume.header = header\n\n return {\n dataLineStart: dataLineStart,\n headerByteCount: headerByteCount\n }\n }\n\n getMatrix () {\n const h = this.volume.header\n const matrix = new Matrix4()\n\n matrix.multiply(\n new Matrix4().makeRotationY(degToRad(90))\n )\n\n matrix.multiply(\n new Matrix4().makeTranslation(\n -h.zmin, h.ymin, h.xmin\n )\n )\n\n matrix.multiply(\n new Matrix4().makeScale(\n -h.hz, h.hy, h.hx\n )\n )\n\n return matrix\n }\n}\n\nParserRegistry.add('dx', DxParser)\n\nexport default DxParser\n","/**\n * @file Dxbin Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport { uint8ToLines, ensureBuffer } from '../utils'\nimport DxParser from './dx-parser'\n\nclass DxbinParser extends DxParser {\n get type () { return 'dxbin' }\n get isBinary () { return true }\n\n _parse () {\n // https://github.com/Electrostatics/apbs-pdb2pqr/issues/216\n\n if (Debug) Log.time('DxbinParser._parse ' + this.name)\n\n const bin = ensureBuffer(this.streamer.data)\n const headerLines = uint8ToLines(new Uint8Array(bin, 0, 1000))\n const headerInfo = this.parseHeaderLines(headerLines)\n const header = this.volume.header\n const headerByteCount = headerInfo.headerByteCount\n\n const size = header.nx * header.ny * header.nz\n const dv = new DataView(bin)\n const data = new Float32Array(size)\n\n for (let i = 0; i < size; ++i) {\n data[ i ] = dv.getFloat64(i * 8 + headerByteCount, true)\n }\n\n this.volume.setData(data, header.nz, header.ny, header.nx)\n\n if (Debug) Log.timeEnd('DxbinParser._parse ' + this.name)\n }\n}\n\nParserRegistry.add('dxbin', DxbinParser)\n\nexport default DxbinParser\n","/**\n * @file Mrc Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Matrix4 } from 'three'\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport { ensureBuffer } from '../utils'\nimport VolumeParser from './volume-parser'\n\ninterface MrcHeader {\n MAP: string,\n MACHST: number [],\n NX: number,\n NY: number,\n NZ: number,\n MODE: number,\n NXSTART: number,\n NYSTART: number,\n NZSTART: number,\n MX: number,\n MY: number,\n MZ: number,\n xlen: number,\n ylen: number,\n zlen: number,\n alpha: number,\n beta: number,\n gamma: number,\n MAPC: number,\n MAPR: number,\n MAPS: number,\n DMIN: number,\n DMAX: number,\n DMEAN: number,\n ISPG: number,\n NSYMBT: number,\n LSKFLG: number,\n originX: number,\n originY: number,\n originZ: number,\n ARMS: number\n}\n\nclass MrcParser extends VolumeParser {\n get type () { return 'mrc' }\n get isBinary () { return true }\n\n _parse () {\n // MRC\n // http://ami.scripps.edu/software/mrctools/mrc_specification.php\n // http://www2.mrc-lmb.cam.ac.uk/research/locally-developed-software/image-processing-software/#image\n // http://bio3d.colorado.edu/imod/doc/mrc_format.txt\n\n // CCP4 (MAP)\n // http://www.ccp4.ac.uk/html/maplib.html\n\n // MRC format does not use the skew transformation header records (words 25-37)\n // CCP4 format does not use the ORIGIN header records (words 50-52)\n\n if (Debug) Log.time('MrcParser._parse ' + this.name)\n\n const v = this.volume\n const header: Partial = {}\n\n const bin = ensureBuffer(this.streamer.data)\n const intView = new Int32Array(bin, 0, 56)\n const floatView = new Float32Array(bin, 0, 56)\n const dv = new DataView(bin)\n\n // 53 MAP Character string 'MAP ' to identify file type\n header.MAP = String.fromCharCode(\n dv.getUint8(52 * 4), dv.getUint8(52 * 4 + 1),\n dv.getUint8(52 * 4 + 2), dv.getUint8(52 * 4 + 3)\n )\n\n // 54 MACHST Machine stamp indicating machine type which wrote file\n // 17 and 17 for big-endian or 68 and 65 for little-endian\n header.MACHST = [ dv.getUint8(53 * 4), dv.getUint8(53 * 4 + 1) ]\n\n // swap byte order when big endian\n if (header.MACHST[ 0 ] === 17 && header.MACHST[ 1 ] === 17) {\n const n = bin.byteLength\n for (let i = 0; i < n; i += 4) {\n dv.setFloat32(i, dv.getFloat32(i), true)\n }\n }\n\n header.NX = intView[ 0 ] // NC - columns (fastest changing)\n header.NY = intView[ 1 ] // NR - rows\n header.NZ = intView[ 2 ] // NS - sections (slowest changing)\n\n // mode\n // 0 image : signed 8-bit bytes range -128 to 127\n // 1 image : 16-bit halfwords\n // 2 image : 32-bit reals\n // 3 transform : complex 16-bit integers\n // 4 transform : complex 32-bit reals\n // 6 image : unsigned 16-bit range 0 to 65535\n // 16 image: unsigned char * 3 (for rgb data, non-standard)\n //\n // Note: Mode 2 is the normal mode used in the CCP4 programs.\n // Other modes than 2 and 0 may NOT WORK\n header.MODE = intView[ 3 ]\n\n // start\n header.NXSTART = intView[ 4 ] // NCSTART - first column\n header.NYSTART = intView[ 5 ] // NRSTART - first row\n header.NZSTART = intView[ 6 ] // NSSTART - first section\n\n // intervals\n header.MX = intView[ 7 ] // intervals along x\n header.MY = intView[ 8 ] // intervals along y\n header.MZ = intView[ 9 ] // intervals along z\n\n // cell length (Angstroms in CCP4)\n header.xlen = floatView[ 10 ] * this.voxelSize\n header.ylen = floatView[ 11 ] * this.voxelSize\n header.zlen = floatView[ 12 ] * this.voxelSize\n\n // cell angle (Degrees)\n header.alpha = floatView[ 13 ]\n header.beta = floatView[ 14 ]\n header.gamma = floatView[ 15 ]\n\n // axis correspondence (1,2,3 for X,Y,Z)\n header.MAPC = intView[ 16 ] // column\n header.MAPR = intView[ 17 ] // row\n header.MAPS = intView[ 18 ] // section\n\n // density statistics\n header.DMIN = floatView[ 19 ]\n header.DMAX = floatView[ 20 ]\n header.DMEAN = floatView[ 21 ]\n\n // space group number 0 or 1 (default=0)\n header.ISPG = intView[ 22 ]\n\n // number of bytes used for symmetry data (0 or 80)\n header.NSYMBT = intView[ 23 ]\n\n // Flag for skew transformation, =0 none, =1 if foll\n header.LSKFLG = intView[ 24 ]\n\n // 26-34 SKWMAT Skew matrix S (in order S11, S12, S13, S21 etc) if\n // LSKFLG .ne. 0.\n // 35-37 SKWTRN Skew translation t if LSKFLG != 0.\n // Skew transformation is from standard orthogonal\n // coordinate frame (as used for atoms) to orthogonal\n // map frame, as Xo(map) = S * (Xo(atoms) - t)\n\n // 38 future use (some of these are used by the MSUBSX routines\n // . \" in MAPBRICK, MAPCONT and FRODO)\n // . \" (all set to zero by default)\n // . \"\n // 52 \"\n\n // 50-52 origin in X,Y,Z used for transforms\n header.originX = floatView[ 49 ]\n header.originY = floatView[ 50 ]\n header.originZ = floatView[ 51 ]\n\n // 53 MAP Character string 'MAP ' to identify file type\n // => see top of this parser\n\n // 54 MACHST Machine stamp indicating machine type which wrote file\n // => see top of this parser\n\n // Rms deviation of map from mean density\n header.ARMS = floatView[ 54 ]\n\n // 56 NLABL Number of labels being used\n // 57-256 LABEL(20,10) 10 80 character text labels (ie. A4 format)\n\n v.header = header\n\n // Log.log( header );\n\n let data\n if (header.MODE === 2) {\n data = new Float32Array(\n bin, 256 * 4 + header.NSYMBT,\n header.NX * header.NY * header.NZ\n )\n } else if (header.MODE === 0) {\n data = new Float32Array(new Int8Array(\n bin, 256 * 4 + header.NSYMBT,\n header.NX * header.NY * header.NZ\n ))\n\n // based on uglymol (https://github.com/uglymol/uglymol) by Marcin Wojdyr (wojdyr)\n // if the file was converted by mapmode2to0 - scale the data\n if (intView[ 39 ] === -128 && intView[ 40 ] === 127) {\n // scaling f(x)=b1*x+b0 such that f(-128)=min and f(127)=max\n const b1 = (header.DMAX - header.DMIN) / 255.0\n const b0 = 0.5 * (header.DMIN + header.DMAX + b1)\n for (let j = 0, jl = data.length; j < jl; ++j) {\n data[ j ] = b1 * data[ j ] + b0\n }\n }\n } else {\n Log.error('MrcParser unknown mode', header.MODE)\n }\n\n v.setData(data, header.NX, header.NY, header.NZ)\n if (header.ARMS !== 0) {\n v.setStats(header.DMIN, header.DMAX, header.DMEAN, header.ARMS)\n }\n\n if (Debug) Log.timeEnd('MrcParser._parse ' + this.name)\n }\n\n getMatrix () {\n const h = this.volume.header\n\n const basisX = [\n h.xlen,\n 0,\n 0\n ]\n\n const basisY = [\n h.ylen * Math.cos(Math.PI / 180.0 * h.gamma),\n h.ylen * Math.sin(Math.PI / 180.0 * h.gamma),\n 0\n ]\n\n const basisZ = [\n h.zlen * Math.cos(Math.PI / 180.0 * h.beta),\n h.zlen * (\n Math.cos(Math.PI / 180.0 * h.alpha) -\n Math.cos(Math.PI / 180.0 * h.gamma) *\n Math.cos(Math.PI / 180.0 * h.beta)\n ) / Math.sin(Math.PI / 180.0 * h.gamma),\n 0\n ]\n basisZ[ 2 ] = Math.sqrt(\n h.zlen * h.zlen * Math.sin(Math.PI / 180.0 * h.beta) *\n Math.sin(Math.PI / 180.0 * h.beta) - basisZ[ 1 ] * basisZ[ 1 ]\n )\n\n const basis = [ [], basisX, basisY, basisZ ]\n const nxyz = [ 0, h.MX, h.MY, h.MZ ]\n const mapcrs = [ 0, h.MAPC, h.MAPR, h.MAPS ]\n\n const matrix = new Matrix4()\n\n matrix.set(\n basis[ mapcrs[1] ][0] / nxyz[ mapcrs[1] ],\n basis[ mapcrs[2] ][0] / nxyz[ mapcrs[2] ],\n basis[ mapcrs[3] ][0] / nxyz[ mapcrs[3] ],\n 0,\n basis[ mapcrs[1] ][1] / nxyz[ mapcrs[1] ],\n basis[ mapcrs[2] ][1] / nxyz[ mapcrs[2] ],\n basis[ mapcrs[3] ][1] / nxyz[ mapcrs[3] ],\n 0,\n basis[ mapcrs[1] ][2] / nxyz[ mapcrs[1] ],\n basis[ mapcrs[2] ][2] / nxyz[ mapcrs[2] ],\n basis[ mapcrs[3] ][2] / nxyz[ mapcrs[3] ],\n 0,\n 0, 0, 0, 1\n )\n\n matrix.setPosition(new Vector3(\n h.originX, h.originY, h.originZ\n ))\n\n matrix.multiply(new Matrix4().makeTranslation(\n h.NXSTART, h.NYSTART, h.NZSTART\n ))\n\n return matrix\n }\n}\n\nParserRegistry.add('mrc', MrcParser)\nParserRegistry.add('ccp4', MrcParser)\nParserRegistry.add('map', MrcParser)\n\nexport default MrcParser\n","/**\n * @file Xplor Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4 } from 'three'\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport VolumeParser from './volume-parser'\n\nconst reWhitespace = /\\s+/\n\nfunction parseNumberLine (line: string) {\n return line.trim().split(reWhitespace).map(parseFloat)\n}\n\ninterface XplorHeader {\n NA: number,\n AMIN: number,\n AMAX: number,\n NB: number,\n BMIN: number,\n BMAX: number,\n NC: number,\n CMIN: number,\n CMAX: number,\n a: number,\n b: number,\n c: number,\n alpha: number,\n beta: number,\n gamma: number,\n RAVE: number,\n RSIGMA: number\n}\n\nclass XplorParser extends VolumeParser {\n get type () { return 'xplor' }\n\n _parse () {\n // http://hincklab.uthscsa.edu/html/soft_packs/msi_docs/insight980/xplor/formats.html\n // http://www.mrc-lmb.cam.ac.uk/public/xtal/doc/cns/cns_1.3/tutorial/formats/maps/text.html\n\n if (Debug) Log.time('XplorParser._parse ' + this.name)\n\n const v = this.volume\n const headerLines = this.streamer.peekLines(8)\n const header: Partial = {}\n\n let infoStart\n if (headerLines[ 2 ].startsWith('REMARKS')) {\n infoStart = parseInt(headerLines[ 1 ].substring(0, 8)) + 2\n } else {\n infoStart = 5\n }\n const dataStart = infoStart + 3\n\n const gridInfo = parseNumberLine(headerLines[ infoStart ])\n header.NA = gridInfo[ 0 ]\n header.AMIN = gridInfo[ 1 ]\n header.AMAX = gridInfo[ 2 ]\n header.NB = gridInfo[ 3 ]\n header.BMIN = gridInfo[ 4 ]\n header.BMAX = gridInfo[ 5 ]\n header.NC = gridInfo[ 6 ]\n header.CMIN = gridInfo[ 7 ]\n header.CMAX = gridInfo[ 8 ]\n\n const cellInfo = parseNumberLine(headerLines[ infoStart + 1 ])\n header.a = cellInfo[ 0 ] * this.voxelSize\n header.b = cellInfo[ 1 ] * this.voxelSize\n header.c = cellInfo[ 2 ] * this.voxelSize\n header.alpha = cellInfo[ 3 ]\n header.beta = cellInfo[ 4 ]\n header.gamma = cellInfo[ 5 ]\n\n const na = header.AMAX - header.AMIN + 1\n const nb = header.BMAX - header.BMIN + 1\n const nc = header.CMAX - header.CMIN + 1\n const n = na * nb * nc\n\n const data = new Float32Array(n)\n const lineSection = Math.ceil(1 + (na * nb) / 6)\n let count = 0\n let lineNo = 0\n\n function _parseChunkOfLines (_i: number, _n: number, lines: string[]) {\n for (let i = _i; i < _n; ++i) {\n const line = lines[ i ]\n\n if (lineNo >= dataStart && (lineNo - dataStart) % lineSection !== 0 && count < n) {\n for (let j = 0, lj = 6; j < lj; ++j) {\n const value = parseFloat(line.substr(12 * j, 12))\n if (isNaN(value)) { break } // Last line of map section\n data[count++] = value\n }\n } else if (count === n) {\n const lt = line.trim()\n if (lt && lt !== '-9999') {\n const ls = parseNumberLine(line)\n header.RAVE = ls[0]\n header.RSIGMA = ls[1]\n }\n }\n\n ++lineNo\n }\n }\n\n this.streamer.eachChunkOfLines(function (lines/*, chunkNo, chunkCount */) {\n _parseChunkOfLines(0, lines.length, lines)\n })\n\n v.header = header\n v.setData(data, na, nb, nc)\n if (header.RAVE !== 0 && header.RSIGMA !== 1) {\n v.setStats(undefined, undefined, header.RAVE, header.RSIGMA)\n }\n\n if (Debug) Log.timeEnd('XplorParser._parse ' + this.name)\n }\n\n getMatrix () {\n const h = this.volume.header\n\n const basisX = [\n h.a,\n 0,\n 0\n ]\n\n const basisY = [\n h.b * Math.cos(Math.PI / 180.0 * h.gamma),\n h.b * Math.sin(Math.PI / 180.0 * h.gamma),\n 0\n ]\n\n const basisZ = [\n h.c * Math.cos(Math.PI / 180.0 * h.beta),\n h.c * (\n Math.cos(Math.PI / 180.0 * h.alpha) -\n Math.cos(Math.PI / 180.0 * h.gamma) *\n Math.cos(Math.PI / 180.0 * h.beta)\n ) / Math.sin(Math.PI / 180.0 * h.gamma),\n 0\n ]\n basisZ[ 2 ] = Math.sqrt(\n h.c * h.c * Math.sin(Math.PI / 180.0 * h.beta) *\n Math.sin(Math.PI / 180.0 * h.beta) - basisZ[ 1 ] * basisZ[ 1 ]\n )\n\n const basis = [ [], basisX, basisY, basisZ ]\n const nxyz = [ 0, h.NA, h.NB, h.NC ]\n const mapcrs = [ 0, 1, 2, 3 ]\n\n const matrix = new Matrix4()\n\n matrix.set(\n basis[ mapcrs[1] ][0] / nxyz[ mapcrs[1] ],\n basis[ mapcrs[2] ][0] / nxyz[ mapcrs[2] ],\n basis[ mapcrs[3] ][0] / nxyz[ mapcrs[3] ],\n 0,\n basis[ mapcrs[1] ][1] / nxyz[ mapcrs[1] ],\n basis[ mapcrs[2] ][1] / nxyz[ mapcrs[2] ],\n basis[ mapcrs[3] ][1] / nxyz[ mapcrs[3] ],\n 0,\n basis[ mapcrs[1] ][2] / nxyz[ mapcrs[1] ],\n basis[ mapcrs[2] ][2] / nxyz[ mapcrs[2] ],\n basis[ mapcrs[3] ][2] / nxyz[ mapcrs[3] ],\n 0,\n 0, 0, 0, 1\n )\n\n matrix.multiply(new Matrix4().makeTranslation(\n h.AMIN, h.BMIN, h.CMIN\n ))\n\n return matrix\n }\n}\n\nParserRegistry.add('xplor', XplorParser)\nParserRegistry.add('cns', XplorParser)\n\nexport default XplorParser\n","/**\n * @file Kin Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport { Vector3 } from 'three'\nimport Parser from './parser'\n\nfunction hsvToRgb (h: number, s: number, v: number) {\n h /= 360\n s /= 100\n v /= 100\n let r, g, b\n const i = Math.floor(h * 6)\n const f = h * 6 - i\n const p = v * (1 - s)\n const q = v * (1 - f * s)\n const t = v * (1 - (1 - f) * s)\n switch (i % 6) {\n case 0: r = v; g = t; b = p; break\n case 1: r = q; g = v; b = p; break\n case 2: r = p; g = v; b = t; break\n case 3: r = p; g = q; b = v; break\n case 4: r = t; g = p; b = v; break\n case 5: r = v; g = p; b = q; break\n }\n return [ r, g, b ] as number []\n}\n\nconst ColorDict: {[k: string]: number[]} = {\n red: hsvToRgb(0, 100, 100),\n orange: hsvToRgb(20, 100, 100),\n gold: hsvToRgb(40, 100, 100),\n yellow: hsvToRgb(60, 100, 100),\n lime: hsvToRgb(80, 100, 100),\n green: hsvToRgb(120, 80, 100),\n sea: hsvToRgb(150, 100, 100),\n cyan: hsvToRgb(180, 100, 85),\n sky: hsvToRgb(210, 75, 95),\n blue: hsvToRgb(240, 70, 100),\n purple: hsvToRgb(275, 75, 100),\n magenta: hsvToRgb(300, 95, 100),\n hotpink: hsvToRgb(335, 100, 100),\n pink: hsvToRgb(350, 55, 100),\n peach: hsvToRgb(25, 75, 100),\n lilac: hsvToRgb(275, 55, 100),\n pinktint: hsvToRgb(340, 30, 100),\n peachtint: hsvToRgb(25, 50, 100),\n yellowtint: hsvToRgb(60, 50, 100),\n greentint: hsvToRgb(135, 40, 100),\n bluetint: hsvToRgb(220, 40, 100),\n lilactint: hsvToRgb(275, 35, 100),\n white: hsvToRgb(0, 0, 100),\n gray: hsvToRgb(0, 0, 50),\n brown: hsvToRgb(20, 45, 75),\n deadwhite: [ 1, 1, 1 ],\n deadblack: [ 0, 0, 0 ],\n invisible: [ 0, 0, 0 ]\n}\n\nconst reWhitespaceComma = /[\\s,]+/\nconst reCurlyWhitespace = /[^{}\\s]*{[^{}]+}|[^{}\\s]+/g\nconst reTrimCurly = /^{+|}+$/g\nconst reTrimQuotes = /^['\"]+|['\"]+$/g\nconst reCollapseEqual = /\\s*=\\s*/g\n\nfunction parseListDef (line: string) {\n let name\n let defaultColor\n let master = []\n let width\n\n line = line.replace(reCollapseEqual, '=')\n\n const lm = line.match(reCurlyWhitespace) as RegExpMatchArray\n for (let j = 1; j < lm.length; ++j) {\n const e = lm[ j ]\n if (e[ 0 ] === '{') {\n name = e.substring(1, e.length - 1)\n } else {\n const es = e.split('=')\n if (es.length === 2) {\n if (es[ 0 ] === 'color') {\n defaultColor = ColorDict[ es[ 1 ] ]\n } else if (es[ 0 ] === 'width') {\n width = parseInt(es[ 1 ])\n } else if (es[ 0 ] === 'master') {\n master.push(es[ 1 ].replace(reTrimCurly, ''))\n }\n }\n }\n }\n\n return {\n listName: name,\n listColor: defaultColor,\n listMasters: master,\n listWidth: width\n }\n}\n\nfunction parseListElm (line: string) {\n line = line.trim()\n\n const idx1 = line.indexOf('{')\n const idx2 = line.indexOf('}')\n const ls = line.substr(idx2 + 1).split(reWhitespaceComma)\n\n const label = line.substr(idx1 + 1, idx2 - 1)\n const position = [\n parseFloat(ls[ ls.length - 3 ]),\n parseFloat(ls[ ls.length - 2 ]),\n parseFloat(ls[ ls.length - 1 ])\n ]\n let color, width, radius\n let lineBreak = false\n let triangleBreak = false\n for (let lsindex = 4; lsindex <= ls.length; lsindex++) {\n const literal = ls[ ls.length - lsindex ]\n if (literal in ColorDict) {\n color = ColorDict[ ls[ ls.length - lsindex ] ]\n }\n if (literal.startsWith('width')) {\n width = parseInt(literal.substring(5))\n }\n if (literal.startsWith('r=')) {\n radius = parseFloat(literal.split('=')[1])\n }\n if (literal.startsWith('P')) {\n lineBreak = true\n }\n if (literal.startsWith('X')) {\n triangleBreak = true\n }\n }\n // const color = line[ idx2 + 1 ] === ' ' ? undefined : ColorDict[ ls[ 0 ] ]\n\n return {\n label: label,\n position: position,\n color: color,\n radius: radius,\n width: width,\n isLineBreak: lineBreak,\n isTriangleBreak: triangleBreak\n }\n}\n\nfunction parseStr (line: string) {\n const start = line.indexOf('{')\n const end = line.indexOf('}')\n return line.substring(\n start !== -1 ? start + 1 : 0,\n end !== -1 ? end : undefined\n ).trim()\n}\n\nfunction parseFlag (line: string) {\n const end = line.indexOf('}')\n return end === -1 ? undefined : line.substr(end + 1).trim()\n}\n\nfunction parseGroup (line: string) {\n let name:string = ''\n let master:string[] = []\n let flags: {[k: string]: string|boolean} = {}\n\n line = line.replace(reCollapseEqual, '=')\n\n const lm = line.match(reCurlyWhitespace) as RegExpMatchArray\n for (let j = 1; j < lm.length; ++j) {\n const e = lm[ j ]\n if (e[ 0 ] === '{') {\n name = e.substring(1, e.length - 1)\n } else {\n const es = e.split('=')\n if (es.length === 2) {\n if (es[ 0 ] === 'master') {\n master.push(es[ 1 ].replace(reTrimCurly, ''))\n } else {\n flags[ es[ 0 ] ] = es[ 1 ].replace(reTrimCurly, '')\n }\n } else {\n flags[ es[ 0 ] ] = true\n }\n }\n }\n\n return { groupName: name,\n groupFlags: flags,\n groupMasters: master\n }\n}\ninterface RibbonObject {\n labelArray: string[],\n positionArray: number[],\n breakArray: boolean[],\n colorArray: number[],\n name?: string,\n masterArray: any[]\n}\nfunction convertKinTriangleArrays (ribbonObject: RibbonObject) {\n // have to convert ribbons/triangle lists from stripdrawmode to normal drawmode\n // index [ 0 1 2 3 4 5 6 7 8 91011 ]\n // label [ 0 1 2 3 4 5 ] to [ 0 1 2 1 2 3 2 3 4 3 4 5 ]\n // convertedindex [ 0 1 2 3 4 5 6 7 8 91011121314151617181920212223242526 ]\n // index [ 0 1 2 3 4 5 6 7 8 91011121314 ] [ 0 1 2 3 4 5 6 7 8 3 4 5 6 7 8 91011 6 7 8 91011121314 ]\n // position/color [ 0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 ] to [ 0 0 0 1 1 1 2 2 2 1 1 1 2 2 2 3 3 3 2 2 2 3 3 3 4 4 4 ]\n let { labelArray, positionArray, colorArray, breakArray } = ribbonObject\n let convertedLabels = []\n for (let i = 0; i < (labelArray.length - 2) * 3; ++i) {\n convertedLabels[i] = labelArray[i - Math.floor(i / 3) * 2]\n }\n let convertedBreaks = []\n for (let i = 0; i < (breakArray.length - 2) * 3; ++i) {\n convertedBreaks[i] = breakArray[i - Math.floor(i / 3) * 2]\n }\n let convertedPositions = []\n for (let i = 0; i < (positionArray.length / 3 - 2) * 9; ++i) {\n convertedPositions[i] = positionArray[i - Math.floor(i / 9) * 6]\n }\n let convertedColors = []\n for (let i = 0; i < (colorArray.length / 3 - 2) * 9; ++i) {\n convertedColors[i] = colorArray[i - Math.floor(i / 9) * 6]\n }\n let vector3Positions = []\n for (let i = 0; i < (convertedPositions.length) / 3; ++i) {\n vector3Positions.push(new Vector3(convertedPositions[i * 3], convertedPositions[i * 3] + 1, convertedPositions[i * 3] + 2))\n }\n //let normals = []\n //for (let i = 0; i < vector3Positions.length - 1; ++i) {\n // let normalVec3 = vector3Positions[i].cross(vector3Positions[i + 1])\n // normals.push(normalVec3.x)\n // normals.push(normalVec3.y)\n // normals.push(normalVec3.z)\n //}\n return {\n name: ribbonObject.name,\n masterArray: ribbonObject.masterArray,\n labelArray: convertedLabels,\n positionArray: convertedPositions,\n breakArray: convertedBreaks,\n colorArray: convertedColors\n }\n}\n\nfunction removePointBreaksTriangleArrays (convertedRibbonObject: RibbonObject) {\n // after converting ribbon/triangle arrys to drawmode, removed point break triangles\n // label [ 0 1 2 3 4 5 ] to [ 0 1 2 1 2 3 2 3 4 3 4 5 ]\n // position/color [ 0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 ] to [ 0 0 0 1 1 1 2 2 2 1 1 1 2 2 2 3 3 3 2 2 2 3 3 3 4 4 4 ]\n let { labelArray, positionArray, colorArray, breakArray } = convertedRibbonObject\n let editedLabels = []\n let editedPositions = []\n let editedColors = []\n let editedBreaks = []\n for (let i = 0; i < breakArray.length / 3; i++) {\n let breakPointer = i * 3\n let positionPointer = i * 9\n if (!breakArray[breakPointer+1]&&!breakArray[breakPointer+2]) {\n editedLabels.push(labelArray[breakPointer])\n editedLabels.push(labelArray[breakPointer+1])\n editedLabels.push(labelArray[breakPointer+2])\n editedBreaks.push(breakArray[breakPointer])\n editedBreaks.push(breakArray[breakPointer+1])\n editedBreaks.push(breakArray[breakPointer+2])\n editedPositions.push(positionArray[positionPointer])\n editedPositions.push(positionArray[positionPointer+1])\n editedPositions.push(positionArray[positionPointer+2])\n editedPositions.push(positionArray[positionPointer+3])\n editedPositions.push(positionArray[positionPointer+4])\n editedPositions.push(positionArray[positionPointer+5])\n editedPositions.push(positionArray[positionPointer+6])\n editedPositions.push(positionArray[positionPointer+7])\n editedPositions.push(positionArray[positionPointer+8])\n editedColors.push(colorArray[positionPointer])\n editedColors.push(colorArray[positionPointer+1])\n editedColors.push(colorArray[positionPointer+2])\n editedColors.push(colorArray[positionPointer+3])\n editedColors.push(colorArray[positionPointer+4])\n editedColors.push(colorArray[positionPointer+5])\n editedColors.push(colorArray[positionPointer+6])\n editedColors.push(colorArray[positionPointer+7])\n editedColors.push(colorArray[positionPointer+8])\n } else {\n //console.log('X triangle break found')\n //console.log('skipping: '+positionArray[positionPointer]+','+positionArray[positionPointer+1]+','+positionArray[positionPointer+2]+','\n // +positionArray[positionPointer+3]+','+positionArray[positionPointer+4]+','+positionArray[positionPointer+5]+','\n // +positionArray[positionPointer+6]+','+positionArray[positionPointer+7]+','+positionArray[positionPointer+8])\n }\n }\n return {\n name: convertedRibbonObject.name,\n masterArray: convertedRibbonObject.masterArray,\n labelArray: editedLabels,\n positionArray: editedPositions,\n breakArray: editedBreaks,\n colorArray: editedColors\n }\n}\n\ninterface Kinemage {\n kinemage?: number,\n onewidth?: any,\n '1viewid'?: string,\n pdbfile?: string,\n text: string,\n texts: string[],\n captions: string[],\n caption: string,\n groupDict: {[k:string]: {[k:string]: boolean}},\n subgroupDict: {[k: string]: any},\n masterDict: {[k:string]: {indent: boolean, visible: boolean}},\n pointmasterDict: {[k: string]: any},\n dotLists: DotList[],\n vectorLists: VectorList[],\n ballLists: any[],\n ribbonLists: RibbonObject[]\n}\n\ninterface DotList {\n name?: string,\n masterArray: any[],\n labelArray: any[],\n positionArray: any[],\n colorArray: any[]\n}\n\ninterface VectorList {\n name?: string,\n masterArray: any[],\n label1Array: string[],\n label2Array: string[],\n position1Array: number[],\n position2Array: number[],\n color1Array: number[],\n color2Array: number[],\n width: number[]\n}\n\nclass KinParser extends Parser {\n kinemage: Kinemage\n get type () { return 'kin' }\n get __objName () { return 'kinemage' }\n\n _parse () {\n // http://kinemage.biochem.duke.edu/software/king.php\n\n if (Debug) Log.time(`KinParser._parse ${this.name}`)\n\n const kinemage: Kinemage = {\n kinemage: undefined,\n onewidth: undefined,\n '1viewid': undefined,\n pdbfile: undefined,\n texts: [],\n text: '',\n captions: [],\n caption: '',\n groupDict: {},\n subgroupDict: {},\n masterDict: {},\n pointmasterDict: {},\n dotLists: [],\n vectorLists: [],\n ballLists: [],\n ribbonLists: []\n }\n this.kinemage = kinemage\n\n let currentGroupMasters: string[]\n let currentSubgroupMasters: string[]\n\n let isDotList = false\n let prevDotLabel = ''\n let dotDefaultColor: number[]\n let dotLabel: string[], dotPosition: number[], dotColor: number[]\n\n let isVectorList = false\n let prevVecLabel = ''\n let prevVecPosition: number[]|null = null\n let prevVecColor: number[]|null = null\n let vecDefaultColor: number[], vecDefaultWidth: number[]\n let vecLabel1: string[], vecLabel2: string[], vecPosition1: number[], vecPosition2: number[], vecColor1: number[], vecColor2: number[]\n\n let isBallList = false\n let prevBallLabel = ''\n let ballRadius: number[], ballDefaultColor: number[]\n let ballLabel: string[], ballPosition: number[], ballColor: number[]\n\n let isRibbonList = false\n let prevRibbonPointLabel = ''\n\n let ribbonListDefaultColor: number[]\n let ribbonPointLabelArray: string[], ribbonPointPositionArray: number[], ribbonPointBreakArray: boolean[], ribbonPointColorArray: number[]\n\n let isText = false\n let isCaption = false\n\n // @vectorlist {mc} color= white master= {mainchain}\n // { n thr A 1 B13.79 1crnFH} P 17.047, 14.099, 3.625 { n thr A 1 B13.79 1crnFH} L 17.047, 14.099, 3.625\n\n // @dotlist {x} color=white master={vdw contact} master={dots}\n // { CB THR 1 A}sky 'P' 18.915,14.199,5.024\n\n function _parseChunkOfLines (_i: number, _n: number, lines: string[]) {\n for (let i = _i; i < _n; ++i) {\n const line = lines[ i ]\n\n if (line[ 0 ] === '@') {\n isDotList = false\n isVectorList = false\n isBallList = false\n isRibbonList = false\n isText = false\n isCaption = false\n }\n\n if (!line) {\n isDotList = false\n isVectorList = false\n isBallList = false\n isRibbonList = false\n } else if (line.startsWith('@dotlist')) {\n // @dotlist {x} color=white master={vdw contact} master={dots}\n\n let { listColor, listName, listMasters } = parseListDef(line)\n\n isDotList = true\n prevDotLabel = ''\n dotLabel = []\n dotPosition = []\n dotColor = []\n dotDefaultColor = listColor as number[]\n\n if (currentGroupMasters) {\n listMasters = listMasters.concat(currentGroupMasters)\n }\n if (currentSubgroupMasters) {\n listMasters = listMasters.concat(currentSubgroupMasters)\n }\n\n kinemage.dotLists.push({\n name: listName,\n masterArray: listMasters,\n labelArray: dotLabel,\n positionArray: dotPosition,\n colorArray: dotColor\n })\n } else if (line.startsWith('@vectorlist')) {\n // @vectorlist {x} color=white master={small overlap} master={dots}\n\n let { listMasters, listName, listWidth, listColor } = parseListDef(line)\n\n if (listMasters) {\n listMasters.forEach(function (name: string) {\n if (!kinemage.masterDict[ name ]) {\n kinemage.masterDict[ name ] = {\n indent: false,\n visible: false\n }\n }\n })\n }\n\n isVectorList = true\n prevVecLabel = ''\n prevVecPosition = null\n prevVecColor = null\n vecLabel1 = []\n vecLabel2 = []\n vecPosition1 = []\n vecPosition2 = []\n vecColor1 = []\n vecColor2 = []\n vecDefaultColor = listColor as number[]\n vecDefaultWidth = []\n if (listWidth) {\n vecDefaultWidth.push(listWidth)\n }\n\n if (currentGroupMasters) {\n listMasters = listMasters.concat(currentGroupMasters)\n }\n if (currentSubgroupMasters) {\n listMasters = listMasters.concat(currentSubgroupMasters)\n }\n\n kinemage.vectorLists.push({\n name: listName,\n masterArray: listMasters,\n label1Array: vecLabel1,\n label2Array: vecLabel2,\n position1Array: vecPosition1,\n position2Array: vecPosition2,\n color1Array: vecColor1,\n color2Array: vecColor2,\n width: vecDefaultWidth\n })\n } else if (line.startsWith('@balllist')) {\n let { listName, listColor, listMasters } = parseListDef(line)\n\n if (listMasters) {\n listMasters.forEach(function (name: string) {\n if (!kinemage.masterDict[ name ]) {\n kinemage.masterDict[ name ] = {\n indent: false,\n visible: false\n }\n }\n })\n }\n\n isBallList = true\n\n prevBallLabel = ''\n ballLabel = []\n ballRadius = []\n ballPosition = []\n ballColor = []\n ballDefaultColor = listColor as number[]\n\n if (currentGroupMasters) {\n listMasters = listMasters.concat(currentGroupMasters)\n }\n if (currentSubgroupMasters) {\n listMasters = listMasters.concat(currentSubgroupMasters)\n }\n\n kinemage.ballLists.push({\n name: listName,\n masterArray: listMasters,\n labelArray: ballLabel,\n radiusArray: ballRadius,\n positionArray: ballPosition,\n colorArray: ballColor\n })\n } else if (line.startsWith('@ribbonlist')||line.startsWith('@trianglelist')) {\n let { listMasters, listName, listColor } = parseListDef(line)\n\n if (listMasters) {\n listMasters.forEach(function (name: string) {\n if (!kinemage.masterDict[ name ]) {\n kinemage.masterDict[ name ] = {\n indent: false,\n visible: false\n }\n }\n })\n }\n isRibbonList = true\n prevRibbonPointLabel = ''\n ribbonPointLabelArray = []\n ribbonPointPositionArray = []\n ribbonPointBreakArray = []\n ribbonPointColorArray = []\n ribbonListDefaultColor = listColor as number[]\n\n if (currentGroupMasters) {\n listMasters = listMasters.concat(currentGroupMasters)\n }\n if (currentSubgroupMasters) {\n listMasters = listMasters.concat(currentSubgroupMasters)\n }\n\n kinemage.ribbonLists.push({\n name: listName,\n masterArray: listMasters,\n labelArray: ribbonPointLabelArray,\n positionArray: ribbonPointPositionArray,\n breakArray: ribbonPointBreakArray,\n colorArray: ribbonPointColorArray\n })\n } else if (line.startsWith('@text')) {\n isText = true\n kinemage.texts.push(line.substr(5))\n } else if (line.startsWith('@caption')) {\n isCaption = true\n kinemage.captions.push(line.substr(8))\n } else if (isDotList) {\n // { CB THR 1 A}sky 'P' 18.915,14.199,5.024\n\n let { label, color, position } = parseListElm(line)\n\n if (label === '\"') {\n label = prevDotLabel\n } else {\n prevDotLabel = label\n }\n\n if (color === undefined) {\n color = dotDefaultColor\n }\n\n dotLabel.push(label)\n dotPosition.push(...position)\n dotColor.push(...color)\n } else if (isVectorList) {\n // { n thr A 1 B13.79 1crnFH} P 17.047, 14.099, 3.625 { n thr A 1 B13.79 1crnFH} L 17.047, 14.099, 3.625\n\n let doubleLine = line.replace(/(?!^){/g, '\\n{')\n let splitLine = doubleLine.split(/\\n/)\n\n for (var i2 = 0; i2 < splitLine.length; i2++) {\n let singlePointLine = splitLine[i2]\n let { label, color, width, position, isLineBreak } = parseListElm(singlePointLine)\n\n if (label === '\"') {\n label = prevVecLabel\n } else {\n prevVecLabel = label\n }\n\n if (color === undefined) {\n color = vecDefaultColor\n }\n\n if (!isLineBreak) {\n if (prevVecPosition !== null) {\n if (width) {\n vecDefaultWidth.push(width)\n }\n\n vecLabel1.push(prevVecLabel)\n vecPosition1.push(...prevVecPosition)\n vecColor1.push(...prevVecColor as number[])\n\n vecLabel2.push(label)\n vecPosition2.push(...position)\n vecColor2.push(...color)\n\n }\n }\n\n prevVecLabel = label\n prevVecPosition = position\n prevVecColor = color\n }\n } else if (isBallList) {\n // {cb arg A 1 1.431 -106.80} r=1.431 39.085, 8.083, 22.182\n\n let { label, radius, color, position } = parseListElm(line)\n\n if (label === '\"') {\n label = prevBallLabel\n } else {\n prevBallLabel = label\n }\n\n if (radius === undefined) {\n radius = 1 // temporary default radius\n }\n\n if (color === undefined) {\n color = ballDefaultColor\n }\n\n ballLabel.push(label)\n ballRadius.push(radius)\n ballPosition.push(...position)\n ballColor.push(...color)\n } else if (isRibbonList) {\n let { label, color, position, isTriangleBreak } = parseListElm(line)\n\n if (label === '\"') {\n label = prevRibbonPointLabel\n } else {\n prevRibbonPointLabel = label\n }\n\n if (color === undefined) {\n color = ribbonListDefaultColor\n }\n\n ribbonPointLabelArray.push(label)\n ribbonPointPositionArray.push(...position)\n ribbonPointBreakArray.push(isTriangleBreak)\n ribbonPointColorArray.push(...color)\n } else if (isText) {\n kinemage.texts.push(line)\n } else if (isCaption) {\n kinemage.captions.push(line)\n } else if (line.startsWith('@kinemage')) {\n kinemage.kinemage = parseInt(line.substr(9).trim())\n } else if (line.startsWith('@onewidth')) {\n kinemage.onewidth = true\n } else if (line.startsWith('@1viewid')) {\n kinemage[ '1viewid' ] = parseStr(line)\n } else if (line.startsWith('@pdbfile')) {\n kinemage.pdbfile = parseStr(line)\n } else if (line.startsWith('@group')) {\n let { groupName, groupFlags, groupMasters } = parseGroup(line)\n if (!kinemage.groupDict[ groupName as string ]) {\n kinemage.groupDict[ groupName as string ] = {\n dominant: false,\n animate: false\n }\n currentGroupMasters = groupMasters\n }\n\n if (currentGroupMasters) {\n currentGroupMasters.forEach(function (master) {\n if (!kinemage.masterDict[ master ]) {\n kinemage.masterDict[ master ] = {\n indent: false,\n visible: false\n }\n }\n })\n }\n\n for (let key in groupFlags as {[k: string]: boolean}) {\n kinemage.groupDict[ groupName as string ][ key ] = (groupFlags as {[k: string]: boolean})[ key ]\n }\n } else if (line.startsWith('@subgroup')) {\n const { groupName, groupFlags, groupMasters } = parseGroup(line)\n\n if (!kinemage.subgroupDict[ groupName as string ]) {\n kinemage.subgroupDict[ groupName as string ] = {\n dominant: false,\n animate: false\n }\n currentSubgroupMasters = groupMasters\n }\n\n if (currentSubgroupMasters) {\n currentSubgroupMasters.forEach(function (master) {\n if (!kinemage.masterDict[ master ]) {\n kinemage.masterDict[ master ] = {\n indent: false,\n visible: false\n }\n }\n })\n }\n\n for (let key in groupFlags as {[k: string]: boolean}) {\n kinemage.subgroupDict[ groupName as string ][ key ] = (groupFlags as {[k: string]: boolean})[ key ]\n }\n } else if (line.startsWith('@master')) {\n const name = parseStr(line)\n const flag = parseFlag(line)\n\n if (!kinemage.masterDict[ name ]) {\n kinemage.masterDict[ name ] = {\n indent: false,\n visible: false\n }\n }\n\n if (flag === 'on') {\n kinemage.masterDict[ name ].visible = true\n } else if (flag === 'off') {\n kinemage.masterDict[ name ].visible = false\n } else if (flag === 'indent') {\n kinemage.masterDict[ name ].indent = true\n } else if (!flag) {\n // nothing to do\n }\n } else if (line.startsWith('@pointmaster')) {\n const { groupName, groupFlags } = parseGroup(line)\n\n kinemage.pointmasterDict[ groupName as string] = {\n id: Object.keys(groupFlags as {[k: string]: boolean})[ 0 ].replace(reTrimQuotes, '')\n }\n } else {\n console.log(line)\n }\n }\n }\n\n this.streamer.eachChunkOfLines(function (lines/*, chunkNo, chunkCount */) {\n _parseChunkOfLines(0, lines.length, lines)\n })\n\n kinemage.text = kinemage.texts.join('\\n').trim()\n kinemage.caption = kinemage.captions.join('\\n').trim()\n if (kinemage.ribbonLists) {\n let convertedLists: RibbonObject[] = []\n kinemage.ribbonLists.forEach(function (listObject) {\n convertedLists.push(removePointBreaksTriangleArrays(convertKinTriangleArrays(listObject)))\n })\n kinemage.ribbonLists = convertedLists\n }\n\n if (Debug) Log.timeEnd(`KinParser._parse ${this.name}`)\n }\n}\n\nParserRegistry.add('kin', KinParser)\n\nexport default KinParser\n","/**\n * @file Surface Parser\n * @author Alexander Rose \n * @private\n */\n\nimport Parser, { ParserParameters } from './parser'\nimport Surface from '../surface/surface'\nimport Streamer from '../streamer/streamer';\n\nclass SurfaceParser extends Parser {\n constructor (streamer: Streamer, params?:Partial) {\n super(streamer, params)\n\n this.loader = this.getLoader()\n this.surface = new Surface(this.name, this.path)\n }\n\n get type () { return 'surface' }\n get __objName () { return 'surface' }\n\n _parse () {\n var geometry = this.loader.parse(this.streamer.asText())\n\n this.surface.fromGeometry(geometry)\n }\n}\n\nexport default SurfaceParser\n","/**\n * @file Obj Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { BufferGeometry, BufferAttribute } from 'three'\n\nimport { ParserRegistry } from '../globals'\nimport SurfaceParser from './surface-parser'\n\nexport interface _OBJLoader {\n regexp: {[k: string]: RegExp}\n}\n\ninterface _OBJLoaderConstructor {\n (this: _OBJLoader): void\n new(): _OBJLoader\n}\n\ninterface ObjectType {\n name: string,\n fromDeclaration: boolean,\n geometry: {\n vertices: number[],\n normals: number[],\n type?: string\n }\n}\n/**\n * OBJLoader\n * @class\n * @private\n * @author mrdoob / http://mrdoob.com/\n */\nconst OBJLoader = (function OBJLoader (this: _OBJLoader) {\n this.regexp = {\n // v float float float\n vertex_pattern: /^v\\s+([\\d.+\\-eE]+)\\s+([\\d.+\\-eE]+)\\s+([\\d.+\\-eE]+)/,\n // vn float float float\n normal_pattern: /^vn\\s+([\\d.+\\-eE]+)\\s+([\\d.+\\-eE]+)\\s+([\\d.+\\-eE]+)/,\n // vt float float\n uv_pattern: /^vt\\s+([\\d.+\\-eE]+)\\s+([\\d.+\\-eE]+)/,\n // f vertex vertex vertex\n face_vertex: /^f\\s+(-?\\d+)\\s+(-?\\d+)\\s+(-?\\d+)(?:\\s+(-?\\d+))?/,\n // f vertex/uv vertex/uv vertex/uv\n face_vertex_uv: /^f\\s+(-?\\d+)\\/(-?\\d+)\\s+(-?\\d+)\\/(-?\\d+)\\s+(-?\\d+)\\/(-?\\d+)(?:\\s+(-?\\d+)\\/(-?\\d+))?/,\n // f vertex/uv/normal vertex/uv/normal vertex/uv/normal\n face_vertex_uv_normal: /^f\\s+(-?\\d+)\\/(-?\\d+)\\/(-?\\d+)\\s+(-?\\d+)\\/(-?\\d+)\\/(-?\\d+)\\s+(-?\\d+)\\/(-?\\d+)\\/(-?\\d+)(?:\\s+(-?\\d+)\\/(-?\\d+)\\/(-?\\d+))?/,\n // f vertex//normal vertex//normal vertex//normal\n face_vertex_normal: /^f\\s+(-?\\d+)\\/\\/(-?\\d+)\\s+(-?\\d+)\\/\\/(-?\\d+)\\s+(-?\\d+)\\/\\/(-?\\d+)(?:\\s+(-?\\d+)\\/\\/(-?\\d+))?/,\n // o object_name | g group_name\n object_pattern: /^[og]\\s*(.+)?/,\n // s boolean\n smoothing_pattern: /^s\\s+(\\d+|on|off)/,\n // mtllib file_reference\n material_library_pattern: /^mtllib /,\n // usemtl material_name\n material_use_pattern: /^usemtl /\n }\n}) as _OBJLoaderConstructor\n\nOBJLoader.prototype = {\n\n constructor: OBJLoader,\n\n setPath: function (value: string) {\n this.path = value\n },\n\n _createParserState: function () {\n var state = {\n objects: [] as ObjectType[],\n object: {} as ObjectType,\n\n vertices: [],\n normals: [],\n\n startObject: function (name: string, fromDeclaration: boolean) {\n // If the current object (initial from reset) is not from a g/o declaration in the parsed\n // file. We need to use it for the first parsed g/o to keep things in sync.\n if (this.object && this.object.fromDeclaration === false) {\n this.object.name = name\n this.object.fromDeclaration = (fromDeclaration !== false)\n return\n }\n\n this.object = {\n name: name || '',\n geometry: {\n vertices: [],\n normals: []\n },\n fromDeclaration: (fromDeclaration !== false)\n }\n\n this.objects.push(this.object)\n },\n\n parseVertexIndex: function (value: string, len: number) {\n var index = parseInt(value, 10)\n return (index >= 0 ? index - 1 : index + len / 3) * 3\n },\n\n parseNormalIndex: function (value: string, len: number) {\n var index = parseInt(value, 10)\n return (index >= 0 ? index - 1 : index + len / 3) * 3\n },\n\n addVertex: function (a: number, b: number, c: number) {\n var src = this.vertices\n var dst = this.object.geometry.vertices\n\n dst.push(src[ a + 0 ])\n dst.push(src[ a + 1 ])\n dst.push(src[ a + 2 ])\n dst.push(src[ b + 0 ])\n dst.push(src[ b + 1 ])\n dst.push(src[ b + 2 ])\n dst.push(src[ c + 0 ])\n dst.push(src[ c + 1 ])\n dst.push(src[ c + 2 ])\n },\n\n addVertexLine: function (a: number) {\n var src = this.vertices\n var dst = this.object.geometry.vertices\n\n dst.push(src[ a + 0 ])\n dst.push(src[ a + 1 ])\n dst.push(src[ a + 2 ])\n },\n\n addNormal: function (a: number, b: number, c: number) {\n var src = this.normals\n var dst = this.object.geometry.normals\n\n dst.push(src[ a + 0 ])\n dst.push(src[ a + 1 ])\n dst.push(src[ a + 2 ])\n dst.push(src[ b + 0 ])\n dst.push(src[ b + 1 ])\n dst.push(src[ b + 2 ])\n dst.push(src[ c + 0 ])\n dst.push(src[ c + 1 ])\n dst.push(src[ c + 2 ])\n },\n\n addFace: function (a: string, b: string, c: string, d?: string, na?: string, nb?: string, nc?: string, nd?: string) {\n var vLen = this.vertices.length\n\n var ia = this.parseVertexIndex(a, vLen)\n var ib = this.parseVertexIndex(b, vLen)\n var ic = this.parseVertexIndex(c, vLen)\n var id\n\n if (d === undefined) {\n this.addVertex(ia, ib, ic)\n } else {\n id = this.parseVertexIndex(d, vLen)\n\n this.addVertex(ia, ib, id)\n this.addVertex(ib, ic, id)\n }\n\n if (na !== undefined) {\n // Normals are many times the same. If so, skip function call and parseInt.\n var nLen = this.normals.length\n ia = this.parseNormalIndex(na, nLen)\n\n ib = na === nb ? ia : this.parseNormalIndex(nb!, nLen)\n ic = na === nc ? ia : this.parseNormalIndex(nc!, nLen)\n\n if (d === undefined) {\n this.addNormal(ia, ib, ic)\n } else {\n id = this.parseNormalIndex(nd!, nLen)\n\n this.addNormal(ia, ib, id)\n this.addNormal(ib, ic, id)\n }\n }\n },\n\n addLineGeometry: function (vertices: string[]) {\n this.object.geometry.type = 'Line'\n\n var vLen = this.vertices.length\n\n for (var vi = 0, l = vertices.length; vi < l; vi++) {\n this.addVertexLine(this.parseVertexIndex(vertices[ vi ], vLen))\n }\n }\n\n }\n\n state.startObject('', false)\n\n return state\n },\n\n parse: function (text: string) {\n var state = this._createParserState()\n\n if (text.indexOf('\\r\\n') !== -1) {\n // This is faster than String.split with regex that splits on both\n text = text.replace(/\\r\\n/g, '\\n')\n }\n\n if (text.indexOf('\\\\\\n') !== -1) {\n // join lines separated by a line continuation character (\\)\n text = text.replace(/\\\\\\n/g, '')\n }\n\n var i, l\n var lines = text.split('\\n')\n var line = ''\n var lineFirstChar = ''\n var lineSecondChar = ''\n var lineLength = 0\n var result = []\n\n // Faster to just trim left side of the line. Use if available.\n var trimLeft = (typeof ''.trimLeft === 'function')\n\n for (i = 0, l = lines.length; i < l; i++) {\n line = lines[ i ]\n\n line = trimLeft ? line.trimLeft() : line.trim()\n\n lineLength = line.length\n\n if (lineLength === 0) continue\n\n lineFirstChar = line.charAt(0)\n\n // @todo invoke passed in handler if any\n if (lineFirstChar === '#') continue\n\n if (lineFirstChar === 'v') {\n lineSecondChar = line.charAt(1)\n\n if (lineSecondChar === ' ' && (result = this.regexp.vertex_pattern.exec(line)) !== null) {\n // 0 1 2 3\n // [\"v 1.0 2.0 3.0\", \"1.0\", \"2.0\", \"3.0\"]\n\n state.vertices.push(\n parseFloat(result[ 1 ]),\n parseFloat(result[ 2 ]),\n parseFloat(result[ 3 ])\n )\n } else if (lineSecondChar === 'n' && (result = this.regexp.normal_pattern.exec(line)) !== null) {\n // 0 1 2 3\n // [\"vn 1.0 2.0 3.0\", \"1.0\", \"2.0\", \"3.0\"]\n\n state.normals.push(\n parseFloat(result[ 1 ]),\n parseFloat(result[ 2 ]),\n parseFloat(result[ 3 ])\n )\n } else if (lineSecondChar === 't' && this.regexp.uv_pattern.exec(line) !== null) {\n\n // ignore uv line\n\n } else {\n throw new Error(\"Unexpected vertex/normal/uv line: '\" + line + \"'\")\n }\n } else if (lineFirstChar === 'f') {\n if ((result = this.regexp.face_vertex_uv_normal.exec(line)) !== null) {\n // f vertex/uv/normal vertex/uv/normal vertex/uv/normal\n // 0 1 2 3 4 5 6 7 8 9 10 11 12\n // [\"f 1/1/1 2/2/2 3/3/3\", \"1\", \"1\", \"1\", \"2\", \"2\", \"2\", \"3\", \"3\", \"3\", undefined, undefined, undefined]\n\n state.addFace(\n result[ 1 ], result[ 4 ], result[ 7 ], result[ 10 ],\n // result[ 2 ], result[ 5 ], result[ 8 ], result[ 11 ], // ignore uv part\n result[ 3 ], result[ 6 ], result[ 9 ], result[ 12 ]\n )\n } else if (this.regexp.face_vertex_uv.exec(line) !== null) {\n\n // ignore uv line\n\n } else if ((result = this.regexp.face_vertex_normal.exec(line)) !== null) {\n // f vertex//normal vertex//normal vertex//normal\n // 0 1 2 3 4 5 6 7 8\n // [\"f 1//1 2//2 3//3\", \"1\", \"1\", \"2\", \"2\", \"3\", \"3\", undefined, undefined]\n\n state.addFace(\n result[ 1 ], result[ 3 ], result[ 5 ], result[ 7 ],\n result[ 2 ], result[ 4 ], result[ 6 ], result[ 8 ]\n )\n } else if ((result = this.regexp.face_vertex.exec(line)) !== null) {\n // f vertex vertex vertex\n // 0 1 2 3 4\n // [\"f 1 2 3\", \"1\", \"2\", \"3\", undefined]\n\n state.addFace(\n result[ 1 ], result[ 2 ], result[ 3 ], result[ 4 ]\n )\n } else {\n throw new Error(\"Unexpected face line: '\" + line + \"'\")\n }\n } else if (lineFirstChar === 'l') {\n var lineParts = line.substring(1).trim().split(' ')\n var lineVertices = []\n var lineUVs = []\n\n if (line.indexOf('/') === -1) {\n lineVertices = lineParts\n } else {\n for (var li = 0, llen = lineParts.length; li < llen; li++) {\n var parts = lineParts[ li ].split('/')\n\n if (parts[ 0 ] !== '') lineVertices.push(parts[ 0 ])\n if (parts[ 1 ] !== '') lineUVs.push(parts[ 1 ])\n }\n }\n state.addLineGeometry(lineVertices, lineUVs)\n } else if ((result = this.regexp.object_pattern.exec(line)) !== null) {\n // o object_name\n // or\n // g group_name\n\n var name = result[ 0 ].substr(1).trim()\n state.startObject(name)\n\n // ignore material related lines\n // eslint-disable-next-line no-empty\n } else if (this.regexp.material_use_pattern.test(line)) {\n // eslint-disable-next-line no-empty\n } else if (this.regexp.material_library_pattern.test(line)) {\n // eslint-disable-next-line no-empty\n } else if (this.regexp.smoothing_pattern.exec(line) !== null) {\n } else {\n // Handle null terminated files without exception\n if (line === '\\0') continue\n\n throw new Error(\"Unexpected line: '\" + line + \"'\")\n }\n }\n\n var container = []\n\n for (i = 0, l = state.objects.length; i < l; i++) {\n var object = state.objects[ i ]\n var geometry = object.geometry\n\n // Skip o/g line declarations that did not follow with any faces\n if (geometry.vertices.length === 0) continue\n\n var buffergeometry = new BufferGeometry()\n\n buffergeometry.setAttribute('position', new BufferAttribute(new Float32Array(geometry.vertices), 3))\n\n if (geometry.normals.length > 0) {\n buffergeometry.setAttribute('normal', new BufferAttribute(new Float32Array(geometry.normals), 3))\n } else {\n buffergeometry.computeVertexNormals()\n }\n\n container.push(buffergeometry)\n }\n\n return container\n }\n\n}\n\nclass ObjParser extends SurfaceParser {\n get type () { return 'obj' }\n\n getLoader () {\n return new OBJLoader()\n }\n}\n\nParserRegistry.add('obj', ObjParser)\n\nexport default ObjParser\n","/**\n * @file Ply Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Geometry, Vector3, Face3, Color } from 'three'\n\nimport { ParserRegistry } from '../globals'\nimport SurfaceParser from './surface-parser'\n\n/**\n * PLYLoader\n * @class\n * @private\n * @author Wei Meng / http://about.me/menway\n *\n * @description\n * A THREE loader for PLY ASCII files (known as the Polygon File Format or the Stanford Triangle Format).\n *\n * Limitations: ASCII decoding assumes file is UTF-8.\n *\n * @example\n * var loader = new THREE.PLYLoader();\n * loader.load('./models/ply/ascii/dolphins.ply', function (geometry) {\n * scene.add( new THREE.Mesh( geometry ) );\n * } );\n *\n * // If the PLY file uses non standard property names, they can be mapped while\n * // loading. For example, the following maps the properties\n * // “diffuse_(red|green|blue)” in the file to standard color names.\n *\n * loader.setPropertyNameMapping( {\n * diffuse_red: 'red',\n * diffuse_green: 'green',\n * diffuse_blue: 'blue'\n * } );\n *\n */\n\nexport interface _PLYLoader {\n propertyNameMapping: {[k: string]: string}\n}\n\ninterface _PLYLoaderConstructor {\n (this: _PLYLoader): void\n new(): _PLYLoader\n}\n\ninterface PLYProperty {\n type: string,\n name: string,\n countType: string,\n itemType: string\n}\n\ninterface PLYElement {\n name: string,\n count: number,\n properties: PLYProperty[],\n x: number,\n y: number,\n z: number,\n red: number,\n green: number,\n blue: number,\n [k:string]: any\n}\n\ninterface PLYHeader {\n format: string,\n version: string,\n comments: string[],\n elements: PLYElement[],\n headerLength: number\n}\n\ninterface GeometryPLY extends Geometry {\n useColor: boolean\n}\n\nconst PLYLoader = (function PLYLoader (this: _PLYLoader) {\n this.propertyNameMapping = {}\n}) as _PLYLoaderConstructor\n\nPLYLoader.prototype = {\n\n constructor: PLYLoader,\n\n setPropertyNameMapping: function (mapping: {[k: string]: string}) {\n this.propertyNameMapping = mapping\n },\n\n bin2str: function (buf: ArrayBuffer) {\n var arrayBuffer = new Uint8Array(buf)\n var str = ''\n for (var i = 0; i < buf.byteLength; i++) {\n str += String.fromCharCode(arrayBuffer[ i ]) // implicitly assumes little-endian\n }\n\n return str\n },\n\n isASCII: function (data: ArrayBuffer) {\n var header = this.parseHeader(this.bin2str(data))\n\n return header.format === 'ascii'\n },\n\n parse: function (data: string|ArrayBuffer) {\n if (data instanceof ArrayBuffer) {\n return (\n this.isASCII(data)\n ? this.parseASCII(this.bin2str(data))\n : this.parseBinary(data)\n )\n } else {\n return this.parseASCII(data)\n }\n },\n\n parseHeader: function (data: string) {\n var patternHeader = /ply([\\s\\S]*)end_header\\s/\n var headerText = ''\n var headerLength = 0\n var result = patternHeader.exec(data)\n if (result !== null) {\n headerText = result[ 1 ]\n headerLength = result[ 0 ].length\n }\n\n var header: Partial = {\n comments: [],\n elements: [],\n headerLength: headerLength\n }\n\n var lines = headerText.split('\\n')\n var currentElement: PLYElement|undefined, lineType, lineValues\n\n function makePlyElementProperty (propertValues: string[], propertyNameMapping: {[k: string]: string}) {\n var property = {\n type: propertValues[ 0 ]\n } as PLYProperty\n\n if (property.type === 'list') {\n property.name = propertValues[ 3 ]\n property.countType = propertValues[ 1 ]\n property.itemType = propertValues[ 2 ]\n } else {\n property.name = propertValues[ 1 ]\n }\n\n if (property.name in propertyNameMapping) {\n property.name = propertyNameMapping[ property.name ]\n }\n\n return property\n }\n\n for (var i = 0; i < lines.length; i++) {\n var line = lines[ i ]\n line = line.trim()\n if (line === '') {\n continue\n }\n lineValues = line.split(/\\s+/)\n lineType = lineValues.shift()\n line = lineValues.join(' ')\n\n switch (lineType) {\n case 'format':\n\n header.format = lineValues[ 0 ]\n header.version = lineValues[ 1 ]\n\n break\n\n case 'comment':\n\n header.comments!.push(line)\n\n break\n\n case 'element':\n\n if (currentElement !== undefined) {\n header.elements!.push(currentElement as PLYElement)\n }\n\n currentElement = {} as PLYElement\n currentElement.name = lineValues[ 0 ]\n currentElement.count = parseInt(lineValues[ 1 ])\n currentElement.properties = []\n\n break\n\n case 'property':\n\n currentElement!.properties.push(makePlyElementProperty(lineValues, this.propertyNameMapping))\n\n break\n\n default:\n\n console.log('unhandled', lineType, lineValues)\n }\n }\n\n if (currentElement !== undefined) {\n header.elements!.push(currentElement)\n }\n\n return header\n },\n\n parseASCIINumber: function (n: string, type: string) {\n switch (type) {\n case 'char': case 'uchar': case 'short': case 'ushort': case 'int': case 'uint':\n case 'int8': case 'uint8': case 'int16': case 'uint16': case 'int32': case 'uint32':\n\n return parseInt(n)\n\n case 'float': case 'double': case 'float32': case 'float64':\n\n return parseFloat(n)\n }\n },\n\n parseASCIIElement: function (properties: PLYProperty[], line: string) {\n var values = line.split(/\\s+/)\n\n var element = {} as PLYElement\n\n for (var i = 0; i < properties.length; i++) {\n if (properties[ i ].type === 'list') {\n var list = []\n var n = this.parseASCIINumber(values.shift(), properties[ i ].countType)\n\n for (var j = 0; j < n; j++) {\n list.push(this.parseASCIINumber(values.shift(), properties[ i ].itemType))\n }\n\n element[ properties[ i ].name ] = list\n } else {\n element[ properties[ i ].name ] = this.parseASCIINumber(values.shift(), properties[ i ].type)\n }\n }\n\n return element\n },\n\n parseASCII: function (data: string) {\n // PLY ascii format specification, as per http://en.wikipedia.org/wiki/PLY_(file_format)\n\n var geometry = new Geometry() as GeometryPLY\n\n var result\n\n var header = this.parseHeader(data)\n\n var patternBody = /end_header\\s([\\s\\S]*)$/\n var body = ''\n if ((result = patternBody.exec(data)) !== null) {\n body = result[ 1 ]\n }\n\n var lines = body.split('\\n')\n var currentElement = 0\n var currentElementCount = 0\n geometry.useColor = false\n\n for (var i = 0; i < lines.length; i++) {\n var line = lines[ i ]\n line = line.trim()\n if (line === '') {\n continue\n }\n\n if (currentElementCount >= header.elements[ currentElement ].count) {\n currentElement++\n currentElementCount = 0\n }\n\n var element = this.parseASCIIElement(header.elements[ currentElement ].properties, line)\n\n this.handleElement(geometry, header.elements[ currentElement ].name, element)\n\n currentElementCount++\n }\n\n return this.postProcess(geometry)\n },\n\n postProcess: function (geometry: GeometryPLY) {\n if (geometry.useColor) {\n for (var i = 0; i < geometry.faces.length; i++) {\n geometry.faces[ i ].vertexColors = [\n geometry.colors[ geometry.faces[ i ].a ],\n geometry.colors[ geometry.faces[ i ].b ],\n geometry.colors[ geometry.faces[ i ].c ]\n ]\n }\n\n geometry.elementsNeedUpdate = true\n }\n\n geometry.computeBoundingSphere()\n\n return geometry\n },\n\n handleElement: function (geometry: GeometryPLY, elementName: string, element: PLYElement) {\n if (elementName === 'vertex') {\n geometry.vertices.push(\n new Vector3(element.x, element.y, element.z)\n )\n\n if ('red' in element && 'green' in element && 'blue' in element) {\n geometry.useColor = true\n\n var color = new Color()\n color.setRGB(element.red / 255.0, element.green / 255.0, element.blue / 255.0)\n geometry.colors.push(color)\n }\n } else if (elementName === 'face') {\n var vertexIndices = element.vertex_indices\n\n if (vertexIndices.length === 3) {\n geometry.faces.push(\n new Face3(vertexIndices[ 0 ], vertexIndices[ 1 ], vertexIndices[ 2 ])\n )\n } else if (vertexIndices.length === 4) {\n geometry.faces.push(\n new Face3(vertexIndices[ 0 ], vertexIndices[ 1 ], vertexIndices[ 3 ]),\n new Face3(vertexIndices[ 1 ], vertexIndices[ 2 ], vertexIndices[ 3 ])\n )\n }\n }\n },\n\n binaryRead: function (dataview: DataView, at: number, type: string, littleEndian: boolean) {\n switch (type) {\n // corespondences for non-specific length types here match rply:\n case 'int8': case 'char': return [ dataview.getInt8(at), 1 ]\n\n case 'uint8': case 'uchar': return [ dataview.getUint8(at), 1 ]\n\n case 'int16': case 'short': return [ dataview.getInt16(at, littleEndian), 2 ]\n\n case 'uint16': case 'ushort': return [ dataview.getUint16(at, littleEndian), 2 ]\n\n case 'int32': case 'int': return [ dataview.getInt32(at, littleEndian), 4 ]\n\n case 'uint32': case 'uint': return [ dataview.getUint32(at, littleEndian), 4 ]\n\n case 'float32': case 'float': return [ dataview.getFloat32(at, littleEndian), 4 ]\n\n case 'float64': case 'double': return [ dataview.getFloat64(at, littleEndian), 8 ]\n }\n },\n\n binaryReadElement: function (dataview: DataView, at: number, properties: PLYProperty[], littleEndian: boolean) {\n var element = {} as PLYElement\n var result\n var read = 0\n\n for (var i = 0; i < properties.length; i++) {\n if (properties[ i ].type === 'list') {\n var list = []\n\n result = this.binaryRead(dataview, at + read, properties[ i ].countType, littleEndian)\n var n = result[ 0 ]\n read += result[ 1 ]\n\n for (var j = 0; j < n; j++) {\n result = this.binaryRead(dataview, at + read, properties[ i ].itemType, littleEndian)\n list.push(result[ 0 ])\n read += result[ 1 ]\n }\n\n element[ properties[ i ].name ] = list\n } else {\n result = this.binaryRead(dataview, at + read, properties[ i ].type, littleEndian)\n element[ properties[ i ].name ] = result[ 0 ]\n read += result[ 1 ]\n }\n }\n\n return [ element, read ]\n },\n\n parseBinary: function (data: ArrayBuffer) {\n var geometry = new Geometry()\n\n var header = this.parseHeader(this.bin2str(data))\n var littleEndian = (header.format === 'binary_little_endian')\n var body = new DataView(data, header.headerLength)\n var result\n var loc = 0\n\n for (var currentElement = 0; currentElement < header.elements.length; currentElement++) {\n for (var currentElementCount = 0; currentElementCount < header.elements[ currentElement ].count; currentElementCount++) {\n result = this.binaryReadElement(body, loc, header.elements[ currentElement ].properties, littleEndian)\n loc += result[ 1 ]\n var element = result[ 0 ]\n\n this.handleElement(geometry, header.elements[ currentElement ].name, element)\n }\n }\n\n return this.postProcess(geometry)\n }\n\n}\n\nclass PlyParser extends SurfaceParser {\n get type () { return 'ply' }\n\n getLoader () {\n return new PLYLoader()\n }\n}\n\nParserRegistry.add('ply', PlyParser)\n\nexport default PlyParser\n","/**\n * @file Csv Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport { ParserRegistry } from '../globals'\nimport Parser, { ParserParameters } from './parser'\nimport Streamer from '../streamer/streamer';\n\nexport interface CsvParserParameters extends ParserParameters {\n delimiter: string\n comment: string\n columnNames: boolean\n}\n/**\n * CSV parser\n */\nclass CsvParser extends Parser {\n /**\n * [constructor description]\n * @param {Streamer} streamer - the streamer object\n * @param {Object} params - parameter object\n * @param {Char} params.delimiter - delimiter character\n * @param {Char} params.comment - comment character\n * @param {Boolean} params.columnNames - use first data line as column names\n */\n constructor (streamer: Streamer, params?: Partial) {\n const p = params || {}\n\n super(streamer, p)\n\n this.delimiter = defaults(p.delimiter, ',')\n this.comment = defaults(p.comment, '#')\n this.columnNames = defaults(p.columnNames, false)\n\n this.table = {\n name: this.name,\n path: this.path,\n columnNames: [],\n data: []\n }\n }\n\n get type () { return 'csv' }\n get __objName () { return 'table' }\n\n _parse () {\n const data = this.table.data\n const reDelimiter = new RegExp('\\\\s*' + this.delimiter + '\\\\s*')\n\n let j = 0\n\n this.streamer.eachChunkOfLines(chunk => {\n const n = chunk.length\n\n for (let i = 0; i < n; ++i) {\n const line = chunk[ i ].trim()\n if (line.startsWith(this.comment)) continue\n const values = line.split(reDelimiter)\n\n if (j === 0) {\n this.table.columnNames = values\n } else if (line) {\n data.push(values)\n }\n ++j\n }\n })\n }\n}\n\nParserRegistry.add('csv', CsvParser)\n\nexport default CsvParser\n","/**\n * @file Json Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { ParserRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport Parser, { ParserParameters } from './parser'\nimport Streamer from '../streamer/streamer';\n\nexport interface JsonParserParameters extends ParserParameters {\n string: boolean\n}\n\nclass JsonParser extends Parser {\n constructor (streamer: Streamer, params?: Partial) {\n const p = params || {}\n\n super(streamer, p)\n\n this.string = defaults(p.string, false)\n\n this.json = {\n name: this.name,\n path: this.path,\n data: {}\n }\n }\n\n get type () { return 'json' }\n get __objName () { return 'json' }\n get isJson () { return true }\n\n _parse () {\n if (this.streamer.isBinary() || this.string) {\n this.json.data = JSON.parse(this.streamer.asText())\n } else {\n this.json.data = this.streamer.data\n }\n }\n}\n\nParserRegistry.add('json', JsonParser)\n\nexport default JsonParser\n","/**\n * @file Msgpack Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport Parser, { ParserParameters } from './parser'\n\nimport { decodeMsgpack } from '../../lib/mmtf.es6'\nimport Streamer from '../streamer/streamer';\n\nclass MsgpackParser extends Parser {\n constructor (streamer: Streamer, params?: Partial) {\n const p = params || {}\n\n super(streamer, p)\n\n this.msgpack = {\n name: this.name,\n path: this.path,\n data: undefined\n }\n }\n\n get type () { return 'msgpack' }\n get __objName () { return 'msgpack' }\n get isBinary () { return true }\n\n _parse () {\n if (Debug) Log.time('MsgpackParser._parse ' + this.name)\n\n this.msgpack.data = decodeMsgpack(this.streamer.data)\n\n if (Debug) Log.timeEnd('MsgpackParser._parse ' + this.name)\n }\n}\n\nParserRegistry.add('msgpack', MsgpackParser)\n\nexport default MsgpackParser\n","/**\n * @file Netcdf Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport Parser, { ParserParameters } from './parser'\nimport NetcdfReader from '../utils/netcdf-reader'\nimport Streamer from '../streamer/streamer';\n\nclass NetcdfParser extends Parser {\n constructor (streamer: Streamer, params?: Partial) {\n const p = params || {}\n\n super(streamer, p)\n\n this.netcdf = {\n name: this.name,\n path: this.path,\n data: undefined\n }\n }\n\n get type () { return 'netcdf' }\n get __objName () { return 'netcdf' }\n get isBinary () { return true }\n\n _parse () {\n if (Debug) Log.time('NetcdfParser._parse ' + this.name)\n\n this.netcdf.data = new NetcdfReader(this.streamer.data)\n\n if (Debug) Log.timeEnd('NetcdfParser._parse ' + this.name)\n }\n}\n\nParserRegistry.add('netcdf', NetcdfParser)\n\nexport default NetcdfParser\n","/**\n * @file Text Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { ParserRegistry } from '../globals'\nimport Parser, { ParserParameters } from './parser'\nimport Streamer from '../streamer/streamer';\n\nclass TextParser extends Parser {\n constructor (streamer: Streamer, params?: Partial) {\n super(streamer, params)\n\n this.text = {\n\n name: this.name,\n path: this.path,\n data: ''\n\n }\n }\n\n get type () { return 'text' }\n get __objName () { return 'text' }\n\n _parse () {\n this.text.data = this.streamer.asText()\n }\n}\n\nParserRegistry.add('txt', TextParser)\nParserRegistry.add('text', TextParser)\n\nexport default TextParser\n","/**\n * @file Parse Xml\n * @author Alexander Rose \n * @private\n */\n\n// https://github.com/segmentio/xml-parser\n// MIT license\n\nexport type XMLNodeAttributes = { [k: string]: any }\nexport interface XMLNode {\n name?: string\n content?: string\n attributes: XMLNodeAttributes\n children?: XMLNode[]\n}\n\nconst reStrip = /^['\"]|['\"]$/g\nconst reTag = /^<([\\w-:.]+)\\s*/\nconst reContent = /^([^<]*)/\nconst reAttr = /([\\w:-]+)\\s*=\\s*(\"[^\"]*\"|'[^']*'|\\w+)\\s*/\n\nfunction strip (val: string) {\n return val.replace(reStrip, '')\n}\n\nexport function parseXml (xml: string) {\n // trim and strip comments\n xml = xml.trim().replace(//g, '')\n\n return document()\n\n function document () {\n return {\n declaration: declaration(),\n root: tag()\n }\n }\n\n function declaration () {\n const m = match(/^<\\?xml\\s*/)\n if (!m) return\n\n // tag\n const node: XMLNode = {\n attributes: {}\n }\n\n // attributes\n while (!(eos() || is('?>'))) {\n const attr = attribute()\n if (!attr) return node\n node.attributes[attr.name] = attr.value\n }\n match(/\\?>\\s*/)\n return node\n }\n\n function tag () {\n const m = match(reTag)\n if (!m) return\n\n // name\n const node: XMLNode = {\n name: m[1],\n attributes: {},\n children: []\n }\n\n // attributes\n while (!(eos() || is('>') || is('?>') || is('/>'))) {\n const attr = attribute()\n if (!attr) return node\n node.attributes[attr.name] = attr.value\n }\n\n // self closing tag\n if (match(/^\\s*\\/>\\s*/)) {\n return node\n }\n match(/\\??>\\s*/)\n\n // content\n node.content = content()\n\n // children\n let child\n while ((child = tag())) {\n node.children!.push(child)\n }\n\n // closing\n match(/^<\\/[\\w-:.]+>\\s*/)\n return node\n }\n\n function content () {\n const m = match(reContent)\n if (m) return m[1]\n return ''\n }\n\n function attribute () {\n const m = match(reAttr)\n if (!m) return\n return { name: m[1], value: strip(m[2]) }\n }\n\n function match (re: RegExp) {\n const m = xml.match(re)\n if (!m) return\n xml = xml.slice(m[0].length)\n return m\n }\n\n function eos () {\n return xml.length === 0\n }\n\n function is (prefix: string) {\n return xml.indexOf(prefix) === 0\n }\n}\n","/**\n * @file Xml Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport { defaults } from '../utils'\n// @ts-ignore: unused import XMLNode required for declaration only\nimport { parseXml, XMLNode } from '../utils/parse-xml'\nimport Parser, { ParserParameters } from './parser'\nimport Streamer from '../streamer/streamer';\n\nexport interface XmlParserParameters extends ParserParameters {\n useDomParser: boolean\n}\n\nclass XmlParser extends Parser {\n xml: {\n name: string\n path: string\n data: any\n }\n constructor (streamer: Streamer, params?: Partial) {\n const p = params || {}\n\n super(streamer, p)\n\n this.useDomParser = defaults(p.useDomParser, false)\n\n this.xml = {\n name: this.name,\n path: this.path,\n data: {}\n }\n }\n\n get type () { return 'xml' }\n get __objName () { return 'xml' }\n get isXml () { return true }\n\n __xmlParser (xml: string) {\n return parseXml(xml)\n }\n\n __domParser (xml: string) {\n const domParser = new (window as any).DOMParser() as DOMParser\n return domParser.parseFromString(xml, 'text/xml')\n }\n\n _parse () {\n if (Debug) Log.time('XmlParser._parse ' + this.name)\n\n if (this.useDomParser) {\n if (this.streamer.data instanceof Document) { //TS conversion: stripped the window prefix from window.Document\n this.xml.data = this.streamer.data\n } else {\n this.xml.data = this.__domParser(this.streamer.asText())\n }\n } else {\n this.xml.data = this.__xmlParser(this.streamer.asText())\n }\n\n if (Debug) Log.timeEnd('XmlParser._parse ' + this.name)\n }\n}\n\nParserRegistry.add('xml', XmlParser)\n\nexport default XmlParser\n","/**\n * @file Validation\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Color } from 'three'\n\nimport { Debug, Log } from '../globals'\nimport { defaults } from '../utils'\nimport { ClashPicker } from '../utils/picker'\nimport { uniformArray3 } from '../math/array-utils'\nimport { guessElement } from '../structure/structure-utils'\nimport AtomProxy from '../proxy/atom-proxy'\nimport Structure from '../structure/structure'\n\nfunction getNamedItem(a: NamedNodeMap, name: string) {\n const item = a.getNamedItem(name)\n return item !== null ? item.value : ''\n}\n\nfunction getSele (a: NamedNodeMap, atomname?: string, useAltcode = false) {\n const icode = getNamedItem(a, 'icode').trim()\n const chain = getNamedItem(a, 'chain').trim()\n const altcode = getNamedItem(a, 'altcode')\n let sele = getNamedItem(a, 'resnum')\n if (icode) sele += '^' + icode\n if (chain) sele += ':' + chain\n if (atomname) sele += '.' + atomname\n if (useAltcode && altcode.trim()) sele += '%' + altcode\n sele += '/' + (parseInt(getNamedItem(a, 'model')) - 1)\n return sele\n}\n\nfunction getResSele (a: NamedNodeMap) {\n const chain = getNamedItem(a, 'chain').trim()\n const rescode = getNamedItem(a, 'rescode')\n const resnum = getNamedItem(a, 'resnum')\n let sele = `[${rescode}]${resnum}`\n if (chain) sele += `:${chain}`\n return sele\n}\n\nfunction setBitDict (dict: { [k: string]: number }, key: string, bit: number) {\n if (dict[ key ] === undefined) {\n dict[ key ] = bit\n } else {\n dict[ key ] |= bit\n }\n}\n\nfunction hasAttrValue (attr: Attr|null, value: string) {\n return attr !== null && attr.value === value\n}\n\nfunction getAtomSele (ap: AtomProxy) {\n const icode = ap.inscode\n const chain = ap.chainname\n const atomname = ap.atomname\n const altcode = ap.altloc\n let sele = ap.resno + ''\n if (icode) sele += '^' + icode\n if (chain) sele += ':' + chain\n if (atomname) sele += '.' + atomname\n if (altcode) sele += '%' + altcode\n sele += '/' + ap.modelIndex\n return sele\n}\n\nfunction getProblemCount (clashDict: { [k: string]: { [k: string]: string } }, g: Element, ga: NamedNodeMap) {\n let geoProblemCount = 0\n\n const clashes = g.getElementsByTagName('clash')\n for (let j = 0, jl = clashes.length; j < jl; ++j) {\n if (clashDict[ getNamedItem(clashes[ j ].attributes, 'cid') ]) {\n geoProblemCount += 1\n break\n }\n }\n\n const angleOutliers = g.getElementsByTagName('angle-outlier')\n if (angleOutliers.length > 0) {\n geoProblemCount += 1\n }\n\n const bondOutliers = g.getElementsByTagName('bond-outlier')\n if (bondOutliers.length > 0) {\n geoProblemCount += 1\n }\n\n const planeOutliers = g.getElementsByTagName('plane-outlier')\n if (planeOutliers.length > 0) {\n geoProblemCount += 1\n }\n\n if (hasAttrValue(ga.getNamedItem('rota'), 'OUTLIER')) {\n geoProblemCount += 1\n }\n\n if (hasAttrValue(ga.getNamedItem('rama'), 'OUTLIER')) {\n geoProblemCount += 1\n }\n\n if (hasAttrValue(ga.getNamedItem('RNApucker'), 'outlier')) {\n geoProblemCount += 1\n }\n\n return geoProblemCount\n}\n\nclass Validation {\n rsrzDict: { [k: string]: number } = {}\n rsccDict: { [k: string]: number } = {}\n /**\n * Random Coil Index (RCI) - evaluates the proximity of residue structural\n * and dynamic properties to the properties of flexible random coil regions\n * from NMR chemical shifts.\n *\n * Mark V. Berjanskii and David S. Wishart (2005)\n * A Simple Method To Predict Protein Flexibility Using Secondary Chemical Shifts\n * J. Am. Chem. Soc., 2005, 127 (43), pp 14970–14971\n * http://pubs.acs.org/doi/abs/10.1021/ja054842f\n *\n * Mark V. Berjanskii and David S. Wishart (2008)\n * Application of the random coil index to studying protein flexibility.\n * J Biomol NMR. 2008 Jan;40(1):31-48. Epub 2007 Nov 6.\n * http://www.springerlink.com/content/2966482w10306126/\n */\n rciDict: { [k: string]: number } = {}\n clashDict: { [k: string]: { [k: string]: string } } = {}\n clashArray: { [k: string]: string }[] = []\n geoDict: { [k: string]: number } = {}\n geoAtomDict: { [k: string]: { [k: string]: number } } = {}\n atomDict: { [k: string]: boolean|number } = {}\n clashSele = 'NONE'\n\n constructor (readonly name: string, readonly path: string) {}\n\n get type () { return 'validation' }\n\n fromXml (xml: XMLDocument) {\n if (Debug) Log.time('Validation.fromXml')\n\n const rsrzDict = this.rsrzDict\n const rsccDict = this.rsccDict\n const rciDict = this.rciDict\n const clashDict = this.clashDict\n const clashArray = this.clashArray\n const geoDict = this.geoDict\n const geoAtomDict = this.geoAtomDict\n const atomDict = this.atomDict\n\n const entries = xml.getElementsByTagName('Entry')\n if (entries.length === 1) {\n const chemicalShiftLists = entries[0].getElementsByTagName('chemical_shift_list')\n if (chemicalShiftLists.length === 1) {\n const randomCoilIndices = chemicalShiftLists[0].getElementsByTagName('random_coil_index')\n for (let j = 0, jl = randomCoilIndices.length; j < jl; ++j) {\n const rcia = randomCoilIndices[ j ].attributes\n const sele = getResSele(rcia)\n rciDict[ sele ] = parseFloat(getNamedItem(rcia, 'value'))\n }\n }\n }\n\n const groups = xml.getElementsByTagName('ModelledSubgroup')\n\n const _clashDict: { [k: string]: { [k: string]: string } } = {}\n const clashList: string[] = []\n\n if (Debug) Log.time('Validation.fromXml#clashDict')\n\n for (let i = 0, il = groups.length; i < il; ++i) {\n const g = groups[ i ]\n const ga = g.attributes\n\n const sele = getSele(ga)\n if (ga.getNamedItem('rsrz') !== null) {\n rsrzDict[ sele ] = parseFloat(getNamedItem(ga, 'rsrz'))\n }\n if (ga.getNamedItem('rscc') !== null) {\n rsccDict[ sele ] = parseFloat(getNamedItem(ga, 'rscc'))\n }\n const seleAttr = xml.createAttribute('sele')\n seleAttr.value = sele\n ga.setNamedItem(seleAttr)\n\n const clashes = g.getElementsByTagName('clash')\n\n for (let j = 0, jl = clashes.length; j < jl; ++j) {\n const ca = clashes[ j ].attributes\n const atom = getNamedItem(ca, 'atom')\n\n if (guessElement(atom) !== 'H') {\n const cid = getNamedItem(ca, 'cid')\n const atomSele = getSele(ga, atom, true)\n atomDict[ atomSele ] = true\n\n if (_clashDict[ cid ] === undefined) {\n _clashDict[ cid ] = {\n sele1: atomSele,\n res1: sele\n }\n } else {\n const c = _clashDict[ cid ]\n if (c.res1 !== sele) {\n c.sele2 = atomSele\n c.res2 = sele\n clashList.push(c.res1, sele)\n clashDict[ cid ] = c\n clashArray.push(c)\n }\n }\n }\n }\n }\n\n if (Debug) Log.timeEnd('Validation.fromXml#clashDict')\n\n for (let i = 0, il = groups.length; i < il; ++i) {\n const g = groups[ i ]\n const ga = g.attributes\n\n const sele = getNamedItem(ga, 'sele')\n const isPolymer = getNamedItem(ga, 'seq') !== '.'\n\n if (isPolymer) {\n const geoProblemCount = getProblemCount(clashDict, g, ga)\n if (geoProblemCount > 0) {\n geoDict[ sele ] = geoProblemCount\n }\n } else {\n const clashes = g.getElementsByTagName('clash')\n const mogBondOutliers = g.getElementsByTagName('mog-bond-outlier')\n const mogAngleOutliers = g.getElementsByTagName('mog-angle-outlier')\n\n if (mogBondOutliers.length > 0 || mogAngleOutliers.length > 0 || clashes.length > 0) {\n const atomDict = {}\n geoAtomDict[ sele ] = atomDict\n\n for (let j = 0, jl = clashes.length; j < jl; ++j) {\n const ca = clashes[ j ].attributes\n if (clashDict[ getNamedItem(ca, 'cid') ]) {\n setBitDict(atomDict, getNamedItem(ca, 'atom'), 1)\n }\n }\n\n for (let j = 0, jl = mogBondOutliers.length; j < jl; ++j) {\n const mbo = mogBondOutliers[ j ].attributes\n getNamedItem(mbo, 'atoms').split(',').forEach(function (atomname) {\n setBitDict(atomDict, atomname, 2)\n })\n }\n\n for (let j = 0, jl = mogAngleOutliers.length; j < jl; ++j) {\n const mao = mogAngleOutliers[ j ].attributes\n getNamedItem(mao, 'atoms').split(',').forEach(function (atomname) {\n setBitDict(atomDict, atomname, 4)\n })\n }\n }\n }\n }\n\n this.clashSele = clashList.length ? clashList.join(' OR ') : 'NONE'\n\n if (Debug) Log.timeEnd('Validation.fromXml')\n }\n\n getClashData (params: { color: number|string|Color, structure: Structure }) {\n if (Debug) Log.time('Validation.getClashData')\n\n const p = params || {}\n\n const s = p.structure\n const atomSet = s.atomSet! // TODO\n const c = new Color(defaults(p.color, '#f0027f'))\n\n const ap1 = s.getAtomProxy()\n const ap2 = s.getAtomProxy()\n const vDir = new Vector3()\n const vPos1 = new Vector3()\n const vPos2 = new Vector3()\n\n const clashArray = this.clashArray\n const n = clashArray.length\n\n const position1 = new Float32Array(n * 3)\n const position2 = new Float32Array(n * 3)\n const color = uniformArray3(n, c.r, c.g, c.b) as Float32Array\n const radius = new Float32Array(n)\n const picking = new Float32Array(n)\n\n if (Debug) Log.time('Validation.getClashData#atomDict')\n\n const atomDict = this.atomDict\n\n s.eachAtom(function (ap) {\n const sele = getAtomSele(ap)\n if (atomDict[ sele ] === true) {\n atomDict[ sele ] = ap.index\n }\n })\n\n if (Debug) Log.timeEnd('Validation.getClashData#atomDict')\n\n let i = 0\n\n clashArray.forEach(function (c, idx) {\n ap1.index = atomDict[ c.sele1 ] as number // TODO\n ap2.index = atomDict[ c.sele2 ] as number // TODO\n\n if (ap1.index === undefined || ap2.index === undefined ||\n !atomSet.isSet(ap1.index, ap2.index)) return\n\n vDir.subVectors(ap2 as any, ap1 as any).setLength(ap1.vdw) // TODO\n vPos1.copy(ap1 as any).add(vDir) // TODO\n\n vDir.subVectors(ap1 as any, ap2 as any).setLength(ap2.vdw) // TODO\n vPos2.copy(ap2 as any).add(vDir) // TODO\n\n const dHalf = ap1.distanceTo(ap2) / 2\n const r1 = Math.sqrt(ap1.vdw * ap1.vdw - dHalf * dHalf)\n const r2 = Math.sqrt(ap2.vdw * ap2.vdw - dHalf * dHalf)\n\n vPos1.toArray(position1 as any, i * 3) // TODO\n vPos2.toArray(position2 as any, i * 3)\n radius[ i ] = (r1 + r2) / 2\n picking[ i ] = idx\n\n ++i\n })\n\n if (Debug) Log.timeEnd('Validation.getClashData')\n\n return {\n position1: position1.subarray(0, i * 3),\n position2: position2.subarray(0, i * 3),\n color: color.subarray(0, i * 3),\n color2: color.subarray(0, i * 3),\n radius: radius.subarray(0, i),\n picking: new ClashPicker(picking.subarray(0, i), this, s)\n }\n }\n}\n\nexport default Validation\n","\n// https://github.com/nodeca/pako\n// MIT License, Copyright (c) 2014 by Vitaly Puzrin\n\n\n// 'use strict';\n\n\n// var TYPED_OK = (typeof Uint8Array !== 'undefined') &&\n// (typeof Uint16Array !== 'undefined') &&\n// (typeof Int32Array !== 'undefined');\n\n\nfunction assign(obj /*from1, from2, from3, ...*/) {\n var sources = Array.prototype.slice.call(arguments, 1);\n while (sources.length) {\n var source = sources.shift();\n if (!source) { continue; }\n\n if (typeof source !== 'object') {\n throw new TypeError(source + 'must be non-object');\n }\n\n for (var p in source) {\n if (source.hasOwnProperty(p)) {\n obj[p] = source[p];\n }\n }\n }\n\n return obj;\n}\n\n\n// reduce buffer size, avoiding mem copy\nfunction shrinkBuf(buf, size) {\n if (buf.length === size) { return buf; }\n if (buf.subarray) { return buf.subarray(0, size); }\n buf.length = size;\n return buf;\n}\n\n\nfunction arraySet(dest, src, src_offs, len, dest_offs) {\n if (src.subarray && dest.subarray) {\n dest.set(src.subarray(src_offs, src_offs + len), dest_offs);\n return;\n }\n // Fallback to ordinary array\n for (var i = 0; i < len; i++) {\n dest[dest_offs + i] = src[src_offs + i];\n }\n}\n\n// Join array of chunks to single array.\nfunction flattenChunks(chunks) {\n var i, l, len, pos, chunk, result;\n\n // calculate data length\n len = 0;\n for (i = 0, l = chunks.length; i < l; i++) {\n len += chunks[i].length;\n }\n\n // join chunks\n result = new Uint8Array(len);\n pos = 0;\n for (i = 0, l = chunks.length; i < l; i++) {\n chunk = chunks[i];\n result.set(chunk, pos);\n pos += chunk.length;\n }\n\n return result;\n}\n\n// 'use strict';\n\n// Note: adler32 takes 12% for level 0 and 2% for level 6.\n// It doesn't worth to make additional optimizationa as in original.\n// Small size is preferable.\n\nfunction adler32(adler, buf, len, pos) {\n var s1 = (adler & 0xffff) |0,\n s2 = ((adler >>> 16) & 0xffff) |0,\n n = 0;\n\n while (len !== 0) {\n // Set limit ~ twice less than 5552, to keep\n // s2 in 31-bits, because we force signed ints.\n // in other case %= will fail.\n n = len > 2000 ? 2000 : len;\n len -= n;\n\n do {\n s1 = (s1 + buf[pos++]) |0;\n s2 = (s2 + s1) |0;\n } while (--n);\n\n s1 %= 65521;\n s2 %= 65521;\n }\n\n return (s1 | (s2 << 16)) |0;\n}\n\n// 'use strict';\n\n// Note: we can't get significant speed boost here.\n// So write code to minimize size - no pregenerated tables\n// and array tools dependencies.\n\n\n// Use ordinary array, since untyped makes no boost here\nfunction makeTable() {\n var c, table = [];\n\n for (var n = 0; n < 256; n++) {\n c = n;\n for (var k = 0; k < 8; k++) {\n c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));\n }\n table[n] = c;\n }\n\n return table;\n}\n\n// Create table on load. Just 255 signed longs. Not a problem.\nvar crcTable = makeTable();\n\n\nfunction crc32(crc, buf, len, pos) {\n var t = crcTable,\n end = pos + len;\n\n crc ^= -1;\n\n for (var i = pos; i < end; i++) {\n crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF];\n }\n\n return (crc ^ (-1)); // >>> 0;\n}\n\n// 'use strict';\n\n// See state defs from inflate.js\nvar BAD$1 = 30; /* got a data error -- remain here until reset */\nvar TYPE$1 = 12; /* i: waiting for type bits, including last-flag bit */\n\n/*\n Decode literal, length, and distance codes and write out the resulting\n literal and match bytes until either not enough input or output is\n available, an end-of-block is encountered, or a data error is encountered.\n When large enough input and output buffers are supplied to inflate(), for\n example, a 16K input buffer and a 64K output buffer, more than 95% of the\n inflate execution time is spent in this routine.\n\n Entry assumptions:\n\n state.mode === LEN\n strm.avail_in >= 6\n strm.avail_out >= 258\n start >= strm.avail_out\n state.bits < 8\n\n On return, state.mode is one of:\n\n LEN -- ran out of enough output space or enough available input\n TYPE -- reached end of block code, inflate() to interpret next block\n BAD -- error in block data\n\n Notes:\n\n - The maximum input bits used by a length/distance pair is 15 bits for the\n length code, 5 bits for the length extra, 15 bits for the distance code,\n and 13 bits for the distance extra. This totals 48 bits, or six bytes.\n Therefore if strm.avail_in >= 6, then there is enough input to avoid\n checking for available input while decoding.\n\n - The maximum bytes that a single length/distance pair can output is 258\n bytes, which is the maximum length that can be coded. inflate_fast()\n requires strm.avail_out >= 258 for each loop to avoid checking for\n output space.\n */\n// module.exports =\nfunction inflate_fast(strm, start) {\n var state;\n var _in; /* local strm.input */\n var last; /* have enough input while in < last */\n var _out; /* local strm.output */\n var beg; /* inflate()'s initial strm.output */\n var end; /* while out < end, enough space available */\n//#ifdef INFLATE_STRICT\n var dmax; /* maximum distance from zlib header */\n//#endif\n var wsize; /* window size or zero if not using window */\n var whave; /* valid bytes in the window */\n var wnext; /* window write index */\n // Use `s_window` instead `window`, avoid conflict with instrumentation tools\n var s_window; /* allocated sliding window, if wsize != 0 */\n var hold; /* local strm.hold */\n var bits; /* local strm.bits */\n var lcode; /* local strm.lencode */\n var dcode; /* local strm.distcode */\n var lmask; /* mask for first level of length codes */\n var dmask; /* mask for first level of distance codes */\n var here; /* retrieved table entry */\n var op; /* code bits, operation, extra bits, or */\n /* window position, window bytes to copy */\n var len; /* match length, unused bytes */\n var dist; /* match distance */\n var from; /* where to copy match from */\n var from_source;\n\n\n var input, output; // JS specific, because we have no pointers\n\n /* copy state to local variables */\n state = strm.state;\n //here = state.here;\n _in = strm.next_in;\n input = strm.input;\n last = _in + (strm.avail_in - 5);\n _out = strm.next_out;\n output = strm.output;\n beg = _out - (start - strm.avail_out);\n end = _out + (strm.avail_out - 257);\n//#ifdef INFLATE_STRICT\n dmax = state.dmax;\n//#endif\n wsize = state.wsize;\n whave = state.whave;\n wnext = state.wnext;\n s_window = state.window;\n hold = state.hold;\n bits = state.bits;\n lcode = state.lencode;\n dcode = state.distcode;\n lmask = (1 << state.lenbits) - 1;\n dmask = (1 << state.distbits) - 1;\n\n\n /* decode literals and length/distances until end-of-block or not enough\n input data or output space */\n\n top:\n do {\n if (bits < 15) {\n hold += input[_in++] << bits;\n bits += 8;\n hold += input[_in++] << bits;\n bits += 8;\n }\n\n here = lcode[hold & lmask];\n\n dolen:\n for (;;) { // Goto emulation\n op = here >>> 24/*here.bits*/;\n hold >>>= op;\n bits -= op;\n op = (here >>> 16) & 0xff/*here.op*/;\n if (op === 0) { /* literal */\n //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?\n // \"inflate: literal '%c'\\n\" :\n // \"inflate: literal 0x%02x\\n\", here.val));\n output[_out++] = here & 0xffff/*here.val*/;\n }\n else if (op & 16) { /* length base */\n len = here & 0xffff/*here.val*/;\n op &= 15; /* number of extra bits */\n if (op) {\n if (bits < op) {\n hold += input[_in++] << bits;\n bits += 8;\n }\n len += hold & ((1 << op) - 1);\n hold >>>= op;\n bits -= op;\n }\n //Tracevv((stderr, \"inflate: length %u\\n\", len));\n if (bits < 15) {\n hold += input[_in++] << bits;\n bits += 8;\n hold += input[_in++] << bits;\n bits += 8;\n }\n here = dcode[hold & dmask];\n\n dodist:\n for (;;) { // goto emulation\n op = here >>> 24/*here.bits*/;\n hold >>>= op;\n bits -= op;\n op = (here >>> 16) & 0xff/*here.op*/;\n\n if (op & 16) { /* distance base */\n dist = here & 0xffff/*here.val*/;\n op &= 15; /* number of extra bits */\n if (bits < op) {\n hold += input[_in++] << bits;\n bits += 8;\n if (bits < op) {\n hold += input[_in++] << bits;\n bits += 8;\n }\n }\n dist += hold & ((1 << op) - 1);\n//#ifdef INFLATE_STRICT\n if (dist > dmax) {\n strm.msg = 'invalid distance too far back';\n state.mode = BAD$1;\n break top;\n }\n//#endif\n hold >>>= op;\n bits -= op;\n //Tracevv((stderr, \"inflate: distance %u\\n\", dist));\n op = _out - beg; /* max distance in output */\n if (dist > op) { /* see if copy from window */\n op = dist - op; /* distance back in window */\n if (op > whave) {\n if (state.sane) {\n strm.msg = 'invalid distance too far back';\n state.mode = BAD$1;\n break top;\n }\n\n// (!) This block is disabled in zlib defailts,\n// don't enable it for binary compatibility\n//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR\n// if (len <= op - whave) {\n// do {\n// output[_out++] = 0;\n// } while (--len);\n// continue top;\n// }\n// len -= op - whave;\n// do {\n// output[_out++] = 0;\n// } while (--op > whave);\n// if (op === 0) {\n// from = _out - dist;\n// do {\n// output[_out++] = output[from++];\n// } while (--len);\n// continue top;\n// }\n//#endif\n }\n from = 0; // window index\n from_source = s_window;\n if (wnext === 0) { /* very common case */\n from += wsize - op;\n if (op < len) { /* some from window */\n len -= op;\n do {\n output[_out++] = s_window[from++];\n } while (--op);\n from = _out - dist; /* rest from output */\n from_source = output;\n }\n }\n else if (wnext < op) { /* wrap around window */\n from += wsize + wnext - op;\n op -= wnext;\n if (op < len) { /* some from end of window */\n len -= op;\n do {\n output[_out++] = s_window[from++];\n } while (--op);\n from = 0;\n if (wnext < len) { /* some from start of window */\n op = wnext;\n len -= op;\n do {\n output[_out++] = s_window[from++];\n } while (--op);\n from = _out - dist; /* rest from output */\n from_source = output;\n }\n }\n }\n else { /* contiguous in window */\n from += wnext - op;\n if (op < len) { /* some from window */\n len -= op;\n do {\n output[_out++] = s_window[from++];\n } while (--op);\n from = _out - dist; /* rest from output */\n from_source = output;\n }\n }\n while (len > 2) {\n output[_out++] = from_source[from++];\n output[_out++] = from_source[from++];\n output[_out++] = from_source[from++];\n len -= 3;\n }\n if (len) {\n output[_out++] = from_source[from++];\n if (len > 1) {\n output[_out++] = from_source[from++];\n }\n }\n }\n else {\n from = _out - dist; /* copy direct from output */\n do { /* minimum length is three */\n output[_out++] = output[from++];\n output[_out++] = output[from++];\n output[_out++] = output[from++];\n len -= 3;\n } while (len > 2);\n if (len) {\n output[_out++] = output[from++];\n if (len > 1) {\n output[_out++] = output[from++];\n }\n }\n }\n }\n else if ((op & 64) === 0) { /* 2nd level distance code */\n here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];\n continue dodist;\n }\n else {\n strm.msg = 'invalid distance code';\n state.mode = BAD$1;\n break top;\n }\n\n break; // need to emulate goto via \"continue\"\n }\n }\n else if ((op & 64) === 0) { /* 2nd level length code */\n here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))];\n continue dolen;\n }\n else if (op & 32) { /* end-of-block */\n //Tracevv((stderr, \"inflate: end of block\\n\"));\n state.mode = TYPE$1;\n break top;\n }\n else {\n strm.msg = 'invalid literal/length code';\n state.mode = BAD$1;\n break top;\n }\n\n break; // need to emulate goto via \"continue\"\n }\n } while (_in < last && _out < end);\n\n /* return unused bytes (on entry, bits < 8, so in won't go too far back) */\n len = bits >> 3;\n _in -= len;\n bits -= len << 3;\n hold &= (1 << bits) - 1;\n\n /* update state and return */\n strm.next_in = _in;\n strm.next_out = _out;\n strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last));\n strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end));\n state.hold = hold;\n state.bits = bits;\n return;\n};\n\n// 'use strict';\n\n\n// var utils = require('../utils/common');\n\nvar MAXBITS = 15;\nvar ENOUGH_LENS$1 = 852;\nvar ENOUGH_DISTS$1 = 592;\n//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS);\n\nvar CODES$1 = 0;\nvar LENS$1 = 1;\nvar DISTS$1 = 2;\n\nvar lbase = [ /* Length codes 257..285 base */\n 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,\n 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0\n];\n\nvar lext = [ /* Length codes 257..285 extra */\n 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,\n 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78\n];\n\nvar dbase = [ /* Distance codes 0..29 base */\n 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,\n 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,\n 8193, 12289, 16385, 24577, 0, 0\n];\n\nvar dext = [ /* Distance codes 0..29 extra */\n 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22,\n 23, 23, 24, 24, 25, 25, 26, 26, 27, 27,\n 28, 28, 29, 29, 64, 64\n];\n\n// module.exports =\nfunction inflate_table(type, lens, lens_index, codes, table, table_index, work, opts)\n{\n var bits = opts.bits;\n //here = opts.here; /* table entry for duplication */\n\n var len = 0; /* a code's length in bits */\n var sym = 0; /* index of code symbols */\n var min = 0, max = 0; /* minimum and maximum code lengths */\n var root = 0; /* number of index bits for root table */\n var curr = 0; /* number of index bits for current table */\n var drop = 0; /* code bits to drop for sub-table */\n var left = 0; /* number of prefix codes available */\n var used = 0; /* code entries in table used */\n var huff = 0; /* Huffman code */\n var incr; /* for incrementing code, index */\n var fill; /* index for replicating entries */\n var low; /* low bits for current root entry */\n var mask; /* mask for low root bits */\n var next; /* next available space in table */\n var base = null; /* base value table to use */\n var base_index = 0;\n// var shoextra; /* extra bits table to use */\n var end; /* use base and extra for symbol > end */\n var count = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */\n var offs = new Uint16Array(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */\n var extra = null;\n var extra_index = 0;\n\n var here_bits, here_op, here_val;\n\n /*\n Process a set of code lengths to create a canonical Huffman code. The\n code lengths are lens[0..codes-1]. Each length corresponds to the\n symbols 0..codes-1. The Huffman code is generated by first sorting the\n symbols by length from short to long, and retaining the symbol order\n for codes with equal lengths. Then the code starts with all zero bits\n for the first code of the shortest length, and the codes are integer\n increments for the same length, and zeros are appended as the length\n increases. For the deflate format, these bits are stored backwards\n from their more natural integer increment ordering, and so when the\n decoding tables are built in the large loop below, the integer codes\n are incremented backwards.\n\n This routine assumes, but does not check, that all of the entries in\n lens[] are in the range 0..MAXBITS. The caller must assure this.\n 1..MAXBITS is interpreted as that code length. zero means that that\n symbol does not occur in this code.\n\n The codes are sorted by computing a count of codes for each length,\n creating from that a table of starting indices for each length in the\n sorted table, and then entering the symbols in order in the sorted\n table. The sorted table is work[], with that space being provided by\n the caller.\n\n The length counts are used for other purposes as well, i.e. finding\n the minimum and maximum length codes, determining if there are any\n codes at all, checking for a valid set of lengths, and looking ahead\n at length counts to determine sub-table sizes when building the\n decoding tables.\n */\n\n /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */\n for (len = 0; len <= MAXBITS; len++) {\n count[len] = 0;\n }\n for (sym = 0; sym < codes; sym++) {\n count[lens[lens_index + sym]]++;\n }\n\n /* bound code lengths, force root to be within code lengths */\n root = bits;\n for (max = MAXBITS; max >= 1; max--) {\n if (count[max] !== 0) { break; }\n }\n if (root > max) {\n root = max;\n }\n if (max === 0) { /* no symbols to code at all */\n //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */\n //table.bits[opts.table_index] = 1; //here.bits = (var char)1;\n //table.val[opts.table_index++] = 0; //here.val = (var short)0;\n table[table_index++] = (1 << 24) | (64 << 16) | 0;\n\n\n //table.op[opts.table_index] = 64;\n //table.bits[opts.table_index] = 1;\n //table.val[opts.table_index++] = 0;\n table[table_index++] = (1 << 24) | (64 << 16) | 0;\n\n opts.bits = 1;\n return 0; /* no symbols, but wait for decoding to report error */\n }\n for (min = 1; min < max; min++) {\n if (count[min] !== 0) { break; }\n }\n if (root < min) {\n root = min;\n }\n\n /* check for an over-subscribed or incomplete set of lengths */\n left = 1;\n for (len = 1; len <= MAXBITS; len++) {\n left <<= 1;\n left -= count[len];\n if (left < 0) {\n return -1;\n } /* over-subscribed */\n }\n if (left > 0 && (type === CODES$1 || max !== 1)) {\n return -1; /* incomplete set */\n }\n\n /* generate offsets into symbol table for each length for sorting */\n offs[1] = 0;\n for (len = 1; len < MAXBITS; len++) {\n offs[len + 1] = offs[len] + count[len];\n }\n\n /* sort symbols by length, by symbol order within each length */\n for (sym = 0; sym < codes; sym++) {\n if (lens[lens_index + sym] !== 0) {\n work[offs[lens[lens_index + sym]]++] = sym;\n }\n }\n\n /*\n Create and fill in decoding tables. In this loop, the table being\n filled is at next and has curr index bits. The code being used is huff\n with length len. That code is converted to an index by dropping drop\n bits off of the bottom. For codes where len is less than drop + curr,\n those top drop + curr - len bits are incremented through all values to\n fill the table with replicated entries.\n\n root is the number of index bits for the root table. When len exceeds\n root, sub-tables are created pointed to by the root entry with an index\n of the low root bits of huff. This is saved in low to check for when a\n new sub-table should be started. drop is zero when the root table is\n being filled, and drop is root when sub-tables are being filled.\n\n When a new sub-table is needed, it is necessary to look ahead in the\n code lengths to determine what size sub-table is needed. The length\n counts are used for this, and so count[] is decremented as codes are\n entered in the tables.\n\n used keeps track of how many table entries have been allocated from the\n provided *table space. It is checked for LENS and DIST tables against\n the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in\n the initial root table size constants. See the comments in inftrees.h\n for more information.\n\n sym increments through all symbols, and the loop terminates when\n all codes of length max, i.e. all codes, have been processed. This\n routine permits incomplete codes, so another loop after this one fills\n in the rest of the decoding tables with invalid code markers.\n */\n\n /* set up for code type */\n // poor man optimization - use if-else instead of switch,\n // to avoid deopts in old v8\n if (type === CODES$1) {\n base = extra = work; /* dummy value--not used */\n end = 19;\n\n } else if (type === LENS$1) {\n base = lbase;\n base_index -= 257;\n extra = lext;\n extra_index -= 257;\n end = 256;\n\n } else { /* DISTS */\n base = dbase;\n extra = dext;\n end = -1;\n }\n\n /* initialize opts for loop */\n huff = 0; /* starting code */\n sym = 0; /* starting code symbol */\n len = min; /* starting code length */\n next = table_index; /* current table to fill in */\n curr = root; /* current table index bits */\n drop = 0; /* current bits to drop from code for index */\n low = -1; /* trigger new sub-table when len > root */\n used = 1 << root; /* use root table entries */\n mask = used - 1; /* mask for comparing low */\n\n /* check available table space */\n if ((type === LENS$1 && used > ENOUGH_LENS$1) ||\n (type === DISTS$1 && used > ENOUGH_DISTS$1)) {\n return 1;\n }\n\n var i = 0;\n /* process all codes and make table entries */\n for (;;) {\n i++;\n /* create table entry */\n here_bits = len - drop;\n if (work[sym] < end) {\n here_op = 0;\n here_val = work[sym];\n }\n else if (work[sym] > end) {\n here_op = extra[extra_index + work[sym]];\n here_val = base[base_index + work[sym]];\n }\n else {\n here_op = 32 + 64; /* end of block */\n here_val = 0;\n }\n\n /* replicate for those indices with low len bits equal to huff */\n incr = 1 << (len - drop);\n fill = 1 << curr;\n min = fill; /* save offset to next table */\n do {\n fill -= incr;\n table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0;\n } while (fill !== 0);\n\n /* backwards increment the len-bit code huff */\n incr = 1 << (len - 1);\n while (huff & incr) {\n incr >>= 1;\n }\n if (incr !== 0) {\n huff &= incr - 1;\n huff += incr;\n } else {\n huff = 0;\n }\n\n /* go to next symbol, update count, len */\n sym++;\n if (--count[len] === 0) {\n if (len === max) { break; }\n len = lens[lens_index + work[sym]];\n }\n\n /* create new sub-table if needed */\n if (len > root && (huff & mask) !== low) {\n /* if first time, transition to sub-tables */\n if (drop === 0) {\n drop = root;\n }\n\n /* increment past last table */\n next += min; /* here min is 1 << curr */\n\n /* determine length of next table */\n curr = len - drop;\n left = 1 << curr;\n while (curr + drop < max) {\n left -= count[curr + drop];\n if (left <= 0) { break; }\n curr++;\n left <<= 1;\n }\n\n /* check for enough space */\n used += 1 << curr;\n if ((type === LENS$1 && used > ENOUGH_LENS$1) ||\n (type === DISTS$1 && used > ENOUGH_DISTS$1)) {\n return 1;\n }\n\n /* point entry in root table to sub-table */\n low = huff & mask;\n /*table.op[low] = curr;\n table.bits[low] = root;\n table.val[low] = next - opts.table_index;*/\n table[low] = (root << 24) | (curr << 16) | (next - table_index) |0;\n }\n }\n\n /* fill in remaining table entry if code is incomplete (guaranteed to have\n at most one remaining entry, since if the code is incomplete, the\n maximum code length that was allowed to get this far is one bit) */\n if (huff !== 0) {\n //table.op[next + huff] = 64; /* invalid code marker */\n //table.bits[next + huff] = len - drop;\n //table.val[next + huff] = 0;\n table[next + huff] = ((len - drop) << 24) | (64 << 16) |0;\n }\n\n /* set return parameters */\n //opts.table_index += used;\n opts.bits = root;\n return 0;\n};\n\n// 'use strict';\n\n\n// var utils = require('../utils/common');\n// var adler32 = require('./adler32');\n// var crc32 = require('./crc32');\n// var inflate_fast = require('./inffast');\n// var inflate_table = require('./inftrees');\n\nvar CODES = 0;\nvar LENS = 1;\nvar DISTS = 2;\n\n/* Public constants ==========================================================*/\n/* ===========================================================================*/\n\n\n/* Allowed flush values; see deflate() and inflate() below for details */\n//var Z_NO_FLUSH = 0;\n//var Z_PARTIAL_FLUSH = 1;\n//var Z_SYNC_FLUSH = 2;\n//var Z_FULL_FLUSH = 3;\nvar Z_FINISH = 4;\nvar Z_BLOCK = 5;\nvar Z_TREES = 6;\n\n\n/* Return codes for the compression/decompression functions. Negative values\n * are errors, positive values are used for special but normal events.\n */\nvar Z_OK = 0;\nvar Z_STREAM_END = 1;\nvar Z_NEED_DICT = 2;\n//var Z_ERRNO = -1;\nvar Z_STREAM_ERROR = -2;\nvar Z_DATA_ERROR = -3;\nvar Z_MEM_ERROR = -4;\nvar Z_BUF_ERROR = -5;\n//var Z_VERSION_ERROR = -6;\n\n/* The deflate compression method */\nvar Z_DEFLATED = 8;\n\n\n/* STATES ====================================================================*/\n/* ===========================================================================*/\n\n\nvar HEAD = 1; /* i: waiting for magic header */\nvar FLAGS = 2; /* i: waiting for method and flags (gzip) */\nvar TIME = 3; /* i: waiting for modification time (gzip) */\nvar OS = 4; /* i: waiting for extra flags and operating system (gzip) */\nvar EXLEN = 5; /* i: waiting for extra length (gzip) */\nvar EXTRA = 6; /* i: waiting for extra bytes (gzip) */\nvar NAME = 7; /* i: waiting for end of file name (gzip) */\nvar COMMENT = 8; /* i: waiting for end of comment (gzip) */\nvar HCRC = 9; /* i: waiting for header crc (gzip) */\nvar DICTID = 10; /* i: waiting for dictionary check value */\nvar DICT = 11; /* waiting for inflateSetDictionary() call */\nvar TYPE = 12; /* i: waiting for type bits, including last-flag bit */\nvar TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */\nvar STORED = 14; /* i: waiting for stored size (length and complement) */\nvar COPY_ = 15; /* i/o: same as COPY below, but only first time in */\nvar COPY = 16; /* i/o: waiting for input or output to copy stored block */\nvar TABLE = 17; /* i: waiting for dynamic block table lengths */\nvar LENLENS = 18; /* i: waiting for code length code lengths */\nvar CODELENS = 19; /* i: waiting for length/lit and distance code lengths */\nvar LEN_ = 20; /* i: same as LEN below, but only first time in */\nvar LEN = 21; /* i: waiting for length/lit/eob code */\nvar LENEXT = 22; /* i: waiting for length extra bits */\nvar DIST = 23; /* i: waiting for distance code */\nvar DISTEXT = 24; /* i: waiting for distance extra bits */\nvar MATCH = 25; /* o: waiting for output space to copy string */\nvar LIT = 26; /* o: waiting for output space to write literal */\nvar CHECK = 27; /* i: waiting for 32-bit check value */\nvar LENGTH = 28; /* i: waiting for 32-bit length (gzip) */\nvar DONE = 29; /* finished check, done -- remain here until reset */\nvar BAD = 30; /* got a data error -- remain here until reset */\nvar MEM = 31; /* got an inflate() memory error -- remain here until reset */\nvar SYNC = 32; /* looking for synchronization bytes to restart inflate() */\n\n/* ===========================================================================*/\n\n\n\nvar ENOUGH_LENS = 852;\nvar ENOUGH_DISTS = 592;\nfunction zswap32(q) {\n return (((q >>> 24) & 0xff) +\n ((q >>> 8) & 0xff00) +\n ((q & 0xff00) << 8) +\n ((q & 0xff) << 24));\n}\n\n\nfunction InflateState() {\n this.mode = 0; /* current inflate mode */\n this.last = false; /* true if processing last block */\n this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */\n this.havedict = false; /* true if dictionary provided */\n this.flags = 0; /* gzip header method and flags (0 if zlib) */\n this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */\n this.check = 0; /* protected copy of check value */\n this.total = 0; /* protected copy of output count */\n // TODO: may be {}\n this.head = null; /* where to save gzip header information */\n\n /* sliding window */\n this.wbits = 0; /* log base 2 of requested window size */\n this.wsize = 0; /* window size or zero if not using window */\n this.whave = 0; /* valid bytes in the window */\n this.wnext = 0; /* window write index */\n this.window = null; /* allocated sliding window, if needed */\n\n /* bit accumulator */\n this.hold = 0; /* input bit accumulator */\n this.bits = 0; /* number of bits in \"in\" */\n\n /* for string and stored block copying */\n this.length = 0; /* literal or length of data to copy */\n this.offset = 0; /* distance back to copy string from */\n\n /* for table and code decoding */\n this.extra = 0; /* extra bits needed */\n\n /* fixed and dynamic code tables */\n this.lencode = null; /* starting table for length/literal codes */\n this.distcode = null; /* starting table for distance codes */\n this.lenbits = 0; /* index bits for lencode */\n this.distbits = 0; /* index bits for distcode */\n\n /* dynamic table building */\n this.ncode = 0; /* number of code length code lengths */\n this.nlen = 0; /* number of length code lengths */\n this.ndist = 0; /* number of distance code lengths */\n this.have = 0; /* number of code lengths in lens[] */\n this.next = null; /* next available space in codes[] */\n\n this.lens = new Uint16Array(320); /* temporary storage for code lengths */\n this.work = new Uint16Array(288); /* work area for code table building */\n\n /*\n because we don't have pointers in js, we use lencode and distcode directly\n as buffers so we don't need codes\n */\n //this.codes = new Buf32(ENOUGH); /* space for code tables */\n this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */\n this.distdyn = null; /* dynamic table for distance codes (JS specific) */\n this.sane = 0; /* if false, allow invalid distance too far */\n this.back = 0; /* bits back of last unprocessed length/lit */\n this.was = 0; /* initial length of match */\n}\n\nfunction inflateResetKeep(strm) {\n var state;\n\n if (!strm || !strm.state) { return Z_STREAM_ERROR; }\n state = strm.state;\n strm.total_in = strm.total_out = state.total = 0;\n strm.msg = ''; /*Z_NULL*/\n if (state.wrap) { /* to support ill-conceived Java test suite */\n strm.adler = state.wrap & 1;\n }\n state.mode = HEAD;\n state.last = 0;\n state.havedict = 0;\n state.dmax = 32768;\n state.head = null/*Z_NULL*/;\n state.hold = 0;\n state.bits = 0;\n //state.lencode = state.distcode = state.next = state.codes;\n state.lencode = state.lendyn = new Int32Array(ENOUGH_LENS);\n state.distcode = state.distdyn = new Int32Array(ENOUGH_DISTS);\n\n state.sane = 1;\n state.back = -1;\n //Tracev((stderr, \"inflate: reset\\n\"));\n return Z_OK;\n}\n\nfunction inflateReset(strm) {\n var state;\n\n if (!strm || !strm.state) { return Z_STREAM_ERROR; }\n state = strm.state;\n state.wsize = 0;\n state.whave = 0;\n state.wnext = 0;\n return inflateResetKeep(strm);\n\n}\n\nfunction inflateReset2(strm, windowBits) {\n var wrap;\n var state;\n\n /* get the state */\n if (!strm || !strm.state) { return Z_STREAM_ERROR; }\n state = strm.state;\n\n /* extract wrap request from windowBits parameter */\n if (windowBits < 0) {\n wrap = 0;\n windowBits = -windowBits;\n }\n else {\n wrap = (windowBits >> 4) + 1;\n if (windowBits < 48) {\n windowBits &= 15;\n }\n }\n\n /* set number of window bits, free window if different */\n if (windowBits && (windowBits < 8 || windowBits > 15)) {\n return Z_STREAM_ERROR;\n }\n if (state.window !== null && state.wbits !== windowBits) {\n state.window = null;\n }\n\n /* update state and reset the rest of it */\n state.wrap = wrap;\n state.wbits = windowBits;\n return inflateReset(strm);\n}\n\nfunction inflateInit2(strm, windowBits) {\n var ret;\n var state;\n\n if (!strm) { return Z_STREAM_ERROR; }\n //strm.msg = Z_NULL; /* in case we return an error */\n\n state = new InflateState();\n\n //if (state === Z_NULL) return Z_MEM_ERROR;\n //Tracev((stderr, \"inflate: allocated\\n\"));\n strm.state = state;\n state.window = null/*Z_NULL*/;\n ret = inflateReset2(strm, windowBits);\n if (ret !== Z_OK) {\n strm.state = null/*Z_NULL*/;\n }\n return ret;\n}\n\n/*\n Return state with length and distance decoding tables and index sizes set to\n fixed code decoding. Normally this returns fixed tables from inffixed.h.\n If BUILDFIXED is defined, then instead this routine builds the tables the\n first time it's called, and returns those tables the first time and\n thereafter. This reduces the size of the code by about 2K bytes, in\n exchange for a little execution time. However, BUILDFIXED should not be\n used for threaded applications, since the rewriting of the tables and virgin\n may not be thread-safe.\n */\nvar virgin = true;\n\nvar lenfix;\nvar distfix;\n// We have no pointers in JS, so keep tables separate\n\nfunction fixedtables(state) {\n /* build fixed huffman tables if first call (may not be thread safe) */\n if (virgin) {\n var sym;\n\n lenfix = new Int32Array(512);\n distfix = new Int32Array(32);\n\n /* literal/length table */\n sym = 0;\n while (sym < 144) { state.lens[sym++] = 8; }\n while (sym < 256) { state.lens[sym++] = 9; }\n while (sym < 280) { state.lens[sym++] = 7; }\n while (sym < 288) { state.lens[sym++] = 8; }\n\n inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 });\n\n /* distance table */\n sym = 0;\n while (sym < 32) { state.lens[sym++] = 5; }\n\n inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 });\n\n /* do this just once */\n virgin = false;\n }\n\n state.lencode = lenfix;\n state.lenbits = 9;\n state.distcode = distfix;\n state.distbits = 5;\n}\n\n\n/*\n Update the window with the last wsize (normally 32K) bytes written before\n returning. If window does not exist yet, create it. This is only called\n when a window is already in use, or when output has been written during this\n inflate call, but the end of the deflate stream has not been reached yet.\n It is also called to create a window for dictionary data when a dictionary\n is loaded.\n\n Providing output buffers larger than 32K to inflate() should provide a speed\n advantage, since only the last 32K of output is copied to the sliding window\n upon return from inflate(), and since all distances after the first 32K of\n output will fall in the output data, making match copies simpler and faster.\n The advantage may be dependent on the size of the processor's data caches.\n */\nfunction updatewindow(strm, src, end, copy) {\n var dist;\n var state = strm.state;\n\n /* if it hasn't been done already, allocate space for the window */\n if (state.window === null) {\n state.wsize = 1 << state.wbits;\n state.wnext = 0;\n state.whave = 0;\n\n state.window = new Uint8Array(state.wsize);\n }\n\n /* copy state->wsize or less output bytes into the circular window */\n if (copy >= state.wsize) {\n arraySet(state.window, src, end - state.wsize, state.wsize, 0);\n state.wnext = 0;\n state.whave = state.wsize;\n }\n else {\n dist = state.wsize - state.wnext;\n if (dist > copy) {\n dist = copy;\n }\n //zmemcpy(state->window + state->wnext, end - copy, dist);\n arraySet(state.window, src, end - copy, dist, state.wnext);\n copy -= dist;\n if (copy) {\n //zmemcpy(state->window, end - copy, copy);\n arraySet(state.window, src, end - copy, copy, 0);\n state.wnext = copy;\n state.whave = state.wsize;\n }\n else {\n state.wnext += dist;\n if (state.wnext === state.wsize) { state.wnext = 0; }\n if (state.whave < state.wsize) { state.whave += dist; }\n }\n }\n return 0;\n}\n\nfunction inflate(strm, flush) {\n var state;\n var input, output; // input/output buffers\n var next; /* next input INDEX */\n var put; /* next output INDEX */\n var have, left; /* available input and output */\n var hold; /* bit buffer */\n var bits; /* bits in bit buffer */\n var _in, _out; /* save starting available input and output */\n var copy; /* number of stored or match bytes to copy */\n var from; /* where to copy match bytes from */\n var from_source;\n var here = 0; /* current decoding table entry */\n var here_bits, here_op, here_val; // paked \"here\" denormalized (JS specific)\n //var last; /* parent table entry */\n var last_bits, last_op, last_val; // paked \"last\" denormalized (JS specific)\n var len; /* length to copy for repeats, bits to drop */\n var ret; /* return code */\n var hbuf = new Uint8Array(4); /* buffer for gzip header crc calculation */\n var opts;\n\n var n; // temporary var for NEED_BITS\n\n var order = /* permutation of code lengths */\n [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ];\n\n\n if (!strm || !strm.state || !strm.output ||\n (!strm.input && strm.avail_in !== 0)) {\n return Z_STREAM_ERROR;\n }\n\n state = strm.state;\n if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */\n\n\n //--- LOAD() ---\n put = strm.next_out;\n output = strm.output;\n left = strm.avail_out;\n next = strm.next_in;\n input = strm.input;\n have = strm.avail_in;\n hold = state.hold;\n bits = state.bits;\n //---\n\n _in = have;\n _out = left;\n ret = Z_OK;\n\n inf_leave: // goto emulation\n for (;;) {\n switch (state.mode) {\n case HEAD:\n if (state.wrap === 0) {\n state.mode = TYPEDO;\n break;\n }\n //=== NEEDBITS(16);\n while (bits < 16) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */\n state.check = 0/*crc32(0L, Z_NULL, 0)*/;\n //=== CRC2(state.check, hold);\n hbuf[0] = hold & 0xff;\n hbuf[1] = (hold >>> 8) & 0xff;\n state.check = crc32(state.check, hbuf, 2, 0);\n //===//\n\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n state.mode = FLAGS;\n break;\n }\n state.flags = 0; /* expect zlib header */\n if (state.head) {\n state.head.done = false;\n }\n if (!(state.wrap & 1) || /* check if zlib header allowed */\n (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) {\n strm.msg = 'incorrect header check';\n state.mode = BAD;\n break;\n }\n if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) {\n strm.msg = 'unknown compression method';\n state.mode = BAD;\n break;\n }\n //--- DROPBITS(4) ---//\n hold >>>= 4;\n bits -= 4;\n //---//\n len = (hold & 0x0f)/*BITS(4)*/ + 8;\n if (state.wbits === 0) {\n state.wbits = len;\n }\n else if (len > state.wbits) {\n strm.msg = 'invalid window size';\n state.mode = BAD;\n break;\n }\n state.dmax = 1 << len;\n //Tracev((stderr, \"inflate: zlib header ok\\n\"));\n strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;\n state.mode = hold & 0x200 ? DICTID : TYPE;\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n break;\n case FLAGS:\n //=== NEEDBITS(16); */\n while (bits < 16) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.flags = hold;\n if ((state.flags & 0xff) !== Z_DEFLATED) {\n strm.msg = 'unknown compression method';\n state.mode = BAD;\n break;\n }\n if (state.flags & 0xe000) {\n strm.msg = 'unknown header flags set';\n state.mode = BAD;\n break;\n }\n if (state.head) {\n state.head.text = ((hold >> 8) & 1);\n }\n if (state.flags & 0x0200) {\n //=== CRC2(state.check, hold);\n hbuf[0] = hold & 0xff;\n hbuf[1] = (hold >>> 8) & 0xff;\n state.check = crc32(state.check, hbuf, 2, 0);\n //===//\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n state.mode = TIME;\n /* falls through */\n case TIME:\n //=== NEEDBITS(32); */\n while (bits < 32) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n if (state.head) {\n state.head.time = hold;\n }\n if (state.flags & 0x0200) {\n //=== CRC4(state.check, hold)\n hbuf[0] = hold & 0xff;\n hbuf[1] = (hold >>> 8) & 0xff;\n hbuf[2] = (hold >>> 16) & 0xff;\n hbuf[3] = (hold >>> 24) & 0xff;\n state.check = crc32(state.check, hbuf, 4, 0);\n //===\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n state.mode = OS;\n /* falls through */\n case OS:\n //=== NEEDBITS(16); */\n while (bits < 16) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n if (state.head) {\n state.head.xflags = (hold & 0xff);\n state.head.os = (hold >> 8);\n }\n if (state.flags & 0x0200) {\n //=== CRC2(state.check, hold);\n hbuf[0] = hold & 0xff;\n hbuf[1] = (hold >>> 8) & 0xff;\n state.check = crc32(state.check, hbuf, 2, 0);\n //===//\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n state.mode = EXLEN;\n /* falls through */\n case EXLEN:\n if (state.flags & 0x0400) {\n //=== NEEDBITS(16); */\n while (bits < 16) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.length = hold;\n if (state.head) {\n state.head.extra_len = hold;\n }\n if (state.flags & 0x0200) {\n //=== CRC2(state.check, hold);\n hbuf[0] = hold & 0xff;\n hbuf[1] = (hold >>> 8) & 0xff;\n state.check = crc32(state.check, hbuf, 2, 0);\n //===//\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n }\n else if (state.head) {\n state.head.extra = null/*Z_NULL*/;\n }\n state.mode = EXTRA;\n /* falls through */\n case EXTRA:\n if (state.flags & 0x0400) {\n copy = state.length;\n if (copy > have) { copy = have; }\n if (copy) {\n if (state.head) {\n len = state.head.extra_len - state.length;\n if (!state.head.extra) {\n // Use untyped array for more conveniend processing later\n state.head.extra = new Array(state.head.extra_len);\n }\n arraySet(\n state.head.extra,\n input,\n next,\n // extra field is limited to 65536 bytes\n // - no need for additional size check\n copy,\n /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/\n len\n );\n //zmemcpy(state.head.extra + len, next,\n // len + copy > state.head.extra_max ?\n // state.head.extra_max - len : copy);\n }\n if (state.flags & 0x0200) {\n state.check = crc32(state.check, input, copy, next);\n }\n have -= copy;\n next += copy;\n state.length -= copy;\n }\n if (state.length) { break inf_leave; }\n }\n state.length = 0;\n state.mode = NAME;\n /* falls through */\n case NAME:\n if (state.flags & 0x0800) {\n if (have === 0) { break inf_leave; }\n copy = 0;\n do {\n // TODO: 2 or 1 bytes?\n len = input[next + copy++];\n /* use constant limit because in js we should not preallocate memory */\n if (state.head && len &&\n (state.length < 65536 /*state.head.name_max*/)) {\n state.head.name += String.fromCharCode(len);\n }\n } while (len && copy < have);\n\n if (state.flags & 0x0200) {\n state.check = crc32(state.check, input, copy, next);\n }\n have -= copy;\n next += copy;\n if (len) { break inf_leave; }\n }\n else if (state.head) {\n state.head.name = null;\n }\n state.length = 0;\n state.mode = COMMENT;\n /* falls through */\n case COMMENT:\n if (state.flags & 0x1000) {\n if (have === 0) { break inf_leave; }\n copy = 0;\n do {\n len = input[next + copy++];\n /* use constant limit because in js we should not preallocate memory */\n if (state.head && len &&\n (state.length < 65536 /*state.head.comm_max*/)) {\n state.head.comment += String.fromCharCode(len);\n }\n } while (len && copy < have);\n if (state.flags & 0x0200) {\n state.check = crc32(state.check, input, copy, next);\n }\n have -= copy;\n next += copy;\n if (len) { break inf_leave; }\n }\n else if (state.head) {\n state.head.comment = null;\n }\n state.mode = HCRC;\n /* falls through */\n case HCRC:\n if (state.flags & 0x0200) {\n //=== NEEDBITS(16); */\n while (bits < 16) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n if (hold !== (state.check & 0xffff)) {\n strm.msg = 'header crc mismatch';\n state.mode = BAD;\n break;\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n }\n if (state.head) {\n state.head.hcrc = ((state.flags >> 9) & 1);\n state.head.done = true;\n }\n strm.adler = state.check = 0;\n state.mode = TYPE;\n break;\n case DICTID:\n //=== NEEDBITS(32); */\n while (bits < 32) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n strm.adler = state.check = zswap32(hold);\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n state.mode = DICT;\n /* falls through */\n case DICT:\n if (state.havedict === 0) {\n //--- RESTORE() ---\n strm.next_out = put;\n strm.avail_out = left;\n strm.next_in = next;\n strm.avail_in = have;\n state.hold = hold;\n state.bits = bits;\n //---\n return Z_NEED_DICT;\n }\n strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/;\n state.mode = TYPE;\n /* falls through */\n case TYPE:\n if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; }\n /* falls through */\n case TYPEDO:\n if (state.last) {\n //--- BYTEBITS() ---//\n hold >>>= bits & 7;\n bits -= bits & 7;\n //---//\n state.mode = CHECK;\n break;\n }\n //=== NEEDBITS(3); */\n while (bits < 3) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.last = (hold & 0x01)/*BITS(1)*/;\n //--- DROPBITS(1) ---//\n hold >>>= 1;\n bits -= 1;\n //---//\n\n switch ((hold & 0x03)/*BITS(2)*/) {\n case 0: /* stored block */\n //Tracev((stderr, \"inflate: stored block%s\\n\",\n // state.last ? \" (last)\" : \"\"));\n state.mode = STORED;\n break;\n case 1: /* fixed block */\n fixedtables(state);\n //Tracev((stderr, \"inflate: fixed codes block%s\\n\",\n // state.last ? \" (last)\" : \"\"));\n state.mode = LEN_; /* decode codes */\n if (flush === Z_TREES) {\n //--- DROPBITS(2) ---//\n hold >>>= 2;\n bits -= 2;\n //---//\n break inf_leave;\n }\n break;\n case 2: /* dynamic block */\n //Tracev((stderr, \"inflate: dynamic codes block%s\\n\",\n // state.last ? \" (last)\" : \"\"));\n state.mode = TABLE;\n break;\n case 3:\n strm.msg = 'invalid block type';\n state.mode = BAD;\n }\n //--- DROPBITS(2) ---//\n hold >>>= 2;\n bits -= 2;\n //---//\n break;\n case STORED:\n //--- BYTEBITS() ---// /* go to byte boundary */\n hold >>>= bits & 7;\n bits -= bits & 7;\n //---//\n //=== NEEDBITS(32); */\n while (bits < 32) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) {\n strm.msg = 'invalid stored block lengths';\n state.mode = BAD;\n break;\n }\n state.length = hold & 0xffff;\n //Tracev((stderr, \"inflate: stored length %u\\n\",\n // state.length));\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n state.mode = COPY_;\n if (flush === Z_TREES) { break inf_leave; }\n /* falls through */\n case COPY_:\n state.mode = COPY;\n /* falls through */\n case COPY:\n copy = state.length;\n if (copy) {\n if (copy > have) { copy = have; }\n if (copy > left) { copy = left; }\n if (copy === 0) { break inf_leave; }\n //--- zmemcpy(put, next, copy); ---\n arraySet(output, input, next, copy, put);\n //---//\n have -= copy;\n next += copy;\n left -= copy;\n put += copy;\n state.length -= copy;\n break;\n }\n //Tracev((stderr, \"inflate: stored end\\n\"));\n state.mode = TYPE;\n break;\n case TABLE:\n //=== NEEDBITS(14); */\n while (bits < 14) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257;\n //--- DROPBITS(5) ---//\n hold >>>= 5;\n bits -= 5;\n //---//\n state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1;\n //--- DROPBITS(5) ---//\n hold >>>= 5;\n bits -= 5;\n //---//\n state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4;\n //--- DROPBITS(4) ---//\n hold >>>= 4;\n bits -= 4;\n //---//\n//#ifndef PKZIP_BUG_WORKAROUND\n if (state.nlen > 286 || state.ndist > 30) {\n strm.msg = 'too many length or distance symbols';\n state.mode = BAD;\n break;\n }\n//#endif\n //Tracev((stderr, \"inflate: table sizes ok\\n\"));\n state.have = 0;\n state.mode = LENLENS;\n /* falls through */\n case LENLENS:\n while (state.have < state.ncode) {\n //=== NEEDBITS(3);\n while (bits < 3) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.lens[order[state.have++]] = (hold & 0x07);//BITS(3);\n //--- DROPBITS(3) ---//\n hold >>>= 3;\n bits -= 3;\n //---//\n }\n while (state.have < 19) {\n state.lens[order[state.have++]] = 0;\n }\n // We have separate tables & no pointers. 2 commented lines below not needed.\n //state.next = state.codes;\n //state.lencode = state.next;\n // Switch to use dynamic table\n state.lencode = state.lendyn;\n state.lenbits = 7;\n\n opts = { bits: state.lenbits };\n ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts);\n state.lenbits = opts.bits;\n\n if (ret) {\n strm.msg = 'invalid code lengths set';\n state.mode = BAD;\n break;\n }\n //Tracev((stderr, \"inflate: code lengths ok\\n\"));\n state.have = 0;\n state.mode = CODELENS;\n /* falls through */\n case CODELENS:\n while (state.have < state.nlen + state.ndist) {\n for (;;) {\n here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/\n here_bits = here >>> 24;\n here_op = (here >>> 16) & 0xff;\n here_val = here & 0xffff;\n\n if ((here_bits) <= bits) { break; }\n //--- PULLBYTE() ---//\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n //---//\n }\n if (here_val < 16) {\n //--- DROPBITS(here.bits) ---//\n hold >>>= here_bits;\n bits -= here_bits;\n //---//\n state.lens[state.have++] = here_val;\n }\n else {\n if (here_val === 16) {\n //=== NEEDBITS(here.bits + 2);\n n = here_bits + 2;\n while (bits < n) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n //--- DROPBITS(here.bits) ---//\n hold >>>= here_bits;\n bits -= here_bits;\n //---//\n if (state.have === 0) {\n strm.msg = 'invalid bit length repeat';\n state.mode = BAD;\n break;\n }\n len = state.lens[state.have - 1];\n copy = 3 + (hold & 0x03);//BITS(2);\n //--- DROPBITS(2) ---//\n hold >>>= 2;\n bits -= 2;\n //---//\n }\n else if (here_val === 17) {\n //=== NEEDBITS(here.bits + 3);\n n = here_bits + 3;\n while (bits < n) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n //--- DROPBITS(here.bits) ---//\n hold >>>= here_bits;\n bits -= here_bits;\n //---//\n len = 0;\n copy = 3 + (hold & 0x07);//BITS(3);\n //--- DROPBITS(3) ---//\n hold >>>= 3;\n bits -= 3;\n //---//\n }\n else {\n //=== NEEDBITS(here.bits + 7);\n n = here_bits + 7;\n while (bits < n) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n //--- DROPBITS(here.bits) ---//\n hold >>>= here_bits;\n bits -= here_bits;\n //---//\n len = 0;\n copy = 11 + (hold & 0x7f);//BITS(7);\n //--- DROPBITS(7) ---//\n hold >>>= 7;\n bits -= 7;\n //---//\n }\n if (state.have + copy > state.nlen + state.ndist) {\n strm.msg = 'invalid bit length repeat';\n state.mode = BAD;\n break;\n }\n while (copy--) {\n state.lens[state.have++] = len;\n }\n }\n }\n\n /* handle error breaks in while */\n if (state.mode === BAD) { break; }\n\n /* check for end-of-block code (better have one) */\n if (state.lens[256] === 0) {\n strm.msg = 'invalid code -- missing end-of-block';\n state.mode = BAD;\n break;\n }\n\n /* build code tables -- note: do not change the lenbits or distbits\n values here (9 and 6) without reading the comments in inftrees.h\n concerning the ENOUGH constants, which depend on those values */\n state.lenbits = 9;\n\n opts = { bits: state.lenbits };\n ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts);\n // We have separate tables & no pointers. 2 commented lines below not needed.\n // state.next_index = opts.table_index;\n state.lenbits = opts.bits;\n // state.lencode = state.next;\n\n if (ret) {\n strm.msg = 'invalid literal/lengths set';\n state.mode = BAD;\n break;\n }\n\n state.distbits = 6;\n //state.distcode.copy(state.codes);\n // Switch to use dynamic table\n state.distcode = state.distdyn;\n opts = { bits: state.distbits };\n ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts);\n // We have separate tables & no pointers. 2 commented lines below not needed.\n // state.next_index = opts.table_index;\n state.distbits = opts.bits;\n // state.distcode = state.next;\n\n if (ret) {\n strm.msg = 'invalid distances set';\n state.mode = BAD;\n break;\n }\n //Tracev((stderr, 'inflate: codes ok\\n'));\n state.mode = LEN_;\n if (flush === Z_TREES) { break inf_leave; }\n /* falls through */\n case LEN_:\n state.mode = LEN;\n /* falls through */\n case LEN:\n if (have >= 6 && left >= 258) {\n //--- RESTORE() ---\n strm.next_out = put;\n strm.avail_out = left;\n strm.next_in = next;\n strm.avail_in = have;\n state.hold = hold;\n state.bits = bits;\n //---\n inflate_fast(strm, _out);\n //--- LOAD() ---\n put = strm.next_out;\n output = strm.output;\n left = strm.avail_out;\n next = strm.next_in;\n input = strm.input;\n have = strm.avail_in;\n hold = state.hold;\n bits = state.bits;\n //---\n\n if (state.mode === TYPE) {\n state.back = -1;\n }\n break;\n }\n state.back = 0;\n for (;;) {\n here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/\n here_bits = here >>> 24;\n here_op = (here >>> 16) & 0xff;\n here_val = here & 0xffff;\n\n if (here_bits <= bits) { break; }\n //--- PULLBYTE() ---//\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n //---//\n }\n if (here_op && (here_op & 0xf0) === 0) {\n last_bits = here_bits;\n last_op = here_op;\n last_val = here_val;\n for (;;) {\n here = state.lencode[last_val +\n ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];\n here_bits = here >>> 24;\n here_op = (here >>> 16) & 0xff;\n here_val = here & 0xffff;\n\n if ((last_bits + here_bits) <= bits) { break; }\n //--- PULLBYTE() ---//\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n //---//\n }\n //--- DROPBITS(last.bits) ---//\n hold >>>= last_bits;\n bits -= last_bits;\n //---//\n state.back += last_bits;\n }\n //--- DROPBITS(here.bits) ---//\n hold >>>= here_bits;\n bits -= here_bits;\n //---//\n state.back += here_bits;\n state.length = here_val;\n if (here_op === 0) {\n //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?\n // \"inflate: literal '%c'\\n\" :\n // \"inflate: literal 0x%02x\\n\", here.val));\n state.mode = LIT;\n break;\n }\n if (here_op & 32) {\n //Tracevv((stderr, \"inflate: end of block\\n\"));\n state.back = -1;\n state.mode = TYPE;\n break;\n }\n if (here_op & 64) {\n strm.msg = 'invalid literal/length code';\n state.mode = BAD;\n break;\n }\n state.extra = here_op & 15;\n state.mode = LENEXT;\n /* falls through */\n case LENEXT:\n if (state.extra) {\n //=== NEEDBITS(state.extra);\n n = state.extra;\n while (bits < n) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;\n //--- DROPBITS(state.extra) ---//\n hold >>>= state.extra;\n bits -= state.extra;\n //---//\n state.back += state.extra;\n }\n //Tracevv((stderr, \"inflate: length %u\\n\", state.length));\n state.was = state.length;\n state.mode = DIST;\n /* falls through */\n case DIST:\n for (;;) {\n here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/\n here_bits = here >>> 24;\n here_op = (here >>> 16) & 0xff;\n here_val = here & 0xffff;\n\n if ((here_bits) <= bits) { break; }\n //--- PULLBYTE() ---//\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n //---//\n }\n if ((here_op & 0xf0) === 0) {\n last_bits = here_bits;\n last_op = here_op;\n last_val = here_val;\n for (;;) {\n here = state.distcode[last_val +\n ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)];\n here_bits = here >>> 24;\n here_op = (here >>> 16) & 0xff;\n here_val = here & 0xffff;\n\n if ((last_bits + here_bits) <= bits) { break; }\n //--- PULLBYTE() ---//\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n //---//\n }\n //--- DROPBITS(last.bits) ---//\n hold >>>= last_bits;\n bits -= last_bits;\n //---//\n state.back += last_bits;\n }\n //--- DROPBITS(here.bits) ---//\n hold >>>= here_bits;\n bits -= here_bits;\n //---//\n state.back += here_bits;\n if (here_op & 64) {\n strm.msg = 'invalid distance code';\n state.mode = BAD;\n break;\n }\n state.offset = here_val;\n state.extra = (here_op) & 15;\n state.mode = DISTEXT;\n /* falls through */\n case DISTEXT:\n if (state.extra) {\n //=== NEEDBITS(state.extra);\n n = state.extra;\n while (bits < n) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/;\n //--- DROPBITS(state.extra) ---//\n hold >>>= state.extra;\n bits -= state.extra;\n //---//\n state.back += state.extra;\n }\n//#ifdef INFLATE_STRICT\n if (state.offset > state.dmax) {\n strm.msg = 'invalid distance too far back';\n state.mode = BAD;\n break;\n }\n//#endif\n //Tracevv((stderr, \"inflate: distance %u\\n\", state.offset));\n state.mode = MATCH;\n /* falls through */\n case MATCH:\n if (left === 0) { break inf_leave; }\n copy = _out - left;\n if (state.offset > copy) { /* copy from window */\n copy = state.offset - copy;\n if (copy > state.whave) {\n if (state.sane) {\n strm.msg = 'invalid distance too far back';\n state.mode = BAD;\n break;\n }\n// (!) This block is disabled in zlib defailts,\n// don't enable it for binary compatibility\n//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR\n// Trace((stderr, \"inflate.c too far\\n\"));\n// copy -= state.whave;\n// if (copy > state.length) { copy = state.length; }\n// if (copy > left) { copy = left; }\n// left -= copy;\n// state.length -= copy;\n// do {\n// output[put++] = 0;\n// } while (--copy);\n// if (state.length === 0) { state.mode = LEN; }\n// break;\n//#endif\n }\n if (copy > state.wnext) {\n copy -= state.wnext;\n from = state.wsize - copy;\n }\n else {\n from = state.wnext - copy;\n }\n if (copy > state.length) { copy = state.length; }\n from_source = state.window;\n }\n else { /* copy from output */\n from_source = output;\n from = put - state.offset;\n copy = state.length;\n }\n if (copy > left) { copy = left; }\n left -= copy;\n state.length -= copy;\n do {\n output[put++] = from_source[from++];\n } while (--copy);\n if (state.length === 0) { state.mode = LEN; }\n break;\n case LIT:\n if (left === 0) { break inf_leave; }\n output[put++] = state.length;\n left--;\n state.mode = LEN;\n break;\n case CHECK:\n if (state.wrap) {\n //=== NEEDBITS(32);\n while (bits < 32) {\n if (have === 0) { break inf_leave; }\n have--;\n // Use '|' insdead of '+' to make sure that result is signed\n hold |= input[next++] << bits;\n bits += 8;\n }\n //===//\n _out -= left;\n strm.total_out += _out;\n state.total += _out;\n if (_out) {\n strm.adler = state.check =\n /*UPDATE(state.check, put - _out, _out);*/\n (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out));\n\n }\n _out = left;\n // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too\n if ((state.flags ? hold : zswap32(hold)) !== state.check) {\n strm.msg = 'incorrect data check';\n state.mode = BAD;\n break;\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n //Tracev((stderr, \"inflate: check matches trailer\\n\"));\n }\n state.mode = LENGTH;\n /* falls through */\n case LENGTH:\n if (state.wrap && state.flags) {\n //=== NEEDBITS(32);\n while (bits < 32) {\n if (have === 0) { break inf_leave; }\n have--;\n hold += input[next++] << bits;\n bits += 8;\n }\n //===//\n if (hold !== (state.total & 0xffffffff)) {\n strm.msg = 'incorrect length check';\n state.mode = BAD;\n break;\n }\n //=== INITBITS();\n hold = 0;\n bits = 0;\n //===//\n //Tracev((stderr, \"inflate: length matches trailer\\n\"));\n }\n state.mode = DONE;\n /* falls through */\n case DONE:\n ret = Z_STREAM_END;\n break inf_leave;\n case BAD:\n ret = Z_DATA_ERROR;\n break inf_leave;\n case MEM:\n return Z_MEM_ERROR;\n case SYNC:\n /* falls through */\n default:\n return Z_STREAM_ERROR;\n }\n }\n\n // inf_leave <- here is real place for \"goto inf_leave\", emulated via \"break inf_leave\"\n\n /*\n Return from inflate(), updating the total counts and the check value.\n If there was no progress during the inflate() call, return a buffer\n error. Call updatewindow() to create and/or update the window state.\n Note: a memory error from inflate() is non-recoverable.\n */\n\n //--- RESTORE() ---\n strm.next_out = put;\n strm.avail_out = left;\n strm.next_in = next;\n strm.avail_in = have;\n state.hold = hold;\n state.bits = bits;\n //---\n\n if (state.wsize || (_out !== strm.avail_out && state.mode < BAD &&\n (state.mode < CHECK || flush !== Z_FINISH))) {\n if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) {\n state.mode = MEM;\n return Z_MEM_ERROR;\n }\n }\n _in -= strm.avail_in;\n _out -= strm.avail_out;\n strm.total_in += _in;\n strm.total_out += _out;\n state.total += _out;\n if (state.wrap && _out) {\n strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/\n (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out));\n }\n strm.data_type = state.bits + (state.last ? 64 : 0) +\n (state.mode === TYPE ? 128 : 0) +\n (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0);\n if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) {\n ret = Z_BUF_ERROR;\n }\n return ret;\n}\n\nfunction inflateEnd(strm) {\n\n if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) {\n return Z_STREAM_ERROR;\n }\n\n var state = strm.state;\n if (state.window) {\n state.window = null;\n }\n strm.state = null;\n return Z_OK;\n}\n\nfunction inflateGetHeader(strm, head) {\n var state;\n\n /* check state */\n if (!strm || !strm.state) { return Z_STREAM_ERROR; }\n state = strm.state;\n if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; }\n\n /* save header structure */\n state.head = head;\n head.done = false;\n return Z_OK;\n}\n\nfunction inflateSetDictionary(strm, dictionary) {\n var dictLength = dictionary.length;\n\n var state;\n var dictid;\n var ret;\n\n /* check state */\n if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; }\n state = strm.state;\n\n if (state.wrap !== 0 && state.mode !== DICT) {\n return Z_STREAM_ERROR;\n }\n\n /* check for correct dictionary identifier */\n if (state.mode === DICT) {\n dictid = 1; /* adler32(0, null, 0)*/\n /* dictid = adler32(dictid, dictionary, dictLength); */\n dictid = adler32(dictid, dictionary, dictLength, 0);\n if (dictid !== state.check) {\n return Z_DATA_ERROR;\n }\n }\n /* copy dictionary to window using updatewindow(), which will amend the\n existing dictionary if appropriate */\n ret = updatewindow(strm, dictionary, dictLength, dictLength);\n if (ret) {\n state.mode = MEM;\n return Z_MEM_ERROR;\n }\n state.havedict = 1;\n // Tracev((stderr, \"inflate: dictionary set\\n\"));\n return Z_OK;\n}\n\n// String encode/decode helpers\n// 'use strict';\n\n\n// var utils = require('./common');\n\n\n// Quick check if we can use fast array to bin string conversion\n//\n// - apply(Array) can fail on Android 2.2\n// - apply(Uint8Array) can fail on iOS 5.1 Safary\n//\nvar STR_APPLY_OK = true;\nvar STR_APPLY_UIA_OK = true;\n\ntry { String.fromCharCode.apply(null, [ 0 ]); } catch (__) { STR_APPLY_OK = false; }\ntry { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APPLY_UIA_OK = false; }\n\n\n// Table with utf8 lengths (calculated by first byte of sequence)\n// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS,\n// because max possible codepoint is 0x10ffff\nvar _utf8len = new Uint8Array(256);\nfor (var q = 0; q < 256; q++) {\n _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1);\n}\n_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start\n\n\n// convert string to array (typed, when possible)\nfunction string2buf(str) {\n var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0;\n\n // count binary size\n for (m_pos = 0; m_pos < str_len; m_pos++) {\n c = str.charCodeAt(m_pos);\n if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {\n c2 = str.charCodeAt(m_pos + 1);\n if ((c2 & 0xfc00) === 0xdc00) {\n c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);\n m_pos++;\n }\n }\n buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4;\n }\n\n // allocate buffer\n buf = new Uint8Array(buf_len);\n\n // convert\n for (i = 0, m_pos = 0; i < buf_len; m_pos++) {\n c = str.charCodeAt(m_pos);\n if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) {\n c2 = str.charCodeAt(m_pos + 1);\n if ((c2 & 0xfc00) === 0xdc00) {\n c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00);\n m_pos++;\n }\n }\n if (c < 0x80) {\n /* one byte */\n buf[i++] = c;\n } else if (c < 0x800) {\n /* two bytes */\n buf[i++] = 0xC0 | (c >>> 6);\n buf[i++] = 0x80 | (c & 0x3f);\n } else if (c < 0x10000) {\n /* three bytes */\n buf[i++] = 0xE0 | (c >>> 12);\n buf[i++] = 0x80 | (c >>> 6 & 0x3f);\n buf[i++] = 0x80 | (c & 0x3f);\n } else {\n /* four bytes */\n buf[i++] = 0xf0 | (c >>> 18);\n buf[i++] = 0x80 | (c >>> 12 & 0x3f);\n buf[i++] = 0x80 | (c >>> 6 & 0x3f);\n buf[i++] = 0x80 | (c & 0x3f);\n }\n }\n\n return buf;\n}\n\n// Helper (used in 2 places)\nfunction _buf2binstring(buf, len) {\n // use fallback for big arrays to avoid stack overflow\n if (len < 65537) {\n if ((buf.subarray && STR_APPLY_UIA_OK) || (!buf.subarray && STR_APPLY_OK)) {\n return String.fromCharCode.apply(null, shrinkBuf(buf, len));\n }\n }\n\n var result = '';\n for (var i = 0; i < len; i++) {\n result += String.fromCharCode(buf[i]);\n }\n return result;\n}\n\n\n// Convert binary string (typed, when possible)\nfunction binstring2buf(str) {\n var buf = new Uint8Array(str.length);\n for (var i = 0, len = buf.length; i < len; i++) {\n buf[i] = str.charCodeAt(i);\n }\n return buf;\n}\n\n\n// convert array to string\nfunction buf2string(buf, max) {\n var i, out, c, c_len;\n var len = max || buf.length;\n\n // Reserve max possible length (2 words per char)\n // NB: by unknown reasons, Array is significantly faster for\n // String.fromCharCode.apply than Uint16Array.\n var utf16buf = new Array(len * 2);\n\n for (out = 0, i = 0; i < len;) {\n c = buf[i++];\n // quick process ascii\n if (c < 0x80) { utf16buf[out++] = c; continue; }\n\n c_len = _utf8len[c];\n // skip 5 & 6 byte codes\n if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; }\n\n // apply mask on first byte\n c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07;\n // join the rest\n while (c_len > 1 && i < len) {\n c = (c << 6) | (buf[i++] & 0x3f);\n c_len--;\n }\n\n // terminated by end of string?\n if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; }\n\n if (c < 0x10000) {\n utf16buf[out++] = c;\n } else {\n c -= 0x10000;\n utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff);\n utf16buf[out++] = 0xdc00 | (c & 0x3ff);\n }\n }\n\n return _buf2binstring(utf16buf, out);\n}\n\n\n// Calculate max possible position in utf8 buffer,\n// that will not break sequence. If that's not possible\n// - (very small limits) return max size as is.\n//\n// buf[] - utf8 bytes array\n// max - length limit (mandatory);\nfunction utf8border(buf, max) {\n var pos;\n\n max = max || buf.length;\n if (max > buf.length) { max = buf.length; }\n\n // go back from last position, until start of sequence found\n pos = max - 1;\n while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; }\n\n // Fuckup - very small and broken sequence,\n // return max, because we should return something anyway.\n if (pos < 0) { return max; }\n\n // If we came to start of buffer - that means vuffer is too small,\n // return max too.\n if (pos === 0) { return max; }\n\n return (pos + _utf8len[buf[pos]] > max) ? pos : max;\n}\n\n/* Allowed flush values; see deflate() and inflate() below for details */\nvar Z_NO_FLUSH = 0;\nvar Z_SYNC_FLUSH = 2;\nvar Z_FINISH$1 = 4;\n/* Return codes for the compression/decompression functions. Negative values\n * are errors, positive values are used for special but normal events.\n */\nvar Z_OK$1 = 0;\nvar Z_STREAM_END$1 = 1;\nvar Z_NEED_DICT$1 = 2;\n//export var Z_MEM_ERROR = -4;\nvar Z_BUF_ERROR$1 = -5;\n\n// 'use strict';\n\nvar messages = {\n 2: 'need dictionary', /* Z_NEED_DICT 2 */\n 1: 'stream end', /* Z_STREAM_END 1 */\n 0: '', /* Z_OK 0 */\n '-1': 'file error', /* Z_ERRNO (-1) */\n '-2': 'stream error', /* Z_STREAM_ERROR (-2) */\n '-3': 'data error', /* Z_DATA_ERROR (-3) */\n '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */\n '-5': 'buffer error', /* Z_BUF_ERROR (-5) */\n '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */\n};\n\n// 'use strict';\n\n\nfunction ZStream() {\n /* next input byte */\n this.input = null; // JS specific, because we have no pointers\n this.next_in = 0;\n /* number of bytes available at input */\n this.avail_in = 0;\n /* total number of input bytes read so far */\n this.total_in = 0;\n /* next output byte should be put there */\n this.output = null; // JS specific, because we have no pointers\n this.next_out = 0;\n /* remaining free space at output */\n this.avail_out = 0;\n /* total number of bytes output so far */\n this.total_out = 0;\n /* last error message, NULL if no error */\n this.msg = ''/*Z_NULL*/;\n /* not visible by applications */\n this.state = null;\n /* best guess about the data type: binary or text */\n this.data_type = 2/*Z_UNKNOWN*/;\n /* adler32 value of the uncompressed data */\n this.adler = 0;\n}\n\n// 'use strict';\n\n\nfunction GZheader() {\n /* true if compressed data believed to be text */\n this.text = 0;\n /* modification time */\n this.time = 0;\n /* extra flags (not used when writing a gzip file) */\n this.xflags = 0;\n /* operating system */\n this.os = 0;\n /* pointer to extra field or Z_NULL if none */\n this.extra = null;\n /* extra field length (valid if extra != Z_NULL) */\n this.extra_len = 0; // Actually, we don't need it in JS,\n // but leave for few code modifications\n\n //\n // Setup limits is not necessary because in js we should not preallocate memory\n // for inflate use constant limit in 65536 bytes\n //\n\n /* space at extra (only when reading header) */\n // this.extra_max = 0;\n /* pointer to zero-terminated file name or Z_NULL */\n this.name = '';\n /* space at name (only when reading header) */\n // this.name_max = 0;\n /* pointer to zero-terminated comment or Z_NULL */\n this.comment = '';\n /* space at comment (only when reading header) */\n // this.comm_max = 0;\n /* true if there was or will be a header crc */\n this.hcrc = 0;\n /* true when done reading gzip header (not used when writing a gzip file) */\n this.done = false;\n}\n\n// 'use strict';\n\n\n// var zlib_inflate = require('./zlib/inflate');\n// var utils = require('./utils/common');\n// var strings = require('./utils/strings');\n// var c = require('./zlib/constants');\n// var msg = require('./zlib/messages');\n// var ZStream = require('./zlib/zstream');\n// var GZheader = require('./zlib/gzheader');\n\nvar toString = Object.prototype.toString;\n\n/**\n * class Inflate\n *\n * Generic JS-style wrapper for zlib calls. If you don't need\n * streaming behaviour - use more simple functions: [[inflate]]\n * and [[inflateRaw]].\n **/\n\n/* internal\n * inflate.chunks -> Array\n *\n * Chunks of output data, if [[Inflate#onData]] not overriden.\n **/\n\n/**\n * Inflate.result -> Uint8Array|Array|String\n *\n * Uncompressed result, generated by default [[Inflate#onData]]\n * and [[Inflate#onEnd]] handlers. Filled after you push last chunk\n * (call [[Inflate#push]] with `Z_FINISH` / `true` param) or if you\n * push a chunk with explicit flush (call [[Inflate#push]] with\n * `Z_SYNC_FLUSH` param).\n **/\n\n/**\n * Inflate.err -> Number\n *\n * Error code after inflate finished. 0 (Z_OK) on success.\n * Should be checked if broken data possible.\n **/\n\n/**\n * Inflate.msg -> String\n *\n * Error message, if [[Inflate.err]] != 0\n **/\n\n\n/**\n * new Inflate(options)\n * - options (Object): zlib inflate options.\n *\n * Creates new inflator instance with specified params. Throws exception\n * on bad params. Supported options:\n *\n * - `windowBits`\n * - `dictionary`\n *\n * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)\n * for more information on these.\n *\n * Additional options, for internal needs:\n *\n * - `chunkSize` - size of generated data chunks (16K by default)\n * - `raw` (Boolean) - do raw inflate\n * - `to` (String) - if equal to 'string', then result will be converted\n * from utf8 to utf16 (javascript) string. When string output requested,\n * chunk length can differ from `chunkSize`, depending on content.\n *\n * By default, when no options set, autodetect deflate/gzip data format via\n * wrapper header.\n *\n * ##### Example:\n *\n * ```javascript\n * var pako = require('pako')\n * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9])\n * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]);\n *\n * var inflate = new pako.Inflate({ level: 3});\n *\n * inflate.push(chunk1, false);\n * inflate.push(chunk2, true); // true -> last chunk\n *\n * if (inflate.err) { throw new Error(inflate.err); }\n *\n * console.log(inflate.result);\n * ```\n **/\nfunction Inflate(options) {\n if (!(this instanceof Inflate)) return new Inflate(options);\n\n this.options = assign({\n chunkSize: 16384,\n windowBits: 0,\n to: ''\n }, options || {});\n\n var opt = this.options;\n\n // Force window size for `raw` data, if not set directly,\n // because we have no header for autodetect.\n if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) {\n opt.windowBits = -opt.windowBits;\n if (opt.windowBits === 0) { opt.windowBits = -15; }\n }\n\n // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate\n if ((opt.windowBits >= 0) && (opt.windowBits < 16) &&\n !(options && options.windowBits)) {\n opt.windowBits += 32;\n }\n\n // Gzip header has no info about windows size, we can do autodetect only\n // for deflate. So, if window size not set, force it to max when gzip possible\n if ((opt.windowBits > 15) && (opt.windowBits < 48)) {\n // bit 3 (16) -> gzipped data\n // bit 4 (32) -> autodetect gzip/deflate\n if ((opt.windowBits & 15) === 0) {\n opt.windowBits |= 15;\n }\n }\n\n this.err = 0; // error code, if happens (0 = Z_OK)\n this.msg = ''; // error message\n this.ended = false; // used to avoid multiple onEnd() calls\n this.chunks = []; // chunks of compressed data\n\n this.strm = new ZStream();\n this.strm.avail_out = 0;\n\n var status = inflateInit2(\n this.strm,\n opt.windowBits\n );\n\n if (status !== Z_OK$1) {\n throw new Error(messages[status]);\n }\n\n this.header = new GZheader();\n\n inflateGetHeader(this.strm, this.header);\n}\n\n/**\n * Inflate#push(data[, mode]) -> Boolean\n * - data (Uint8Array|Array|ArrayBuffer|String): input data\n * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes.\n * See constants. Skipped or `false` means Z_NO_FLUSH, `true` meansh Z_FINISH.\n *\n * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with\n * new output chunks. Returns `true` on success. The last data block must have\n * mode Z_FINISH (or `true`). That will flush internal pending buffers and call\n * [[Inflate#onEnd]]. For interim explicit flushes (without ending the stream) you\n * can use mode Z_SYNC_FLUSH, keeping the decompression context.\n *\n * On fail call [[Inflate#onEnd]] with error code and return false.\n *\n * We strongly recommend to use `Uint8Array` on input for best speed (output\n * format is detected automatically). Also, don't skip last param and always\n * use the same type in your code (boolean or number). That will improve JS speed.\n *\n * For regular `Array`-s make sure all elements are [0..255].\n *\n * ##### Example\n *\n * ```javascript\n * push(chunk, false); // push one of data chunks\n * ...\n * push(chunk, true); // push last chunk\n * ```\n **/\nInflate.prototype.push = function (data, mode) {\n var strm = this.strm;\n var chunkSize = this.options.chunkSize;\n var dictionary = this.options.dictionary;\n var status, _mode;\n var next_out_utf8, tail, utf8str;\n var dict;\n\n // Flag to properly process Z_BUF_ERROR on testing inflate call\n // when we check that all output data was flushed.\n var allowBufError = false;\n\n if (this.ended) { return false; }\n _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH$1 : Z_NO_FLUSH);\n\n // Convert data if needed\n if (typeof data === 'string') {\n // Only binary strings can be decompressed on practice\n strm.input = binstring2buf(data);\n } else if (toString.call(data) === '[object ArrayBuffer]') {\n strm.input = new Uint8Array(data);\n } else {\n strm.input = data;\n }\n\n strm.next_in = 0;\n strm.avail_in = strm.input.length;\n\n do {\n if (strm.avail_out === 0) {\n strm.output = new Uint8Array(chunkSize);\n strm.next_out = 0;\n strm.avail_out = chunkSize;\n }\n\n status = inflate(strm, Z_NO_FLUSH); /* no bad return value */\n\n if (status === Z_NEED_DICT$1 && dictionary) {\n // Convert data if needed\n if (typeof dictionary === 'string') {\n dict = string2buf(dictionary);\n } else if (toString.call(dictionary) === '[object ArrayBuffer]') {\n dict = new Uint8Array(dictionary);\n } else {\n dict = dictionary;\n }\n\n status = inflateSetDictionary(this.strm, dict);\n\n }\n\n if (status === Z_BUF_ERROR$1 && allowBufError === true) {\n status = Z_OK$1;\n allowBufError = false;\n }\n\n if (status !== Z_STREAM_END$1 && status !== Z_OK$1) {\n this.onEnd(status);\n this.ended = true;\n return false;\n }\n\n if (strm.next_out) {\n if (strm.avail_out === 0 || status === Z_STREAM_END$1 || (strm.avail_in === 0 && (_mode === Z_FINISH$1 || _mode === Z_SYNC_FLUSH))) {\n\n if (this.options.to === 'string') {\n\n next_out_utf8 = utf8border(strm.output, strm.next_out);\n\n tail = strm.next_out - next_out_utf8;\n utf8str = buf2string(strm.output, next_out_utf8);\n\n // move tail\n strm.next_out = tail;\n strm.avail_out = chunkSize - tail;\n if (tail) { arraySet(strm.output, strm.output, next_out_utf8, tail, 0); }\n\n this.onData(utf8str);\n\n } else {\n this.onData(shrinkBuf(strm.output, strm.next_out));\n }\n }\n }\n\n // When no more input data, we should check that internal inflate buffers\n // are flushed. The only way to do it when avail_out = 0 - run one more\n // inflate pass. But if output data not exists, inflate return Z_BUF_ERROR.\n // Here we set flag to process this error properly.\n //\n // NOTE. Deflate does not return error in this case and does not needs such\n // logic.\n if (strm.avail_in === 0 && strm.avail_out === 0) {\n allowBufError = true;\n }\n\n } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END$1);\n\n if (status === Z_STREAM_END$1) {\n _mode = Z_FINISH$1;\n }\n\n // Finalize on the last chunk.\n if (_mode === Z_FINISH$1) {\n status = inflateEnd(this.strm);\n this.onEnd(status);\n this.ended = true;\n return status === Z_OK$1;\n }\n\n // callback interim results if Z_SYNC_FLUSH.\n if (_mode === Z_SYNC_FLUSH) {\n this.onEnd(Z_OK$1);\n strm.avail_out = 0;\n return true;\n }\n\n return true;\n};\n\n\n/**\n * Inflate#onData(chunk) -> Void\n * - chunk (Uint8Array|Array|String): ouput data. Type of array depends\n * on js engine support. When string output requested, each chunk\n * will be string.\n *\n * By default, stores data blocks in `chunks[]` property and glue\n * those in `onEnd`. Override this handler, if you need another behaviour.\n **/\nInflate.prototype.onData = function (chunk) {\n this.chunks.push(chunk);\n};\n\n\n/**\n * Inflate#onEnd(status) -> Void\n * - status (Number): inflate status. 0 (Z_OK) on success,\n * other if not.\n *\n * Called either after you tell inflate that the input stream is\n * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH)\n * or if an error happened. By default - join collected chunks,\n * free memory and fill `results` / `err` properties.\n **/\nInflate.prototype.onEnd = function (status) {\n // On success - join\n if (status === Z_OK$1) {\n if (this.options.to === 'string') {\n // Glue & convert here, until we teach pako to send\n // utf8 alligned strings to onData\n this.result = this.chunks.join('');\n } else {\n this.result = flattenChunks(this.chunks);\n }\n }\n this.chunks = [];\n this.err = status;\n this.msg = this.strm.msg;\n};\n\n\n/**\n * inflate(data[, options]) -> Uint8Array|Array|String\n * - data (Uint8Array|Array|String): input data to decompress.\n * - options (Object): zlib inflate options.\n *\n * Decompress `data` with inflate/ungzip and `options`. Autodetect\n * format via wrapper header by default. That's why we don't provide\n * separate `ungzip` method.\n *\n * Supported options are:\n *\n * - windowBits\n *\n * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced)\n * for more information.\n *\n * Sugar (options):\n *\n * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify\n * negative windowBits implicitly.\n * - `to` (String) - if equal to 'string', then result will be converted\n * from utf8 to utf16 (javascript) string. When string output requested,\n * chunk length can differ from `chunkSize`, depending on content.\n *\n *\n * ##### Example:\n *\n * ```javascript\n * var pako = require('pako')\n * , input = pako.deflate([1,2,3,4,5,6,7,8,9])\n * , output;\n *\n * try {\n * output = pako.inflate(input);\n * } catch (err)\n * console.log(err);\n * }\n * ```\n **/\nfunction doInflate(input, options) {\n var inflator = new Inflate(options);\n\n inflator.push(input, true);\n\n // That will never happens, if you don't cheat with options :)\n if (inflator.err) { throw inflator.msg; }\n\n return inflator.result;\n}\n\nexport { doInflate as ungzip };","/**\n * @file Validation Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, ParserRegistry } from '../globals'\nimport XmlParser, { XmlParserParameters } from './xml-parser'\nimport Validation from '../structure/validation'\nimport Streamer from '../streamer/streamer';\n\nclass ValidationParser extends XmlParser {\n constructor (streamer: Streamer, params?: Partial) {\n const p = params || {}\n\n super(streamer, p)\n\n this.useDomParser = true\n this.validation = new Validation(this.name, this.path)\n }\n\n get __objName () { return 'validation' }\n get isXml () { return true }\n\n _parse () {\n super._parse()\n\n if (Debug) Log.time('ValidationParser._parse ' + this.name)\n\n this.validation.fromXml(this.xml.data)\n\n if (Debug) Log.timeEnd('ValidationParser._parse ' + this.name)\n }\n}\n\nParserRegistry.add('validation', ValidationParser)\n\nexport default ValidationParser\n","/**\n * @file Gzip Decompressor\n * @author Alexander Rose \n * @private\n */\n\nimport { ungzip } from '../../lib/pako_inflate.es6'\n\nimport { DecompressorRegistry } from '../globals'\n\nfunction gzipDecompress (data: ArrayBuffer|Uint8Array) {\n let decompressedData\n\n if (data instanceof ArrayBuffer) {\n data = new Uint8Array(data)\n }\n\n try {\n decompressedData = ungzip(data as Uint8Array)\n } catch (e) {\n decompressedData = data // assume it is already uncompressed\n }\n\n return decompressedData\n}\n\nDecompressorRegistry.add('gz', gzipDecompress)\n","/**\n * @file Datasource\n * @author Alexander Rose \n * @private\n */\n\n/**\n * Datasource base class\n * @interface\n */\nabstract class Datasource {\n /**\n * Get full url\n * @abstract\n * @param {String} path - datasource string\n * @return {String} - url\n */\n abstract getUrl (path: string): string\n\n /**\n * Get file extension\n * @abstract\n * @param {String} path - datasource string\n * @return {String} - extension\n */\n abstract getExt (path: string): string\n}\n\nexport default Datasource\n","/**\n * @file RCSB Datasource\n * @author Alexander Rose \n * @private\n */\n\nimport { Log, DatasourceRegistry } from '../globals'\nimport { getProtocol } from '../utils'\nimport { getFileInfo } from '../loader/loader-utils'\nimport Datasource from './datasource'\n\nconst baseUrl = '//files.rcsb.org/download/'\nconst mmtfBaseUrl = '//mmtf.rcsb.org/v1.0/'\nconst mmtfFullUrl = mmtfBaseUrl + 'full/'\nconst mmtfReducedUrl = mmtfBaseUrl + 'reduced/'\n\nclass RcsbDatasource extends Datasource {\n getUrl (src: string) {\n // valid path are\n // XXXX.pdb, XXXX.pdb.gz, XXXX.cif, XXXX.cif.gz, XXXX.mmtf, XXXX.bb.mmtf\n // XXXX defaults to XXXX.cif\n const info = getFileInfo(src)\n const pdbid = info.name.substr(0, 4)\n let url\n if ([ 'pdb', 'cif' ].includes(info.ext) &&\n (info.compressed === false || info.compressed === 'gz')\n ) {\n url = baseUrl + info.path\n } else if (info.ext === 'mmtf') {\n if (info.base.endsWith('.bb')) {\n url = mmtfReducedUrl + pdbid\n } else {\n url = mmtfFullUrl + pdbid\n }\n } else if (!info.ext) {\n url = mmtfFullUrl + pdbid\n } else {\n Log.warn('unsupported ext', info.ext)\n url = mmtfFullUrl + pdbid\n }\n return getProtocol() + url\n }\n\n getExt (src: string) {\n const ext = getFileInfo(src).ext\n return ext ? ext : 'mmtf'\n }\n}\n\nDatasourceRegistry.add('rcsb', new RcsbDatasource())\n\nexport default RcsbDatasource\n","/**\n * @file PubChem Datasource\n * @author Alexander Rose \n * @private\n */\n\nimport { Log, DatasourceRegistry } from '../globals'\nimport { getProtocol } from '../utils'\nimport { getFileInfo } from '../loader/loader-utils'\nimport Datasource from './datasource'\n\nconst baseUrl = '//pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/'\nconst suffixUrl = '/SDF?record_type=3d'\n\nclass PubchemDatasource extends Datasource {\n getUrl (src: string) {\n const info = getFileInfo(src)\n const cid = info.name\n let url\n if (!info.ext || info.ext === 'sdf') {\n url = baseUrl + cid + suffixUrl\n } else {\n Log.warn('unsupported ext', info.ext)\n url = baseUrl + cid + suffixUrl\n }\n return getProtocol() + url\n }\n\n getExt (src: string) {\n const ext = getFileInfo(src).ext\n return ext ? ext : 'sdf'\n }\n}\n\nDatasourceRegistry.add('pubchem', new PubchemDatasource())\n\nexport default PubchemDatasource\n","/**\n * @file Pass Through Datasource\n * @author Alexander Rose \n * @private\n */\n\nimport { DatasourceRegistry } from '../globals'\nimport { getFileInfo } from '../loader/loader-utils'\nimport Datasource from './datasource'\n\nclass PassThroughDatasource extends Datasource {\n getUrl (path: string) {\n return path\n }\n\n getExt (path: string) {\n return getFileInfo(path).ext\n }\n}\n\nDatasourceRegistry.add('ftp', new PassThroughDatasource())\nDatasourceRegistry.add('http', new PassThroughDatasource())\nDatasourceRegistry.add('https', new PassThroughDatasource())\n\nexport default PassThroughDatasource\n","/**\r\n * @file Alphafold Datasource\r\n * @author Fredric Johansson \r\n * @private\r\n */\r\n\r\nimport { Log, DatasourceRegistry } from '../globals'\r\nimport { getProtocol } from '../utils'\r\nimport { getFileInfo } from '../loader/loader-utils'\r\nimport Datasource from './datasource'\r\n\r\nconst baseUrl = '//alphafold.ebi.ac.uk/files/AF-'\r\nconst suffixURL = '-F1-model_v2.pdb'\r\n\r\nclass AlphafoldDatasource extends Datasource {\r\n getUrl (src: string) {\r\n const info = getFileInfo(src)\r\n const uniprotid = info.name\r\n let url\r\n if (!info.ext || info.ext === 'pdb') {\r\n url = baseUrl + uniprotid + suffixURL\r\n } else {\r\n Log.warn('unsupported AF ext', info.ext)\r\n url = baseUrl + uniprotid + suffixURL\r\n }\r\n return getProtocol() + url\r\n }\r\n\r\n getExt (src: string) {\r\n const ext = getFileInfo(src).ext\r\n return ext ? ext : 'pdb'\r\n }\r\n}\r\n\r\nDatasourceRegistry.add('alphafold', new AlphafoldDatasource())\r\n\r\nexport default AlphafoldDatasource\r\n","/**\n * @file Static Datasource\n * @author Alexander Rose \n * @private\n */\n\nimport { getAbsolutePath } from '../utils'\nimport { getFileInfo } from '../loader/loader-utils'\nimport Datasource from './datasource'\n\nconst reProtocol = /^((http|https|ftp):)*\\/\\//\n\nclass StaticDatasource extends Datasource {\n baseUrl: string\n\n constructor (baseUrl: string = '') {\n super()\n this.baseUrl = baseUrl\n }\n\n getUrl (src: string) {\n const info = getFileInfo(src)\n let url = this.baseUrl + info.path\n if (!reProtocol.test(this.baseUrl)) {\n url = getAbsolutePath(url)\n }\n return url\n }\n\n getExt (src: string) {\n return getFileInfo(src).ext\n }\n}\n\nexport default StaticDatasource\n","/**\n * @file MDsrv Datasource\n * @author Alexander Rose \n * @private\n */\n\nimport { autoLoad, getFileInfo } from '../loader/loader-utils'\nimport Datasource from './datasource'\n\nclass MdsrvDatasource extends Datasource {\n baseUrl: string\n\n constructor (baseUrl: string = '') {\n super()\n this.baseUrl = baseUrl\n }\n\n getListing (path: string = '') {\n let url = `${this.baseUrl}dir/${path}`\n if (url[url.length - 1] !== '/') url += '/'\n return autoLoad(url, {\n ext: 'json'\n }).then((jsonData: any) => ({\n path: path,\n data: jsonData.data\n }))\n }\n\n getUrl (src: string) {\n const info = getFileInfo(src)\n return `${this.baseUrl}file/${info.path}${info.query}`\n }\n\n getCountUrl (src: string) {\n const info = getFileInfo(src)\n return `${this.baseUrl}traj/numframes/${info.path}${info.query}`\n }\n\n getFrameUrl (src: string, frameIndex: number|string) {\n const info = getFileInfo(src)\n return `${this.baseUrl}traj/frame/${frameIndex}/${info.path}${info.query}`\n }\n\n getFrameParams (src: string, atomIndices: (number|string)[]) {\n return `atomIndices=${atomIndices.join(';')}`\n }\n\n getPathUrl (src: string, atomIndex: number|string) {\n const info = getFileInfo(src)\n return `${this.baseUrl}traj/path/${atomIndex}/${info.path}${info.query}`\n }\n\n getExt (src: string) {\n return getFileInfo(src).ext\n }\n}\n\nexport default MdsrvDatasource\n","/**\n * @file UI Parameters\n * @author Alexander Rose \n */\n\nimport { StageParameters } from '../stage/stage'\nimport { MouseActionPresets } from '../controls/mouse-actions'\n\nexport type BooleanParam = { type: 'boolean' }\nfunction BooleanParam () { return { type: 'boolean' } as BooleanParam }\n\nexport type ColorParam = { type: 'color' }\nfunction ColorParam () { return { type: 'color' } as ColorParam }\n\nexport type IntegerParam = { type: 'integer', max: number, min: number }\nfunction IntegerParam (max: number, min: number) {\n return { type: 'integer', max, min } as IntegerParam\n}\n\nexport type NumberParam = { type: 'number', precision: number, max: number, min: number }\nfunction NumberParam (precision: number, max: number, min: number) {\n return { type: 'number', precision, max, min } as NumberParam\n}\n\nexport type RangeParam = { type: 'range', step: number, max: number, min: number }\nfunction RangeParam (step: number, max: number, min: number) {\n return { type: 'range', step, max, min } as RangeParam\n}\n\nexport type SelectParam = { type: 'select', options: { [k: string]: string } }\nfunction SelectParam (...options: string[]) {\n return { type: 'select', options: options.reduce((o, k) => ({ ...o, [k]: k}), {}) } as SelectParam\n}\n\nexport type ParamType = BooleanParam|ColorParam|IntegerParam|NumberParam|RangeParam|SelectParam\n\nexport const UIStageParameters: { [k in keyof StageParameters]: ParamType } = {\n backgroundColor: ColorParam(),\n quality: SelectParam('auto', 'low', 'medium', 'high'),\n sampleLevel: RangeParam(1, 5, -1),\n impostor: BooleanParam(),\n workerDefault: BooleanParam(),\n rotateSpeed: NumberParam(1, 10, 0),\n zoomSpeed: NumberParam(1, 10, 0),\n panSpeed: NumberParam(1, 10, 0),\n clipNear: RangeParam(1, 100, 0),\n clipFar: RangeParam(1, 100, 0),\n clipDist: IntegerParam(200, 0),\n clipMode: SelectParam('scene', 'camera'),\n clipScale: SelectParam('relative', 'absolute'),\n fogNear: RangeParam(1, 100, 0),\n fogFar: RangeParam(1, 100, 0),\n cameraType: SelectParam('perspective', 'orthographic', 'stereo'),\n cameraEyeSep: NumberParam(3, 1.0, 0.01),\n cameraFov: RangeParam(1, 120, 15),\n lightColor: ColorParam(),\n lightIntensity: NumberParam(2, 10, 0),\n ambientColor: ColorParam(),\n ambientIntensity: NumberParam(2, 10, 0),\n hoverTimeout: IntegerParam(10000, -1),\n tooltip: BooleanParam(),\n mousePreset: SelectParam(...Object.keys(MouseActionPresets))\n}\n","/**\n * @file Version\n * @private\n * @author Alexander Rose \n */\n\nimport * as data from '../package.json'\n\n/**\n * Version name\n * @type {String}\n */\nconst Version = (data as any).version as string\n\nexport default Version\n"],"names":["getQuery","id","window","m","RegExp","exec","location","search","decodeURIComponent","defaults","value","defaultValue","undefined","createParams","params","defaultParams","o","Object","assign","k","updateParams","newParams","flatten","array","ret","i","length","Array","isArray","push","getProtocol","protocol","match","getBrowser","ua","navigator","userAgent","test","openUrl","url","open","href","download","data","downloadName","isSafari","isChromeIos","a","document","createElement","str","replace","msSaveOrOpenBlob","FileReader","Blob","reader","onloadend","result","readAsDataURL","objectUrlCreated","URL","createObjectURL","style","display","body","appendChild","target","click","removeChild","revokeObjectURL","throttle","func","wait","options","context","args","timeout","previous","later","leading","Date","now","apply","remaining","this","arguments","clearTimeout","trailing","setTimeout","lexicographicCompare","elm1","elm2","binarySearchIndexOf","element","compareFunction","low","high","mid","cmp","rangeInSortedArray","min","max","indexLeft","leftRange","binarySearchForLeftRange","indexRight","rightRange","binarySearchForRightRange","uniqueArray","sort","filter","index","sorted","uint8ToString","u8a","chunkSize","c","String","fromCharCode","subarray","join","getTypedArray","arrayType","arraySize","Int8Array","Int16Array","Int32Array","Uint8Array","Uint16Array","Uint32Array","Float32Array","Error","getUintArray","sizeOrArray","maxUint","ensureBuffer","buffer","ArrayBuffer","_ensureClassFromArray","constructor","fromArray","ensureVector3","v","Vector3","ensureMatrix4","Matrix4","ensureQuaternion","q","Quaternion","ensureFloat32Array","arg","toLowerCaseString","toString","toLowerCase","Registry","name","_dict","add","key","get","names","keys","degToRad","deg","chars","split","uuid","generateUUID","r","rnd","Math","random","clamp","lerp","start","stop","alpha","spline","p0","p1","p2","p3","t","tension","v0","v1","t2","smoothstep","x","normalize","colorSpace","ScaleDefaultParameters","scale","mode","domain","reverse","tmpColor","Color","manageColor","_target","_name","descriptor","originalMethod","fromTo","bind","set","convertSRGBToLinear","getHex","Colormaker","parameters","structure","atomProxy","getAtomProxy","getScale","p","slice","chroma","out","colorToArray","color","offset","atomColorToArray","atom","atomColor","bondColor","bond","atomIndex1","atomIndex2","bondColorToArray","volumeColorToArray","volumeColor","positionColorToArray","coords","positionColor","kwd","SelectAllKeyword","SelectNoneKeyword","AtomOnlyKeywords","BACKBONE","SIDECHAIN","BONDED","RING","AROMATICRING","METAL","POLARH","ChainKeywords","POLYMER","WATER","SmallResname","NucleophilicResname","HydrophobicResname","AromaticResname","AmideResname","AcidicResname","BasicResname","ChargedResname","PolarResname","NonpolarResname","CyclicResname","AliphaticResname","atomTestFn","s","atomname","altloc","atomindex","keyword","inscode","resname","sstruc","resno","chainname","model","isBackbone","isSidechain","isBonded","isRing","isAromatic","HETERO","isHetero","PROTEIN","isProtein","NUCLEIC","isNucleic","RNA","isRna","DNA","isDna","isPolymer","isWater","HELIX","isHelix","SHEET","isSheet","TURN","isTurn","ION","isIon","SACCHARIDE","isSaccharide","isMetal","isPolarHydrogen","includes","modelIndex","residueTestFn","atomOffset","atomEnd","chainTestFn","entity","modelTestFn","makeTest","selection","fn","error","rules","n","negate","f","subTests","hasOwnProperty","and","operator","na","ALL","NONE","filtered","fs","makeAtomTest","atomOnly","filteredSelection","makeResidueTest","residueOnly","makeChainTest","chainOnly","makeModelTest","modelOnly","Selection","string","signals","stringChanged","Signal","setString","type","silent","retSelection","newSelection","oldSelection","selectionStack","trim","charAt","substr","chunks","createNewContext","getPrevContext","pop","pushRule","rule","not","cu","toUpperCase","lastRule","indexOf","indexList","map","parseInt","b","console","resnameList","isNaN","sele","substring","chain","negate2","resi","resiSingle","resiRange","parseSele","e","message","residueTest","chainTest","modelTest","atomOnlyTest","residueOnlyTest","chainOnlyTest","modelOnlyTest","dispatch","isAllSelection","isNoneSelection","SelectionColormaker","super","colormakerList","selectionList","dataList","forEach","scheme","ColormakerRegistry","hasScheme","getScheme","ColormakerScales","OrRd","PuBu","BuPu","Oranges","BuGn","YlOrBr","YlGn","Reds","RdPu","Greens","YlGnBu","Purples","GnBu","Greys","YlOrRd","PuRd","Blues","PuBuGn","Viridis","Spectral","RdYlGn","RdBu","PiYG","PRGn","RdYlBu","BrBG","RdGy","PuOr","Set1","Set2","Set3","Dark2","Paired","Pastel1","Pastel2","Accent","rainbow","rwb","ColormakerModes","rgb","hsv","hsl","hsi","lab","hcl","getWorkerDeps","vars","deps","sym","__deps","prototype","makeWorkerString","onmessage","__name","postId","__postId","self","callback","aMessage","transferList","postMessage","makeWorkerBlob","Browser","SupportsPassiveEventHandler","opts","defineProperty","addEventListener","Mobile","orientation","SupportsReadPixelsFloat","setSupportsReadPixelsFloat","ExtensionFragDepth","setExtensionFragDepth","Log","log","Function","call","info","warn","time","timeEnd","MeasurementDefaultParams","labelColor","labelAttachment","labelSize","labelZOffset","labelYOffset","labelBorder","labelBorderColor","labelBorderWidth","lineOpacity","linewidth","opacity","labelUnit","arcVisible","planeVisible","setMeasurementDefaultParams","Debug","setDebug","ScriptExtensions","WorkerRegistry","activeWorkerCount","_funcDict","_depsDict","_blobDict","schemes","userSchemes","SchemeClass","getSchemes","types","getScales","getModes","addScheme","label","_createScheme","_addUserScheme","removeScheme","addSelectionScheme","DatasourceRegistry","RepresentationRegistry","ParserRegistry","__hasObjName","objName","parser","__objName","isTrajectory","isStructure","isVolume","isSurface","isBinary","isXml","isJson","getTrajectoryExtensions","getStructureExtensions","getVolumeExtensions","getSurfaceExtensions","ShaderRegistry","DecompressorRegistry","ComponentRegistry","BufferRegistry","PickerRegistry","ListingDatasource","TrajectoryDatasource","setListingDatasource","setTrajectoryDatasource","Streamer","src","newline","__pointer","__partialLine","compressed","binary","json","xml","read","_read","then","decompressFn","_chunk","end","chunk","peekLines","charCodeAt","count","chunkToLines","lines","chunkCount","floor","asText","partialLine","isLast","idx","lastIndexOf","str2","concat","nextChunk","nextChunkOfLines","d","eachChunk","round","eachChunkOfLines","chunkNo","dispose","FileStreamer","Promise","resolve","reject","file","onload","event","onerror","readAsArrayBuffer","readAsText","NetworkStreamer","xhr","XMLHttpRequest","status","response","statusText","responseType","send","Loader","ext","dir","path","streamerParams","File","streamer","ParserLoader","parserParams","voxelSize","firstModelOnly","asTrajectory","cAlphaOnly","delimiter","comment","columnNames","inferBonds","load","parse","Script","functionBody","elementAdded","elementRemoved","nameChanged","run","stage","ScriptLoader","getFileInfo","compressedExtList","queryIndex","query","base","nameSplit","protocolMatch","getDataInfo","datasource","getUrl","getExt","autoLoad","loader","Writer","getBlob","getData","mimeType","defaultName","defaultExt","PdbWriter","renumberSerial","remarks","ensureArray","_records","_writeRecords","_writeTitle","_writeRemarks","_writeAtoms","sprintf","trajectory","frame","ia","im","charge","chargeSign","hasModels","modelStore","eachModel","eachAtom","formatString","hetero","serial","formalCharge","abs","toPrecision","y","z","occupancy","bfactor","getSelection","getString","SdfWriter","idString","titleString","title","countsString","atomCount","bondCount","chargeLines","pairs","ap","nCharges","j","formatAtom","line","formatBond","bp","bondOrder","_writeHeader","_writeCTab","_writeFooter","eachBond","charArray","IOBuffer","_mark","_marks","littleEndian","dataIsGiven","byteLength","dvOffset","byteOffset","_lastWrittenByte","_data","DataView","available","isLittleEndian","setLittleEndian","isBigEndian","setBigEndian","skip","seek","mark","reset","pushMark","popMark","rewind","ensureAvailable","newLength","newArray","readBoolean","readUint8","readInt8","getInt8","getUint8","readByte","readBytes","bytes","readInt16","getInt16","readUint16","getUint16","readInt32","getInt32","readUint32","getUint32","readFloat32","getFloat32","readFloat64","getFloat64","readChar","readChars","writeBoolean","writeUint8","writeInt8","setInt8","_updateLastWrittenByte","setUint8","writeByte","writeBytes","writeInt16","setInt16","writeUint16","setUint16","writeInt32","setInt32","writeUint32","setUint32","writeFloat32","setFloat32","writeFloat64","setFloat64","writeChar","writeChars","toArray","StlWriter","surface","triangles","output","vector","vectorNorm1","vectorNorm2","vectorNorm3","indices","normal","addVectors","position","Counter","countChanged","signalsWrapper","clear","change","delta","increment","decrement","listen","counter","unlisten","has","remove","onZeroOnce","Stats","updated","maxDuration","Infinity","minDuration","avgDuration","lastDuration","prevFpsTime","lastFps","lastFrames","frames","begin","update","startTime","currentTime","performance","reInclude","shaderCache","getShader","defines","hash","definesText","getDefines","shaderText","ShaderChunk","WebGLRenderingContext","wrcp","_getShaderParameter","getShaderParameter","_getShaderInfoLog","getShaderInfoLog","_getProgramParameter","getProgramParameter","program","pname","LINK_STATUS","_getProgramInfoLog","getProgramInfoLog","JitterVectors","offsetList","TiledRenderer","renderer","camera","viewer","canvas","_viewer","_factor","factor","_antialias","antialias","_onProgress","onProgress","_onFinish","onFinish","_n","_width","width","_height","height","_ctx","getContext","_viewerSampleLevel","sampleLevel","setSampling","_renderTile","offsetX","offsetY","setViewOffset","render","w","h","drawImage","domElement","ceil","_finalize","view","renderAsync","TwoPI","PI","RAD2DEG","circularMean","stride","cosMean","sinMean","angle","cos","sin","atan2","calculateCenterArray","array1","array2","center","calculateDirectionArray","direction","uniformArray","optionalTarget","uniformArray3","serialArray","serialBlockArray","replicateArrayEntries","repArr","copyArray","dst","srcOffset","dstOffset","copyWithin","arrayMax","il","arrayMin","arraySum","sum","arrayMean","ImageDefaultParameters","transparent","makeImage","originalClearAlpha","getClearAlpha","backgroundColor","getClearColor","setLineWidthAndPixelSize","invert","scene","traverse","material","uniforms","size","__seen","trimCanvas","bg","g","canvasHeight","canvasWidth","pixels","getImageData","doBreak","off","topY","topX","bottomY","bottomX","trimedCanvas","_trimCanvas","finished","tiledRenderer","toBlob","blob","setClearAlpha","requestRender","vertex","matrix","modelViewProjectionMatrix","resolution","Vector2","projectionMatrixInverse","projectionMatrixTranspose","updateCameraUniforms","group","getInverse","projectionMatrix","copy","transpose","u","loadShader","gl","shaderSource","shaderType","shader","createShader","compileShader","COMPILE_STATUS","deleteShader","getExtension","TextureTestTexCoords","testTextureSupport","vertShader","VERTEX_SHADER","fragShader","FRAGMENT_SHADER","shaders","attribs","locations","createProgram","attachShader","attrib","bindAttribLocation","linkProgram","deleteProgram","useProgram","positionLocation","getAttribLocation","colorLoc","getUniformLocation","positionBuffer","createBuffer","bindBuffer","ARRAY_BUFFER","bufferData","STATIC_DRAW","enableVertexAttribArray","vertexAttribPointer","FLOAT","whiteTex","createTexture","whiteData","bindTexture","TEXTURE_2D","texImage2D","RGBA","UNSIGNED_BYTE","tex","texParameteri","TEXTURE_MIN_FILTER","NEAREST","TEXTURE_MAG_FILTER","fb","createFramebuffer","bindFramebuffer","FRAMEBUFFER","framebufferTexture2D","COLOR_ATTACHMENT0","checkFramebufferStatus","FRAMEBUFFER_COMPLETE","uniform4fv","drawArrays","TRIANGLES","clearColor","COLOR_BUFFER_BIT","pixel","readPixels","floatPixel","getError","NO_ERROR","INVALID_ENUM","INVALID_VALUE","INVALID_OPERATION","INVALID_FRAMEBUFFER_OPERATION","OUT_OF_MEMORY","CONTEXT_LOST_WEBGL","getErrorDescription","pixelBufferFloat","pixelBufferUint","pixelOrder","tmpMatrix","onBeforeRender","geometry","updateList","objectId","modelViewMatrixInverse","modelViewMatrixInverseTranspose","modelViewProjectionMatrixInverse","modelViewMatrix","multiplyMatrices","matrixWorldInverse","matrixWorld","materialProperties","properties","pu","getUniforms","setValue","Viewer","idOrElement","boundingBox","Box3","boundingBoxSize","boundingBoxLength","memory","programs","geometries","textures","calls","vertices","faces","points","distVector","ticked","rendered","elm","getElementById","container","HTMLElement","innerWidth","innerHeight","box","getBoundingClientRect","overflow","wrapper","_initParams","_initStats","_initCamera","_initScene","_initRenderer","_initHelper","setBackground","setFog","animate","fogColor","fogNear","fogFar","cameraType","cameraFov","cameraEyeSep","cameraZ","clipNear","clipFar","clipDist","clipMode","clipScale","lightColor","lightIntensity","ambientColor","ambientIntensity","rendererEncoding","LinearEncoding","lookAt","perspectiveCamera","PerspectiveCamera","orthographicCamera","OrthographicCamera","stereoCamera","StereoCamera","aspect","eyeSep","updateProjectionMatrix","stats","Scene","rotationGroup","Group","translationGroup","modelGroup","pickingGroup","backgroundGroup","helperGroup","fog","Fog","spotLight","SpotLight","ambientLight","AmbientLight","dpr","devicePixelRatio","WebGLRenderer","preserveDrawingBuffer","innerHTML","setPixelRatio","setSize","autoClear","sortObjects","outputEncoding","capabilities","isWebGL2","extensions","supportsHalfFloat","dprWidth","dprHeight","JSON","stringify","OES_texture_float","OES_texture_half_float","WEBGL_color_buffer_float","pickingTarget","WebGLRenderTarget","minFilter","NearestFilter","magFilter","stencilBuffer","format","RGBAFormat","FloatType","UnsignedByteType","texture","generateMipmaps","encoding","setRenderTarget","sampleTarget","LinearFilter","holdTarget","compositeUniforms","tForeground","Uniform","compositeMaterial","ShaderMaterial","vertexShader","fragmentShader","premultipliedAlpha","blending","AdditiveBlending","depthTest","depthWrite","compositeCamera","compositeScene","Mesh","PlaneGeometry","positions","bbGeometry","BufferGeometry","setIndex","BufferAttribute","setAttribute","bbMaterial","uColor","boundingBoxMesh","LineSegments","updateHelper","attributes","needsUpdate","isEmpty","computeBoundingSphere","cameraDistance","instanceList","instance","addBuffer","wireframeGroup","background","pickable","setUserData","object","children","userData","mesh","getMesh","applyMatrix4","wireframeMesh","getWireframeMesh","quaternion","pickingMesh","getPickingMesh","_updateBoundingBox","updateBoundingBox","instanceMatrix","updateGeometry","computeBoundingBox","geoBoundingBox","clone","equals","expandByScalar","union","updateNode","node","makeEmpty","getSize","getPickingPixels","imgBuffer","readRenderTargetPixels","getImage","picking","imgBuffer2","ctx","imgData","putImageData","setLight","intensity","near","far","setClearColor","getStyle","level","setOutputEncoding","setColorWorkflow","sRGBEncoding","setCamera","fov","up","updateZoom","setClip","dist","left","right","top","bottom","handleResize","updateInfo","rInfo","rMemory","rRender","isStill","currentSampleLevel","renderPending","frameRequest","requestAnimationFrame","pick","pid","picker","pixelBuffer","oid","getObjectById","tan","zoom","absoluteToRelative","bRadius","relativeToAbsolute","__updateClipping","isFinite","getWorldPosition","cDist","nearFactor","farFactor","fogNearFactor","fogFarFactor","__updateCamera","updateMatrix","updateMatrixWorld","pixelRatio","getPixelRatio","ortho","nearClip","updateMaterialUniforms","traverseVisible","Points","sortParticles","sortData","sortArray","zArray","cmpFn","indexSrc","indexDst","tmpTab","__zArray","__sortArray","__cmpFn","ai","bi","arr","stack","tmp","sp","swap","tmp2","quicksortCmp","attr","itemSize","sortProjectedPosition","__setVisibility","helper","visible","__updateLights","setLength","__renderPickingGroup","__renderModelGroup","renderTarget","__renderSuperSample","baseSampleWeight","sampleWeight","clearViewOffset","__renderStereo","_renderTarget","setScissorTest","setScissor","setViewport","cameraL","__render","cameraR","lastRenderedPicking","rendering","cancelAnimationFrame","LeftMouseButton","MiddleMouseButton","RightMouseButton","getTouchDistance","dx","touches","pageX","dy","pageY","sqrt","MouseObserver","moved","scrolled","dragged","dropped","clicked","hovered","doubleClicked","prevPosition","down","canvasPosition","prevClickCP","moving","hovering","lastMoved","which","buttons","pressed","altKey","ctrlKey","metaKey","shiftKey","touchAction","hoverTimeout","handleScroll","doubleClickSpeed","_listen","_onMousewheel","_onMousemove","_onMousedown","_onMouseup","_onContextmenu","_onTouchstart","_onTouchend","_onTouchmove","opt","passive","setParameters","cp","doubleClickPending","lastClicked","overElement","preventDefault","_setKeys","deltaY","deltaMode","WheelEvent","DOM_DELTA_PIXEL","DOM_DELTA_LINE","wheelDelta","wheelDeltaY","detail","clientX","clientY","_setCanvasPosition","button","getMouseButtons","_distance","distanceTo","lastTouchDistance","touchDistance","removeEventListener","tmpRotateXMatrix","tmpRotateYMatrix","tmpRotateZMatrix","tmpRotateMatrix","tmpRotateCameraMatrix","tmpRotateVector","tmpRotateQuaternion","tmpRotateQuaternion2","tmpPanMatrix","tmpPanVector","tmpAtomVector","TrackballControls","rotateSpeed","zoomSpeed","panSpeed","mouse","mouseObserver","controls","viewerControls","component","transformComponent","transformAtom","_setPanVector","scaleFactor","getCanvasScaleFactor","multiplyScalar","_getRotateXY","_getCameraRotation","extractRotation","multiply","makeRotationY","_transformPanVector","transform","premultiply","pan","translate","panComponent","panAtom","positionToVector3","positionAdd","updateRepresentations","rotate","setFromAxisAngle","makeRotationFromQuaternion","applyMatrix","zRotate","dz","makeRotationZ","rotateComponent","makeRotationAxis","setFromRotationMatrix","tmpVec","PickingProxy","pickingData","getComponentsByObject","list","getObject","getPosition","closestBondAtom","atom1","v2","atom2","acp1","getPositionOnCanvas","acp2","closeAtom","ca","acp","radius","getMaxRepresentationRadius","arrow","_objectIfType","axes","cone","clash","contact","cylinder","distance","ellipsoid","octahedron","point","sphere","tetrahedron","torus","unitcell","unknown","volume","wideline","getLabel","msg","qualifiedName","sele1","sele2","shape","spacegroup","PickingControls","pickerArray","tmpQ","tmpP","tmpS","tmpCanvasVector","tmpScaleVector","tmpAlignMatrix","ViewerControls","changed","rotation","project","getCameraDistance","getOrientation","setPosition","orient","decompose","setRotationFromQuaternion","spin","axis","rotateOnAxis","align","basis","setRotationFromMatrix","Animation","duration","pausedTime","elapsedDuration","pausedDuration","ignoreGlobalToggle","_paused","_resolveList","_init","done","paused","tick","_tick","pause","hold","_hold","resume","releaseHold","toggle","SpinAnimation","RockAnimation","angleSum","angleStep","angleEnd","MoveAnimation","moveFrom","moveTo","lerpVectors","ZoomAnimation","zoomFrom","zoomTo","RotateAnimation","_currentRotation","rotateFrom","rotateTo","slerp","ValueAnimation","valueFrom","valueTo","TimeoutAnimation","AnimationList","_list","every","animation","AnimationControls","animationList","finishedList","splice","rock","move","zoomMove","orientTo","spinComponent","rockComponent","moveComponent","Queue","argList","queue","pending","next","shift","kill","Representation","lazy","step","clipRadius","precision","clipCenter","flatShaded","side","front","back","double","wireframe","colorData","colorScheme","colorScale","colorReverse","colorValue","colorDomain","colorMode","roughness","metalness","diffuse","diffuseInterior","useInteriorColor","interiorColor","interiorDarkening","disablePicking","rebuild","tasks","make","bufferList","toBePrepared","init","setColor","quality","lazyProps","build","bufferParams","what","tp","sphereDetail","radialSegments","openEnded","disableImpostor","getColorParams","getBufferParams","val","prepare","cb","create","updateWhat","_make","manualAttach","disposed","attach","setVisibility","noRenderRequest","updateParameters","int","float","parseFloat","getParameters","_Worker","postCount","onmessageDict","onerrorDict","blobUrl","worker","Worker","post","__debug","terminate","WorkerPool","maxCount","pool","getNextWorker","nextWorker","minPending","calculateMeanVector3","projectPointOnVector","origin","sub","projectOnVector","minX","minY","minZ","maxX","maxY","maxZ","l","v3new","applyMatrix4toVector3array","applyMatrix3toVector3array","normalizeVector3array","len2","v3cross","ax","ay","az","bx","by","bz","v3dot","v3sub","v3add","v3fromArray","v3toArray","input","v3length2","v3length","v3divideScalar","v3multiplyScalar","v3normalize","length2","v3subScalar","v3addScalar","v3floor","v3ceil","v3negate","v3angle","cx","cy","cz","getFixedCountDashData","segmentCount","position1","sn3","position2","i3","j3","f1","f2","replicateArray3Entries","color2","primitiveId","getFixedLengthDashData","segmentLength","pos1","pos2","col","rad","getFixedLengthWrappedDashData","drawing","k3","kprev","vl","inv","Primitive","Picker","Buffer","static","_primitiveData","getShapeKey","fields","valueToShape","expandBoundingBox","valueFromShape","arrayFromShape","dataFromShape","SpherePrimitive","expandByPoint","BoxPrimitive","heightAxis","depthAxis","OctahedronPrimitive","TetrahedronPrimitive","CylinderPrimitive","dashedCylinder","ArrowPrimitive","ConePrimitive","EllipsoidPrimitive","majorAxis","minorAxis","TorusPrimitive","TextPrimitive","text","PointPrimitive","WidelinePrimitive","SpatialHash","exp","bb","createBoundingBox","boundX","boundY","boundZ","an","xArray","yArray","grid","bucketIndex","bucketCount","bucketOffset","bucketFill","bucketArray","bucketIdx","within","eachWithin","atomIndex","rSq","loX","loY","loZ","hiX","hiY","hiZ","ix","iy","iz","dSq","Store","_fields","_defaultFields","_initField","addField","resize","tmpArray","growIfFull","copyFrom","other","thisOffset","otherOffset","thisField","otherField","thisIndex","otherIndex","offsetTarget","offsetSource","targetIndex","sourceIndex","thisStore","tmpStore","quicksort","pivot","leftNew","rightNew","index1","index2","ContactStore","addContact","hammingWeight","BitArray","setAll","_words","flip","_assignRange","words","wordValue","wordStart","wordEnd","startWord","endWord","setRange","clearRange","setBits","clearBits","clearAll","flipAll","bs","_isRangeValue","isRangeSet","isRangeClear","isAllSet","isAllClear","isSet","isClear","isEqualTo","otherBitarray","words1","words2","difference","intersection","intersects","getIntersectionSize","makeIntersection","wordsA","answer","pos","toSeleString","createAdjacencyList","edges","edgeCount","nodeCount","nodeArray1","nodeArray2","countArray","offsetArray","bondCount2","indexArray","idx1","idx2","j1","j2","createFeatureState","atomSet","addAtom","state","addFeature","features","groups","centers","atomSets","UnknownBackboneType","ChemCompProtein","ChemCompRna","ChemCompDna","ChemCompSaccharide","ChemCompHetero","SecStrucHelix","SecStrucSheet","SecStrucTurn","AtomicNumbers","H","D","T","HE","LI","BE","B","C","N","O","F","NE","NA","MG","AL","SI","P","S","CL","AR","K","CA","SC","TI","V","CR","MN","FE","CO","NI","CU","ZN","GA","GE","AS","SE","BR","KR","RB","SR","Y","ZR","NB","MO","TC","RU","RH","PD","AG","CD","IN","SN","SB","TE","I","XE","CS","BA","LA","CE","PR","ND","PM","SM","EU","GD","TB","DY","HO","ER","TM","YB","LU","HF","TA","W","RE","OS","IR","PT","AU","HG","TL","PB","BI","PO","AT","RN","FR","RA","AC","TH","PA","U","NP","PU","AM","CM","BK","CF","ES","FM","MD","NO","LR","RF","DB","SG","BH","HS","MT","DS","RG","CN","NH","FL","MC","LV","TS","OG","VdwRadii","CovalentRadii","Valences","OuterShellElectronCounts","ResidueHydrophobicity","ALA","ARG","ASN","ASP","ASH","CYS","GLN","GLU","GLH","GLY","HIS","ILE","LEU","LYS","MET","PHE","PRO","SER","THR","TRP","TYR","VAL","DefaultResidueHydrophobicity","AA1","SEC","PYL","AA3","RnaBases","DnaBases","PurinBases","Bases","WaterNames","IonNames","SaccharideNames","ProteinBackboneAtoms","NucleicBackboneAtoms","ResidueTypeAtoms","trace","direction1","direction2","backboneStart","backboneEnd","PDBQTSpecialElements","HD","A","NS","OA","SA","G0","G1","G2","G3","CG0","CG1","CG2","CG3","assignGeometry","totalCoordination","Angles","Map","calcAngles","ap1","ap2","angles","d1","d2","subVectors","eachBondedAtom","number","angleTo","calcPlaneAngle","x1","v12","neighbours","ni","cross","ValenceModel","implicitH","totalH","idealGeometry","chg","implH","totH","geom","hydrogenCount","bondToElementCount","assignCharge","assignH","degree","valence","explicitValence","conjugated","_bp","getBondProxy","atomicNumber","flag","a2","getOtherAtom","b2","atomicNumber2","isConjugated","multiBond","implicitHCount","ba","oa","calculateHydrogensCharge","valenceModel","isPhosphate","PositvelyCharged","NegativelyCharged","isIonicInteraction","ti","tj","isPiStacking","isCationPi","isHistidineNitrogen","isHydrogenBond","isWeakHydrogenBond","IonicTypeMetals","isMetalComplex","halBondElements","X","OptimalHalogenAngle","OptimalAcceptorAngle","invalidAtomContact","masterIdx","isMasterContact","ContactDefaultParams","maxHydrophobicDist","maxHbondDist","maxHbondSulfurDist","maxHbondAccAngle","maxHbondDonAngle","maxHbondAccPlaneAngle","maxHbondDonPlaneAngle","maxPiStackingDist","maxPiStackingOffset","maxPiStackingAngle","maxCationPiDist","maxCationPiOffset","maxIonicDist","maxHalogenBondDist","maxHalogenBondAngle","maxMetalDist","refineSaltBridges","masterModelIndex","lineOfSightDistFactor","residueIndex","calculateFeatures","atomInGroupDict","eachResidue","addGroup","terminalNitrogenCount","isGuanidine","isAcetamidine","addPositiveCharges","isSulfonicAcid","isSulfate","terminalOxygenCount","isCarboxylate","addNegativeCharges","rings","getAromaticRings","ring","addAromaticRings","totalBonds","ig","addHydrogenAcceptors","addHydrogenDonors","ringData","residueType","getRings","hasElement","some","residueAtomOffset","atomTypeId","atomTypeIdList","atomMap","inAromaticRingWithElectronNegativeElement","addWeakHydrogenDonors","dative","ionic","isStandardAminoacid","isStandardBase","isHalogen","addMetalBinding","isTransitionMetal","addMetals","addHydrophobic","addHalogenAcceptors","addHalogenDonors","calculateContacts","contacts","spatialHash","contactStore","featureSet","createContacts","maxDistance","maxPiStackingDistSq","maxCationPiDistSq","atomStore","areAtomSetsWithinDist","atomSet1","atomSet2","maxDist","sn","sm","si","sj","v3","n1","n2","getNormal","atoms","crossVectors","getOffset","projectOnPlane","ct","addChargedContacts","maxHbondDistSq","donor","acceptor","isWeak","connectedTo","donorAngles","idealDonorAngle","donorAngle","outOfPlane","acceptorAngles","idealAcceptorAngle","acceptorAngle","bondType","isWaterHydrogenBond","isBackboneHydrogenBond","addHydrogenBonds","m1","m2","addMetalComplexation","addHydrophobicContacts","halogen","halogenAngles","addHalogenBonds","frozenContacts","adjacencyList","contactSet","createFrozenContacts","ac1","ac2","aw","c1","c2","lineOfSightDist","lineOfSightDistFactorSq","as1","as2","vdw","distanceToSquared","refineLineOfSight","residueContactDict","handleResidueContact","minDist","minIndex","refineHydrophobicContacts","ionicInteractionDict","isHydrogenBondType","iil1","iil2","piStackingDict","pil1","pil2","refinePiStacking","refineMetalCoordination","contactTypeName","ContactDataDefaultParams","hydrogenBond","hydrophobic","halogenBond","ionicInteraction","metalCoordination","cationPi","piStacking","weakHydrogenBond","waterHydrogenBond","backboneHydrogenBond","filterSele","getContactData","filterSet","getAtomSet","setHex","contactColor","ContactPicker","getIndex","_applyTransformations","_getPosition","ShapePicker","primitive","objectFromShape","positionFromShape","AtomPicker","AxesPicker","BondPicker","bondStore","center1","center2","ClashPicker","validation","clashArray","_getAtomProxyFromSele","getAtomIndices","DistancePicker","IgnorePicker","MeshPicker","__position","SurfacePicker","UnitcellPicker","getCenter","VolumePicker","vol","dp","SlicePicker","getEdgeTable","getTriTable","MarchingCubes","field","nx","ny","nz","normalCache","vertexIndex","icount","mx","my","mz","allowedContours","isolevel","noNormals","contour","wrap","isNegativeIso","normalFactor","yd","zd","ilist","positionArray","normalArray","atomindexArray","edgeTable","triTable","VIntX","valp1","valp2","_q","mu","nc","q3","VIntY","q6","VIntZ","compNorm","polygonize","fx","fy","fz","edgeFilter","q1","qy","qz","q1y","q1z","qyz","q1yz","cubeindex","field0","field1","field2","field3","field4","field5","field6","field7","bits","fx2","fy2","fz2","e1","e2","e3","triIndex","triangulate","xBeg","yBeg","zBeg","xEnd","yEnd","zEnd","yOffset","zOffset","xBeg2","yBeg2","zBeg2","xEnd2","yEnd2","zEnd2","__break","__xBeg","__yBeg","__zBeg","__xEnd","__yEnd","__zEnd","_isolevel","_noNormals","_box","_contour","_wrap","vIndexLength","Matrix","cols","rows","copyTo","At","nrows","ncols","Ai","Ati","pAt","ad","atd","multiplyABt","Ap","pA","pB","Cp","mrows","bd","cd","multiply3x3","Cd","Ad","Bd","m10","m11","m12","m13","m14","m15","m16","m17","m18","m20","m21","m22","m23","m24","m25","m26","m27","m28","meanRows","mean","subRows","row","i0","i1","hypot","EPSILON","FLT_MIN","svd","at","_m","amt","wmt","vmt","astep","_W","Vt","vstep","eps","minval","iter","maxIter","Aj","Vi","Vj","t0","t1","sd","beta","gamma","seed","val0","asum","Float64Array","JacobiSVDImpl","m4new","m4set","n11","n12","n13","n14","n21","n22","n23","n24","n31","n32","n33","n34","n41","n42","n43","n44","m4multiply","a11","a12","a13","a14","a21","a22","a23","a24","a31","a32","a33","a34","a41","a42","a43","a44","b11","b12","b13","b14","b21","b22","b23","b24","b31","b32","b33","b34","b41","b42","b43","b44","m4makeScale","m4makeTranslation","m4makeRotationY","theta","m3new","m3makeNormal","m4","r0","r1","r2","laplacianSmooth","verts","numiter","inflate","nv","nf","norms","tps","vertdeg","jl","flagvert","ao","bo","co","vi3","vdi","wtvi","wt2vi","wt2","outwt","computeVertexNormals","nv3","ab","ci","getRadiusDict","radiusList","radiusDict","getSurfaceGrid","maxRadius","extraMargin","margin","dim","maxSize","pow","tmpSize","tran","mroty","mscale","mtrans","Surface","Geometry","fromGeometry","setFromArray","geo","getColor","colormaker","tc","getPicking","getFilteredIndex","filteredIndex","elementSize","include","getAtomindex","VolumeSurface","mc","getSurface","smooth","normalMatrix","volsurf","Volume","Matrix3","inverseMatrix","setData","setAtomindex","_position","_min","_max","_mean","_rms","setStats","rms","setMatrix","me","elements","ne","getBox","_getBox","__box","_makeSurface","getValueForSigma","getSurfaceWorker","workerPool","sigma","getSigmaForValue","getDataAtomindex","getDataPosition","getDataColor","getDataPicking","getDataSize","_sum","sumSq","di","arrayRms","header","getThreeSide","FrontSide","BackSide","DoubleSide","setObjectMatrix","matrixWorldNeedsUpdate","BufferDefaultParameters","opaqueBack","forceTransparent","BufferParameterTypes","updateShader","property","uniform","updateVisibility","parameterTypes","indexVersion","wireframeIndexVersion","isImpostor","isText","isPoint","isLine","dynamic","wireframeIndexCount","defaultParameters","UniformsUtils","merge","UniformsLib","common","emissive","lights","pickingUniforms","_positionDataSize","addAttributes","initIndex","makeWireframeGeometry","attributeSize","nindex","setUsage","DYNAMIC_DRAW","makeMaterial","vertexColors","derivatives","fragDepth","wm","pm","NoBlending","wireframeMaterial","pickingMaterial","makeWireframeIndex","wireframeIndex","wireframeGeometry","setDrawRange","checkEdge","drawRange","updateWireframeIndex","updateRange","getRenderOrder","renderOrder","_getMesh","materialName","frustumCulled","getVertexShader","getFragmentShader","NEAR_CLIP","RADIUS_CLIP","PICKING","NOLIGHT","FLAT_SHADED","OPAQUE_BACK","DIFFUSE_INTERIOR","USE_INTERIOR_COLOR","addUniforms","buf","updateRenderOrder","setRenderOrder","pt","pv","propertyData","uniformData","doShaderUpdate","doVisibilityUpdate","setProperties","setUniforms","setAttributes","attribute","wu","isVector3","toJSON","MeshBuffer","SurfaceBuffer","setVisibilityTrue","setVisibilityFalse","DoubleSidedBuffer","frontMeshes","backMeshes","frontBuffer","backBuffer","ContourBuffer","SurfaceRepresentation","isolevelType","negateIsolevel","isolevelScroll","boxSize","colorVolume","useWorker","boxCenter","__boxCenter","setBox","__isolevel","__smooth","__contour","__wrap","__boxSize","onSurfaceFinish","surfaceBuffer","dullInterior","surfaceData","MouseActions","trackballControls","focus","getFocus","sign","almostIdentity","setFocus","eachRepresentation","reprElem","comp","repr","pickingProxy","animationControls","tt","tooltip","mp","innerText","measurePick","measureClear","MouseActionPresets","default","zoomScroll","focusScroll","zoomFocusScroll","rotateDrag","panDrag","zRotateDrag","zoomDrag","zoomFocusDrag","panComponentDrag","rotateComponentDrag","movePick","tooltipPick","pymol","coot","astexviewer","triggerFromString","tokens","MouseControls","actionList","disabled","preset","triggerStr","wildcard","action","KeyActions","autoView","toggleRock","toggleSpin","KeyActionPresets","toggleAnimations","toggleAntialiasing","KeyControls","char","PickingBehavior","mouseControls","_onClick","_onHover","pickingControls","MouseBehavior","_onMove","_onScroll","_onDrag","_onDblclick","AnimationBehavior","_onTick","KeyBehavior","keyControls","outline","_focusDomElement","_onKeydown","_onKeyup","_onKeypress","pressedKey","KeyboardEvent","keyCode","Annotation","content","_viewerPosition","_updateViewerPosition","_canvasPosition","_cameraPosition","pointerEvents","whiteSpace","setContent","_update","matrixChanged","displayValue","padding","fontFamily","_clientRect","getVisibility","vp","cr","depth","zIndex","ComponentControls","RadiusFactoryTypes","covalent","explicit","RadiusFactory","atomRadius","negateVector","PrincipalAxes","n3","pointsT","vm","van","vbn","vcn","va","vb","vc","begA","endA","begB","endB","begC","endC","vecA","vecB","vecC","normVecA","normVecB","normVecC","getBasisMatrix","makeBasis","determinant","getRotationQuaternion","inverse","getProjectedScaleForAtoms","d1a","d1b","d2a","d2b","d3a","d3b","ax1","ax2","ax3","dp1","dot","dt1","dp2","dt2","dp3","dt3","FilteredVolume","minValue","maxValue","outside","setFilter","_getFilterHash","DMEAN","ARMS","filterHash","_filterHash","_dataBuffer","_positionBuffer","_atomindexBuffer","filteredData","filteredPosition","filteredAtomindex","BondHash","al","BondStore","addBond","ai1","ai2","addBondIfConnected","AtomStore","setAltloc","getAltloc","code","ResidueStore","setSstruc","getSstruc","setInscode","getInscode","ChainStore","setChainname","getChainname","setChainid","chainid","getChainid","ModelStore","Helixorient","polymer","residueCount","getCenterIterator","cache","idx3","residueIndexStart","rp","getResidueProxy","traceAtomIndex","radiusFactory","diff","rise","twist","resdir","r12","r23","r34","diff13","diff24","vt","_axis","_prevAxis","_resdir","_center","a1","getAtomIndexByType","a3","a4","acos","diff13Length","diff24Length","resRadius","resTwist","resRise","resBending","resAxis","bending","Helixbundle","helixorient","getAxis","localAngle","centerDist","ssBorder","colorParams","radiusParams","beg","residueOffset","tmpAxis","tmpCenter","_beg","_end","rp1","rp2","BinaryHeap","scoreFunction","bubbleUp","sinkDown","peek","len","parentN","parent","elemScore","child1Score","child2Score","child2N","child1N","child1","child2","Kdtree","metric","maxDepth","currentNode","nodes","rootIndex","buildTree","arrBegin","arrEnd","plength","nodeIndex","arrMedian","currentDim","pivotIndex","pivotValue","storeIndex","getNodeDepth","parentIndex","nearest","maxNodes","bestNodes","nearestSearch","bestChild","otherChild","dimension","pointIndex","ownPoint","ownDistance","saveNode","leftIndex","rightIndex","linearPoint","linearDistance","verify","AtomProxy","chainStore","residueStore","residueMap","bondHash","entityList","entityIndex","chainIndex","residue","residueTypeId","atomType","partialCharge","aromatic","_ap","hasBondTo","bap","hasBondToElement","backboneIndexList","moleculeType","isCg","backboneType","isTrace","atomRings","isNonmetal","isMetalloid","isDiatomicNonmetal","isPolyatomicNonmetal","isAlkaliMetal","isAlkalineEarthMetal","isNobleGas","isPostTransitionMetal","isLanthanide","isActinide","getDefaultValence","getValenceList","getOuterShellElectronCount","taa","aaa","distSquared","ta","aa","positionFromArray","positionToArray","positionFromVector3","positionSub","getResidueBonds","firstOnly","relativeIndex","bonds","getBonds","atomIndices1","atomIndices2","connectedAtomIndex","connectedAtomIndices","noResname","toObject","euclideanDistSq","euclideanDist","pointArray","useSquaredDist","atomIndices","kdtree","_Kdtree","nodeList","resultList","SymOpCode","$","E","G","J","L","M","Q","R","Z","_","EncodedSymOp","reInteger","selectionFromChains","chainList","Assembly","partList","addPart","matrixList","part","AssemblyPart","getAtomCount","reduce","getResidueCount","getInstanceCount","instanceCount","isIdentity","structureChainList","eachChain","getBoundingBox","partBox","_getCount","propertyName","instanceBox","structureBox","getView","getInstanceList","StructureBuilder","currentModelindex","currentChainid","currentResname","currentResno","currentInscode","currentHetero","previousResname","previousHetero","ri","mi","addResidueType","modelindex","addModel","addChain","addResidue","chainOffset","chainCount","finalize","assignSecondaryStructure","secStruct","chainnames","chainnamesSorted","chainnamesIndex","helices","h1","h2","helix","helixRun","chainChange","sheets","s1","s2","strandCharCode","sheet","sheetRun","calculateSecondaryStructure","zhangSkolnickSS","distances","isHelical","eachPolymer","cgPolymer","proteinPolymer","prevSstruc","sstrucCount","ChainnameAlphabet","calculateChainnames","useExistingBonds","doAutoChainName","mIndex","rOffset","rCount","rStart","rEnd","chainData","eachResidueN","newChain","bbType1","bbType2","bbTypeUnk","backboneEndAtomIndex","backboneStartAtomIndex","fill","calculateBonds","calculateBondsWithin","calculateBondsBetween","BondOrderTable","getBondOrderFromTable","atomname1","atomname2","onlyAddRung","rungBondStore","rungAtomSet","atomBondMap","calculateAtomBondMap","bondedAtoms","Set","rai","bondOrders","nn","rai1","rai2","getBondIndex","rungEndAtomIndex","atomSetDict","rung","onlyAddBackbone","backboneBondStore","backboneAtomSet","needsBond","needsBackbone","backbone","buildUnitcellAssembly","uc","structureCenterFrac","cartToFrac","centerFrac","symopDict","encodedSymopList","matrixDict","symopList","symop","denominator","integer","getSymmetryOperations","centerFracSymop","positionFracSymop","getMatrixList","setFromMatrixPosition","fracToCart","unitcellAssembly","unitcellMatrixList","ncsMatrixList","biomolDict","NCS","ncsUnitcellMatrixList","nm","vec","supercellAssembly","supercellMatrixList","ncsSupercellMatrixList","UNITCELL","SUPERCELL","guessElement","atomName","assignResidueTypeBonds","bondDict","nextAtomOffset","concatStructures","structures","Structure","sb","atomIndexDict","modelCount","finalizeAtoms","finalizeBonds","AlkaliMetals","AlkalineEarthMetals","PolyatomicNonmetals","DiatomicNonmetals","NobleGases","PostTransitionMetals","Metalloids","Halogens","AtomType","no","AtomMap","dict","getHash","ResidueType","chemCompType","bondReferenceAtomIndices","getMoleculeType","getBackboneType","backboneEndType","backboneStartType","getBackboneIndexList","atomnames","atomnamesStart","atomnamesEnd","traceIndex","getAtomIndexByName","dir1Index","direction1AtomIndex","dir2Index","direction2AtomIndex","bbStartIndex","bbEndIndex","rungEndIndex","atomnameList","hasProteinBackbone","hasRnaBackbone","hasDnaBackbone","hasCgProteinBackbone","hasCgRnaBackbone","hasCgDnaBackbone","hasAtomWithName","hasBackboneAtoms","hasBackbone","end1","maxd","nearestAtoms","calculateResidueBonds","calculateRings","getBondGraph","bondGraph","calculateBondGraph","getAromatic","aromaticAtoms","calculateAromatic","aromaticRings","nb","capacity","visited","pred","RingFinderMaxDepth","currentColor","RingFinderState","findRings","aromaticRingFlags","AromaticRingElements","AromaticRingPlanarityThreshold","isRingAromatic","assignBondReferenceAtomIndices","refRing","rings1","rings2","ri1","ai3","_idx2","getBondReferenceAtomIndex","bondIndex","addRing","current","leftOffset","rightOffset","found","rn","ringOffset","from","head","ResidueMap","BondProxy","_v12","_v13","_ap1","_ap2","_ap3","getOtherAtomIndex","getReferenceAtomIndex","typeAtomIndex1","typeAtomIndex2","calculateShiftDir","ap3","v13","ResidueProxy","getChainProxy","getAtomType","getResname1","getAtomnameList","rNext","bbAtomEnd","bbAtomStart","getNextConnectedResidue","nextIndex","rpNext","rpFirst","getPreviousConnectedResidue","residueProxy","prevIndex","rpPrev","rpLast","Polymer","residueIndexEnd","rpStart","rpEnd","isPrevConnected","isNextConnected","isNextNextConnected","isCyclic","__residueProxy","aIndex","eachAtomN","rStartIndex","ChainProxy","getModelProxy","residueEnd","_rp","rNextIndex","first","ModelProxy","chainEnd","_cp","refreshed","extraData","atomSetCache","boxes","bondSet","getBondSet","getBackboneBondSet","backboneBondSet","__backbone","getRungBondSet","rungBondSet","__rung","seleString","getAtomSetWithinSelection","getAtomSetWithinPoint","getAtomSetWithinVolume","fv","getMaxScaleOnAxis","getAtomSetWithinGroup","atomResidueIndex","getStructure","eachEntity","getEntityType","mn","cn","getAtomData","atomData","getBondData","multipleBond","isMulti","isOffset","bondScale","bondSpacing","bondData","storeBondOrder","radius2","absOffset","multiRadius","vShortening","vShift","getBackboneAtomData","getBackboneBondData","getRungAtomData","getRungBondData","getPrincipalAxes","atomCenter","hasCoords","_hasCoords","getSequence","seq","getChainnameCount","updatePosition","refresh","refreshPosition","tmpBox","Primitives","ShapeDefaultParameters","aspectRatio","labelParams","pointSize","sizeAttenuation","useTexture","Shape","meshCount","addMesh","meshBuffer","addSphere","objectToShape","addEllipsoid","addTorus","addCylinder","addCone","addArrow","addBox","addOctahedron","addTetrahedron","addText","addPoint","addWideline","addLabel","getBufferList","buffers","bufferFromShape","BufferRepresentation","GeometryBuffer","geoPosition","geoIndex","meshPosition","meshNormal","meshColor","meshIndex","updateNormals","geoNormal","positionCount","geoPositionCount","transformedGeoPosition","transformedGeoNormal","makeIndex","initNormals","makeTranslation","applyPositionTransform","getNormalMatrix","o3","SphereGeometryBufferDefaultParameters","SphereGeometryBuffer","IcosahedronBufferGeometry","_radius","MappedBuffer","mappingType","indexSize","mapping","mappingSize","mappingIndicesSize","nullValueAttributes","getAttributeIndex","dataIndex","makeMapping","mappingItemSize","aMapping","mappingIndices","it","MappedQuadBuffer","SphereImpostorBuffer","SphereBuffer","x0","y0","y1","PointBufferDefaultParameters","alphaTest","edgeBleach","PointBufferParameterTypes","PointBuffer","makeTexture","DataTexture","makePointTexture","USE_SIZEATTENUATION","USE_MAP","ALPHATEST","DotRepresentation","thresholdType","thresholdMin","thresholdMax","thresholdOut","dotType","radiusType","deviation","dotData","dotBuffer","quadIndices","quadUvs","ImageBufferDefaultParameters","ImageBufferParameterTypes","ImageBuffer","alwaysTransparent","hasWireframe","imageData","flipY","pickingTex","pickingMap","mapSize","startsWith","CUBIC_INTERPOLATION","endsWith","BSPLINE_FILTER","CATMULROM_FILTER","MITCHELL_FILTER","updateTexture","NormalBlending","VolumeSlice","positionType","getPositionFromCoordinate","coord","ms","setFromMatrixScale","vn","dimLen","z0","setVec","pickingArray","tMin","tMax","SliceRepresentation","linear","percent","coordinate","volumeSlice","sliceBuffer","logReprUnknown","ElementDefaultParameters","Element","statusChanged","setStatus","setName","RepresentationElementDefaultParameters","RepresentationElement","visibilityChanged","parametersChanged","setRepresentation","getType","_disposeRepresentation","hasRepresentation","removeRepresentation","toggleVisibility","setSelection","_v","ComponentDefaultParameters","Component","representationAdded","representationRemoved","reprList","annotationList","setRotation","Euler","setFromEuler","setScale","setTransform","getCenterUntransformed","makeScale","updateRepresentationMatrices","addAnnotation","annotation","eachAnnotation","removeAnnotation","removeAllAnnotations","_addRepresentation","hidden","impostor","workerDefault","ReprClass","makeRepresentation","addBufferRepresentation","removeAllRepresentations","getBoxUntransformed","getZoom","getZoomForBox","Collection","_remove","RepresentationCollection","TrajectoryElementDefaultParameters","defaultStep","defaultTimeout","defaultInterpolateType","defaultInterpolateStep","defaultMode","defaultDirection","initialFrame","TrajectoryElement","frameChanged","playerChanged","player","setFrame","Frames","coordinates","times","timeOffset","deltaTime","Superposition","atoms1","atoms2","VH","coords1","coords2","coords1t","coords2t","transformationMatrix","prepCoords","_superpose","mean1","mean2","to","invA","t4","t5","t8","t9","t11","t13","t14","t15","t17","t18","t20","t21","t23","t26","invert3x3","md","mat3x3determinant","transformMat_","tmp_1","tmp_2","mult","M1","M2","is4X4","tCoords","det","_pB","mcols","invertTrasform","mat","n4","TrajectoryPlayerDefaultParameters","interpolateType","interpolateStep","TrajectoryPlayer","traj","startedRunning","haltedRunning","_run","_previousTime","_currentTime","_currentStep","frameCount","_currentFrame","_direction","_animate","isRunning","dt","inProgress","_nextInterpolated","hasFrame","ip","ipp","ippp","setFrameInterpolated","loadFrame","_next","currentFrame","play","setPlayer","Trajectory","trajPath","frameCache","loadQueue","boxCache","pathCache","frameCacheSize","_frameCount","_disposed","centerPbc","removePbc","removePeriodicity","superpose","selectionIndices","_resetCache","_saveInitialCoords","setStructure","_loadFrameCount","backboneIndices","_getIndices","_makeAtomIndices","_saveStructureCoords","initialCoords","structureCoords","_makeSuperposeCoords","resetCache","_updateStructure","_interpolate","fc","cpp","cppp","j0","interpolateSpline","interpolateLerp","iList","_loadFrame","_doSuperpose","_process","_setFrameCount","box2","circMean","circularMean3","arrayMean3","getFrameTime","FramesTrajectory","StructureTrajectory","RemoteTrajectory","request","getFrameUrl","getFrameParams","setRequestHeader","arrayBuffer","getCountUrl","CallbackTrajectory","requestCallback","StructureView","seleList","parentSelection","ignoreView","blosum62x","prepareMatrix","cellNames","matDict","rowDict","SubstitutionMatrices","blosum62","Alignment","seq1","seq2","gapPenalty","gapExtensionPenalty","substMatrix","initMatrices","score","ali","gap","makeScoreFn","calc","gap0","scoreFn","Vi1","Si1","Hi","Si","ali1","ali2","_s1","_s2","_i","_j","aliIdx1","aliIdx2","_atoms1","_atoms2","StructureComponentDefaultParameters","defaultAssembly","StructureComponent","trajList","trajectoryAdded","trajectoryRemoved","defaultAssemblyChanged","initSelection","pickBuffer","pointer","item","createRingBuffer","pickDict","del","values","createSimpleDict","spacefillRepresentation","addRepresentation","distanceRepresentation","angleRepresentation","dihedralRepresentation","measureRepresentations","setDefaultAssembly","structureView","rebuildRepresentations","rebuildTrajectories","reprParams","trajComp","reprComp","measureUpdate","addTrajectory","trajSrc","makeTrajectory","removeTrajectory","getAtomRadius","pickCount","lastPick","atomList","atomListSorted","atomPair","atomTriple","atomQuad","measureBuild","measureData","dihedral","pickData","radiusData","removeAllMeasurements","pd","removeMeasurement","addMeasurement","SurfaceComponent","VolumeComponent","ComponentCollection","matchName","tmpZoomVector","StageDefaultParameters","mousePreset","Stage","fullscreenChanged","componentAdded","componentRemoved","compList","defaultFileParams","logList","pickingBehavior","mouseBehavior","animationBehavior","keyBehavior","spinAnimation","rockAnimation","setQuality","setImpostor","defaultFileRepresentation","BU1","assembly","sizeScore","backboneOnly","radiusScale","surfaceType","probeRadius","lineOnly","loadFile","promise","addComponentFromObject","defaultRepresentation","errorMsg","loadScript","script","addComponent","CompClass","removeComponent","removeAllComponents","toggleFullscreen","fullscreenEnabled","mozFullScreenEnabled","webkitFullscreenEnabled","msFullscreenEnabled","getFullscreenElement","fullscreenElement","mozFullScreenElement","webkitFullscreenElement","msFullscreenElement","resizeElement","lastFullscreenElement","dataset","normalWidth","normalHeight","exitFullscreen","msExitFullscreen","mozCancelFullScreen","webkitExitFullscreen","screen","requestFullscreen","msRequestFullscreen","mozRequestFullScreen","webkitRequestFullscreen","setSpin","setRock","pclamp","bbSize","minSize","aspectFactor","catch","impostorTypes","eachComponent","getComponentsByName","getRepresentationsByName","sc","ShapeComponent","__decorate","decorators","desc","getOwnPropertyDescriptor","Reflect","decorate","AtomindexColormaker","scalePerModel","BfactorColormaker","bfactorScale","ChainidColormaker","chainidDictPerModel","chainidDict","ChainindexColormaker","ChainnameColormaker","chainnameDictPerModel","chainnameDict","DensityfitColormaker","rsrzDict","rsccDict","rsrzScale","rsccScale","rsrz","rscc","partialCharges","CZ","CG","OD1","CB","OD2","OE1","OE2","CD2","CE1","ND1","NE2","NZ","SD","PTR","O1P","O2P","O3P","OG1","SEP","TPO","CD1","CE2","CE3","NE1","OH","ElectrostaticColormaker","hCharges","charges","hPositions","hPos","backboneNHPosition","bbox","hStore","buildStoreLike","hHash","ElementColors","UUT","UUP","UUH","ElementColormaker","EntityindexColormaker","entityindexScale","EntitytypeColormaker","entityType","GeoqualityColormaker","geoAtomDict","geoDict","geoProblemCount","geoAtom","atomProblems","HydrophobicityColormaker","resHF","defaultResidueHydrophobicity","hfScale","ModelindexColormaker","modelindexScale","MoleculetypeColormaker","OccupancyColormaker","occupancyScale","PartialchargeColormaker","partialchargeScale","randomColor","RandomColormaker","RandomcoilindexColormaker","rciDict","rciScale","rci","ResidueindexColormaker","scalePerChain","ResidueColors","ASX","GLX","DA","DG","DI","DX","DC","DT","DU","DD","ResnameColormaker","StructureColors","SstrucColormaker","StructuredataColormaker","_a","_b","UniformColormaker","valueColor","ValueColormaker","valueScale","VolumeColormaker","nxy","i1y","i1z","iyz","i1yz","vy","vz","v1y","v1z","vyz","v1yz","xd","c00","c01","c10","c11","c0","StructureRepresentation","radiusSize","biomolOptions","defaultScale","setRadius","getQuality","getAssembly","needsBuild","sview","createData","updateData","getRadiusParams","param","getAtomParams","getBondParams","MeasurementRepresentation","labelVisible","labelFontFamily","monospace","serif","labelFontStyle","italic","labelFontWeight","bold","labelsdf","labelXOffset","labelBackground","labelBackgroundColor","labelBackgroundMargin","labelBackgroundOpacity","labelFixedSize","labelFontstyle","textData","textBuffer","getLabelBufferParams","fontStyle","fontWeight","sdf","xOffset","attachment","showBorder","borderColor","borderWidth","showBackground","backgroundMargin","backgroundOpacity","fixedSize","parseNestedAtoms","nSets","order","selected","_break","Number","isInteger","calcArcPoint","edt","edt1d","MIN_SAFE_INTEGER","MAX_SAFE_INTEGER","TextAtlasCache","TextAtlasDefaultParams","font","variant","weight","TextAtlas","mapped","scratchW","scratchH","currentX","currentY","cutoff","lineHeight","maxWidth","fillStyle","textAlign","textBaseline","lineJoin","gridOuter","gridInner","canvas2","context2","placeholder","CanvasTexture","draw","measureText","clearRect","fillText","TextBufferDefaultParameters","fontSize","TextBufferParameterTypes","getCharCount","charCount","TextBuffer","fontTexture","inputTexCoord","inputSize","aPosition","aColor","txt","iChar","nChar","iCharAll","textAtlas","getTextAtlas","inputMapping","xadvance","xShift","yShift","texWidth","texHeight","texCoords","FIXED_SIZE","WideLineBufferDefaultParameters","WideLineBufferParameterTypes","WideLineBuffer","AngleRepresentation","vectorVisible","sectorVisible","atomPosition","okay","outPosition","outIdx","validatePositions","atomTriplePositions","angleData","labelPosition","labelText","vectorPosition1","vectorPosition2","arcPositionTmp1","arcPositionTmp2","sectorPositionTmp","totalSegments","v21","v23","cross2","labelTmp","arcPoint","crossLength","toFixed","nSegments","sectorVertices","arcVertices1","arcVertices2","appendArcSection","arcSize","sectorSize","arcPosition1","arcPosition2","sectorPosition","sectorOffset","arcOffset","getAngleData","vectorBuffer","arcLength","arcBuffer","sectorLength","sectorBuffer","vectorData","arcData","sectorData","eye","CylinderGeometryBufferDefaultParameters","getGeo","makeRotationX","CylinderBufferGeometry","CylinderGeometryBuffer","geoLength","__center","_color","_from","_to","meshData","MappedAlignedBoxBuffer","CylinderImpostorBufferDefaultParameters","CylinderImpostorBufferParameterTypes","CylinderImpostorBuffer","CAP","CylinderBuffer","AxesRepresentation","showAxes","showBox","getAxesData","pa","en","vertexPosition","vertexColor","vertexRadius","edgePosition1","edgePosition2","edgeColor","edgeRadius","addAxis","offset2","addCorner","d3","addScaledVector","edgeOffset","addEdge","edge","axesData","sphereBuffer","cylinderBuffer","sphereData","cylinderData","BallAndStickRepresentation","cylinderOnly","symmetric","lineBuffer","lineData","BackboneRepresentation","BaseRepresentation","Interpolator","vec1","vec2","vDir","vTan","vNorm","vBin","interpolateToArr","interpolateToVec","interpolatePosition","interpolateTangent","vectorSubdivide","interpolationFn","iterator","getTangent","interpolateNormalDir","u0","u1","u2","u3","norm","bin","interpolateNormal","getNormalDir","iterDir1","iterDir2","vSub1","vSub2","vSub3","vSub4","d1v1","d1v2","d1v3","d1v4","d2v1","d2v2","d2v3","d2v4","interpolateColor","item1","item2","colFn","interpolatePicking","pickFn","interpolateSize","sizeFn","Spline","directional","positionIterator","subdiv","smoothSheet","interpolator","getAtomIterator","cache2","apPrev","apNext","getSubdividedColor","nCol","getSubdividedPicking","getSubdividedPosition","getSubdividedOrientation","normals","getNormals","tangent","binormal","getSubdividedSize","nSize","nPos","nTan","nNorm","vTangent","vMeshNormal","TubeMeshBufferDefaultParameters","capped","TubeMeshBuffer","capVertices","capTriangles","xi","size2","meshPrimitiveId","normX","normY","normZ","biX","biY","biZ","posX","posY","posZ","cxArr","cyArr","cx1Arr","cy1Arr","cx2Arr","cy2Arr","cx1","cy1","cx2","cy2","radialSegments1","irs","irs1","strip","CartoonRepresentation","NaN","getSplineParams","getSpline","getAspectRatio","polymerList","subPos","subOri","subCol","subPick","subSize","ContactRepresentation","angstrom","dataParams","contactData","unit","getLabelData","DihedralRepresentation","extendLine","lineVisible","dihedralData","lineTmp1","lineTmp2","sectorTmp","planeTmp","totalLines","totalPlanes","p4","v34","inPlane1","inPlane2","improperStart","improperEnd","nLines","nPlanes","line1","line2","sector","plane","li","nSuccess","linePosition1","linePosition2","planePosition","lineOffset","planeOffset","lp1","lp2","pp","getDihedralData","lineLength","lineColor","planeLength","planeBuffer","planeData","createUpdatedObject","updateSource","hasKey","obj","createColorArray","arrayLength","targetArray","DihedralHistogramRepresentation","histogramsData","histogramBinBorderVisible","scaleBinToSectorArea","histogramBinBorderColor","adjacentBondArrowColor","distantBondArrowColor","frontHistogramColor","backHistogramColor","opaqueMiddleDiscColor","histogramOpacity","opaqueMiddleDiscVisible","opaqueMiddleDiscOpacity","histogramBinBorderWidth","histogramBinBorderOpacity","bondArrowVisible","bondArrowWidth","bondArrowOpacity","specificColorData","getHistogramBinBorderBufferParameters","getBondArrowsBufferParameters","getOpaqueMiddleDiscBufferParameters","getHistogramBufferParameters","atomPositions","scaleData","Float32Concat","arrays","lengths","accumulatedOffset","createWideLineBuffer","linesList","startPoints","endPoints","startColors","endColors","createMeshBuffer","triangleColors","histogram360Scaled","histogram360","dihedralDataArray","currentHistogramData","calculateDihedralHistogram","frontHistogramBinBordersBuffer","frontHistogramBinBorders","backHistogramBinBordersBuffer","backHistogramBinBorders","adjacentBondArrowsBuffer","adjacentBondArrows","distantBondArrowsBuffer","distantBondArrows","opaqueMiddleDiscBuffer","opaqueMiddleDisc","frontHistogramBuffer","frontHistogram","backHistogramBuffer","backHistogram","histogramData","positionOfDihedralAtoms","histogram","totalSectorTrianglesInOpaqueMiddleDisc","frontAndBack","v32","cross1","dihedralAtomVectors","absAngle","maxHist","histBinAngleStep","setHistogramBinCoordinates","ind","zeroDegreeVector","crossVector","startOffset","scalingFactor","setOneSideHistogram","discHistogram","binBorders","sectionIndex","opaqueCircleSectorAngleStep","DistanceRepresentation","useCylinder","getDistanceData","pair","distanceData","bondParams","distanceBuffer","VectorBufferDefaultParameters","VectorBuffer","HelixorientRepresentation","LicoriceRepresentation","MappedBoxBuffer","HyperballStickImpostorBufferDefaultParameters","shrink","HyperballStickImpostorBufferParameterTypes","HyperballStickImpostorBuffer","HyperballStickBuffer","calculateMinArray","HyperballRepresentation","stickData","LabelFactory","errorLogged","atomLabel","aa1","res","qualified","LabelRepresentation","labelType","labelFormat","labelGrouping","getTextData","labelFactory","positionN","sizeN","colorN","getLoneAtomSet","LineRepresentation","crosses","lone","all","crossSize","_crossData","crossData","attrSize","cPosition1","cPosition2","cColor","cColor2","cOffset","cimax","crossBuffer","bufferIdx","lineAttributes","crossAttributes","makeGrid","DataCtor","elemSize","EDTSurface","coordList","pLength","pWidth","pHeight","ptran","depty","widxz","cutRadius","setAtomID","vpBits","vpDistance","vpAtomID","btype","_probeRadius","_scaleFactor","_cutoff","_setAtomID","boundingatom","INOUT","ISDONE","ISBOUND","txz","tdept","sradius","tradius","widxzR","deptyName","indx","fillatom","ox","oy","oz","mj","mk","sk","ii","jj","kk","deptyAtNind","deptyAt","nind","pWH","ci2","fillvoxels","fillAtomWaals","fastdistancemap","boundPoint","cutRSq","totalsurfacevox","inarray","positin","outarray","positout","fastoneshell","cutoffSq","tx","ty","tz","square","nbj","tnvix","tnviy","tnviz","getVolume","tk","buildboundary","fillvoxelswaals","stype","marchingcubeinit","vd","makeAVHash","atomsX","atomsY","atomsZ","atomsR","nAtoms","hashFunc","minW","iDim","jDim","kDim","nCells","jkDim","preHash","cid","cellOffsets","cellLengths","maxCellLength","subArray","cellLength","neighbourListLength","withinRadii","rExtra","nearI","nearJ","nearK","loI","loJ","loK","hiI","hiJ","hiK","iOffset","jOffset","cellStart","cellEnd","rSum","AVSurface","probePositions","gridx","gridy","gridz","sinTable","cosTable","lastClip","atob","ngTorus","_probePositions","rExt","surfGrid","fillGridDim","initializeGrid","initializeAngleTables","obscured","singleAtomObscures","ra2","projectPoints","ar","ar2","ng","iax","iay","iaz","minx","miny","minz","maxx","maxy","maxz","xoffset","dxy2","xyoffset","spx","spy","spz","dd","projectTorus","dmp","normalToLine","rInt","cost","sint","px","py","pz","projectTorii","fixNegatives","fixAtomIDs","MolecularSurface","_getAtomData","MolecularSurfaceRepresentation","vws","sas","ses","av","__infoList","__forceNewMolsurf","prepareData","molsurf","sviewFilter","maxDim","asWithin","getSurfaceParams","__sele","__surfaceParams","after","contourBuffer","doubleSidedBuffer","PointRepresentation","pointData","RibbonBuffer","aNormal","aSize","aDir","aPrimitiveId","currSize","prevSize","RibbonRepresentation","RocketRepresentation","axisList","helixbundleList","helixbundle","axisData","RopeRepresentation","SpacefillRepresentation","TraceBuffer","linePosition","TraceRepresentation","TubeRepresentation","UnitcellRepresentation","defaultRadius","cbrt","getUnitcellData","unitcellData","ValidationRepresentation","clashData","getClashData","ConeBufferDefaultParameters","ConeBuffer","ConeBufferGeometry","_position1","_position2","GeometryGroup","geometryList","empty","ArrowBufferDefaultParameters","ArrowBuffer","splitPosition","cylinderRadius","makeAttributes","coneBuffer","vFrom","vTo","vSplit","fullLength","coneLength","BoxBuffer","BoxBufferGeometry","_heightAxis","_depthAxis","_size","EllipsoidBufferDefaultParameters","EllipsoidBuffer","_majorAxis","_minorAxis","OctahedronBuffer","OctahedronBufferGeometry","TetrahedronBuffer","TetrahedronBufferGeometry","TorusBufferDefaultParameters","radiusRatio","tubularSegments","TorusBuffer","TorusBufferGeometry","Parser","_beforeParse","_parse","_afterParse","StructureParser","structureBuilder","Entity","description","chainIndexList","entityTypeFromString","entityFromType","isNonPolymer","isMacrolide","DefaultBoxParams","Unitcell","alphaRad","betaRad","gammaRad","cosAlpha","cosBeta","cosGamma","sinBeta","sinGamma","cStar","cosAlphaStar","cornerOffset","divideScalar","centerArray3","HelixTypes","dAminoAcids","entityKeyList","reWhitespace","getModresId","PdbParser","hex","isLegacy","headerLine","headerId","legacyId","isPqr","isPdbqt","serialRadix","resnoRadix","currentCoord","doFrames","currentBiomol","currentPart","currentMatrix","recordName","startChain","startResi","startIcode","endChain","endResi","endIcode","serialDict","unitcellDict","entityDataList","currentEntityData","currentEntityKey","hetnameDict","modresDict","chainDict","chainIdx","currentChainname","seqresDict","currentSeqresChainname","modelIdx","pendingStart","ls","modresId","fromIdx","toIdx","helixType","seqresChainname","keyEnd","biomt","biomtElms","ncsName","ncs","ncsRow","ncsElms","origx","orgix","origxRow","origxElms","scaleRow","scaleElms","aLength","bLength","cLength","sGroup","_parseChunkOfLines","ei","residueDict","reQuotedWhitespace","reDoubleQuote","reTrimQuotes","reAtomSymbol","trimQuotes","hasValue","cifDefaults","getBondOrder","valueOrder","CifParser","rawline","authAsymId","authSeqId","labelSeqId","labelAtomId","labelCompId","labelAsymId","labelEntityId","labelAltId","groupPDB","typeSymbol","pdbxPDBmodelNum","pdbxPDBinsCode","CartnX","CartnY","CartnZ","bIsoOrEquiv","cif","asymIdDict","chainIndexDict","pendingString","currentString","pendingValue","pendingLoop","pendingName","loopPointers","currentLoopIndex","currentCategory","currentName","pointerNames","modelNum","keyParts","category","keyValuePair","_modelNum","frameOffset","occ","assignedChainname","entityId","chem_comp","chem_comp_atom","struct","cc","cca","ccb","chem_comp_bond","atomnameDict","comp_id","atom_id","type_symbol","model_Cartn_x","model_Cartn_y","model_Cartn_z","pdbx_component_comp_id","pdbx_residue_numbering","pdbx_model_Cartn_x_ideal","pdbx_model_Cartn_y_ideal","pdbx_model_Cartn_z_ideal","atom_id_1","atom_id_2","value_order","parseChemComp","atom_site_type_symbol","atom_site_label","atom_site_fract_x","cell_length_a","cell_length_b","cell_length_c","cell_angle_alpha","cell_angle_beta","cell_angle_gamma","typeSymbolMap","atom_site_fract_y","atom_site_fract_z","atom_site_occupancy","ml","identityMatrix","covalentI","parseCore","begIcode","struct_conf","pdbx_PDB_helix_class","beg_auth_seq_id","pdbx_beg_PDB_ins_code","pdbx_end_PDB_ins_code","beg_label_asym_id","end_label_asym_id","end_auth_seq_id","ssr","struct_sheet_range","processSecondaryStructure","operDict","pdbx_struct_oper_list","biomolOp","elms","pdbx_struct_assembly_gen","gen","getMatrixDict","expr","es","assembly_id","oe","oper_expression","md1","md2","k1","k2","asym_id_list","struct_ncs_oper","ncsOp","ncsPart","cell","length_a","length_b","length_c","angle_alpha","angle_beta","angle_gamma","symmetry","database_PDB_matrix","origxMat","atom_sites","scaleMat","processSymmetry","struct_conn","atomIndicesCache","connTypeId","conn_type_id","ptnr1_symmetry","ptnr2_symmetry","inscode1","pdbx_ptnr1_PDB_ins_code","altloc1","pdbx_ptnr1_label_alt_id","ptnr1_auth_seq_id","ptnr1_label_asym_id","ptnr1_label_atom_id","selection1","inscode2","pdbx_ptnr2_PDB_ins_code","altloc2","pdbx_ptnr2_label_alt_id","ptnr2_auth_seq_id","ptnr2_label_asym_id","ptnr2_label_atom_id","selection2","tmpA","tmpB","pdbx_value_order","processConnections","pdbx_description","processEntities","entry","pdbx_audit_revision_history","revision_date","dates","releaseDate","pdbx_database_status","recvd_initial_deposition_date","depDates","depositionDate","database_PDB_rev","date","date_original","reflns","d_resolution_high","refine","ls_d_res_high","ls_R_factor_R_free","rFree","ls_R_factor_R_work","rWork","exptl","method","experimentalMethods","firstLines","lpos","ypos","zpos","modelLineCount","lineNo","AllFields","ctor","typedArray","getDataView","getInt8View","getInt32View","decodeInt16","i2","decodeInt32","i4","decodeInteger","intArray","divisor","invDiv","decodeRun","dataOffset","decodeDelta","decodePacking","int16or8","upperLimit","lowerLimit","decodeIntegerPacking","decodeIntegerDeltaPacking","unpacked","decodeIntegerDelta","decodeMsgpack","dataView","performDecoding","dvOut","dvIn","decodeFloat32","decodeIntegerRun","decodeMmtf","inputDict","ignoreFields","outputDict","dv","ignore","SstrucMap","groupData","numBonds","numAtoms","numGroups","numChains","numModels","chainsPerModel","structureId","groupsPerChain","groupList","groupTypeList","atomNameList","frameAtomOffset","xCoordList","yCoordList","zCoordList","bAtomIndex1","bAtomIndex2","bBondOrder","aGroupIndex","aFormalCharge","gChainIndex","gAtomOffset","gAtomCount","cModelIndex","cGroupOffset","cGroupCount","mChainOffset","mChainCount","modelChainCount","groupOffset","chainGroupCount","bondOffset","groupAtomCount","groupFormalChargeList","formalChargeList","groupBondAtomList","bondAtomList","groupBondOrderList","bondOrderList","atomIdList","bFactorList","altLocList","occupancyList","groupIdList","secStructList","insCodeList","chainNameList","chainIdList","groupTypeDict","groupType","elementList","hetFlag","numGroupBonds","groupName","resAtomOffset","secStructLength","bioAssemblyList","_assembly","chainToPart","transformList","_transform","ncsOperatorList","ncsAssembly","_operator","unitCell","spaceGroup","bondTypes","am","du","un","moleculeLineNo","modelAtomIdxStart","currentRecordType","reItem","SdfParser","headerLines","sdfData","mItem","atomStart","bondStart","bondEnd","currentItem","currentData","isV3000","isAtomBlock","isBondBlock","acc","atomindexToStoreindex","chgTok","find","chargeCount","coffset","atomIdx","cToken","_postProcess","parseIntSubstr","PrmtopParser","pointersDict","pointers","atomNames","radii","residueLabels","residuePointers","curIdx","bondIdx","lt","NATOM","NBONH","MBONA","NRES","curResIdx","curResname","curResno","reTitle","lastSegid","segid","reField","molecules","moleculetypeDict","currentMoleculetype","fieldMatch","cIdx","molName","molCount","molType","lastResno","resIdx","chainidIdx","chainnameIdx","TrajectoryParser","notNetcdf","statement","reason","TypeError","readName","nameLength","nextPos","intView","ef","isCharmm","extraBlock","fourDims","NSET","ISTART","NSAVC","NAMNF","DELTA","titleLength","titlePos","TITLE","natom","natom4","BYTE","CHAR","SHORT","INT","DOUBLE","num2str","num2bytes","str2num","readNumber","bufferReader","numbers","readType","trimNull","ZERO","NC_DIMENSION","NC_VARIABLE","NC_ATTRIBUTE","version","recordDimension","dimList","dimensions","recordId","dimensionSize","dimensionsList","globalAttributes","attributesList","variables","varList","recordStep","variableSize","dimensionality","dimensionsIds","varSize","record","variablesList","gAttList","gAtt","NetcdfReader","hasDataVariable","variableName","findIndex","getDataVariable","variable","currentOffset","nonRecord","NctrajParser","netcdfReader","versionSize","virSize","presSize","coordSize","velocitySize","forceSize","natoms","floatSize","natoms3","frameCoords","MagicInts","sizeOfInt","num","numOfBits","_tmpBytes","sizeOfInts","numOfInts","sizes","numOfBytes","bytecnt","decodeBits","cbuf","buf2","mask","lastBB0","lastBB1","cnt","_tmpIntBytes","decodeInts","nums","minMaxInt","sizeint","bitsizeint","sizesmall","thiscoord","prevcoord","lfp","lsize","bitsize","smallidx","tmpIdx","smaller","smallnum","adz","invPrecision","buf8","isSmaller","tmpSwap","VolumeParser","getMatrix","reScientificNotation","bohrToAngstromFactor","CubeParser","originX","originY","originZ","NVX","NVY","NVZ","basisX","basisY","basisZ","oribitalFlag","lj","Dsn6Parser","summand","byteView","brixStr","xStart","yStart","zStart","xExtent","yExtent","zExtent","xRate","yRate","zRate","xlen","ylen","zlen","xBlocks","yBlocks","zBlocks","zz","yy","xx","nxyz","mapcrs","DxParser","headerInfo","parseHeaderLines","dataLineStart","headerByteCount","deltaLineCount","xmin","ymin","zmin","hx","hy","hz","uint8ToLines","MrcParser","floatView","MAP","MACHST","NX","NY","MODE","NXSTART","NYSTART","NZSTART","MX","MY","MZ","MAPC","MAPR","MAPS","DMIN","DMAX","ISPG","NSYMBT","LSKFLG","b1","b0","parseNumberLine","XplorParser","infoStart","dataStart","gridInfo","AMIN","AMAX","BMIN","BMAX","NC","CMIN","CMAX","cellInfo","lineSection","RAVE","RSIGMA","hsvToRgb","ColorDict","red","orange","gold","yellow","lime","green","sea","cyan","sky","blue","purple","magenta","hotpink","pink","peach","lilac","pinktint","peachtint","yellowtint","greentint","bluetint","lilactint","white","gray","brown","deadwhite","deadblack","invisible","reWhitespaceComma","reCurlyWhitespace","reTrimCurly","reCollapseEqual","parseListDef","defaultColor","master","lm","listName","listColor","listMasters","listWidth","parseListElm","lineBreak","triangleBreak","lsindex","literal","isLineBreak","isTriangleBreak","parseStr","parseFlag","parseGroup","flags","groupFlags","groupMasters","kinemage","onewidth","pdbfile","texts","captions","caption","groupDict","subgroupDict","masterDict","pointmasterDict","dotLists","vectorLists","ballLists","ribbonLists","currentGroupMasters","currentSubgroupMasters","dotDefaultColor","dotLabel","dotPosition","dotColor","vecDefaultColor","vecDefaultWidth","vecLabel1","vecLabel2","vecPosition1","vecPosition2","vecColor1","vecColor2","ballRadius","ballDefaultColor","ballLabel","ballPosition","ballColor","ribbonListDefaultColor","ribbonPointLabelArray","ribbonPointPositionArray","ribbonPointBreakArray","ribbonPointColorArray","isDotList","prevDotLabel","isVectorList","prevVecLabel","prevVecPosition","prevVecColor","isBallList","prevBallLabel","isRibbonList","prevRibbonPointLabel","isCaption","masterArray","labelArray","colorArray","indent","label1Array","label2Array","position1Array","position2Array","color1Array","color2Array","radiusArray","breakArray","splitLine","singlePointLine","dominant","convertedLists","listObject","convertedRibbonObject","editedLabels","editedPositions","editedColors","editedBreaks","breakPointer","positionPointer","removePointBreaksTriangleArrays","ribbonObject","convertedLabels","convertedBreaks","convertedPositions","convertedColors","vector3Positions","convertKinTriangleArrays","SurfaceParser","getLoader","OBJLoader","regexp","vertex_pattern","normal_pattern","uv_pattern","face_vertex","face_vertex_uv","face_vertex_uv_normal","face_vertex_normal","object_pattern","smoothing_pattern","material_library_pattern","material_use_pattern","setPath","_createParserState","objects","startObject","fromDeclaration","parseVertexIndex","parseNormalIndex","addVertex","addVertexLine","addNormal","addFace","nd","vLen","ib","ic","nLen","addLineGeometry","vi","lineFirstChar","lineSecondChar","trimLeft","lineParts","lineVertices","lineUVs","llen","parts","buffergeometry","PLYLoader","propertyNameMapping","setPropertyNameMapping","bin2str","isASCII","parseHeader","parseASCII","parseBinary","headerText","headerLength","currentElement","lineType","lineValues","propertValues","comments","countType","itemType","parseASCIINumber","parseASCIIElement","currentElementCount","useColor","handleElement","postProcess","colors","elementsNeedUpdate","elementName","setRGB","vertexIndices","vertex_indices","Face3","binaryRead","dataview","binaryReadElement","loc","table","reDelimiter","msgpack","netcdf","TextParser","reStrip","reTag","reContent","reAttr","parseXml","declaration","root","tag","eos","is","child","re","prefix","XmlParser","useDomParser","__xmlParser","__domParser","DOMParser","parseFromString","Document","getNamedItem","getSele","useAltcode","icode","altcode","getResSele","setBitDict","bit","hasAttrValue","getProblemCount","clashDict","ga","clashes","getElementsByTagName","Validation","atomDict","clashSele","fromXml","entries","chemicalShiftLists","randomCoilIndices","rcia","_clashDict","clashList","seleAttr","createAttribute","setNamedItem","atomSele","res1","res2","mogBondOutliers","mogAngleOutliers","vPos1","vPos2","getAtomSele","dHalf","shrinkBuf","arraySet","dest","src_offs","dest_offs","adler32","adler","crcTable","makeTable","crc32","crc","BAD$1","TYPE$1","inflate_fast","strm","_in","last","_out","dmax","wsize","whave","wnext","s_window","lcode","dcode","lmask","dmask","here","op","from_source","next_in","avail_in","next_out","avail_out","lencode","distcode","lenbits","distbits","dolen","dodist","sane","MAXBITS","ENOUGH_LENS$1","ENOUGH_DISTS$1","CODES$1","LENS$1","DISTS$1","lbase","lext","dbase","dext","inflate_table","lens","lens_index","codes","table_index","work","incr","here_bits","here_op","here_val","curr","drop","used","huff","base_index","offs","extra","extra_index","LENS","DISTS","Z_OK","Z_STREAM_ERROR","HEAD","TYPE","BAD","ENOUGH_LENS","ENOUGH_DISTS","zswap32","InflateState","havedict","check","total","wbits","ncode","nlen","ndist","have","lendyn","distdyn","was","inflateReset","total_in","total_out","inflateResetKeep","inflateInit2","windowBits","inflateReset2","lenfix","distfix","virgin","fixedtables","updatewindow","flush","put","last_bits","last_op","last_val","hbuf","inf_leave","xflags","os","extra_len","hcrc","data_type","inflateSetDictionary","dictionary","dictLength","STR_APPLY_OK","STR_APPLY_UIA_OK","__","_utf8len","string2buf","m_pos","str_len","buf_len","buf2string","c_len","utf16buf","_buf2binstring","utf8border","Z_OK$1","messages","ZStream","GZheader","Inflate","sources","source","raw","err","ended","_mode","next_out_utf8","tail","utf8str","allowBufError","binstring2buf","onEnd","onData","inflateEnd","flattenChunks","decompressedData","inflator","ungzip","Datasource","mmtfBaseUrl","mmtfFullUrl","mmtfReducedUrl","pdbid","baseUrl","suffixUrl","PassThroughDatasource","suffixURL","uniprotid","reProtocol","StaticDatasource","relativePath","pn","pathname","basePath","getAbsolutePath","MdsrvDatasource","getListing","jsonData","frameIndex","getPathUrl","IntegerParam","NumberParam","RangeParam","SelectParam","UIStageParameters","Version"],"mappings":"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GAAI,KAAM,GAAI,EAAK,GAAI,KAAM,GAAI,IAAK,GAAI,IAAK,GAAI,IAAK,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,IAAK,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,IAAK,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,IAAK,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,IAAK,GAAI,IAAK,GAAI,KAAM,GAAI,EAAK,GAAI,EAAK,GAAI,KAAM,GAAI,IAAK,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,IAAK,GAAI,KAAM,GAAI,KAAM,GAAI,EAAK,GAAI,IAAK,GAAI,EAAK,GAAI,IAAK,GAAI,EAAK,GAAI,EAAK,GAAI,EAAK,GAAI,EAAK,GAAI,EAAK,GAAI,EAAK,GAAI,EAAK,IAAK,EAAK,IAAK,EAAK,IAAK,EAAK,IAAK,EAAK,IAAK,EAAK,IAAK,EAAK,IAAK,EAAK,IAAK,EAAK,IAAK,EAAK,IAAK,EAAK,IAAK,EAAK,IAAK,EAAK,IAAK,EAAK,IAAK,EAAK,IAAK,EAAK,IAAK,EAAK,IAAK,EAAK,IAAK,EAAK,IAAK,GAouB5lCC,GAAqD,CAChE,EAAG,IAAM,EAAG,IAAM,EAAG,KAAM,EAAG,IAAM,EAAG,IAAM,EAAG,IAAM,EAAG,IAAM,EAAG,IAAM,EAAG,IAAM,GAAI,IAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,IAAK,GAAI,IAAK,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,IAAK,GAAI,KAAM,GAAI,IAAK,GAAI,IAAK,GAAI,KAAM,GAAI,IAAK,GAAI,KAAM,GAAI,IAAK,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAAI,KAAM,GAA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KACvE,MAAO,KAAM,MAAO,MAAO,KAAM,MAAO,MAAO,MAAO,MAEtD,OAYWC,GAAkB,CAC7B,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAC/D,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MACtE,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO,MAAO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D,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAC1D,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EACvD,EAAG,EAAG,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAC3D,EAAG,EAAG,EAAG,EAAG,EAAG,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EACxD,EAAG,EAAG,GAAI,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EACxD,EAAG,EAAG,EAAG,EAAG,GAAI,EAAG,GAAI,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EACtD,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAC3D,EAAG,GAAI,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EACzD,EAAG,EAAG,EAAG,EAAG,EAAG,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EACxD,EAAG,GAAI,EAAG,EAAG,EAAG,GAAI,EAAG,EAAG,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EACvD,EAAG,GAAI,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAC1D,EAAG,GAAI,EAAG,EAAG,EAAG,GAAI,EAAG,GAAI,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EACxD,EAAG,EAAG,EAAG,EAAG,GAAI,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EACvD,EAAG,EAAG,GAAI,GAAI,EAAG,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EAC1D,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI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,GAAI,GAAI,GAAI,EAAG,GAAI,GAAI,GAAI,GAAI,EACrD,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,EAAG,IAAK,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EACvD,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EACvD,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EACpD,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EACpD,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EACvD,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EACrD,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,EAClD,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,EAAG,GAAI,GAAI,GAAI,GAAI,EAClD,EAAG,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EACrD,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EACrD,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,IAAK,GAAI,GAAI,GAAI,EAClD,EAAG,EAAG,GAAI,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,EAClD,GAAI,EAAG,EAAG,GAAI,EAAG,EAAG,EAAG,EAAG,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,GAAI,EACtD,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,GAAI,EAAG,EAAG,GAAI,EAAG,IAAK,GAAI,GAAI,GAAI,EACpD,EAAG,EAAG,EAAG,EAAG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"} \ No newline at end of file +{"version":3,"file":"ngl.esm.js","sources":["../src/utils.ts","../src/utils/registry.ts","../src/math/math-utils.ts","../src/color/colormaker.ts","../src/selection/selection-constants.ts","../src/selection/selection-test.ts","../src/selection/selection.ts","../src/selection/selection-parser.ts","../src/color/selection-colormaker.ts","../src/color/colormaker-registry.ts","../src/worker/worker-utils.ts","../src/globals.ts","../src/worker/worker-registry.ts","../src/parser/parser-registry.ts","../src/streamer/streamer.ts","../src/streamer/file-streamer.ts","../src/streamer/network-streamer.ts","../src/loader/loader.ts","../src/loader/parser-loader.ts","../src/script.ts","../src/loader/script-loader.ts","../src/loader/loader-utils.ts","../src/writer/writer.ts","../src/writer/pdb-writer.ts","../src/writer/sdf-writer.ts","../src/utils/io-buffer.ts","../src/writer/stl-writer.ts","../src/utils/counter.ts","../src/viewer/stats.ts","../src/shader/shader-utils.ts","../src/viewer/viewer-constants.ts","../src/viewer/tiled-renderer.ts","../src/math/math-constants.ts","../src/math/array-utils.ts","../src/viewer/viewer-utils.ts","../src/viewer/gl-utils.ts","../src/viewer/viewer.ts","../src/constants.ts","../src/stage/mouse-observer.ts","../src/controls/trackball-controls.ts","../src/controls/picking-proxy.ts","../src/controls/picking-controls.ts","../src/controls/viewer-controls.ts","../src/animation/animation.ts","../src/controls/animation-controls.ts","../src/utils/queue.ts","../src/representation/representation.ts","../src/worker/worker.ts","../src/worker/worker-pool.ts","../src/math/vector-utils.ts","../src/geometry/dash.ts","../src/geometry/primitive.ts","../src/geometry/spatial-hash.ts","../src/store/store.ts","../src/store/contact-store.ts","../src/utils/bitarray.ts","../src/utils/adjacency-list.ts","../src/chemistry/interactions/features.ts","../src/structure/structure-constants.ts","../src/chemistry/geometry.ts","../src/chemistry/valence-model.ts","../src/structure/data.ts","../src/chemistry/functional-groups.ts","../src/chemistry/interactions/charged.ts","../src/chemistry/interactions/hydrogen-bonds.ts","../src/chemistry/interactions/metal-binding.ts","../src/chemistry/interactions/halogen-bonds.ts","../src/chemistry/interactions/refine-contacts.ts","../src/chemistry/interactions/contact.ts","../src/chemistry/interactions/hydrophobic.ts","../src/utils/picker.ts","../src/surface/marching-cubes.ts","../src/math/matrix-utils.ts","../src/surface/surface-utils.ts","../src/surface/surface.ts","../src/surface/volume.ts","../src/buffer/buffer.ts","../src/buffer/mesh-buffer.ts","../src/buffer/surface-buffer.ts","../src/buffer/doublesided-buffer.ts","../src/buffer/contour-buffer.ts","../src/representation/surface-representation.ts","../src/controls/mouse-actions.ts","../src/controls/mouse-controls.ts","../src/controls/key-actions.ts","../src/controls/key-controls.ts","../src/stage/picking-behavior.ts","../src/stage/mouse-behavior.ts","../src/stage/animation-behavior.ts","../src/stage/key-behavior.ts","../src/component/annotation.ts","../src/controls/component-controls.ts","../src/utils/radius-factory.ts","../src/math/principal-axes.ts","../src/surface/filtered-volume.ts","../src/store/bond-hash.ts","../src/store/bond-store.ts","../src/store/atom-store.ts","../src/store/residue-store.ts","../src/store/chain-store.ts","../src/store/model-store.ts","../src/geometry/helixorient.ts","../src/geometry/helixbundle.ts","../src/utils/binary-heap.ts","../src/utils/kdtree.ts","../src/proxy/atom-proxy.ts","../src/geometry/kdtree.ts","../src/symmetry/symmetry-constants.ts","../src/symmetry/symmetry-utils.ts","../src/symmetry/assembly.ts","../src/structure/structure-builder.ts","../src/structure/structure-utils.ts","../src/store/atom-type.ts","../src/store/atom-map.ts","../src/store/residue-type.ts","../src/store/residue-map.ts","../src/proxy/bond-proxy.ts","../src/proxy/residue-proxy.ts","../src/proxy/polymer.ts","../src/proxy/chain-proxy.ts","../src/proxy/model-proxy.ts","../src/structure/structure.ts","../src/geometry/shape.ts","../src/representation/buffer-representation.ts","../src/buffer/geometry-buffer.ts","../src/buffer/spheregeometry-buffer.ts","../src/buffer/mapped-buffer.ts","../src/buffer/mappedquad-buffer.ts","../src/buffer/sphereimpostor-buffer.ts","../src/buffer/sphere-buffer.ts","../src/buffer/point-buffer.ts","../src/representation/dot-representation.ts","../src/buffer/image-buffer.ts","../src/surface/volume-slice.ts","../src/representation/slice-representation.ts","../src/representation/representation-utils.ts","../src/component/element.ts","../src/component/representation-element.ts","../src/component/component.ts","../src/component/collection.ts","../src/component/representation-collection.ts","../src/component/trajectory-element.ts","../src/trajectory/frames.ts","../src/align/superposition.ts","../src/trajectory/trajectory-player.ts","../src/trajectory/trajectory.ts","../src/trajectory/frames-trajectory.ts","../src/trajectory/structure-trajectory.ts","../src/trajectory/remote-trajectory.ts","../src/trajectory/callback-trajectory.ts","../src/structure/structure-view.ts","../src/align/alignment.ts","../src/align/align-utils.ts","../src/component/structure-component.ts","../src/trajectory/trajectory-utils.ts","../src/component/surface-component.ts","../src/component/volume-component.ts","../src/component/component-collection.ts","../src/stage/stage.ts","../src/component/shape-component.ts","../node_modules/tslib/tslib.es6.js","../src/color/atomindex-colormaker.ts","../src/color/bfactor-colormaker.ts","../src/color/chainid-colormaker.ts","../src/color/chainindex-colormaker.ts","../src/color/chainname-colormaker.ts","../src/color/densityfit-colormaker.ts","../src/color/electrostatic-colormaker.ts","../src/color/element-colormaker.ts","../src/color/entityindex-colormaker.ts","../src/color/entitytype-colormaker.ts","../src/color/geoquality-colormaker.ts","../src/color/hydrophobicity-colormaker.ts","../src/color/modelindex-colormaker.ts","../src/color/moleculetype-colormaker.ts","../src/color/occupancy-colormaker.ts","../src/color/partialcharge-colormaker.ts","../src/color/random-colormaker.ts","../src/color/randomcoilindex-colormaker.ts","../src/color/residueindex-colormaker.ts","../src/color/resname-colormaker.ts","../src/color/sstruc-colormaker.ts","../src/color/structuredata-colormaker.ts","../src/color/uniform-colormaker.ts","../src/color/value-colormaker.ts","../src/color/volume-colormaker.ts","../src/representation/structure-representation.ts","../src/representation/measurement-representation.ts","../src/utils/edt.ts","../src/buffer/text-buffer.ts","../src/buffer/wideline-buffer.ts","../src/representation/angle-representation.ts","../src/buffer/cylindergeometry-buffer.ts","../src/buffer/mappedalignedbox-buffer.ts","../src/buffer/cylinderimpostor-buffer.ts","../src/buffer/cylinder-buffer.ts","../src/representation/axes-representation.ts","../src/representation/ballandstick-representation.ts","../src/representation/backbone-representation.ts","../src/representation/base-representation.ts","../src/geometry/spline.ts","../src/buffer/tubemesh-buffer.ts","../src/representation/cartoon-representation.ts","../src/representation/contact-representation.ts","../src/representation/dihedral-representation.ts","../src/representation/dihedral-histogram-representation.ts","../src/representation/distance-representation.ts","../src/buffer/vector-buffer.ts","../src/representation/helixorient-representation.ts","../src/representation/licorice-representation.ts","../src/buffer/mappedbox-buffer.ts","../src/buffer/hyperballstickimpostor-buffer.ts","../src/buffer/hyperballstick-buffer.ts","../src/representation/hyperball-representation.ts","../src/utils/label-factory.ts","../src/representation/label-representation.ts","../src/representation/line-representation.ts","../src/geometry/grid.ts","../src/surface/edt-surface.ts","../src/surface/av-surface.ts","../src/surface/molecular-surface.ts","../src/representation/molecularsurface-representation.ts","../src/representation/point-representation.ts","../src/buffer/ribbon-buffer.ts","../src/representation/ribbon-representation.ts","../src/representation/rocket-representation.ts","../src/representation/rope-representation.ts","../src/representation/spacefill-representation.ts","../src/buffer/trace-buffer.ts","../src/representation/trace-representation.ts","../src/representation/tube-representation.ts","../src/representation/unitcell-representation.ts","../src/representation/validation-representation.ts","../src/buffer/cone-buffer.ts","../src/viewer/geometry-group.ts","../src/buffer/arrow-buffer.ts","../src/buffer/box-buffer.ts","../src/buffer/ellipsoid-buffer.ts","../src/buffer/octahedron-buffer.ts","../src/buffer/tetrahedron-buffer.ts","../src/buffer/torus-buffer.ts","../node_modules/molstar/lib/mol-data/db/column-helpers.js","../node_modules/molstar/lib/mol-math/linear-algebra/3d/common.js","../node_modules/molstar/lib/mol-math/interpolate.js","../node_modules/molstar/lib/mol-math/linear-algebra/3d/vec3.js","../node_modules/molstar/lib/mol-math/misc.js","../node_modules/molstar/lib/mol-math/linear-algebra/3d/mat4.js","../node_modules/molstar/lib/mol-math/linear-algebra/3d/mat3.js","../node_modules/molstar/lib/mol-math/linear-algebra/3d/vec2.js","../node_modules/molstar/lib/mol-math/linear-algebra/3d/vec4.js","../node_modules/molstar/lib/mol-util/type-helpers.js","../node_modules/molstar/lib/mol-math/linear-algebra/3d/quat.js","../node_modules/molstar/lib/mol-math/linear-algebra/tensor.js","../node_modules/molstar/lib/mol-data/db/column.js","../node_modules/molstar/lib/mol-util/bit-flags.js","../node_modules/molstar/lib/mol-util/string-builder.js","../node_modules/molstar/lib/mol-io/reader/common/text/number-parser.js","../node_modules/molstar/lib/mol-data/util/sort.js","../node_modules/molstar/lib/mol-util/now.js","../node_modules/molstar/lib/mol-util/uuid.js","../node_modules/molstar/lib/mol-util/mask.js","../node_modules/molstar/lib/mol-util/value-cell.js","../node_modules/molstar/lib/mol-util/id-factory.js","../node_modules/molstar/lib/mol-data/db/table.js","../node_modules/molstar/lib/mol-data/db/database.js","../node_modules/molstar/lib/mol-io/reader/cif/data-model.js","../node_modules/molstar/lib/mol-io/reader/common/text/column/token.js","../node_modules/molstar/lib/mol-task/util/scheduler.js","../node_modules/molstar/lib/mol-util/debug.js","../node_modules/molstar/lib/mol-task/util/user-timing.js","../node_modules/molstar/lib/mol-task/execution/observable.js","../node_modules/molstar/lib/mol-task/execution/synchronous.js","../node_modules/molstar/lib/mol-task/task.js","../node_modules/molstar/lib/mol-task/execution/runtime-context.js","../node_modules/molstar/lib/mol-task/execution/progress.js","../node_modules/molstar/lib/mol-io/reader/common/text/tokenizer.js","../node_modules/molstar/lib/mol-io/reader/result.js","../node_modules/molstar/lib/mol-io/common/binary-cif/encoding.js","../node_modules/molstar/lib/mol-task/util/chunked.js","../node_modules/molstar/lib/mol-io/reader/cif/text/parser.js","../node_modules/molstar/lib/mol-io/common/binary.js","../node_modules/molstar/lib/mol-io/common/binary-cif/decoder.js","../node_modules/molstar/lib/mol-data/util/chunked-array.js","../node_modules/molstar/lib/mol-io/common/binary-cif/classifier.js","../node_modules/molstar/lib/mol-io/common/binary-cif/array-encoder.js","../node_modules/molstar/lib/mol-util/number.js","../node_modules/molstar/lib/mol-io/common/utf8.js","../node_modules/molstar/lib/mol-io/common/msgpack/decode.js","../node_modules/molstar/lib/mol-io/reader/cif/binary/parser.js","../node_modules/molstar/lib/mol-io/reader/cif/binary/field.js","../node_modules/molstar/lib/mol-io/reader/cif/schema.js","../node_modules/molstar/lib/mol-util/index.js","../node_modules/molstar/lib/mol-io/reader/cif/schema/mmcif.js","../node_modules/molstar/lib/mol-io/reader/cif/schema/ccd.js","../node_modules/molstar/lib/mol-io/reader/cif/schema/bird.js","../node_modules/molstar/lib/mol-io/reader/cif/schema/dic.js","../node_modules/molstar/lib/mol-io/reader/cif/schema/density-server.js","../node_modules/molstar/lib/mol-io/reader/cif/schema/cif-core.js","../node_modules/molstar/lib/mol-io/reader/cif/schema/segmentation.js","../node_modules/molstar/lib/mol-io/reader/cif.js","../src/parser/parser.ts","../src/parser/structure-parser.ts","../src/structure/entity.ts","../src/symmetry/unitcell.ts","../src/parser/pdb-parser.ts","../src/store/chemcomp-map.ts","../src/parser/cif-parser.ts","../src/parser/gro-parser.ts","../lib/mmtf.es6.js","../src/parser/mmtf-parser.ts","../src/parser/mol2-parser.ts","../src/parser/pdbqt-parser.ts","../src/parser/pqr-parser.ts","../src/parser/sdf-parser.ts","../src/parser/prmtop-parser.ts","../src/parser/psf-parser.ts","../src/parser/top-parser.ts","../src/parser/trajectory-parser.ts","../src/utils/netcdf-reader.ts","../src/parser/dcd-parser.ts","../src/parser/nctraj-parser.ts","../src/parser/trr-parser.ts","../src/parser/xtc-parser.ts","../src/parser/volume-parser.ts","../src/parser/cube-parser.ts","../src/parser/dsn6-parser.ts","../src/parser/dx-parser.ts","../src/parser/dxbin-parser.ts","../src/parser/mrc-parser.ts","../src/parser/xplor-parser.ts","../src/parser/kin-parser.ts","../src/parser/surface-parser.ts","../src/parser/obj-parser.ts","../src/parser/csv-parser.ts","../src/parser/json-parser.ts","../src/parser/msgpack-parser.ts","../src/parser/netcdf-parser.ts","../src/parser/text-parser.ts","../src/utils/parse-xml.ts","../src/parser/xml-parser.ts","../src/structure/validation.ts","../lib/pako_inflate.es6.js","../src/parser/validation-parser.ts","../src/utils/gzip-decompressor.ts","../src/datasource/datasource.ts","../src/datasource/rcsb-datasource.ts","../src/datasource/pdbe-datasource.ts","../src/datasource/pubchem-datasource.ts","../src/datasource/passthrough-datasource.ts","../src/datasource/alphafold-datasource.ts","../src/datasource/static-datasource.ts","../src/datasource/mdsrv-datasource.ts","../src/ui/parameters.ts","../src/version.ts"],"sourcesContent":["/**\n * @file Utils\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector2, Vector3, Matrix4, Quaternion } from 'three'\n\nexport function getQuery (id: string) {\n if (typeof window === 'undefined') return undefined\n\n const a = new RegExp(`${id}=([^&#=]*)`)\n const m = a.exec(window.location.search)\n\n if (m) {\n return decodeURIComponent(m[1])\n } else {\n return undefined\n }\n}\n\nexport function boolean (value: any) {\n if (!value) {\n return false\n }\n\n if (typeof value === 'string') {\n return /^1|true|t|yes|y$/i.test(value)\n }\n\n return true\n}\n\nexport function defaults (value: any, defaultValue: any) {\n return value !== undefined ? value : defaultValue\n}\n\nexport function createParams (params: {[k in keyof T]?: any}, defaultParams: T) {\n const o: any = Object.assign({}, params)\n for (const k in defaultParams) {\n const value = params[k]\n if (value === undefined) o[k] = defaultParams[k]\n }\n return o as T\n}\n\nexport function updateParams (params: T, newParams: {[k in keyof T]?: any}) {\n for (const k in newParams) {\n const value = newParams[k]\n if (value !== undefined) params[k] = value\n }\n return params as T\n}\n\nexport function pick (object: { [index: string]: any }) {\n const properties = [].slice.call(arguments, 1)\n return properties.reduce((a: { [index: string]: any }, e: any) => {\n a[ e ] = object[ e ]\n return a\n }, {})\n}\n\nexport function flatten (array: any[], ret: any[]) {\n ret = defaults(ret, [])\n for (let i = 0; i < array.length; i++) {\n if (Array.isArray(array[i])) {\n flatten(array[i], ret)\n } else {\n ret.push(array[i])\n }\n }\n return ret\n}\n\nexport function getProtocol () {\n const protocol = window.location.protocol\n return protocol.match(/http(s)?:/gi) === null ? 'http:' : protocol\n}\n\nexport function getBrowser () {\n if (typeof window === 'undefined') return false\n\n const ua = window.navigator.userAgent\n\n if (/Opera|OPR/.test(ua)) {\n return 'Opera'\n } else if (/Chrome/i.test(ua)) {\n return 'Chrome'\n } else if (/Firefox/i.test(ua)) {\n return 'Firefox'\n } else if (/Mobile(\\/.*)? Safari/i.test(ua)) {\n return 'Mobile Safari'\n } else if (/MSIE/i.test(ua)) {\n return 'Internet Explorer'\n } else if (/Safari/i.test(ua)) {\n return 'Safari'\n }\n\n return false\n}\n\nexport function getAbsolutePath (relativePath: string) {\n const loc = window.location\n const pn = loc.pathname\n const basePath = pn.substring(0, pn.lastIndexOf('/') + 1)\n\n return loc.origin + basePath + relativePath\n}\n\nexport function deepCopy (src: any) {\n if (typeof src !== 'object') {\n return src\n }\n\n const dst: { [index: string]: any } = Array.isArray(src) ? [] : {}\n\n for (let key in src) {\n dst[ key ] = deepCopy(src[ key ])\n }\n\n return dst\n}\n\nexport function deepEqual(a: any, b: any) {\n // from https://github.com/epoberezkin/fast-deep-equal MIT\n if (a === b) return true;\n\n const arrA = Array.isArray(a)\n const arrB = Array.isArray(b)\n\n if (arrA && arrB) {\n if (a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) {\n if (!deepEqual(a[i], b[i])) return false\n }\n return true\n }\n\n if (arrA !== arrB) return false\n\n if (a && b && typeof a === 'object' && typeof b === 'object') {\n const keys = Object.keys(a)\n if (keys.length !== Object.keys(b).length) return false;\n\n const dateA = a instanceof Date\n const dateB = b instanceof Date\n if (dateA && dateB) return a.getTime() === b.getTime()\n if (dateA !== dateB) return false\n\n const regexpA = a instanceof RegExp\n const regexpB = b instanceof RegExp\n if (regexpA && regexpB) return a.toString() === b.toString()\n if (regexpA !== regexpB) return false\n\n for (let i = 0; i < keys.length; i++) {\n if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false\n }\n\n for (let i = 0; i < keys.length; i++) {\n if(!deepEqual(a[keys[i]], b[keys[i]])) return false\n }\n\n return true\n }\n\n return false\n}\n\nfunction openUrl (url: string) {\n const opened = window.open(url, '_blank')\n if (!opened) {\n window.location.href = url\n }\n}\n\nexport function download (data: Blob|string, downloadName = 'download') {\n // using ideas from https://github.com/eligrey/FileSaver.js/blob/master/FileSaver.js\n\n if (!data) return\n\n const isSafari = getBrowser() === 'Safari'\n const isChromeIos = /CriOS\\/[\\d]+/.test(window.navigator.userAgent)\n\n const a = document.createElement('a')\n\n function open (str: string) {\n openUrl(isChromeIos ? str : str.replace(/^data:[^;]*;/, 'data:attachment/file;'))\n }\n\n if (typeof navigator !== 'undefined' && (navigator as any).msSaveOrOpenBlob) {\n // native saveAs in IE 10+\n (navigator as any).msSaveOrOpenBlob(data, downloadName)\n } else if ((isSafari || isChromeIos) && FileReader) {\n if (data instanceof Blob) {\n // no downloading of blob urls in Safari\n var reader = new FileReader()\n reader.onloadend = function () {\n open(reader.result as string)\n }\n reader.readAsDataURL(data)\n } else {\n open(data)\n }\n } else {\n let objectUrlCreated = false\n if (data instanceof Blob) {\n data = URL.createObjectURL(data)\n objectUrlCreated = true\n }\n\n if ('download' in a) {\n // download link available\n a.style.display = 'hidden'\n document.body.appendChild(a)\n a.href = data\n a.download = downloadName\n a.target = '_blank'\n a.click()\n document.body.removeChild(a)\n } else {\n openUrl(data)\n }\n\n if (objectUrlCreated) {\n window.URL.revokeObjectURL(data)\n }\n }\n}\n\nexport function submit (url: string, data: FormData, callback: Function, onerror: Function) {\n const xhr = new XMLHttpRequest()\n xhr.open('POST', url)\n\n xhr.addEventListener('load', function () {\n if (xhr.status === 200 || xhr.status === 304) {\n callback(xhr.response)\n } else {\n if (typeof onerror === 'function') {\n onerror(xhr.status)\n }\n }\n }, false)\n\n xhr.send(data)\n}\n\ninterface HTMLInputEvent extends Event {\n target: HTMLInputElement & EventTarget\n}\n\nexport function open (callback: Function, extensionList = ['*']) {\n const fileInput = document.createElement('input')\n fileInput.type = 'file'\n fileInput.multiple = true\n fileInput.style.display = 'hidden'\n document.body.appendChild(fileInput)\n fileInput.accept = '.' + extensionList.join(',.')\n fileInput.addEventListener('change', function (e: HTMLInputEvent) {\n callback(e.target.files)\n }, false)\n\n fileInput.click()\n}\n\nexport function throttle (func: Function, wait: number, options: { leading?: boolean, trailing?: boolean }) {\n // from http://underscorejs.org/docs/underscore.html\n\n let context: any\n let args: any\n let result: any\n let timeout: any = null\n let previous = 0\n\n if (!options) options = {}\n\n function later () {\n previous = options.leading === false ? 0 : Date.now()\n timeout = null\n result = func.apply(context, args)\n if (!timeout) context = args = null\n }\n\n return function throttle (this: any) {\n var now = Date.now()\n if (!previous && options.leading === false) previous = now\n var remaining = wait - (now - previous)\n context = this\n args = arguments\n if (remaining <= 0 || remaining > wait) {\n if (timeout) {\n clearTimeout(timeout)\n timeout = null\n }\n previous = now\n result = func.apply(context, args)\n if (!timeout) context = args = null\n } else if (!timeout && options.trailing !== false) {\n timeout = setTimeout(later, remaining)\n }\n\n return result\n }\n}\n\nexport function lexicographicCompare (elm1: T, elm2: T) {\n if (elm1 < elm2) return -1\n if (elm1 > elm2) return 1\n return 0\n}\n\n/**\n * Does a binary search to get the index of an element in the input array\n * @function\n * @example\n * var array = [ 1, 2, 3, 4, 5, 6 ];\n * var element = 4;\n * binarySearchIndexOf( array, element ); // returns 3\n *\n * @param {Array} array - sorted array\n * @param {Anything} element - element to search for in the array\n * @param {Function} [compareFunction] - compare function\n * @return {Number} the index of the element or -1 if not in the array\n */\nexport function binarySearchIndexOf (array: T[], element: T, compareFunction = lexicographicCompare) {\n let low = 0\n let high = array.length - 1\n while (low <= high) {\n const mid = (low + high) >> 1\n const cmp = compareFunction(element, array[ mid ])\n if (cmp > 0) {\n low = mid + 1\n } else if (cmp < 0) {\n high = mid - 1\n } else {\n return mid\n }\n }\n return -low - 1\n}\n\nexport function binarySearchForLeftRange (array: number[], leftRange: number) {\n let high = array.length - 1\n if (array[ high ] < leftRange) return -1\n let low = 0\n while (low <= high) {\n const mid = (low + high) >> 1\n if (array[ mid ] >= leftRange) {\n high = mid - 1\n } else {\n low = mid + 1\n }\n }\n return high + 1\n}\n\nexport function binarySearchForRightRange (array: number[], rightRange: number) {\n if (array[ 0 ] > rightRange) return -1\n let low = 0\n let high = array.length - 1\n while (low <= high) {\n const mid = (low + high) >> 1\n if (array[ mid ] > rightRange) {\n high = mid - 1\n } else {\n low = mid + 1\n }\n }\n return low - 1\n}\n\nexport function rangeInSortedArray (array: number[], min: number, max: number) {\n const indexLeft = binarySearchForLeftRange(array, min)\n const indexRight = binarySearchForRightRange(array, max)\n if (indexLeft === -1 || indexRight === -1 || indexLeft > indexRight) {\n return 0\n } else {\n return indexRight - indexLeft + 1\n }\n}\n\nexport function dataURItoImage (dataURI: string) {\n const img = document.createElement('img')\n img.src = dataURI\n return img\n}\n\nexport function uniqueArray (array: any[]) {\n return array.sort().filter(function (value, index, sorted) {\n return (index === 0) || (value !== sorted[ index - 1 ])\n })\n}\n\n// String/arraybuffer conversion\n\nexport function uint8ToString (u8a: Uint8Array) {\n const chunkSize = 0x7000\n\n if (u8a.length > chunkSize) {\n const c = []\n\n for (let i = 0; i < u8a.length; i += chunkSize) {\n c.push(String.fromCharCode.apply(\n null, u8a.subarray(i, i + chunkSize)\n ))\n }\n\n return c.join('')\n } else {\n return String.fromCharCode.apply(null, u8a)\n }\n}\n\nexport function uint8ToLines (u8a: Uint8Array, chunkSize = 1024 * 1024 * 10, newline = '\\n') {\n let partialLine = ''\n let lines: string[] = []\n\n for (let i = 0; i < u8a.length; i += chunkSize) {\n const str = uint8ToString(u8a.subarray(i, i + chunkSize))\n const idx = str.lastIndexOf(newline)\n\n if (idx === -1) {\n partialLine += str\n } else {\n const str2 = partialLine + str.substr(0, idx)\n lines = lines.concat(str2.split(newline))\n\n if (idx === str.length - newline.length) {\n partialLine = ''\n } else {\n partialLine = str.substr(idx + newline.length)\n }\n }\n }\n\n if (partialLine !== '') {\n lines.push(partialLine)\n }\n\n return lines\n}\n\nexport type TypedArrayString = 'int8'|'int16'|'int32'|'uint8'|'uint16'|'uint32'|'float32'\nexport function getTypedArray (arrayType: TypedArrayString, arraySize: number) {\n switch (arrayType) {\n case 'int8':\n return new Int8Array(arraySize)\n case 'int16':\n return new Int16Array(arraySize)\n case 'int32':\n return new Int32Array(arraySize)\n case 'uint8':\n return new Uint8Array(arraySize)\n case 'uint16':\n return new Uint16Array(arraySize)\n case 'uint32':\n return new Uint32Array(arraySize)\n case 'float32':\n return new Float32Array(arraySize)\n default:\n throw new Error('arrayType unknown: ' + arrayType)\n }\n}\n\nexport function getUintArray (sizeOrArray: any, maxUint: number) { // TODO\n const TypedArray = maxUint > 65535 ? Uint32Array : Uint16Array\n return new TypedArray(sizeOrArray)\n}\n\nexport function ensureArray (value: any) {\n return Array.isArray(value) ? value : [value]\n}\n\nexport function ensureBuffer (a: any) { // TODO\n return (a.buffer && a.buffer instanceof ArrayBuffer) ? a.buffer : a\n}\n\nfunction _ensureClassFromArg (arg: any, constructor: { new (arg: any): any }) {\n return arg instanceof constructor ? arg : new constructor(arg)\n}\n\nfunction _ensureClassFromArray (array: any, constructor: { new (): any }) {\n if (array === undefined) {\n array = new constructor()\n } else if (Array.isArray(array)) {\n array = new constructor().fromArray(array)\n }\n return array\n}\n\nexport function ensureVector2 (v?: number[]|Vector2) {\n return _ensureClassFromArray(v, Vector2)\n}\n\nexport function ensureVector3 (v?: number[]|Vector3) {\n return _ensureClassFromArray(v, Vector3)\n}\n\nexport function ensureMatrix4 (m?: number[]|Matrix4) {\n return _ensureClassFromArray(m, Matrix4)\n}\n\nexport function ensureQuaternion (q?: number[]|Quaternion) {\n return _ensureClassFromArray(q, Quaternion)\n}\n\nexport function ensureFloat32Array (a?: number[]|Float32Array) {\n return _ensureClassFromArg(a, Float32Array)\n}\n\nexport interface RingBuffer {\n has: (value: T) => boolean\n get: (value: number) => T\n push: (value: T) => void\n count: number\n data: T[]\n clear: () => void\n}\n\nexport function createRingBuffer (length: number): RingBuffer {\n let pointer = 0\n let count = 0\n const buffer: T[] = []\n\n return {\n has: function (value: any) { return buffer.indexOf(value) !== -1 },\n get: function (idx: number) { return buffer[idx] },\n push: function (item: any) {\n buffer[pointer] = item\n pointer = (length + pointer + 1) % length\n ++count\n },\n get count () { return count },\n get data () { return buffer.slice(0, Math.min(count, length)) },\n clear: function () {\n count = 0\n pointer = 0\n buffer.length = 0\n }\n }\n}\n\nexport interface SimpleDict {\n has: (k: K) => boolean\n add: (k: K, v: V) => void\n del: (k: K) => void\n values: V[]\n}\n\nexport function createSimpleDict (): SimpleDict {\n const set: { [k: string]: V } = {}\n\n return {\n has: function (k: K) { return set[JSON.stringify(k)] !== undefined },\n add: function (k: K, v: V) { set[JSON.stringify(k)] = v },\n del: function (k: K) { delete set[JSON.stringify(k)] },\n get values () { return Object.keys(set).map(k => set[k]) }\n }\n}\n\nexport interface SimpleSet {\n has: (value: T) => boolean\n add: (value: T) => void\n del: (value: T) => void\n list: T[]\n}\n\nexport function createSimpleSet (): SimpleSet {\n const set: { [k: string]: T } = {}\n\n return {\n has: function (v: T) { return set[JSON.stringify(v)] !== undefined },\n add: function (v: T) { set[JSON.stringify(v)] = v },\n del: function (v: T) { delete set[JSON.stringify(v)] },\n get list () { return Object.keys(set).map(k => set[k]) },\n }\n}\n","/**\n * @file Registry\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\n\nfunction toLowerCaseString (value: string) {\n return defaults(value, '').toString().toLowerCase()\n}\n\nexport default class Registry {\n name: string\n private _dict: {[k: string]: any}\n\n constructor (name: string) {\n this.name = name\n this._dict = {}\n }\n\n add (key: string, value: any) {\n this._dict[ toLowerCaseString(key) ] = value\n }\n\n get (key: string) {\n return this._dict[ toLowerCaseString(key) ]\n }\n\n get names () {\n return Object.keys(this._dict)\n }\n}","/**\n * @file Math Utils\n * @author Alexander Rose \n * @private\n */\n\nexport function degToRad (deg: number) {\n return deg * 0.01745 // deg * Math.PI / 180\n}\n\nexport function radToDeg (rad: number) {\n return rad * 57.29578 // rad * 180 / Math.PI\n}\n\n// http://www.broofa.com/Tools/Math.uuid.htm\nconst chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')\nconst uuid = new Array(36)\n\nexport function generateUUID () {\n let rnd = 0\n let r\n\n for (let i = 0; i < 36; i++) {\n if (i === 8 || i === 13 || i === 18 || i === 23) {\n uuid[ i ] = '-'\n } else if (i === 14) {\n uuid[ i ] = '4'\n } else {\n if (rnd <= 0x02) rnd = 0x2000000 + (Math.random() * 0x1000000) | 0\n r = rnd & 0xf\n rnd = rnd >> 4\n uuid[ i ] = chars[ (i === 19) ? (r & 0x3) | 0x8 : r ]\n }\n }\n\n return uuid.join('')\n}\n\nexport function countSetBits (i: number) {\n i = i - ((i >> 1) & 0x55555555)\n i = (i & 0x33333333) + ((i >> 2) & 0x33333333)\n return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24\n}\n\nexport function normalize (value: number, min: number, max: number) {\n return (value - min) / (max - min)\n}\n\nexport function clamp (value: number, min: number, max: number) {\n return Math.max(min, Math.min(max, value))\n}\n\nexport function pclamp (value: number) {\n return clamp(value, 0, 100)\n}\n\nexport function saturate (value: number) {\n return clamp(value, 0, 1)\n}\n\nexport function lerp (start: number, stop: number, alpha: number) {\n return start + (stop - start) * alpha\n}\n\nexport function spline (p0: number, p1: number, p2: number, p3: number, t: number, tension: number) {\n const v0 = (p2 - p0) * tension\n const v1 = (p3 - p1) * tension\n const t2 = t * t\n const t3 = t * t2\n return (2 * p1 - 2 * p2 + v0 + v1) * t3 +\n (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 +\n v0 * t + p1\n}\n\nexport function smoothstep (min: number, max: number, x: number) {\n x = saturate(normalize(x, min, max))\n return x * x * (3 - 2 * x)\n}\n\nexport function smootherstep (min: number, max: number, x: number) {\n x = saturate(normalize(x, min, max))\n return x * x * x * (x * (x * 6 - 15) + 10)\n}\n\nexport function smootheststep (min: number, max: number, x: number) {\n x = saturate(normalize(x, min, max))\n return (\n -20 * Math.pow(x, 7) +\n 70 * Math.pow(x, 6) -\n 84 * Math.pow(x, 5) +\n 35 * Math.pow(x, 4)\n )\n}\n\nexport function almostIdentity (value: number, start: number, stop: number) {\n if (value > start) return value\n const a = 2 * stop - start\n const b = 2 * start - 3 * stop\n const t = value / start\n return (a * t + b) * t * t + stop\n}","/**\n * @file Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Color } from 'three'\nimport * as chroma from 'chroma-js'\n\nimport { createParams } from '../utils'\nimport { NumberArray } from '../types'\nimport Structure from '../structure/structure'\nimport Surface from '../surface/surface'\nimport Volume from '../surface/volume'\nimport AtomProxy from '../proxy/atom-proxy'\nimport BondProxy from '../proxy/bond-proxy'\n\nexport type ColorMode = 'rgb'|'hsv'|'hsl'|'hsi'|'lab'|'hcl'\nexport type ColorSpace = 'sRGB' | 'linear'\n\n/**\n * Internal color space for all colors (global).\n * Colors are always specified as sRGB; if this is set to\n * 'linear' then colors get linearized when used internally\n * as vertex or texture colors.\n * @see setColorSpace/getColorSpace.\n */\nvar colorSpace: ColorSpace = 'sRGB' // default: don't linearize\n\n/** Set the global internal color space for colormakers */\nexport function setColorSpace(space: ColorSpace) {\n colorSpace = space\n}\n\n/** Get the global internal color space for colormakers */\nexport function getColorSpace() {\n return colorSpace\n}\n\nexport const ScaleDefaultParameters = {\n scale: 'uniform' as string|string[],\n mode: 'hcl' as ColorMode,\n domain: [ 0, 1 ] as number[],\n value: 0xFFFFFF,\n reverse: false,\n}\nexport type ScaleParameters = typeof ScaleDefaultParameters\n\nexport interface ColorData {\n atomData?: number[],\n bondData?: number[]\n}\n\nexport interface ColormakerParameters extends ScaleParameters {\n structure?: Structure\n volume?: Volume\n surface?: Surface\n data?: ColorData\n}\n\nexport type StuctureColormakerParams = { structure: Structure } & Partial\nexport type VolumeColormakerParams = { volume: Volume } & Partial\nexport type ColormakerScale = (v: number) => number\nexport type ColormakerConstructor = new (...p: ConstructorParameters) => Colormaker\n\nconst tmpColor = new Color()\n\n/** Decorator for optionally linearizing a numeric color */\ntype colorFuncType = (value: any, fromTo?: boolean) => number // decorator applies to functions with this shape\nexport function manageColor\n (_target: Object,\n _name: string | symbol,\n descriptor: TypedPropertyDescriptor): PropertyDescriptor {\n const originalMethod = descriptor.value\n const linearize: colorFuncType = function (this: T, value: any, fromTo?: boolean) {\n let result = originalMethod!.bind(this, value, fromTo)()\n if (colorSpace == 'linear') {\n tmpColor.set(result)\n tmpColor.convertSRGBToLinear()\n return tmpColor.getHex()\n } else {\n return result\n }\n }\n descriptor.value = linearize\n return descriptor\n }\n\n/**\n * Class for making colors.\n * @interface\n */\nabstract class Colormaker {\n parameters: ColormakerParameters\n atomProxy?: AtomProxy\n\n /**\n * Create a colormaker instance\n * @param {ColormakerParameters} params - colormaker parameter\n */\n constructor (params: Partial = {}) {\n this.parameters = createParams(params, ScaleDefaultParameters)\n\n if (typeof this.parameters.value === 'string') {\n this.parameters.value = tmpColor.set(this.parameters.value).getHex()\n }\n\n if (this.parameters.structure) {\n this.atomProxy = this.parameters.structure.getAtomProxy()\n }\n }\n\n getScale (params: Partial = {}) {\n const p = createParams(params, this.parameters)\n\n if (p.scale === 'rainbow') {\n p.scale = [ 'red', 'orange', 'yellow', 'green', 'blue' ]\n } else if (p.scale === 'rwb') {\n p.scale = [ 'red', 'white', 'blue' ]\n }\n\n if (p.reverse) {\n p.domain = p.domain.slice().reverse()\n }\n return chroma\n .scale(p.scale as any) // TODO\n .mode(p.mode)\n .domain(p.domain)\n .out('num' as any) // returns RGB color as numeric (not string \"#ffffff\")\n }\n\n /**\n * save a color to an array\n * @param {Integer} color - hex color value\n * @param {Array|TypedArray} array - destination\n * @param {Integer} offset - index into the array\n * @return {Array} the destination array\n */\n colorToArray (color: number, array: NumberArray = [], offset = 0) {\n array[ offset ] = (color >> 16 & 255) / 255\n array[ offset + 1 ] = (color >> 8 & 255) / 255\n array[ offset + 2 ] = (color & 255) / 255\n\n return array\n }\n\n atomColor? (atom: AtomProxy): number\n\n /**\n * save an atom color to an array\n * @param {AtomProxy} atom - atom to get color for\n * @param {Array|TypedArray} array - destination\n * @param {Integer} offset - index into the array\n * @return {Array} the destination array\n */\n atomColorToArray (atom: AtomProxy, array: NumberArray, offset: number) {\n return this.colorToArray(\n this.atomColor ? this.atomColor(atom) : 0x000000, array, offset\n )\n }\n\n /**\n * return the color for an bond\n * @param {BondProxy} bond - bond to get color for\n * @param {Boolean} fromTo - whether to use the first or second atom of the bond\n * @return {Integer} hex bond color\n */\n bondColor (bond: BondProxy, fromTo: boolean) {\n if (this.atomProxy && this.atomColor) {\n this.atomProxy.index = fromTo ? bond.atomIndex1 : bond.atomIndex2\n return this.atomColor(this.atomProxy)\n } else {\n return 0x000000\n }\n }\n\n /**\n * safe a bond color to an array\n * @param {BondProxy} bond - bond to get color for\n * @param {Boolean} fromTo - whether to use the first or second atom of the bond\n * @param {Array|TypedArray} array - destination\n * @param {Integer} offset - index into the array\n * @return {Array} the destination array\n */\n bondColorToArray (bond: BondProxy, fromTo: boolean, array: NumberArray, offset: number) {\n return this.colorToArray(\n this.bondColor(bond, fromTo), array, offset\n )\n }\n\n volumeColor? (index: number): number\n\n /**\n * safe a volume cell color to an array\n * @param {Integer} index - volume cell index\n * @param {Array|TypedArray} array - destination\n * @param {Integer} offset - index into the array\n * @return {Array} the destination array\n */\n volumeColorToArray (index: number, array: NumberArray, offset: number) {\n return this.colorToArray(\n this.volumeColor ? this.volumeColor(index) : 0x000000, array, offset\n )\n }\n\n positionColor? (position: Vector3): number\n\n /**\n * safe a color for coordinates in space to an array\n * @param {Vector3} coords - xyz coordinates\n * @param {Array|TypedArray} array - destination\n * @param {Integer} offset - index into the array\n * @return {Array} the destination array\n */\n positionColorToArray (coords: Vector3, array: NumberArray, offset: number) {\n return this.colorToArray(\n this.positionColor ? this.positionColor(coords) : 0x000000, array, offset\n )\n }\n}\n\nexport default Colormaker\n","/**\n * @file Selection Constants\n * @author Alexander Rose \n * @private\n */\n\nexport enum kwd {\n PROTEIN = 1,\n NUCLEIC = 2,\n RNA = 3,\n DNA = 4,\n POLYMER = 5,\n WATER = 6,\n HELIX = 7,\n SHEET = 8,\n TURN = 9,\n BACKBONE = 10,\n SIDECHAIN = 11,\n ALL = 12,\n HETERO = 13,\n ION = 14,\n SACCHARIDE = 15,\n SUGAR = 15,\n BONDED = 16,\n RING = 17,\n AROMATICRING = 18,\n METAL = 19,\n POLARH = 20,\n NONE = 21\n}\n\nexport const SelectAllKeyword = [ '*', '', 'ALL' ]\nexport const SelectNoneKeyword = [ 'NONE' ]\n\nexport const AtomOnlyKeywords = [\n kwd.BACKBONE, kwd.SIDECHAIN, kwd.BONDED, kwd.RING, kwd.AROMATICRING, kwd.METAL, kwd.POLARH\n]\n\nexport const ChainKeywords = [\n kwd.POLYMER, kwd.WATER\n]\n\nexport const SmallResname = [ 'ALA', 'GLY', 'SER' ]\nexport const NucleophilicResname = [ 'CYS', 'SER', 'THR' ]\nexport const HydrophobicResname = [ 'ALA', 'ILE', 'LEU', 'MET', 'PHE', 'PRO', 'TRP', 'VAL' ]\nexport const AromaticResname = [ 'PHE', 'TRP', 'TYR', 'HIS' ]\nexport const AmideResname = [ 'ASN', 'GLN' ]\nexport const AcidicResname = [ 'ASP', 'GLU' ]\nexport const BasicResname = [ 'ARG', 'HIS', 'LYS' ]\nexport const ChargedResname = [ 'ARG', 'ASP', 'GLU', 'HIS', 'LYS' ]\nexport const PolarResname = [ 'ASN', 'ARG', 'ASP', 'CYS', 'GLY', 'GLN', 'GLU', 'HIS', 'LYS', 'SER', 'THR', 'TYR' ]\nexport const NonpolarResname = [ 'ALA', 'ILE', 'LEU', 'MET', 'PHE', 'PRO', 'TRP', 'VAL' ]\nexport const CyclicResname = [ 'HIS', 'PHE', 'PRO', 'TRP', 'TYR' ]\nexport const AliphaticResname = [ 'ALA', 'GLY', 'ILE', 'LEU', 'VAL' ]\n","/**\n * @file Selection Test\n * @author Alexander Rose \n * @private\n */\n\nimport { binarySearchIndexOf, rangeInSortedArray } from '../utils'\nimport { kwd, AtomOnlyKeywords, ChainKeywords } from './selection-constants'\n\nimport AtomProxy from '../proxy/atom-proxy'\nimport ResidueProxy from '../proxy/residue-proxy'\nimport ChainProxy from '../proxy/chain-proxy'\nimport ModelProxy from '../proxy/model-proxy'\n\nexport type ProxyEntity = AtomProxy|ResidueProxy|ChainProxy|ModelProxy\ntype TestEntityFn = (e: ProxyEntity, s: SelectionRule) => boolean|-1\ntype FilterFn = (s: SelectionRule) => boolean\nexport type SelectionTest = false|((e: ProxyEntity) => boolean|-1)\n\nexport type SelectionOperator = 'AND'|'OR'\nexport interface SelectionRule {\n keyword?: any\n atomname?: string\n element?: string\n atomindex?: number[]\n altloc?: string\n inscode?: string\n resname?: string|string[]\n sstruc?: string\n resno?: number|[number, number]\n chainname?: string\n model?: number\n\n error?: string\n rules?: SelectionRule[]\n negate?: boolean\n operator?: SelectionOperator\n}\n\nfunction atomTestFn (a: AtomProxy, s: SelectionRule) {\n // returning -1 means the rule is not applicable\n if (s.atomname === undefined && s.element === undefined &&\n s.altloc === undefined && s.atomindex === undefined &&\n s.keyword === undefined && s.inscode === undefined &&\n s.resname === undefined && s.sstruc === undefined &&\n s.resno === undefined && s.chainname === undefined &&\n s.model === undefined\n ) return -1\n\n if (s.keyword !== undefined) {\n if (s.keyword === kwd.BACKBONE && !a.isBackbone()) return false\n if (s.keyword === kwd.SIDECHAIN && !a.isSidechain()) return false\n if (s.keyword === kwd.BONDED && !a.isBonded()) return false\n if (s.keyword === kwd.RING && !a.isRing()) return false\n if (s.keyword === kwd.AROMATICRING && !a.isAromatic()) return false\n\n if (s.keyword === kwd.HETERO && !a.isHetero()) return false\n if (s.keyword === kwd.PROTEIN && !a.isProtein()) return false\n if (s.keyword === kwd.NUCLEIC && !a.isNucleic()) return false\n if (s.keyword === kwd.RNA && !a.isRna()) return false\n if (s.keyword === kwd.DNA && !a.isDna()) return false\n if (s.keyword === kwd.POLYMER && !a.isPolymer()) return false\n if (s.keyword === kwd.WATER && !a.isWater()) return false\n if (s.keyword === kwd.HELIX && !a.isHelix()) return false\n if (s.keyword === kwd.SHEET && !a.isSheet()) return false\n if (s.keyword === kwd.TURN && !a.isTurn()) return false\n if (s.keyword === kwd.ION && !a.isIon()) return false\n if (s.keyword === kwd.SACCHARIDE && !a.isSaccharide()) return false\n if (s.keyword === kwd.METAL && !a.isMetal()) return false\n if (s.keyword === kwd.POLARH && !a.isPolarHydrogen()) return false\n }\n\n if (s.atomname !== undefined && s.atomname !== a.atomname) return false\n if (s.element !== undefined && s.element !== a.element) return false\n if (s.altloc !== undefined && s.altloc !== a.altloc) return false\n\n if (s.atomindex !== undefined &&\n binarySearchIndexOf(s.atomindex, a.index) < 0\n ) return false\n\n if (s.resname !== undefined) {\n if (Array.isArray(s.resname)) {\n if (!s.resname.includes(a.resname)) return false\n } else {\n if (s.resname !== a.resname) return false\n }\n }\n if (s.sstruc !== undefined && s.sstruc !== a.sstruc) return false\n if (s.resno !== undefined) {\n if (Array.isArray(s.resno) && s.resno.length === 2) {\n if (s.resno[0] > a.resno || s.resno[1] < a.resno) return false\n } else {\n if (s.resno !== a.resno) return false\n }\n }\n if (s.inscode !== undefined && s.inscode !== a.inscode) return false\n\n if (s.chainname !== undefined && s.chainname !== a.chainname) return false\n if (s.model !== undefined && s.model !== a.modelIndex) return false\n\n return true\n}\n\nfunction residueTestFn (r: ResidueProxy, s: SelectionRule) {\n // returning -1 means the rule is not applicable\n if (s.resname === undefined && s.resno === undefined && s.inscode === undefined &&\n s.sstruc === undefined && s.model === undefined && s.chainname === undefined &&\n s.atomindex === undefined &&\n (s.keyword === undefined || AtomOnlyKeywords.includes(s.keyword))\n ) return -1\n\n if (s.keyword !== undefined) {\n if (s.keyword === kwd.HETERO && !r.isHetero()) return false\n if (s.keyword === kwd.PROTEIN && !r.isProtein()) return false\n if (s.keyword === kwd.NUCLEIC && !r.isNucleic()) return false\n if (s.keyword === kwd.RNA && !r.isRna()) return false\n if (s.keyword === kwd.DNA && !r.isDna()) return false\n if (s.keyword === kwd.POLYMER && !r.isPolymer()) return false\n if (s.keyword === kwd.WATER && !r.isWater()) return false\n if (s.keyword === kwd.HELIX && !r.isHelix()) return false\n if (s.keyword === kwd.SHEET && !r.isSheet()) return false\n if (s.keyword === kwd.TURN && !r.isTurn()) return false\n if (s.keyword === kwd.ION && !r.isIon()) return false\n if (s.keyword === kwd.SACCHARIDE && !r.isSaccharide()) return false\n }\n\n if (s.atomindex !== undefined &&\n rangeInSortedArray(s.atomindex, r.atomOffset, r.atomEnd) === 0\n ) return false\n\n if (s.resname !== undefined) {\n if (Array.isArray(s.resname)) {\n if (!s.resname.includes(r.resname)) return false\n } else {\n if (s.resname !== r.resname) return false\n }\n }\n if (s.sstruc !== undefined && s.sstruc !== r.sstruc) return false\n if (s.resno !== undefined) {\n if (Array.isArray(s.resno) && s.resno.length === 2) {\n if (s.resno[0] > r.resno || s.resno[1] < r.resno) return false\n } else {\n if (s.resno !== r.resno) return false\n }\n }\n if (s.inscode !== undefined && s.inscode !== r.inscode) return false\n\n if (s.chainname !== undefined && s.chainname !== r.chainname) return false\n if (s.model !== undefined && s.model !== r.modelIndex) return false\n\n return true\n}\n\nfunction chainTestFn (c: ChainProxy, s: SelectionRule) {\n // returning -1 means the rule is not applicable\n if (s.chainname === undefined && s.model === undefined && s.atomindex === undefined &&\n (s.keyword === undefined || !ChainKeywords.includes(s.keyword) || !c.entity)\n ) return -1\n\n if (s.keyword !== undefined) {\n if (s.keyword === kwd.POLYMER && !c.entity.isPolymer()) return false\n if (s.keyword === kwd.WATER && !c.entity.isWater()) return false\n }\n\n if (s.atomindex !== undefined &&\n rangeInSortedArray(s.atomindex, c.atomOffset, c.atomEnd) === 0\n ) return false\n\n if (s.chainname !== undefined && s.chainname !== c.chainname) return false\n\n if (s.model !== undefined && s.model !== c.modelIndex) return false\n\n return true\n}\n\nfunction modelTestFn (m: ModelProxy, s: SelectionRule) {\n // returning -1 means the rule is not applicable\n if (s.model === undefined && s.atomindex === undefined) return -1\n\n if (s.atomindex !== undefined &&\n rangeInSortedArray(s.atomindex, m.atomOffset, m.atomEnd) === 0\n ) return false\n\n if (s.model !== undefined && s.model !== m.index) return false\n\n return true\n}\n\nfunction makeTest (selection: SelectionRule|null, fn: TestEntityFn) {\n if (selection === null) return false\n if (selection.error) return false\n if (!selection.rules || selection.rules.length === 0) return false\n\n const n = selection.rules.length\n\n const t = !selection.negate\n const f = !!selection.negate\n\n const subTests: SelectionTest[] = []\n for (let i = 0; i < n; ++i) {\n const s = selection.rules[ i ]\n if (s.hasOwnProperty('operator')) {\n subTests[ i ] = makeTest(s, fn) as SelectionTest // TODO\n }\n }\n\n // ( x and y ) can short circuit on false\n // ( x or y ) can short circuit on true\n // not ( x and y )\n\n return function test (entity: ProxyEntity) {\n const and = selection.operator === 'AND'\n let na = false\n\n for (let i = 0; i < n; ++i) {\n const s = selection.rules![ i ] // TODO\n let ret\n\n if (s.hasOwnProperty('operator')) {\n const test = subTests[ i ]\n if (test !== false) {\n ret = test(entity)\n } else {\n ret = -1\n }\n\n if (ret === -1) {\n na = true\n continue\n } else if (ret === true) {\n if (and) { continue } else { return t }\n } else {\n if (and) { return f } else { continue }\n }\n } else {\n if (s.keyword === kwd.ALL) {\n if (and) { continue } else { return t }\n } else if (s.keyword === kwd.NONE) {\n if (and) { continue } else { return f }\n }\n\n ret = fn(entity, s)\n\n // console.log( entity.qualifiedName(), ret, s, selection.negate, \"t\", t, \"f\", f )\n\n if (ret === -1) {\n na = true\n continue\n } else if (ret === true) {\n if (and) { continue } else { return t }\n } else {\n if (and) { return f } else { continue }\n }\n }\n }\n\n if (na) {\n return -1\n } else {\n if (and) { return t } else { return f }\n }\n } as SelectionTest\n}\n\nfunction filter (selection: SelectionRule, fn: FilterFn) {\n if (selection.error) return selection\n if (!selection.rules || selection.rules.length === 0) return selection\n\n const n = selection.rules.length\n\n const filtered: SelectionRule = {\n operator: selection.operator,\n rules: []\n }\n if (selection.hasOwnProperty('negate')) {\n filtered.negate = selection.negate\n }\n\n for (let i = 0; i < n; ++i) {\n const s = selection.rules[ i ]\n if (s.hasOwnProperty('operator')) {\n const fs = filter(s, fn)\n if (fs !== null) filtered.rules!.push(fs) // TODO\n } else if (!fn(s)) {\n filtered.rules!.push(s) // TODO\n }\n }\n\n if (filtered.rules!.length > 0) { // TODO\n // TODO maybe the filtered rules could be returned\n // in some case, but the way how tests are applied\n // e.g. when traversing a structure would also need\n // to change\n return selection\n // return filtered;\n } else {\n return null\n }\n}\n\nfunction makeAtomTest (selection: SelectionRule, atomOnly = false) {\n let filteredSelection: SelectionRule|null = selection\n if (atomOnly) {\n filteredSelection = filter(selection, function (s) {\n if (s.keyword !== undefined && !AtomOnlyKeywords.includes(s.keyword)) return true\n if (s.model !== undefined) return true\n if (s.chainname !== undefined) return true\n if (s.resname !== undefined) return true\n if (s.resno !== undefined) return true\n if (s.sstruc !== undefined) return true\n return false\n })\n }\n return makeTest(filteredSelection, atomTestFn)\n}\n\nfunction makeResidueTest (selection: SelectionRule, residueOnly = false) {\n let filteredSelection: SelectionRule|null = selection\n if (residueOnly) {\n filteredSelection = filter(selection, function (s) {\n if (s.keyword !== undefined && AtomOnlyKeywords.includes(s.keyword)) return true\n if (s.model !== undefined) return true\n if (s.chainname !== undefined) return true\n if (s.atomname !== undefined) return true\n if (s.element !== undefined) return true\n if (s.altloc !== undefined) return true\n return false\n })\n }\n return makeTest(filteredSelection, residueTestFn)\n}\n\nfunction makeChainTest (selection: SelectionRule, chainOnly = false) {\n let filteredSelection: SelectionRule|null = selection\n if (chainOnly) {\n filteredSelection = filter(selection, function (s) {\n if (s.keyword !== undefined && !ChainKeywords.includes(s.keyword)) return true\n // if( s.model!==undefined ) return true;\n if (s.resname !== undefined) return true\n if (s.resno !== undefined) return true\n if (s.atomname !== undefined) return true\n if (s.element !== undefined) return true\n if (s.altloc !== undefined) return true\n if (s.sstruc !== undefined) return true\n if (s.inscode !== undefined) return true\n return false\n })\n }\n return makeTest(filteredSelection, chainTestFn)\n}\n\nfunction makeModelTest (selection: SelectionRule, modelOnly = false) {\n let filteredSelection: SelectionRule|null = selection\n if (modelOnly) {\n filteredSelection = filter(selection, function (s) {\n if (s.keyword !== undefined) return true\n if (s.chainname !== undefined) return true\n if (s.resname !== undefined) return true\n if (s.resno !== undefined) return true\n if (s.atomname !== undefined) return true\n if (s.element !== undefined) return true\n if (s.altloc !== undefined) return true\n if (s.sstruc !== undefined) return true\n if (s.inscode !== undefined) return true\n return false\n })\n }\n return makeTest(filteredSelection, modelTestFn)\n}\n\nexport {\n makeAtomTest,\n makeResidueTest,\n makeChainTest,\n makeModelTest\n}\n","/**\n * @file Selection\n * @author Alexander Rose \n * @private\n */\n\nimport { Signal } from 'signals'\n\nimport { parseSele } from './selection-parser'\nimport {\n SelectionTest, SelectionRule,\n makeAtomTest, makeResidueTest, makeChainTest, makeModelTest\n} from './selection-test'\nimport { SelectAllKeyword, SelectNoneKeyword } from './selection-constants'\n\nexport type SelectionSignals = {\n stringChanged: Signal\n}\n\n/**\n * Selection\n */\nclass Selection {\n signals: SelectionSignals\n string: string\n selection: SelectionRule\n\n test: SelectionTest\n residueTest: SelectionTest\n chainTest: SelectionTest\n modelTest: SelectionTest\n\n atomOnlyTest: SelectionTest\n residueOnlyTest: SelectionTest\n chainOnlyTest: SelectionTest\n modelOnlyTest: SelectionTest\n\n /**\n * Create Selection\n * @param {String} string - selection string, see {@tutorial selection-language}\n */\n constructor (string?: string) {\n this.signals = {\n stringChanged: new Signal()\n }\n\n this.setString(string)\n }\n\n get type () { return 'selection' }\n\n setString (string?: string, silent?: boolean) {\n if (string === undefined) string = this.string || ''\n if (string === this.string) return\n\n try {\n this.selection = parseSele(string)\n } catch (e) {\n // Log.error( e.stack );\n this.selection = { 'error': e.message }\n }\n const selection = this.selection\n\n this.string = string\n\n this.test = makeAtomTest(selection)\n this.residueTest = makeResidueTest(selection)\n this.chainTest = makeChainTest(selection)\n this.modelTest = makeModelTest(selection)\n\n this.atomOnlyTest = makeAtomTest(selection, true)\n this.residueOnlyTest = makeResidueTest(selection, true)\n this.chainOnlyTest = makeChainTest(selection, true)\n this.modelOnlyTest = makeModelTest(selection, true)\n\n if (!silent) {\n this.signals.stringChanged.dispatch(this.string)\n }\n }\n\n isAllSelection () {\n return SelectAllKeyword.includes(this.string.toUpperCase())\n }\n\n isNoneSelection () {\n return SelectNoneKeyword.includes(this.string.toUpperCase())\n }\n}\n\nexport default Selection\n","/**\n * @file Selection Parser\n * @author Alexander Rose \n * @private\n */\n\nimport { SelectionRule, SelectionOperator } from './selection-test'\nimport {\n kwd, SelectAllKeyword,\n SmallResname, NucleophilicResname, HydrophobicResname, AromaticResname,\n AmideResname, AcidicResname, BasicResname, ChargedResname,\n PolarResname, NonpolarResname, CyclicResname, AliphaticResname\n} from './selection-constants'\n\nfunction parseSele (string: string) {\n let retSelection: SelectionRule = {\n operator: undefined,\n rules: []\n }\n\n if (!string) {\n return retSelection\n }\n\n let selection = retSelection\n let newSelection: SelectionRule\n let oldSelection: SelectionRule\n const selectionStack: SelectionRule[] = []\n\n string = string.replace(/\\(/g, ' ( ').replace(/\\)/g, ' ) ').trim()\n if (string.charAt(0) === '(' && string.substr(-1) === ')') {\n string = string.slice(1, -1).trim()\n }\n const chunks = string.split(/\\s+/)\n\n // Log.log( string, chunks )\n\n const createNewContext = (operator?: SelectionOperator) => {\n newSelection = {\n operator,\n rules: []\n }\n if (selection === undefined) {\n selection = newSelection\n retSelection = newSelection\n } else {\n selection.rules!.push(newSelection)\n selectionStack.push(selection)\n selection = newSelection\n }\n }\n\n const getPrevContext = function (operator?: SelectionOperator) {\n oldSelection = selection\n selection = selectionStack.pop()!\n if (selection === undefined) {\n createNewContext(operator)\n pushRule(oldSelection)\n }\n }\n\n const pushRule = function (rule: SelectionRule) {\n selection.rules!.push(rule)\n }\n\n let not: false|0|1|2 = false\n\n for (let i = 0; i < chunks.length; ++i) {\n const c = chunks[ i ]\n const cu = c.toUpperCase()\n\n // handle parens\n\n if (c === '(') {\n // Log.log( \"(\" );\n not = false\n createNewContext()\n continue\n } else if (c === ')') {\n // Log.log( \")\" );\n getPrevContext()\n if (selection.negate) {\n getPrevContext()\n }\n continue\n }\n\n // leave 'not' context\n\n if (not > 0) {\n if (cu === 'NOT') {\n not = 1\n } else if (not === 1) {\n not = 2\n } else if (not === 2) {\n not = false\n getPrevContext()\n } else {\n throw new Error(\"something went wrong with 'not'\")\n }\n }\n\n // handle logic operators\n\n if (cu === 'AND') {\n // Log.log( \"AND\" );\n if (selection.operator === 'OR') {\n const lastRule = selection.rules!.pop()!\n createNewContext('AND')\n pushRule(lastRule)\n } else {\n selection.operator = 'AND'\n }\n continue\n } else if (cu === 'OR') {\n // Log.log( \"OR\" );\n if (selection.operator === 'AND') {\n getPrevContext('OR')\n } else {\n selection.operator = 'OR'\n }\n continue\n } else if (c.toUpperCase() === 'NOT') {\n // Log.log( \"NOT\", j );\n not = 1\n createNewContext()\n selection.negate = true\n continue\n } else {\n // Log.log( \"chunk\", c, j, selection );\n }\n\n // handle keyword attributes\n\n // ensure `cu` is not a number before testing if it is in the\n // kwd enum dictionary which includes the enum numbers as well...\n if (+cu !== +cu) {\n const keyword = (kwd as any)[ cu ]\n if (keyword !== undefined) {\n pushRule({ keyword })\n continue\n }\n }\n\n if (cu === 'HYDROGEN') {\n pushRule({\n operator: 'OR',\n rules: [\n { element: 'H' },\n { element: 'D' }\n ]\n })\n continue\n }\n\n if (cu === 'SMALL') {\n pushRule({ resname: SmallResname })\n continue\n }\n\n if (cu === 'NUCLEOPHILIC') {\n pushRule({ resname: NucleophilicResname })\n continue\n }\n\n if (cu === 'HYDROPHOBIC') {\n pushRule({ resname: HydrophobicResname })\n continue\n }\n\n if (cu === 'AROMATIC') {\n pushRule({ resname: AromaticResname })\n continue\n }\n\n if (cu === 'AMIDE') {\n pushRule({ resname: AmideResname })\n continue\n }\n\n if (cu === 'ACIDIC') {\n pushRule({ resname: AcidicResname })\n continue\n }\n\n if (cu === 'BASIC') {\n pushRule({ resname: BasicResname })\n continue\n }\n\n if (cu === 'CHARGED') {\n pushRule({ resname: ChargedResname })\n continue\n }\n\n if (cu === 'POLAR') {\n pushRule({ resname: PolarResname })\n continue\n }\n\n if (cu === 'NONPOLAR') {\n pushRule({ resname: NonpolarResname })\n continue\n }\n\n if (cu === 'CYCLIC') {\n pushRule({ resname: CyclicResname })\n continue\n }\n\n if (cu === 'ALIPHATIC') {\n pushRule({ resname: AliphaticResname })\n continue\n }\n\n if (cu === 'SIDECHAINATTACHED') {\n pushRule({\n operator: 'OR',\n rules: [\n { keyword: kwd.SIDECHAIN },\n {\n operator: 'AND',\n negate: false,\n rules: [\n { keyword: kwd.PROTEIN },\n {\n operator: 'OR',\n negate: false,\n rules: [\n { atomname: 'CA' },\n { atomname: 'BB' }\n ]\n }\n ]\n },\n {\n operator: 'AND',\n negate: false,\n rules: [\n { resname: 'PRO' },\n { atomname: 'N' }\n ]\n },\n {\n operator: 'AND',\n negate: false,\n rules: [\n { keyword: kwd.NUCLEIC },\n {\n operator: 'OR',\n negate: true,\n rules: [\n { atomname: 'P' },\n { atomname: 'OP1' },\n { atomname: 'OP2' },\n { atomname: \"O3'\" },\n { atomname: 'O3*' },\n { atomname: \"HO3'\"},\n { atomname: \"O5'\" },\n { atomname: 'O5*' },\n { atomname: \"HO5'\"},\n { atomname: \"C5'\" },\n { atomname: 'C5*' },\n { atomname: \"H5'\" },\n { atomname: \"H5''\"}\n ]\n }\n ]\n }\n ]\n })\n continue\n }\n\n if (cu === 'APOLARH') {\n pushRule({\n operator: 'AND',\n negate: false,\n rules: [\n { element: 'H' },\n {\n negate: true,\n operator: undefined,\n rules: [\n { keyword: kwd.POLARH }\n ]\n }\n ]\n })\n continue\n }\n\n if (cu === 'LIGAND') {\n pushRule({\n operator: 'AND',\n rules: [\n {\n operator: 'OR',\n rules: [\n {\n operator: 'AND',\n rules: [\n { keyword: kwd.HETERO },\n {\n negate: true,\n operator: undefined,\n rules: [\n { keyword: kwd.POLYMER }\n ]\n }\n ]\n },\n {\n negate: true,\n operator: undefined,\n rules: [\n { keyword: kwd.POLYMER }\n ]\n }\n ]\n },\n {\n negate: true,\n operator: undefined,\n rules: [\n {\n operator: 'OR',\n rules: [\n { keyword: kwd.WATER },\n { keyword: kwd.ION }\n ]\n }\n ]\n }\n ]\n })\n continue\n }\n\n if (SelectAllKeyword.indexOf(cu) !== -1) {\n pushRule({ keyword: kwd.ALL })\n continue\n }\n\n // handle atom expressions\n\n if (c.charAt(0) === '@') {\n const indexList = c.substr(1).split(',').map(x => parseInt(x))\n indexList.sort(function (a, b) { return a - b })\n pushRule({ atomindex: indexList })\n continue\n }\n\n if (c.charAt(0) === '#') {\n console.error('# for element selection deprecated, use _')\n pushRule({ element: cu.substr(1) })\n continue\n }\n if (c.charAt(0) === '_') {\n pushRule({ element: cu.substr(1) })\n continue\n }\n\n if (c[0] === '[' && c[c.length - 1] === ']') {\n const resnameList = cu.substr(1, c.length - 2).split(',')\n const resname = resnameList.length > 1 ? resnameList : resnameList[ 0 ]\n pushRule({ resname: resname })\n continue\n } else if (\n (c.length >= 1 && c.length <= 4) &&\n c[0] !== '^' && c[0] !== ':' && c[0] !== '.' && c[0] !== '%' && c[0] !== '/' &&\n isNaN(parseInt(c))\n ) {\n pushRule({ resname: cu })\n continue\n }\n\n // there must be only one constraint per rule\n // otherwise a test quickly becomes not applicable\n // e.g. chainTest for chainname when resno is present too\n\n const sele: SelectionRule = {\n operator: 'AND',\n rules: []\n }\n\n const model = c.split('/')\n if (model.length > 1 && model[1]) {\n if (isNaN(parseInt(model[1]))) {\n throw new Error('model must be an integer')\n }\n sele.rules!.push({\n model: parseInt(model[1])\n })\n }\n\n const altloc = model[0].split('%')\n if (altloc.length > 1) {\n sele.rules!.push({\n altloc: altloc[1]\n })\n }\n\n const atomname = altloc[0].split('.')\n if (atomname.length > 1 && atomname[1]) {\n if (atomname[1].length > 4) {\n throw new Error('atomname must be one to four characters')\n }\n sele.rules!.push({\n atomname: atomname[1].substring(0, 4).toUpperCase()\n })\n }\n\n const chain = atomname[0].split(':')\n if (chain.length > 1 && chain[1]) {\n sele.rules!.push({\n chainname: chain[1]\n })\n }\n\n const inscode = chain[0].split('^')\n if (inscode.length > 1) {\n sele.rules!.push({\n inscode: inscode[1]\n })\n }\n\n if (inscode[0]) {\n let negate, negate2\n if (inscode[0][0] === '-') {\n inscode[0] = inscode[0].substr(1)\n negate = true\n }\n if (inscode[0].includes('--')) {\n inscode[0] = inscode[0].replace('--', '-')\n negate2 = true\n }\n let resi = inscode[0].split('-')\n if (resi.length === 1) {\n let resiSingle = parseInt(resi[0])\n if (isNaN(resiSingle)) {\n throw new Error('resi must be an integer')\n }\n if (negate) resiSingle *= -1\n sele.rules!.push({\n resno: resiSingle\n })\n } else if (resi.length === 2) {\n const resiRange = resi.map(x => parseInt(x))\n if (negate) resiRange[0] *= -1\n if (negate2) resiRange[1] *= -1\n sele.rules!.push({\n resno: [resiRange[0], resiRange[1]]\n })\n } else {\n throw new Error(\"resi range must contain one '-'\")\n }\n }\n\n // round up\n\n if (sele.rules!.length === 1) {\n pushRule(sele.rules![ 0 ])\n } else if (sele.rules!.length > 1) {\n pushRule(sele)\n } else {\n throw new Error('empty selection chunk')\n }\n }\n\n // cleanup\n\n if (\n retSelection.operator === undefined &&\n retSelection.rules!.length === 1 &&\n retSelection.rules![ 0 ].hasOwnProperty('operator')\n ) {\n retSelection = retSelection.rules![ 0 ]\n }\n\n return retSelection\n}\n\nexport {\n parseSele\n}\n","/**\n * @file Selection Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { Color } from 'three'\n\nimport { ColormakerRegistry } from '../globals'\nimport Selection from '../selection/selection'\nimport Colormaker, { ColormakerParameters } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport Structure from '../structure/structure'\n\nexport type SelectionSchemeData = [ string, string, ColormakerParameters|undefined ]\n\n/**\n * Color based on {@link Selection}\n */\nclass SelectionColormaker extends Colormaker {\n colormakerList: any[] = [] // TODO\n selectionList: Selection[] = []\n\n constructor (params: { structure: Structure, dataList: SelectionSchemeData[] } & Partial) {\n super(params)\n\n const dataList = params.dataList || []\n\n dataList.forEach((data: SelectionSchemeData) => {\n const [ scheme, sele, params = {} ] = data\n\n if (ColormakerRegistry.hasScheme(scheme)) {\n Object.assign(params, {\n scheme: scheme,\n structure: this.parameters.structure\n })\n } else {\n Object.assign(params, {\n scheme: 'uniform',\n value: new Color(scheme).getHex()\n })\n }\n\n this.colormakerList.push(ColormakerRegistry.getScheme(params as { scheme: string } & ColormakerParameters))\n this.selectionList.push(new Selection(sele))\n })\n }\n\n // NOT NEEDED @manageColor\n atomColor (a: AtomProxy) {\n for (let i = 0, n = this.selectionList.length; i < n; ++i) {\n const test = this.selectionList[ i ].test\n if (test && test(a)) {\n return this.colormakerList[ i ].atomColor(a)\n }\n }\n\n return 0xFFFFFF\n }\n}\n\nexport default SelectionColormaker\n","/**\n * @file Colormaker Registry\n * @author Alexander Rose \n * @private\n */\n\nimport { generateUUID } from '../math/math-utils'\nimport Colormaker, { ColormakerConstructor, ColormakerParameters } from './colormaker'\nimport SelectionColormaker, { SelectionSchemeData } from './selection-colormaker'\nimport Structure from '../structure/structure'\n\ntype ColormakerDefinitionFunction = ((this: Colormaker, param?: ColormakerParameters) => void)\n\nconst ColormakerScales = {\n '': '',\n\n // Sequential\n OrRd: '[S] Orange-Red',\n PuBu: '[S] Purple-Blue',\n BuPu: '[S] Blue-Purple',\n Oranges: '[S] Oranges',\n BuGn: '[S] Blue-Green',\n YlOrBr: '[S] Yellow-Orange-Brown',\n YlGn: '[S] Yellow-Green',\n Reds: '[S] Reds',\n RdPu: '[S] Red-Purple',\n Greens: '[S] Greens',\n YlGnBu: '[S] Yellow-Green-Blue',\n Purples: '[S] Purples',\n GnBu: '[S] Green-Blue',\n Greys: '[S] Greys',\n YlOrRd: '[S] Yellow-Orange-Red',\n PuRd: '[S] Purple-Red',\n Blues: '[S] Blues',\n PuBuGn: '[S] Purple-Blue-Green',\n\n // Diverging\n Viridis: '[D] Viridis',\n Spectral: '[D] Spectral',\n RdYlGn: '[D] Red-Yellow-Green',\n RdBu: '[D] Red-Blue',\n PiYG: '[D] Pink-Yellowgreen',\n PRGn: '[D] Purplered-Green',\n RdYlBu: '[D] Red-Yellow-Blue',\n BrBG: '[D] Brown-Bluegreen',\n RdGy: '[D] Red-Grey',\n PuOr: '[D] Purple-Orange',\n\n // Qualitative\n Set1: '[Q] Set1',\n Set2: '[Q] Set2',\n Set3: '[Q] Set3',\n Dark2: '[Q] Dark2',\n Paired: '[Q] Paired',\n Pastel1: '[Q] Pastel1',\n Pastel2: '[Q] Pastel2',\n Accent: '[Q] Accent',\n\n // Other\n rainbow: '[?] Rainbow',\n rwb: '[?] Red-White-Blue'\n}\n\nconst ColormakerModes = {\n '': '',\n\n rgb: 'Red Green Blue',\n hsv: 'Hue Saturation Value',\n hsl: 'Hue Saturation Lightness',\n hsi: 'Hue Saturation Intensity',\n lab: 'CIE L*a*b*',\n hcl: 'Hue Chroma Lightness'\n}\n\n/**\n * Class for registering {@link Colormaker}s. Generally use the\n * global {@link src/globals.js~ColormakerRegistry} instance.\n */\nclass ColormakerRegistry {\n schemes: { [k: string]: ColormakerConstructor }\n userSchemes: { [k: string]: ColormakerConstructor }\n\n constructor () {\n this.schemes = {}\n this.userSchemes = {}\n }\n\n getScheme (params: Partial<{ scheme: string } & ColormakerParameters>) {\n const p = params || {}\n const id = (p.scheme || '').toLowerCase()\n\n let SchemeClass: ColormakerConstructor\n\n if (id in this.schemes) {\n SchemeClass = this.schemes[ id ]\n } else if (id in this.userSchemes) {\n SchemeClass = this.userSchemes[ id ]\n } else {\n //@ts-expect-error abstract class used as a constructor\n SchemeClass = Colormaker\n }\n\n return new SchemeClass(params)\n }\n\n /**\n * Get an description of available schemes as an\n * object with id-label as key-value pairs\n * @return {Object} available schemes\n */\n getSchemes () {\n const types: { [k: string]: string } = {}\n\n Object.keys(this.schemes).forEach(function (k) {\n types[ k ] = k\n })\n\n Object.keys(this.userSchemes).forEach(function (k) {\n types[ k ] = k.split('|')[ 1 ]\n })\n\n return types\n }\n\n /**\n * Get an description of available scales as an\n * object with id-label as key-value pairs\n * @return {Object} available scales\n */\n getScales () {\n return ColormakerScales\n }\n\n getModes () {\n return ColormakerModes\n }\n\n /**\n * Add a scheme with a hardcoded id\n * @param {String} id - the id\n * @param {Colormaker} scheme - the colormaker\n * @return {undefined}\n */\n add (id: string, scheme: ColormakerConstructor) {\n id = id.toLowerCase()\n this.schemes[ id ] = scheme\n }\n\n /**\n * Register a custom scheme\n *\n * @example\n * // Create a class with a `atomColor` method that returns a hex color.\n * var schemeId = NGL.ColormakerRegistry.addScheme( function( params ){\n * this.atomColor = function( atom ){\n * if( atom.serial < 1000 ){\n * return 0x0000FF; // blue\n * }else if( atom.serial > 2000 ){\n * return 0xFF0000; // red\n * }else{\n * return 0x00FF00; // green\n * }\n * };\n * } );\n *\n * stage.loadFile( \"rcsb://3dqb.pdb\" ).then( function( o ){\n * o.addRepresentation( \"cartoon\", { color: schemeId } ); // pass schemeId here\n * o.autoView();\n * } );\n *\n * @param {Function|Colormaker} scheme - constructor or {@link Colormaker} instance\n * @param {String} label - scheme label\n * @return {String} id to refer to the registered scheme\n */\n addScheme (scheme: ColormakerConstructor|ColormakerDefinitionFunction, label?: string) {\n if (!(isColormakerSubClass(scheme))) {\n scheme = this._createScheme(scheme)\n }\n\n return this._addUserScheme(scheme, label)\n }\n\n /**\n * Add a user-defined scheme\n * @param {Colormaker} scheme - the user-defined scheme\n * @param {String} [label] - scheme label\n * @return {String} id to refer to the registered scheme\n */\n _addUserScheme (scheme: ColormakerConstructor, label?: string) {\n label = label || ''\n const id = `${generateUUID()}|${label}`.toLowerCase()\n this.userSchemes[ id ] = scheme\n\n return id\n }\n\n /**\n * Remove the scheme with the given id\n * @param {String} id - scheme to remove\n * @return {undefined}\n */\n removeScheme (id: string) {\n id = id.toLowerCase()\n delete this.userSchemes[ id ]\n }\n\n _createScheme (constructor: ColormakerDefinitionFunction): ColormakerConstructor {\n class _Colormaker extends Colormaker {\n constructor (params: ColormakerParameters) {\n super(params)\n constructor.call(this, params)\n }\n }\n return _Colormaker\n }\n\n /**\n * Create and a selection-based coloring scheme. Supply a list with pairs\n * of colorname and selection for coloring by selections. Use the last\n * entry as a default (catch all) coloring definition.\n *\n * @example\n * var schemeId = NGL.ColormakerRegistry.addSelectionScheme( [\n * [ \"red\", \"64-74 or 134-154 or 222-254 or 310-310 or 322-326\" ],\n * [ \"green\", \"311-322\" ],\n * [ \"yellow\", \"40-63 or 75-95 or 112-133 or 155-173 or 202-221 or 255-277 or 289-309\" ],\n * [ \"blue\", \"1-39 or 96-112 or 174-201 or 278-288\" ],\n * [ \"white\", \"*\" ]\n * ], \"Transmembrane 3dqb\" );\n *\n * stage.loadFile( \"rcsb://3dqb.pdb\" ).then( function( o ){\n * o.addRepresentation( \"cartoon\", { color: schemeId } ); // pass schemeId here\n * o.autoView();\n * } );\n *\n * @param {Array} dataList - cloror-selection pairs\n * @param {String} label - scheme name\n * @return {String} id to refer to the registered scheme\n */\n addSelectionScheme (dataList: SelectionSchemeData[], label?: string) {\n class MySelectionColormaker extends SelectionColormaker {\n constructor (params: { structure: Structure } & ColormakerParameters) {\n super(Object.assign({ dataList }, params))\n }\n }\n\n return this._addUserScheme(MySelectionColormaker, label)\n }\n\n /**\n * Check if a scheme with the given id exists\n * @param {String} id - the id to check\n * @return {Boolean} flag indicating if the scheme exists\n */\n hasScheme (id: string) {\n id = id.toLowerCase()\n return id in this.schemes || id in this.userSchemes\n }\n}\n\nfunction isColormakerSubClass (\n scheme: ColormakerConstructor|((this: Colormaker, param?: ColormakerParameters) => void)\n): scheme is ColormakerConstructor {\n return (scheme instanceof Colormaker)\n}\n\nexport default ColormakerRegistry\n","/**\n * @file Worker Utils\n * @author Alexander Rose \n * @private\n */\n\nimport { uniqueArray } from '../utils'\n\nexport type FunctionWithDeps = { __deps?: Function[] } & Function\nexport interface WorkerEvent {\n data: {\n __name: string\n __postId: string\n }\n}\n\nfunction getWorkerDeps (vars: FunctionWithDeps[]) {\n const deps = vars\n vars.forEach(function (sym) {\n if (sym.__deps) {\n Array.prototype.push.apply(deps, getWorkerDeps(sym.__deps))\n }\n })\n return deps\n}\n\nfunction makeWorkerString (vars: any) {\n const deps = uniqueArray(getWorkerDeps(vars))\n return deps.map(function (sym) {\n return sym.toString()\n }).join('\\n\\n\\n')\n}\n\nfunction onmessage (e: WorkerEvent) {\n const name = e.data.__name\n const postId = e.data.__postId\n\n /* global self */\n if (name === undefined) {\n console.error('message __name undefined')\n } else if ((self as any).func === undefined) {\n console.error('worker func undefined', name)\n } else {\n const callback = function (aMessage: any, transferList: any[]) {\n aMessage = aMessage || {}\n if (postId !== undefined) aMessage.__postId = postId\n\n try {\n (self as any).postMessage(aMessage, transferList)\n } catch (error) {\n console.error('self.postMessage:', error);\n (self as any).postMessage(aMessage)\n }\n };\n (self as any).func(e, callback)\n }\n}\n\nexport function makeWorkerBlob (func: Function, deps: Function[]) {\n let str = \"'use strict';\\n\\n\" + makeWorkerString(deps)\n str += '\\n\\n\\nself.func = ' + func.toString() + ';'\n str += '\\n\\n\\nself.onmessage = ' + onmessage.toString() + ';'\n // console.log(str);\n return new Blob([ str ], { type: 'application/javascript' })\n}\n","/**\n * @file Globals\n * @author Alexander Rose \n * @private\n */\n\nimport { getBrowser, getQuery, boolean } from './utils'\nimport Registry from './utils/registry'\nimport _ColormakerRegistry from './color/colormaker-registry'\nimport _ParserRegistry from './parser/parser-registry'\nimport _WorkerRegistry from './worker/worker-registry'\nimport { MeasurementRepresentationParameters } from './representation/measurement-representation';\n\n/**\n * The browser name: \"Opera\", \"Chrome\", \"Firefox\", \"Mobile Safari\",\n * \"Internet Explorer\", \"Safari\" or false.\n */\nexport const Browser = getBrowser()\n\n/**\n * Flag indicating support for the 'passive' option for event handler\n */\nexport let SupportsPassiveEventHandler = false\ntry {\n // Test via a getter in the options object to see if the passive property is accessed\n const opts = Object.defineProperty({}, 'passive', {\n get: function () {\n SupportsPassiveEventHandler = true\n }\n })\n window.addEventListener('test', e => {}, opts)\n} catch (e) {}\n\n/**\n * Flag indicating a mobile browser\n */\nexport const Mobile = typeof window !== 'undefined' ? typeof window.orientation !== 'undefined' : false\n\nexport let SupportsReadPixelsFloat = false\nexport function setSupportsReadPixelsFloat (value: boolean) {\n SupportsReadPixelsFloat = value\n}\n\n/**\n * Flag indicating support for the `EXT_frag_depth` WebGL extension\n * (Always present in WebGL2)\n */\nexport let ExtensionFragDepth = false\nexport function setExtensionFragDepth (value: boolean) {\n ExtensionFragDepth = value\n}\n\nexport const Log = {\n log: Function.prototype.bind.call(console.log, console),\n info: Function.prototype.bind.call(console.info, console),\n warn: Function.prototype.bind.call(console.warn, console),\n error: Function.prototype.bind.call(console.error, console),\n time: Function.prototype.bind.call(console.time, console),\n timeEnd: Function.prototype.bind.call(console.timeEnd, console)\n}\n\nexport let MeasurementDefaultParams: Partial = {\n color: 'green',\n labelColor: 0x808080,\n labelAttachment: 'bottom-center',\n labelSize: 0.7,\n labelZOffset: 0.5,\n labelYOffset: 0.1,\n labelBorder: true,\n labelBorderColor: 0xd3d3d3,\n labelBorderWidth: 0.25,\n lineOpacity: 0.8,\n linewidth: 5.0,\n opacity: 0.6,\n\n labelUnit: 'angstrom',\n arcVisible: true,\n planeVisible: false\n}\nexport function setMeasurementDefaultParams (params = {}) {\n Object.assign(MeasurementDefaultParams, params)\n}\n\nexport let Debug = boolean(getQuery('debug'))\nexport function setDebug (value: boolean) {\n Debug = value\n}\n\nexport const WebglErrorMessage = '

Your browser/graphics card does not seem to support WebGL.

Find out how to get it here.

'\n\n/**\n * List of file extensions to be recognized as scripts\n */\nexport const ScriptExtensions = [ 'ngl', 'js' ]\n\nexport const WorkerRegistry = new _WorkerRegistry()\nexport const ColormakerRegistry = new _ColormakerRegistry()\nexport const DatasourceRegistry = new Registry('datasource')\nexport const RepresentationRegistry = new Registry('representatation')\nexport const ParserRegistry = new _ParserRegistry()\nexport const ShaderRegistry = new Registry('shader')\nexport const DecompressorRegistry = new Registry('decompressor')\nexport const ComponentRegistry = new Registry('component')\nexport const BufferRegistry = new Registry('buffer')\nexport const PickerRegistry = new Registry('picker')\n\nexport let ListingDatasource: any\nexport function setListingDatasource (value: any) {\n ListingDatasource = value\n}\n\nexport let TrajectoryDatasource: any // TODO should accept mdsrvDatasource\nexport function setTrajectoryDatasource (value: any) {\n TrajectoryDatasource = value\n}\n","/**\n * @file Worker Registry\n * @author Alexander Rose \n * @private\n */\n\nimport { makeWorkerBlob } from './worker-utils'\n\nclass WorkerRegistry {\n activeWorkerCount = 0\n\n private _funcDict: { [k: string]: Function } = {}\n private _depsDict: { [k: string]: Function[] } = {}\n private _blobDict: { [k: string]: Blob } = {}\n\n add (name: string, func: Function, deps: Function[]) {\n this._funcDict[ name ] = func\n this._depsDict[ name ] = deps\n }\n\n get (name: string) {\n if (!this._blobDict[ name ]) {\n this._blobDict[ name ] = makeWorkerBlob(\n this._funcDict[ name ], this._depsDict[ name ]\n )\n }\n return this._blobDict[ name ]\n }\n}\n\nexport default WorkerRegistry\n","/**\n * @file Parser Registry\n * @author Alexander Rose \n * @private\n */\n\nimport Registry from '../utils/registry'\n\nclass ParserRegistry extends Registry {\n constructor () {\n super('parser')\n }\n\n __hasObjName (key: string, objName: string) {\n const parser = this.get(key)\n return parser && parser.prototype.__objName === objName\n }\n\n isTrajectory (key: string) {\n return this.__hasObjName(key, 'frames')\n }\n\n isStructure (key: string) {\n return this.__hasObjName(key, 'structure')\n }\n\n isVolume (key: string) {\n return this.__hasObjName(key, 'volume')\n }\n\n isSurface (key: string) {\n return this.__hasObjName(key, 'surface')\n }\n\n isBinary (key: string) {\n const parser = this.get(key)\n return parser && parser.prototype.isBinary\n }\n\n isXml (key: string) {\n const parser = this.get(key)\n return parser && parser.prototype.isXml\n }\n\n isJson (key: string) {\n const parser = this.get(key)\n return parser && parser.prototype.isJson\n }\n\n getTrajectoryExtensions () {\n return this.names.filter(name => this.isTrajectory(name))\n }\n\n getStructureExtensions () {\n return this.names.filter(name => this.isStructure(name))\n }\n\n getVolumeExtensions () {\n return this.names.filter(name => this.isVolume(name))\n }\n\n getSurfaceExtensions () {\n return this.names.filter(name => this.isSurface(name))\n }\n}\n\nexport default ParserRegistry\n","/**\n * @file Streamer\n * @author Alexander Rose \n * @private\n */\n\nimport { DecompressorRegistry } from '../globals'\nimport { uint8ToString, defaults } from '../utils'\n\nexport interface StreamerParams {\n compressed?: string|false\n binary?: boolean\n json?: boolean\n xml?: boolean\n}\n\nabstract class Streamer {\n src: any\n data: any\n\n compressed: string|false\n binary: boolean\n json: boolean\n xml: boolean\n\n chunkSize = 1024 * 1024 * 10\n newline = '\\n'\n\n protected __pointer = 0\n protected __partialLine = ''\n\n constructor (src: any, params: StreamerParams = {}) {\n this.compressed = defaults(params.compressed, false)\n this.binary = defaults(params.binary, false)\n this.json = defaults(params.json, false)\n this.xml = defaults(params.xml, false)\n\n this.src = src\n }\n\n isBinary () {\n return this.binary || this.compressed\n }\n\n read () {\n return this._read().then(data => {\n const decompressFn = this.compressed ? DecompressorRegistry.get(this.compressed) : undefined\n\n if (this.compressed && decompressFn) {\n this.data = decompressFn(data)\n } else {\n if ((this.binary || this.compressed) && data instanceof ArrayBuffer) {\n data = new Uint8Array(data)\n }\n this.data = data\n }\n\n return this.data\n })\n }\n\n protected abstract _read (): Promise\n\n protected _chunk (start: number, end: number) {\n end = Math.min(this.data.length, end)\n\n if (start === 0 && this.data.length === end) {\n return this.data\n } else {\n if (this.isBinary()) {\n return this.data.subarray(start, end)\n } else {\n return this.data.substring(start, end)\n }\n }\n }\n\n chunk (start: number) {\n const end = start + this.chunkSize\n\n return this._chunk(start, end)\n }\n\n peekLines (m: number) {\n const data = this.data\n const n = data.length\n\n // FIXME does not work for multi-char newline\n const newline = this.isBinary() ? this.newline.charCodeAt(0) : this.newline\n\n let i\n let count = 0\n for (i = 0; i < n; ++i) {\n if (data[ i ] === newline) ++count\n if (count === m) break\n }\n\n const chunk = this._chunk(0, i + 1)\n const d = this.chunkToLines(chunk, '', i > n)\n\n return d.lines\n }\n\n chunkCount () {\n return Math.floor(this.data.length / this.chunkSize) + 1\n }\n\n asText () {\n return this.isBinary() ? uint8ToString(this.data) : this.data\n }\n\n chunkToLines (chunk: string|Uint8Array, partialLine: string, isLast: boolean) {\n const newline = this.newline\n\n if (!this.isBinary() && chunk.length === this.data.length) {\n return {\n lines: (chunk as string).split(newline),\n partialLine: ''\n }\n }\n\n let lines: string[] = []\n const str = this.isBinary() ? uint8ToString(chunk as Uint8Array) : chunk\n const idx = str.lastIndexOf(newline)\n\n if (idx === -1) {\n partialLine += str\n } else {\n const str2 = partialLine + str.substr(0, idx)\n lines = lines.concat(str2.split(newline))\n\n if (idx === str.length - newline.length) {\n partialLine = ''\n } else {\n partialLine = str.substr(idx + newline.length)\n }\n }\n\n if (isLast && partialLine !== '') {\n lines.push(partialLine)\n }\n\n return {\n lines: lines,\n partialLine: partialLine\n }\n }\n\n nextChunk () {\n const start = this.__pointer\n\n if (start > this.data.length) {\n return undefined\n }\n\n this.__pointer += this.chunkSize\n return this.chunk(start)\n }\n\n nextChunkOfLines () {\n const chunk = this.nextChunk()\n\n if (chunk === undefined) {\n return undefined\n }\n\n const isLast = this.__pointer > this.data.length\n const d = this.chunkToLines(chunk, this.__partialLine, isLast)\n\n this.__partialLine = d.partialLine\n\n return d.lines\n }\n\n eachChunk (callback: (chunk: string|Uint8Array, chunkNo: number, chunkCount: number) => void) {\n const chunkSize = this.chunkSize\n const n = this.data.length\n const chunkCount = this.chunkCount()\n\n for (let i = 0; i < n; i += chunkSize) {\n const chunk = this.chunk(i)\n const chunkNo = Math.round(i / chunkSize)\n\n callback(chunk, chunkNo, chunkCount)\n }\n }\n\n eachChunkOfLines (callback: (chunk: string[], chunkNo: number, chunkCount: number) => void) {\n this.eachChunk((chunk, chunkNo, chunkCount) => {\n const isLast = chunkNo === chunkCount + 1\n const d = this.chunkToLines(chunk, this.__partialLine, isLast)\n\n this.__partialLine = d.partialLine\n\n callback(d.lines, chunkNo, chunkCount)\n })\n }\n\n dispose () {\n delete this.src\n }\n}\n\nexport default Streamer\n","/**\n * @file File Streamer\n * @author Alexander Rose \n * @private\n */\n\nimport Streamer from './streamer'\n\ninterface FileReaderEventTarget extends EventTarget {\n result:string | ArrayBuffer | null\n}\n\ninterface FileReaderEvent extends ProgressEvent {\n target: FileReaderEventTarget | null;\n}\n\nclass FileStreamer extends Streamer {\n _read () {\n return new Promise((resolve, reject) => {\n const file = this.src\n const reader = new FileReader()\n\n reader.onload = (event: FileReaderEvent) => {\n if(event.target) resolve(event.target.result)\n }\n\n // if (typeof this.onprogress === 'function') {\n // reader.onprogress = event => this.onprogress(event)\n // }\n\n reader.onerror = event => reject(event)\n\n if (this.binary || this.compressed) {\n reader.readAsArrayBuffer(file)\n } else {\n reader.readAsText(file)\n }\n })\n }\n}\n\nexport default FileStreamer\n","/**\n * @file Network Streamer\n * @author Alexander Rose \n * @private\n */\n\nimport Streamer from './streamer'\n\nclass NetworkStreamer extends Streamer {\n _read () {\n return new Promise((resolve, reject) => {\n const url = this.src\n const xhr = new XMLHttpRequest()\n\n xhr.open('GET', url, true)\n\n xhr.addEventListener('load', () => {\n if (xhr.status === 200 || xhr.status === 304 ||\n // when requesting from local file system\n // the status in Google Chrome/Chromium is 0\n xhr.status === 0\n ) {\n try {\n resolve(xhr.response)\n } catch (e) {\n reject(e)\n }\n } else {\n reject(xhr.statusText)\n }\n }, false)\n\n // if (typeof this.onprogress === 'function') {\n // xhr.addEventListener('progress', event => this.onprogress(event), false);\n // }\n\n xhr.addEventListener('error', event => reject('network error'), false)\n\n if (this.isBinary()) {\n xhr.responseType = 'arraybuffer'\n } else if (this.json) {\n xhr.responseType = 'json'\n } else if (this.xml) {\n xhr.responseType = 'document'\n } else {\n xhr.responseType = 'text'\n }\n // xhr.crossOrigin = true;\n\n xhr.send()\n })\n }\n}\n\nexport default NetworkStreamer\n","/**\n * @file Loader\n * @author Alexander Rose \n * @private\n */\n\nimport { ParserRegistry } from '../globals'\nimport { createParams } from '../utils'\nimport FileStreamer from '../streamer/file-streamer'\nimport NetworkStreamer from '../streamer/network-streamer'\nimport { LoaderParameters, LoaderInput } from './loader-utils'\n\n/**\n * Loader parameter object.\n * @typedef {Object} LoaderParameters - loader parameters\n * @property {String} ext - file extension, determines file type\n * @property {Boolean} compressed - flag data as compressed\n * @property {Boolean} binary - flag data as binary\n * @property {String} name - set data name\n */\n\n/**\n * Loader base class\n */\nabstract class Loader {\n parameters: LoaderParameters\n streamer: FileStreamer | NetworkStreamer\n\n /**\n * Construct a loader object\n * @param {String|File|Blob} src - data source, string is interpreted as an URL\n * @param {LoaderParameters} params - parameters object\n */\n constructor (src: LoaderInput, params: Partial = {}) {\n this.parameters = createParams(params, {\n ext: '',\n compressed: false,\n binary: ParserRegistry.isBinary(params.ext || ''),\n name: '',\n\n dir: '',\n path: '',\n protocol: ''\n } as LoaderParameters)\n\n const streamerParams = {\n compressed: this.parameters.compressed as string|false,\n binary: this.parameters.binary,\n json: ParserRegistry.isJson(this.parameters.ext),\n xml: ParserRegistry.isXml(this.parameters.ext)\n }\n\n if ((typeof File !== 'undefined' && src instanceof File) ||\n (typeof Blob !== 'undefined' && src instanceof Blob)\n ) {\n this.streamer = new FileStreamer(src, streamerParams)\n } else {\n this.streamer = new NetworkStreamer(src, streamerParams)\n }\n }\n\n /**\n * Load data\n * @abstract\n * @return {Promise} resolves to the loaded data {@link Object}\n */\n abstract load (): Promise\n}\n\nexport default Loader\n","/**\n * @file Parser Loader\n * @author Alexander Rose \n * @private\n */\n\nimport { ParserRegistry } from '../globals'\nimport type { InferBondsOptions } from '../structure/structure-utils'\nimport Loader from './loader'\nimport { LoaderParameters, LoaderInput } from './loader-utils'\n\nexport interface ParserParams {\n voxelSize?: number\n firstModelOnly?: boolean\n asTrajectory?: boolean\n cAlphaOnly?: boolean\n name?: string\n path?: string\n delimiter?: string\n comment?: string\n columnNames?: string\n inferBonds?: InferBondsOptions\n}\n\n/**\n * Parser loader class\n * @extends Loader\n */\nclass ParserLoader extends Loader {\n parserParams: ParserParams\n\n constructor (src: LoaderInput, params: Partial & ParserParams = {}) {\n super(src, params)\n this.parserParams = {\n voxelSize: params.voxelSize,\n firstModelOnly: params.firstModelOnly,\n asTrajectory: params.asTrajectory,\n cAlphaOnly: params.cAlphaOnly,\n delimiter: params.delimiter,\n comment: params.comment,\n columnNames: params.columnNames,\n inferBonds: params.inferBonds,\n name: this.parameters.name,\n path: this.parameters.path\n }\n }\n\n /**\n * Load parsed object\n * @return {Promise} resolves to the loaded & parsed {@link Structure},\n * {@link Volume}, {@link Surface} or data object\n */\n load () {\n var ParserClass = ParserRegistry.get(this.parameters.ext)\n var parser = new ParserClass(this.streamer, this.parserParams)\n\n return parser.parse()\n }\n}\n\nexport default ParserLoader\n","/**\n * @file Script\n * @author Alexander Rose \n * @private\n */\n\nimport { Signal } from 'signals'\n\nimport { Log } from './globals'\nimport Stage from './stage/stage'\n\nexport interface ScriptSignals {\n elementAdded: Signal\n elementRemoved: Signal\n nameChanged: Signal\n}\n\n/**\n * Script class\n */\nclass Script {\n readonly signals: ScriptSignals = {\n elementAdded: new Signal(),\n elementRemoved: new Signal(),\n nameChanged: new Signal()\n }\n\n readonly dir: string\n readonly fn: Function\n\n readonly type = 'Script'\n\n /**\n * Create a script instance\n * @param {String} functionBody - the function source\n * @param {String} name - name of the script\n * @param {String} path - path of the script\n */\n constructor (functionBody: string, readonly name: string, readonly path: string) {\n this.dir = path.substring(0, path.lastIndexOf('/') + 1)\n\n try {\n /* eslint-disable no-new-func */\n this.fn = new Function('stage', '__name', '__path', '__dir', functionBody)\n } catch (e) {\n Log.error('Script compilation failed', e)\n this.fn = function () {}\n }\n }\n\n /**\n * Execute the script\n * @param {Stage} stage - the stage context\n * @return {Promise} - resolve when script finished running\n */\n run (stage: Stage): Promise {\n return new Promise((resolve, reject) => {\n try {\n this.fn.apply(null, [ stage, this.name, this.path, this.dir ])\n resolve()\n } catch (e) {\n Log.error('Script.fn', e)\n reject(e)\n }\n })\n }\n}\n\nexport default Script\n","/**\n * @file Script Loader\n * @author Alexander Rose \n * @private\n */\n\nimport Loader from './loader'\nimport Script from '../script'\n\n/**\n * Script loader class\n * @extends Loader\n */\nclass ScriptLoader extends Loader {\n /**\n * Load script\n * @return {Promise} resolves to the loaded {@link Script}\n */\n load () {\n return this.streamer.read().then(() => {\n return new Script(\n this.streamer.asText(), this.parameters.name, this.parameters.path\n )\n })\n }\n}\n\nexport default ScriptLoader\n","/**\n * @file Loader Utils\n * @author Alexander Rose \n * @private\n */\n\nimport {\n DatasourceRegistry, DecompressorRegistry, ParserRegistry, ScriptExtensions\n} from '../globals'\nimport ParserLoader, { ParserParams } from './parser-loader'\nimport ScriptLoader from './script-loader'\n\nexport interface LoaderParameters {\n ext: string // file extension, determines file type\n compressed: string|false // flag data as compressed\n binary: boolean // flag data as binary\n name: string // set data name\n\n dir: string\n path: string\n protocol: string\n}\n\nexport type LoaderInput = File|Blob|string\n\nexport function getFileInfo (file: LoaderInput) {\n const compressedExtList = DecompressorRegistry.names\n\n let path: string\n let compressed: string|false\n let protocol = ''\n\n if (file instanceof File) {\n path = file.name\n } else if (file instanceof Blob) {\n path = ''\n } else {\n path = file\n }\n const queryIndex = path.lastIndexOf('?')\n const query = queryIndex !== -1 ? path.substring(queryIndex) : ''\n path = path.substring(0, queryIndex === -1 ? path.length : queryIndex)\n\n const name = path.replace(/^.*[\\\\/]/, '')\n let base = name.substring(0, name.lastIndexOf('.'))\n\n const nameSplit = name.split('.')\n let ext = nameSplit.length > 1 ? (nameSplit.pop() || '').toLowerCase() : ''\n\n const protocolMatch = path.match(/^(.+):\\/\\/(.+)$/)\n if (protocolMatch) {\n protocol = protocolMatch[ 1 ].toLowerCase()\n path = protocolMatch[ 2 ] || ''\n }\n\n const dir = path.substring(0, path.lastIndexOf('/') + 1)\n\n if (compressedExtList.includes(ext)) {\n compressed = ext\n const n = path.length - ext.length - 1\n ext = (path.substr(0, n).split('.').pop() || '').toLowerCase()\n const m = base.length - ext.length - 1\n base = base.substr(0, m)\n } else {\n compressed = false\n }\n\n return { path, name, ext, base, dir, compressed, protocol, query, 'src': file }\n}\n\nexport function getDataInfo (src: LoaderInput) {\n let info = getFileInfo(src)\n const datasource = DatasourceRegistry.get(info.protocol)\n if (datasource) {\n info = getFileInfo(datasource.getUrl(info.src))\n if (!info.ext && datasource.getExt) {\n info.ext = datasource.getExt(src)\n }\n }\n return info\n}\n\n/**\n * Load a file\n *\n * @example\n * // load from URL\n * NGL.autoLoad( \"http://files.rcsb.org/download/5IOS.cif\" );\n *\n * @example\n * // load binary data in CCP4 format via a Blob\n * var binaryBlob = new Blob( [ ccp4Data ], { type: 'application/octet-binary'} );\n * NGL.autoLoad( binaryBlob, { ext: \"ccp4\" } );\n *\n * @example\n * // load string data in PDB format via a Blob\n * var stringBlob = new Blob( [ pdbData ], { type: 'text/plain'} );\n * NGL.autoLoad( stringBlob, { ext: \"pdb\" } );\n *\n * @example\n * // load a File object\n * NGL.autoLoad( file );\n *\n * @param {String|File|Blob} file - either a URL or an object containing the file data\n * @param {LoaderParameters} params - loading parameters\n * @return {Promise} Promise resolves to the loaded data\n */\nexport function autoLoad (file: LoaderInput, params: Partial = {}) {\n const p = Object.assign(getDataInfo(file), params)\n\n let loader\n if (ParserRegistry.names.includes(p.ext)) {\n loader = new ParserLoader(p.src, p)\n } else if (ScriptExtensions.includes(p.ext)) {\n loader = new ScriptLoader(p.src, p)\n }\n\n if (loader) {\n return loader.load()\n } else {\n return Promise.reject(new Error(`autoLoad: ext '${p.ext}' unknown`))\n }\n}\n","/**\n * @file Writer\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults, download } from '../utils'\n\n/**\n * Base class for writers\n * @interface\n */\nabstract class Writer {\n readonly mimeType: string\n readonly defaultName: string\n readonly defaultExt: string\n\n /**\n * @abstract\n * @return {Anything} the data to be written\n */\n abstract getData (): any\n\n /**\n * Get a blob with the written data\n * @return {Blob} the blob\n */\n getBlob () {\n return new Blob([ this.getData() ], { type: this.mimeType })\n }\n\n /**\n * Trigger a download of the\n * @param {[type]} name [description]\n * @param {[type]} ext [description]\n * @return {[type]} [description]\n */\n download (name?: string, ext?: string) {\n name = defaults(name, this.defaultName)\n ext = defaults(ext, this.defaultExt)\n\n download(this.getBlob(), `${name}.${ext}`)\n }\n}\n\nexport default Writer","/**\n * @file Pdb Writer\n * @author Alexander Rose \n * @private\n */\n\nimport { sprintf } from 'sprintf-js'\n\nimport Writer from './writer'\nimport { defaults, ensureArray } from '../utils'\nimport Structure from '../structure/structure'\nimport AtomProxy from '../proxy/atom-proxy'\n\n// http://www.wwpdb.org/documentation/file-format\n\n// Sample PDB line, the coords X,Y,Z are fields 5,6,7 on each line.\n// ATOM 1 N ARG 1 29.292 13.212 -12.751 1.00 33.78 1BPT 108\n\nconst AtomFormat =\n 'ATOM %5d %-4s %3s %1s%4d %8.3f%8.3f%8.3f%6.2f%6.2f %4s%2s%1s%1s'\n\nconst HetatmFormat =\n 'HETATM%5d %-4s %3s %1s%4d %8.3f%8.3f%8.3f%6.2f%6.2f %4s%2s%1s%1s'\n\nexport interface PdbWriterParams {\n renumberSerial: boolean\n remarks: string[]\n}\n\n/**\n * Create a PDB file from a Structure object\n */\nexport default class PdbWriter extends Writer {\n readonly mimeType = 'text/plain'\n readonly defaultName = 'structure'\n readonly defaultExt = 'pdb'\n\n renumberSerial: boolean\n remarks: string[]\n\n structure: Structure\n private _records: string[]\n\n /**\n * @param {Structure} structure - the structure object\n * @param {Object} params - parameters]\n */\n constructor (structure: Structure, params?: PdbWriterParams) {\n super()\n\n const p = Object.assign({}, params)\n\n this.renumberSerial = defaults(p.renumberSerial, true)\n this.remarks = ensureArray(defaults(p.remarks, []))\n\n this.structure = structure\n this._records = []\n }\n\n private _writeRecords () {\n this._records.length = 0\n\n this._writeTitle()\n this._writeRemarks()\n this._writeAtoms()\n }\n\n private _writeTitle () {\n // FIXME multiline if title line longer than 80 chars\n this._records.push(sprintf('TITLE %-74s', this.structure.name))\n }\n\n private _writeRemarks () {\n this.remarks.forEach(str => {\n this._records.push(sprintf('REMARK %-73s', str))\n })\n\n if (this.structure.trajectory) {\n this._records.push(sprintf(\n 'REMARK %-73s',\n \"Trajectory '\" + this.structure.trajectory.name + \"'\"\n ))\n this._records.push(sprintf(\n 'REMARK %-73s',\n `Frame ${(this.structure.trajectory as any).frame}` // TODO\n ))\n }\n }\n\n private _writeAtoms () {\n let ia = 1\n let im = 1\n let charge = \" \"\n let chargeSign = \" \"\n const hasModels = this.structure.modelStore.count > 1\n\n this.structure.eachModel(m => {\n if (hasModels) this._records.push(sprintf('MODEL %4d%-66s', im++, ''))\n\n m.eachAtom((a: AtomProxy) => {\n const formatString = a.hetero ? HetatmFormat : AtomFormat\n const serial = this.renumberSerial ? ia : a.serial\n\n // Formal PDB spec\n // Alignment of one-letter atom name such as C starts at column 14,\n // while two-letter atom name such as FE starts at column 13.\n\n // This, however, leaves Calcium and C-alpha ambiguous\n // The convention (from earlier versions of the spec, see 1992, and also: \n // https://www.cgl.ucsf.edu/chimera/docs/UsersGuide/tutorials/pdbintro.html#misalignment)\n // is that element is right-justified in 13-14, modifiers are left justified in columns 15-16\n // A single-character element symmbol should not appear in column 13 unless the atom name has four characters\n let atomname = a.atomname\n\n if (atomname.length === 1) {\n // Simple case\n atomname = ' ' + atomname\n } else if (atomname.length < 4) {\n // 2 or 3-letter name, if element symbol is single char and matches name, add a space\n if (a.element.length === 1 && atomname[0] === a.element) {\n atomname = ' ' + atomname\n }\n }\n\n if (a.formalCharge) { // Skip nulls and zeros\n charge = Math.abs(a.formalCharge).toPrecision(1)\n chargeSign = (a.formalCharge > 0) ? \"+\" : \"-\"\n } else {\n charge = \" \"\n chargeSign = \" \"\n }\n\n this._records.push(sprintf(\n formatString,\n\n serial,\n atomname,\n a.resname,\n defaults(a.chainname, ' '),\n a.resno,\n a.x, a.y, a.z,\n defaults(a.occupancy, 1.0),\n defaults(a.bfactor, 0.0),\n '', // segid\n defaults(a.element, ''),\n charge,\n chargeSign\n ))\n ia += 1\n }, this.structure.getSelection())\n\n if (hasModels) this._records.push(sprintf('%-80s', 'ENDMDL'))\n })\n\n this._records.push(sprintf('%-80s', 'END'))\n }\n\n getString () {\n console.warn('PdbWriter.getString() is deprecated, use .getData instead')\n return this.getData()\n }\n\n /**\n * Get string containing the PDB file data\n * @return {String} PDB file\n */\n getData () {\n this._writeRecords()\n return this._records.join('\\n')\n }\n}\n","/**\n * Writer class for sdf/mol files.\n */\n\nimport { sprintf } from 'sprintf-js'\n\nimport Writer from './writer'\nimport Structure from '../structure/structure'\nimport AtomProxy from '../proxy/atom-proxy'\nimport BondProxy from '../proxy/bond-proxy'\n\n// Hard-coded chiral as false as we don't specify it any atoms\nconst CountFormat = '%3i%3i 0 0 0 0 0 0 0 0999 V2000'\nconst AtomLine = '%10.4f%10.4f%10.4f %-3s 0%3i 0 0 0'\nconst BondFormat = '%3i%3i%3i 0 0 0'\n\nclass SdfWriter extends Writer {\n readonly mimeType = 'text/plain'\n readonly defaultName = 'structure'\n readonly defaultExt = 'sdf'\n\n structure: Structure\n private _records: string[]\n\n /**\n * @param {Structure} structure - structure to write\n * @param {Object} params - parameters\n */\n constructor (structure: Structure) {\n super()\n\n this.structure = structure\n // Follow the pdb-writer example:\n this._records = []\n }\n\n get idString () {\n return this.structure.id\n }\n\n get titleString () {\n return ' ' + this.structure.title\n }\n\n get countsString () {\n return sprintf(\n CountFormat,\n this.structure.atomCount,\n this.structure.bondCount\n )\n }\n\n get chargeLines () {\n const pairs: [number, number][] = []\n this.structure.eachAtom(ap => {\n if (ap.formalCharge != null && ap.formalCharge !== 0) {\n pairs.push([ap.index, ap.formalCharge])\n }\n })\n const lines = []\n for (let i = 0; i < pairs.length; i += 8) {\n const nCharges = Math.min(8, pairs.length - i)\n let s = sprintf('M CHG%3i', nCharges)\n for (let j = i; j < i + nCharges; j++) {\n s += sprintf(' %3i %3i', pairs[j][0] + 1, pairs[j][1])\n }\n lines.push(s)\n }\n return lines\n }\n\n formatAtom (ap: AtomProxy) {\n let charge = 0\n if (ap.formalCharge != null && ap.formalCharge !== 0) {\n charge = 4 - ap.formalCharge\n }\n const line = sprintf(\n AtomLine, ap.x, ap.y, ap.z, ap.element, charge\n )\n if (line.length !== 48) { throw new Error('Incompatible atom for sdf format') }\n\n return line\n }\n\n formatBond (bp: BondProxy) {\n return sprintf(\n BondFormat,\n bp.atomIndex1 + 1,\n bp.atomIndex2 + 1,\n bp.bondOrder)\n }\n\n _writeRecords () {\n this._records.length = 0\n this._writeHeader()\n this._writeCTab()\n this._writeFooter()\n }\n\n _writeHeader () {\n this._records.push(this.idString, this.titleString, '')\n }\n\n _writeCTab () {\n this._records.push(this.countsString)\n this.structure.eachAtom(ap => {\n this._records.push(this.formatAtom(ap))\n })\n this.structure.eachBond(bp => {\n this._records.push(this.formatBond(bp))\n })\n this.chargeLines.forEach(line => {\n this._records.push(line)\n })\n this._records.push('M END')\n }\n\n _writeFooter () {\n this._records.push('$$$$')\n }\n\n getData () {\n this._writeRecords()\n return this._records.join('\\n')\n }\n}\n\nexport default SdfWriter\n","/**\n * @file IO Buffer\n * @author Alexander Rose \n * @private\n *\n * Adapted and converted to TypeScript from https://github.com/image-js/iobuffer\n * MIT License, Copyright (c) 2015 Michaël Zasso\n */\n\nimport { TypedArray } from '../types'\n\nconst defaultByteLength = 1024 * 8\nconst charArray: string[] = []\n\nexport interface IOBufferParameters {\n offset?: number // Ignore the first n bytes of the ArrayBuffer\n}\n\n/**\n * Class for writing and reading binary data\n */\nclass IOBuffer {\n private _lastWrittenByte: number\n private _mark = 0\n private _marks: number[] = []\n private _data: DataView\n\n offset = 0 // The current offset of the buffer's pointer\n littleEndian = true\n buffer: ArrayBuffer // Reference to the internal ArrayBuffer object\n length: number // Byte length of the internal ArrayBuffer\n byteLength: number // Byte length of the internal ArrayBuffer\n byteOffset: number // Byte offset of the internal ArrayBuffer\n\n /**\n * If it's a number, it will initialize the buffer with the number as\n * the buffer's length. If it's undefined, it will initialize the buffer\n * with a default length of 8 Kb. If its an ArrayBuffer, a TypedArray,\n * it will create a view over the underlying ArrayBuffer.\n */\n constructor (data: number|ArrayBuffer|TypedArray, params: IOBufferParameters = {}) {\n let dataIsGiven = false\n if (data === undefined) {\n data = defaultByteLength\n }\n if (typeof data === 'number') {\n data = new ArrayBuffer(data)\n } else {\n dataIsGiven = true\n }\n\n const offset = params.offset ? params.offset >>> 0 : 0\n let byteLength = data.byteLength - offset\n let dvOffset = offset\n if (!(data instanceof ArrayBuffer)) {\n if (data.byteLength !== data.buffer.byteLength) {\n dvOffset = data.byteOffset + offset\n }\n data = data.buffer\n }\n if (dataIsGiven) {\n this._lastWrittenByte = byteLength\n } else {\n this._lastWrittenByte = 0\n }\n\n this.buffer = data\n this.length = byteLength\n this.byteLength = byteLength\n this.byteOffset = dvOffset\n\n this._data = new DataView(this.buffer, dvOffset, byteLength)\n }\n\n /**\n * Checks if the memory allocated to the buffer is sufficient to store more bytes after the offset\n * @param {number} [byteLength=1] The needed memory in bytes\n * @return {boolean} Returns true if there is sufficient space and false otherwise\n */\n available (byteLength: number) {\n if (byteLength === undefined) byteLength = 1\n return (this.offset + byteLength) <= this.length\n }\n\n /**\n * Check if little-endian mode is used for reading and writing multi-byte values\n * @return {boolean} Returns true if little-endian mode is used, false otherwise\n */\n isLittleEndian () {\n return this.littleEndian\n }\n\n /**\n * Set little-endian mode for reading and writing multi-byte values\n * @return {IOBuffer}\n */\n setLittleEndian () {\n this.littleEndian = true\n return this\n }\n\n /**\n * Check if big-endian mode is used for reading and writing multi-byte values\n * @return {boolean} Returns true if big-endian mode is used, false otherwise\n */\n isBigEndian () {\n return !this.littleEndian\n }\n\n /**\n * Switches to big-endian mode for reading and writing multi-byte values\n * @return {IOBuffer}\n */\n setBigEndian () {\n this.littleEndian = false\n return this\n }\n\n /**\n * Move the pointer n bytes forward\n * @param {number} n\n * @return {IOBuffer}\n */\n skip (n: number) {\n if (n === undefined) n = 1\n this.offset += n\n return this\n }\n\n /**\n * Move the pointer to the given offset\n * @param {number} offset\n * @return {IOBuffer}\n */\n seek (offset: number) {\n this.offset = offset\n return this\n }\n\n /**\n * Store the current pointer offset.\n * @see {@link IOBuffer#reset}\n * @return {IOBuffer}\n */\n mark () {\n this._mark = this.offset\n return this\n }\n\n /**\n * Move the pointer back to the last pointer offset set by mark\n * @see {@link IOBuffer#mark}\n * @return {IOBuffer}\n */\n reset () {\n this.offset = this._mark\n return this\n }\n\n /**\n * Push the current pointer offset to the mark stack\n * @see {@link IOBuffer#popMark}\n * @return {IOBuffer}\n */\n pushMark () {\n this._marks.push(this.offset)\n return this\n }\n\n /**\n * Pop the last pointer offset from the mark stack, and set the current pointer offset to the popped value\n * @see {@link IOBuffer#pushMark}\n * @return {IOBuffer}\n */\n popMark () {\n const offset = this._marks.pop()\n if (offset === undefined) throw new Error('Mark stack empty')\n this.seek(offset)\n return this\n }\n\n /**\n * Move the pointer offset back to 0\n * @return {IOBuffer}\n */\n rewind () {\n this.offset = 0\n return this\n }\n\n /**\n * Make sure the buffer has sufficient memory to write a given byteLength at the current pointer offset\n * If the buffer's memory is insufficient, this method will create a new buffer (a copy) with a length\n * that is twice (byteLength + current offset)\n * @param {number} [byteLength = 1]\n * @return {IOBuffer}\n */\n ensureAvailable (byteLength: number) {\n if (byteLength === undefined) byteLength = 1\n if (!this.available(byteLength)) {\n const lengthNeeded = this.offset + byteLength\n const newLength = lengthNeeded * 2\n const newArray = new Uint8Array(newLength)\n newArray.set(new Uint8Array(this.buffer))\n this.buffer = newArray.buffer\n this.length = this.byteLength = newLength\n this._data = new DataView(this.buffer)\n }\n return this\n }\n\n /**\n * Read a byte and return false if the byte's value is 0, or true otherwise\n * Moves pointer forward\n * @return {boolean}\n */\n readBoolean () {\n return this.readUint8() !== 0\n }\n\n /**\n * Read a signed 8-bit integer and move pointer forward\n * @return {number}\n */\n readInt8 () {\n return this._data.getInt8(this.offset++)\n }\n\n /**\n * Read an unsigned 8-bit integer and move pointer forward\n * @return {number}\n */\n readUint8 () {\n return this._data.getUint8(this.offset++)\n }\n\n /**\n * Alias for {@link IOBuffer#readUint8}\n * @return {number}\n */\n readByte () {\n return this.readUint8()\n }\n\n /**\n * Read n bytes and move pointer forward.\n * @param {number} n\n * @return {Uint8Array}\n */\n readBytes (n: number) {\n if (n === undefined) n = 1\n var bytes = new Uint8Array(n)\n for (var i = 0; i < n; i++) {\n bytes[i] = this.readByte()\n }\n return bytes\n }\n\n /**\n * Read a 16-bit signed integer and move pointer forward\n * @return {number}\n */\n readInt16 () {\n var value = this._data.getInt16(this.offset, this.littleEndian)\n this.offset += 2\n return value\n }\n\n /**\n * Read a 16-bit unsigned integer and move pointer forward\n * @return {number}\n */\n readUint16 () {\n var value = this._data.getUint16(this.offset, this.littleEndian)\n this.offset += 2\n return value\n }\n\n /**\n * Read a 32-bit signed integer and move pointer forward\n * @return {number}\n */\n readInt32 () {\n var value = this._data.getInt32(this.offset, this.littleEndian)\n this.offset += 4\n return value\n }\n\n /**\n * Read a 32-bit unsigned integer and move pointer forward\n * @return {number}\n */\n readUint32 () {\n var value = this._data.getUint32(this.offset, this.littleEndian)\n this.offset += 4\n return value\n }\n\n /**\n * Read a 32-bit floating number and move pointer forward\n * @return {number}\n */\n readFloat32 () {\n var value = this._data.getFloat32(this.offset, this.littleEndian)\n this.offset += 4\n return value\n }\n\n /**\n * Read a 64-bit floating number and move pointer forward\n * @return {number}\n */\n readFloat64 () {\n var value = this._data.getFloat64(this.offset, this.littleEndian)\n this.offset += 8\n return value\n }\n\n /**\n * Read 1-byte ascii character and move pointer forward\n * @return {string}\n */\n readChar () {\n return String.fromCharCode(this.readInt8())\n }\n\n /**\n * Read n 1-byte ascii characters and move pointer forward\n * @param {number} n\n * @return {string}\n */\n readChars (n = 1) {\n charArray.length = n\n for (var i = 0; i < n; i++) {\n charArray[i] = this.readChar()\n }\n return charArray.join('')\n }\n\n /**\n * Write 0xff if the passed value is truthy, 0x00 otherwise\n * @param {any} value\n * @return {IOBuffer}\n */\n writeBoolean (value = false) {\n this.writeUint8(value ? 0xff : 0x00)\n return this\n }\n\n /**\n * Write value as an 8-bit signed integer\n * @param {number} value\n * @return {IOBuffer}\n */\n writeInt8 (value: number) {\n this.ensureAvailable(1)\n this._data.setInt8(this.offset++, value)\n this._updateLastWrittenByte()\n return this\n }\n\n /**\n * Write value as a 8-bit unsigned integer\n * @param {number} value\n * @return {IOBuffer}\n */\n writeUint8 (value: number) {\n this.ensureAvailable(1)\n this._data.setUint8(this.offset++, value)\n this._updateLastWrittenByte()\n return this\n }\n\n /**\n * An alias for {@link IOBuffer#writeUint8}\n * @param {number} value\n * @return {IOBuffer}\n */\n writeByte (value: number) {\n return this.writeUint8(value)\n }\n\n /**\n * Write bytes\n * @param {Array|Uint8Array} bytes\n * @return {IOBuffer}\n */\n writeBytes (bytes: number[]|Uint8Array) {\n this.ensureAvailable(bytes.length)\n for (var i = 0; i < bytes.length; i++) {\n this._data.setUint8(this.offset++, bytes[i])\n }\n this._updateLastWrittenByte()\n return this\n }\n\n /**\n * Write value as an 16-bit signed integer\n * @param {number} value\n * @return {IOBuffer}\n */\n writeInt16 (value: number) {\n this.ensureAvailable(2)\n this._data.setInt16(this.offset, value, this.littleEndian)\n this.offset += 2\n this._updateLastWrittenByte()\n return this\n }\n\n /**\n * Write value as a 16-bit unsigned integer\n * @param {number} value\n * @return {IOBuffer}\n */\n writeUint16 (value: number) {\n this.ensureAvailable(2)\n this._data.setUint16(this.offset, value, this.littleEndian)\n this.offset += 2\n this._updateLastWrittenByte()\n return this\n }\n\n /**\n * Write a 32-bit signed integer at the current pointer offset\n * @param {number} value\n * @return {IOBuffer}\n */\n writeInt32 (value: number) {\n this.ensureAvailable(4)\n this._data.setInt32(this.offset, value, this.littleEndian)\n this.offset += 4\n this._updateLastWrittenByte()\n return this\n }\n\n /**\n * Write a 32-bit unsigned integer at the current pointer offset\n * @param {number} value - The value to set\n * @return {IOBuffer}\n */\n writeUint32 (value: number) {\n this.ensureAvailable(4)\n this._data.setUint32(this.offset, value, this.littleEndian)\n this.offset += 4\n this._updateLastWrittenByte()\n return this\n }\n\n /**\n * Write a 32-bit floating number at the current pointer offset\n * @param {number} value - The value to set\n * @return {IOBuffer}\n */\n writeFloat32 (value: number) {\n this.ensureAvailable(4)\n this._data.setFloat32(this.offset, value, this.littleEndian)\n this.offset += 4\n this._updateLastWrittenByte()\n return this\n }\n\n /**\n * Write a 64-bit floating number at the current pointer offset\n * @param {number} value\n * @return {IOBuffer}\n */\n writeFloat64 (value: number) {\n this.ensureAvailable(8)\n this._data.setFloat64(this.offset, value, this.littleEndian)\n this.offset += 8\n this._updateLastWrittenByte()\n return this\n }\n\n /**\n * Write the charCode of the passed string's first character to the current pointer offset\n * @param {string} str - The character to set\n * @return {IOBuffer}\n */\n writeChar (str: string) {\n return this.writeUint8(str.charCodeAt(0))\n }\n\n /**\n * Write the charCodes of the passed string's characters to the current pointer offset\n * @param {string} str\n * @return {IOBuffer}\n */\n writeChars (str: string) {\n for (var i = 0; i < str.length; i++) {\n this.writeUint8(str.charCodeAt(i))\n }\n return this\n }\n\n /**\n * Export a Uint8Array view of the internal buffer.\n * The view starts at the byte offset and its length\n * is calculated to stop at the last written byte or the original length.\n * @return {Uint8Array}\n */\n toArray () {\n return new Uint8Array(this.buffer, this.byteOffset, this._lastWrittenByte)\n }\n\n /**\n * Update the last written byte offset\n * @private\n */\n _updateLastWrittenByte () {\n if (this.offset > this._lastWrittenByte) {\n this._lastWrittenByte = this.offset\n }\n }\n}\n\nexport default IOBuffer\n","/**\n * @file STL Writer\n * @author Paul Pillot \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport Writer from './writer'\nimport IOBuffer from '../utils/io-buffer'\nimport Surface from '../surface/surface'\n\n// https://en.wikipedia.org/wiki/STL_(file_format)#ASCII_STL\n\n/**\n * Create an STL File from a surface Object (e.g. for 3D printing)\n *\n * @example\n * molsurf = new MolecularSurface(structure)\n * surf = molsurf.getSurface({type: 'av', probeRadius: 1.4})\n * stl = new StlWriter(surf)\n * stl.download('myFileName')\n */\nexport default class StlWriter extends Writer {\n readonly mimeType = 'application/vnd.ms-pki.stl'\n readonly defaultName = 'surface'\n readonly defaultExt = 'stl'\n\n surface: any // TODO\n\n /**\n * @param {Surface} surface - the surface to write out\n */\n constructor (surface: Surface) {\n super()\n\n this.surface = surface\n }\n\n /*\n * Get STL Binary data\n *\n * Adapted from: https://github.com/mrdoob/three.js/blob/master/examples/js/exporters/STLBinaryExporter.js\n * see https://en.wikipedia.org/wiki/STL_(file_format)#Binary_STL for the file format description\n *\n * @return {DataView} the data\n */\n getData () {\n const triangles = this.surface.index.length / 3\n const bufferLength = triangles * 2 + triangles * 3 * 4 * 4 + 80 + 4\n const output = new IOBuffer(bufferLength)\n\n output.skip(80) // skip header\n output.writeUint32(triangles)\n\n const vector = new Vector3()\n const vectorNorm1 = new Vector3()\n const vectorNorm2 = new Vector3()\n const vectorNorm3 = new Vector3()\n\n // traversing vertices\n for (let i = 0; i < triangles; i++) {\n const indices = [\n this.surface.index[i * 3],\n this.surface.index[i * 3 + 1],\n this.surface.index[i * 3 + 2]\n ]\n\n vectorNorm1.fromArray(this.surface.normal, indices[0] * 3)\n vectorNorm2.fromArray(this.surface.normal, indices[1] * 3)\n vectorNorm3.fromArray(this.surface.normal, indices[2] * 3)\n\n vector.addVectors(vectorNorm1, vectorNorm2).add(vectorNorm3).normalize()\n\n output.writeFloat32(vector.x)\n output.writeFloat32(vector.y)\n output.writeFloat32(vector.z)\n\n for (let j = 0; j < 3; j++) {\n vector.fromArray(this.surface.position, indices[j] * 3)\n\n output.writeFloat32(vector.x) // vertices\n output.writeFloat32(vector.y)\n output.writeFloat32(vector.z)\n }\n\n output.writeUint16(0) // attribute byte count\n }\n\n return new DataView(output.buffer)\n }\n}","/**\n * @file Counter\n * @author Alexander Rose \n * @private\n */\n\nimport { Log } from '../globals'\n\nimport * as signalsWrapper from 'signals'\n\n/**\n * {@link Signal}, dispatched when the `count` changes\n * @example\n * counter.signals.countChanged.add( function( delta ){ ... } );\n * @event Counter#countChanged\n * @type {Integer}\n */\n\nexport interface CounterSignals {\n countChanged: signalsWrapper.Signal\n}\n\n/**\n * Counter class for keeping track of counts\n */\nclass Counter {\n count = 0\n\n signals: CounterSignals = {\n countChanged: new signalsWrapper.Signal()\n }\n\n /**\n * Set the `count` to zero\n * @return {undefined}\n */\n clear () {\n this.change(-this.count)\n }\n\n /**\n * Change the `count`\n * @fires Counter#countChanged\n * @param {Integer} delta - count change\n * @return {undefined}\n */\n change (delta: number) {\n this.count += delta\n this.signals.countChanged.dispatch(delta, this.count)\n\n if (this.count < 0) {\n Log.warn('Counter.count below zero', this.count)\n }\n }\n\n /**\n * Increments the `count` by one.\n * @return {undefined}\n */\n increment () {\n this.change(1)\n }\n\n /**\n * Decrements the `count` by one.\n * @return {undefined}\n */\n decrement () {\n this.change(-1)\n }\n\n /**\n * Listen to another counter object and change this `count` by the\n * same amount\n * @param {Counter} counter - the counter object to listen to\n * @return {undefined}\n */\n listen (counter: Counter) {\n this.change(counter.count)\n counter.signals.countChanged.add(this.change, this)\n }\n\n /**\n * Stop listening to the other counter object\n * @param {Counter} counter - the counter object to stop listening to\n * @return {undefined}\n */\n unlisten (counter: Counter) {\n const countChanged = counter.signals.countChanged\n if (countChanged.has(this.change, this)) {\n countChanged.remove(this.change, this)\n }\n }\n\n /**\n * Invole the callback function once, when the `count` becomes zero\n * @param {Function} callback - the callback function\n * @param {Object} context - the context for the callback function\n * @return {undefined}\n */\n onZeroOnce (callback: () => void, context?: any) {\n if (this.count === 0) {\n callback.call(context)\n } else {\n const fn = () => {\n if (this.count === 0) {\n this.signals.countChanged.remove(fn, this)\n callback.call(context)\n }\n }\n this.signals.countChanged.add(fn, this)\n }\n }\n\n dispose () {\n this.clear()\n this.signals.countChanged.dispose()\n }\n}\n\nexport default Counter\n","/**\n * @file Stats\n * @author Alexander Rose \n * @private\n */\n\nimport * as signalsWrapper from 'signals'\n\nexport default class Stats {\n signals = {\n updated: new signalsWrapper.Signal()\n }\n\n maxDuration = -Infinity\n minDuration = Infinity\n avgDuration = 14\n lastDuration = Infinity\n\n prevFpsTime = 0\n lastFps = Infinity\n lastFrames = 1\n frames = 0\n count = 0\n\n startTime: number\n currentTime: number\n\n constructor () {\n this.begin()\n }\n\n update () {\n this.startTime = this.end()\n this.currentTime = this.startTime\n this.signals.updated.dispatch()\n }\n\n begin () {\n this.startTime = window.performance.now()\n this.lastFrames = this.frames\n }\n\n end () {\n const time = window.performance.now()\n\n this.count += 1\n this.frames += 1\n\n this.lastDuration = time - this.startTime\n this.minDuration = Math.min(this.minDuration, this.lastDuration)\n this.maxDuration = Math.max(this.maxDuration, this.lastDuration)\n this.avgDuration -= this.avgDuration / 30\n this.avgDuration += this.lastDuration / 30\n\n if (time > this.prevFpsTime + 1000) {\n this.lastFps = this.frames\n this.prevFpsTime = time\n this.frames = 0\n }\n\n return time\n }\n}","/**\n * @file Shader Utils\n * @author Alexander Rose \n * @private\n */\n\nimport { ShaderChunk } from 'three'\n\nimport './chunk/fog_fragment.glsl'\nimport './chunk/interior_fragment.glsl'\nimport './chunk/matrix_scale.glsl'\nimport './chunk/nearclip_vertex.glsl'\nimport './chunk/nearclip_fragment.glsl'\nimport './chunk/opaque_back_fragment.glsl'\nimport './chunk/radiusclip_vertex.glsl'\nimport './chunk/radiusclip_fragment.glsl'\nimport './chunk/unpack_color.glsl'\n\nimport { ShaderRegistry } from '../globals'\n\nexport type ShaderDefine = (\n 'NEAR_CLIP'|'RADIUS_CLIP'|'PICKING'|'NOLIGHT'|'FLAT_SHADED'|'OPAQUE_BACK'|\n 'DIFFUSE_INTERIOR'|'USE_INTERIOR_COLOR'|\n 'USE_SIZEATTENUATION'|'USE_MAP'|'USE_ALPHATEST'|'SDF'|'FIXED_SIZE'|\n 'CUBIC_INTERPOLATION'|'BSPLINE_FILTER'|'CATMULROM_FILTER'|'MITCHELL_FILTER'\n)\nexport type ShaderDefines = {\n [k in ShaderDefine]?: number|string\n}\n\nfunction getDefines (defines: ShaderDefines) {\n if (defines === undefined) return ''\n\n const lines = []\n\n for (const name in defines) {\n const value = defines[ name as keyof ShaderDefines ]\n\n if (!value) continue\n\n lines.push(`#define ${name} ${value}`)\n }\n\n return lines.join('\\n') + '\\n'\n}\n\nconst reInclude = /^(?!\\/\\/)\\s*#include\\s+(\\S+)/gmi\nconst shaderCache: { [k: string]: string } = {}\n\nexport function getShader (name: string, defines: ShaderDefines = {}) {\n let hash = name + '|'\n for (const key in defines) {\n hash += key + ':' + defines[ key as keyof ShaderDefines ]\n }\n\n if (!shaderCache[ hash ]) {\n const definesText = getDefines(defines)\n\n let shaderText = ShaderRegistry.get(`shader/${name}`) as string\n if (!shaderText) {\n throw new Error(`empty shader, '${name}'`)\n }\n shaderText = shaderText.replace(reInclude, function (match, p1: keyof typeof ShaderChunk) {\n const path = `shader/chunk/${p1}.glsl`\n const chunk = ShaderRegistry.get(path) || ShaderChunk[ p1 ]\n if (!chunk) {\n throw new Error(`empty chunk, '${p1}'`)\n }\n return chunk\n })\n\n shaderCache[ hash ] = definesText + shaderText\n }\n\n return shaderCache[ hash ]\n}\n","/**\n * @file Viewer Constants\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug } from '../globals'\n\nif (typeof WebGLRenderingContext !== 'undefined') {\n const wrcp = WebGLRenderingContext.prototype\n\n // wrap WebGL debug function used by three.js and\n // ignore calls to them when the debug flag is not set\n\n const _getShaderParameter = wrcp.getShaderParameter\n wrcp.getShaderParameter = function getShaderParameter (this: WebGLRenderingContext) {\n if (Debug) {\n return _getShaderParameter.apply(this, arguments)\n } else {\n return true\n }\n }\n\n const _getShaderInfoLog = wrcp.getShaderInfoLog\n wrcp.getShaderInfoLog = function getShaderInfoLog (this: WebGLRenderingContext) {\n if (Debug) {\n return _getShaderInfoLog.apply(this, arguments)\n } else {\n return ''\n }\n }\n\n const _getProgramParameter = wrcp.getProgramParameter\n wrcp.getProgramParameter = function getProgramParameter (this: WebGLRenderingContext, program, pname) {\n if (Debug || pname !== wrcp.LINK_STATUS) {\n return _getProgramParameter.apply(this, arguments)\n } else {\n return true\n }\n }\n\n const _getProgramInfoLog = wrcp.getProgramInfoLog\n wrcp.getProgramInfoLog = function getProgramInfoLog (this: WebGLRenderingContext) {\n if (Debug) {\n return _getProgramInfoLog.apply(this, arguments)\n } else {\n return ''\n }\n }\n}\n\nexport const JitterVectors = [\n [\n [ 0, 0 ]\n ],\n [\n [ 4, 4 ], [ -4, -4 ]\n ],\n [\n [ -2, -6 ], [ 6, -2 ], [ -6, 2 ], [ 2, 6 ]\n ],\n [\n [ 1, -3 ], [ -1, 3 ], [ 5, 1 ], [ -3, -5 ],\n [ -5, 5 ], [ -7, -1 ], [ 3, 7 ], [ 7, -7 ]\n ],\n [\n [ 1, 1 ], [ -1, -3 ], [ -3, 2 ], [ 4, -1 ],\n [ -5, -2 ], [ 2, 5 ], [ 5, 3 ], [ 3, -5 ],\n [ -2, 6 ], [ 0, -7 ], [ -4, -6 ], [ -6, 4 ],\n [ -8, 0 ], [ 7, -4 ], [ 6, 7 ], [ -7, -8 ]\n ],\n [\n [ -4, -7 ], [ -7, -5 ], [ -3, -5 ], [ -5, -4 ],\n [ -1, -4 ], [ -2, -2 ], [ -6, -1 ], [ -4, 0 ],\n [ -7, 1 ], [ -1, 2 ], [ -6, 3 ], [ -3, 3 ],\n [ -7, 6 ], [ -3, 6 ], [ -5, 7 ], [ -1, 7 ],\n [ 5, -7 ], [ 1, -6 ], [ 6, -5 ], [ 4, -4 ],\n [ 2, -3 ], [ 7, -2 ], [ 1, -1 ], [ 4, -1 ],\n [ 2, 1 ], [ 6, 2 ], [ 0, 4 ], [ 4, 4 ],\n [ 2, 5 ], [ 7, 5 ], [ 5, 6 ], [ 3, 7 ]\n ]\n]\n\nJitterVectors.forEach(offsetList => {\n offsetList.forEach(offset => {\n // 0.0625 = 1 / 16\n offset[ 0 ] *= 0.0625\n offset[ 1 ] *= 0.0625\n })\n})\n","/**\n * @file Tiled Renderer\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport { Camera, WebGLRenderer } from 'three'\nimport Viewer from './viewer'\n\nexport interface TiledRendererParams {\n factor?: number\n antialias?: boolean\n onProgress?: Function\n onFinish?: Function\n}\n\nclass TiledRenderer {\n canvas = document.createElement('canvas')\n\n private _width: number\n private _height: number\n private _n: number\n private _factor: number\n private _antialias: boolean\n private _viewerSampleLevel: number\n\n private _viewer: Viewer\n private _onProgress?: Function\n private _onFinish?: Function\n private _ctx: CanvasRenderingContext2D\n\n constructor(renderer: WebGLRenderer, camera: Camera, viewer: Viewer, params: TiledRendererParams) {\n this._viewer = viewer\n\n this._factor = defaults(params.factor, 2)\n this._antialias = defaults(params.antialias, false)\n\n this._onProgress = params.onProgress\n this._onFinish = params.onFinish\n\n if (this._antialias) this._factor *= 2\n this._n = this._factor * this._factor\n\n // canvas\n\n this._width = this._viewer.width\n this._height = this._viewer.height\n\n if (this._antialias) {\n this.canvas.width = this._width * this._factor / 2\n this.canvas.height = this._height * this._factor / 2\n } else {\n this.canvas.width = this._width * this._factor\n this.canvas.height = this._height * this._factor\n }\n\n this._ctx = this.canvas.getContext('2d')!\n\n this._viewerSampleLevel = viewer.sampleLevel\n this._viewer.setSampling(-1)\n }\n\n private _renderTile (i: number) {\n const viewer = this._viewer\n const width = this._width\n const height = this._height\n const factor = this._factor\n\n const x = i % factor\n const y = Math.floor(i / factor)\n\n const offsetX = x * width\n const offsetY = y * height\n\n viewer.camera.setViewOffset(\n width * factor,\n height * factor,\n offsetX,\n offsetY,\n width,\n height\n )\n\n viewer.render()\n\n if (this._antialias) {\n const w = Math.round((offsetX + width) / 2) - Math.round (offsetX / 2);\n const h = Math.round((offsetY + height) / 2) - Math.round (offsetY / 2);\n this._ctx.drawImage(\n viewer.renderer.domElement,\n Math.round(offsetX / 2),\n Math.round(offsetY / 2),\n w,\n h\n )\n } else {\n this._ctx.drawImage(\n viewer.renderer.domElement,\n Math.floor(offsetX),\n Math.floor(offsetY),\n Math.ceil(width),\n Math.ceil(height)\n )\n }\n\n if (typeof this._onProgress === 'function') {\n this._onProgress(i + 1, this._n, false)\n }\n }\n\n private _finalize () {\n this._viewer.setSampling(this._viewerSampleLevel)\n this._viewer.camera.view = null! // TODO\n\n if (typeof this._onFinish === 'function') {\n this._onFinish(this._n + 1, this._n, false)\n }\n }\n\n render () {\n for (let i = 0; i <= this._n; ++i) {\n if (i === this._n) {\n this._finalize()\n } else {\n this._renderTile(i)\n }\n }\n }\n\n renderAsync () {\n let count = 0\n const n = this._n\n\n const fn = () => {\n if (count === n) {\n this._finalize()\n } else {\n this._renderTile(count)\n }\n count += 1\n }\n\n for (let i = 0; i <= n; ++i) {\n setTimeout(fn, 0)\n }\n }\n}\n\nexport default TiledRenderer\n","/**\n * @file Math Constants\n * @author Alexander Rose \n * @private\n */\n\nexport const EPS = 0.0000001\nexport const TwoPI = 2 * Math.PI\n\nexport const DEG2RAD = Math.PI / 180\nexport const RAD2DEG = 180 / Math.PI\n","/**\n * @file Array Utils\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { NumberArray } from '../types'\nimport { TwoPI } from './math-constants'\n\nexport function circularMean (array: NumberArray, max: number, stride = 1, offset = 0, indices?: NumberArray) {\n // http://en.wikipedia.org/wiki/Center_of_mass#Systems_with_periodic_boundary_conditions\n\n // Bai, Linge; Breen, David (2008). Calculating Center of Mass in an Unbounded 2D Environment. Journal of Graphics, GPU, and Game Tools 13 (4): 53–60.\n\n // http://stackoverflow.com/questions/18166507/using-fft-to-find-the-center-of-mass-under-periodic-boundary-conditions\n\n const n = indices ? indices.length : array.length / stride\n\n let cosMean = 0\n let sinMean = 0\n\n if (indices) {\n for (let i = 0; i < n; ++i) {\n const c = (array[ indices[ i ] * stride + offset ] + max) % max\n const angle = (c / max) * TwoPI - Math.PI\n\n cosMean += Math.cos(angle)\n sinMean += Math.sin(angle)\n }\n } else {\n for (let i = offset; i < n; i += stride) {\n const c = (array[ i ] + max) % max\n const angle = (c / max) * TwoPI - Math.PI\n\n cosMean += Math.cos(angle)\n sinMean += Math.sin(angle)\n }\n }\n\n cosMean /= n\n sinMean /= n\n\n const meanAngle = Math.atan2(sinMean, cosMean)\n const mean = (meanAngle + Math.PI) / TwoPI * max\n\n return mean\n}\n\nexport function calculateCenterArray (array1: NumberArray, array2: NumberArray, center?: T, offset = 0): T {\n const n = array1.length\n const c = center || new Float32Array(n)\n\n for (let i = 0; i < n; i += 3) {\n c[ offset + i + 0 ] = (array1[ i + 0 ] + array2[ i + 0 ]) / 2.0\n c[ offset + i + 1 ] = (array1[ i + 1 ] + array2[ i + 1 ]) / 2.0\n c[ offset + i + 2 ] = (array1[ i + 2 ] + array2[ i + 2 ]) / 2.0\n }\n\n return c as T\n}\n\nexport function calculateDirectionArray (array1: NumberArray, array2: NumberArray) {\n const n = array1.length\n const direction = new Float32Array(n)\n\n for (let i = 0; i < n; i += 3) {\n direction[ i + 0 ] = array2[ i + 0 ] - array1[ i + 0 ]\n direction[ i + 1 ] = array2[ i + 1 ] - array1[ i + 1 ]\n direction[ i + 2 ] = array2[ i + 2 ] - array1[ i + 2 ]\n }\n\n return direction\n}\n\nexport function uniformArray (n: number, a: number, optionalTarget?: T): T {\n const array = optionalTarget || new Float32Array(n)\n\n for (let i = 0; i < n; ++i) {\n array[ i ] = a\n }\n\n return array as T\n}\n\nexport function uniformArray3 (n: number, a: number, b: number, c: number, optionalTarget?: NumberArray) {\n const array = optionalTarget || new Float32Array(n * 3)\n\n for (let i = 0; i < n; ++i) {\n const j = i * 3\n\n array[ j + 0 ] = a\n array[ j + 1 ] = b\n array[ j + 2 ] = c\n }\n\n return array\n}\n\nexport function centerArray3 (array: NumberArray, center = new Vector3()) {\n const n = array.length\n\n for (let i = 0; i < n; i += 3) {\n center.x += array[ i ]\n center.y += array[ i + 1 ]\n center.z += array[ i + 2 ]\n }\n\n center.divideScalar(n / 3)\n\n return center\n}\n\nexport function serialArray (n: number) {\n const array = new Float32Array(n)\n\n for (let i = 0; i < n; ++i) {\n array[ i ] = i\n }\n\n return array\n}\n\nexport function serialBlockArray (n: number, b: number, offset = 0, optionalTarget?: NumberArray) {\n const array = optionalTarget || new Float32Array(n * b)\n\n for (let i = 0; i < n; ++i) {\n const k = offset + i * b\n\n for (let j = 0; j < b; ++j) {\n array[ k + j ] = i\n }\n }\n\n return array\n}\n\nexport function randomColorArray (n: number) {\n const array = new Float32Array(n * 3)\n\n for (let i = 0; i < n; ++i) {\n const j = i * 3\n\n array[ j + 0 ] = Math.random()\n array[ j + 1 ] = Math.random()\n array[ j + 2 ] = Math.random()\n }\n\n return array\n}\n\nexport function replicateArrayEntries (array: NumberArray, m: number) {\n const n = array.length\n const repArr = new Float32Array(n * m)\n\n for (let i = 0; i < n; ++i) {\n const k = i * m\n const a = array[ i ]\n\n for (let j = 0; j < m; ++j) {\n repArr[ k + j ] = a\n }\n }\n\n return repArr\n}\n\nexport function replicateArray3Entries (array: NumberArray, m: number) {\n const n = array.length / 3\n const repArr = new Float32Array(n * m * 3)\n\n for (let i = 0; i < n; ++i) {\n const v = i * 3\n const k = i * m * 3\n\n const a = array[ v + 0 ]\n const b = array[ v + 1 ]\n const c = array[ v + 2 ]\n\n for (let j = 0; j < m; ++j) {\n const l = k + j * 3\n\n repArr[ l + 0 ] = a\n repArr[ l + 1 ] = b\n repArr[ l + 2 ] = c\n }\n }\n\n return repArr\n}\n\nexport function calculateMeanArray (array1: NumberArray, array2: NumberArray) {\n const n = array1.length\n const mean = new Float32Array(n)\n\n for (let i = 0; i < n; i++) {\n mean[ i ] = (array1[ i ] + array2[ i ]) / 2.0\n }\n\n return mean\n}\n\nexport function calculateMinArray (array1: NumberArray, array2: NumberArray) {\n const n = array1.length\n const min = new Float32Array(n)\n\n for (let i = 0; i < n; i++) {\n min[ i ] = Math.min(array1[ i ], array2[ i ])\n }\n\n return min\n}\n\nexport function copyArray (src: T, dst: T, srcOffset: number, dstOffset: number, length: number) {\n for (let i = 0; i < length; ++i) {\n dst[ dstOffset + i ] = src[ srcOffset + i ]\n }\n}\n\nexport function copyWithin (array: NumberArray|any[], srcOffset: number, dstOffset: number, length: number) {\n copyArray(array, array, srcOffset, dstOffset, length)\n}\n\nconst swap = new Float32Array(4)\nconst temp = new Float32Array(4)\n/**\n * quicksortIP\n * @function\n * @author Roman Bolzern , 2013\n * @author I4DS http://www.fhnw.ch/i4ds, 2013\n * @license MIT License \n * @description\n * In-place quicksort for typed arrays (e.g. for Float32Array)\n * provides fast sorting\n * useful e.g. for a custom shader and/or BufferGeometry\n * Complexity: http://bigocheatsheet.com/ see Quicksort\n *\n * @example\n * points: [x, y, z, x, y, z, x, y, z, ...]\n * eleSize: 3 //because of (x, y, z)\n * orderElement: 0 //order according to x\n *\n * @param {TypedArray} arr - array to be sorted\n * @param {Integer} eleSize - element size\n * @param {Integer} orderElement - index of element used for sorting, < eleSize\n * @param {Integer} [begin] - start index for range to be sorted\n * @param {Integer} [end] - end index for range to be sorted\n * @return {TypedArray} the input array\n */\nexport function quicksortIP (arr: NumberArray, eleSize: number, orderElement: number, begin = 0, end?: number) {\n end = (end || (arr.length / eleSize)) - 1\n\n const stack = []\n let sp = -1\n let left = begin\n let right = end\n let tmp = 0.0\n let x = 0\n let y = 0\n\n const swapF = function (a: number, b: number) {\n a *= eleSize; b *= eleSize\n for (y = 0; y < eleSize; y++) {\n tmp = arr[ a + y ]\n arr[ a + y ] = arr[ b + y ]\n arr[ b + y ] = tmp\n }\n }\n\n let i, j\n\n while (true) {\n if (right - left <= 25) {\n for (j = left + 1; j <= right; j++) {\n for (x = 0; x < eleSize; x++) {\n swap[ x ] = arr[ j * eleSize + x ]\n }\n\n i = j - 1\n\n while (i >= left && arr[ i * eleSize + orderElement ] > swap[ orderElement ]) {\n for (x = 0; x < eleSize; x++) {\n arr[ (i + 1) * eleSize + x ] = arr[ i * eleSize + x ]\n }\n i--\n }\n\n for (x = 0; x < eleSize; x++) {\n arr[ (i + 1) * eleSize + x ] = swap[ x ]\n }\n }\n\n if (sp === -1) break\n\n right = stack[ sp-- ] // ?\n left = stack[ sp-- ]\n } else {\n const median = (left + right) >> 1\n\n i = left + 1\n j = right\n\n swapF(median, i)\n\n if (arr[ left * eleSize + orderElement ] > arr[ right * eleSize + orderElement ]) {\n swapF(left, right)\n }\n\n if (arr[ i * eleSize + orderElement ] > arr[ right * eleSize + orderElement ]) {\n swapF(i, right)\n }\n\n if (arr[ left * eleSize + orderElement ] > arr[ i * eleSize + orderElement ]) {\n swapF(left, i)\n }\n\n for (x = 0; x < eleSize; x++) {\n temp[ x ] = arr[ i * eleSize + x ]\n }\n\n while (true) {\n do i++; while (arr[ i * eleSize + orderElement ] < temp[ orderElement ])\n do j--; while (arr[ j * eleSize + orderElement ] > temp[ orderElement ])\n if (j < i) break\n swapF(i, j)\n }\n\n for (x = 0; x < eleSize; x++) {\n arr[ (left + 1) * eleSize + x ] = arr[ j * eleSize + x ]\n arr[ j * eleSize + x ] = temp[ x ]\n }\n\n if (right - i + 1 >= j - left) {\n stack[ ++sp ] = i\n stack[ ++sp ] = right\n right = j - 1\n } else {\n stack[ ++sp ] = left\n stack[ ++sp ] = j - 1\n left = i\n }\n }\n }\n\n return arr\n}\n\nexport function quicksortCmp (arr: NumberArray|T[], cmp?: (a: number|T, b: number|T) => number, begin = 0, end?: number) {\n cmp = cmp || function cmp (a, b) {\n if (a > b) return 1\n if (a < b) return -1\n return 0\n }\n end = (end || arr.length) - 1\n\n const stack = []\n let sp = -1\n let left = begin\n let right = end\n let tmp: number|T\n\n function swap (a: number, b: number) {\n const tmp2 = arr[ a ]\n arr[ a ] = arr[ b ]\n arr[ b ] = tmp2\n }\n\n let i, j\n\n while (true) {\n if (right - left <= 25) {\n for (let k = left + 1; k <= right; ++k) {\n tmp = arr[ k ]\n i = k - 1\n\n while (i >= left && cmp(arr[ i ], tmp) > 0) {\n arr[ i + 1 ] = arr[ i ]\n --i\n }\n\n arr[ i + 1 ] = tmp\n }\n\n if (sp === -1) break\n\n right = stack[ sp-- ] // ?\n left = stack[ sp-- ]\n } else {\n const median = (left + right) >> 1\n\n i = left + 1\n j = right\n\n swap(median, i)\n\n if (cmp(arr[ left ], arr[ right ]) > 0) {\n swap(left, right)\n }\n\n if (cmp(arr[ i ], arr[ right ]) > 0) {\n swap(i, right)\n }\n\n if (cmp(arr[ left ], arr[ i ]) > 0) {\n swap(left, i)\n }\n\n tmp = arr[ i ]\n\n while (true) {\n do i++; while (cmp(arr[ i ], tmp) < 0)\n do j--; while (cmp(arr[ j ], tmp) > 0)\n if (j < i) break\n swap(i, j)\n }\n\n arr[ left + 1 ] = arr[ j ]\n arr[ j ] = tmp\n\n if (right - i + 1 >= j - left) {\n stack[ ++sp ] = i\n stack[ ++sp ] = right\n right = j - 1\n } else {\n stack[ ++sp ] = left\n stack[ ++sp ] = j - 1\n left = i\n }\n }\n }\n\n return arr\n}\n\nexport function quickselectCmp (arr: NumberArray|T[], n: number, cmp?: (a: number|T, b: number|T) => number, left = 0, right?: number) {\n cmp = cmp || function cmp (a, b) {\n if (a > b) return 1\n if (a < b) return -1\n return 0\n }\n right = (right || arr.length) - 1\n\n let pivotIndex, pivotValue, storeIndex\n\n function swap (a: number, b: number) {\n const tmp = arr[ a ]\n arr[ a ] = arr[ b ]\n arr[ b ] = tmp\n }\n\n while (true) {\n if (left === right) {\n return arr[ left ]\n }\n pivotIndex = (left + right) >> 1\n pivotValue = arr[ pivotIndex ]\n swap(pivotIndex, right)\n storeIndex = left\n for (let i = left; i < right; ++i) {\n if (cmp(arr[ i ], pivotValue) < 0) {\n swap(storeIndex, i)\n ++storeIndex\n }\n }\n swap(right, storeIndex)\n pivotIndex = storeIndex\n if (n === pivotIndex) {\n return arr[ n ]\n } else if (n < pivotIndex) {\n right = pivotIndex - 1\n } else {\n left = pivotIndex + 1\n }\n }\n}\n\nexport function arrayMax (array: NumberArray) {\n let max = -Infinity\n for (let i = 0, il = array.length; i < il; ++i) {\n if (array[ i ] > max) max = array[ i ]\n }\n return max\n}\n\nexport function arrayMin (array: NumberArray) {\n let min = Infinity\n for (let i = 0, il = array.length; i < il; ++i) {\n if (array[ i ] < min) min = array[ i ]\n }\n return min\n}\n\nexport function arraySum (array: NumberArray, stride = 1, offset = 0) {\n const n = array.length\n let sum = 0\n for (let i = offset; i < n; i += stride) {\n sum += array[ i ]\n }\n return sum\n}\n\nexport function arrayMean (array: NumberArray, stride = 1, offset = 0) {\n return arraySum(array, stride, offset) / (array.length / stride)\n}\n\nexport function arrayRms (array: NumberArray) {\n const n = array.length\n let sumSq = 0\n for (let i = 0; i < n; ++i) {\n const di = array[ i ]\n sumSq += di * di\n }\n return Math.sqrt(sumSq / n)\n}\n\nexport function arraySorted (array: NumberArray) {\n for (let i = 1, il = array.length; i < il; ++i) {\n if (array[ i - 1 ] > array[ i ]) return false\n }\n return true\n}\n\nexport function arraySortedCmp (array: NumberArray|T[], cmp: (a: number|T, b: number|T) => number) {\n for (let i = 1, il = array.length; i < il; ++i) {\n if (cmp(array[ i - 1 ], array[ i ]) > 0) return false\n }\n return true\n}\n","/**\n * @file Viewer Utils\n * @author Alexander Rose \n * @private\n */\n\nimport {\n Vector2, Vector3, Matrix4, Points, Scene, Camera,\n Object3D, WebGLRenderer, Color\n} from 'three'\n\nimport { createParams } from '../utils'\nimport TiledRenderer from './tiled-renderer'\nimport { quicksortCmp } from '../math/array-utils'\nimport Viewer from './viewer'\n\nfunction _trimCanvas (canvas: HTMLCanvasElement, r: number, g: number, b: number, a: number) {\n const canvasHeight = canvas.height\n const canvasWidth = canvas.width\n\n const ctx = canvas.getContext('2d')!\n const pixels = ctx.getImageData(0, 0, canvasWidth, canvasHeight).data\n\n let x, y, doBreak, off\n\n doBreak = false\n for (y = 0; y < canvasHeight; y++) {\n for (x = 0; x < canvasWidth; x++) {\n off = (y * canvasWidth + x) * 4\n if (pixels[ off ] !== r || pixels[ off + 1 ] !== g ||\n pixels[ off + 2 ] !== b || pixels[ off + 3 ] !== a\n ) {\n doBreak = true\n break\n }\n }\n if (doBreak) {\n break\n }\n }\n const topY = y\n\n doBreak = false\n for (x = 0; x < canvasWidth; x++) {\n for (y = 0; y < canvasHeight; y++) {\n off = (y * canvasWidth + x) * 4\n if (pixels[ off ] !== r || pixels[ off + 1 ] !== g ||\n pixels[ off + 2 ] !== b || pixels[ off + 3 ] !== a\n ) {\n doBreak = true\n break\n }\n }\n if (doBreak) {\n break\n }\n }\n const topX = x\n\n doBreak = false\n for (y = canvasHeight - 1; y >= 0; y--) {\n for (x = canvasWidth - 1; x >= 0; x--) {\n off = (y * canvasWidth + x) * 4\n if (pixels[ off ] !== r || pixels[ off + 1 ] !== g ||\n pixels[ off + 2 ] !== b || pixels[ off + 3 ] !== a\n ) {\n doBreak = true\n break\n }\n }\n if (doBreak) {\n break\n }\n }\n const bottomY = y\n\n doBreak = false\n for (x = canvasWidth - 1; x >= 0; x--) {\n for (y = canvasHeight - 1; y >= 0; y--) {\n off = (y * canvasWidth + x) * 4\n if (pixels[ off ] !== r || pixels[ off + 1 ] !== g ||\n pixels[ off + 2 ] !== b || pixels[ off + 3 ] !== a\n ) {\n doBreak = true\n break\n }\n }\n if (doBreak) {\n break\n }\n }\n const bottomX = x\n\n const trimedCanvas = document.createElement('canvas')\n trimedCanvas.width = bottomX - topX\n trimedCanvas.height = bottomY - topY\n\n const trimedCtx = trimedCanvas.getContext('2d')!\n trimedCtx.drawImage(\n canvas,\n topX, topY,\n trimedCanvas.width, trimedCanvas.height,\n 0, 0,\n trimedCanvas.width, trimedCanvas.height\n )\n\n return trimedCanvas\n}\n\n/**\n * Image parameter object.\n * @typedef {Object} ImageParameters - image generation parameters\n * @property {Boolean} trim - trim the image\n * @property {Integer} factor - scaling factor to apply to the viewer canvas\n * @property {Boolean} antialias - antialias the image\n * @property {Boolean} transparent - transparent image background\n */\n\nexport const ImageDefaultParameters = {\n trim: false,\n factor: 1,\n antialias: false,\n transparent: false,\n onProgress: undefined as Function|undefined\n}\nexport type ImageParameters = typeof ImageDefaultParameters\n\n/**\n * Make image from what is shown in a viewer canvas\n * @param {Viewer} viewer - the viewer\n * @param {ImageParameters} params - parameters object\n * @return {Promise} A Promise object that resolves to an image {@link Blob}.\n */\nexport function makeImage (viewer: Viewer, params: Partial = {}) {\n const {trim, factor, antialias, transparent} = createParams(params, ImageDefaultParameters)\n\n const renderer = viewer.renderer\n const camera = viewer.camera\n\n const originalClearAlpha = renderer.getClearAlpha()\n const backgroundColor = renderer.getClearColor(new Color())\n\n function setLineWidthAndPixelSize (invert = false) {\n let _factor = factor\n if (antialias) _factor *= 2\n if (invert) _factor = 1 / _factor\n viewer.scene.traverse(function (o: any) { // TODO\n const m = o.material\n if (m && m.linewidth) {\n m.linewidth *= _factor\n }\n if (m && m.uniforms && m.uniforms.size) {\n if (m.uniforms.size.__seen === undefined) {\n m.uniforms.size.value *= _factor\n m.uniforms.size.__seen = true\n }\n }\n if (m && m.uniforms && m.uniforms.linewidth) {\n if (m.uniforms.linewidth.__seen === undefined) {\n m.uniforms.linewidth.value *= _factor\n m.uniforms.linewidth.__seen = true\n }\n }\n })\n viewer.scene.traverse(function (o: any) { // TODO\n const m = o.material\n if (m && m.uniforms && m.uniforms.size) {\n delete m.uniforms.size.__seen\n }\n if (m && m.uniforms && m.uniforms.linewidth) {\n delete m.uniforms.linewidth.__seen\n }\n })\n }\n\n function trimCanvas (canvas: HTMLCanvasElement) {\n if (trim) {\n const bg = backgroundColor\n const r = transparent ? 0 : bg.r * 255\n const g = transparent ? 0 : bg.g * 255\n const b = transparent ? 0 : bg.b * 255\n const a = transparent ? 0 : 255\n return _trimCanvas(canvas, r, g, b, a)\n } else {\n return canvas\n }\n }\n\n function onProgress (i: number, n: number, finished: boolean) {\n if (typeof params.onProgress === 'function') {\n params.onProgress(i, n, finished)\n }\n }\n\n return new Promise(function (resolve, reject) {\n const tiledRenderer = new TiledRenderer(\n renderer, camera, viewer,\n { factor, antialias, onProgress, onFinish }\n )\n\n renderer.setClearAlpha(transparent ? 0 : 1)\n setLineWidthAndPixelSize()\n tiledRenderer.renderAsync()\n\n function onFinish (i: number, n: number) {\n const canvas = trimCanvas(tiledRenderer.canvas)\n canvas.toBlob(\n function (blob) {\n renderer.setClearAlpha(originalClearAlpha)\n setLineWidthAndPixelSize(true)\n viewer.requestRender()\n onProgress(n, n, true)\n if (blob) {\n resolve(blob)\n } else {\n reject('error creating image')\n }\n },\n 'image/png'\n )\n }\n })\n}\n\nconst vertex = new Vector3()\nconst matrix = new Matrix4()\nconst modelViewProjectionMatrix = new Matrix4()\n\nexport function sortProjectedPosition (scene: Scene, camera: Camera) {\n // console.time( \"sort\" );\n\n scene.traverseVisible(function (o) {\n if (!(o instanceof Points) || !o.userData.buffer.parameters.sortParticles) {\n return\n }\n\n const attributes = (o.geometry as any).attributes // TODO\n const n = attributes.position.count\n\n if (n === 0) return\n\n matrix.multiplyMatrices(\n camera.matrixWorldInverse, o.matrixWorld\n )\n modelViewProjectionMatrix.multiplyMatrices(\n camera.projectionMatrix, matrix\n )\n\n let sortData, sortArray, zArray: Float32Array, cmpFn\n\n if (!o.userData.sortData) {\n zArray = new Float32Array(n)\n sortArray = new Uint32Array(n)\n cmpFn = function (ai: number, bi: number) {\n const a = zArray[ ai ]\n const b = zArray[ bi ]\n if (a > b) return 1\n if (a < b) return -1\n return 0\n }\n\n sortData = {\n __zArray: zArray,\n __sortArray: sortArray,\n __cmpFn: cmpFn\n }\n\n o.userData.sortData = sortData\n } else {\n sortData = o.userData.sortData\n zArray = sortData.__zArray\n sortArray = sortData.__sortArray\n cmpFn = sortData.__cmpFn\n }\n\n for (let i = 0; i < n; ++i) {\n vertex.fromArray(attributes.position.array, i * 3)\n vertex.applyMatrix4(modelViewProjectionMatrix)\n\n // negate, so that sorting order is reversed\n zArray[ i ] = -vertex.z\n sortArray[ i ] = i\n }\n\n quicksortCmp(sortArray, cmpFn)\n\n let index, indexSrc, indexDst, tmpTab\n\n for (let name in attributes) {\n const attr = attributes[ name ]\n const array = attr.array\n const itemSize = attr.itemSize\n\n if (!sortData[ name ]) {\n sortData[ name ] = new Float32Array(itemSize * n)\n }\n\n tmpTab = sortData[ name ]\n sortData[ name ] = array\n\n for (let i = 0; i < n; ++i) {\n index = sortArray[ i ]\n\n for (let j = 0; j < itemSize; ++j) {\n indexSrc = index * itemSize + j\n indexDst = i * itemSize + j\n tmpTab[ indexDst ] = array[ indexSrc ]\n }\n }\n\n attributes[ name ].array = tmpTab\n attributes[ name ].needsUpdate = true\n }\n })\n\n // console.timeEnd( \"sort\" );\n}\n\nconst resolution = new Vector2()\nconst projectionMatrixInverse = new Matrix4()\nconst projectionMatrixTranspose = new Matrix4()\n\nexport function updateMaterialUniforms (group: Object3D, camera: Camera, renderer: WebGLRenderer, cDist: number, bRadius: number) {\n let size = new Vector2()\n renderer.getSize(size)\n const canvasHeight = size.height\n const pixelRatio = renderer.getPixelRatio()\n const ortho = camera.type === 'OrthographicCamera'\n\n resolution.set(size.width, size.height)\n projectionMatrixInverse.copy(camera.projectionMatrix).invert()\n projectionMatrixTranspose.copy(camera.projectionMatrix).transpose()\n\n group.traverse(function (o: any) {\n const m = o.material\n if (!m) return\n\n const u = m.uniforms\n if (!u) return\n\n if (m.clipNear) {\n const nearFactor = (50 - m.clipNear) / 50\n const nearClip = cDist - (bRadius * nearFactor)\n u.clipNear.value = nearClip\n }\n\n if (u.canvasHeight) {\n u.canvasHeight.value = canvasHeight\n }\n\n if (u.resolution) {\n u.resolution.value.copy(resolution)\n }\n\n if (u.pixelRatio) {\n u.pixelRatio.value = pixelRatio\n }\n\n if (u.projectionMatrixInverse) {\n u.projectionMatrixInverse.value.copy(projectionMatrixInverse)\n }\n\n if (u.projectionMatrixTranspose) {\n u.projectionMatrixTranspose.value.copy(projectionMatrixTranspose)\n }\n\n if (u.ortho) {\n u.ortho.value = ortho\n }\n })\n}\n\nexport function updateCameraUniforms (group: Object3D, camera: Camera) {\n projectionMatrixInverse.copy(camera.projectionMatrix).invert()\n projectionMatrixTranspose.copy(camera.projectionMatrix).transpose()\n\n group.traverse(function (o: any) {\n const m = o.material\n if (!m) return\n\n const u = m.uniforms\n if (!u) return\n\n if (u.projectionMatrixInverse) {\n u.projectionMatrixInverse.value.copy(projectionMatrixInverse)\n }\n\n if (u.projectionMatrixTranspose) {\n u.projectionMatrixTranspose.value.copy(projectionMatrixTranspose)\n }\n })\n}\n","/**\n * @file Viewer\n * @author Alexander Rose \n * @private\n */\n\n// adapted from https://webglfundamentals.org/webgl/resources/webgl-utils.js\n// Copyright 2012, Gregg Tavares. Modified BSD License\n\nexport function createProgram(gl: WebGLRenderingContext, shaders: WebGLShader[], attribs?: string[], locations?: number[]) {\n const program = gl.createProgram()\n if (!program) {\n console.log(`error creating WebGL program`)\n return\n }\n shaders.forEach(shader => gl.attachShader(program, shader))\n if (attribs) {\n attribs.forEach((attrib, i) => {\n gl.bindAttribLocation(program, locations ? locations[i] : i, attrib)\n })\n }\n gl.linkProgram(program);\n\n // Check the link status\n const linked = gl.getProgramParameter(program, gl.LINK_STATUS)\n if (!linked) {\n console.log(`error linking program: ${gl.getProgramInfoLog(program)}`)\n gl.deleteProgram(program)\n return null\n }\n return program\n}\n\nexport function loadShader(gl: WebGLRenderingContext, shaderSource: string, shaderType: number) {\n const shader = gl.createShader(shaderType)\n if (!shader) {\n console.log(`error creating WebGL shader ${shaderType}`)\n return // can't create shader\n }\n gl.shaderSource(shader, shaderSource)\n gl.compileShader(shader)\n\n // Check the compile status\n const compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS)\n if (!compiled) {\n console.log(`error compiling shader ${shader}: ${gl.getShaderInfoLog(shader)}`)\n gl.deleteShader(shader)\n return null\n }\n\n return shader\n}\n\n//\n\nexport function getErrorDescription(gl: WebGLRenderingContext, error: number) {\n switch (error) {\n case gl.NO_ERROR: return 'no error'\n case gl.INVALID_ENUM: return 'invalid enum'\n case gl.INVALID_VALUE: return 'invalid value'\n case gl.INVALID_OPERATION: return 'invalid operation'\n case gl.INVALID_FRAMEBUFFER_OPERATION: return 'invalid framebuffer operation'\n case gl.OUT_OF_MEMORY: return 'out of memory'\n case gl.CONTEXT_LOST_WEBGL: return 'context lost'\n }\n return 'unknown error'\n}\n\nexport function getExtension (gl: WebGLRenderingContext, name: string) {\n const ext = gl.getExtension(name)\n if (!ext) console.log(`extension '${name}' not available`)\n return ext\n}\n\nconst TextureTestVertShader = `\nattribute vec4 a_position;\n\nvoid main() {\n gl_Position = a_position;\n}`\n\nconst TextureTestFragShader = `\nprecision mediump float;\nuniform vec4 u_color;\nuniform sampler2D u_texture;\n\nvoid main() {\n gl_FragColor = texture2D(u_texture, vec2(0.5, 0.5)) * u_color;\n}`\n\nconst TextureTestTexCoords = new Float32Array([\n -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0\n])\n\nexport function testTextureSupport (type: number) {\n // adapted from\n // https://stackoverflow.com/questions/28827511/webgl-ios-render-to-floating-point-texture\n\n // Get A WebGL context\n const canvas = document.createElement('canvas')\n canvas.width = 16\n canvas.height = 16\n canvas.style.width = 16 + 'px'\n canvas.style.height = 16 + 'px'\n const gl = canvas.getContext(\"webgl\") || canvas.getContext(\"experimental-webgl\");\n if (!gl) {\n console.log(`error creating webgl context for ${type}`)\n return false\n }\n if (!(gl instanceof WebGLRenderingContext)) {\n console.log(`Got unexpected type for WebGL rendering context`)\n return false\n }\n\n getExtension(gl, 'OES_texture_float')\n getExtension(gl, 'OES_texture_half_float')\n getExtension(gl, 'WEBGL_color_buffer_float')\n\n // setup shaders\n const vertShader = loadShader(gl, TextureTestVertShader, gl.VERTEX_SHADER)\n const fragShader = loadShader(gl, TextureTestFragShader, gl.FRAGMENT_SHADER)\n if (!vertShader || !fragShader) return false\n\n // setup program\n const program = createProgram(gl, [ vertShader, fragShader ])\n if (!program) {\n console.log(`error creating WebGL program`)\n return false\n }\n gl.useProgram(program);\n\n // look up where the vertex data needs to go.\n const positionLocation = gl.getAttribLocation(program, \"a_position\");\n const colorLoc = gl.getUniformLocation(program, \"u_color\");\n if (!colorLoc) {\n console.log(`error getting 'u_color' uniform location`)\n return false\n }\n\n // provide texture coordinates for the rectangle.\n const positionBuffer = gl.createBuffer()\n gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)\n gl.bufferData(gl.ARRAY_BUFFER, TextureTestTexCoords, gl.STATIC_DRAW)\n gl.enableVertexAttribArray(positionLocation)\n gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0)\n\n const whiteTex = gl.createTexture()\n const whiteData = new Uint8Array([255, 255, 255, 255])\n gl.bindTexture(gl.TEXTURE_2D, whiteTex)\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, whiteData)\n\n const tex = gl.createTexture()\n gl.bindTexture(gl.TEXTURE_2D, tex)\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, type, null)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)\n\n const fb = gl.createFramebuffer()\n gl.bindFramebuffer(gl.FRAMEBUFFER, fb)\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0)\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER)\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n console.log(`error creating framebuffer for ${type}`)\n return false\n }\n\n // Draw the rectangle.\n gl.bindTexture(gl.TEXTURE_2D, whiteTex)\n gl.uniform4fv(colorLoc, [0, 10, 20, 1])\n gl.drawArrays(gl.TRIANGLES, 0, 6)\n\n gl.bindTexture(gl.TEXTURE_2D, tex)\n gl.bindFramebuffer(gl.FRAMEBUFFER, null)\n gl.clearColor(1, 0, 0, 1)\n gl.clear(gl.COLOR_BUFFER_BIT)\n gl.uniform4fv(colorLoc, [0, 1/10, 1/20, 1])\n gl.drawArrays(gl.TRIANGLES, 0, 6)\n\n // Check if rendered correctly\n const pixel = new Uint8Array(4)\n gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel)\n if (pixel[0] !== 0 || pixel[1] < 248 || pixel[2] < 248 || pixel[3] < 254) {\n console.log(`not able to actually render to ${type} texture`)\n return false\n }\n\n // Check reading from float texture\n if (type === gl.FLOAT) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, fb)\n const floatPixel = new Float32Array(4)\n gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, floatPixel)\n const error = gl.getError()\n if (error) {\n console.log(`error reading pixels as float: '${getErrorDescription(gl, error)}'`)\n return false\n }\n }\n\n return true\n}\n","/**\n * @file Viewer\n * @author Alexander Rose \n * @private\n */\n\nimport { Signal } from 'signals'\nimport {\n PerspectiveCamera, OrthographicCamera, StereoCamera,\n Vector2, Box3, Vector3, Matrix4, Color,\n WebGLRenderer, WebGLRenderTarget,\n NearestFilter, LinearFilter, AdditiveBlending,\n RGBAFormat, FloatType, /*HalfFloatType, */UnsignedByteType,\n ShaderMaterial,\n PlaneGeometry,\n Scene, Mesh, Group, Object3D, Uniform,\n Fog, DirectionalLight, AmbientLight,\n BufferGeometry, BufferAttribute,\n LineSegments, ColorSpace,\n HalfFloatType\n} from 'three'\nimport '../shader/BasicLine.vert'\nimport '../shader/BasicLine.frag'\nimport '../shader/Quad.vert'\nimport '../shader/Quad.frag'\n\nimport {\n Debug, Log, WebglErrorMessage, Browser,\n setExtensionFragDepth, SupportsReadPixelsFloat, setSupportsReadPixelsFloat\n} from '../globals'\nimport { degToRad } from '../math/math-utils'\nimport Stats from './stats'\nimport { getShader } from '../shader/shader-utils'\nimport { setColorSpace } from '../color/colormaker'\nimport { JitterVectors } from './viewer-constants'\nimport {\n makeImage, ImageParameters,\n sortProjectedPosition, updateMaterialUniforms, updateCameraUniforms\n} from './viewer-utils'\nimport { testTextureSupport } from './gl-utils'\n\nimport Buffer from '../buffer/buffer'\n\nconst pixelBufferFloat = new Float32Array(4 * 25)\nconst pixelBufferUint = new Uint8Array(4 * 25)\n\n// When picking, we read a 25 pixel (5x5) array (readRenderTargetPixels)\n// We read the pixels in the order below to find what was picked.\n// This starts at the center and tries successively further points.\n// (Many points will be at equal distance to the center, their order\n// is arbitrary).\nconst pixelOrder = [12,7,13,17,11,6,8,18,16,2,14,22,10,1,3,9,19,23,21,15,5,0,4,24,20]\n\n\nconst tmpMatrix = new Matrix4()\n\nfunction onBeforeRender (this: Object3D, renderer: WebGLRenderer, scene: Scene, camera: PerspectiveCamera|OrthographicCamera, geometry: BufferGeometry, material: ShaderMaterial/*, group */) {\n const u = material.uniforms\n const updateList = []\n\n if (!u) return // See #908 - some materials may not have uniforms, ignore these\n\n if (u.objectId) {\n u.objectId.value = SupportsReadPixelsFloat ? this.id : this.id / 255\n updateList.push('objectId')\n }\n\n if (u.modelViewMatrixInverse || u.modelViewMatrixInverseTranspose ||\n u.modelViewProjectionMatrix || u.modelViewProjectionMatrixInverse\n ) {\n this.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, this.matrixWorld)\n }\n\n if (u.modelViewMatrixInverse) {\n u.modelViewMatrixInverse.value.copy(this.modelViewMatrix).invert()\n updateList.push('modelViewMatrixInverse')\n }\n\n if (u.modelViewMatrixInverseTranspose) {\n if (u.modelViewMatrixInverse) {\n u.modelViewMatrixInverseTranspose.value.copy(\n u.modelViewMatrixInverse.value\n ).transpose()\n } else {\n u.modelViewMatrixInverseTranspose.value\n .copy(this.modelViewMatrix).invert()\n .transpose()\n }\n updateList.push('modelViewMatrixInverseTranspose')\n }\n\n if (u.modelViewProjectionMatrix) {\n u.modelViewProjectionMatrix.value.multiplyMatrices(\n camera.projectionMatrix, this.modelViewMatrix\n )\n updateList.push('modelViewProjectionMatrix')\n }\n\n if (u.modelViewProjectionMatrixInverse) {\n if (u.modelViewProjectionMatrix) {\n tmpMatrix.copy(\n u.modelViewProjectionMatrix.value\n )\n u.modelViewProjectionMatrixInverse.value.copy(\n tmpMatrix.invert()\n )\n } else {\n tmpMatrix.multiplyMatrices(\n camera.projectionMatrix, this.modelViewMatrix\n )\n u.modelViewProjectionMatrixInverse.value.copy(\n tmpMatrix.invert()\n )\n }\n updateList.push('modelViewProjectionMatrixInverse')\n }\n\n if (updateList.length) {\n const materialProperties = renderer.properties.get(material)\n\n if (materialProperties.program) {\n const gl = renderer.getContext()\n const p = materialProperties.program\n gl.useProgram(p.program)\n const pu = p.getUniforms()\n\n updateList.forEach(function (name) {\n pu.setValue(gl, name, u[ name ].value)\n })\n }\n }\n}\n\nexport type CameraType = 'perspective'|'orthographic'|'stereo'\nexport type ColorWorkflow = 'linear' | 'sRGB'\n\nexport interface ViewerSignals {\n ticked: Signal,\n rendered: Signal\n}\n\nexport interface ViewerParameters {\n fogColor: Color\n fogNear: number\n fogFar: number\n\n backgroundColor: Color\n\n cameraType: CameraType\n cameraFov: number\n cameraEyeSep: number\n cameraZ: number\n\n clipNear: number\n clipFar: number\n clipDist: number\n clipMode: string // \"scene\" or \"camera\"\n clipScale: string // \"relative\" or \"absolute\"\n\n lightColor: Color\n lightIntensity: number\n ambientColor: Color\n ambientIntensity: number\n\n sampleLevel: number\n\n outputColorSpace: ColorSpace // default is three.LinearEncoding; three.sRGBEncoding gives more correct results\n}\n\nexport interface BufferInstance {\n matrix: Matrix4\n}\n\n/**\n * Viewer class\n * @class\n * @param {String|Element} [idOrElement] - dom id or element\n */\nexport default class Viewer {\n signals: ViewerSignals\n\n container: HTMLElement\n wrapper: HTMLElement\n\n private rendering: boolean\n private renderPending: boolean\n private lastRenderedPicking: boolean\n private isStill: boolean\n private frameRequest: number\n\n sampleLevel: number\n private cDist: number\n private bRadius: number\n\n private parameters: ViewerParameters\n stats: Stats\n\n perspectiveCamera: PerspectiveCamera\n private orthographicCamera: OrthographicCamera\n private stereoCamera: StereoCamera\n camera: PerspectiveCamera|OrthographicCamera\n\n width: number\n height: number\n\n scene: Scene\n private directionalLight: DirectionalLight\n private ambientLight: AmbientLight\n rotationGroup: Group\n translationGroup: Group\n private modelGroup: Group\n private pickingGroup: Group\n private backgroundGroup: Group\n private helperGroup: Group\n\n renderer: WebGLRenderer\n private supportsHalfFloat: boolean\n\n private pickingTarget: WebGLRenderTarget\n private sampleTarget: WebGLRenderTarget\n private holdTarget: WebGLRenderTarget\n\n private compositeUniforms: {\n tForeground: Uniform\n scale: Uniform\n }\n private compositeMaterial: ShaderMaterial\n private compositeCamera: OrthographicCamera\n private compositeScene: Scene\n\n private boundingBoxMesh: LineSegments\n boundingBox = new Box3()\n private boundingBoxSize = new Vector3()\n private boundingBoxLength = 0\n\n private info = {\n memory: {\n programs: 0,\n geometries: 0,\n textures: 0\n },\n render: {\n calls: 0,\n vertices: 0,\n faces: 0,\n points: 0\n }\n }\n\n private distVector = new Vector3()\n\n constructor (idOrElement: string|HTMLElement) {\n this.signals = {\n ticked: new Signal(),\n rendered: new Signal()\n }\n\n if (typeof idOrElement === 'string') {\n const elm = document.getElementById(idOrElement)\n if (elm === null) {\n this.container = document.createElement('div')\n }else {\n this.container = elm\n }\n } else if (idOrElement instanceof HTMLElement) {\n this.container = idOrElement\n } else {\n this.container = document.createElement('div')\n }\n\n if (this.container === document.body) {\n this.width = window.innerWidth || 1\n this.height = window.innerHeight || 1\n } else {\n const box = this.container.getBoundingClientRect()\n this.width = box.width || 1\n this.height = box.height || 1\n this.container.style.overflow = 'hidden'\n }\n\n this.wrapper = document.createElement('div')\n this.wrapper.style.position = 'relative'\n this.container.appendChild(this.wrapper)\n\n this._initParams()\n this._initStats()\n this._initCamera()\n this._initScene()\n\n if (this._initRenderer() === false) {\n Log.error('Viewer: could not initialize renderer')\n return\n }\n\n this._initHelper()\n\n // fog & background\n this.setBackground()\n this.setFog()\n\n this.animate = this.animate.bind(this)\n }\n\n private _initParams () {\n this.parameters = {\n fogColor: new Color(0x000000),\n fogNear: 50,\n fogFar: 100,\n\n backgroundColor: new Color(0x000000),\n\n cameraType: 'perspective',\n cameraFov: 40,\n cameraEyeSep: 0.3,\n cameraZ: -80, // FIXME initial value should be automatically determined\n\n clipNear: 0,\n clipFar: 100,\n clipDist: 10,\n clipMode: 'scene',\n clipScale: 'relative',\n\n lightColor: new Color(0xdddddd),\n lightIntensity: 1.2,\n ambientColor: new Color(0xdddddd),\n ambientIntensity: 0.3,\n\n sampleLevel: 0,\n\n // output encoding: use srgb for a linear internal workflow, srgb-linear for traditional sRGB workflow.\n outputColorSpace: 'srgb-linear',\n }\n }\n\n private _initCamera () {\n const lookAt = new Vector3(0, 0, 0)\n const {width, height} = this\n\n this.perspectiveCamera = new PerspectiveCamera(\n this.parameters.cameraFov, width / height\n )\n this.perspectiveCamera.position.z = this.parameters.cameraZ\n this.perspectiveCamera.lookAt(lookAt)\n\n this.orthographicCamera = new OrthographicCamera(\n width / -2, width / 2, height / 2, height / -2\n )\n this.orthographicCamera.position.z = this.parameters.cameraZ\n this.orthographicCamera.lookAt(lookAt)\n\n this.stereoCamera = new StereoCamera()\n this.stereoCamera.aspect = 0.5\n this.stereoCamera.eyeSep = this.parameters.cameraEyeSep\n\n const cameraType = this.parameters.cameraType\n if (cameraType === 'orthographic') {\n this.camera = this.orthographicCamera\n } else if(cameraType === 'perspective' || cameraType === 'stereo') {\n this.camera = this.perspectiveCamera\n } else {\n throw new Error(`Unknown cameraType '${cameraType}'`)\n }\n this.camera.updateProjectionMatrix()\n }\n\n private _initStats () {\n this.stats = new Stats()\n }\n\n private _initScene () {\n if (!this.scene) {\n this.scene = new Scene()\n this.scene.name = 'scene'\n }\n\n this.rotationGroup = new Group()\n this.rotationGroup.name = 'rotationGroup'\n this.scene.add(this.rotationGroup)\n\n this.translationGroup = new Group()\n this.translationGroup.name = 'translationGroup'\n this.rotationGroup.add(this.translationGroup)\n\n this.modelGroup = new Group()\n this.modelGroup.name = 'modelGroup'\n this.translationGroup.add(this.modelGroup)\n\n this.pickingGroup = new Group()\n this.pickingGroup.name = 'pickingGroup'\n this.translationGroup.add(this.pickingGroup)\n\n this.backgroundGroup = new Group()\n this.backgroundGroup.name = 'backgroundGroup'\n this.translationGroup.add(this.backgroundGroup)\n\n this.helperGroup = new Group()\n this.helperGroup.name = 'helperGroup'\n this.translationGroup.add(this.helperGroup)\n\n // fog\n\n this.scene.fog = new Fog(this.parameters.fogColor.getHex())\n\n // light\n\n this.directionalLight = new DirectionalLight(\n this.parameters.lightColor.getHex(), this.parameters.lightIntensity\n )\n this.scene.add(this.directionalLight)\n\n this.ambientLight = new AmbientLight(\n this.parameters.ambientColor.getHex(), this.parameters.ambientIntensity\n )\n this.scene.add(this.ambientLight)\n }\n\n private _initRenderer () {\n const dpr = window.devicePixelRatio\n const {width, height} = this\n\n try {\n this.renderer = new WebGLRenderer({\n preserveDrawingBuffer: true,\n alpha: true,\n antialias: true\n })\n } catch (e) {\n this.wrapper.innerHTML = WebglErrorMessage\n return false\n }\n this.renderer.setPixelRatio(dpr)\n this.renderer.setSize(width, height)\n this.renderer.autoClear = false\n this.renderer.sortObjects = true\n this.renderer.outputColorSpace = this.parameters.outputColorSpace\n this.renderer.useLegacyLights = true\n\n const gl = this.renderer.getContext()\n // console.log(gl.getContextAttributes().antialias)\n // console.log(gl.getParameter(gl.SAMPLES))\n\n // For WebGL1, extensions must be explicitly enabled.\n // The following are builtin to WebGL2 (and don't appear as\n // extensions)\n // EXT_frag_depth, OES_element_index_uint, OES_texture_float\n // OES_texture_half_float\n\n // The WEBGL_color_buffer_float extension is replaced by\n // EXT_color_buffer_float\n\n // If not webgl2 context, explicitly check for these\n if (!this.renderer.capabilities.isWebGL2) {\n setExtensionFragDepth(this.renderer.extensions.get('EXT_frag_depth'))\n this.renderer.extensions.get('OES_element_index_uint')\n\n setSupportsReadPixelsFloat(\n (this.renderer.extensions.get('OES_texture_float') &&\n this.renderer.extensions.get('WEBGL_color_buffer_float')) ||\n (this.renderer.extensions.get('OES_texture_float') &&\n testTextureSupport(gl.FLOAT))\n )\n // picking texture\n\n this.renderer.extensions.get('OES_texture_float')\n\n this.supportsHalfFloat = (\n this.renderer.extensions.get('OES_texture_half_float') &&\n testTextureSupport(0x8D61)\n )\n\n } else {\n setExtensionFragDepth(true)\n setSupportsReadPixelsFloat(\n this.renderer.extensions.get('EXT_color_buffer_float')\n )\n this.supportsHalfFloat = true\n }\n\n this.wrapper.appendChild(this.renderer.domElement)\n\n const dprWidth = width * dpr\n const dprHeight = height * dpr\n\n\n if (Debug) {\n console.log(JSON.stringify({\n 'Browser': Browser,\n 'OES_texture_float': !!this.renderer.extensions.get('OES_texture_float'),\n 'OES_texture_half_float': !!this.renderer.extensions.get('OES_texture_half_float'),\n 'WEBGL_color_buffer_float': !!this.renderer.extensions.get('WEBGL_color_buffer_float'),\n 'testTextureSupport Float': testTextureSupport(gl.FLOAT),\n 'testTextureSupport HalfFloat': testTextureSupport(0x8D61),\n 'this.supportsHalfFloat': this.supportsHalfFloat,\n 'SupportsReadPixelsFloat': SupportsReadPixelsFloat\n }, null, 2))\n }\n\n this.pickingTarget = new WebGLRenderTarget(\n dprWidth, dprHeight,\n {\n minFilter: NearestFilter,\n magFilter: NearestFilter,\n stencilBuffer: false,\n format: RGBAFormat,\n type: SupportsReadPixelsFloat ? FloatType : UnsignedByteType\n }\n )\n this.pickingTarget.texture.generateMipmaps = false\n this.pickingTarget.texture.colorSpace = this.parameters.outputColorSpace\n\n // workaround to reset the gl state after using testTextureSupport\n // fixes some bug where nothing is rendered to the canvas\n // when animations are started on page load\n this.renderer.setRenderTarget(this.pickingTarget)\n this.renderer.clear()\n this.renderer.setRenderTarget(null!)\n\n // ssaa textures\n\n this.sampleTarget = new WebGLRenderTarget(\n dprWidth, dprHeight,\n {\n minFilter: LinearFilter,\n magFilter: LinearFilter,\n format: RGBAFormat,\n type: this.supportsHalfFloat ? HalfFloatType : (\n SupportsReadPixelsFloat ? FloatType : UnsignedByteType\n )\n }\n )\n this.sampleTarget.texture.colorSpace = this.parameters.outputColorSpace\n\n this.holdTarget = new WebGLRenderTarget(\n dprWidth, dprHeight,\n {\n minFilter: NearestFilter,\n magFilter: NearestFilter,\n format: RGBAFormat,\n type: this.supportsHalfFloat ? HalfFloatType : (\n SupportsReadPixelsFloat ? FloatType : UnsignedByteType\n )\n }\n )\n this.holdTarget.texture.colorSpace = this.parameters.outputColorSpace\n\n this.compositeUniforms = {\n 'tForeground': new Uniform(this.sampleTarget.texture),\n 'scale': new Uniform(1.0)\n }\n\n this.compositeMaterial = new ShaderMaterial({\n uniforms: this.compositeUniforms,\n vertexShader: getShader('Quad.vert'),\n fragmentShader: getShader('Quad.frag'),\n premultipliedAlpha: true,\n transparent: true,\n blending: AdditiveBlending,\n depthTest: false,\n depthWrite: false\n })\n\n this.compositeCamera = new OrthographicCamera(-1, 1, 1, -1, 0, 1)\n this.compositeScene = new Scene()\n this.compositeScene.name = 'compositeScene'\n this.compositeScene.add(new Mesh(\n new PlaneGeometry(2, 2), this.compositeMaterial\n ))\n }\n\n private _initHelper () {\n const indices = new Uint16Array([\n 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6,\n 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7\n ])\n const positions = new Float32Array(8 * 3)\n\n const bbGeometry = new BufferGeometry()\n bbGeometry.setIndex(new BufferAttribute(indices, 1))\n bbGeometry.setAttribute('position', new BufferAttribute(positions, 3))\n const bbMaterial = new ShaderMaterial({\n uniforms: { 'uColor': { value: new Color('skyblue') } },\n vertexShader: getShader('BasicLine.vert'),\n fragmentShader: getShader('BasicLine.frag')\n })\n\n this.boundingBoxMesh = new LineSegments(bbGeometry, bbMaterial)\n this.helperGroup.add(this.boundingBoxMesh)\n }\n\n updateHelper () {\n const position = ((this.boundingBoxMesh.geometry as BufferGeometry).attributes as any).position // TODO\n const array = position.array\n const {min, max} = this.boundingBox\n\n array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z\n array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z\n array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z\n array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z\n array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z\n array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z\n array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z\n array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z\n\n position.needsUpdate = true\n\n if (!this.boundingBox.isEmpty()) {\n this.boundingBoxMesh.geometry.computeBoundingSphere()\n }\n }\n\n /** Distance from origin (lookAt point) */\n get cameraDistance(): number {\n return Math.abs(this.camera.position.z)\n }\n\n /** Set distance from origin (lookAt point); along the -z axis */\n set cameraDistance(d: number) {\n this.camera.position.z = -d\n }\n\n add (buffer: Buffer, instanceList?: BufferInstance[]) {\n // Log.time( \"Viewer.add\" );\n\n if (instanceList) {\n instanceList.forEach(instance => this.addBuffer(buffer, instance))\n } else {\n this.addBuffer(buffer)\n }\n\n buffer.group.name = 'meshGroup'\n buffer.wireframeGroup.name = 'wireframeGroup'\n if (buffer.parameters.background) {\n this.backgroundGroup.add(buffer.group)\n this.backgroundGroup.add(buffer.wireframeGroup)\n } else {\n this.modelGroup.add(buffer.group)\n this.modelGroup.add(buffer.wireframeGroup)\n }\n\n if (buffer.pickable) {\n this.pickingGroup.add(buffer.pickingGroup)\n }\n\n if (Debug) this.updateHelper()\n\n // Log.timeEnd( \"Viewer.add\" );\n }\n\n addBuffer (buffer: Buffer, instance?: BufferInstance) {\n // Log.time( \"Viewer.addBuffer\" );\n\n function setUserData (object: Object3D) {\n if (object instanceof Group) {\n object.children.forEach(setUserData)\n } else {\n object.userData.buffer = buffer\n object.userData.instance = instance\n object.onBeforeRender = onBeforeRender\n }\n }\n\n const mesh = buffer.getMesh()\n if (instance) {\n mesh.applyMatrix4(instance.matrix)\n }\n setUserData(mesh)\n buffer.group.add(mesh)\n\n const wireframeMesh = buffer.getWireframeMesh()\n if (instance) {\n // wireframeMesh.applyMatrix( instance.matrix );\n wireframeMesh.matrix.copy(mesh.matrix)\n wireframeMesh.position.copy(mesh.position)\n wireframeMesh.quaternion.copy(mesh.quaternion)\n wireframeMesh.scale.copy(mesh.scale)\n }\n setUserData(wireframeMesh)\n buffer.wireframeGroup.add(wireframeMesh)\n\n if (buffer.pickable) {\n const pickingMesh = buffer.getPickingMesh()\n if (instance) {\n // pickingMesh.applyMatrix( instance.matrix );\n pickingMesh.matrix.copy(mesh.matrix)\n pickingMesh.position.copy(mesh.position)\n pickingMesh.quaternion.copy(mesh.quaternion)\n pickingMesh.scale.copy(mesh.scale)\n }\n setUserData(pickingMesh)\n buffer.pickingGroup.add(pickingMesh)\n }\n\n if (instance) {\n this._updateBoundingBox(buffer.geometry, buffer.matrix, instance.matrix)\n } else {\n this._updateBoundingBox(buffer.geometry, buffer.matrix)\n }\n\n // Log.timeEnd( \"Viewer.addBuffer\" );\n }\n\n remove (buffer: Buffer) {\n this.translationGroup.children.forEach(function (group) {\n group.remove(buffer.group)\n group.remove(buffer.wireframeGroup)\n })\n\n if (buffer.pickable) {\n this.pickingGroup.remove(buffer.pickingGroup)\n }\n\n this.updateBoundingBox()\n if (Debug) this.updateHelper()\n\n // this.requestRender();\n }\n\n private _updateBoundingBox (geometry?: BufferGeometry, matrix?: Matrix4, instanceMatrix?: Matrix4) {\n const boundingBox = this.boundingBox\n\n function updateGeometry (geometry: BufferGeometry, matrix?: Matrix4, instanceMatrix?: Matrix4) {\n if (geometry.boundingBox == null) {\n geometry.computeBoundingBox()\n }\n\n const geoBoundingBox = (geometry.boundingBox as Box3).clone()\n\n if (matrix) {\n geoBoundingBox.applyMatrix4(matrix)\n }\n if (instanceMatrix) {\n geoBoundingBox.applyMatrix4(instanceMatrix)\n }\n\n if (geoBoundingBox.min.equals(geoBoundingBox.max)) {\n // mainly to give a single impostor geometry some volume\n // as it is only expanded in the shader on the GPU\n geoBoundingBox.expandByScalar(5)\n }\n\n boundingBox.union(geoBoundingBox)\n }\n\n function updateNode (node: Mesh) {\n if (node.geometry !== undefined) {\n let matrix, instanceMatrix\n if (node.userData.buffer) {\n matrix = node.userData.buffer.matrix\n }\n if (node.userData.instance) {\n instanceMatrix = node.userData.instance.matrix\n }\n updateGeometry(node.geometry as BufferGeometry, matrix, instanceMatrix) // TODO\n }\n }\n\n if (geometry) {\n updateGeometry(geometry, matrix, instanceMatrix)\n } else {\n boundingBox.makeEmpty()\n this.modelGroup.traverse(updateNode)\n this.backgroundGroup.traverse(updateNode)\n }\n\n boundingBox.getSize(this.boundingBoxSize)\n this.boundingBoxLength = this.boundingBoxSize.length()\n }\n\n updateBoundingBox () {\n this._updateBoundingBox()\n if (Debug) this.updateHelper()\n }\n\n getPickingPixels () {\n const {width, height} = this\n\n const n = width * height * 4\n const imgBuffer = SupportsReadPixelsFloat ? new Float32Array(n) : new Uint8Array(n)\n\n this.render(true)\n this.renderer.readRenderTargetPixels(\n this.pickingTarget, 0, 0, width, height, imgBuffer\n )\n\n return imgBuffer\n }\n\n getImage (picking: boolean) {\n return new Promise(resolve => {\n if (picking) {\n const {width, height} = this\n const n = width * height * 4\n let imgBuffer = this.getPickingPixels()\n\n if (SupportsReadPixelsFloat) {\n const imgBuffer2 = new Uint8Array(n)\n for (let i = 0; i < n; ++i) {\n imgBuffer2[ i ] = Math.round(imgBuffer[ i ] * 255)\n }\n imgBuffer = imgBuffer2\n }\n\n const canvas = document.createElement('canvas')\n canvas.width = width\n canvas.height = height\n const ctx = canvas.getContext('2d')! // TODO\n const imgData = ctx.getImageData(0, 0, width, height)\n imgData.data.set(imgBuffer as any) // TODO\n ctx.putImageData(imgData, 0, 0)\n canvas.toBlob(resolve as any, 'image/png') // TODO\n } else {\n this.renderer.domElement.toBlob(resolve as any, 'image/png') // TODO\n }\n })\n }\n\n makeImage (params: Partial = {}) {\n return makeImage(this, params)\n }\n\n setLight (color: Color|number|string, intensity: number, ambientColor: Color|number|string, ambientIntensity: number) {\n const p = this.parameters\n\n if (color !== undefined) p.lightColor.set(color as string) // TODO\n if (intensity !== undefined) p.lightIntensity = intensity\n if (ambientColor !== undefined) p.ambientColor.set(ambientColor as string) // TODO\n if (ambientIntensity !== undefined) p.ambientIntensity = ambientIntensity\n\n this.requestRender()\n }\n\n setFog (color?: Color|number|string, near?: number, far?: number) {\n const p = this.parameters\n\n if (color !== undefined) p.fogColor.set(color as string) // TODO\n if (near !== undefined) p.fogNear = near\n if (far !== undefined) p.fogFar = far\n\n this.requestRender()\n }\n\n setBackground (color?: Color|number|string) {\n const p = this.parameters\n\n if (color) p.backgroundColor.set(color as string) // TODO\n\n this.setFog(p.backgroundColor)\n this.renderer.setClearColor(p.backgroundColor, 0)\n this.renderer.domElement.style.backgroundColor = p.backgroundColor.getStyle()\n\n this.requestRender()\n }\n\n setSampling (level: number) {\n if (level !== undefined) {\n this.parameters.sampleLevel = level\n this.sampleLevel = level\n }\n\n this.requestRender()\n }\n\n /**\n * Set the output color encoding, i.e. how the renderer translates\n * colorspaces as it renders to the screen.\n\n * The default is LinearEncoding, because the internals of NGL are\n * already sRGB so no translation is needed to show sRGB colors.\n * Set to sRGBEncoding to create a linear workflow, and also call\n * `setColorEncoding(LinearEncoding)` to linearize colors on input.\n * @see setColorEncoding\n */\n private setOutputEncoding (colorspace: ColorSpace) {\n this.parameters.outputColorSpace = colorspace\n this.renderer.outputColorSpace = colorspace\n this.pickingTarget.texture.colorSpace = colorspace\n this.sampleTarget.texture.colorSpace = colorspace\n this.holdTarget.texture.colorSpace = colorspace\n }\n\n /**\n * Set the internal color workflow, linear or sRGB.\n * sRGB, the default, is more \"vibrant\" at the cost of accuracy.\n * Linear gives more accurate results, especially for transparent objects.\n * In all cases, the output is always sRGB; this just affects how colors are computed internally.\n * Call this just after creating the viewer, before loading any models.\n */\n setColorWorkflow (colorspace: ColorSpace) {\n if (colorspace != 'srgb-linear' && colorspace != 'srgb')\n throw new Error(`setColorWorkflow: invalid color workflow ${colorspace}`)\n setColorSpace(colorspace == 'srgb-linear' ? 'linear' : 'sRGB')\n this.setOutputEncoding(colorspace == 'srgb-linear' ? 'srgb' : 'srgb-linear')\n // Note: this doesn't rebuild models, so existing geometry will have\n // the old color encoding.\n this.requestRender()\n }\n\n setCamera (type: CameraType, fov?: number, eyeSep?: number) {\n const p = this.parameters\n\n if (type) p.cameraType = type\n if (fov) p.cameraFov = fov\n if (eyeSep) p.cameraEyeSep = eyeSep\n\n if (p.cameraType === 'orthographic') {\n if (this.camera !== this.orthographicCamera) {\n this.camera = this.orthographicCamera\n this.camera.position.copy(this.perspectiveCamera.position)\n this.camera.up.copy(this.perspectiveCamera.up)\n this.updateZoom()\n }\n } else if (p.cameraType === 'perspective' || p.cameraType === 'stereo') {\n if (this.camera !== this.perspectiveCamera) {\n this.camera = this.perspectiveCamera\n this.camera.position.copy(this.orthographicCamera.position)\n this.camera.up.copy(this.orthographicCamera.up)\n }\n } else {\n throw new Error(`Unknown cameraType '${p.cameraType}'`)\n }\n\n this.perspectiveCamera.fov = p.cameraFov\n this.stereoCamera.eyeSep = p.cameraEyeSep\n this.camera.updateProjectionMatrix()\n\n this.requestRender()\n }\n\n setClip (near: number, far: number, dist: number, clipMode?: string, clipScale?: string) {\n const p = this.parameters\n\n if (near !== undefined) p.clipNear = near\n if (far !== undefined) p.clipFar = far\n if (dist !== undefined) p.clipDist = dist\n if (clipMode !== undefined) p.clipMode = clipMode\n if (clipScale !== undefined) p.clipScale = clipScale\n\n this.requestRender()\n }\n\n setSize (width: number, height: number) {\n this.width = width || 1\n this.height = height || 1\n\n this.perspectiveCamera.aspect = this.width / this.height\n this.orthographicCamera.left = -this.width / 2\n this.orthographicCamera.right = this.width / 2\n this.orthographicCamera.top = this.height / 2\n this.orthographicCamera.bottom = -this.height / 2\n this.camera.updateProjectionMatrix()\n\n const dpr = window.devicePixelRatio\n\n this.renderer.setPixelRatio(dpr)\n this.renderer.setSize(width, height)\n\n const dprWidth = this.width * dpr\n const dprHeight = this.height * dpr\n\n this.pickingTarget.setSize(dprWidth, dprHeight)\n this.sampleTarget.setSize(dprWidth, dprHeight)\n this.holdTarget.setSize(dprWidth, dprHeight)\n\n this.requestRender()\n }\n\n handleResize () {\n if (this.container === document.body) {\n this.setSize(window.innerWidth, window.innerHeight)\n } else {\n const box = this.container.getBoundingClientRect()\n this.setSize(box.width, box.height)\n }\n }\n\n updateInfo (reset?: boolean) {\n const { memory, render } = this.info\n\n if (reset) {\n memory.programs = 0\n memory.geometries = 0\n memory.textures = 0\n\n render.calls = 0\n render.vertices = 0\n render.points = 0\n } else {\n const rInfo = this.renderer.info\n const rMemory = rInfo.memory\n const rRender = rInfo.render\n\n memory.geometries = rMemory.geometries\n memory.textures = rMemory.textures\n\n render.calls += rRender.calls\n render.faces += rRender.triangles\n render.points += rRender.points\n }\n }\n\n animate () {\n this.signals.ticked.dispatch(this.stats)\n const delta = window.performance.now() - this.stats.startTime\n\n if (delta > 500 && !this.isStill && this.sampleLevel < 3 && this.sampleLevel !== -1) {\n const currentSampleLevel = this.sampleLevel\n this.sampleLevel = 3\n this.renderPending = true\n this.render()\n this.isStill = true\n this.sampleLevel = currentSampleLevel\n if (Debug) Log.log('rendered still frame')\n }\n\n this.frameRequest = window.requestAnimationFrame(this.animate)\n }\n\n pick (x: number, y: number) {\n if (this.parameters.cameraType === 'stereo') {\n // TODO picking broken for stereo camera\n return {\n 'pid': 0,\n 'instance': undefined,\n 'picker': undefined\n }\n }\n\n x *= window.devicePixelRatio\n y *= window.devicePixelRatio\n\n x = Math.max(x - 2, 0)\n y = Math.max(y - 2, 0)\n\n let pid = 0, instance, picker\n const pixelBuffer = SupportsReadPixelsFloat ? pixelBufferFloat : pixelBufferUint\n\n this.render(true)\n this.renderer.readRenderTargetPixels(\n this.pickingTarget, x, y, 5, 5, pixelBuffer\n )\n\n for (let i = 0; i < pixelOrder.length; i++) {\n\n const offset = pixelOrder[i] * 4\n\n const oid = Math.round(pixelBuffer[ offset + 3 ])\n const object = this.pickingGroup.getObjectById(oid)\n if (object) {\n instance = object.userData.instance\n picker = object.userData.buffer.picking\n } else {\n continue\n }\n\n if (SupportsReadPixelsFloat) {\n pid =\n ((Math.round(pixelBuffer[offset] * 255) << 16) & 0xFF0000) |\n ((Math.round(pixelBuffer[offset + 1] * 255) << 8) & 0x00FF00) |\n ((Math.round(pixelBuffer[offset + 2] * 255)) & 0x0000FF)\n } else {\n pid =\n (pixelBuffer[offset] << 16) |\n (pixelBuffer[offset + 1] << 8) |\n (pixelBuffer[offset + 2])\n }\n }\n // if( Debug ){\n // const rgba = Array.apply( [], pixelBuffer );\n // Log.log( pixelBuffer );\n // Log.log(\n // \"picked color\",\n // rgba.map( c => { return c.toPrecision( 2 ) } )\n // );\n // Log.log( \"picked pid\", pid );\n // Log.log( \"picked oid\", oid );\n // Log.log( \"picked object\", object );\n // Log.log( \"picked instance\", instance );\n // Log.log( \"picked position\", x, y );\n // Log.log( \"devicePixelRatio\", window.devicePixelRatio );\n // }\n\n return { pid, instance, picker }\n }\n\n requestRender () {\n if (this.renderPending) {\n // Log.info(\"there is still a 'render' call pending\")\n return\n }\n\n // start gathering stats anew after inactivity\n if (window.performance.now() - this.stats.startTime > 22) {\n this.stats.begin()\n this.isStill = false\n }\n\n this.renderPending = true\n\n window.requestAnimationFrame(() => {\n this.render()\n this.stats.update()\n })\n }\n\n updateZoom () {\n const fov = degToRad(this.perspectiveCamera.fov)\n const height = 2 * Math.tan(fov / 2) * this.cameraDistance\n this.orthographicCamera.zoom = this.height / height\n }\n\n /**\n * Convert an absolute clip value to a relative one using bRadius.\n *\n * 0.0 -> 50.0\n * bRadius -> 0.0\n */\n absoluteToRelative (d: number) :number {\n return 50 * (1 - d / this.bRadius)\n }\n\n /**\n * Convert a relative clip value to an absolute one using bRadius\n *\n * 0.0 -> bRadius\n * 50.0 -> 0.0\n */\n relativeToAbsolute (d: number) : number {\n return this.bRadius * (1 - d / 50)\n }\n\n /**\n * Intepret clipMode, clipScale and set the camera and fog clipping.\n * Also ensures bRadius and cDist are valid\n */\n private __updateClipping () {\n const p = this.parameters\n\n // bRadius must always be updated for material-based clipping\n // and for focus calculations\n this.bRadius = Math.max(10, this.boundingBoxLength * 0.5)\n\n // FL: Removed below, but leaving commented as I don't understand intention\n // this.bRadius += this.boundingBox.getCenter(this.distVector).length()\n\n if (!isFinite(this.bRadius)) {\n this.bRadius = 50\n }\n\n this.camera.getWorldPosition(this.distVector)\n this.cDist = this.distVector.length()\n if (!this.cDist) {\n // recover from a broken (NaN) camera position\n this.cameraDistance = Math.abs(p.cameraZ)\n this.cDist = Math.abs(p.cameraZ)\n }\n\n // fog\n const fog = this.scene.fog as Fog\n fog.color.set(p.fogColor)\n\n if (p.clipMode === 'camera') {\n // Always interpret clipScale as absolute for clipMode camera\n\n this.camera.near = p.clipNear\n this.camera.far = p.clipFar\n fog.near = p.fogNear\n fog.far = p.fogFar\n\n } else {\n // scene mode\n\n if (p.clipScale === 'absolute') {\n // absolute scene mode; offset clip planes from scene center\n // (note: positive values move near plane towards camera and rear plane away)\n\n this.camera.near = this.cDist - p.clipNear\n this.camera.far = this.cDist + p.clipFar\n fog.near = this.cDist - p.fogNear\n fog.far = this.cDist + p.fogFar\n\n } else {\n // relative scene mode (default): convert pecentages to Angstroms\n\n const nearFactor = (50 - p.clipNear) / 50\n const farFactor = -(50 - p.clipFar) / 50\n this.camera.near = this.cDist - (this.bRadius * nearFactor)\n this.camera.far = this.cDist + (this.bRadius * farFactor)\n\n const fogNearFactor = (50 - p.fogNear) / 50\n const fogFarFactor = -(50 - p.fogFar) / 50\n fog.near = this.cDist - (this.bRadius * fogNearFactor)\n fog.far = this.cDist + (this.bRadius * fogFarFactor)\n }\n }\n\n if (p.clipMode !== 'camera') {\n\n if (this.camera.type === 'PerspectiveCamera') {\n\n this.camera.near = Math.max(0.1, p.clipDist, this.camera.near)\n this.camera.far = Math.max(1, this.camera.far)\n fog.near = Math.max(0.1, fog.near)\n fog.far = Math.max(1, fog.far)\n } else if (this.camera.type === 'OrthographicCamera') {\n\n if (p.clipDist > 0) {\n this.camera.near = Math.max(p.clipDist, this.camera.near)\n }\n }\n }\n }\n\n private __updateCamera () {\n const camera = this.camera\n camera.updateMatrix()\n camera.updateMatrixWorld(true)\n camera.updateProjectionMatrix()\n\n updateMaterialUniforms(this.scene, camera, this.renderer, this.cDist, this.bRadius)\n sortProjectedPosition(this.scene, camera)\n }\n\n private __setVisibility (model: boolean, picking: boolean, background: boolean, helper: boolean) {\n this.modelGroup.visible = model\n this.pickingGroup.visible = picking\n this.backgroundGroup.visible = background\n this.helperGroup.visible = helper\n }\n\n private __updateLights () {\n this.directionalLight.color.set(this.parameters.lightColor)\n this.directionalLight.intensity = this.parameters.lightIntensity\n\n this.distVector.copy(this.camera.position).setLength(this.boundingBoxLength * 100)\n this.directionalLight.position.copy(this.camera.position).add(this.distVector)\n\n this.ambientLight.color.set(this.parameters.ambientColor)\n this.ambientLight.intensity = this.parameters.ambientIntensity\n }\n\n private __renderPickingGroup (camera: PerspectiveCamera|OrthographicCamera) {\n this.renderer.setRenderTarget(this.pickingTarget || null)\n this.renderer.clear()\n this.__setVisibility(false, true, false, false)\n this.renderer.render(this.scene, camera)\n // back to standard render target\n this.renderer.setRenderTarget(null)\n this.updateInfo()\n\n // if (Debug) {\n // this.__setVisibility(false, true, false, true);\n\n // this.renderer.clear();\n // this.renderer.render(this.scene, camera);\n // }\n }\n\n private __renderModelGroup (camera: PerspectiveCamera|OrthographicCamera, renderTarget?: WebGLRenderTarget) {\n this.renderer.setRenderTarget(renderTarget || null)\n this.renderer.clear()\n this.__setVisibility(false, false, true, false)\n this.renderer.render(this.scene, camera)\n this.renderer.clear(false, true, true)\n this.updateInfo()\n\n this.__setVisibility(true, false, false, Debug)\n this.renderer.render(this.scene, camera)\n this.renderer.setRenderTarget(null) // set back to default canvas\n this.updateInfo()\n }\n\n private __renderSuperSample (camera: PerspectiveCamera|OrthographicCamera, renderTarget?: WebGLRenderTarget) {\n // based on the Supersample Anti-Aliasing Render Pass\n // contributed to three.js by bhouston / http://clara.io/\n //\n // This manual approach to SSAA re-renders the scene ones for\n // each sample with camera jitter and accumulates the results.\n // References: https://en.wikipedia.org/wiki/Supersampling\n const offsetList = JitterVectors[ Math.max(0, Math.min(this.sampleLevel, 5)) ]\n\n const baseSampleWeight = 1.0 / offsetList.length\n const roundingRange = 1 / 32\n\n this.compositeUniforms.tForeground.value = this.sampleTarget.texture\n\n let width = this.sampleTarget.width\n const height = this.sampleTarget.height\n if (this.parameters.cameraType === 'stereo') {\n width /= 2\n }\n\n // render the scene multiple times, each slightly jitter offset\n // from the last and accumulate the results.\n for (let i = 0; i < offsetList.length; ++i) {\n const offset = offsetList[ i ]\n camera.setViewOffset(\n width, height, offset[ 0 ], offset[ 1 ], width, height\n )\n camera.updateProjectionMatrix()\n updateCameraUniforms(this.scene, camera)\n\n let sampleWeight = baseSampleWeight\n // the theory is that equal weights for each sample lead to an\n // accumulation of rounding errors.\n // The following equation varies the sampleWeight per sample\n // so that it is uniformly distributed across a range of values\n // whose rounding errors cancel each other out.\n const uniformCenteredDistribution = -0.5 + (i + 0.5) / offsetList.length\n sampleWeight += roundingRange * uniformCenteredDistribution\n this.compositeUniforms.scale.value = sampleWeight\n\n this.__renderModelGroup(camera, this.sampleTarget)\n this.renderer.setRenderTarget(this.holdTarget)\n if (i === 0) {\n this.renderer.clear()\n }\n\n this.renderer.render(this.compositeScene, this.compositeCamera)\n }\n\n this.compositeUniforms.scale.value = 1.0\n this.compositeUniforms.tForeground.value = this.holdTarget.texture\n\n camera.clearViewOffset()\n this.renderer.setRenderTarget(renderTarget || null)\n this.renderer.clear()\n this.renderer.render(this.compositeScene, this.compositeCamera)\n }\n\n private __renderStereo (picking = false, _renderTarget?: WebGLRenderTarget) {\n const stereoCamera = this.stereoCamera\n stereoCamera.update(this.perspectiveCamera);\n\n const renderer = this.renderer\n let size = new Vector2()\n renderer.getSize(size)\n\n renderer.setScissorTest(true)\n\n renderer.setScissor(0, 0, size.width / 2, size.height)\n renderer.setViewport(0, 0, size.width / 2, size.height)\n updateCameraUniforms(this.scene, stereoCamera.cameraL)\n this.__render(picking, stereoCamera.cameraL)\n\n renderer.setScissor(size.width / 2, 0, size.width / 2, size.height)\n renderer.setViewport(size.width / 2, 0, size.width / 2, size.height)\n updateCameraUniforms(this.scene, stereoCamera.cameraR)\n this.__render(picking, stereoCamera.cameraR)\n\n renderer.setScissorTest(false)\n renderer.setViewport(0, 0, size.width, size.height)\n }\n\n private __render(picking = false, camera: PerspectiveCamera|OrthographicCamera, renderTarget?: WebGLRenderTarget) {\n if (picking) {\n if (!this.lastRenderedPicking) this.__renderPickingGroup(camera)\n } else if (this.sampleLevel > 0 && this.parameters.cameraType !== 'stereo') {\n // TODO super sample broken for stereo camera\n this.__renderSuperSample(camera, renderTarget)\n } else {\n this.__renderModelGroup(camera, renderTarget)\n }\n }\n\n render (picking = false, renderTarget?: WebGLRenderTarget) {\n if (this.rendering) {\n Log.warn(\"'tried to call 'render' from within 'render'\")\n return\n }\n\n // Log.time('Viewer.render')\n\n this.rendering = true\n\n try {\n this.__updateClipping()\n this.__updateCamera()\n this.__updateLights()\n this.updateInfo(true)\n\n // render\n if (this.parameters.cameraType === 'stereo') {\n this.__renderStereo(picking, renderTarget)\n } else {\n this.__render(picking, this.camera, renderTarget)\n }\n this.lastRenderedPicking = picking\n } finally {\n this.rendering = false\n this.renderPending = false\n }\n this.signals.rendered.dispatch()\n\n // Log.timeEnd('Viewer.render')\n // Log.log(this.info.memory, this.info.render)\n }\n\n clear () {\n Log.log('scene cleared')\n this.scene.remove(this.rotationGroup)\n this._initScene()\n this.renderer.clear()\n }\n\n dispose () {\n this.renderer.dispose()\n window.cancelAnimationFrame(this.frameRequest)\n }\n}\n","/**\n * @file Constants\n * @author Alexander Rose \n * @private\n */\n\nexport const LeftMouseButton = 1\nexport const MiddleMouseButton = 2\nexport const RightMouseButton = 3\n","/**\n * @file Mouse Observer\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector2 } from 'three'\nimport { Signal } from 'signals'\n\nimport { LeftMouseButton, RightMouseButton } from '../constants'\nimport { defaults } from '../utils'\nimport Viewer from '../viewer/viewer'\nimport MouseControls from '../controls/mouse-controls'\n\ntype Optional = Pick, K> & Omit;\n\n/**\n * @example\n * mouseObserver.signals.scrolled.add( function( delta ){ ... } );\n *\n * @typedef {Object} MouseSignals\n * @property {Signal} moved - on move: deltaX, deltaY\n * @property {Signal} scrolled - on scroll: delta\n * @property {Signal} dragged - on drag: deltaX, deltaY\n * @property {Signal} dropped - on drop\n * @property {Signal} clicked - on click\n * @property {Signal} hovered - on hover\n */\n\nfunction getTouchDistance (event: TouchEvent) {\n const dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX\n const dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY\n return Math.sqrt(dx * dx + dy * dy)\n}\n\nfunction getMouseButtons (event: MouseEvent) {\n if (typeof event === 'object') {\n if ('buttons' in event) {\n return event.buttons\n } else if ('which' in event as any) {\n const b = (event as any).which\n if (b === 2) {\n return 4\n } else if (b === 3) {\n return 2\n } else if (b > 0) {\n return 1 << (b - 1)\n }\n } else if ('button' in event as any) {\n const b = (event as any).button\n if (b === 1) {\n return 4\n } else if (b === 2) {\n return 2\n } else if (b >= 0) {\n return 1 << b\n }\n }\n }\n return 0\n}\n\nexport interface MouseSignals {\n moved: Signal // on move: deltaX, deltaY\n scrolled: Signal // on scroll: delta\n dragged: Signal // on drag: deltaX, deltaY\n dropped: Signal // on drop\n clicked: Signal // on click\n hovered: Signal // on hover\n doubleClicked: Signal\n}\n\nexport interface MouseParams {\n hoverTimeout?: number\n handleScroll?:boolean\n doubleClickSpeed?: number\n}\n\n/**\n * Mouse observer\n *\n * @example\n * // listen to mouse moving (and touch-moving) events\n * mouseObserver.moved.moved.add( function( deltaX, deltaY ){ ... } );\n *\n * @example\n * // listen to scrolling (and pinching) events\n * mouseObserver.signals.scrolled.add( function( delta ){ ... } );\n *\n * @example\n * // listen to dragging (and touch-dragging) events\n * mouseObserver.signals.dragged.add( function( deltaX, deltaY ){ ... } );\n *\n * @example\n * // listen to clicking (and tapping) events\n * mouseObserver.signals.clicked.add( function(){ ... } );\n *\n * @example\n * // listen to double clicking (and double tapping) events\n * mouseObserver.signals.doubleClicked.add( function(){ ... } );\n *\n * @example\n * // listen to hovering events\n * mouseObserver.signals.hovered.add( function(){ ... } );\n */\nclass MouseObserver {\n signals: MouseSignals = {\n moved: new Signal(),\n scrolled: new Signal(),\n dragged: new Signal(),\n dropped: new Signal(),\n clicked: new Signal(),\n hovered: new Signal(),\n doubleClicked: new Signal()\n }\n\n hoverTimeout: number\n handleScroll:boolean\n doubleClickSpeed: number\n\n viewer: Viewer\n mouse: MouseObserver\n controls: MouseControls\n\n position = new Vector2() // Position on page\n prevPosition = new Vector2() // Previous position on page\n down = new Vector2() // Position on page when clicked\n canvasPosition = new Vector2() // Position on dom element\n prevClickCP = new Vector2()\n\n moving = false // Flag indicating if the mouse is moving\n hovering = true // Flag indicating if the mouse is hovering\n scrolled = false // Flag indicating if there was a scolling event since the last mouse move\n lastMoved = Infinity // Timestamp of last mouse move\n which? = 0 // 0: No button; 1: Left button; 2: Middle button; 3: Right button\n buttons? = 0 // 0: No button; 1: Left button; 2: Right button; 4: Middle button\n pressed? = false // Flag indicating if the mouse is pressed down\n altKey = false // Flag indicating if the alt key is pressed\n ctrlKey = false // Flag indicating if the ctrl key is pressed\n metaKey = false // Flag indicating if the meta key is pressed\n shiftKey = false // Flag indicating if the shift key is pressed\n\n doubleClickPending: boolean\n lastClicked: number\n overElement: boolean\n lastTouchDistance: number\n private frameRequest: number\n\n /**\n * @param {Element} domElement - the dom element to observe mouse events in\n * @param {Object} params - parameters object\n * @param {Integer} params.hoverTimeout - timeout in ms until the {@link MouseSignals.hovered}\n * signal is fired, set to -1 to ignore hovering\n * @param {Boolean} params.handleScroll - whether or not to handle scroll events\n * @param {Integer} params.doubleClickSpeed - max time in ms to trigger double click\n */\n constructor (readonly domElement: HTMLCanvasElement, params: MouseParams = {}) {\n this.domElement.style.touchAction = 'none'\n\n this.hoverTimeout = defaults(params.hoverTimeout, 50)\n this.handleScroll = defaults(params.handleScroll, true)\n this.doubleClickSpeed = defaults(params.doubleClickSpeed, 500)\n\n this._listen = this._listen.bind(this)\n this._onMousewheel = this._onMousewheel.bind(this)\n this._onMousemove = this._onMousemove.bind(this)\n this._onMousedown = this._onMousedown.bind(this)\n this._onMouseup = this._onMouseup.bind(this)\n this._onContextmenu = this._onContextmenu.bind(this)\n this._onTouchstart = this._onTouchstart.bind(this)\n this._onTouchend = this._onTouchend.bind(this)\n this._onTouchmove = this._onTouchmove.bind(this)\n\n this._listen()\n\n const opt = { passive: false } // treat as 'passive' so preventDefault can be called\n document.addEventListener('mousewheel', this._onMousewheel, opt)\n document.addEventListener('wheel', this._onMousewheel, opt)\n document.addEventListener('MozMousePixelScroll', this._onMousewheel, opt)\n document.addEventListener('mousemove', this._onMousemove, opt)\n document.addEventListener('mousedown', this._onMousedown, opt)\n document.addEventListener('mouseup', this._onMouseup, opt)\n document.addEventListener('contextmenu', this._onContextmenu, opt)\n document.addEventListener('touchstart', this._onTouchstart, opt)\n document.addEventListener('touchend', this._onTouchend, opt)\n document.addEventListener('touchmove', this._onTouchmove, opt)\n }\n\n get key () {\n let key = 0\n if (this.altKey) key += 1\n if (this.ctrlKey) key += 2\n if (this.metaKey) key += 4\n if (this.shiftKey) key += 8\n return key\n }\n\n setParameters (params: MouseParams = {}) {\n this.hoverTimeout = defaults(params.hoverTimeout, this.hoverTimeout)\n }\n\n /**\n * listen to mouse actions\n * @emits {MouseSignals.clicked} when clicked\n * @emits {MouseSignals.hovered} when hovered\n * @return {undefined}\n */\n _listen () {\n const now = window.performance.now()\n const cp = this.canvasPosition\n if (this.doubleClickPending && now - this.lastClicked > this.doubleClickSpeed) {\n this.doubleClickPending = false\n }\n if (now - this.lastMoved > this.hoverTimeout) {\n this.moving = false\n }\n if (this.scrolled || (!this.moving && !this.hovering)) {\n this.scrolled = false\n if (this.hoverTimeout !== -1 && this.overElement) {\n this.hovering = true\n this.signals.hovered.dispatch(cp.x, cp.y)\n }\n }\n this.frameRequest = window.requestAnimationFrame(this._listen)\n }\n\n /**\n * handle mouse scroll\n * @emits {MouseSignals.scrolled} when scrolled\n * @param {Event} event - mouse event\n * @return {undefined}\n */\n _onMousewheel(event: Optional & { wheelDelta?: number, wheelDeltaY?: number }) {\n if (event.target !== this.domElement || !this.handleScroll) {\n return\n }\n event.preventDefault()\n this._setKeys(event as any)\n\n let delta = 0\n // This has to be written in a particular way to handle old browsers that\n // all send events with different properties set in different ways.\n if ('deltaY' in event && 'deltaMode' in event &&\n event.deltaY !== undefined && event.deltaMode !== undefined) {\n // all modern browsers, using WheelEvent; deltaY + down (toward user)\n if (event.deltaMode === WheelEvent.DOM_DELTA_PIXEL)\n // everything except Firefox: normally 100 per wheel click\n delta = -event.deltaY * (2.5 / 100.0)\n else if (event.deltaMode === WheelEvent.DOM_DELTA_LINE)\n // Firefox in line mode, normally 3 per wheel click\n delta = -event.deltaY * (2.5 / 3.0)\n else // page mode: 1 per wheel click\n delta = -event.deltaY * 2.5\n } else if ('deltaY' in event && !('detail' in event)) {\n // Old Firefox or IE 11: deltaY but no deltaMode; treat as pixels\n delta = -event.deltaY * (2.5 / 100.0)\n } else if (event.wheelDelta !== undefined) {\n delta = -event.wheelDelta * (2.5 / 100)\n } else if (event.wheelDeltaY !== undefined) {\n delta = -event.wheelDeltaY * (2.5 / 100)\n } else if (event.detail !== undefined){\n // Old Firefox, MouseWheelEvent\n delta = -event.detail / 3\n }\n this.signals.scrolled.dispatch(delta)\n\n setTimeout(() => {\n this.scrolled = true\n }, this.hoverTimeout)\n }\n\n /**\n * handle mouse move\n * @emits {MouseSignals.moved} when moved\n * @emits {MouseSignals.dragged} when dragged\n * @param {Event} event - mouse event\n * @return {undefined}\n */\n _onMousemove (event: MouseEvent) {\n if (event.target === this.domElement) {\n event.preventDefault()\n this.overElement = true\n } else {\n this.overElement = false\n }\n this._setKeys(event)\n this.moving = true\n this.hovering = false\n this.lastMoved = window.performance.now()\n this.prevPosition.copy(this.position)\n this.position.set(event.clientX, event.clientY)\n this._setCanvasPosition(event)\n const dx = this.prevPosition.x - this.position.x\n const dy = this.prevPosition.y - this.position.y\n this.signals.moved.dispatch(dx, dy)\n if (this.pressed) {\n this.signals.dragged.dispatch(dx, dy)\n }\n }\n\n _onMousedown (event: MouseEvent) {\n if (event.target !== this.domElement) {\n return\n }\n event.preventDefault()\n this._setKeys(event)\n this.moving = false\n this.hovering = false\n this.down.set(event.clientX, event.clientY)\n this.position.set(event.clientX, event.clientY)\n this.which = event.which\n this.buttons = getMouseButtons(event)\n this.pressed = true\n this._setCanvasPosition(event)\n }\n\n /**\n * handle mouse up\n * @emits {MouseSignals.doubleClicked} when double clicked\n * @emits {MouseSignals.dropped} when dropped\n * @param {Event} event - mouse event\n * @return {undefined}\n */\n _onMouseup (event: MouseEvent) {\n if (event.target === this.domElement) {\n event.preventDefault()\n }\n this._setKeys(event)\n const cp = this.canvasPosition\n if (this._distance() < 4) {\n this.lastClicked = window.performance.now()\n if (this.doubleClickPending && this.prevClickCP.distanceTo(cp) < 4) {\n this.signals.doubleClicked.dispatch(cp.x, cp.y)\n this.doubleClickPending = false\n }\n this.signals.clicked.dispatch(cp.x, cp.y)\n this.doubleClickPending = true\n this.prevClickCP.copy(cp)\n }\n this.which = undefined\n this.buttons = undefined\n this.pressed = undefined\n // if (this._distance() > 3 || event.which === RightMouseButton) {\n // this.signals.dropped.dispatch();\n // }\n }\n\n _onContextmenu (event: MouseEvent) {\n if (event.target === this.domElement) {\n event.preventDefault()\n }\n }\n\n _onTouchstart (event: TouchEvent) {\n if (event.target !== this.domElement) {\n return\n }\n event.preventDefault()\n this.pressed = true\n switch (event.touches.length) {\n case 1: {\n this.moving = false\n this.hovering = false\n this.down.set(\n event.touches[ 0 ].pageX,\n event.touches[ 0 ].pageY\n )\n this.position.set(\n event.touches[ 0 ].pageX,\n event.touches[ 0 ].pageY\n )\n this._setCanvasPosition(event.touches[ 0 ])\n break\n }\n\n case 2: {\n this.down.set(\n (event.touches[ 0 ].pageX + event.touches[ 1 ].pageX) / 2,\n (event.touches[ 0 ].pageY + event.touches[ 1 ].pageY) / 2\n )\n this.position.set(\n (event.touches[ 0 ].pageX + event.touches[ 1 ].pageX) / 2,\n (event.touches[ 0 ].pageY + event.touches[ 1 ].pageY) / 2\n )\n this.lastTouchDistance = getTouchDistance(event)\n }\n }\n }\n\n _onTouchend (event: TouchEvent) {\n if (event.target === this.domElement) {\n event.preventDefault()\n }\n this.which = undefined\n this.buttons = undefined\n this.pressed = undefined\n }\n\n _onTouchmove (event: TouchEvent) {\n if (event.target === this.domElement) {\n event.preventDefault()\n this.overElement = true\n } else {\n this.overElement = false\n }\n switch (event.touches.length) {\n case 1: {\n this._setKeys(event)\n this.which = LeftMouseButton\n this.buttons = 1\n this.moving = true\n this.hovering = false\n this.lastMoved = window.performance.now()\n this.prevPosition.copy(this.position)\n this.position.set(\n event.touches[ 0 ].pageX,\n event.touches[ 0 ].pageY\n )\n this._setCanvasPosition(event.touches[ 0 ])\n const dx = this.prevPosition.x - this.position.x\n const dy = this.prevPosition.y - this.position.y\n this.signals.moved.dispatch(dx, dy)\n if (this.pressed) {\n this.signals.dragged.dispatch(dx, dy)\n }\n break\n }\n\n case 2: {\n const touchDistance = getTouchDistance(event)\n const delta = touchDistance - this.lastTouchDistance\n this.lastTouchDistance = touchDistance\n this.prevPosition.copy(this.position)\n this.position.set(\n (event.touches[ 0 ].pageX + event.touches[ 1 ].pageX) / 2,\n (event.touches[ 0 ].pageY + event.touches[ 1 ].pageY) / 2\n )\n if (Math.abs(delta) > 2 && this.handleScroll &&\n this.position.distanceTo(this.prevPosition) < 2\n ) {\n this.which = 0\n this.buttons = 0\n this.signals.scrolled.dispatch(delta / 2)\n } else {\n this.which = RightMouseButton\n this.buttons = 2\n const dx = this.prevPosition.x - this.position.x\n const dy = this.prevPosition.y - this.position.y\n this.signals.moved.dispatch(dx, dy)\n if (this.pressed) {\n this.signals.dragged.dispatch(dx, dy)\n }\n }\n }\n }\n }\n\n _distance () {\n return this.position.distanceTo(this.down)\n }\n\n _setCanvasPosition (event: any) { // TODO\n const box = this.domElement.getBoundingClientRect()\n let offsetX, offsetY;\n if ('clientX' in event && 'clientY' in event) {\n offsetX = event.clientX - box.left\n offsetY = event.clientY - box.top\n } else {\n offsetX = event.offsetX\n offsetY = event.offsetY\n }\n this.canvasPosition.set(offsetX, box.height - offsetY)\n }\n\n _setKeys (event: MouseEvent|TouchEvent) {\n this.altKey = event.altKey\n this.ctrlKey = event.ctrlKey\n this.metaKey = event.metaKey\n this.shiftKey = event.shiftKey\n }\n\n dispose () {\n document.removeEventListener('mousewheel', this._onMousewheel)\n document.removeEventListener('wheel', this._onMousewheel)\n document.removeEventListener('MozMousePixelScroll', this._onMousewheel)\n document.removeEventListener('mousemove', this._onMousemove)\n document.removeEventListener('mousedown', this._onMousedown)\n document.removeEventListener('mouseup', this._onMouseup)\n document.removeEventListener('contextmenu', this._onContextmenu)\n document.removeEventListener('touchstart', this._onTouchstart)\n document.removeEventListener('touchend', this._onTouchend)\n document.removeEventListener('touchmove', this._onTouchmove)\n window.cancelAnimationFrame(this.frameRequest)\n }\n}\n\nexport default MouseObserver\n","/**\n * @file Trackball Controls\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Matrix4, Quaternion } from 'three'\n\nimport { defaults } from '../utils'\nimport Stage from '../stage/stage'\nimport MouseObserver from '../stage/mouse-observer'\nimport Viewer from '../viewer/viewer'\nimport ViewerControls from './viewer-controls'\nimport AtomProxy from '../proxy/atom-proxy';\nimport Component from '../component/component';\n\nconst tmpRotateXMatrix = new Matrix4()\nconst tmpRotateYMatrix = new Matrix4()\nconst tmpRotateZMatrix = new Matrix4()\nconst tmpRotateMatrix = new Matrix4()\nconst tmpRotateCameraMatrix = new Matrix4()\nconst tmpRotateVector = new Vector3()\nconst tmpRotateQuaternion = new Quaternion()\nconst tmpRotateQuaternion2 = new Quaternion()\nconst tmpPanMatrix = new Matrix4()\nconst tmpPanVector = new Vector3()\nconst tmpAtomVector = new Vector3()\n\nexport interface TrackballControlsParams {\n rotateSpeed?: number\n zoomSpeed?: number\n panSpeed?: number\n}\n\n/**\n * Trackball controls\n */\nclass TrackballControls {\n viewer: Viewer\n mouse: MouseObserver\n controls: ViewerControls\n\n rotateSpeed: number\n zoomSpeed: number\n panSpeed: number\n\n constructor (readonly stage: Stage, params: TrackballControlsParams = {}) {\n this.rotateSpeed = defaults(params.rotateSpeed, 2.0)\n this.zoomSpeed = defaults(params.zoomSpeed, 1.2)\n this.panSpeed = defaults(params.panSpeed, 1.0)\n\n this.viewer = stage.viewer\n this.mouse = stage.mouseObserver\n this.controls = stage.viewerControls\n }\n\n get component (): Component|undefined {\n return this.stage.transformComponent\n }\n\n get atom (): AtomProxy|undefined {\n return this.stage.transformAtom\n }\n\n private _setPanVector (x: number, y: number, z = 0) {\n const scaleFactor = this.controls.getCanvasScaleFactor(z)\n tmpPanVector.set(x, y, 0)\n tmpPanVector.multiplyScalar(this.panSpeed * scaleFactor)\n }\n\n private _getRotateXY (x: number, y: number) {\n return [\n this.rotateSpeed * -x * 0.01,\n this.rotateSpeed * y * 0.01\n ]\n }\n\n private _getCameraRotation(m: Matrix4) {\n m.extractRotation(this.viewer.camera.matrixWorld)\n m.multiply(tmpRotateYMatrix.makeRotationY(Math.PI))\n\n return m\n }\n\n private _transformPanVector () {\n if (!this.component) return\n\n // Adjust for component and scene rotation\n tmpPanMatrix.extractRotation(this.component.transform)\n tmpPanMatrix.premultiply(this.viewer.rotationGroup.matrix)\n tmpPanMatrix.invert()\n\n // Adjust for camera rotation\n tmpPanMatrix.multiply(this._getCameraRotation(tmpRotateMatrix))\n\n tmpPanVector.applyMatrix4(tmpPanMatrix)\n }\n\n zoom (delta: number) {\n this.controls.zoom(this.zoomSpeed * delta * 0.02)\n }\n\n pan (x: number, y: number) {\n this._setPanVector(x, y)\n\n // Adjust for scene rotation\n tmpPanMatrix.copy(this.viewer.rotationGroup.matrix).invert()\n\n // Adjust for camera rotation\n tmpPanMatrix.multiply(this._getCameraRotation(tmpRotateMatrix))\n\n tmpPanVector.applyMatrix4(tmpPanMatrix)\n this.controls.translate(tmpPanVector)\n }\n\n panComponent (x: number, y: number) {\n if (!this.component) return\n\n this._setPanVector(x, y)\n this._transformPanVector()\n\n this.component.position.add(tmpPanVector)\n this.component.updateMatrix()\n }\n\n panAtom (x: number, y: number) {\n if (!this.atom || !this.component) return\n\n this.atom.positionToVector3(tmpAtomVector)\n tmpAtomVector.add(this.viewer.translationGroup.position)\n tmpAtomVector.applyMatrix4(this.viewer.rotationGroup.matrix)\n\n this._setPanVector(x, y, tmpAtomVector.z)\n this._transformPanVector()\n\n this.atom.positionAdd(tmpPanVector)\n this.component.updateRepresentations({ 'position': true })\n }\n\n rotate (x: number, y: number) {\n const [ dx, dy ] = this._getRotateXY(x, y)\n\n // rotate around screen X then screen Y\n this._getCameraRotation(tmpRotateMatrix)\n tmpRotateVector.set(1, 0, 0) // X axis\n tmpRotateVector.applyMatrix4(tmpRotateMatrix) // screen X\n tmpRotateQuaternion.setFromAxisAngle(tmpRotateVector, dy)\n\n tmpRotateVector.set(0, 1, 0) // Y axis\n tmpRotateVector.applyMatrix4(tmpRotateMatrix) // screen Y\n tmpRotateQuaternion2.setFromAxisAngle(tmpRotateVector, dx)\n\n tmpRotateQuaternion.multiply(tmpRotateQuaternion2)\n tmpRotateMatrix.makeRotationFromQuaternion(tmpRotateQuaternion)\n this.controls.applyMatrix(tmpRotateMatrix)\n }\n\n zRotate (x: number, y: number) {\n const dz = this.rotateSpeed * ((-x + y) / -2) * 0.01\n\n tmpRotateZMatrix.makeRotationZ(dz)\n this.controls.applyMatrix(tmpRotateZMatrix)\n }\n\n rotateComponent (x: number, y: number) {\n if (!this.component) return\n\n const [ dx, dy ] = this._getRotateXY(x, y)\n\n this._getCameraRotation(tmpRotateCameraMatrix)\n\n tmpRotateMatrix.extractRotation(this.component.transform)\n tmpRotateMatrix.premultiply(this.viewer.rotationGroup.matrix)\n tmpRotateMatrix.invert()\n tmpRotateMatrix.premultiply(tmpRotateCameraMatrix)\n\n tmpRotateVector.set(1, 0, 0)\n tmpRotateVector.applyMatrix4(tmpRotateMatrix)\n tmpRotateXMatrix.makeRotationAxis(tmpRotateVector, dy)\n\n tmpRotateVector.set(0, 1, 0)\n tmpRotateVector.applyMatrix4(tmpRotateMatrix)\n tmpRotateYMatrix.makeRotationAxis(tmpRotateVector, dx)\n\n tmpRotateXMatrix.multiply(tmpRotateYMatrix)\n tmpRotateQuaternion.setFromRotationMatrix(tmpRotateXMatrix)\n this.component.quaternion.premultiply(tmpRotateQuaternion)\n this.component.quaternion.normalize()\n this.component.updateMatrix()\n }\n}\n\nexport default TrackballControls\n","/**\n * @file Picking Proxy\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Matrix4, Vector2 } from 'three'\n\nimport Stage from '../stage/stage'\nimport StructureComponent from '../component/structure-component'\nimport MouseObserver from '../stage/mouse-observer'\nimport { Picker } from '../utils/picker'\nimport ViewerControls from './viewer-controls'\nimport Shape from '../geometry/shape'\nimport Structure from '../structure/structure'\nimport BondProxy from '../proxy/bond-proxy'\nimport AtomProxy from '../proxy/atom-proxy'\nimport Surface from '../surface/surface'\nimport Volume from '../surface/volume'\nimport Unitcell from '../symmetry/unitcell'\nimport Component from '../component/component';\n\nconst tmpVec = new Vector3()\n\nexport interface ShapePrimitive {\n name: string\n shape: Shape\n}\n\nfunction closer (x: Vector3, a: Vector3, b: Vector3) {\n return x.distanceTo(a) < x.distanceTo(b)\n}\n\n/**\n * Picking data object.\n * @typedef {Object} PickingData - picking data\n * @property {Number} [pid] - picking id\n * @property {Object} [instance] - instance data\n * @property {Integer} instance.id - instance id\n * @property {String|Integer} instance.name - instance name\n * @property {Matrix4} instance.matrix - transformation matrix of the instance\n * @property {Picker} [picker] - picker object\n */\n\nexport interface InstanceData {\n id: number\n name: number|string\n matrix: Matrix4\n}\n\nexport interface PickingData {\n pid: number\n instance: InstanceData\n picker: Picker\n}\n\n/**\n * Picking proxy class.\n */\nclass PickingProxy {\n pid: number\n picker: Picker\n instance: InstanceData\n controls: ViewerControls\n mouse: MouseObserver\n\n /**\n * Create picking proxy object\n * @param {PickingData} pickingData - picking data\n * @param {Stage} stage - stage object\n */\n constructor (pickingData: PickingData, readonly stage: Stage) {\n this.pid = pickingData.pid\n this.picker = pickingData.picker\n\n /**\n * @type {Object}\n */\n this.instance = pickingData.instance\n\n /**\n * @type {Stage}\n */\n this.stage = stage\n /**\n * @type {ViewerControls}\n */\n this.controls = stage.viewerControls\n /**\n * @type {MouseObserver}\n */\n this.mouse = stage.mouseObserver\n }\n\n /**\n * Kind of the picked data\n * @type {String}\n */\n get type () { return this.picker.type }\n\n /**\n * If the `alt` key was pressed\n * @type {Boolean}\n */\n get altKey () { return this.mouse.altKey }\n /**\n * If the `ctrl` key was pressed\n * @type {Boolean}\n */\n get ctrlKey () { return this.mouse.ctrlKey }\n /**\n * If the `meta` key was pressed\n * @type {Boolean}\n */\n get metaKey () { return this.mouse.metaKey }\n /**\n * If the `shift` key was pressed\n * @type {Boolean}\n */\n get shiftKey () { return this.mouse.shiftKey }\n\n /**\n * Position of the mouse on the canvas\n * @type {Vector2}\n */\n get canvasPosition (): Vector2 { return this.mouse.canvasPosition }\n\n /**\n * The component the picked data is part of\n * @type {Component}\n */\n get component (): Component {\n return this.stage.getComponentsByObject(this.picker.data as any).list[ 0 ] // TODO\n }\n\n /**\n * The picked object data\n * @type {Object}\n */\n get object () {\n return this.picker.getObject(this.pid)\n }\n\n /**\n * The 3d position in the scene of the picked object\n * @type {Vector3}\n */\n get position () {\n return this.picker.getPosition(this.pid, this.instance, this.component)\n }\n\n /**\n * The atom of a picked bond that is closest to the mouse\n * @type {AtomProxy}\n */\n get closestBondAtom (): AtomProxy|undefined {\n if (this.type !== 'bond' || !this.bond) return undefined\n\n const bond = this.bond\n const controls = this.controls\n const cp = this.canvasPosition\n\n const v1 = bond.atom1.positionToVector3()\n const v2 = bond.atom2.positionToVector3()\n\n v1.applyMatrix4(this.component.matrix)\n v2.applyMatrix4(this.component.matrix)\n\n const acp1 = controls.getPositionOnCanvas(v1)\n const acp2 = controls.getPositionOnCanvas(v2)\n\n return closer(cp as any, acp1, acp2) ? bond.atom1 : bond.atom2\n }\n\n /**\n * Close-by atom\n * @type {AtomProxy}\n */\n get closeAtom (): AtomProxy|undefined {\n const cp = this.canvasPosition\n const ca = this.closestBondAtom\n if (!ca) return undefined\n\n const v = ca.positionToVector3().applyMatrix4(this.component.matrix)\n\n const acp = this.controls.getPositionOnCanvas(v)\n\n ca.positionToVector3(tmpVec)\n if (this.instance) tmpVec.applyMatrix4(this.instance.matrix)\n tmpVec.applyMatrix4(this.component.matrix)\n const viewer = this.controls.viewer\n tmpVec.add(viewer.translationGroup.position)\n tmpVec.applyMatrix4(viewer.rotationGroup.matrix)\n\n const scaleFactor = this.controls.getCanvasScaleFactor(tmpVec.z)\n const sc = this.component as StructureComponent\n const radius = sc.getMaxRepresentationRadius(ca.index)\n //console.log(scaleFactor, cp.distanceTo(acp), radius/scaleFactor, radius)\n\n if (cp.distanceTo(acp) <= radius/scaleFactor) {\n return ca\n } else {\n return undefined\n }\n }\n\n /**\n * @type {Object}\n */\n get arrow () { return this._objectIfType('arrow') as ShapePrimitive }\n /**\n * @type {AtomProxy}\n */\n get atom () { return this._objectIfType('atom') as AtomProxy }\n /**\n * @type {Object}\n */\n get axes () { return this._objectIfType('axes') }\n /**\n * @type {BondProxy}\n */\n get bond () { return this._objectIfType('bond') as BondProxy }\n /**\n * @type {Object}\n */\n get box () { return this._objectIfType('box') as ShapePrimitive }\n /**\n * @type {Object}\n */\n get cone () { return this._objectIfType('cone') as ShapePrimitive }\n /**\n * @type {Object}\n */\n get clash () { return this._objectIfType('clash') as { clash: { sele1: string, sele2: string } } }\n /**\n * @type {BondProxy}\n */\n get contact () { return this._objectIfType('contact') as { type: string, atom1: AtomProxy, atom2: AtomProxy } }\n /**\n * @type {Object}\n */\n get cylinder () { return this._objectIfType('cylinder') as ShapePrimitive }\n /**\n * @type {BondProxy}\n */\n get distance () { return this._objectIfType('distance') as BondProxy }\n /**\n * @type {Object}\n */\n get ellipsoid () { return this._objectIfType('ellipsoid') as ShapePrimitive }\n /**\n * @type {Object}\n */\n get octahedron () { return this._objectIfType('octahedron') as ShapePrimitive }\n /**\n * @type {Object}\n */\n get point () { return this._objectIfType('point') as ShapePrimitive }\n /**\n * @type {Object}\n */\n get mesh () { return this._objectIfType('mesh') as { name: string, shape: Shape, serial: number } }\n /**\n * @type {Object}\n */\n get slice () { return this._objectIfType('slice') as { volume: Volume, value: number } }\n /**\n * @type {Object}\n */\n get sphere () { return this._objectIfType('sphere') as ShapePrimitive }\n /**\n * @type {Object}\n */\n get tetrahedron () { return this._objectIfType('tetrahedron') as ShapePrimitive }\n /**\n * @type {Object}\n */\n get torus () { return this._objectIfType('torus') as ShapePrimitive }\n /**\n * @type {Object}\n */\n get surface () { return this._objectIfType('surface') as { surface: Surface, index: number } }\n /**\n * @type {Object}\n */\n get unitcell () { return this._objectIfType('unitcell') as { unitcell: Unitcell, structure: Structure } }\n /**\n * @type {Object}\n */\n get unknown () { return this._objectIfType('unknown') }\n /**\n * @type {Object}\n */\n get volume () { return this._objectIfType('volume') as { volume: Volume, value: number } }\n /**\n * @type {Object}\n */\n get wideline () { return this._objectIfType('wideline') as ShapePrimitive }\n\n _objectIfType (type: string) {\n return this.type === type ? this.object : undefined\n }\n\n getLabel () {\n const atom = this.atom || this.closeAtom\n let msg = 'nothing'\n if (this.arrow) {\n msg = this.arrow.name\n } else if (atom) {\n msg = `atom: ${atom.qualifiedName()} (${atom.structure.name})`\n } else if (this.axes) {\n msg = 'axes'\n } else if (this.bond) {\n msg = `bond: ${this.bond.atom1.qualifiedName()} - ${this.bond.atom2.qualifiedName()} (${this.bond.structure.name})`\n } else if (this.box) {\n msg = this.box.name\n } else if (this.cone) {\n msg = this.cone.name\n } else if (this.clash) {\n msg = `clash: ${this.clash.clash.sele1} - ${this.clash.clash.sele2}`\n } else if (this.contact) {\n msg = `${this.contact.type}: ${this.contact.atom1.qualifiedName()} - ${this.contact.atom2.qualifiedName()} (${this.contact.atom1.structure.name})`\n } else if (this.cylinder) {\n msg = this.cylinder.name\n } else if (this.distance) {\n msg = `distance: ${this.distance.atom1.qualifiedName()} - ${this.distance.atom2.qualifiedName()} (${this.distance.structure.name})`\n } else if (this.ellipsoid) {\n msg = this.ellipsoid.name\n } else if (this.octahedron) {\n msg = this.octahedron.name\n } else if (this.point) {\n msg = this.point.name\n } else if (this.mesh) {\n msg = `mesh: ${this.mesh.name || this.mesh.serial} (${this.mesh.shape.name})`\n } else if (this.slice) {\n msg = `slice: ${this.slice.value.toPrecision(3)} (${this.slice.volume.name})`\n } else if (this.sphere) {\n msg = this.sphere.name\n } else if (this.surface) {\n msg = `surface: ${this.surface.surface.name}`\n } else if (this.tetrahedron) {\n msg = this.tetrahedron.name\n } else if (this.torus) {\n msg = this.torus.name\n } else if (this.unitcell) {\n msg = `unitcell: ${this.unitcell.unitcell.spacegroup} (${this.unitcell.structure.name})`\n } else if (this.unknown) {\n msg = 'unknown'\n } else if (this.volume) {\n msg = `volume: ${this.volume.value.toPrecision(3)} (${this.volume.volume.name})`\n } else if (this.wideline) {\n msg = this.wideline.name\n }\n return msg\n }\n}\n\nexport default PickingProxy\n","/**\n * @file Picking Controls\n * @author Alexander Rose \n * @private\n */\n\nimport PickingProxy from './picking-proxy'\nimport Stage from '../stage/stage'\nimport Viewer from '../viewer/viewer'\n\n/**\n * Picking controls\n */\nclass PickingControls {\n viewer: Viewer\n\n constructor (readonly stage: Stage) {\n this.viewer = stage.viewer\n }\n\n /**\n * get picking data\n * @param {Number} x - canvas x coordinate\n * @param {Number} y - canvas y coordinate\n * @return {PickingProxy|undefined} picking proxy\n */\n pick (x: number, y: number) {\n const pickingData = this.viewer.pick(x, y)\n\n if (pickingData.picker &&\n pickingData.picker.type !== 'ignore' &&\n pickingData.pid !== undefined\n ) {\n const pickerArray = pickingData.picker.array\n if (pickerArray && pickingData.pid >= pickerArray.length) {\n console.error('pid >= picker.array.length')\n } else {\n return new PickingProxy(pickingData, this.stage)\n }\n }\n }\n}\n\nexport default PickingControls\n","/**\n * @file Viewer Controls\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector2, Vector3, Matrix4, Quaternion, OrthographicCamera } from 'three'\nimport * as signalsWrapper from 'signals'\n\nimport {\n ensureVector2, ensureVector3, ensureMatrix4, ensureQuaternion\n} from '../utils'\nimport { degToRad } from '../math/math-utils'\nimport Stage from '../stage/stage'\nimport Viewer from '../viewer/viewer'\n\n/**\n * Orientation matrix, a 4x4 transformation matrix with rotation part\n * used for scene rotation, scale part for scene camera distance and\n * position part for scene translation\n * @typedef {Matrix4} OrientationMatrix - orientation matrix\n */\n\nconst tmpQ = new Quaternion()\nconst tmpP = new Vector3()\nconst tmpS = new Vector3()\n\nconst tmpCanvasVector = new Vector3()\nconst tmpScaleVector = new Vector3()\nconst tmpRotateMatrix = new Matrix4()\nconst tmpRotateVector = new Vector3()\nconst tmpAlignMatrix = new Matrix4()\n\n/**\n * Viewer controls\n */\nclass ViewerControls {\n signals = {\n changed: new signalsWrapper.Signal()\n }\n\n viewer: Viewer\n\n /**\n * @param {Stage} stage - the stage object\n */\n constructor (readonly stage: Stage) {\n this.viewer = stage.viewer\n }\n\n /**\n * scene center position\n * @type {Vector3}\n */\n get position () {\n return this.viewer.translationGroup.position\n }\n\n /**\n * scene rotation\n * @type {Quaternion}\n */\n get rotation () {\n return this.viewer.rotationGroup.quaternion\n }\n\n /**\n * Trigger render and emit changed event\n * @emits {ViewerControls.signals.changed}\n * @return {undefined}\n */\n changed () {\n this.viewer.requestRender()\n this.signals.changed.dispatch()\n }\n\n getPositionOnCanvas (position: Vector3, optionalTarget?: Vector2) {\n const canvasPosition = ensureVector2(optionalTarget)\n const viewer = this.viewer\n\n tmpCanvasVector.copy(position)\n .add(viewer.translationGroup.position)\n .applyMatrix4(viewer.rotationGroup.matrix)\n .project(viewer.camera)\n\n return canvasPosition.set(\n (tmpCanvasVector.x + 1) * viewer.width / 2,\n (tmpCanvasVector.y + 1) * viewer.height / 2\n )\n }\n\n getCanvasScaleFactor (z = 0) {\n const camera = this.viewer.camera\n if (camera instanceof OrthographicCamera) {\n return 1 / camera.zoom\n } else {\n z = Math.abs(z)\n z += this.getCameraDistance()\n const fov = degToRad(camera.fov)\n const unitHeight = 2.0 * z * Math.tan(fov / 2)\n return unitHeight / this.viewer.height\n }\n }\n\n /**\n * get scene orientation\n * @param {Matrix4} optionalTarget - pre-allocated target matrix\n * @return {OrientationMatrix} scene orientation\n */\n getOrientation (optionalTarget?: Matrix4) {\n const m = ensureMatrix4(optionalTarget)\n\n m.copy(this.viewer.rotationGroup.matrix)\n const z = this.getCameraDistance()\n m.scale(tmpScaleVector.set(z, z, z))\n m.setPosition(this.viewer.translationGroup.position)\n\n return m\n }\n\n /**\n * set scene orientation\n * @param {OrientationMatrix|Array} orientation - scene orientation\n * @return {undefined}\n */\n orient (orientation?: Matrix4) {\n ensureMatrix4(orientation).decompose(tmpP, tmpQ, tmpS)\n\n const v = this.viewer\n v.rotationGroup.setRotationFromQuaternion(tmpQ)\n v.translationGroup.position.copy(tmpP)\n v.cameraDistance = tmpS.z\n v.updateZoom()\n this.changed()\n }\n\n /**\n * translate scene\n * @param {Vector3|Array} vector - translation vector\n * @return {undefined}\n */\n translate (vector: Vector3|number[]) {\n this.viewer.translationGroup.position\n .add(ensureVector3(vector))\n this.changed()\n }\n\n /**\n * center scene\n * @param {Vector3|Array} position - center position\n * @return {undefined}\n */\n center (position: Vector3|number[]) {\n this.viewer.translationGroup.position\n .copy(ensureVector3(position)).negate()\n this.changed()\n }\n\n /**\n * \"zoom\" scene by moving camera closer to origin\n * @param {Number} delta - zoom change\n * @return {undefined}\n */\n zoom (delta: number) {\n this.distance(this.getCameraDistance() * (1 - delta))\n }\n\n /**\n * get camera distance\n */\n getCameraDistance(): number {\n return this.viewer.cameraDistance\n }\n\n /**\n * camera distance\n * @param {Number} z - distance\n * @return {undefined}\n */\n distance (distance: number) {\n // Math.abs because distance used to be \"z\", normally negative.\n // Math.max to prevent us from getting _too_ close.\n this.viewer.cameraDistance = Math.max(Math.abs(distance), 0.2)\n this.viewer.updateZoom()\n this.changed()\n }\n\n /**\n * spin scene on axis\n * @param {Vector3|Array} axis - rotation axis\n * @param {Number} angle - amount to spin\n * @return {undefined}\n */\n spin (axis: Vector3|number[], angle: number) {\n tmpRotateMatrix.copy(this.viewer.rotationGroup.matrix).invert()\n tmpRotateVector\n .copy(ensureVector3(axis)).applyMatrix4(tmpRotateMatrix)\n\n this.viewer.rotationGroup.rotateOnAxis(tmpRotateVector, angle)\n this.changed()\n }\n\n /**\n * rotate scene\n * @param {Quaternion|Array} quaternion - rotation quaternion\n * @return {undefined}\n */\n rotate (quaternion: Quaternion|number[]) {\n this.viewer.rotationGroup\n .setRotationFromQuaternion(ensureQuaternion(quaternion))\n this.changed()\n }\n\n /**\n * align scene to basis matrix\n * @param {Matrix4|Array} basis - basis matrix\n * @return {undefined}\n */\n align (basis: Matrix4|number[]) {\n tmpAlignMatrix.copy(ensureMatrix4(basis)).invert()\n\n this.viewer.rotationGroup.setRotationFromMatrix(tmpAlignMatrix)\n this.changed()\n }\n\n /**\n * apply rotation matrix to scene\n * @param {Matrix4|Array} matrix - rotation matrix\n * @return {undefined}\n */\n applyMatrix (matrix: Matrix4|number[]) {\n this.viewer.rotationGroup.applyMatrix4(ensureMatrix4(matrix))\n this.changed()\n }\n}\n\nexport default ViewerControls\n","/**\n * @file Animation\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Quaternion } from 'three'\n\nimport { defaults, ensureVector3, ensureQuaternion } from '../utils'\nimport { lerp, smoothstep } from '../math/math-utils'\nimport ViewerControls from '../controls/viewer-controls'\nimport Stats from '../viewer/stats'\n\n/**\n * Animation. Base animation class.\n * @interface\n */\nabstract class Animation {\n duration: number\n controls: ViewerControls\n\n alpha: number\n startTime: number\n\n pausedTime = -1\n elapsedDuration = 0\n pausedDuration = 0\n ignoreGlobalToggle = false\n\n private _paused = false\n private _resolveList: Function[] = []\n private _hold: boolean\n\n constructor (duration: number|undefined, controls: ViewerControls, ...args: any[]) {\n this.duration = defaults(duration, 1000)\n this.controls = controls\n\n this.startTime = window.performance.now()\n\n this._init(...args)\n }\n\n /**\n * True when animation has finished\n */\n get done () {\n return this.alpha === 1\n }\n\n /**\n * True when animation is paused\n */\n get paused () {\n return this._paused\n }\n\n /**\n * init animation\n */\n abstract _init (...args: any[]): void\n\n /**\n * called on every tick\n */\n abstract _tick (stats?: Stats): void\n\n tick (stats: Stats) {\n if (this._paused) return\n\n this.elapsedDuration = stats.currentTime - this.startTime - this.pausedDuration\n\n if (this.duration === 0) {\n this.alpha = 1\n } else {\n this.alpha = smoothstep(0, 1, this.elapsedDuration / this.duration)\n }\n\n this._tick(stats)\n\n if (this.done) {\n this._resolveList.forEach(resolve => resolve())\n }\n\n return this.done\n }\n\n /**\n * Pause animation\n * @param {boolean} [hold] - put animation on a hold which\n * must be release before it can be resumed\n */\n pause (hold?: boolean) {\n if (hold) this._hold = true\n\n if (this.pausedTime === -1) {\n this.pausedTime = window.performance.now()\n }\n this._paused = true\n }\n\n /**\n * Resume animation\n * @param {Boolean} [releaseHold] - release a hold on the animation\n */\n resume (releaseHold?: boolean) {\n if (!releaseHold && this._hold) return\n\n this.pausedDuration += window.performance.now() - this.pausedTime\n this._paused = false\n this._hold = false\n this.pausedTime = -1\n }\n\n /**\n * Toggle animation\n */\n toggle () {\n if (this._paused) {\n this.resume()\n } else {\n this.pause()\n }\n }\n\n /**\n * Promise-like interface\n */\n then (callback: Function) {\n let p: Promise\n\n if (this.done) {\n p = Promise.resolve()\n } else {\n p = new Promise(resolve => this._resolveList.push(resolve))\n }\n\n return p.then(callback as any)\n }\n}\n\nexport default Animation\n\n/**\n * Spin animation. Spin around an axis.\n */\nexport class SpinAnimation extends Animation {\n axis: Vector3\n angle: number\n\n constructor (duration: number|undefined, controls: ViewerControls, ...args: any[]) {\n super(defaults(duration, Infinity), controls, ...args)\n }\n\n _init (axis: number[]|Vector3, angle: number) {\n if (Array.isArray(axis)) {\n this.axis = new Vector3().fromArray(axis)\n } else {\n this.axis = defaults(axis, new Vector3(0, 1, 0))\n }\n this.angle = defaults(angle, 0.01)\n }\n\n _tick (stats: Stats) {\n if (!this.axis || !this.angle) return\n\n this.controls.spin(\n this.axis, this.angle * stats.lastDuration / 16\n )\n }\n}\n\n/**\n * Rock animation. Rock around an axis.\n */\nexport class RockAnimation extends Animation {\n axis: Vector3\n angleStep: number\n angleEnd: number\n angleSum = 0\n direction = 1\n\n constructor (duration: number|undefined, controls: ViewerControls, ...args: any[]) {\n super(defaults(duration, Infinity), controls, ...args)\n }\n\n _init (axis: number[]|Vector3, angleStep: number, angleEnd: number) {\n if (Array.isArray(axis)) {\n this.axis = new Vector3().fromArray(axis)\n } else {\n this.axis = defaults(axis, new Vector3(0, 1, 0))\n }\n this.angleStep = defaults(angleStep, 0.01)\n this.angleEnd = defaults(angleEnd, 0.2)\n }\n\n _tick (stats: Stats) {\n if (!this.axis || !this.angleStep || !this.angleEnd) return\n\n const alpha = smoothstep(\n 0, 1, Math.abs(this.angleSum) / this.angleEnd\n )\n const angle = this.angleStep * this.direction * (1.1 - alpha)\n\n this.controls.spin(\n this.axis, angle * stats.lastDuration / 16\n )\n\n this.angleSum += this.angleStep\n\n if (this.angleSum >= this.angleEnd) {\n this.direction *= -1\n this.angleSum = -this.angleEnd\n }\n }\n}\n\n/**\n * Move animation. Move from one position to another.\n */\nexport class MoveAnimation extends Animation {\n moveFrom: Vector3\n moveTo: Vector3\n\n _init (moveFrom: number[]|Vector3, moveTo: number[]|Vector3) {\n this.moveFrom = ensureVector3(defaults(moveFrom, new Vector3()))\n this.moveTo = ensureVector3(defaults(moveTo, new Vector3()))\n }\n\n _tick (/* stats */) {\n this.controls.position.lerpVectors(\n this.moveFrom, this.moveTo, this.alpha\n ).negate()\n this.controls.changed()\n }\n}\n\n/**\n * Zoom animation. Gradually change the zoom level.\n */\nexport class ZoomAnimation extends Animation {\n zoomFrom: number\n zoomTo: number\n\n _init (zoomFrom: number, zoomTo: number) {\n this.zoomFrom = zoomFrom\n this.zoomTo = zoomTo\n }\n\n _tick () {\n this.controls.distance(lerp(this.zoomFrom, this.zoomTo, this.alpha))\n }\n}\n\n/**\n * Rotate animation. Rotate from one orientation to another.\n */\nexport class RotateAnimation extends Animation {\n rotateFrom: Quaternion\n rotateTo: Quaternion\n\n private _currentRotation = new Quaternion()\n\n _init (rotateFrom: number[]|Quaternion, rotateTo: number[]|Quaternion) {\n this.rotateFrom = ensureQuaternion(rotateFrom)\n this.rotateTo = ensureQuaternion(rotateTo)\n\n this._currentRotation = new Quaternion()\n }\n\n _tick () {\n this._currentRotation\n .copy(this.rotateFrom)\n .slerp(this.rotateTo, this.alpha)\n\n this.controls.rotate(this._currentRotation)\n }\n}\n\n/**\n * Value animation. Call callback with interpolated value.\n */\nexport class ValueAnimation extends Animation {\n valueFrom: number\n valueTo: number\n callback: Function\n\n _init (valueFrom: number, valueTo: number, callback: Function) {\n this.valueFrom = valueFrom\n this.valueTo = valueTo\n\n this.callback = callback\n }\n\n _tick (/* stats */) {\n this.callback(lerp(this.valueFrom, this.valueTo, this.alpha))\n }\n}\n\n/**\n * Timeout animation. Call callback after duration.\n */\nexport class TimeoutAnimation extends Animation {\n callback: Function\n\n _init (callback: Function) {\n this.callback = callback\n }\n\n _tick () {\n if (this.alpha === 1) this.callback()\n }\n}\n\n/**\n * Animation list.\n */\nexport class AnimationList {\n _list: Animation[]\n _resolveList: Function[] = []\n\n constructor (list: Animation[] = []) {\n this._list = list\n }\n\n /**\n * True when all animations have finished\n */\n get done () {\n return this._list.every(animation => {\n return animation.done\n })\n }\n\n /**\n * Promise-like interface\n */\n then (callback: Function) {\n let p: Promise\n\n if (this.done) {\n p = Promise.resolve()\n } else {\n p = new Promise(resolve => {\n this._resolveList.push(resolve)\n this._list.forEach(animation => {\n animation.then(() => {\n this._resolveList.forEach(callback => {\n callback()\n })\n this._resolveList.length = 0\n })\n })\n })\n }\n\n return p.then(callback as any)\n }\n}\n","/**\n * @file Animation Controls\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Quaternion, Matrix4 } from 'three'\n\nimport { ensureMatrix4 } from '../utils'\nimport Animation, {\n SpinAnimation, RockAnimation, MoveAnimation, ZoomAnimation,\n RotateAnimation, ValueAnimation, TimeoutAnimation, AnimationList\n} from '../animation/animation'\nimport Stage from '../stage/stage'\nimport Component from '../component/component'\nimport Viewer from '../viewer/viewer'\nimport Stats from '../viewer/stats'\nimport ViewerControls from './viewer-controls'\n\n/**\n * Animation controls\n */\nclass AnimationControls {\n viewer: Viewer\n controls: ViewerControls\n\n animationList: Animation[] = []\n finishedList: Animation[] = []\n\n /**\n * Create animation controls\n * @param {Stage} stage - the stage object\n */\n constructor (readonly stage: Stage) {\n this.viewer = stage.viewer\n this.controls = stage.viewerControls\n }\n\n /**\n * True when all animations are paused\n * @type {Boolean}\n */\n get paused () {\n return this.animationList.every((animation: Animation) => animation.paused)\n }\n\n /**\n * Add an animation\n */\n add (animation: Animation) {\n if (animation.duration === 0) {\n animation.tick(this.viewer.stats)\n } else {\n this.animationList.push(animation)\n }\n\n return animation\n }\n\n /**\n * Remove an animation\n */\n remove (animation: Animation) {\n const list = this.animationList\n const index = list.indexOf(animation)\n\n if (index > -1) {\n list.splice(index, 1)\n }\n }\n\n /**\n * Run all animations\n */\n run (stats: Stats) {\n const finishedList = this.finishedList\n const animationList = this.animationList\n\n const n = animationList.length\n for (let i = 0; i < n; ++i) {\n const animation = animationList[ i ]\n // tick returns true when finished\n if (animation.tick(stats)) {\n finishedList.push(animation)\n }\n }\n\n const m = finishedList.length\n if (m) {\n for (let j = 0; j < m; ++j) {\n this.remove(finishedList[ j ])\n }\n finishedList.length = 0\n }\n }\n\n /**\n * Add a spin animation\n * @param {Vector3} axis - axis to spin around\n * @param {Number} angle - amount to spin per frame, radians\n * @param {Number} duration - animation time in milliseconds\n * @return {SpinAnimation} the animation\n */\n spin (axis: Vector3|number[], angle?: number, duration?: number) {\n return this.add(\n new SpinAnimation(duration, this.controls, axis, angle)\n )\n }\n\n /**\n * Add a rock animation\n * @param {Vector3} axis - axis to rock around\n * @param {Number} angle - amount to spin per frame, radians\n * @param {Number} end - maximum extend of motion, radians\n * @param {Number} duration - animation time in milliseconds\n * @return {SpinAnimation} the animation\n */\n rock (axis: Vector3|number[], angle?: number, end?: number, duration?: number) {\n return this.add(\n new RockAnimation(duration, this.controls, axis, angle, end)\n )\n }\n\n /**\n * Add a rotate animation\n * @param {Quaternion} rotateTo - target rotation\n * @param {Number} duration - animation time in milliseconds\n * @return {RotateAnimation} the animation\n */\n rotate (rotateTo: Quaternion|number[], duration?: number) {\n const rotateFrom = this.viewer.rotationGroup.quaternion.clone()\n\n return this.add(\n new RotateAnimation(duration, this.controls, rotateFrom, rotateTo)\n )\n }\n\n /**\n * Add a move animation\n * @param {Vector3} moveTo - target position\n * @param {Number} duration - animation time in milliseconds\n * @return {MoveAnimation} the animation\n */\n move (moveTo: Vector3|number[], duration?: number) {\n const moveFrom = this.controls.position.clone().negate()\n\n return this.add(\n new MoveAnimation(duration, this.controls, moveFrom, moveTo)\n )\n }\n\n /**\n * Add a zoom animation\n * @param {Number} zoomTo - target distance\n * @param {Number} duration - animation time in milliseconds\n * @return {ZoomAnimation} the animation\n */\n zoom (zoomTo: number, duration?: number) {\n const zoomFrom = this.viewer.camera.position.z\n\n return this.add(\n new ZoomAnimation(duration, this.controls, zoomFrom, zoomTo)\n )\n }\n\n /**\n * Add a zoom and a move animation\n * @param {Vector3} moveTo - target position\n * @param {Number} zoomTo - target distance\n * @param {Number} duration - animation time in milliseconds\n * @return {Array} the animations\n */\n zoomMove (moveTo: Vector3, zoomTo: number, duration?: number) {\n return new AnimationList([\n this.move(moveTo, duration),\n this.zoom(zoomTo, duration)\n ])\n }\n\n /**\n * Add an orient animation\n * @param {OrientationMatrix|Array} orientTo - target orientation\n * @param {Number} duration - animation time in milliseconds\n * @return {Array} the animations\n */\n orient (orientTo: Matrix4|number[], duration?: number) {\n const p = new Vector3()\n const q = new Quaternion()\n const s = new Vector3()\n\n ensureMatrix4(orientTo).decompose(p, q, s)\n\n return new AnimationList([\n this.move(p.negate(), duration),\n this.rotate(q, duration),\n this.zoom(-s.x, duration)\n ])\n }\n\n /**\n * Add a value animation\n * @param {Number} valueFrom - start value\n * @param {Number} valueTo - target value\n * @param {Function} callback - called on every tick\n * @param {Number} duration - animation time in milliseconds\n * @return {ValueAnimation} the animation\n */\n value (valueFrom: number, valueTo: number, callback: Function, duration?: number) {\n return this.add(\n new ValueAnimation(duration, this.controls, valueFrom, valueTo, callback)\n )\n }\n\n /**\n * Add a timeout animation\n * @param {Function} callback - called after duration\n * @param {Number} duration - timeout in milliseconds\n * @return {TimeoutAnimation} the animation\n */\n timeout (callback: Function, duration?: number) {\n return this.add(\n new TimeoutAnimation(duration, this.controls, callback)\n )\n }\n\n /**\n * Add a component spin animation\n * @param {Component} component - object to move\n * @param {Vector3} axis - axis to spin around\n * @param {Number} angle - amount to spin per frame, radians\n * @param {Number} duration - animation time in milliseconds\n * @return {SpinAnimation} the animation\n */\n spinComponent (component: Component, axis?: Vector3|number[], angle?: number, duration?: number) {\n return this.add(\n // TODO\n new SpinAnimation(duration, component.controls as any, axis, angle)\n )\n }\n\n /**\n * Add a component rock animation\n * @param {Component} component - object to move\n * @param {Vector3} axis - axis to rock around\n * @param {Number} angle - amount to spin per frame, radians\n * @param {Number} end - maximum extend of motion, radians\n * @param {Number} duration - animation time in milliseconds\n * @return {SpinAnimation} the animation\n */\n rockComponent (component: Component, axis: Vector3|number[], angle?: number, end?: number, duration?: number) {\n return this.add(\n // TODO\n new RockAnimation(duration, component.controls as any, axis, angle, end)\n )\n }\n\n /**\n * Add a component move animation\n * @param {Component} component - object to move\n * @param {Vector3} moveTo - target position\n * @param {Number} duration - animation time in milliseconds\n * @return {MoveAnimation} the animation\n */\n moveComponent (component: Component, moveTo: Vector3|number[], duration?: number) {\n const moveFrom = component.controls.position.clone().negate()\n\n return this.add(\n // TODO\n new MoveAnimation(duration, component.controls as any, moveFrom, moveTo)\n )\n }\n\n /**\n * Pause all animations\n * @return {undefined}\n */\n pause () {\n this.animationList.forEach(animation => animation.pause())\n }\n\n /**\n * Resume all animations\n * @return {undefined}\n */\n resume () {\n this.animationList.forEach(animation => animation.resume())\n }\n\n /**\n * Toggle all animations\n * @return {undefined}\n */\n toggle () {\n if (this.paused) {\n this.resume()\n } else {\n this.pause()\n }\n }\n\n /**\n * Clear all animations\n * @return {undefined}\n */\n clear () {\n this.animationList.length = 0\n }\n\n dispose () {\n this.clear()\n }\n}\n\nexport default AnimationControls\n","/**\n * @file Queue\n * @author Alexander Rose \n * @private\n */\n\nclass Queue {\n queue: T[] = []\n pending = false\n\n constructor(readonly fn: Function, argList?: T[]) {\n this.next = this.next.bind(this)\n\n if (argList) {\n for (let i = 0, il = argList.length; i < il; ++i) {\n this.queue.push(argList[ i ])\n }\n this.next()\n }\n }\n\n private run (arg: any) {\n this.fn(arg, this.next)\n }\n\n private next () {\n const arg = this.queue.shift()\n if (arg !== undefined) {\n this.pending = true\n setTimeout(() => this.run(arg))\n } else {\n this.pending = false\n }\n }\n\n push (arg: T) {\n this.queue.push(arg)\n if (!this.pending) this.next()\n }\n\n kill () {\n this.queue.length = 0\n }\n\n length () {\n return this.queue.length\n }\n}\n\nexport default Queue\n","/**\n * @file Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { Color, Vector3, Matrix4 } from 'three'\n\nimport { Debug, Log, ColormakerRegistry, ExtensionFragDepth } from '../globals'\nimport { defaults } from '../utils'\nimport Queue from '../utils/queue'\nimport Counter from '../utils/counter'\nimport Viewer from '../viewer/viewer'\nimport { BufferParameters, BufferSide, default as Buffer } from '../buffer/buffer';\nimport { ColorData, ColormakerParameters, ColorMode } from '../color/colormaker';\nimport { GenericColor } from '../types'\n\nexport interface RepresentationParameters {\n name: string\n lazy: boolean,\n clipNear: number,\n clipRadius: number,\n clipCenter: Vector3,\n flatShaded: boolean,\n opacity: number,\n depthWrite: boolean,\n side: BufferSide,\n wireframe: boolean,\n colorData: ColorData,\n colorScheme: string,\n colorScale: string | number[],\n colorReverse: boolean,\n colorValue: GenericColor,\n colorDomain: number[],\n colorMode: ColorMode,\n colorSpace: 'sRGB' | 'linear',\n roughness: number,\n metalness: number,\n diffuse: GenericColor,\n diffuseInterior: boolean,\n useInteriorColor: boolean,\n interiorColor: GenericColor,\n interiorDarkening: number,\n disablePicking: boolean,\n matrix: Matrix4\n quality: string,\n visible: boolean,\n color: GenericColor,\n sphereDetail: number,\n radialSegments: number,\n openEnded: boolean\n disableImpostor: boolean\n [key: string]: any//boolean | number | undefined | Color | string | Vector3 | Matrix4 | number[]\n}\n/**\n * Representation parameter object.\n * @typedef {Object} RepresentationParameters - representation parameters\n * @property {Boolean} [lazy] - only build & update the representation when visible\n * otherwise defer changes until set visible again\n * @property {Integer} [clipNear] - position of camera near/front clipping plane\n * in percent of scene bounding box\n * @property {Integer} [clipRadius] - radius of clipping sphere\n * @property {Vector3} [clipCenter] - position of for spherical clipping\n * @property {Boolean} [flatShaded] - render flat shaded\n * @property {Float} [opacity] - translucency: 1 is fully opaque, 0 is fully transparent\n * @property {Boolean} [depthWrite] - depth write\n * @property {String} [side] - which triangle sides to render, \"front\" front-side,\n * \"back\" back-side, \"double\" front- and back-side\n * @property {Boolean} [wireframe] - render as wireframe\n * @property {ColorData} [colorData] - atom or bond indexed data for coloring\n * @property {String} [colorScheme] - color scheme\n * @property {String} [colorScale] - color scale, either a string for a\n * predefined scale or an array of\n * colors to be used as the scale\n * @property {Boolean} [colorReverse] - reverse color scale\n * @property {Color} [colorValue] - color value\n * @property {Integer[]} [colorDomain] - scale value range\n * @property {Integer} colorDomain.0 - min value\n * @property {Integer} colorDomain.1 - max value\n * @property {String} [colorMode] - color mode, one of rgb, hsv, hsl, hsi, lab, hcl\n * @property {Float} [roughness] - how rough the material is, between 0 and 1\n * @property {Float} [metalness] - how metallic the material is, between 0 and 1\n * @property {Color} [diffuse] - diffuse color for lighting\n * @property {Boolean} [diffuseInterior] - diffuse interior, i.e. ignore normal\n * @property {Boolean} [useInteriorColor] - use interior color\n * @property {Color} [interiorColor] - interior color\n * @property {Float} [interiorDarkening] - interior darkening: 0 no darking, 1 fully darkened\n * @property {Boolean} [disablePicking] - disable picking\n */\n\n/**\n * Representation object\n * @interface\n * @param {Object} object - the object to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {RepresentationParameters} [params] - representation parameters\n */\nclass Representation {\n parameters: any\n type: string\n viewer: Viewer\n tasks: Counter\n private queue: Queue\n bufferList: Buffer[]\n\n lazy: boolean\n lazyProps: { build: boolean, bufferParams: BufferParameters | {}, what: {}}\n protected name: string\n protected clipNear: number\n protected clipRadius: number\n protected clipCenter: Vector3\n protected flatShaded: boolean\n protected opacity: number\n protected depthWrite: boolean\n protected side: BufferSide\n protected wireframe: boolean\n protected colorData: ColorData\n protected colorScheme: string\n protected colorScale: string | string[]\n protected colorReverse: boolean\n protected colorValue: number\n protected colorDomain: number[]\n protected colorMode: ColorMode\n protected roughness: number\n protected metalness: number\n protected diffuse: GenericColor\n protected diffuseInterior?: boolean\n protected useInteriorColor?: boolean\n protected interiorColor: GenericColor\n protected interiorDarkening: number\n protected disablePicking: boolean\n protected sphereDetail: number\n protected radialSegments: number\n protected openEnded: boolean\n protected disableImpostor: boolean\n protected disposed: boolean\n\n protected matrix: Matrix4\n\n private quality: string\n visible: boolean\n\n protected manualAttach: ()=> any\n\n protected toBePrepared: boolean\n\n [key: string]: any\n\n constructor (object: any, viewer: Viewer, params: Partial) {\n // eslint-disable-next-line no-unused-vars\n // const p = params || {}\n\n this.type = ''\n\n this.parameters = {\n\n lazy: {\n type: 'boolean'\n },\n\n clipNear: {\n type: 'range', step: 1, max: 100, min: 0, buffer: true\n },\n clipRadius: {\n type: 'number', precision: 1, max: 1000, min: 0, buffer: true\n },\n clipCenter: {\n type: 'vector3', precision: 1, buffer: true\n },\n flatShaded: {\n type: 'boolean', buffer: true\n },\n opacity: {\n type: 'range', step: 0.01, max: 1, min: 0, buffer: true\n },\n depthWrite: {\n type: 'boolean', buffer: true\n },\n side: {\n type: 'select',\n buffer: true,\n options: { front: 'front', back: 'back', double: 'double' }\n },\n wireframe: {\n type: 'boolean', buffer: true\n },\n\n colorData: {\n type: 'hidden',\n update: 'color',\n },\n\n colorScheme: {\n type: 'select',\n update: 'color',\n options: {}\n },\n colorScale: {\n type: 'select',\n update: 'color',\n options: ColormakerRegistry.getScales()\n },\n colorReverse: {\n type: 'boolean', update: 'color'\n },\n colorValue: {\n type: 'color', update: 'color'\n },\n colorDomain: {\n type: 'hidden', update: 'color'\n },\n colorMode: {\n type: 'select',\n update: 'color',\n options: ColormakerRegistry.getModes()\n },\n\n roughness: {\n type: 'range', step: 0.01, max: 1, min: 0, buffer: true\n },\n metalness: {\n type: 'range', step: 0.01, max: 1, min: 0, buffer: true\n },\n diffuse: {\n type: 'color', buffer: true\n },\n\n diffuseInterior: {\n type: 'boolean', buffer: true\n },\n useInteriorColor: {\n type: 'boolean', buffer: true\n },\n interiorColor: {\n type: 'color', buffer: true\n },\n interiorDarkening: {\n type: 'range', step: 0.01, max: 1, min: 0, buffer: true\n },\n\n matrix: {\n type: 'hidden', buffer: true\n },\n\n disablePicking: {\n type: 'boolean', rebuild: true\n }\n\n }\n\n /**\n * @type {Viewer}\n */\n this.viewer = viewer\n\n /**\n * Counter that keeps track of tasks related to the creation of\n * the representation, including surface calculations.\n * @type {Counter}\n */\n this.tasks = new Counter()\n\n /**\n * @type {Queue}\n * @private\n */\n this.queue = new Queue(this.make.bind(this))\n\n /**\n * @type {Array}\n * @private\n */\n this.bufferList = []\n\n if (this.parameters.colorScheme) {\n this.parameters.colorScheme.options = ColormakerRegistry.getSchemes()\n }\n\n this.toBePrepared = false\n }\n\n init (params: Partial) {\n const p = params || {}\n\n this.clipNear = defaults(p.clipNear, 0)\n this.clipRadius = defaults(p.clipRadius, 0)\n this.clipCenter = defaults(p.clipCenter, new Vector3())\n this.flatShaded = defaults(p.flatShaded, false)\n this.side = defaults(p.side, 'double')\n this.opacity = defaults(p.opacity, 1.0)\n this.depthWrite = defaults(p.depthWrite, true)\n this.wireframe = defaults(p.wireframe, false)\n\n this.setColor(p.color, p)\n\n this.colorData = defaults(p.colorData, undefined)\n this.colorScheme = defaults(p.colorScheme, 'uniform')\n this.colorScale = defaults(p.colorScale, '')\n this.colorReverse = defaults(p.colorReverse, false)\n this.colorValue = defaults(p.colorValue, 0x909090)\n this.colorDomain = defaults(p.colorDomain, undefined)\n this.colorMode = defaults(p.colorMode, 'hcl')\n\n this.visible = defaults(p.visible, true)\n this.quality = defaults(p.quality, undefined)\n\n this.roughness = defaults(p.roughness, 0.4)\n this.metalness = defaults(p.metalness, 0.0)\n this.diffuse = defaults(p.diffuse, 0xffffff)\n\n this.diffuseInterior = defaults(p.diffuseInterior, false)\n this.useInteriorColor = defaults(p.useInteriorColor, false)\n this.interiorColor = defaults(p.interiorColor, 0x222222)\n this.interiorDarkening = defaults(p.interiorDarkening, 0)\n\n this.lazy = defaults(p.lazy, false)\n this.lazyProps = {\n build: false,\n bufferParams: {},\n what: {}\n }\n\n this.matrix = defaults(p.matrix, new Matrix4())\n\n this.disablePicking = defaults(p.disablePicking, false)\n\n // handle common parameters when applicable\n\n const tp = this.parameters\n\n if (tp.sphereDetail === true) {\n tp.sphereDetail = {\n type: 'integer', max: 3, min: 0, rebuild: 'impostor'\n }\n }\n if (tp.radialSegments === true) {\n tp.radialSegments = {\n type: 'integer', max: 25, min: 5, rebuild: 'impostor'\n }\n }\n if (tp.openEnded === true) {\n tp.openEnded = {\n type: 'boolean', rebuild: 'impostor', buffer: true\n }\n }\n if (tp.disableImpostor === true) {\n tp.disableImpostor = {\n type: 'boolean', rebuild: true\n }\n }\n\n if (p.quality === 'low') {\n if (tp.sphereDetail) this.sphereDetail = 0\n if (tp.radialSegments) this.radialSegments = 5\n } else if (p.quality === 'medium') {\n if (tp.sphereDetail) this.sphereDetail = 1\n if (tp.radialSegments) this.radialSegments = 10\n } else if (p.quality === 'high') {\n if (tp.sphereDetail) this.sphereDetail = 2\n if (tp.radialSegments) this.radialSegments = 20\n } else {\n if (tp.sphereDetail) {\n this.sphereDetail = defaults(p.sphereDetail, 1)\n }\n if (tp.radialSegments) {\n this.radialSegments = defaults(p.radialSegments, 10)\n }\n }\n\n if (tp.openEnded) {\n this.openEnded = defaults(p.openEnded, true)\n }\n\n if (tp.disableImpostor) {\n this.disableImpostor = defaults(p.disableImpostor, false)\n }\n\n }\n\n getColorParams (p?: {[k: string]: any}): { scheme: string, [k: string]: any } & ColormakerParameters {\n return Object.assign({\n\n data: this.colorData,\n scheme: this.colorScheme,\n scale: this.colorScale,\n reverse: this.colorReverse,\n value: this.colorValue,\n domain: this.colorDomain,\n mode: this.colorMode,\n colorSpace: this.colorSpace,\n\n }, p)\n }\n\n getBufferParams (p: {[k: string]: any} = {}) {\n return Object.assign({\n\n clipNear: this.clipNear,\n clipRadius: this.clipRadius,\n clipCenter: this.clipCenter,\n flatShaded: this.flatShaded,\n opacity: this.opacity,\n depthWrite: this.depthWrite,\n side: this.side,\n wireframe: this.wireframe,\n\n roughness: this.roughness,\n metalness: this.metalness,\n diffuse: this.diffuse,\n\n diffuseInterior: this.diffuseInterior,\n useInteriorColor: this.useInteriorColor,\n interiorColor: this.interiorColor,\n interiorDarkening: this.interiorDarkening,\n\n matrix: this.matrix,\n\n disablePicking: this.disablePicking\n\n }, p)\n }\n\n setColor (value: number | string | Color | undefined , p?: Partial) {\n const types = Object.keys(ColormakerRegistry.getSchemes())\n\n if (typeof value === 'string' && types.includes(value.toLowerCase())) {\n if (p) {\n p.colorScheme = value\n } else {\n this.setParameters({ colorScheme: value })\n }\n } else if (value !== undefined) {\n let val = new Color(value as string).getHex() //TODO\n if (p) {\n p.colorScheme = 'uniform'\n p.colorValue = val\n } else {\n this.setParameters({\n colorScheme: 'uniform', colorValue: val\n })\n }\n }\n\n return this\n }\n\n // TODO\n prepare (cb: ()=> void) {\n\n }\n\n create () {\n // this.bufferList.length = 0;\n }\n\n update (what?: any) {\n this.build()\n }\n\n build (updateWhat?: {[k: string]: boolean}) {\n if (this.lazy && (!this.visible || !this.opacity)) {\n this.lazyProps.build = true\n return\n }\n\n if (!this.toBePrepared) {\n this.tasks.increment()\n this.make()\n return\n }\n\n // don't let tasks accumulate\n if (this.queue.length() > 0) {\n this.tasks.change(1 - this.queue.length())\n this.queue.kill()\n } else {\n this.tasks.increment()\n }\n\n this.queue.push(updateWhat || false)\n }\n\n make (updateWhat?: boolean, callback?: () => void) {\n if (Debug) Log.time('Representation.make ' + this.type)\n\n const _make = () => {\n if (updateWhat) {\n this.update(updateWhat)\n this.viewer.requestRender()\n this.tasks.decrement()\n if (callback) callback()\n } else {\n this.clear()\n this.create()\n if (!this.manualAttach && !this.disposed) {\n if (Debug) Log.time('Representation.attach ' + this.type)\n this.attach(() => {\n if (Debug) Log.timeEnd('Representation.attach ' + this.type)\n this.tasks.decrement()\n if (callback) callback()\n })\n }\n }\n\n if (Debug) Log.timeEnd('Representation.make ' + this.type)\n }\n\n if (this.toBePrepared) {\n this.prepare(_make)\n } else {\n _make()\n }\n }\n\n attach (callback: () => void) {\n this.setVisibility(this.visible)\n\n callback()\n }\n\n /**\n * Set the visibility of the representation\n * @param {Boolean} value - visibility flag\n * @param {Boolean} [noRenderRequest] - whether or not to request a re-render from the viewer\n * @return {Representation} this object\n */\n setVisibility (value: boolean, noRenderRequest?: boolean): Representation {\n this.visible = value\n\n if (this.visible && this.opacity) {\n const lazyProps = this.lazyProps\n const bufferParams = lazyProps.bufferParams\n const what = lazyProps.what\n\n if (lazyProps.build) {\n lazyProps.build = false\n this.build()\n return this\n } else if (Object.keys(bufferParams).length || Object.keys(what).length) {\n lazyProps.bufferParams = {}\n lazyProps.what = {}\n this.updateParameters(bufferParams, what)\n }\n }\n\n this.bufferList.forEach(function (buffer) {\n buffer.setVisibility(value)\n })\n\n if (!noRenderRequest) this.viewer.requestRender()\n\n return this\n }\n\n /**\n * Set the visibility of the representation\n * @param {RepresentationParameters} params - parameters object\n * @param {Object} [what] - buffer data attributes to be updated,\n * note that this needs to be implemented in the\n * derived classes. Generally it allows more\n * fine-grained control over updating than\n * forcing a rebuild.\n * @param {Boolean} what.position - update position data\n * @param {Boolean} what.color - update color data\n * @param {Boolean} [rebuild] - whether or not to rebuild the representation\n * @return {Representation} this object\n */\n setParameters (params: Partial, what:{[propName: string]: any} = {}, rebuild = false) {\n const p = params || {}\n const tp = this.parameters\n const bufferParams: BufferParameters = {}\n\n if (!this.opacity && p.opacity !== undefined) {\n if (this.lazyProps.build) {\n this.lazyProps.build = false\n rebuild = true\n } else {\n Object.assign(bufferParams, this.lazyProps.bufferParams)\n Object.assign(what, this.lazyProps.what)\n this.lazyProps.bufferParams = {}\n this.lazyProps.what = {}\n }\n }\n\n this.setColor(p.color, p)\n\n for (let name in p) {\n if (p[ name ] === undefined) continue\n if (tp[ name ] == undefined ) continue // Skip nulls as well as undefined\n\n if (tp[ name ].int) p[ name ] = parseInt(p[ name ] as string)\n if (tp[ name ].float) p[ name ] = parseFloat(p[ name ] as string)\n\n // no value change\n if (p[ name ] === this[ name ] && (\n !p[ name ].equals || p[ name ].equals(this[ name ])\n )) continue\n\n if (this[ name ] && this[ name ].copy && p[ name ].copy) {\n this[ name ].copy(p[ name ])\n } else if (this[ name ] && this[ name ].set) {\n this[ name ].set(p[ name ])\n } else {\n this[ name ] = p[ name ]\n }\n\n // buffer param\n if (tp[ name ].buffer) {\n if (tp[ name ].buffer === true) {\n (bufferParams[ name as keyof BufferParameters ] as any) = p[ name ]\n } else {\n let key: (keyof BufferParameters) = tp[ name ].buffer;\n (bufferParams[ key ] as any) = p[ name ]\n }\n }\n\n // mark for update\n if (tp[ name ].update) {\n what[ tp[ name ].update ] = true\n }\n\n // mark for rebuild\n if (tp[ name ].rebuild &&\n !(tp[ name ].rebuild === 'impostor' &&\n ExtensionFragDepth && !this.disableImpostor)\n ) {\n rebuild = true\n }\n }\n\n //\n\n if (rebuild) {\n this.build()\n } else {\n this.updateParameters(bufferParams, what)\n }\n\n return this\n }\n\n updateParameters (bufferParams: BufferParameters | {} = {}, what?: any) {\n if (this.lazy && (!this.visible || !this.opacity) && bufferParams.hasOwnProperty('opacity') === false) {\n Object.assign(this.lazyProps.bufferParams, bufferParams)\n Object.assign(this.lazyProps.what, what)\n return\n }\n\n this.bufferList.forEach(function (buffer) {\n buffer.setParameters(bufferParams)\n })\n\n if (Object.keys(what).length) {\n this.update(what) // update buffer attribute\n }\n\n this.viewer.requestRender()\n }\n\n getParameters () {\n const params: Partial = {\n lazy: this.lazy,\n visible: this.visible,\n quality: this.quality\n }\n\n Object.keys(this.parameters).forEach(name => {\n if (this.parameters[ name ] !== null) {\n params[ name ] = this[ name ]\n }\n })\n\n return params\n }\n\n clear () {\n this.bufferList.forEach(buffer => {\n this.viewer.remove(buffer)\n buffer.dispose()\n })\n this.bufferList.length = 0\n\n this.viewer.requestRender()\n }\n\n dispose () {\n this.disposed = true\n this.queue.kill()\n this.tasks.dispose()\n this.clear()\n }\n}\n\nexport default Representation\n","/**\n * @file Worker\n * @author Alexander Rose \n * @private\n */\n\nimport { Log, Debug, WorkerRegistry } from '../globals'\n\nexport default class _Worker {\n\n pending = 0\n postCount = 0\n onmessageDict: { [k: number]: Function|undefined } = {}\n onerrorDict: { [k: number]: Function|undefined } = {}\n\n name: string\n blobUrl: string\n worker: Worker\n\n constructor (name: string) {\n\n this.name = name\n this.blobUrl = window.URL.createObjectURL(WorkerRegistry.get(name))\n this.worker = new Worker(this.blobUrl)\n\n WorkerRegistry.activeWorkerCount += 1\n\n this.worker.onmessage = (event: any) => {\n this.pending -= 1\n const postId = event.data.__postId\n\n if (Debug) Log.timeEnd('Worker.postMessage ' + name + ' #' + postId)\n\n const onmessage = this.onmessageDict[ postId ]\n if (onmessage) {\n onmessage.call(this.worker, event)\n } else {\n // Log.debug('No onmessage', postId, name)\n }\n\n delete this.onmessageDict[ postId ]\n delete this.onerrorDict[ postId ]\n }\n\n this.worker.onerror = (event: any) => {\n this.pending -= 1\n if (event.data) {\n const postId = event.data.__postId\n\n const onerror = this.onerrorDict[ postId ]\n if (onerror) {\n onerror.call(this.worker, event)\n } else {\n Log.error('Worker.onerror', postId, name, event)\n }\n\n delete this.onmessageDict[ postId ]\n delete this.onerrorDict[ postId ]\n } else {\n Log.error('Worker.onerror', name, event)\n }\n }\n }\n\n post (aMessage: any = {}, transferList?: any, onmessage?: Function, onerror?: Function) {\n this.onmessageDict[ this.postCount ] = onmessage\n this.onerrorDict[ this.postCount ] = onerror\n\n aMessage.__name = this.name\n aMessage.__postId = this.postCount\n aMessage.__debug = Debug\n\n if (Debug) Log.time(`Worker.postMessage ${this.name} #${this.postCount}`)\n\n try {\n this.worker.postMessage(aMessage, transferList)\n } catch (error) {\n Log.error('worker.post:', error)\n this.worker.postMessage(aMessage)\n }\n\n this.pending += 1\n this.postCount += 1\n\n return this\n }\n\n terminate () {\n if (this.worker) {\n this.worker.terminate()\n window.URL.revokeObjectURL(this.blobUrl)\n WorkerRegistry.activeWorkerCount -= 1\n } else {\n Log.log('no worker to terminate')\n }\n }\n}\n","/**\n * @file Worker Pool\n * @author Alexander Rose \n * @private\n */\n\nimport Worker from './worker'\n\nclass WorkerPool {\n maxCount: number\n pool: Worker[] = []\n count = 0\n name: string\n\n constructor (name: string, maxCount = 2) {\n this.maxCount = Math.min(8, maxCount)\n this.name = name\n }\n\n post (aMessage: any = {}, transferList?: any, onmessage?: Function, onerror?: Function) {\n const worker = this.getNextWorker()\n if (worker) {\n worker.post(aMessage, transferList, onmessage, onerror)\n } else {\n console.error('unable to get worker from pool')\n }\n\n return this\n }\n\n terminate () {\n this.pool.forEach(function (worker) {\n worker.terminate()\n })\n }\n\n getNextWorker () {\n let nextWorker\n let minPending = Infinity\n\n for (let i = 0; i < this.maxCount; ++i) {\n if (i >= this.count) {\n nextWorker = new Worker(this.name)\n this.pool.push(nextWorker)\n this.count += 1\n break\n }\n\n const worker = this.pool[ i ]\n\n if (worker.pending === 0) {\n nextWorker = worker\n break\n } else if (worker.pending < minPending) {\n minPending = worker.pending\n nextWorker = worker\n }\n }\n\n return nextWorker\n }\n}\n\nWorkerPool.prototype.constructor = WorkerPool\n\nexport default WorkerPool\n","/**\n * @file Vector Utils\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { NumberArray } from '../types'\nimport { EPS } from './math-constants'\n\n/**\n * Calculate the two intersection points\n * Converted to JavaScript from\n * {@link http://paulbourke.net/geometry/pointlineplane/lineline.c}\n */\nexport function lineLineIntersect (p1: Vector3, p2: Vector3, p3: Vector3, p4: Vector3) {\n const p13 = new Vector3()\n const p43 = new Vector3()\n const p21 = new Vector3()\n let d1343, d4321, d1321, d4343, d2121\n let denom, numer\n\n p13.x = p1.x - p3.x\n p13.y = p1.y - p3.y\n p13.z = p1.z - p3.z\n p43.x = p4.x - p3.x\n p43.y = p4.y - p3.y\n p43.z = p4.z - p3.z\n if (Math.abs(p43.x) < EPS && Math.abs(p43.y) < EPS && Math.abs(p43.z) < EPS) { return null }\n\n p21.x = p2.x - p1.x\n p21.y = p2.y - p1.y\n p21.z = p2.z - p1.z\n if (Math.abs(p21.x) < EPS && Math.abs(p21.y) < EPS && Math.abs(p21.z) < EPS) { return null }\n\n d1343 = p13.x * p43.x + p13.y * p43.y + p13.z * p43.z\n d4321 = p43.x * p21.x + p43.y * p21.y + p43.z * p21.z\n d1321 = p13.x * p21.x + p13.y * p21.y + p13.z * p21.z\n d4343 = p43.x * p43.x + p43.y * p43.y + p43.z * p43.z\n d2121 = p21.x * p21.x + p21.y * p21.y + p21.z * p21.z\n\n denom = d2121 * d4343 - d4321 * d4321\n if (Math.abs(denom) < EPS) { return null }\n numer = d1343 * d4321 - d1321 * d4343\n\n const mua = numer / denom\n const mub = (d1343 + d4321 * mua) / d4343\n\n const pa = new Vector3(\n p1.x + mua * p21.x,\n p1.y + mua * p21.y,\n p1.z + mua * p21.z\n )\n const pb = new Vector3(\n p3.x + mub * p43.x,\n p3.y + mub * p43.y,\n p3.z + mub * p43.z\n )\n\n return [ pa, pb ]\n}\n\nexport function calculateMeanVector3 (array: NumberArray) {\n const n = array.length\n const m = n / 3\n\n let x = 0\n let y = 0\n let z = 0\n\n for (let i = 0; i < n; i += 3) {\n x += array[ i + 0 ]\n y += array[ i + 1 ]\n z += array[ i + 2 ]\n }\n\n return new Vector3(x / m, y / m, z / m)\n}\n\nexport function isPointOnSegment (p: Vector3, l1: Vector3, l2: Vector3) {\n const len = l1.distanceTo(l2)\n\n return p.distanceTo(l1) <= len && p.distanceTo(l2) <= len\n}\n\nexport function projectPointOnVector (point: Vector3, vector: Vector3, origin?: Vector3) {\n if (origin) {\n point.sub(origin).projectOnVector(vector).add(origin)\n } else {\n point.projectOnVector(vector)\n }\n\n return point\n}\n\nexport function computeBoundingBox (array: NumberArray) {\n let minX = +Infinity\n let minY = +Infinity\n let minZ = +Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n let maxZ = -Infinity\n for (let i = 0, l = array.length; i < l; i += 3) {\n const x = array[ i ]\n const y = array[ i + 1 ]\n const z = array[ i + 2 ]\n if (x < minX) minX = x\n if (y < minY) minY = y\n if (z < minZ) minZ = z\n if (x > maxX) maxX = x\n if (y > maxY) maxY = y\n if (z > maxZ) maxZ = z\n }\n return [\n v3new([ minX, minY, minZ ]),\n v3new([ maxX, maxY, maxZ ])\n ]\n}\n(computeBoundingBox as any).__deps = [ v3new ]\n\nexport function applyMatrix4toVector3array (m: Float32Array, a: Float32Array) {\n for (let i = 0, il = a.length; i < il; i += 3) {\n const x = a[ i ]\n const y = a[ i + 1 ]\n const z = a[ i + 2 ]\n a[ i ] = m[ 0 ] * x + m[ 4 ] * y + m[ 8 ] * z + m[ 12 ]\n a[ i + 1 ] = m[ 1 ] * x + m[ 5 ] * y + m[ 9 ] * z + m[ 13 ]\n a[ i + 2 ] = m[ 2 ] * x + m[ 6 ] * y + m[ 10 ] * z + m[ 14 ]\n }\n}\n\nexport function applyMatrix3toVector3array (m: Float32Array, a: Float32Array) {\n for (let i = 0, il = a.length; i < il; i += 3) {\n const x = a[ i ]\n const y = a[ i + 1 ]\n const z = a[ i + 2 ]\n a[ i ] = m[ 0 ] * x + m[ 3 ] * y + m[ 6 ] * z\n a[ i + 1 ] = m[ 1 ] * x + m[ 4 ] * y + m[ 7 ] * z\n a[ i + 2 ] = m[ 2 ] * x + m[ 5 ] * y + m[ 8 ] * z\n }\n}\n\nexport function normalizeVector3array (a: Float32Array) {\n for (let i = 0, il = a.length; i < il; i += 3) {\n const x = a[ i ]\n const y = a[ i + 1 ]\n const z = a[ i + 2 ]\n const len2 = x * x + y * y + z * z\n if (len2 > 0) { // avoid divide by zero\n const s = 1 / Math.sqrt(len2)\n a[ i ] = x * s\n a[ i + 1 ] = y * s\n a[ i + 2 ] = z * s\n }\n // else leave as all zeros\n }\n}\n\nexport function v3new (array?: NumberArray) {\n return new Float32Array(array as any || 3) // TODO\n}\n\nexport function v3cross (out: Float32Array, a: Float32Array, b: Float32Array) {\n const ax = a[0]\n const ay = a[1]\n const az = a[2]\n const bx = b[0]\n const by = b[1]\n const bz = b[2]\n out[0] = ay * bz - az * by\n out[1] = az * bx - ax * bz\n out[2] = ax * by - ay * bx\n}\n\nexport function v3dot (a: Float32Array, b: Float32Array) {\n return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]\n}\n\nexport function v3sub (out: Float32Array, a: Float32Array, b: Float32Array) {\n out[0] = a[0] - b[0]\n out[1] = a[1] - b[1]\n out[2] = a[2] - b[2]\n}\n\nexport function v3add (out: Float32Array, a: Float32Array, b: Float32Array) {\n out[0] = a[0] + b[0]\n out[1] = a[1] + b[1]\n out[2] = a[2] + b[2]\n}\n\nexport function v3fromArray (out: Float32Array, array: Float32Array, offset = 0) {\n out[0] = array[offset]\n out[1] = array[offset + 1]\n out[2] = array[offset + 2]\n}\n\nexport function v3toArray (input: Float32Array, array: Float32Array, offset = 0) {\n array[offset] = input[0]\n array[offset + 1] = input[1]\n array[offset + 2] = input[2]\n}\n\nexport function v3forEach (array: Float32Array, fn: (i: Float32Array, j: Float32Array, k: Float32Array) => void, b: Float32Array) {\n const a = v3new()\n for (let i = 0, n = array.length; i < n; i += 3) {\n v3fromArray(a, array, i)\n fn(a, a, b)\n v3toArray(a, array, i)\n }\n}\n(v3forEach as any).__deps = [ v3new, v3fromArray, v3toArray ]\n\nexport function v3length2 (a: Float32Array) {\n return a[0] * a[0] + a[1] * a[1] + a[2] * a[2]\n}\n\nexport function v3length (a: Float32Array) {\n return Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2])\n}\n\nexport function v3divide (out: Float32Array, a: Float32Array, b: Float32Array) {\n out[0] = a[0] / b[0]\n out[1] = a[1] / b[1]\n out[2] = a[2] / b[2]\n}\n\nexport function v3multiply (out: Float32Array, a: Float32Array, b: Float32Array) {\n out[0] = a[0] * b[0]\n out[1] = a[1] * b[1]\n out[2] = a[2] * b[2]\n}\n\nexport function v3divideScalar (out: Float32Array, a: Float32Array, s: number) {\n v3multiplyScalar(out, a, 1 / s)\n}\n(v3divideScalar as any).__deps = [ v3multiplyScalar ]\n\nexport function v3multiplyScalar (out: Float32Array, a: Float32Array, s: number) {\n out[0] = a[0] * s\n out[1] = a[1] * s\n out[2] = a[2] * s\n}\n\nexport function v3normalize (out: Float32Array, a: Float32Array) {\n const length2 = v3length2(a)\n if (length2 == 0) {\n out[0] = a[0]\n out[1] = a[1]\n out[2] = a[2]\n } else {\n v3multiplyScalar(out, a, 1 / Math.sqrt(length2))\n }\n}\n(v3normalize as any).__deps = [ v3multiplyScalar, v3length2 ]\n\nexport function v3subScalar (out: Float32Array, a: Float32Array, s: number) {\n out[0] = a[0] - s\n out[1] = a[1] - s\n out[2] = a[2] - s\n}\n\nexport function v3addScalar (out: Float32Array, a: Float32Array, s: number) {\n out[0] = a[0] + s\n out[1] = a[1] + s\n out[2] = a[2] + s\n}\n\nexport function v3floor (out: Float32Array, a: Float32Array) {\n out[0] = Math.floor(a[0])\n out[1] = Math.floor(a[1])\n out[2] = Math.floor(a[2])\n}\n\nexport function v3ceil (out: Float32Array, a: Float32Array) {\n out[0] = Math.ceil(a[0])\n out[1] = Math.ceil(a[1])\n out[2] = Math.ceil(a[2])\n}\n\nexport function v3round (out: Float32Array, a: Float32Array) {\n out[0] = Math.round(a[0])\n out[1] = Math.round(a[1])\n out[2] = Math.round(a[2])\n}\n\nexport function v3negate (out: Float32Array, a: Float32Array) {\n out[0] = -a[0]\n out[1] = -a[1]\n out[2] = -a[2]\n}\n\nexport function v3angle (a: Float32Array, b: Float32Array) {\n const ax = a[0]\n const ay = a[1]\n const az = a[2]\n const bx = b[0]\n const by = b[1]\n const bz = b[2]\n const cx = ay * bz - az * by\n const cy = az * bx - ax * bz\n const cz = ax * by - ay * bx\n const s = Math.sqrt(cx * cx + cy * cy + cz * cz)\n const c = ax * bx + ay * by + az * bz\n return Math.atan2(s, c)\n}\n","/**\n * @file Dash\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { CylinderBufferData } from '../buffer/cylinder-buffer'\nimport { WideLineBufferData } from '../buffer/wideline-buffer'\nimport {\n calculateDirectionArray, calculateCenterArray,\n replicateArrayEntries, replicateArray3Entries\n} from '../math/array-utils'\n\nexport function getFixedCountDashData (data: T, segmentCount: number = 9) {\n\n const s = Math.floor(segmentCount / 2)\n const n = data.position1.length / 3\n const sn = s * n\n const sn3 = sn * 3\n const step = 1 / segmentCount\n\n const direction = calculateDirectionArray(data.position1, data.position2)\n const position1 = new Float32Array(sn3)\n const position2 = new Float32Array(sn3)\n\n const v = new Vector3()\n\n for (let i = 0; i < n; ++i) {\n const i3 = i * 3\n v.set(direction[ i3 ], direction[ i3 + 1 ], direction[ i3 + 2 ])\n\n const x = data.position1[ i3 ]\n const y = data.position1[ i3 + 1 ]\n const z = data.position1[ i3 + 2 ]\n\n for (let j = 0; j < s; ++j) {\n const j3 = s * i3 + j * 3\n\n const f1 = step * (j * 2 + 1)\n const f2 = step * (j * 2 + 2)\n\n position1[ j3 ] = x + v.x * f1\n position1[ j3 + 1 ] = y + v.y * f1\n position1[ j3 + 2 ] = z + v.z * f1\n\n position2[ j3 ] = x + v.x * f2\n position2[ j3 + 1 ] = y + v.y * f2\n position2[ j3 + 2 ] = z + v.z * f2\n }\n }\n\n const position = calculateCenterArray(position1, position2) as Float32Array\n const color = replicateArray3Entries(data.color!, s) // TODO\n const color2 = color\n\n const d: any = { position, position1, position2, color, color2 }\n\n if ((data as any).radius) { // TODO\n d.radius = replicateArrayEntries((data as any).radius, s) // TODO\n }\n\n if (data.picking && data.picking.array) {\n data.picking.array = replicateArrayEntries(data.picking.array, s)\n d.picking = data.picking\n }\n if (data.primitiveId) {\n d.primitiveId = replicateArrayEntries(data.primitiveId, s)\n }\n\n return d as T\n}\n\nexport function getFixedLengthDashData (data: T, segmentLength: number = 0.1) {\n\n const direction = calculateDirectionArray(data.position1, data.position2)\n const pos1: number[] = []\n const pos2: number[] = []\n const col: number[] = []\n const rad: number[]|undefined = (data as any).radius ? [] : undefined\n const pick: number[]|undefined = (data as any).picking ? [] : undefined\n const id: number[]|undefined = (data as any).primitiveId ? [] : undefined\n\n const v = new Vector3()\n const n = data.position1.length / 3\n\n let k = 0\n\n for (let i = 0; i < n; ++i) {\n const i3 = i * 3\n v.set(direction[ i3 ], direction[ i3 + 1 ], direction[ i3 + 2 ])\n\n const vl = v.length()\n const segmentCount = vl / segmentLength\n const s = Math.floor(segmentCount / 2)\n const step = 1 / segmentCount\n\n const x = data.position1[ i3 ]\n const y = data.position1[ i3 + 1 ]\n const z = data.position1[ i3 + 2 ]\n\n for (let j = 0; j < s; ++j) {\n const j3 = k * 3 + j * 3\n\n const f1 = step * (j * 2 + 1)\n const f2 = step * (j * 2 + 2)\n\n pos1[ j3 ] = x + v.x * f1\n pos1[ j3 + 1 ] = y + v.y * f1\n pos1[ j3 + 2 ] = z + v.z * f1\n\n pos2[ j3 ] = x + v.x * f2\n pos2[ j3 + 1 ] = y + v.y * f2\n pos2[ j3 + 2 ] = z + v.z * f2\n\n if (data.color) {\n col[ j3 ] = data.color[ i3 ]\n col[ j3 + 1 ] = data.color[ i3 + 1 ]\n col[ j3 + 2 ] = data.color[ i3 + 2 ]\n }\n\n if (rad) rad[ k + j ] = (data as any).radius[ i ]\n if (pick) {\n if ((data as any).picking.array) {\n pick[ k + j ] = (data as any).picking.array[ i ]\n } else {\n pick[ k + j ] = i\n }\n }\n if (id) id[ k + j ] = (data as any).primitiveId[ i ]\n }\n\n k += s\n }\n\n const position1 = new Float32Array(pos1)\n const position2 = new Float32Array(pos2)\n const position = calculateCenterArray(position1, position2) as Float32Array\n const color = new Float32Array(col)\n const color2 = color\n\n const d: any = { position, position1, position2, color, color2 }\n\n if (rad) d.radius = new Float32Array(rad)\n if (pick && data.picking) {\n data.picking.array = new Float32Array(pick)\n d.picking = data.picking\n }\n if (id) d.primitiveId = new Float32Array(id)\n\n return d as T\n}\n\nexport function getFixedLengthWrappedDashData (data: T, segmentLength: number = 0.1) {\n\n const direction = calculateDirectionArray(data.position1, data.position2)\n const pos1: number[] = []\n const pos2: number[] = []\n const col: number[] = []\n const rad: number[]|undefined = (data as any).radius ? [] : undefined\n const pick: number[]|undefined = (data as any).picking ? [] : undefined\n const id: number[]|undefined = (data as any).primitiveId ? [] : undefined\n\n const v = new Vector3()\n const n = data.position1.length / 3\n\n let remaining = segmentLength\n let drawing = true\n\n let k = 0\n let k3 = 0\n let kprev = 0\n\n for (let i = 0; i < n; ++i) {\n const i3 = i * 3\n const x = data.position1[ i3 ]\n const y = data.position1[ i3 + 1 ]\n const z = data.position1[ i3 + 2 ]\n\n v.set(direction[ i3 ], direction[ i3 + 1 ], direction[ i3 + 2 ])\n const vl = v.length()\n\n if (drawing) {\n pos1[ k3 ] = x\n pos1[ k3 + 1 ] = y\n pos1[ k3 + 2 ] = z\n }\n\n let dist = remaining\n const inv = 1 / vl\n while (dist < vl) {\n const a = drawing ? pos2 : pos1\n a[ k3 ] = x + v.x * dist * inv\n a[ k3 + 1 ] = y + v.y * dist * inv\n a[ k3 + 2 ] = z + v.z * dist * inv\n if (drawing) {\n k++\n k3 = k * 3\n }\n drawing = !drawing\n remaining = segmentLength\n dist += segmentLength\n }\n\n if (drawing) {\n pos2[ k3 ] = data.position2[ i3 ]\n pos2[ k3 + 1 ] = data.position2[ i3 + 1 ]\n pos2[ k3 + 2 ] = data.position2[ i3 + 2 ]\n k++\n k3 = k * 3\n }\n\n remaining = dist - vl\n\n for (let j = kprev; j < k ; j++){\n if (data.color) {\n const j3 = j * 3\n col[ j3 ] = data.color[ i3 ]\n col[ j3 + 1 ] = data.color[ i3 + 1 ]\n col[ j3 + 2 ] = data.color[ i3 + 2 ]\n }\n\n if (rad) rad[ j ] = (data as any).radius[ i ]\n if (pick) {\n if ((data as any).picking.array) {\n pick[ j ] = (data as any).picking.array[ i ]\n } else {\n pick[ j ] = i\n }\n }\n if (id) id[ j ] = (data as any).primitiveId[ i ]\n }\n\n kprev = k\n\n }\n\n if (!drawing && n > 0) {\n const k3 = k * 3\n pos2[ k3 ] = data.position2[ 3 * n - 3 ]\n pos2[ k3 + 1 ] = data.position2[ 3 * n - 2 ]\n pos2[ k3 + 1 ] = data.position2[ 3 * n - 1 ]\n }\n\n const position1 = new Float32Array(pos1)\n const position2 = new Float32Array(pos2)\n const position = calculateCenterArray(position1, position2) as Float32Array\n const color = new Float32Array(col)\n const color2 = color\n\n const d: any = { position, position1, position2, color, color2 }\n\n if (rad) d.radius = new Float32Array(rad)\n if (pick && data.picking) {\n data.picking.array = new Float32Array(pick)\n d.picking = data.picking\n }\n if (id) d.primitiveId = new Float32Array(id)\n\n return d as T\n}\n","/**\n * @file Primitive\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Color, Box3 } from 'three'\n\nimport { BufferRegistry, PickerRegistry } from '../globals'\nimport Shape from './shape'\nimport { getFixedLengthDashData } from './dash'\n\nfunction addElement (elm: any, array: any[]) {\n if (elm.toArray !== undefined) {\n elm = elm.toArray()\n } else if (elm.x !== undefined) {\n elm = [ elm.x, elm.y, elm.z ]\n } else if (elm.r !== undefined) {\n elm = [ elm.r, elm.g, elm.b ]\n }\n array.push.apply(array, elm)\n}\n\nconst tmpVec = new Vector3()\n\nexport type PrimitiveFields = { [k: string]: string }\n\n/**\n * Base class for geometry primitives\n * @interface\n */\nexport abstract class Primitive {\n static type = ''\n static fields: PrimitiveFields = {}\n\n static get Picker () { return PickerRegistry.get(this.type) }\n static get Buffer () { return BufferRegistry.get(this.type) }\n\n static getShapeKey (name: string) {\n return this.type + name[0].toUpperCase() + name.substr(1)\n }\n\n static expandBoundingBox (box: Box3, data: any) {}\n\n static valueToShape (shape: Shape, name: string, value: any) {\n const data = shape._primitiveData[this.getShapeKey(name)]\n const type = this.fields[name]\n\n switch (type) {\n case 'v3':\n case 'c':\n addElement(value, data)\n break\n default:\n data.push(value)\n }\n }\n\n static objectToShape (shape: Shape, data: any) {\n Object.keys(this.fields).forEach(name => {\n this.valueToShape(shape, name, data[name])\n })\n this.valueToShape(shape, 'name', data.name)\n this.expandBoundingBox(shape.boundingBox, data)\n }\n\n static valueFromShape (shape: Shape, pid: number, name: string) {\n const data = shape._primitiveData[this.getShapeKey(name)]\n const type = this.fields[name]\n\n switch (type) {\n case 'v3':\n return new Vector3().fromArray(data, 3 * pid)\n case 'c':\n return new Color().fromArray(data, 3 * pid)\n default:\n return data[pid]\n }\n }\n\n static objectFromShape (shape: Shape, pid: number) {\n let name = this.valueFromShape(shape, pid, 'name')\n if (name === undefined) {\n name = `${this.type}: ${pid} (${shape.name})`\n }\n const o: any = { shape, name }\n\n Object.keys(this.fields).forEach(name => {\n o[name] = this.valueFromShape(shape, pid, name)\n })\n\n return o\n }\n\n static arrayFromShape (shape: Shape, name: string) {\n const data = shape._primitiveData[this.getShapeKey(name)]\n const type = this.fields[name]\n\n switch (type) {\n case 's':\n return data\n default:\n return new Float32Array(data)\n }\n }\n\n static dataFromShape (shape: Shape) {\n const data: any = {}\n\n if (this.Picker) {\n data.picking = new this.Picker(shape)\n }\n\n Object.keys(this.fields).forEach(name => {\n data[name] = this.arrayFromShape(shape, name)\n })\n\n return data\n }\n\n static bufferFromShape (shape: Shape, params: any) {\n return new this.Buffer(this.dataFromShape(shape), params)\n }\n}\n\n/**\n * Sphere geometry primitive\n */\nexport class SpherePrimitive extends Primitive {\n static type = 'sphere'\n\n static fields = {\n position: 'v3',\n color: 'c',\n radius: 'f'\n }\n\n static positionFromShape (shape: Shape, pid: number) {\n return this.valueFromShape(shape, pid, 'position')\n }\n\n static expandBoundingBox (box: Box3, data: any) {\n box.expandByPoint(tmpVec.fromArray(data.position))\n }\n}\n\n/**\n * Box geometry primitive\n */\nexport class BoxPrimitive extends Primitive {\n static type = 'box'\n\n static fields = {\n position: 'v3',\n color: 'c',\n size: 'f',\n heightAxis: 'v3',\n depthAxis: 'v3'\n }\n\n static positionFromShape (shape: Shape, pid: number) {\n return this.valueFromShape(shape, pid, 'position')\n }\n\n static expandBoundingBox (box: Box3, data: any) {\n box.expandByPoint(tmpVec.fromArray(data.position))\n }\n}\n\n/**\n * Octahedron geometry primitive\n */\nexport class OctahedronPrimitive extends BoxPrimitive {\n static type = 'octahedron'\n}\n\n/**\n * Tetrahedron geometry primitive\n */\nexport class TetrahedronPrimitive extends BoxPrimitive {\n static type = 'tetrahedron'\n}\n\n/**\n * Cylinder geometry primitive\n */\nexport class CylinderPrimitive extends Primitive {\n static type = 'cylinder'\n\n static fields = {\n position1: 'v3',\n position2: 'v3',\n color: 'c',\n radius: 'f'\n }\n\n static positionFromShape (shape: Shape, pid: number) {\n const p1 = this.valueFromShape(shape, pid, 'position1')\n const p2 = this.valueFromShape(shape, pid, 'position2')\n return p1.add(p2).multiplyScalar(0.5)\n }\n\n static expandBoundingBox (box: Box3, data: any) {\n box.expandByPoint(tmpVec.fromArray(data.position1))\n box.expandByPoint(tmpVec.fromArray(data.position2))\n }\n\n static bufferFromShape (shape: Shape, params: any = {}) {\n let data = this.dataFromShape(shape)\n if (this.type === 'cylinder' && params.dashedCylinder) {\n data = getFixedLengthDashData(data)\n }\n return new this.Buffer(data, params)\n }\n}\n\n/**\n * Arrow geometry primitive\n */\nexport class ArrowPrimitive extends CylinderPrimitive {\n static type = 'arrow'\n}\n\n/**\n * Cone geometry primitive\n */\nexport class ConePrimitive extends CylinderPrimitive {\n static type = 'cone'\n}\n\n/**\n * Ellipsoid geometry primitive\n */\nexport class EllipsoidPrimitive extends SpherePrimitive {\n static type = 'ellipsoid'\n\n static fields = {\n position: 'v3',\n color: 'c',\n radius: 'f',\n majorAxis: 'v3',\n minorAxis: 'v3'\n }\n}\n\n/**\n * Torus geometry primitive\n */\nexport class TorusPrimitive extends EllipsoidPrimitive {\n static type = 'torus'\n}\n\n/**\n * Text geometry primitive\n */\nexport class TextPrimitive extends Primitive {\n static type = 'text'\n\n static fields = {\n position: 'v3',\n color: 'c',\n size: 'f',\n text: 's'\n }\n\n static positionFromShape (shape: Shape, pid: number) {\n return this.valueFromShape(shape, pid, 'position')\n }\n\n static expandBoundingBox (box: Box3, data: any) {\n box.expandByPoint(tmpVec.fromArray(data.position))\n }\n}\n\n/**\n * Point primitive\n */\nexport class PointPrimitive extends Primitive {\n static type = 'point'\n\n static fields = {\n position: 'v3',\n color: 'c',\n }\n\n static positionFromShape (shape: Shape, pid: number) {\n return this.valueFromShape(shape, pid, 'position')\n }\n\n static expandBoundingBox (box: Box3, data: any) {\n box.expandByPoint(tmpVec.fromArray(data.position))\n }\n}\n\n/**\n * Wideline geometry primitive\n */\nexport class WidelinePrimitive extends Primitive {\n static type = 'wideline'\n\n static fields = {\n position1: 'v3',\n position2: 'v3',\n color: 'c'\n }\n\n static positionFromShape (shape: Shape, pid: number) {\n const p1 = this.valueFromShape(shape, pid, 'position1')\n const p2 = this.valueFromShape(shape, pid, 'position2')\n return p1.add(p2).multiplyScalar(0.5)\n }\n\n static expandBoundingBox (box: Box3, data: any) {\n box.expandByPoint(tmpVec.fromArray(data.position1))\n box.expandByPoint(tmpVec.fromArray(data.position2))\n }\n}\n","/**\n * @file Spatial Hash\n * @author Alexander Rose \n * @private\n */\n\nimport { Box3 } from 'three'\n\nexport type Positions = {\n x: ArrayLike,\n y: ArrayLike,\n z: ArrayLike,\n count?:number\n}\n\nfunction createBoundingBox(positions: Positions) {\n const { x, y, z } = positions\n const boundingBox = new Box3()\n const count = x.length\n const { min, max } = boundingBox\n\n for (let i = 0; i < count; i++) {\n min.x = Math.min(x[i], min.x)\n min.y = Math.min(y[i], min.y)\n min.z = Math.min(z[i], min.z)\n max.x = Math.max(x[i], max.x)\n max.y = Math.max(y[i], max.y)\n max.z = Math.max(z[i], max.z)\n }\n\n return boundingBox\n}\n\nexport default class SpatialHash {\n exp = 3\n\n minX: number\n minY: number\n minZ: number\n\n boundX: number\n boundY: number\n boundZ: number\n\n grid: Uint32Array\n bucketCount: Uint16Array\n bucketOffset: Uint32Array\n bucketArray: Int32Array\n\n xArray: ArrayLike\n yArray: ArrayLike\n zArray: ArrayLike\n\n constructor(positions: Positions, boundingBox?: Box3) {\n const bb = boundingBox || createBoundingBox(positions)\n this.minX = bb.min.x\n this.minY = bb.min.y\n this.minZ = bb.min.z\n this.boundX = ((bb.max.x - this.minX) >> this.exp) + 1\n this.boundY = ((bb.max.y - this.minY) >> this.exp) + 1\n this.boundZ = ((bb.max.z - this.minZ) >> this.exp) + 1\n\n const n = this.boundX * this.boundY * this.boundZ\n const an = (positions.count !== undefined) ? positions.count : positions.x.length\n\n const xArray = positions.x\n const yArray = positions.y\n const zArray = positions.z\n\n let count = 0\n const grid = new Uint32Array(n)\n const bucketIndex = new Int32Array(an)\n for (let i = 0; i < an; ++i) {\n const x = (xArray[ i ] - this.minX) >> this.exp\n const y = (yArray[ i ] - this.minY) >> this.exp\n const z = (zArray[ i ] - this.minZ) >> this.exp\n const idx = (((x * this.boundY) + y) * this.boundZ) + z\n if ((grid[ idx ] += 1) === 1) {\n count += 1\n }\n bucketIndex[ i ] = idx\n }\n\n const bucketCount = new Uint16Array(count)\n for (let i = 0, j = 0; i < n; ++i) {\n const c = grid[ i ]\n if (c > 0) {\n grid[ i ] = j + 1\n bucketCount[ j ] = c\n j += 1\n }\n }\n\n const bucketOffset = new Uint32Array(count)\n for (let i = 1; i < count; ++i) {\n bucketOffset[ i ] += bucketOffset[ i - 1 ] + bucketCount[ i - 1 ]\n }\n\n const bucketFill = new Uint16Array(count)\n const bucketArray = new Int32Array(an)\n for (let i = 0; i < an; ++i) {\n const bucketIdx = grid[ bucketIndex[ i ] ]\n if (bucketIdx > 0) {\n const k = bucketIdx - 1\n bucketArray[ bucketOffset[ k ] + bucketFill[ k ] ] = i\n bucketFill[ k ] += 1\n }\n }\n\n this.grid = grid\n this.bucketCount = bucketCount\n this.bucketOffset = bucketOffset\n this.bucketArray = bucketArray\n\n this.xArray = xArray\n this.yArray = yArray\n this.zArray = zArray\n }\n\n within (x: number, y: number, z: number, r: number) {\n const result: number[] = []\n\n this.eachWithin(x, y, z, r, atomIndex => result.push(atomIndex))\n\n return result\n }\n\n eachWithin (x: number, y: number, z: number, r: number, callback: (atomIndex: number, dSq: number) => void) {\n const rSq = r * r\n\n const loX = Math.max(0, (x - r - this.minX) >> this.exp)\n const loY = Math.max(0, (y - r - this.minY) >> this.exp)\n const loZ = Math.max(0, (z - r - this.minZ) >> this.exp)\n\n const hiX = Math.min(this.boundX, ((x + r - this.minX) >> this.exp) + 1)\n const hiY = Math.min(this.boundY, ((y + r - this.minY) >> this.exp) + 1)\n const hiZ = Math.min(this.boundZ, ((z + r - this.minZ) >> this.exp) + 1)\n\n for (let ix = loX; ix < hiX; ++ix) {\n for (let iy = loY; iy < hiY; ++iy) {\n for (let iz = loZ; iz < hiZ; ++iz) {\n const idx = (((ix * this.boundY) + iy) * this.boundZ) + iz\n const bucketIdx = this.grid[ idx ]\n\n if (bucketIdx > 0) {\n const k = bucketIdx - 1\n const offset = this.bucketOffset[ k ]\n const count = this.bucketCount[ k ]\n const end = offset + count\n\n for (let i = offset; i < end; ++i) {\n const atomIndex = this.bucketArray[ i ]\n const dx = this.xArray[ atomIndex ] - x\n const dy = this.yArray[ atomIndex ] - y\n const dz = this.zArray[ atomIndex ] - z\n\n const dSq = dx * dx + dy * dy + dz * dz\n if (dSq <= rSq) callback(atomIndex, dSq)\n }\n }\n }\n }\n }\n }\n}","/**\n * @file Store\n * @author Alexander Rose \n * @private\n */\n\nimport { Log } from '../globals'\nimport { getTypedArray, TypedArrayString } from '../utils'\n\nexport type StoreField = [string, number, TypedArrayString]\n\n/**\n * Store base class\n * @interface\n */\nexport default class Store {\n [k: string]: any\n\n length: number\n count: number\n\n _fields: StoreField[]\n get _defaultFields(): StoreField[] { return [] }\n\n /**\n * @param {Integer} [size] - initial size\n */\n constructor (size = 0) {\n this._fields = this._defaultFields\n this._init(0)\n }\n\n /**\n * Initialize the store\n * @param {Integer} size - size to initialize\n * @return {undefined}\n */\n _init (size: number) {\n this.length = size\n this.count = 0\n\n for (let i = 0, il = this._fields.length; i < il; ++i) {\n const [name, size, type]: StoreField = this._fields[ i ]\n this._initField(name, size, type)\n }\n }\n\n /**\n * Initialize a field\n * @param {String} name - field name\n * @param {Integer} size - element size\n * @param {String} type - data type, one of int8, int16, int32,\n * uint8, uint16, uint32, float32\n * @return {undefined}\n */\n _initField (name: string, size: number, type: TypedArrayString) {\n this[ name ] = getTypedArray(type, this.length * size)\n }\n\n /**\n * Add a field\n * @param {String} name - field name\n * @param {Integer} size - element size\n * @param {String} type - data type, one of int8, int16, int32,\n * uint8, uint16, uint32, float32\n * @return {undefined}\n */\n addField (name: string, size: number, type: TypedArrayString) {\n this._fields.push([name, size, type])\n this._initField(name, size, type)\n }\n\n /**\n * Resize the store to the new size\n * @param {Integer} size - new size\n * @return {undefined}\n */\n resize (size?: number) {\n // Log.time( \"Store.resize\" );\n\n this.length = Math.round(size || 0)\n this.count = Math.min(this.count, this.length)\n\n for (let i = 0, il = this._fields.length; i < il; ++i) {\n const name = this._fields[ i ][ 0 ]\n const itemSize = this._fields[ i ][ 1 ]\n const arraySize = this.length * itemSize\n const tmpArray = new this[ name ].constructor(arraySize)\n\n if (this[ name ].length > arraySize) {\n tmpArray.set(this[ name ].subarray(0, arraySize))\n } else {\n tmpArray.set(this[ name ])\n }\n this[ name ] = tmpArray\n }\n\n // Log.timeEnd( \"Store.resize\" );\n }\n\n /**\n * Resize the store to 1.5 times its current size if full\n * @return {undefined}\n */\n growIfFull () {\n if (this.count >= this.length) {\n const size = Math.round(this.length * 1.5)\n this.resize(Math.max(256, size))\n }\n }\n\n /**\n * Copy data from one store to another\n * @param {Store} other - store to copy from\n * @param {Integer} thisOffset - offset to start copying to\n * @param {Integer} otherOffset - offset to start copying from\n * @param {Integer} length - number of entries to copy\n * @return {undefined}\n */\n copyFrom (other: Store, thisOffset: number, otherOffset: number, length: number) {\n for (let i = 0, il = this._fields.length; i < il; ++i) {\n const name = this._fields[ i ][ 0 ]\n const itemSize = this._fields[ i ][ 1 ]\n const thisField = this[ name ]\n const otherField = other[ name ]\n\n for (let j = 0; j < length; ++j) {\n const thisIndex = itemSize * (thisOffset + j)\n const otherIndex = itemSize * (otherOffset + j)\n for (let k = 0; k < itemSize; ++k) {\n thisField[ thisIndex + k ] = otherField[ otherIndex + k ]\n }\n }\n }\n }\n\n /**\n * Copy data within this store\n * @param {Integer} thisOffset - offset to start copying to\n * @param {Integer} otherOffset - offset to start copying from\n * @param {Integer} length - number of entries to copy\n * @return {undefined}\n */\n copyWithin (offsetTarget: number, offsetSource: number, length: number) {\n for (let i = 0, il = this._fields.length; i < il; ++i) {\n const name = this._fields[ i ][ 0 ]\n const itemSize = this._fields[ i ][ 1 ]\n const thisField = this[ name ]\n\n for (let j = 0; j < length; ++j) {\n const targetIndex = itemSize * (offsetTarget + j)\n const sourceIndex = itemSize * (offsetSource + j)\n for (let k = 0; k < itemSize; ++k) {\n thisField[ targetIndex + k ] = thisField[ sourceIndex + k ]\n }\n }\n }\n }\n\n /**\n * Sort entries in the store given the compare function\n * @param {[type]} compareFunction - function to sort by\n * @return {undefined}\n */\n sort (compareFunction: (a: any, b: any) => number) {\n Log.time('Store.sort')\n\n const thisStore = this\n const tmpStore = new (this.constructor as any)(1)\n\n function swap (index1: number, index2: number) {\n if (index1 === index2) return\n tmpStore.copyFrom(thisStore, 0, index1, 1)\n thisStore.copyWithin(index1, index2, 1)\n thisStore.copyFrom(tmpStore, index2, 0, 1)\n }\n\n function quicksort (left: number, right: number) {\n if (left < right) {\n let pivot = Math.floor((left + right) / 2)\n let leftNew = left\n let rightNew = right\n do {\n while (compareFunction(leftNew, pivot) < 0) {\n leftNew += 1\n }\n while (compareFunction(rightNew, pivot) > 0) {\n rightNew -= 1\n }\n if (leftNew <= rightNew) {\n if (leftNew === pivot) {\n pivot = rightNew\n } else if (rightNew === pivot) {\n pivot = leftNew\n }\n swap(leftNew, rightNew)\n leftNew += 1\n rightNew -= 1\n }\n } while (leftNew <= rightNew)\n quicksort(left, rightNew)\n quicksort(leftNew, right)\n }\n }\n\n quicksort(0, this.count - 1)\n\n Log.timeEnd('Store.sort')\n }\n\n /**\n * Empty the store\n * @return {undefined}\n */\n clear () {\n this.count = 0\n }\n\n /**\n * Dispose of the store entries and fields\n * @return {undefined}\n */\n dispose () {\n\n for (let i = 0, il = this._fields.length; i < il; ++i) {\n const name = this._fields[ i ][ 0 ]\n delete this[ name ]\n }\n }\n}\n","/**\n * @file Contact Store\n * @author Alexander Rose \n * @private\n */\n\nimport Store, { StoreField } from './store'\n\n/**\n * Bond store\n */\nexport default class ContactStore extends Store {\n index1: Uint32Array\n index2: Uint32Array\n type: Uint8Array\n\n get _defaultFields () {\n return [\n [ 'index1', 1, 'int32' ],\n [ 'index2', 1, 'int32' ],\n [ 'type', 1, 'int8' ]\n ] as StoreField[]\n }\n\n addContact (index1: number, index2: number, type?: number) {\n this.growIfFull()\n\n const i = this.count\n\n if (index1 < index2) {\n this.index1[ i ] = index1\n this.index2[ i ] = index2\n } else {\n this.index2[ i ] = index1\n this.index1[ i ] = index2\n }\n if (type) this.type[ i ] = type\n\n this.count += 1\n }\n}","/**\n * @file Bit array\n * @author Alexander Rose \n * @author Paul Pillot \n * @private\n */\n\n/**\n * Compute the Hamming weight of a 32-bit unsigned integer\n * @param {Integer} v - a 32-bit unsigned integer\n * @return {Integer} the Hamming weight\n */\nfunction hammingWeight (v: number) {\n // works with signed or unsigned shifts\n v -= ((v >>> 1) & 0x55555555)\n v = (v & 0x33333333) + ((v >>> 2) & 0x33333333)\n return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24\n}\n\n/**\n * Bit array\n *\n * Based heavily on https://github.com/lemire/FastBitSet.js\n * which is licensed under the Apache License, Version 2.0.\n */\nexport default class BitArray {\n private _words: Uint32Array\n public length: number\n\n /**\n * @param {Integer} length - array length\n * @param {Boolean} [setAll] - initialize with true\n */\n constructor (length: number, setAll?: boolean) {\n this.length = length\n this._words = new Uint32Array((length + 32) >>> 5)\n if (setAll === true) {\n this.setAll()\n }\n }\n\n /**\n * Get value at index\n * @param {Integer} index - the index\n * @return {Boolean} value\n */\n get (index: number) {\n return (this._words[ index >>> 5 ] & (1 << index)) !== 0\n }\n\n /**\n * Set value at index to true\n * @param {Integer} index - the index\n * @return {undefined}\n */\n set (index: number) {\n this._words[ index >>> 5 ] |= 1 << index\n }\n\n /**\n * Set value at index to false\n * @param {Integer} index - the index\n * @return {undefined}\n */\n clear (index: number) {\n this._words[ index >>> 5 ] &= ~(1 << index)\n }\n\n /**\n * Flip value at index\n * @param {Integer} index - the index\n * @return {undefined}\n */\n flip (index: number) {\n this._words[ index >>> 5 ] ^= 1 << index\n }\n\n _assignRange (start: number, end: number, value: boolean) {\n if (end < start) return\n const words = this._words\n const wordValue = value === true ? 0xFFFFFFFF : 0\n const wordStart = start >>> 5\n const wordEnd = end >>> 5\n // set complete words when applicable\n for (let k = wordStart + 1; k < wordEnd; ++k) {\n words[ k ] = wordValue\n }\n // set parts of the range not spanning complete words\n const startWord = wordStart << 5\n const endWord = wordEnd << 5\n if (value === true) {\n if (end - start < 32) {\n for (let i = start, n = end + 1; i < n; ++i) {\n words[ i >>> 5 ] |= 1 << i\n }\n } else {\n for (let i = start, n = startWord + 32; i < n; ++i) {\n words[ i >>> 5 ] |= 1 << i\n }\n for (let i = endWord, n = end + 1; i < n; ++i) {\n words[ i >>> 5 ] |= 1 << i\n }\n }\n } else {\n if (end - start < 32) {\n for (let i = start, n = end + 1; i < n; ++i) {\n words[ i >>> 5 ] &= ~(1 << i)\n }\n } else {\n for (let i = start, n = startWord + 32; i < n; ++i) {\n words[ i >>> 5 ] &= ~(1 << i)\n }\n for (let i = endWord, n = end + 1; i < n; ++i) {\n words[ i >>> 5 ] &= ~(1 << i)\n }\n }\n }\n return this\n }\n\n /**\n * Set bits of the given range\n * @param {Integer} start - start index\n * @param {Integer} end - end index\n * @return {BitArray} this object\n */\n setRange (start: number, end: number) {\n return this._assignRange(start, end, true)\n }\n\n /**\n * Clear bits of the given range\n * @param {Integer} start - start index\n * @param {Integer} end - end index\n * @return {BitArray} this object\n */\n clearRange (start: number, end: number) {\n return this._assignRange(start, end, false)\n }\n\n /**\n * Set bits at all given indices\n * @param {...Integer} arguments - indices\n * @return {Boolean} this object\n */\n setBits (...indices: number[]) {\n const words = this._words\n const n = indices.length\n for (let i = 0; i < n; ++i) {\n const index = indices[ i ]\n words[ index >>> 5 ] |= 1 << index\n }\n return this\n }\n\n /**\n * Clear bits at all given indices\n * @param {...Integer} arguments - indices\n * @return {Boolean} this object\n */\n clearBits (...indices: number[]) {\n const words = this._words\n const n = indices.length\n for (let i = 0; i < n; ++i) {\n const index = indices[ i ]\n words[ index >>> 5 ] &= ~(1 << index)\n }\n return this\n }\n\n /**\n * Set all bits of the array\n * @return {BitArray} this object\n */\n setAll () {\n return this._assignRange(0, this.length - 1, true)\n }\n\n /**\n * Clear all bits of the array\n * @return {BitArray} this object\n */\n clearAll () {\n return this._assignRange(0, this.length - 1, false)\n }\n\n /**\n * Flip all the values in the array\n * @return {BitArray} this object\n */\n flipAll () {\n const count = this._words.length\n const words = this._words\n const bs = 32 - this.length % 32\n for (let k = 0; k < count - 1; ++k) {\n words[k] = ~words[ k ]\n }\n words[ count - 1 ] = (~(words[ count - 1 ] << bs)) >>> bs\n return this\n }\n\n _isRangeValue (start: number, end: number, value: boolean) {\n if (end < start) return\n const words = this._words\n const wordValue = value === true ? 0xFFFFFFFF : 0\n const wordStart = start >>> 5\n const wordEnd = end >>> 5\n // set complete words when applicable\n for (let k = wordStart + 1; k < wordEnd; ++k) {\n if (words[ k ] !== wordValue) return false\n }\n // set parts of the range not spanning complete words\n if (end - start < 32) {\n for (let i = start, n = end + 1; i < n; ++i) {\n if (!!(words[ i >>> 5 ] & (1 << i)) !== value) return false\n }\n } else {\n const startWord = wordStart << 5\n const endWord = wordEnd << 5\n for (let i = start, n = startWord + 32; i < n; ++i) {\n if (!!(words[ i >>> 5 ] & (1 << i)) !== value) return false\n }\n for (let i = endWord, n = end + 1; i < n; ++i) {\n if (!!(words[ i >>> 5 ] & (1 << i)) !== value) return false\n }\n }\n return true\n }\n\n /**\n * Test if bits in given range are set\n * @param {Integer} start - start index\n * @param {Integer} end - end index\n * @return {BitArray} this object\n */\n isRangeSet (start: number, end: number) {\n return this._isRangeValue(start, end, true)\n }\n\n /**\n * Test if bits in given range are clear\n * @param {Integer} start - start index\n * @param {Integer} end - end index\n * @return {BitArray} this object\n */\n isRangeClear (start: number, end: number) {\n return this._isRangeValue(start, end, false)\n }\n\n /**\n * Test if all bits in the array are set\n * @return {Boolean} test result\n */\n isAllSet () {\n return this._isRangeValue(0, this.length - 1, true)\n }\n\n /**\n * Test if all bits in the array are clear\n * @return {Boolean} test result\n */\n isAllClear () {\n return this._isRangeValue(0, this.length - 1, false)\n }\n\n /**\n * Test if bits at all given indices are set\n * @param {...Integer} arguments - indices\n * @return {Boolean} test result\n */\n isSet (...indices: number[]) {\n const words = this._words\n const n = indices.length\n for (let i = 0; i < n; ++i) {\n const index = indices[ i ]\n if ((words[ index >>> 5 ] & (1 << index)) === 0) return false\n }\n return true\n }\n\n /**\n * Test if bits at all given indices are clear\n * @param {...Integer} arguments - indices\n * @return {Boolean} test result\n */\n isClear (...indices: number[]) {\n const words = this._words\n const n = indices.length\n for (let i = 0; i < n; ++i) {\n const index = indices[ i ]\n if ((words[ index >>> 5 ] & (1 << index)) !== 0) return false\n }\n return true\n }\n\n /**\n * Test if two BitArrays are identical in all their values\n * @param {BitArray} otherBitarray - the other BitArray\n * @return {Boolean} test result\n */\n isEqualTo (otherBitarray: BitArray) {\n const words1 = this._words\n const words2 = otherBitarray._words\n const count = Math.min(words1.length, words2.length)\n for (let k = 0; k < count; ++k) {\n if (words1[ k ] !== words2[ k ]) {\n return false\n }\n }\n return true\n }\n\n /**\n * How many set bits?\n * @return {Integer} number of set bits\n */\n getSize () {\n const count = this._words.length\n const words = this._words\n let size = 0\n for (let i = 0; i < count; ++i) {\n size += hammingWeight(words[ i ])\n }\n return size\n }\n\n /**\n * Calculate difference betwen this and another bit array.\n * Store result in this object.\n * @param {BitArray} otherBitarray - the other bit array\n * @return {BitArray} this object\n */\n difference (otherBitarray: BitArray) {\n const words1 = this._words\n const words2 = otherBitarray._words\n const count = Math.min(words1.length, words2.length)\n for (let k = 0; k < count; ++k) {\n words1[ k ] = words1[ k ] & ~words2[ k ]\n }\n for (let k = words1.length; k < count; ++k) {\n words1[ k ] = 0\n }\n return this\n }\n\n /**\n * Calculate union betwen this and another bit array.\n * Store result in this object.\n * @param {BitArray} otherBitarray - the other bit array\n * @return {BitArray} this object\n */\n union (otherBitarray: BitArray) {\n const words1 = this._words\n const words2 = otherBitarray._words\n const count = Math.min(words1.length, words2.length)\n for (let k = 0; k < count; ++k) {\n words1[ k ] |= words2[ k ]\n }\n for (let k = words1.length; k < count; ++k) {\n words1[ k ] = 0\n }\n return this\n }\n\n /**\n * Calculate intersection betwen this and another bit array.\n * Store result in this object.\n * @param {BitArray} otherBitarray - the other bit array\n * @return {BitArray} this object\n */\n intersection (otherBitarray: BitArray) {\n const words1 = this._words\n const words2 = otherBitarray._words\n const count = Math.min(words1.length, words2.length)\n for (let k = 0; k < count; ++k) {\n words1[ k ] &= words2[ k ]\n }\n for (let k = words1.length; k < count; ++k) {\n words1[ k ] = 0\n }\n return this\n }\n\n /**\n * Test if there is any intersection betwen this and another bit array.\n * @param {BitArray} otherBitarray - the other bit array\n * @return {Boolean} test result\n */\n intersects (otherBitarray: BitArray) {\n const words1 = this._words\n const words2 = otherBitarray._words\n const count = Math.min(words1.length, words2.length)\n for (let k = 0; k < count; ++k) {\n if ((words1[ k ] & words2[ k ]) !== 0) {\n return true\n }\n }\n return false\n }\n\n /**\n * Calculate the number of bits in common betwen this and another bit array.\n * @param {BitArray} otherBitarray - the other bit array\n * @return {Integer} size\n */\n getIntersectionSize (otherBitarray: BitArray) {\n const words1 = this._words\n const words2 = otherBitarray._words\n const count = Math.min(words1.length, words2.length)\n let size = 0\n for (let k = 0; k < count; ++k) {\n size += hammingWeight(words1[ k ] & words2[ k ])\n }\n return size\n }\n\n /**\n * Calculate intersection betwen this and another bit array.\n * Store result in a new bit array.\n * @param {BitArray} otherBitarray - the other bit array\n * @return {BitArray} the new bit array\n */\n makeIntersection (otherBitarray: BitArray) {\n const words1 = this._words\n const words2 = otherBitarray._words\n const count = Math.min(words1.length, words2.length)\n const wordsA = new Uint32Array(count)\n const intersection = Object.create(BitArray.prototype)\n intersection._words = wordsA\n intersection.length = Math.min(this.length, otherBitarray.length)\n for (let k = 0; k < count; ++k) {\n wordsA[ k ] = words1[ k ] & words2[ k ]\n }\n return intersection\n }\n\n /**\n * Iterate over all set bits in the array\n * @param {function( index: Integer, i: Integer )} callback - the callback\n * @return {undefined}\n */\n forEach (callback: (index: number, i: number) => any) {\n const count = this._words.length\n const words = this._words\n let i = 0\n for (let k = 0; k < count; ++k) {\n let w = words[ k ]\n while (w !== 0) {\n const t = w & -w\n const index = (k << 5) + hammingWeight(t - 1)\n callback(index, i)\n w ^= t\n ++i\n }\n }\n }\n\n /**\n * Get an array with the set bits\n * @return {Array} bit indices\n */\n toArray () {\n const words = this._words\n const answer = new Array(this.getSize())\n const count = this._words.length\n let pos = 0\n for (let k = 0; k < count; ++k) {\n let w = words[ k ]\n while (w !== 0) {\n const t = w & -w\n answer[ pos++ ] = (k << 5) + hammingWeight(t - 1)\n w ^= t\n }\n }\n return answer\n }\n\n toString () {\n return '{' + this.toArray().join(',') + '}'\n }\n\n toSeleString () {\n const sele = this.toArray().join(',')\n return sele ? '@' + sele : 'NONE'\n }\n\n /**\n * Clone this object\n * @return {BitArray} the cloned object\n */\n clone () {\n const clone = Object.create(BitArray.prototype)\n clone.length = this.length\n clone._words = new Uint32Array(this._words)\n return clone\n }\n}","/**\n * @file Adjacency List\n * @author Alexander Rose \n * @private\n */\n\nexport interface Edges {\n nodeArray1: ArrayLike\n nodeArray2: ArrayLike\n edgeCount: number\n nodeCount: number\n}\n\nexport interface AdjacencyList {\n /* number of edges for each node */\n countArray: Uint8Array\n /* offset into indexArray for each node */\n offsetArray: Int32Array\n /* edge indices, grouped by nodes */\n indexArray: Int32Array\n}\n\nexport function createAdjacencyList (edges: Edges): AdjacencyList {\n const { edgeCount, nodeCount, nodeArray1, nodeArray2 } = edges\n\n const countArray = new Uint8Array(nodeCount)\n const offsetArray = new Int32Array(nodeCount)\n\n // count edges per node\n for (let i = 0; i < edgeCount; ++i) {\n countArray[ nodeArray1[ i ] ] += 1\n countArray[ nodeArray2[ i ] ] += 1\n }\n\n // get offsets to node edges\n for (let i = 1; i < nodeCount; ++i) {\n offsetArray[ i ] += offsetArray[ i - 1 ] + countArray[ i - 1 ]\n }\n\n // prepare index array\n const bondCount2 = edgeCount * 2\n const indexArray = new Int32Array(bondCount2)\n for (let j = 0; j < bondCount2; ++j) {\n indexArray[ j ] = -1\n }\n\n // build index array\n for (let i = 0; i < edgeCount; ++i) {\n const idx1 = nodeArray1[ i ]\n const idx2 = nodeArray2[ i ]\n let j1 = offsetArray[ idx1 ]\n while (indexArray[ j1 ] !== -1 && j1 < bondCount2) {\n j1 += 1\n }\n indexArray[ j1 ] = i\n let j2 = offsetArray[ idx2 ]\n while (indexArray[ j2 ] !== -1 && j2 < bondCount2) {\n j2 += 1\n }\n indexArray[ j2 ] = i\n }\n\n return { countArray, offsetArray, indexArray }\n}\n","/**\n * @file Features\n * @author Alexander Rose \n */\n\nimport AtomProxy from '../../proxy/atom-proxy'\n\nexport interface Features {\n types: FeatureType[]\n groups: FeatureGroup[]\n centers: { x: number[], y: number[], z: number[] }\n atomSets: number[][]\n}\n\nexport const enum FeatureType {\n Unknown = 0,\n PositiveCharge = 1,\n NegativeCharge = 2,\n AromaticRing = 3,\n HydrogenDonor = 4,\n HydrogenAcceptor = 5,\n HalogenDonor = 6,\n HalogenAcceptor = 7,\n Hydrophobic = 8,\n WeakHydrogenDonor = 9,\n IonicTypePartner = 10,\n DativeBondPartner = 11,\n TransitionMetal = 12,\n IonicTypeMetal = 13\n}\n\nexport const enum FeatureGroup {\n Unknown = 0,\n QuaternaryAmine = 1,\n TertiaryAmine = 2,\n Sulfonium = 3,\n SulfonicAcid = 4,\n Sulfate = 5,\n Phosphate = 6,\n Halocarbon = 7,\n Guanidine = 8,\n Acetamidine = 9,\n Carboxylate = 10\n}\n\nexport function createFeatures (): Features {\n return {\n types: [],\n groups: [],\n centers: { x: [], y: [], z: [] },\n atomSets: []\n }\n}\n\nexport interface FeatureState {\n type: FeatureType\n group: FeatureGroup\n x: number\n y: number\n z: number\n atomSet: number[]\n}\n\nexport function createFeatureState(type = FeatureType.Unknown, group = FeatureGroup.Unknown): FeatureState {\n return { type, group, x: 0, y: 0, z: 0, atomSet: [] }\n}\n\nexport function addAtom (state: FeatureState, atom: AtomProxy) {\n state.x += atom.x\n state.y += atom.y\n state.z += atom.z\n state.atomSet.push(atom.index)\n}\n\nexport function addFeature (features: Features, state: FeatureState) {\n const n = state.atomSet.length\n if (n > 0) {\n const { types, groups, centers, atomSets } = features\n types.push(state.type)\n groups.push(state.group)\n centers.x.push(state.x / n)\n centers.y.push(state.y / n)\n centers.z.push(state.z / n)\n atomSets.push(state.atomSet)\n }\n}\n","/**\n * @file Structure Constants\n * @author Alexander Rose \n * @private\n */\n\n// entity types\nexport const UnknownEntity = 0\nexport const PolymerEntity = 1\nexport const NonPolymerEntity = 2\nexport const MacrolideEntity = 3\nexport const WaterEntity = 4\n\n// molecule types\nexport const UnknownType = 0\nexport const WaterType = 1\nexport const IonType = 2\nexport const ProteinType = 3\nexport const RnaType = 4\nexport const DnaType = 5\nexport const SaccharideType = 6\n\n// backbone types\nexport const UnknownBackboneType = 0\nexport const ProteinBackboneType = 1\nexport const RnaBackboneType = 2\nexport const DnaBackboneType = 3\nexport const CgProteinBackboneType = 4\nexport const CgRnaBackboneType = 5\nexport const CgDnaBackboneType = 6\n\n// chemical component types\nexport const ChemCompProtein = [\n 'D-BETA-PEPTIDE, C-GAMMA LINKING', 'D-GAMMA-PEPTIDE, C-DELTA LINKING',\n 'D-PEPTIDE COOH CARBOXY TERMINUS', 'D-PEPTIDE NH3 AMINO TERMINUS', 'D-PEPTIDE LINKING',\n 'L-BETA-PEPTIDE, C-GAMMA LINKING', 'L-GAMMA-PEPTIDE, C-DELTA LINKING',\n 'L-PEPTIDE COOH CARBOXY TERMINUS', 'L-PEPTIDE NH3 AMINO TERMINUS', 'L-PEPTIDE LINKING',\n 'PEPTIDE LINKING', 'PEPTIDE-LIKE'\n]\nexport const ChemCompRna = [\n 'RNA OH 3 PRIME TERMINUS', 'RNA OH 5 PRIME TERMINUS', 'RNA LINKING'\n]\nexport const ChemCompDna = [\n 'DNA OH 3 PRIME TERMINUS', 'DNA OH 5 PRIME TERMINUS', 'DNA LINKING',\n 'L-DNA LINKING', 'L-RNA LINKING'\n]\nexport const ChemCompSaccharide = [\n 'D-SACCHARIDE', 'D-SACCHARIDE 1,4 AND 1,4 LINKING', 'D-SACCHARIDE 1,4 AND 1,6 LINKING',\n 'L-SACCHARIDE', 'L-SACCHARIDE 1,4 AND 1,4 LINKING', 'L-SACCHARIDE 1,4 AND 1,6 LINKING',\n 'SACCHARIDE'\n]\nexport const ChemCompOther = [\n 'OTHER'\n]\nexport const ChemCompNonPolymer = [\n 'NON-POLYMER'\n]\nexport const ChemCompHetero = ChemCompNonPolymer.concat(ChemCompOther, ChemCompSaccharide)\n\n// secondary structure\nexport const SecStrucHelix = [ 'h', 'g', 'i' ]\nexport const SecStrucSheet = [ 'e', 'b' ]\nexport const SecStrucTurn = [ 's', 't', 'l', '' ]\n\nexport const AtomicNumbers: { [e: string]: number | undefined } = {\n 'H': 1, 'D': 1, 'T': 1, 'HE': 2, 'LI': 3, 'BE': 4, 'B': 5, 'C': 6, 'N': 7, 'O': 8, 'F': 9, 'NE': 10, 'NA': 11, 'MG': 12, 'AL': 13, 'SI': 14, 'P': 15, 'S': 16, 'CL': 17, 'AR': 18, 'K': 19, 'CA': 20, 'SC': 21, 'TI': 22, 'V': 23, 'CR': 24, 'MN': 25, 'FE': 26, 'CO': 27, 'NI': 28, 'CU': 29, 'ZN': 30, 'GA': 31, 'GE': 32, 'AS': 33, 'SE': 34, 'BR': 35, 'KR': 36, 'RB': 37, 'SR': 38, 'Y': 39, 'ZR': 40, 'NB': 41, 'MO': 42, 'TC': 43, 'RU': 44, 'RH': 45, 'PD': 46, 'AG': 47, 'CD': 48, 'IN': 49, 'SN': 50, 'SB': 51, 'TE': 52, 'I': 53, 'XE': 54, 'CS': 55, 'BA': 56, 'LA': 57, 'CE': 58, 'PR': 59, 'ND': 60, 'PM': 61, 'SM': 62, 'EU': 63, 'GD': 64, 'TB': 65, 'DY': 66, 'HO': 67, 'ER': 68, 'TM': 69, 'YB': 70, 'LU': 71, 'HF': 72, 'TA': 73, 'W': 74, 'RE': 75, 'OS': 76, 'IR': 77, 'PT': 78, 'AU': 79, 'HG': 80, 'TL': 81, 'PB': 82, 'BI': 83, 'PO': 84, 'AT': 85, 'RN': 86, 'FR': 87, 'RA': 88, 'AC': 89, 'TH': 90, 'PA': 91, 'U': 92, 'NP': 93, 'PU': 94, 'AM': 95, 'CM': 96, 'BK': 97, 'CF': 98, 'ES': 99, 'FM': 100, 'MD': 101, 'NO': 102, 'LR': 103, 'RF': 104, 'DB': 105, 'SG': 106, 'BH': 107, 'HS': 108, 'MT': 109, 'DS': 110, 'RG': 111, 'CN': 112, 'NH': 113, 'FL': 114, 'MC': 115, 'LV': 116, 'TS': 117, 'OG': 118\n}\nexport const DefaultAtomicNumber = 0\n\n/**\n * Enum mapping element to atomic number\n */\nexport const enum Elements {\n H = 1, D = 1, T = 1, HE = 2, LI = 3, BE = 4, B = 5, C = 6, N = 7, O = 8, F = 9, NE = 10, NA = 11, MG = 12, AL = 13, SI = 14, P = 15, S = 16, CL = 17, AR = 18, K = 19, CA = 20, SC = 21, TI = 22, V = 23, CR = 24, MN = 25, FE = 26, CO = 27, NI = 28, CU = 29, ZN = 30, GA = 31, GE = 32, AS = 33, SE = 34, BR = 35, KR = 36, RB = 37, SR = 38, Y = 39, ZR = 40, NB = 41, MO = 42, TC = 43, RU = 44, RH = 45, PD = 46, AG = 47, CD = 48, IN = 49, SN = 50, SB = 51, TE = 52, I = 53, XE = 54, CS = 55, BA = 56, LA = 57, CE = 58, PR = 59, ND = 60, PM = 61, SM = 62, EU = 63, GD = 64, TB = 65, DY = 66, HO = 67, ER = 68, TM = 69, YB = 70, LU = 71, HF = 72, TA = 73, W = 74, RE = 75, OS = 76, IR = 77, PT = 78, AU = 79, HG = 80, TL = 81, PB = 82, BI = 83, PO = 84, AT = 85, RN = 86, FR = 87, RA = 88, AC = 89, TH = 90, PA = 91, U = 92, NP = 93, PU = 94, AM = 95, CM = 96, BK = 97, CF = 98, ES = 99, FM = 100, MD = 101, NO = 102, LR = 103, RF = 104, DB = 105, SG = 106, BH = 107, HS = 108, MT = 109, DS = 110, RG = 111, CN = 112, NH = 113, FL = 114, MC = 115, LV = 116, TS = 117, OG = 118\n}\n\n// https://doi.org/10.1515/pac-2015-0305 (table 2, 3, and 4)\nexport const AtomWeights: { [e: number]: number | undefined } = {\n 1: 1.008, 2: 4.0026, 3: 6.94, 4: 9.0122, 5: 10.81, 6: 10.81, 7: 14.007, 8: 15.999, 9: 18.998, 10: 20.180, 11: 22.990, 12: 24.305, 13: 26.982, 14: 28.085, 15: 30.974, 16: 32.06, 17: 35.45, 18: 39.948, 19: 39.098, 20: 40.078, 21: 44.956, 22: 47.867, 23: 50.942, 24: 51.996, 25: 54.938, 26: 55.845, 27: 58.933, 28: 58.693, 29: 63.546, 30: 65.38, 31: 69.723, 32: 72.630, 33: 74.922, 34: 78.971, 35: 79.904, 36: 83.798, 37: 85.468, 38: 87.62, 39: 88.906, 40: 91.224, 41: 92.906, 42: 95.95, 43: 96.906, 44: 101.07, 45: 102.91, 46: 106.42, 47: 107.87, 48: 112.41, 49: 114.82, 50: 118.71, 51: 121.76, 52: 127.60, 53: 127.60, 54: 131.29, 55: 132.91, 56: 137.33, 57: 138.91, 58: 140.12, 59: 140.91, 60: 144.24, 61: 144.912, 62: 150.36, 63: 151.96, 64: 157.25, 65: 158.93, 66: 162.50, 67: 164.93, 68: 167.26, 69: 168.93, 70: 173.05, 71: 174.97, 72: 178.49, 73: 180.95, 74: 183.84, 75: 186.21, 76: 190.23, 77: 192.22, 78: 195.08, 79: 196.97, 80: 200.59, 81: 204.38, 82: 207.2, 83: 208.98, 84: 1.97, 85: 2.02, 86: 2.2, 87: 3.48, 88: 2.83, 89: 2.0, 90: 232.04, 91: 231.04, 92: 238.03, 93: 237.048, 94: 244.064, 95: 243.061, 96: 247.070, 97: 247.070, 98: 251.079, 99: 252.083, 100: 257.095, 101: 258.098, 102: 259.101, 103: 262.110, 104: 267.122, 105: 270.131, 106: 271.134, 107: 270.133, 108: 270.134, 109: 278.156, 110: 281.165, 111: 281.166, 112: 285.177, 113: 286.182, 114: 289.190, 115: 289.194, 116: 293.204, 117: 293.208, 118: 294.214\n}\nexport const DefaultAtomWeight = 10.81 // C\n\n// http://dx.doi.org/10.1021/jp8111556 (or 2.0)\nexport const VdwRadii: { [e: number]: number | undefined } = {\n 1: 1.1, 2: 1.4, 3: 1.81, 4: 1.53, 5: 1.92, 6: 1.7, 7: 1.55, 8: 1.52, 9: 1.47, 10: 1.54, 11: 2.27, 12: 1.73, 13: 1.84, 14: 2.1, 15: 1.8, 16: 1.8, 17: 1.75, 18: 1.88, 19: 2.75, 20: 2.31, 21: 2.3, 22: 2.15, 23: 2.05, 24: 2.05, 25: 2.05, 26: 2.05, 27: 2.0, 28: 2.0, 29: 2.0, 30: 2.1, 31: 1.87, 32: 2.11, 33: 1.85, 34: 1.9, 35: 1.83, 36: 2.02, 37: 3.03, 38: 2.49, 39: 2.4, 40: 2.3, 41: 2.15, 42: 2.1, 43: 2.05, 44: 2.05, 45: 2.0, 46: 2.05, 47: 2.1, 48: 2.2, 49: 2.2, 50: 1.93, 51: 2.17, 52: 2.06, 53: 1.98, 54: 2.16, 55: 3.43, 56: 2.68, 57: 2.5, 58: 2.48, 59: 2.47, 60: 2.45, 61: 2.43, 62: 2.42, 63: 2.4, 64: 2.38, 65: 2.37, 66: 2.35, 67: 2.33, 68: 2.32, 69: 2.3, 70: 2.28, 71: 2.27, 72: 2.25, 73: 2.2, 74: 2.1, 75: 2.05, 76: 2.0, 77: 2.0, 78: 2.05, 79: 2.1, 80: 2.05, 81: 1.96, 82: 2.02, 83: 2.07, 84: 1.97, 85: 2.02, 86: 2.2, 87: 3.48, 88: 2.83, 89: 2.0, 90: 2.4, 91: 2.0, 92: 2.3, 93: 2.0, 94: 2.0, 95: 2.0, 96: 2.0, 97: 2.0, 98: 2.0, 99: 2.0, 100: 2.0, 101: 2.0, 102: 2.0, 103: 2.0, 104: 2.0, 105: 2.0, 106: 2.0, 107: 2.0, 108: 2.0, 109: 2.0, 110: 2.0, 111: 2.0, 112: 2.0, 113: 2.0, 114: 2.0, 115: 2.0, 116: 2.0, 117: 2.0, 118: 2.0\n}\nexport const DefaultVdwRadius = 2.0 // C\n\n// Peter Rose (peter.rose@rcsb.org), private communication, average accross PDB\nexport const ResidueRadii: { [k: string]: number } = {\n '2QY': 6.58,\n 'CY0': 11.98,\n '2QZ': 2.52,\n 'CY1': 6.59,\n 'HHK': 5.11,\n 'CXM': 4.69,\n 'HHI': 4.58,\n 'CY4': 4.57,\n 'S12': 18.57,\n 'CY3': 2.79,\n 'C5C': 5.35,\n 'PFX': 11.84,\n '2R3': 6.94,\n '2R1': 3.78,\n 'ILX': 4.99,\n '32S': 5.68,\n 'BTK': 8.59,\n '32T': 5.72,\n 'FAK': 9.8,\n 'B27': 2.78,\n 'ILM': 3.84,\n 'C4R': 5.63,\n '32L': 6.75,\n 'SYS': 3.01,\n '1MH': 5.04,\n 'ILE': 3.65,\n 'YNM': 6.39,\n '2RX': 4.91,\n 'B3A': 2.48,\n 'GEE': 4.76,\n '7MN': 7.34,\n 'B3E': 5.4,\n 'ARG': 6.33,\n '200': 6.89,\n 'HIP': 5.47,\n 'HIA': 4.64,\n 'B3K': 5.89,\n 'HIC': 5.76,\n 'B3L': 4.96,\n 'B3M': 5.07,\n 'ARM': 6.86,\n 'ARO': 7.35,\n 'AR4': 8.42,\n 'PG1': 10.67,\n 'YOF': 6.44,\n 'IML': 3.74,\n 'SXE': 6.65,\n 'HIQ': 7.98,\n 'PFF': 6.31,\n 'HIS': 4.52,\n '0TD': 3.62,\n 'C3Y': 5.24,\n '1OP': 11.55,\n '02Y': 4.77,\n '02V': 4.83,\n 'ASB': 5.59,\n '30V': 8.53,\n 'S2P': 4.81,\n 'ASP': 3.55,\n 'ASN': 3.54,\n '2OR': 6.91,\n 'QMM': 6.13,\n '2P0': 8.52,\n 'ASL': 5.36,\n 'HFA': 5.14,\n '5PG': 5.69,\n 'B3X': 4.38,\n 'AS9': 4.1,\n 'ARV': 7.59,\n 'B3U': 6.06,\n 'S2C': 7.54,\n 'B3T': 3.34,\n '175': 5.64,\n 'GFT': 8.18,\n 'HG7': 6.8,\n 'B3Q': 4.48,\n 'ASA': 3.64,\n '02K': 2.94,\n 'B3Y': 7.45,\n 'PHD': 5.35,\n 'C6C': 6.42,\n 'BUC': 5.8,\n 'HGL': 8.07,\n 'PHE': 5.06,\n '03Y': 2.6,\n 'PHA': 5.11,\n 'OCY': 5.0,\n '4PH': 6.79,\n '5OH': 4.7,\n '31Q': 10.46,\n 'BTR': 7.98,\n '3PX': 4.7,\n '1PA': 8.07,\n 'ASX': 3.54,\n 'IOR': 7.23,\n '03E': 3.38,\n 'PHL': 5.17,\n 'KWS': 5.09,\n 'PHI': 7.12,\n 'NAL': 7.22,\n 'S1H': 19.21,\n '2ML': 3.86,\n '2MR': 7.35,\n 'GHG': 4.83,\n 'TYY': 6.54,\n '2MT': 3.67,\n '56A': 13.01,\n 'SVA': 5.46,\n 'TYX': 8.31,\n 'TYS': 8.59,\n 'TYR': 6.38,\n 'TYQ': 6.43,\n 'HLU': 3.99,\n 'MYK': 19.47,\n 'TYO': 7.71,\n 'HLX': 4.98,\n 'TYN': 9.87,\n 'TYJ': 6.25,\n 'TYI': 6.49,\n 'LYH': 5.13,\n 'LYF': 12.19,\n 'SUN': 6.73,\n 'LYR': 18.28,\n 'TYB': 6.46,\n '11W': 14.39,\n 'LYS': 5.54,\n 'LYN': 4.8,\n '11Q': 4.85,\n 'LYO': 4.71,\n 'LYZ': 1.76,\n 'TXY': 6.44,\n 'MYN': 4.71,\n 'TY5': 10.6,\n 'HMR': 5.09,\n '01W': 8.55,\n 'LYX': 13.36,\n 'TY8': 7.22,\n 'TY2': 6.49,\n 'KYN': 6.18,\n 'KYQ': 9.75,\n 'CZZ': 5.14,\n 'IIL': 3.81,\n 'HNC': 10.41,\n 'OIC': 4.62,\n 'LVN': 2.89,\n 'QIL': 3.84,\n 'JJL': 8.3,\n 'VAH': 3.88,\n 'JJJ': 7.5,\n 'JJK': 7.43,\n 'VAD': 2.56,\n 'CYW': 4.65,\n '0QL': 5.72,\n '143': 8.22,\n 'SVX': 7.04,\n 'CYJ': 11.64,\n 'SVY': 7.1,\n 'SVZ': 6.6,\n 'CYG': 8.03,\n 'CYF': 13.54,\n 'SVV': 5.09,\n 'GL3': 2.72,\n '8SP': 14.26,\n 'CYS': 2.78,\n '004': 4.33,\n 'CYR': 10.33,\n 'PLJ': 3.71,\n 'EXY': 7.37,\n 'HL2': 3.75,\n 'A5N': 5.21,\n 'CYQ': 5.67,\n 'CZ2': 5.16,\n 'LWY': 4.12,\n 'PM3': 8.78,\n 'OHS': 6.98,\n 'OHI': 5.35,\n '3TY': 8.42,\n 'CYD': 8.55,\n 'DYS': 7.87,\n 'DAH': 6.47,\n '4IK': 11.81,\n '3EG': 3.66,\n 'AYA': 3.65,\n '4IN': 6.31,\n 'DAB': 3.48,\n '4HT': 6.03,\n 'RGL': 7.03,\n 'DAM': 2.49,\n 'NFA': 5.04,\n 'WFP': 6.07,\n '2JC': 2.97,\n 'HAR': 7.55,\n '2JG': 5.67,\n 'MH6': 1.72,\n '2JF': 9.13,\n '3FG': 4.96,\n 'MGN': 4.84,\n 'AZH': 5.36,\n 'AZK': 6.03,\n 'ZBZ': 7.79,\n 'TBG': 2.58,\n 'VAL': 2.51,\n 'MGG': 7.34,\n 'AZS': 5.61,\n 'FHL': 9.75,\n '2JH': 4.56,\n 'IEL': 7.07,\n 'FHO': 6.75,\n 'DA2': 7.79,\n 'FH7': 6.99,\n 'ME0': 4.52,\n '3GL': 4.84,\n 'MDO': 5.03,\n 'AZY': 7.37,\n 'A8E': 3.76,\n 'ZCL': 6.71,\n 'MDH': 2.58,\n 'LA2': 14.07,\n '4FW': 6.1,\n 'YCM': 5.32,\n 'MDF': 4.95,\n 'YCP': 3.01,\n 'TEF': 8.63,\n 'FGP': 4.34,\n 'UF0': 19.72,\n 'XCN': 4.57,\n 'FGL': 2.56,\n 'MF3': 6.37,\n 'MEQ': 5.13,\n 'LAA': 3.23,\n 'IGL': 5.52,\n 'MET': 4.49,\n 'NIY': 6.81,\n 'QCS': 5.18,\n 'TCQ': 8.56,\n 'MEN': 4.33,\n '4HL': 8.79,\n 'MEA': 4.95,\n 'EFC': 5.28,\n 'LAL': 2.41,\n '2HF': 5.52,\n 'KBE': 5.64,\n 'OCS': 3.94,\n 'CAF': 5.46,\n 'NC1': 11.4,\n 'NBQ': 9.82,\n 'CAB': 4.19,\n 'MBQ': 9.55,\n '193': 7.38,\n '192': 2.44,\n '0WZ': 7.61,\n 'CAS': 5.35,\n 'NB8': 11.98,\n 'OBS': 11.71,\n '1AC': 2.42,\n 'PCA': 3.48,\n 'MCL': 9.73,\n 'LBY': 7.75,\n 'GAU': 4.67,\n 'PBF': 9.75,\n 'MCG': 6.46,\n 'DDE': 6.86,\n '19W': 3.94,\n 'MD5': 9.33,\n 'MD6': 6.44,\n 'MD3': 8.41,\n 'MCS': 7.56,\n 'OBF': 3.64,\n 'UAL': 4.68,\n 'PAT': 6.05,\n 'IAM': 8.88,\n 'PAQ': 8.77,\n 'FDL': 9.49,\n 'NCB': 3.45,\n 'LCK': 9.81,\n 'DDZ': 2.52,\n '2FM': 5.54,\n 'IAR': 6.77,\n 'OAS': 4.8,\n 'HBN': 8.8,\n 'TA4': 5.55,\n '1C3': 7.43,\n 'ECX': 5.51,\n 'PF5': 6.28,\n 'RE3': 5.29,\n 'FCL': 6.25,\n 'ECC': 4.79,\n 'LDH': 7.06,\n 'NCY': 2.91,\n 'CCS': 4.58,\n 'PEC': 6.54,\n '2CO': 4.45,\n 'LE1': 2.72,\n 'HCM': 5.53,\n '07O': 8.05,\n 'HCL': 4.96,\n 'NEP': 6.94,\n 'PE1': 8.01,\n 'LEF': 4.37,\n 'FC0': 5.18,\n 'LED': 4.34,\n 'HCS': 4.09,\n 'DBU': 2.49,\n 'RE0': 5.53,\n 'LEN': 3.82,\n '1E3': 8.71,\n 'BB9': 2.56,\n 'BB8': 5.14,\n 'PCS': 5.05,\n 'BB7': 4.56,\n 'BB6': 2.62,\n 'LEU': 3.83,\n 'DBZ': 7.08,\n 'LET': 11.29,\n 'DBY': 6.46,\n 'ICY': 7.76,\n 'MAA': 2.4,\n 'CGA': 7.91,\n '5CS': 8.34,\n 'UGY': 3.7,\n 'LGY': 11.71,\n 'N10': 8.96,\n 'AAR': 6.39,\n 'FT6': 7.5,\n 'MOD': 12.62,\n '5CW': 7.21,\n 'PVH': 4.58,\n 'BBC': 6.42,\n 'YYA': 7.3,\n 'O12': 14.08,\n 'NOT': 7.15,\n 'KGC': 9.88,\n 'MP4': 5.86,\n '0CS': 4.07,\n 'MP8': 3.75,\n 'VLL': 2.54,\n 'VLM': 2.51,\n 'BCS': 8.03,\n 'MNL': 4.9,\n 'AA4': 4.47,\n 'SAC': 3.49,\n 'BCX': 2.99,\n '3CF': 6.47,\n 'SAH': 11.7,\n 'NNH': 6.86,\n 'CGU': 4.71,\n 'SIB': 12.41,\n 'TLY': 8.78,\n 'SIC': 4.81,\n 'VMS': 8.82,\n 'TMD': 6.76,\n 'MMO': 6.53,\n 'PXU': 2.46,\n '4AW': 6.22,\n 'OTH': 3.6,\n 'DLS': 6.84,\n 'MME': 4.99,\n 'DM0': 6.99,\n '0FL': 2.76,\n 'SBL': 8.96,\n 'CDV': 3.72,\n 'OTY': 6.51,\n 'PYA': 7.75,\n '2AS': 3.57,\n 'DMH': 4.92,\n 'ELY': 7.42,\n 'GVL': 9.6,\n 'FVA': 2.9,\n 'SAR': 2.48,\n '4BF': 6.92,\n 'EME': 4.69,\n 'CDE': 2.51,\n '3AR': 7.86,\n '3AH': 9.11,\n 'AC5': 2.44,\n 'FTR': 6.08,\n 'MLL': 3.76,\n 'NPH': 11.66,\n 'NPI': 6.9,\n 'DMT': 6.67,\n 'PYX': 11.3,\n 'MLE': 3.87,\n 'PYL': 9.67,\n 'ZZU': 6.94,\n 'H5M': 3.61,\n 'SCH': 4.46,\n 'DMK': 3.52,\n 'FTY': 9.07,\n '2AG': 3.7,\n 'ABA': 2.55,\n 'ZZJ': 2.44,\n 'MLZ': 6.8,\n 'MLY': 6.88,\n 'KCX': 7.28,\n 'ZZD': 8.16,\n '3A5': 5.37,\n 'LHC': 7.75,\n '9AT': 2.47,\n 'OZT': 3.4,\n 'THO': 2.62,\n 'THR': 2.5,\n 'DFI': 3.93,\n 'MKD': 6.42,\n '4CY': 4.6,\n 'SDP': 6.07,\n 'DFO': 3.94,\n '0A0': 3.45,\n '4DB': 9.73,\n 'ML3': 6.26,\n 'BG1': 8.02,\n 'SD4': 4.57,\n 'THC': 3.8,\n 'SCS': 5.48,\n 'TH5': 4.65,\n 'BFD': 5.33,\n 'AEI': 6.34,\n 'TH6': 2.85,\n 'SCY': 4.53,\n 'TIS': 4.81,\n 'SEE': 4.53,\n 'BHD': 3.48,\n 'SEB': 8.18,\n 'SEC': 2.96,\n 'SEP': 4.8,\n 'CLH': 7.13,\n 'TIH': 5.02,\n 'CLG': 13.62,\n 'SEN': 6.43,\n 'XXA': 7.34,\n 'SEL': 2.46,\n 'SE7': 4.19,\n '4CF': 7.72,\n 'G8M': 3.57,\n 'BH2': 3.51,\n 'UN2': 3.22,\n 'VR0': 10.51,\n 'MK8': 4.76,\n 'DHA': 2.32,\n 'LMQ': 4.69,\n 'SFE': 5.01,\n 'AHB': 3.47,\n 'OXX': 7.05,\n 'BIF': 9.63,\n 'IZO': 4.47,\n 'NMM': 8.25,\n '0BN': 7.0,\n 'HZP': 3.12,\n 'NMC': 4.23,\n 'DHL': 2.69,\n '9DS': 9.29,\n 'SER': 2.41,\n 'CHG': 4.2,\n 'MIR': 6.54,\n 'AGQ': 7.79,\n 'SET': 2.46,\n 'MIS': 6.32,\n '4FB': 3.08,\n '0AR': 8.46,\n 'LME': 3.99,\n 'FZN': 24.42,\n 'AGT': 9.04,\n 'IYR': 6.46,\n '9DN': 9.31,\n 'CHP': 5.75,\n 'UNK': 1.64,\n 'XX1': 9.92,\n 'AGM': 6.57,\n '0AH': 5.78,\n 'LLP': 10.22,\n '0AF': 6.72,\n '4DP': 9.28,\n 'HYP': 2.25,\n 'DIR': 5.8,\n 'LLY': 8.71,\n '0AK': 6.11,\n 'NLE': 4.67,\n 'OYL': 6.42,\n 'WVL': 4.69,\n '0A8': 8.1,\n 'NLY': 6.37,\n 'MHO': 4.89,\n 'VOL': 2.55,\n '0A1': 7.1,\n 'MHL': 3.92,\n 'NLP': 4.81,\n 'NLQ': 4.65,\n 'MHW': 2.74,\n 'BIL': 4.7,\n 'NLO': 4.8,\n 'MHU': 7.51,\n 'XW1': 9.36,\n 'LLO': 10.13,\n 'SGB': 6.88,\n 'MHV': 3.6,\n 'MHS': 4.51,\n '0A9': 5.17,\n '0LF': 9.96,\n 'HT7': 6.82,\n 'X2W': 6.6,\n 'YPZ': 9.38,\n 'I58': 6.73,\n 'FLA': 2.4,\n 'M0H': 4.83,\n 'HSL': 2.46,\n 'FLE': 6.17,\n 'KOR': 10.1,\n '1VR': 3.89,\n 'HSO': 4.56,\n 'TTS': 9.41,\n 'RVX': 7.01,\n 'TTQ': 7.71,\n 'H14': 5.27,\n 'HTI': 7.8,\n 'ONH': 6.14,\n 'LP6': 8.58,\n 'ONL': 4.83,\n 'AHH': 5.06,\n 'HS8': 7.4,\n 'HS9': 4.71,\n 'BL2': 5.82,\n 'AHP': 5.26,\n '6HN': 7.34,\n 'HRP': 5.46,\n 'POM': 3.6,\n 'WPA': 5.11,\n '2ZC': 4.29,\n 'CPC': 2.65,\n 'AIB': 2.4,\n 'XSN': 3.47,\n 'M2S': 5.28,\n 'GND': 6.67,\n 'GNC': 4.6,\n 'MVA': 2.56,\n 'OLZ': 5.32,\n 'M2L': 6.15,\n 'TRF': 6.69,\n 'NZH': 7.66,\n 'SRZ': 5.27,\n 'OLD': 10.47,\n 'CME': 5.86,\n 'CMH': 5.3,\n 'ALA': 2.38,\n 'TRQ': 7.36,\n 'PPN': 7.24,\n 'TRP': 6.07,\n 'TRO': 5.82,\n 'TRN': 5.95,\n 'NYS': 8.1,\n 'ALC': 5.26,\n 'U3X': 11.7,\n 'HVA': 2.58,\n 'TS9': 3.92,\n 'TRX': 7.27,\n 'TRW': 11.8,\n 'LPL': 7.51,\n 'GMA': 4.4,\n 'OMT': 5.07,\n 'CMT': 3.54,\n 'GME': 4.66,\n 'NYB': 6.07,\n 'PR3': 5.12,\n 'LPD': 2.48,\n 'GLU': 4.49,\n '1X6': 6.84,\n 'LPG': 2.39,\n 'GLX': 4.52,\n 'PR4': 4.52,\n 'CML': 6.16,\n 'FME': 4.52,\n 'HTR': 6.48,\n 'PR7': 4.66,\n 'Z3E': 7.2,\n 'GLZ': 2.39,\n 'BMT': 6.37,\n 'WRP': 8.16,\n 'GLY': 2.37,\n 'OMY': 6.11,\n 'MTY': 5.46,\n 'OMX': 6.15,\n 'GLN': 4.46,\n '2XA': 8.25,\n '28X': 7.84,\n '7JA': 9.46,\n 'FLT': 9.65,\n 'GLJ': 3.7,\n 'OMH': 5.26,\n 'TSY': 4.26,\n 'PRV': 4.28,\n 'CS4': 11.21,\n 'DOA': 12.33,\n '23P': 5.42,\n 'CS3': 8.24,\n '6CL': 6.47,\n 'PRR': 5.58,\n 'KST': 11.58,\n 'CS1': 7.23,\n 'PRS': 2.63,\n 'ZYJ': 11.4,\n 'IT1': 9.75,\n 'UU5': 4.98,\n 'ESB': 6.69,\n 'UU4': 2.49,\n 'ESC': 5.65,\n 'LSO': 10.58,\n 'ZYK': 11.45,\n '9NV': 8.99,\n '23F': 5.27,\n 'ORN': 4.25,\n 'HOX': 6.61,\n 'CSD': 3.95,\n 'FP9': 3.03,\n 'DO2': 4.44,\n 'SLL': 11.53,\n 'P3Q': 9.54,\n 'ORQ': 6.04,\n 'MSL': 5.21,\n 'DNP': 2.45,\n 'CSB': 3.51,\n 'WLU': 4.24,\n 'CSA': 5.7,\n 'MT2': 5.51,\n 'CSO': 3.53,\n 'TPO': 4.73,\n 'MSP': 13.11,\n '23S': 6.09,\n 'MSO': 4.96,\n 'PRO': 2.41,\n 'TPL': 5.41,\n 'DNS': 8.79,\n 'CSK': 3.91,\n 'Z70': 7.4,\n 'CSJ': 7.51,\n 'DNW': 7.97,\n 'PRK': 9.15,\n 'GSU': 11.81,\n 'LTA': 6.57,\n 'HPE': 6.63,\n 'TPQ': 6.48,\n 'PRJ': 5.26,\n 'PSW': 4.65,\n 'L3O': 3.89,\n 'CSU': 4.89,\n 'ALY': 7.38,\n 'M3L': 7.12,\n 'CSW': 3.68,\n 'XPR': 7.68,\n 'D4P': 5.66,\n 'FOE': 8.17,\n 'SLZ': 5.69,\n 'CSP': 5.26,\n 'TQI': 7.68,\n 'ALT': 2.72,\n 'CSR': 5.42,\n 'CSS': 3.61,\n 'M3R': 7.18,\n 'ALO': 2.57,\n 'R4K': 4.67,\n 'SMF': 9.0,\n 'MSA': 2.73,\n 'SMC': 3.39,\n 'CSX': 3.47,\n 'SME': 4.8,\n 'ETA': 2.4,\n 'CSZ': 3.6,\n '22G': 8.8,\n 'MSE': 4.62,\n 'ALN': 6.16,\n 'PSH': 7.26,\n 'CTE': 7.27,\n 'DON': 6.72,\n 'CTH': 3.45,\n 'U2X': 11.54,\n '6CW': 7.56,\n 'TQZ': 6.97,\n '3YM': 6.52,\n 'OSE': 4.49,\n '2VA': 9.82,\n 'TQQ': 7.76,\n 'NRG': 8.35,\n 'BPE': 7.24,\n 'F2F': 6.25,\n '1TQ': 8.58,\n 'I2M': 3.13,\n 'NVA': 3.76,\n 'R1A': 8.2,\n 'QPA': 6.95,\n 'C1X': 11.63,\n 'FRD': 5.05,\n 'HR7': 6.98,\n 'SNC': 3.93,\n 'QPH': 5.15,\n '26B': 8.39,\n 'DPQ': 6.54,\n 'DPP': 2.51,\n '2TY': 8.65,\n 'TNR': 6.88,\n 'PTH': 8.35,\n 'DPL': 3.58,\n 'APK': 8.79,\n '1TY': 8.84,\n 'HRG': 7.36,\n 'PTM': 8.74,\n '1U8': 3.62,\n 'PTR': 8.64,\n 'LVG': 3.01,\n '6FL': 4.85,\n 'SOC': 4.05,\n 'KPI': 9.79,\n 'IPG': 2.91,\n 'P2Y': 2.51,\n 'N2C': 3.55,\n 'T0I': 7.34,\n 'MPH': 5.29,\n 'R2T': 4.71,\n 'TOX': 6.78,\n 'P2Q': 9.8,\n 'GPL': 10.77,\n 'MPJ': 5.07,\n 'F2Y': 6.2,\n 'T11': 8.58,\n '9NR': 9.33,\n 'FPR': 8.85,\n '9NF': 8.93,\n 'KPY': 10.17,\n '9NE': 9.77,\n 'TOQ': 7.5,\n 'MPQ': 4.2,\n 'FPK': 3.08,\n 'HQA': 7.25,\n 'SOY': 10.94\n}\nexport const DefaultResidueRadius = 5.0\n\n// http://dx.doi.org/10.1039/b801115j (or 1.6)\nexport const CovalentRadii: { [e: number]: number | undefined } = {\n 1: 0.31, 2: 0.28, 3: 1.28, 4: 0.96, 5: 0.84, 6: 0.76, 7: 0.71, 8: 0.66, 9: 0.57, 10: 0.58, 11: 1.66, 12: 1.41, 13: 1.21, 14: 1.11, 15: 1.07, 16: 1.05, 17: 1.02, 18: 1.06, 19: 2.03, 20: 1.76, 21: 1.7, 22: 1.6, 23: 1.53, 24: 1.39, 25: 1.39, 26: 1.32, 27: 1.26, 28: 1.24, 29: 1.32, 30: 1.22, 31: 1.22, 32: 1.2, 33: 1.19, 34: 1.2, 35: 1.2, 36: 1.16, 37: 2.2, 38: 1.95, 39: 1.9, 40: 1.75, 41: 1.64, 42: 1.54, 43: 1.47, 44: 1.46, 45: 1.42, 46: 1.39, 47: 1.45, 48: 1.44, 49: 1.42, 50: 1.39, 51: 1.39, 52: 1.38, 53: 1.39, 54: 1.4, 55: 2.44, 56: 2.15, 57: 2.07, 58: 2.04, 59: 2.03, 60: 2.01, 61: 1.99, 62: 1.98, 63: 1.98, 64: 1.96, 65: 1.94, 66: 1.92, 67: 1.92, 68: 1.89, 69: 1.9, 70: 1.87, 71: 1.87, 72: 1.75, 73: 1.7, 74: 1.62, 75: 1.51, 76: 1.44, 77: 1.41, 78: 1.36, 79: 1.36, 80: 1.32, 81: 1.45, 82: 1.46, 83: 1.48, 84: 1.4, 85: 1.5, 86: 1.5, 87: 2.6, 88: 2.21, 89: 2.15, 90: 2.06, 91: 2.0, 92: 1.96, 93: 1.9, 94: 1.87, 95: 1.8, 96: 1.69, 97: 1.6, 98: 1.6, 99: 1.6, 100: 1.6, 101: 1.6, 102: 1.6, 103: 1.6, 104: 1.6, 105: 1.6, 106: 1.6, 107: 1.6, 108: 1.6, 109: 1.6, 110: 1.6, 111: 1.6, 112: 1.6, 113: 1.6, 114: 1.6, 115: 1.6, 116: 1.6, 117: 1.6, 118: 1.6\n}\nexport const DefaultCovalentRadius = 1.6\n\nexport const Valences: { [e: number]: number[] | undefined } = {\n 1: [ 1 ],\n 2: [ 0 ],\n 3: [ 1 ],\n 4: [ 2 ],\n 5: [ 3 ],\n 6: [ 4 ],\n 7: [ 3 ],\n 8: [ 2 ],\n 9: [ 1 ],\n 10: [ 0 ],\n 11: [ 1 ],\n 12: [ 2 ],\n 13: [ 6 ],\n 14: [ 6 ],\n 15: [ 3, 5, 7 ],\n 16: [ 2, 4, 6 ],\n 17: [ 1 ],\n 18: [ 0 ],\n 19: [ 1 ],\n 20: [ 2 ],\n\n 31: [ 3 ],\n 32: [ 4 ],\n 33: [ 3, 5 ],\n 34: [ 2, 4, 6 ],\n 35: [ 1 ],\n 36: [ 0 ],\n 37: [ 1 ],\n 38: [ 2 ],\n\n 49: [ 3 ],\n 50: [ 4 ],\n 51: [ 3, 5 ],\n 52: [ 2 ],\n 53: [ 1, 2, 5 ],\n 54: [ 0, 2 ],\n 55: [ 1 ],\n 56: [ 2 ],\n\n 81: [ 3 ],\n 82: [ 4 ],\n 83: [ 3 ],\n 84: [ 2 ],\n 85: [ 1 ],\n 86: [ 0 ],\n 87: [ 1 ],\n 88: [ 2 ]\n}\nexport const DefaultValence = -1\n\nexport const OuterShellElectronCounts: { [e: number]: number | undefined } = {\n1: 1, 2: 2, 3: 1, 4: 2, 5: 3, 6: 4, 7: 5, 8: 6, 9: 7, 10: 8, 11: 1, 12: 2, 13: 3, 14: 4, 15: 5, 16: 6, 17: 7, 18: 8, 19: 1, 20: 2, 21: 3, 22: 4, 23: 5, 24: 6, 25: 7, 26: 8, 27: 9, 28: 10, 29: 11, 30: 2, 31: 3, 32: 4, 33: 5, 34: 6, 35: 7, 36: 8, 37: 1, 38: 2, 39: 3, 40: 4, 41: 5, 42: 6, 43: 7, 44: 8, 45: 9, 46: 10, 47: 11, 48: 2, 49: 3, 50: 4, 51: 5, 52: 6, 53: 7, 54: 8, 55: 1, 56: 2, 57: 3, 58: 4, 59: 3, 60: 4, 61: 5, 62: 6, 63: 7, 64: 8, 65: 9, 66: 10, 67: 11, 68: 12, 69: 13, 70: 14, 71: 15, 72: 4, 73: 5, 74: 6, 75: 7, 76: 8, 77: 9, 78: 10, 79: 11, 80: 2, 81: 3, 82: 4, 83: 5, 84: 6, 85: 7, 86: 8, 87: 1, 88: 2, 89: 3, 90: 4, 91: 3, 92: 4, 93: 5, 94: 6, 95: 7, 96: 8, 97: 9, 98: 10, 99: 11, 100: 12, 101: 13, 102: 14, 103: 15, 104: 2, 105: 2, 106: 2, 107: 2, 108: 2, 109: 2, 110: 2, 111: 2, 112: 2, 113: 3, 114: 4, 115: 5, 116: 6, 117: 7, 118: 8\n}\nexport const DefaultOuterShellElectronCount = 2\n\n// http://blanco.biomol.uci.edu/Whole_residue_HFscales.txt\n// https://www.nature.com/articles/nsb1096-842\nexport const ResidueHydrophobicity: { [k: string]: [number, number, number] } = {\n // AA DGwif DGwoct Oct-IF\n 'ALA': [ 0.17, 0.50, 0.33 ],\n 'ARG': [ 0.81, 1.81, 1.00 ],\n 'ASN': [ 0.42, 0.85, 0.43 ],\n 'ASP': [ 1.23, 3.64, 2.41 ],\n 'ASH': [ -0.07, 0.43, 0.50 ],\n 'CYS': [ -0.24, -0.02, 0.22 ],\n 'GLN': [ 0.58, 0.77, 0.19 ],\n 'GLU': [ 2.02, 3.63, 1.61 ],\n 'GLH': [ -0.01, 0.11, 0.12 ],\n 'GLY': [ 0.01, 1.15, 1.14 ],\n // \"His+\": [ 0.96, 2.33, 1.37 ],\n 'HIS': [ 0.17, 0.11, -0.06 ],\n 'ILE': [ -0.31, -1.12, -0.81 ],\n 'LEU': [ -0.56, -1.25, -0.69 ],\n 'LYS': [ 0.99, 2.80, 1.81 ],\n 'MET': [ -0.23, -0.67, -0.44 ],\n 'PHE': [ -1.13, -1.71, -0.58 ],\n 'PRO': [ 0.45, 0.14, -0.31 ],\n 'SER': [ 0.13, 0.46, 0.33 ],\n 'THR': [ 0.14, 0.25, 0.11 ],\n 'TRP': [ -1.85, -2.09, -0.24 ],\n 'TYR': [ -0.94, -0.71, 0.23 ],\n 'VAL': [ 0.07, -0.46, -0.53 ]\n}\nexport const DefaultResidueHydrophobicity = [ 0.00, 0.00, 0.00 ]\n\nexport const AA1: { [k: string]: string } = {\n 'HIS': 'H',\n 'ARG': 'R',\n 'LYS': 'K',\n 'ILE': 'I',\n 'PHE': 'F',\n 'LEU': 'L',\n 'TRP': 'W',\n 'ALA': 'A',\n 'MET': 'M',\n 'PRO': 'P',\n 'CYS': 'C',\n 'ASN': 'N',\n 'VAL': 'V',\n 'GLY': 'G',\n 'SER': 'S',\n 'GLN': 'Q',\n 'TYR': 'Y',\n 'ASP': 'D',\n 'GLU': 'E',\n 'THR': 'T',\n\n 'SEC': 'U', // as per IUPAC definition\n 'PYL': 'O', // as per IUPAC definition\n}\n\nexport const AA3 = Object.keys(AA1)\n\nexport const RnaBases = [ 'A', 'C', 'T', 'G', 'U', 'I' ]\n\nexport const DnaBases = [ 'DA', 'DC', 'DT', 'DG', 'DU', 'DI' ]\n\nexport const PurinBases = [ 'A', 'G', 'I', 'DA', 'DG', 'DI' ]\n\nexport const Bases = RnaBases.concat(DnaBases)\n\nexport const WaterNames = [\n 'SOL', 'WAT', 'HOH', 'H2O', 'W', 'DOD', 'D3O', 'TIP3', 'TIP4', 'SPC'\n]\n\n// all chemical components with the word \"ion\" in their name, Sep 2016\n//\n// SET SESSION group_concat_max_len = 1000000;\n// SELECT GROUP_CONCAT(id_ ORDER BY id_ ASC SEPARATOR '\", \"') from\n// (\n// SELECT count(obj_id) as c, id_\n// FROM pdb.chem_comp WHERE name LIKE \"% ION%\"\n// GROUP BY id_\n// ) AS t1;\nexport const IonNames = [\n '118', '119', '1AL', '1CU', '2FK', '2HP', '2OF', '3CO',\n '3MT', '3NI', '3OF', '3P8', '4MO', '4PU', '543', '6MO', 'ACT', 'AG', 'AL',\n 'ALF', 'AM', 'ATH', 'AU', 'AU3', 'AUC', 'AZI', 'BA', 'BCT', 'BEF', 'BF4', 'BO4',\n 'BR', 'BS3', 'BSY', 'CA', 'CAC', 'CD', 'CD1', 'CD3', 'CD5', 'CE', 'CHT', 'CL',\n 'CO', 'CO3', 'CO5', 'CON', 'CR', 'CS', 'CSB', 'CU', 'CU1', 'CU3', 'CUA', 'CUZ',\n 'CYN', 'DME', 'DMI', 'DSC', 'DTI', 'DY', 'E4N', 'EDR', 'EMC', 'ER3', 'EU',\n 'EU3', 'F', 'FE', 'FE2', 'FPO', 'GA', 'GD3', 'GEP', 'HAI', 'HG', 'HGC', 'IN',\n 'IOD', 'IR', 'IR3', 'IRI', 'IUM', 'K', 'KO4', 'LA', 'LCO', 'LCP', 'LI', 'LU',\n 'MAC', 'MG', 'MH2', 'MH3', 'MLI', 'MLT', 'MMC', 'MN', 'MN3', 'MN5', 'MN6',\n 'MO1', 'MO2', 'MO3', 'MO4', 'MO5', 'MO6', 'MOO', 'MOS', 'MOW', 'MW1', 'MW2',\n 'MW3', 'NA', 'NA2', 'NA5', 'NA6', 'NAO', 'NAW', 'NCO', 'NET', 'NH4', 'NI',\n 'NI1', 'NI2', 'NI3', 'NO2', 'NO3', 'NRU', 'O4M', 'OAA', 'OC1', 'OC2', 'OC3',\n 'OC4', 'OC5', 'OC6', 'OC7', 'OC8', 'OCL', 'OCM', 'OCN', 'OCO', 'OF1', 'OF2',\n 'OF3', 'OH', 'OS', 'OS4', 'OXL', 'PB', 'PBM', 'PD', 'PDV', 'PER', 'PI', 'PO3',\n 'PO4', 'PR', 'PT', 'PT4', 'PTN', 'RB', 'RH3', 'RHD', 'RU', 'SB', 'SCN', 'SE4',\n 'SEK', 'SM', 'SMO', 'SO3', 'SO4', 'SR', 'T1A', 'TB', 'TBA', 'TCN', 'TEA', 'TH',\n 'THE', 'TL', 'TMA', 'TRA', 'UNX', 'V', 'VN3', 'VO4', 'W', 'WO5', 'Y1', 'YB',\n 'YB2', 'YH', 'YT3', 'ZCM', 'ZN', 'ZN2', 'ZN3', 'ZNO', 'ZO3',\n // additional ion names\n 'OHX'\n]\n\n// all chemical components with the word \"%saccharide%\" in their type, Sep 2016\n//\n// SET SESSION group_concat_max_len = 1000000;\n// select GROUP_CONCAT(id_ ORDER BY id_ ASC SEPARATOR '\", \"') from\n// (\n// SELECT count(obj_id), id_\n// FROM pdb.chem_comp WHERE type like \"%SACCHARIDE%\"\n// GROUP BY id_\n// ) AS t1;\nexport const SaccharideNames = [\n '045', '0AT', '0BD', '0MK', '0NZ', '0TS', '0V4', '0XY', '0YT', '10M',\n '147', '149', '14T', '15L', '16G', '18T', '18Y', '1AR', '1BW', '1GL', '1GN',\n '1JB', '1LL', '1NA', '1S3', '26M', '26Q', '26R', '26V', '26W', '26Y', '27C',\n '289', '291', '293', '2DG', '2F8', '2FG', '2FL', '2FP', '2GL', '2M4', '2M5',\n '32O', '34V', '3CM', '3DO', '3DY', '3FM', '3LR', '3MF', '3MG', '3SA', '3ZW',\n '46D', '46M', '46Z', '48Z', '4CQ', '4GC', '4NN', '50A', '5DI', '5GF', '5MM',\n '5RP', '5SA', '5SP', '64K', '6PG', '6SA', '7JZ', '7SA', 'A1Q', 'A2G', 'AAB',\n 'AAL', 'AAO', 'ABC', 'ABD', 'ABE', 'ABF', 'ABL', 'ACG', 'ACI', 'ACR', 'ACX',\n 'ADA', 'ADG', 'ADR', 'AF1', 'AFD', 'AFL', 'AFO', 'AFP', 'AFR', 'AGC', 'AGH',\n 'AGL', 'AHR', 'AIG', 'ALL', 'ALX', 'AMU', 'AOG', 'AOS', 'ARA', 'ARB', 'ARE',\n 'ARI', 'ASG', 'ASO', 'AXP', 'AXR', 'B0D', 'B16', 'B2G', 'B4G', 'B6D', 'B8D',\n 'B9D', 'BBK', 'BCD', 'BDG', 'BDP', 'BDR', 'BEM', 'BFP', 'BGC', 'BGL', 'BGP',\n 'BGS', 'BHG', 'BMA', 'BMX', 'BNG', 'BNX', 'BOG', 'BRI', 'BXF', 'BXP', 'BXX',\n 'BXY', 'C3X', 'C4X', 'C5X', 'CAP', 'CBI', 'CBK', 'CBS', 'CDR', 'CEG', 'CGF',\n 'CHO', 'CR1', 'CR6', 'CRA', 'CT3', 'CTO', 'CTR', 'CTT', 'D6G', 'DAF', 'DAG',\n 'DDA', 'DDB', 'DDL', 'DEL', 'DFR', 'DFX', 'DG0', 'DGC', 'DGD', 'DGM', 'DGS',\n 'DIG', 'DLF', 'DLG', 'DMU', 'DNO', 'DOM', 'DP5', 'DQQ', 'DQR', 'DR2', 'DR3',\n 'DR4', 'DRI', 'DSR', 'DT6', 'DVC', 'E4P', 'E5G', 'EAG', 'EBG', 'EBQ', 'EGA',\n 'EJT', 'EPG', 'ERE', 'ERI', 'F1P', 'F1X', 'F6P', 'FBP', 'FCA', 'FCB', 'FCT',\n 'FDP', 'FDQ', 'FFC', 'FIX', 'FMO', 'FRU', 'FSI', 'FU4', 'FUB', 'FUC', 'FUD',\n 'FUL', 'FXP', 'G16', 'G1P', 'G2F', 'G3I', 'G4D', 'G4S', 'G6D', 'G6P', 'G6S',\n 'GAC', 'GAD', 'GAL', 'GC1', 'GC4', 'GCD', 'GCN', 'GCO', 'GCS', 'GCT', 'GCU',\n 'GCV', 'GCW', 'GCX', 'GE1', 'GFG', 'GFP', 'GIV', 'GL0', 'GL2', 'GL5', 'GL6',\n 'GL7', 'GL9', 'GLA', 'GLB', 'GLC', 'GLD', 'GLF', 'GLG', 'GLO', 'GLP', 'GLS',\n 'GLT', 'GLW', 'GMH', 'GN1', 'GNX', 'GP1', 'GP4', 'GPH', 'GPM', 'GQ1', 'GQ2',\n 'GQ4', 'GS1', 'GS4', 'GSA', 'GSD', 'GTE', 'GTH', 'GTK', 'GTR', 'GTZ', 'GU0',\n 'GU1', 'GU2', 'GU3', 'GU4', 'GU5', 'GU6', 'GU8', 'GU9', 'GUF', 'GUP', 'GUZ',\n 'GYP', 'GYV', 'H2P', 'HDL', 'HMS', 'HS2', 'HSD', 'HSG', 'HSH', 'HSJ', 'HSQ',\n 'HSR', 'HSU', 'HSX', 'HSY', 'HSZ', 'IAB', 'IDG', 'IDR', 'IDS', 'IDT', 'IDU',\n 'IDX', 'IDY', 'IMK', 'IN1', 'IPT', 'ISL', 'KBG', 'KD2', 'KDA', 'KDM', 'KDO',\n 'KFN', 'KO1', 'KO2', 'KTU', 'L6S', 'LAG', 'LAI', 'LAK', 'LAO', 'LAT', 'LB2',\n 'LBT', 'LCN', 'LDY', 'LGC', 'LGU', 'LM2', 'LMT', 'LMU', 'LOG', 'LOX', 'LPK',\n 'LSM', 'LTM', 'LVZ', 'LXB', 'LXZ', 'M1F', 'M3M', 'M6P', 'M8C', 'MA1', 'MA2',\n 'MA3', 'MAB', 'MAG', 'MAL', 'MAN', 'MAT', 'MAV', 'MAW', 'MBG', 'MCU', 'MDA',\n 'MDM', 'MDP', 'MFA', 'MFB', 'MFU', 'MG5', 'MGA', 'MGL', 'MLB', 'MMA', 'MMN',\n 'MN0', 'MRP', 'MTT', 'MUG', 'MVP', 'MXY', 'N1L', 'N9S', 'NAA', 'NAG', 'NBG',\n 'NDG', 'NED', 'NG1', 'NG6', 'NGA', 'NGB', 'NGC', 'NGE', 'NGF', 'NGL', 'NGS',\n 'NGY', 'NHF', 'NM6', 'NM9', 'NTF', 'NTO', 'NTP', 'NXD', 'NYT', 'OPG', 'OPM',\n 'ORP', 'OX2', 'P3M', 'P53', 'P6P', 'PA5', 'PNA', 'PNG', 'PNW', 'PRP', 'PSJ',\n 'PSV', 'PTQ', 'QDK', 'QPS', 'QV4', 'R1P', 'R1X', 'R2B', 'R5P', 'RAA', 'RAE',\n 'RAF', 'RAM', 'RAO', 'RAT', 'RB5', 'RBL', 'RCD', 'RDP', 'REL', 'RER', 'RF5',\n 'RG1', 'RGG', 'RHA', 'RIB', 'RIP', 'RNS', 'RNT', 'ROB', 'ROR', 'RPA', 'RST',\n 'RUB', 'RUU', 'RZM', 'S6P', 'S7P', 'SA0', 'SCR', 'SDD', 'SF6', 'SF9', 'SG4',\n 'SG5', 'SG6', 'SG7', 'SGA', 'SGC', 'SGD', 'SGN', 'SGS', 'SHB', 'SHG', 'SI3',\n 'SIO', 'SOE', 'SOL', 'SSG', 'SUC', 'SUP', 'SUS', 'T6P', 'T6T', 'TAG', 'TCB',\n 'TDG', 'TGK', 'TGY', 'TH1', 'TIA', 'TM5', 'TM6', 'TM9', 'TMR', 'TMX', 'TOA',\n 'TOC', 'TRE', 'TYV', 'UCD', 'UDC', 'VG1', 'X0X', 'X1X', 'X2F', 'X4S', 'X5S',\n 'X6X', 'XBP', 'XDN', 'XDP', 'XIF', 'XIM', 'XLF', 'XLS', 'XMM', 'XUL', 'XXR',\n 'XYP', 'XYS', 'YO5', 'Z3Q', 'Z6J', 'Z9M', 'ZDC', 'ZDM'\n]\n\nexport const ProteinBackboneAtoms = [\n 'CA', 'C', 'N', 'O',\n 'O1', 'O2', 'OC1', 'OC2', 'OX1', 'OXT', 'OT1', 'OT2',\n 'H', 'H1', 'H2', 'H3', 'HA', 'HN',\n 'BB'\n]\n\nexport const NucleicBackboneAtoms = [\n 'P', 'OP1', 'OP2', 'HOP2', 'HOP3',\n \"O2'\", \"O3'\", \"O4'\", \"O5'\", \"C1'\", \"C2'\", \"C3'\", \"C4'\", \"C5'\",\n \"H1'\", \"H2'\", \"H2''\", \"HO2'\", \"H3'\", \"H4'\", \"H5'\", \"H5''\", \"HO3'\", \"HO5'\",\n 'O2*', 'O3*', 'O4*', 'O5*', 'C1*', 'C2*', 'C3*', 'C4*', 'C5*'\n]\n\nexport const ResidueTypeAtoms: { [k: number]: { [k: string]: string|string[] } } = {}\n\nResidueTypeAtoms[ ProteinBackboneType ] = {\n trace: 'CA',\n direction1: 'C',\n direction2: [ 'O', 'OC1', 'O1', 'OX1', 'OXT', 'OT1', 'OT2' ],\n backboneStart: 'N',\n backboneEnd: 'C'\n}\n\nResidueTypeAtoms[ RnaBackboneType ] = {\n trace: [ \"C4'\", 'C4*' ],\n direction1: [ \"C1'\", 'C1*' ],\n direction2: [ \"C3'\", 'C3*' ],\n backboneStart: 'P',\n backboneEnd: [ \"O3'\", 'O3*' ]\n}\n\nResidueTypeAtoms[ DnaBackboneType ] = {\n trace: [ \"C3'\", 'C3*' ],\n direction1: [ \"C2'\", 'C2*' ],\n direction2: [ \"O4'\", 'O4*' ],\n backboneStart: 'P',\n backboneEnd: [ \"O3'\", 'O3*' ]\n}\n\nResidueTypeAtoms[ CgProteinBackboneType ] = {\n trace: [ 'CA', 'BB' ],\n backboneStart: [ 'CA', 'BB' ],\n backboneEnd: [ 'CA', 'BB' ]\n}\n\nResidueTypeAtoms[ CgRnaBackboneType ] = {\n trace: [ \"C4'\", 'C4*', 'P' ],\n backboneStart: [ \"C4'\", 'C4*', 'P' ],\n backboneEnd: [ \"C4'\", 'C4*', 'P' ]\n}\n\nResidueTypeAtoms[ CgDnaBackboneType ] = {\n trace: [ \"C3'\", 'C3*', \"C2'\", 'P' ], // C2' is used in martini ff\n backboneStart: [ \"C3'\", 'C3*', \"C2'\", 'P' ],\n backboneEnd: [ \"C3'\", 'C3*', \"C2'\", 'P' ]\n}\n\nResidueTypeAtoms[ UnknownBackboneType ] = {}\n\n// Mappings taken from Meeko: https://github.com/forlilab/Meeko/blob/develop/meeko/utils/autodock4_atom_types_elements.py\nexport const PDBQTSpecialElements = {\n 'HD': 'H',\n 'HS': 'H',\n 'A': 'C',\n 'NA': 'N',\n 'NS': 'N',\n 'OA': 'O',\n 'OS': 'O',\n 'SA': 'S',\n 'G0': 'C',\n 'G1': 'C',\n 'G2': 'C',\n 'G3': 'C',\n 'CG0': 'C',\n 'CG1': 'C',\n 'CG2': 'C',\n 'CG3': 'C',\n 'W': 'O'\n}","/**\n * @file Geometry\n * @author Fred Ludlow \n * @author Alexander Rose \n */\n\nimport { Vector3 } from 'three'\n\nimport { Elements } from '../structure/structure-constants'\nimport { degToRad } from '../math/math-utils'\nimport AtomProxy from '../proxy/atom-proxy'\n\n// Changed numbering so they're mostly inline with coordination number\n// from VSEPR\nexport const enum AtomGeometry {\n Spherical = 0,\n Terminal = 1,\n Linear = 2,\n Trigonal = 3,\n Tetrahedral = 4,\n TrigonalBiPyramidal = 5,\n Octahedral = 6,\n SquarePlanar = 7, // Okay, it breaks down somewhere!\n Unknown = 8\n}\n\nexport function assignGeometry (totalCoordination: number): AtomGeometry {\n switch(totalCoordination){\n case 0:\n return AtomGeometry.Spherical\n case 1:\n return AtomGeometry.Terminal\n case 2:\n return AtomGeometry.Linear\n case 3:\n return AtomGeometry.Trigonal\n case 4:\n return AtomGeometry.Tetrahedral\n default:\n return AtomGeometry.Unknown\n }\n}\n\nexport const Angles = new Map([\n [ AtomGeometry.Linear, degToRad(180) ],\n [ AtomGeometry.Trigonal, degToRad(120) ],\n [ AtomGeometry.Tetrahedral, degToRad(109.4721) ],\n [ AtomGeometry.Octahedral, degToRad(90) ]\n])\n\n/**\n * Calculate the angles x-1-2 for all x where x is a heavy atom bonded to ap1.\n * @param {AtomProxy} ap1 First atom (angle centre)\n * @param {AtomProxy} ap2 Second atom\n * @return {number[]} Angles in radians\n */\nexport function calcAngles (ap1: AtomProxy, ap2: AtomProxy): number[] {\n let angles: number[] = []\n const d1 = new Vector3()\n const d2 = new Vector3()\n d1.subVectors(ap2 as any, ap1 as any)\n ap1.eachBondedAtom( x => {\n if (x.number !== Elements.H) {\n d2.subVectors(x as any, ap1 as any)\n angles.push(d1.angleTo(d2))\n }\n })\n return angles\n}\n\n/**\n * Find two neighbours of ap1 to define a plane (if possible) and\n * measure angle out of plane to ap2\n * @param {AtomProxy} ap1 First atom (angle centre)\n * @param {AtomProxy} ap2 Second atom (out-of-plane)\n * @return {number} Angle from plane to second atom\n */\nexport function calcPlaneAngle (ap1: AtomProxy, ap2: AtomProxy): number | undefined {\n const x1 = ap1.clone()\n\n const v12 = new Vector3()\n v12.subVectors(ap2 as any, ap1 as any)\n\n const neighbours = [new Vector3(), new Vector3()]\n let ni = 0\n ap1.eachBondedAtom( x => {\n if (ni > 1) { return }\n if (x.number !== Elements.H) {\n x1.index = x.index\n neighbours[ni++].subVectors(x as any, ap1 as any)\n }\n })\n if (ni === 1) {\n x1.eachBondedAtom( x => {\n if (ni > 1) { return }\n if (x.number !== Elements.H && x.index !== ap1.index){\n neighbours[ni++].subVectors(x as any, ap1 as any)\n }\n })\n }\n if (ni !== 2) {\n return\n }\n\n const cp = neighbours[0].cross(neighbours[1])\n return Math.abs((Math.PI / 2) - cp.angleTo(v12))\n}\n","/**\n * @file Valence Model\n * @author Fred Ludlow \n * @author Alexander Rose \n */\n\n/**\n * Reworked ValenceModel\n *\n * TODO:\n * Ensure proper treatment of disorder/models. e.g. V257 N in 5vim\n * Formal charge of 255 for SO4 anion (e.g. 5ghl)\n * Have removed a lot of explicit features (as I think they're more\n * generally captured by better VM).\n * Could we instead have a \"delocalised negative/positive\" charge\n * feature and flag these up?\n *\n */\nimport { Data } from '../structure/data'\nimport AtomProxy from '../proxy/atom-proxy'\nimport { AtomGeometry, assignGeometry } from './geometry'\nimport { Elements } from '../structure/structure-constants'\n\n/**\n * Are we involved in some kind of pi system. Either explicitly forming\n * double bond or N, O next to a double bond, except:\n *\n * N,O with degree 4 cannot be conjugated.\n * N,O adjacent to P=O or S=O do not qualify (keeps sulfonamide N sp3 geom)\n */\nfunction isConjugated (a: AtomProxy) {\n const _bp = a.structure.getBondProxy()\n const atomicNumber = a.number\n const hetero = atomicNumber === Elements.O || atomicNumber === Elements.N\n\n if (hetero && a.bondCount === 4) {\n return false\n }\n\n let flag = false\n\n a.eachBond(b => {\n if (b.bondOrder > 1) {\n flag = true\n return\n }\n if (hetero) {\n const a2 = b.getOtherAtom(a)\n\n a2.eachBond(b2 => {\n if (b2.bondOrder > 1) {\n const atomicNumber2 = a2.number\n if (\n (atomicNumber2 === Elements.P || atomicNumber2 === Elements.S) &&\n b2.getOtherAtom(a2).number === Elements.O\n ) {\n return\n }\n flag = true\n }\n }, _bp) // Avoid reuse of structure._bp\n }\n })\n\n return flag\n}\n\n/* function hasExplicitCharge(r: ResidueProxy) {\n let flag = false\n r.eachAtom(a => {\n if (a.formalCharge != null && a.formalCharge !== 0) flag = true\n })\n return flag\n}\n\nfunction hasExplicitHydrogen(r: ResidueProxy) {\n let flag = false\n r.eachAtom(a => {\n if (a.number === Elements.H) flag = true\n })\n return flag\n} */\n\nexport function explicitValence (a: AtomProxy) {\n let v = 0\n a.eachBond(b => v += b.bondOrder)\n return v\n}\n\n/**\n * Attempts to produce a consistent charge and implicit\n * H-count for an atom.\n *\n * If both params.assignCharge and params.assignH, this\n * approximately followsthe rules described in\n * https://docs.eyesopen.com/toolkits/python/oechemtk/valence.html#openeye-hydrogen-count-model\n *\n * If only charge or hydrogens are to be assigned it takes\n * a much simpler view and deduces one from the other\n *\n * @param {AtomProxy} a Atom to analyze\n * @param {assignChargeHParams} params What to assign\n */\nexport function calculateHydrogensCharge (a: AtomProxy, params: ValenceModelParams) {\n const hydrogenCount = a.bondToElementCount(Elements.H)\n let charge = a.formalCharge || 0\n\n const assignCharge = (params.assignCharge === 'always' ||\n (params.assignCharge === 'auto' && charge === 0))\n const assignH = (params.assignH === 'always' ||\n (params.assignH === 'auto' && hydrogenCount === 0))\n\n const degree = a.bondCount\n const valence = explicitValence(a)\n\n const conjugated = isConjugated(a)\n const multiBond = (valence - degree > 0)\n\n\n let implicitHCount = 0\n let geom = AtomGeometry.Unknown\n\n switch (a.number) {\n case Elements.H:\n if (assignCharge){\n if (degree === 0){\n charge = 1\n geom = AtomGeometry.Spherical\n } else if (degree === 1) {\n charge = 0\n geom = AtomGeometry.Terminal\n }\n }\n break\n\n case Elements.C:\n // TODO: Isocyanide?\n if (assignCharge) {\n charge = 0 // Assume carbon always neutral\n }\n if (assignH) {\n // Carbocation/carbanion are 3-valent\n implicitHCount = Math.max(0, 4 - valence - Math.abs(charge))\n }\n // Carbocation is planar, carbanion is tetrahedral\n geom = assignGeometry(degree + implicitHCount + Math.max(0, -charge))\n break\n\n case Elements.N:\n if (assignCharge) {\n if (!assignH) { // Trust input H explicitly:\n charge = valence - 3\n } else if (conjugated && valence < 4) {\n // Neutral unless amidine/guanidine double-bonded N:\n if (degree - hydrogenCount === 1 && valence - hydrogenCount === 2) {\n charge = 1\n } else {\n charge = 0\n }\n } else {\n // Sulfonamide nitrogen and classed as sp3 in conjugation model but\n // they won't be charged\n // Don't assign charge to nitrogens bound to metals\n let flag = false\n a.eachBondedAtom(ba => {\n if (ba.number === Elements.S || ba.isMetal()) flag = true\n })\n if (flag) charge = 0\n else charge = 1\n // TODO: Planarity sanity check?\n }\n\n }\n\n if (assignH) {\n // NH4+ -> 4, 1' amide -> 2, nitro N/N+ depiction -> 0\n implicitHCount = Math.max(0, 3 - valence + charge)\n }\n\n if (conjugated && !multiBond) {\n // Amide, anilinic N etc. cannot consider lone-pair for geometry purposes\n // Anilinic N geometry is depenent on ring electronics, for our purposes we\n // assume it's trigonal!\n geom = assignGeometry(degree + implicitHCount - charge)\n } else {\n // Everything else, pyridine, amine, nitrile, lp plays normal role:\n geom = assignGeometry(degree + implicitHCount + 1 - charge)\n }\n break\n\n case Elements.O:\n if (assignCharge) {\n if (!assignH) {\n charge = valence - 2 //\n }\n if (valence === 1) {\n a.eachBondedAtom(ba => {\n ba.eachBond(b => {\n const oa = b.getOtherAtom(ba)\n if (oa.index !== a.index && oa.number === Elements.O && b.bondOrder === 2){\n charge = -1\n }\n })\n })\n }\n }\n if (assignH) {\n // ethanol -> 1, carboxylate -> -1\n implicitHCount = Math.max(0, 2 - valence + charge)\n }\n if (conjugated && !multiBond){\n // carboxylate OH, phenol OH, one lone-pair taken up with conjugation\n geom = assignGeometry(degree + implicitHCount - charge + 1)\n } else {\n // Carbonyl (trigonal)\n geom = assignGeometry(degree + implicitHCount - charge + 2)\n }\n break\n\n // Only handles thiols/thiolates/thioether/sulfonium. Sulfoxides and higher\n // oxidiation states are assumed neutral S (charge carried on O if required)\n case Elements.S:\n if (assignCharge) {\n if (!assignH) {\n if (valence <= 3 && !a.bondToElementCount(Elements.O)) {\n charge = valence - 2 // e.g. explicitly deprotonated thiol\n } else {\n charge = 0\n }\n }\n }\n if (assignH){\n if (valence < 2){\n implicitHCount = Math.max(0, 2 - valence + charge)\n }\n }\n if (valence <= 3){\n // Thiol, thiolate, tioether -> tetrahedral\n geom = assignGeometry(degree + implicitHCount - charge + 2)\n }\n\n break\n\n case Elements.F:\n case Elements.CL:\n case Elements.BR:\n case Elements.I:\n case Elements.AT:\n // Never implicitly protonate halides\n if (assignCharge) {\n charge = valence - 1\n }\n break\n\n case Elements.LI:\n case Elements.NA:\n case Elements.K:\n case Elements.RB:\n case Elements.CS:\n case Elements.FR:\n if (assignCharge) {\n charge = 1 - valence\n }\n break\n\n case Elements.BE:\n case Elements.MG:\n case Elements.CA:\n case Elements.SR:\n case Elements.BA:\n case Elements.RA:\n if (assignCharge) {\n charge = 2 - valence\n }\n break\n\n default:\n console.warn('Requested charge, protonation for an unhandled element', a.element)\n }\n\n return [ charge, implicitHCount, implicitHCount + hydrogenCount, geom ]\n}\n\n\nexport interface ValenceModel {\n charge: Int8Array,\n implicitH: Int8Array,\n totalH: Int8Array,\n idealGeometry: Int8Array\n}\n\nexport interface ValenceModelParams {\n assignCharge: string,\n assignH: string\n}\n\nexport function ValenceModel (data: Data, params: ValenceModelParams) {\n const structure = data.structure\n const n = structure.atomCount\n\n const charge = new Int8Array(n)\n const implicitH = new Int8Array(n)\n const totalH = new Int8Array(n)\n const idealGeometry = new Int8Array(n)\n\n structure.eachAtom(a => {\n const i = a.index\n const [ chg, implH, totH, geom ] = calculateHydrogensCharge(a, params)\n charge[ i ] = chg\n implicitH[ i ] = implH\n totalH[ i ] = totH\n idealGeometry[ i ] = geom\n })\n\n return { charge, implicitH, totalH, idealGeometry }\n}","\nimport Structure from './structure'\nimport SpatialHash from '../geometry/spatial-hash'\nimport { ValenceModel } from '../chemistry/valence-model'\n\nexport interface Data {\n structure: Structure\n '@spatialLookup': SpatialHash | undefined\n '@valenceModel': ValenceModel | undefined\n}\n\nexport function createData(structure: Structure): Data {\n return {\n structure,\n '@spatialLookup': undefined,\n '@valenceModel': undefined\n }\n}\n\nexport function spatialLookup(data: Data): SpatialHash {\n if (data['@spatialLookup']) return data['@spatialLookup']!\n const lookup = new SpatialHash(data.structure.atomStore, data.structure.boundingBox)\n data['@spatialLookup'] = lookup\n return lookup\n}\n\nexport function valenceModel(data: Data): ValenceModel {\n if (data['@valenceModel']) return data['@valenceModel']!\n const valenceModel = ValenceModel(data, {assignCharge: 'auto', assignH: 'auto'})\n data['@valenceModel'] = valenceModel\n return valenceModel\n}\n","/**\n * @file Functional Groups\n * @author Alexander Rose \n */\n\nimport AtomProxy from '../proxy/atom-proxy'\nimport { Elements } from '../structure/structure-constants'\n\n/**\n * Nitrogen in a quaternary amine\n */\nexport function isQuaternaryAmine (a: AtomProxy) {\n return (\n a.number === 7 &&\n a.bondCount === 4 &&\n a.bondToElementCount(Elements.H) === 0\n )\n}\n\n/**\n * Nitrogen in a tertiary amine\n */\nexport function isTertiaryAmine (a: AtomProxy, idealValence: number) {\n return (\n a.number === 7 &&\n a.bondCount >= 3 &&\n idealValence === 3\n )\n}\n\n/**\n * Nitrogen in an imide\n */\nexport function isImide (a: AtomProxy) {\n let flag = false\n if (a.number === Elements.N && (a.bondCount - a.bondToElementCount(Elements.H)) === 2) {\n let carbonylCount = 0\n a.eachBondedAtom(ba => {\n if (isCarbonyl(ba)) ++carbonylCount\n })\n flag = carbonylCount === 2\n }\n return flag\n}\n\n/**\n * Nitrogen in an amide\n */\nexport function isAmide (a: AtomProxy) {\n let flag = false\n if (a.number === Elements.N && (a.bondCount - a.bondToElementCount(Elements.H)) === 2) {\n let carbonylCount = 0\n a.eachBondedAtom(ba => {\n if (isCarbonyl(ba)) ++carbonylCount\n })\n flag = carbonylCount === 1\n }\n return flag\n}\n\n/**\n * Sulfur in a sulfonium group\n */\nexport function isSulfonium (a: AtomProxy) {\n return (\n a.number === 16 &&\n a.bondCount === 3 &&\n a.bondToElementCount(Elements.H) === 0\n )\n}\n\n/**\n * Sulfur in a sulfonic acid or sulfonate group\n */\nexport function isSulfonicAcid (a: AtomProxy) {\n return (\n a.number === 16 &&\n a.bondToElementCount(Elements.O) === 3\n )\n}\n\n/**\n * Sulfur in a sulfate group\n */\nexport function isSulfate (a: AtomProxy) {\n return (\n a.number === 16 &&\n a.bondToElementCount(Elements.O) === 4\n )\n}\n\n/**\n * Phosphor in a phosphate group\n */\nexport function isPhosphate (a: AtomProxy) {\n return (\n a.number === 15 &&\n a.bondToElementCount(Elements.O) === a.bondCount\n )\n}\n\n/**\n * Halogen with one bond to a carbon\n */\nexport function isHalocarbon (a: AtomProxy) {\n return (\n a.isHalogen() &&\n a.bondCount === 1 &&\n a.bondToElementCount(Elements.C) === 1\n )\n}\n\n/**\n * Carbon in a carbonyl/acyl group\n */\nexport function isCarbonyl (a: AtomProxy) {\n let flag = false\n if (a.number === Elements.C) {\n a.eachBond(b => {\n if (b.bondOrder === 2 && b.getOtherAtom(a).number === Elements.O) {\n flag = true\n }\n })\n }\n return flag\n}\n\n/**\n * Carbon in a carboxylate group\n */\nexport function isCarboxylate (a: AtomProxy) {\n let terminalOxygenCount = 0\n if (\n a.number === 6 &&\n a.bondToElementCount(Elements.O) === 2 &&\n a.bondToElementCount(Elements.C) === 1\n ) {\n a.eachBondedAtom(ba => {\n if (ba.number === 8 && ba.bondCount - ba.bondToElementCount(Elements.H) === 1) {\n ++terminalOxygenCount\n }\n })\n }\n return terminalOxygenCount === 2\n}\n\n/**\n * Carbon in a guanidine group\n */\nexport function isGuanidine (a: AtomProxy) {\n let terminalNitrogenCount = 0\n if (\n a.number === 6 &&\n a.bondCount === 3 &&\n a.bondToElementCount(Elements.N) === 3\n ) {\n a.eachBondedAtom(ba => {\n if (ba.bondCount - ba.bondToElementCount(Elements.H) === 1) {\n ++terminalNitrogenCount\n }\n })\n }\n return terminalNitrogenCount === 2\n}\n\n/**\n * Carbon in a acetamidine group\n */\nexport function isAcetamidine (a: AtomProxy) {\n let terminalNitrogenCount = 0\n if (\n a.number === 6 &&\n a.bondCount === 3 &&\n a.bondToElementCount(Elements.N) === 2 &&\n a.bondToElementCount(Elements.C) === 1\n ) {\n a.eachBondedAtom(ba => {\n if (ba.bondCount - ba.bondToElementCount(Elements.H) === 1) {\n ++terminalNitrogenCount\n }\n })\n }\n return terminalNitrogenCount === 2\n}\n\nconst PolarElements = [\n Elements.N, Elements.O, Elements.S,\n Elements.F, Elements.CL, Elements.BR, Elements.I\n]\n\nexport function isPolar (a: AtomProxy) {\n return PolarElements.includes(a.number)\n}\n\nexport function hasPolarNeighbour (a: AtomProxy) {\n let flag = false\n a.eachBondedAtom(ba => {\n if (isPolar(ba)) flag = true\n })\n return flag\n}\n\nexport function hasAromaticNeighbour (a: AtomProxy) {\n let flag = false\n a.eachBondedAtom(function (bap) {\n if (bap.aromatic) flag = true\n })\n return flag\n}\n","/**\n * @file Charged\n * @author Alexander Rose \n * @author Fred Ludlow \n */\n\nimport { Vector3 } from 'three'\n\nimport { defaults } from '../../utils'\nimport { radToDeg } from '../../math/math-utils'\nimport Structure from '../../structure/structure'\nimport { AA3, Bases, Elements } from '../../structure/structure-constants'\nimport { valenceModel } from '../../structure/data'\nimport {\n isGuanidine, isAcetamidine, isSulfonicAcid, isPhosphate, isSulfate, isCarboxylate\n} from '../functional-groups'\nimport {\n Features, FeatureType, FeatureGroup,\n addAtom, addFeature, createFeatureState,\n} from './features'\nimport { Contacts, ContactType, ContactDefaultParams, invalidAtomContact } from './contact'\n\nconst PositvelyCharged = [ 'ARG', 'HIS', 'LYS' ]\nconst NegativelyCharged = [ 'GLU', 'ASP' ]\n\nexport function addPositiveCharges (structure: Structure, features: Features) {\n const { charge } = valenceModel(structure.data)\n const atomInGroupDict: { [atomIndex: number]: true } = {}\n\n structure.eachResidue(r => {\n if (PositvelyCharged.includes(r.resname)) {\n const state = createFeatureState(FeatureType.PositiveCharge)\n r.eachAtom(a => {\n if (a.number === Elements.N && a.isSidechain()) {\n addAtom(state, a)\n }\n })\n addFeature(features, state)\n } else if(!AA3.includes(r.resname) && !r.isNucleic()) {\n r.eachAtom(a => {\n let addGroup = false\n const state = createFeatureState(FeatureType.PositiveCharge)\n if (isGuanidine(a)) {\n state.group = FeatureGroup.Guanidine\n addGroup = true\n } else if (isAcetamidine(a)) {\n state.group = FeatureGroup.Acetamidine\n addGroup = true\n }\n if (addGroup) {\n a.eachBondedAtom(a => {\n if (a.number === Elements.N) {\n atomInGroupDict[a.index] = true\n addAtom(state, a)\n }\n })\n addFeature(features, state)\n }\n })\n r.eachAtom(a => {\n const state = createFeatureState(FeatureType.PositiveCharge)\n if (charge[a.index] > 0) {\n if (!atomInGroupDict[a.index]) {\n addAtom(state, a)\n addFeature(features, state)\n }\n }\n })\n }\n })\n}\n\nexport function addNegativeCharges (structure: Structure, features: Features) {\n const { charge } = valenceModel(structure.data)\n const atomInGroupDict: { [atomIndex: number]: true } = {}\n\n structure.eachResidue(r => {\n if (NegativelyCharged.includes(r.resname)) {\n const state = createFeatureState(FeatureType.NegativeCharge)\n r.eachAtom(a => {\n if (a.number === Elements.O && a.isSidechain()) {\n addAtom(state, a)\n }\n })\n addFeature(features, state)\n } else if (Bases.includes(r.resname)) {\n const state = createFeatureState(FeatureType.NegativeCharge)\n r.eachAtom(a => {\n if (isPhosphate(a)) {\n state.group = FeatureGroup.Phosphate\n a.eachBondedAtom(a => {\n if (a.number === Elements.O) addAtom(state, a)\n })\n addFeature(features, state)\n }\n })\n } else if(!AA3.includes(r.resname) && !Bases.includes(r.resname)) {\n r.eachAtom(a => {\n let addGroup = false\n const state = createFeatureState(FeatureType.NegativeCharge)\n if (isSulfonicAcid(a)) {\n state.group = FeatureGroup.SulfonicAcid\n addGroup = true\n } else if (isPhosphate(a)) {\n state.group = FeatureGroup.Phosphate\n addGroup = true\n } else if (isSulfate(a)) {\n state.group = FeatureGroup.Sulfate\n addGroup = true\n } else if (isCarboxylate(a)) {\n state.group = FeatureGroup.Carboxylate\n addGroup = true\n }\n if (addGroup) {\n a.eachBondedAtom(a => {\n if (a.number === Elements.O) {\n atomInGroupDict[a.index] = true\n addAtom(state, a)\n }\n })\n addFeature(features, state)\n }\n })\n r.eachAtom(a => {\n const state = createFeatureState(FeatureType.NegativeCharge)\n if (charge[a.index] < 0) {\n if (!atomInGroupDict[a.index]) {\n addAtom(state, a)\n addFeature(features, state)\n }\n }\n })\n }\n })\n}\n\nexport function addAromaticRings (structure: Structure, features: Features) {\n const a = structure.getAtomProxy()\n structure.eachResidue(r => {\n const rings = r.getAromaticRings()\n if (rings) {\n const offset = r.atomOffset\n rings.forEach(ring => {\n const state = createFeatureState(FeatureType.AromaticRing)\n ring.forEach(i => {\n a.index = i + offset\n addAtom(state, a)\n })\n addFeature(features, state)\n })\n }\n })\n}\n\nfunction isIonicInteraction (ti: FeatureType, tj: FeatureType) {\n return (\n (ti === FeatureType.NegativeCharge && tj === FeatureType.PositiveCharge) ||\n (ti === FeatureType.PositiveCharge && tj === FeatureType.NegativeCharge)\n )\n}\n\nfunction isPiStacking (ti: FeatureType, tj: FeatureType) {\n return ti === FeatureType.AromaticRing && tj === FeatureType.AromaticRing\n}\n\nfunction isCationPi (ti: FeatureType, tj: FeatureType) {\n return (\n (ti === FeatureType.AromaticRing && tj === FeatureType.PositiveCharge) ||\n (ti === FeatureType.PositiveCharge && tj === FeatureType.AromaticRing)\n )\n}\n\nexport interface ChargedContactsParams {\n maxIonicDist?: number\n maxPiStackingDist?: number\n maxPiStackingOffset?: number\n maxPiStackingAngle?: number\n maxCationPiDist?: number\n maxCationPiOffset?: number\n masterModelIndex?: number\n}\n\nexport function addChargedContacts (structure: Structure, contacts: Contacts, params: ChargedContactsParams = {}) {\n const maxIonicDist = defaults(params.maxIonicDist, ContactDefaultParams.maxIonicDist)\n const maxPiStackingDist = defaults(params.maxPiStackingDist, ContactDefaultParams.maxPiStackingDist)\n const maxPiStackingOffset = defaults(params.maxPiStackingOffset, ContactDefaultParams.maxPiStackingOffset)\n const maxPiStackingAngle = defaults(params.maxPiStackingAngle, ContactDefaultParams.maxPiStackingAngle)\n const maxCationPiDist = defaults(params.maxCationPiDist, ContactDefaultParams.maxCationPiDist)\n const maxCationPiOffset = defaults(params.maxCationPiOffset, ContactDefaultParams.maxCationPiOffset)\n const masterIdx = defaults(params.masterModelIndex, ContactDefaultParams.masterModelIndex)\n\n const maxDistance = Math.max(maxIonicDist + 2, maxPiStackingDist, maxCationPiDist)\n // const maxSaltBridgeDistSq = maxSaltBridgeDist * maxSaltBridgeDist\n const maxPiStackingDistSq = maxPiStackingDist * maxPiStackingDist\n const maxCationPiDistSq = maxCationPiDist * maxCationPiDist\n\n const { features, spatialHash, contactStore, featureSet } = contacts\n const { types, centers, atomSets } = features\n const { x, y, z } = centers\n const n = types.length\n\n const ax = structure.atomStore.x\n const ay = structure.atomStore.y\n const az = structure.atomStore.z\n\n const ap1 = structure.getAtomProxy()\n const ap2 = structure.getAtomProxy()\n\n const areAtomSetsWithinDist = function (atomSet1: number[], atomSet2: number[], maxDist: number) {\n const sn = atomSet1.length\n const sm = atomSet2.length\n for (let si = 0; si < sn; ++si) {\n ap1.index = atomSet1[ si ]\n for (let sj = 0; sj < sm; ++sj) {\n ap2.index = atomSet2[ sj ]\n if (ap1.distanceTo(ap2) <= maxDist) {\n return true\n }\n }\n }\n return false\n }\n\n const v1 = new Vector3()\n const v2 = new Vector3()\n const v3 = new Vector3()\n const d1 = new Vector3()\n const d2 = new Vector3()\n const n1 = new Vector3()\n const n2 = new Vector3()\n\n const getNormal = function (atoms: number[], normal: Vector3) {\n v1.set(ax[ atoms[ 0 ] ], ay[ atoms[ 0 ] ], az[ atoms[ 0 ] ])\n v2.set(ax[ atoms[ 1 ] ], ay[ atoms[ 1 ] ], az[ atoms[ 1 ] ])\n v3.set(ax[ atoms[ 2 ] ], ay[ atoms[ 2 ] ], az[ atoms[ 2 ] ])\n d1.subVectors(v1, v2)\n d2.subVectors(v1, v3)\n normal.crossVectors(d1, d2)\n }\n\n const getOffset = function (i: number, j: number, normal: Vector3) {\n v1.set(x[ i ], y[ i ], z[ i ])\n v2.set(x[ j ], y[ j ], z[ j ])\n return v1.sub(v2).projectOnPlane(normal).add(v2).distanceTo(v2)\n }\n\n const add = function (i: number, j: number, ct: ContactType) {\n featureSet.setBits(i, j)\n contactStore.addContact(i, j, ct)\n }\n\n for (let i = 0; i < n; ++i) {\n spatialHash.eachWithin(x[i], y[i], z[i], maxDistance, (j, dSq) => {\n if (j <= i) return\n\n ap1.index = atomSets[ i ][ 0 ]\n ap2.index = atomSets[ j ][ 0 ]\n\n if (invalidAtomContact(ap1, ap2, masterIdx)) return\n\n const ti = types[ i ]\n const tj = types[ j ]\n\n if (isIonicInteraction(ti, tj)) {\n if (areAtomSetsWithinDist(atomSets[ i ], atomSets[ j ], maxIonicDist)) {\n add(i, j, ContactType.IonicInteraction)\n }\n } else if (isPiStacking(ti, tj)) {\n if (dSq <= maxPiStackingDistSq) {\n getNormal(atomSets[ i ], n1)\n getNormal(atomSets[ j ], n2)\n\n const angle = radToDeg(n1.angleTo(n2))\n const offset = Math.min(getOffset(i, j, n2), getOffset(j, i, n1))\n if (offset <= maxPiStackingOffset) {\n if (angle <= maxPiStackingAngle || angle >= 180 - maxPiStackingAngle) {\n add(i, j, ContactType.PiStacking) // parallel\n } else if (angle <= maxPiStackingAngle + 90 && angle >= 90 - maxPiStackingAngle) {\n add(i, j, ContactType.PiStacking) // t-shaped\n }\n }\n }\n } else if (isCationPi(ti, tj)) {\n if (dSq <= maxCationPiDistSq) {\n const [ l, k ] = ti === FeatureType.AromaticRing ? [ i, j ] : [ j, i ]\n\n getNormal(atomSets[ l ], n1)\n const offset = getOffset(k, l, n1)\n if (offset <= maxCationPiOffset) {\n add(l, k, ContactType.CationPi)\n }\n }\n }\n })\n }\n}\n","/**\n * @file Hydrogen Bonds\n * @author Alexander Rose \n * @author Fred Ludlow \n */\nimport { defaults } from '../../utils'\nimport { degToRad } from '../../math/math-utils'\nimport Structure from '../../structure/structure'\nimport AtomProxy from '../../proxy/atom-proxy'\nimport { valenceModel } from '../../structure/data'\nimport { Elements } from '../../structure/structure-constants'\nimport { Angles, AtomGeometry, calcAngles, calcPlaneAngle } from '../geometry'\nimport {\n Features, FeatureType,\n addAtom, addFeature, createFeatureState,\n} from './features'\nimport { Contacts, ContactType, ContactDefaultParams, invalidAtomContact } from './contact'\n\n\n// Geometric characteristics of hydrogen bonds involving sulfur atoms in proteins\n// https://doi.org/10.1002/prot.22327\n\n// Satisfying Hydrogen Bonding Potential in Proteins (HBPLUS)\n// https://doi.org/10.1006/jmbi.1994.1334\n// http://www.csb.yale.edu/userguides/datamanip/hbplus/hbplus_descrip.html\n\n/**\n * Potential hydrogen donor\n */\nexport function addHydrogenDonors (structure: Structure, features: Features) {\n const { totalH } = valenceModel(structure.data)\n\n structure.eachAtom(a => {\n const state = createFeatureState(FeatureType.HydrogenDonor)\n\n const an = a.number\n if (isHistidineNitrogen(a)) {\n // include both nitrogen atoms in histidine due to\n // their often ambiguous protonation assignment\n addAtom(state, a)\n addFeature(features, state)\n } else if (\n totalH[ a.index ] > 0 &&\n (an === Elements.N || an === Elements.O || an === Elements.S)\n ) {\n addAtom(state, a)\n addFeature(features, state)\n }\n })\n}\n\n/**\n * Weak hydrogen donor.\n */\nexport function addWeakHydrogenDonors (structure: Structure, features: Features) {\n const { totalH } = valenceModel(structure.data)\n\n structure.eachAtom(a => {\n if (\n a.number === Elements.C &&\n totalH[ a.index ] > 0 &&\n (\n a.bondToElementCount(Elements.N) > 0 ||\n a.bondToElementCount(Elements.O) > 0 ||\n inAromaticRingWithElectronNegativeElement(a)\n )\n ) {\n const state = createFeatureState(FeatureType.WeakHydrogenDonor)\n addAtom(state, a)\n addFeature(features, state)\n }\n })\n}\n\nfunction inAromaticRingWithElectronNegativeElement (a: AtomProxy) {\n if (!a.isAromatic()) return false\n\n const ringData = a.residueType.getRings()\n if (!ringData) return false\n\n let hasElement = false\n const rings = ringData.rings\n rings.forEach(ring => {\n if (hasElement) return // already found one\n if (ring.some(idx => (a.index - a.residueAtomOffset) === idx)) { // in ring\n hasElement = ring.some(idx => {\n const atomTypeId = a.residueType.atomTypeIdList[ idx ]\n const number = a.atomMap.get(atomTypeId).number\n return number === Elements.N || number === Elements.O\n })\n }\n })\n\n return hasElement\n}\n\n/**\n * Potential hydrogen acceptor\n */\nexport function addHydrogenAcceptors (structure: Structure, features: Features) {\n const { charge, implicitH, idealGeometry } = valenceModel(structure.data)\n\n structure.eachAtom(a => {\n const state = createFeatureState(FeatureType.HydrogenAcceptor)\n\n const an = a.number\n if (an === Elements.O) {\n // Basically assume all oxygen atoms are acceptors!\n addAtom(state, a)\n addFeature(features, state)\n }else if (an === Elements.N) {\n if (isHistidineNitrogen(a)) {\n // include both nitrogen atoms in histidine due to\n // their often ambiguous protonation assignment\n addAtom(state, a)\n addFeature(features, state)\n } else if (charge[ a.index ] < 1){\n // Neutral nitrogen might be an acceptor\n // It must have at least one lone pair not conjugated\n const totalBonds = a.bondCount + implicitH[ a.index ]\n const ig = idealGeometry[ a.index ]\n if (\n (ig === AtomGeometry.Tetrahedral && totalBonds < 4) ||\n (ig === AtomGeometry.Trigonal && totalBonds < 3) ||\n (ig === AtomGeometry.Linear && totalBonds < 2)\n ) {\n addAtom(state, a)\n addFeature(features, state)\n }\n }\n }else if (an === 16) { // S\n if (a.resname === 'CYS' || a.resname === 'MET' || a.formalCharge === -1) {\n addAtom(state, a)\n addFeature(features, state)\n }\n }\n })\n}\n\n/**\n * Atom that is only bound to carbon or hydrogen\n */\n// function isHydrocarbon (atom: AtomProxy) {\n// let flag = true\n// atom.eachBondedAtom(ap => {\n// const e = ap.element\n// if (e !== 'C' && e !== 'H') flag = false\n// })\n// return flag\n// }\n\nfunction isHistidineNitrogen (ap: AtomProxy) {\n return ap.resname === 'HIS' && ap.number == Elements.N && ap.isRing()\n}\n\nfunction isBackboneHydrogenBond (ap1: AtomProxy, ap2: AtomProxy) {\n return ap1.isBackbone() && ap2.isBackbone()\n}\n\nfunction isWaterHydrogenBond (ap1: AtomProxy, ap2: AtomProxy) {\n return ap1.isWater() && ap2.isWater()\n}\n\nfunction isHydrogenBond (ti: FeatureType, tj: FeatureType) {\n return (\n (ti === FeatureType.HydrogenAcceptor && tj === FeatureType.HydrogenDonor) ||\n (ti === FeatureType.HydrogenDonor && tj === FeatureType.HydrogenAcceptor)\n )\n}\n\nfunction isWeakHydrogenBond (ti: FeatureType, tj: FeatureType){\n return (\n (ti === FeatureType.WeakHydrogenDonor && tj === FeatureType.HydrogenAcceptor) ||\n (ti === FeatureType.HydrogenAcceptor && tj === FeatureType.WeakHydrogenDonor)\n )\n}\n\nfunction getHydrogenBondType (ap1: AtomProxy, ap2: AtomProxy) {\n if (isWaterHydrogenBond(ap1, ap2)) {\n return ContactType.WaterHydrogenBond\n } else if (isBackboneHydrogenBond(ap1, ap2)) {\n return ContactType.BackboneHydrogenBond\n } else {\n return ContactType.HydrogenBond\n }\n}\n\nexport interface HydrogenBondParams {\n maxHbondDist?: number\n maxHbondSulfurDist?: number\n maxHbondAccAngle?: number\n maxHbondDonAngle?: number\n maxHbondAccPlaneAngle?: number\n maxHbondDonPlaneAngle?: number\n backboneHbond?: boolean\n waterHbond?: boolean\n masterModelIndex?: number\n}\n\n/**\n * All pairs of hydrogen donor and acceptor atoms\n */\nexport function addHydrogenBonds (structure: Structure, contacts: Contacts, params: HydrogenBondParams = {}) {\n const maxHbondDist = defaults(params.maxHbondDist, ContactDefaultParams.maxHbondDist)\n const maxHbondSulfurDist = defaults(params.maxHbondSulfurDist, ContactDefaultParams.maxHbondSulfurDist)\n const maxHbondAccAngle = degToRad(defaults(params.maxHbondAccAngle, ContactDefaultParams.maxHbondAccAngle))\n const maxHbondDonAngle = degToRad(defaults(params.maxHbondDonAngle, ContactDefaultParams.maxHbondDonAngle))\n const maxHbondAccPlaneAngle = degToRad(defaults(params.maxHbondAccPlaneAngle, ContactDefaultParams.maxHbondAccPlaneAngle))\n const maxHbondDonPlaneAngle = degToRad(defaults(params.maxHbondDonPlaneAngle, ContactDefaultParams.maxHbondDonPlaneAngle))\n const masterIdx = defaults(params.masterModelIndex, ContactDefaultParams.masterModelIndex)\n\n const maxDist = Math.max(maxHbondDist, maxHbondSulfurDist)\n const maxHbondDistSq = maxHbondDist * maxHbondDist\n\n const { features, spatialHash, contactStore, featureSet } = contacts\n const { types, centers, atomSets } = features\n const { x, y, z } = centers\n const n = types.length\n\n const { idealGeometry } = valenceModel(structure.data)\n\n const donor = structure.getAtomProxy()\n const acceptor = structure.getAtomProxy()\n\n for (let i = 0; i < n; ++i) {\n spatialHash.eachWithin(x[i], y[i], z[i], maxDist, (j, dSq) => {\n if (j <= i) return\n\n const ti = types[ i ]\n const tj = types[ j ]\n\n const isWeak = isWeakHydrogenBond(ti, tj)\n if (!isWeak && !isHydrogenBond(ti, tj)) return\n\n const [ l, k ] = tj === FeatureType.HydrogenAcceptor ? [ i, j ] : [ j, i ]\n\n donor.index = atomSets[ l ][ 0 ]\n acceptor.index = atomSets[ k ][ 0 ]\n\n if (acceptor.index === donor.index) return // DA to self\n\n if (invalidAtomContact(donor, acceptor, masterIdx)) return\n if (donor.number !== Elements.S && acceptor.number !== Elements.S && dSq > maxHbondDistSq) return\n if (donor.connectedTo(acceptor)) return\n\n const donorAngles = calcAngles(donor, acceptor)\n const idealDonorAngle = Angles.get(idealGeometry[donor.index]) || degToRad(120)\n if (donorAngles.some(donorAngle => {\n return Math.abs(idealDonorAngle - donorAngle) > maxHbondDonAngle\n })) return\n\n if (idealGeometry[donor.index] === AtomGeometry.Trigonal){\n const outOfPlane = calcPlaneAngle(donor, acceptor)\n if (outOfPlane !== undefined && outOfPlane > maxHbondDonPlaneAngle) return\n }\n\n const acceptorAngles = calcAngles(acceptor, donor)\n const idealAcceptorAngle = Angles.get(idealGeometry[acceptor.index]) || degToRad(120)\n if (acceptorAngles.some(acceptorAngle => {\n // Do not limit large acceptor angles\n return idealAcceptorAngle - acceptorAngle > maxHbondAccAngle\n })) return\n\n if (idealGeometry[acceptor.index] === AtomGeometry.Trigonal){\n const outOfPlane = calcPlaneAngle(acceptor, donor)\n if (outOfPlane !== undefined && outOfPlane > maxHbondAccPlaneAngle) return\n }\n\n featureSet.setBits(l, k)\n const bondType = isWeak ? ContactType.WeakHydrogenBond : getHydrogenBondType(donor, acceptor)\n contactStore.addContact(l, k, bondType)\n })\n }\n}\n","/**\n * @file Metal Binding\n * @author Alexander Rose \n */\n\nimport { defaults } from '../../utils'\nimport Structure from '../../structure/structure'\n// import { valenceModel } from '../../structure/data'\nimport { Elements, AA3, Bases } from '../../structure/structure-constants'\n// import { hasAromaticNeighbour } from '../functional-groups'\nimport {\n Features, FeatureType,\n addAtom, addFeature, createFeatureState,\n} from './features'\nimport { Contacts, ContactType, ContactDefaultParams, invalidAtomContact } from './contact'\n\nconst IonicTypeMetals = [\n Elements.LI, Elements.NA, Elements.K, Elements.RB, Elements.CS,\n Elements.MG, Elements.CA, Elements.SR, Elements.BA, Elements.AL,\n Elements.GA, Elements.IN, Elements.TL, Elements.SC, Elements.SN,\n Elements.PB, Elements.BI, Elements.SB, Elements.HG\n]\n\n/**\n * Metal binding partners (dative bond or ionic-type interaction)\n */\nexport function addMetalBinding (structure: Structure, features: Features) {\n structure.eachAtom(a => {\n let dative = false\n let ionic = false\n\n const isStandardAminoacid = AA3.includes(a.resname)\n const isStandardBase = Bases.includes(a.resname)\n\n if (!isStandardAminoacid && !isStandardBase) {\n if (a.isHalogen() || a.number === Elements.O || a.number === Elements.S) {\n dative = true\n ionic = true\n } else if (a.number === Elements.N) {\n dative = true\n }\n } else if (isStandardAminoacid){\n // main chain oxygen atom or oxygen, nitrogen and sulfur from specific amino acids\n if (a.number === Elements.O) {\n if(['ASP', 'GLU', 'SER', 'THR', 'TYR', 'ASN', 'GLN'].includes(a.resname) && a.isSidechain()) {\n dative = true\n ionic = true\n } else if (a.isBackbone()) {\n dative = true\n ionic = true\n }\n } else if (a.number === Elements.S && 'CYS' === a.resname) {\n dative = true\n ionic = true\n } else if (a.number === Elements.N) {\n if(a.resname === 'HIS' && a.isSidechain()) {\n dative = true\n }\n }\n } else if (isStandardBase){\n // http://pubs.acs.org/doi/pdf/10.1021/acs.accounts.6b00253\n // http://onlinelibrary.wiley.com/doi/10.1002/anie.200900399/full\n if (a.number === Elements.O && a.isBackbone()) {\n dative = true\n ionic = true\n } else if(['N3', 'N4', 'N7'].includes(a.atomname)) {\n dative = true\n } else if(['O2', 'O4', 'O6'].includes(a.atomname)) {\n dative = true\n ionic = true\n }\n }\n if (dative) {\n const state = createFeatureState(FeatureType.DativeBondPartner)\n addAtom(state, a)\n addFeature(features, state)\n }\n if (ionic) {\n const state = createFeatureState(FeatureType.IonicTypePartner)\n addAtom(state, a)\n addFeature(features, state)\n }\n })\n}\n\n/**\n * Metal Pi complexation partner\n */\n// export function addMetalPiPartners (structure: Structure, features: Features) {\n// const { charge } = valenceModel(structure.data)\n\n// structure.eachAtom(a => {\n// const state = createFeatureState(FeatureType.MetalPiPartner)\n\n// const resname = a.resname\n// const element = a.element\n// const atomname = a.atomname\n// if (!a.isPolymer()) {\n// // water oxygen, as well as oxygen from carboxylate, phosphoryl, phenolate, alcohol;\n// // nitrogen from imidazole; sulfur from thiolate\n// if (element === 'O') {\n// // Water oxygen\n// if (a.bondCount === 0 || a.isWater()) {\n// addAtom(state, a)\n// addFeature(features, state)\n// return\n// }\n// // Oxygen in alcohol (R-[O]-H)\n// if (a.bondCount === 2 && charge[ a.index ] || a.hasBondToElement('H')) {\n// addAtom(state, a)\n// addFeature(features, state)\n// return\n// }\n// // Phenolate oxygen\n// if (hasAromaticNeighbour(a) && !a.aromatic) {\n// addAtom(state, a)\n// addFeature(features, state)\n// return\n// }\n// // Carboxylic acid oxygen\n// if (a.bondToElementCount('C') === 1) {\n// let flag = false\n// a.eachBondedAtom(ba => {\n// if (ba.element === 'C' && ba.bondToElementCount('O') === 2 && ba.bondToElementCount('C') === 1) {\n// flag = true\n// }\n// })\n// if (flag) {\n// addAtom(state, a)\n// addFeature(features, state)\n// return\n// }\n// }\n// // Phosphoryl oxygen\n// if (a.bondToElementCount('P') === 1) {\n// let flag = false\n// a.eachBondedAtom(ba => {\n// if (ba.element === 'P' && ba.bondToElementCount('O') >= 3) {\n// flag = true\n// }\n// })\n// if (flag) {\n// addAtom(state, a)\n// addFeature(features, state)\n// return\n// }\n// }\n// } else if (element === 'N') {\n// // Imidazole/pyrrole or similar\n// if (a.bondToElementCount('C') === 2) {\n// addAtom(state, a)\n// addFeature(features, state)\n// return\n// }\n// } else if (element === 'S') {\n// // Thiolate\n// if (hasAromaticNeighbour(a) && !a.aromatic) {\n// addAtom(state, a)\n// addFeature(features, state)\n// return\n// }\n// // Sulfur in Iron sulfur cluster\n// const ironCount = a.bondToElementCount('FE')\n// if (ironCount > 0 && ironCount === a.bondCount) {\n// addAtom(state, a)\n// addFeature(features, state)\n// return\n// }\n// }\n// }\n// })\n// }\n\nexport function addMetals (structure: Structure, features: Features) {\n structure.eachAtom(a => {\n if (a.isTransitionMetal() || a.number === Elements.ZN || a.number === Elements.CD) {\n const state = createFeatureState(FeatureType.TransitionMetal)\n addAtom(state, a)\n addFeature(features, state)\n } else if (IonicTypeMetals.includes(a.number)) {\n const state = createFeatureState(FeatureType.IonicTypeMetal)\n addAtom(state, a)\n addFeature(features, state)\n }\n })\n}\n\nfunction isMetalComplex (ti: FeatureType, tj: FeatureType) {\n if (ti === FeatureType.TransitionMetal) {\n return (\n tj === FeatureType.DativeBondPartner ||\n tj === FeatureType.TransitionMetal\n )\n } else if (ti === FeatureType.IonicTypeMetal) {\n return (\n tj === FeatureType.IonicTypePartner\n )\n }\n}\n\nexport interface MetalComplexationParams {\n maxMetalDist?: number\n masterModelIndex?: number\n}\n\n/**\n * Metal complexes of metals and appropriate groups in protein and ligand, including water\n */\nexport function addMetalComplexation (structure: Structure, contacts: Contacts, params: MetalComplexationParams = {}) {\n const maxMetalDist = defaults(params.maxMetalDist, ContactDefaultParams.maxMetalDist)\n const masterIdx = defaults(params.masterModelIndex, ContactDefaultParams.masterModelIndex)\n\n const { features, spatialHash, contactStore, featureSet } = contacts\n const { types, centers, atomSets } = features\n const { x, y, z } = centers\n const n = types.length\n\n const ap1 = structure.getAtomProxy()\n const ap2 = structure.getAtomProxy()\n\n for (let i = 0; i < n; ++i) {\n spatialHash.eachWithin(x[i], y[i], z[i], maxMetalDist, (j, dSq) => {\n if (j <= i) return\n\n ap1.index = atomSets[ i ][ 0 ]\n ap2.index = atomSets[ j ][ 0 ]\n\n if (invalidAtomContact(ap1, ap2, masterIdx)) return\n\n const m1 = ap1.isMetal()\n const m2 = ap2.isMetal()\n if (!m1 && !m2) return\n\n const [ ti, tj ] = m1 ? [ types[ i ],types[ j ] ] : [ types[ j ],types[ i ] ]\n\n if (isMetalComplex(ti, tj)) {\n featureSet.setBits(i, j)\n contactStore.addContact(i, j, ContactType.MetalCoordination)\n }\n })\n }\n}\n","/**\n * @file Halogen Bonds\n * @author Alexander Rose \n * @author Fred Ludlow \n */\n\nimport { defaults } from '../../utils'\nimport Structure from '../../structure/structure'\nimport { Elements } from '../../structure/structure-constants'\nimport { degToRad } from '../../math/math-utils'\nimport {\n Features, FeatureType,\n addAtom, addFeature, createFeatureState,\n} from './features'\nimport { Contacts, ContactType, ContactDefaultParams, invalidAtomContact } from './contact'\nimport { calcAngles } from '../geometry'\n\nconst halBondElements = [17, 35, 53, 85]\n\n/**\n * Halogen bond donors (X-C, with X one of Cl, Br, I or At) not F!\n */\nexport function addHalogenDonors (structure: Structure, features: Features) {\n structure.eachAtom(a => {\n if (halBondElements.includes(a.number) && a.bondToElementCount(Elements.C) === 1) {\n const state = createFeatureState(FeatureType.HalogenDonor)\n addAtom(state, a)\n addFeature(features, state)\n }\n })\n}\n\nconst X = [ Elements.N, Elements.O, Elements.S ]\nconst Y = [ Elements.C, Elements.N, Elements.P, Elements.S ]\n\n/**\n * Halogen bond acceptors (Y-{O|N|S}, with Y=C,P,N,S)\n */\nexport function addHalogenAcceptors (structure: Structure, features: Features) {\n structure.eachAtom(a => {\n if (X.includes(a.number)) {\n let flag = false\n a.eachBondedAtom(ba => {\n if (Y.includes(ba.number)) {\n flag = true\n }\n })\n if (flag) {\n const state = createFeatureState(FeatureType.HalogenAcceptor)\n addAtom(state, a)\n addFeature(features, state)\n }\n }\n })\n}\n\nfunction isHalogenBond (ti: FeatureType, tj: FeatureType) {\n return (\n (ti === FeatureType.HalogenAcceptor && tj === FeatureType.HalogenDonor) ||\n (ti === FeatureType.HalogenDonor && tj === FeatureType.HalogenAcceptor)\n )\n}\n\nexport interface HalogenBondsParams {\n maxHalogenBondDist?: number\n maxHalogenBondAngle?: number\n masterModelIndex?: number\n}\n\n// http://www.pnas.org/content/101/48/16789.full\nconst OptimalHalogenAngle = degToRad(180) // adjusted from 165 to account for spherical statistics\nconst OptimalAcceptorAngle = degToRad(120)\n\n/**\n * All pairs of halogen donor and acceptor atoms\n */\nexport function addHalogenBonds (structure: Structure, contacts: Contacts, params: HalogenBondsParams = {}) {\n const maxHalogenBondDist = defaults(params.maxHalogenBondDist, ContactDefaultParams.maxHalogenBondDist)\n const maxHalogenBondAngle = degToRad(defaults(params.maxHalogenBondAngle, ContactDefaultParams.maxHalogenBondAngle))\n const masterIdx = defaults(params.masterModelIndex, ContactDefaultParams.masterModelIndex)\n\n const { features, spatialHash, contactStore, featureSet } = contacts\n const { types, centers, atomSets } = features\n const { x, y, z } = centers\n const n = types.length\n\n const ap1 = structure.getAtomProxy()\n const ap2 = structure.getAtomProxy()\n\n for (let i = 0; i < n; ++i) {\n spatialHash.eachWithin(x[i], y[i], z[i], maxHalogenBondDist, (j, dSq) => {\n if (j <= i) return\n\n ap1.index = atomSets[ i ][ 0 ]\n ap2.index = atomSets[ j ][ 0 ]\n\n if (invalidAtomContact(ap1, ap2, masterIdx)) return\n if (!isHalogenBond(types[ i ], types[ j ])) return\n\n const [ halogen, acceptor ] = types[ i ] === FeatureType.HalogenDonor ? [ ap1, ap2 ] : [ ap2, ap1 ]\n\n const halogenAngles = calcAngles(halogen, acceptor)\n // Singly bonded halogen only (not bromide ion for example)\n if (halogenAngles.length !== 1) return\n if (OptimalHalogenAngle - halogenAngles[0] > maxHalogenBondAngle) return\n\n const acceptorAngles = calcAngles(acceptor, halogen)\n // Angle must be defined. Excludes water as acceptor. Debatable\n if (acceptorAngles.length === 0) return\n if (acceptorAngles.some(acceptorAngle => {\n return (OptimalAcceptorAngle - acceptorAngle > maxHalogenBondAngle)\n })) return\n\n\n featureSet.setBits(i, j)\n contactStore.addContact(i, j, ContactType.HalogenBond)\n\n })\n }\n}\n","/**\n * @file Refine Contacts\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { Debug, Log } from '../../globals'\nimport { defaults } from '../../utils'\nimport Structure from '../../structure/structure'\nimport AtomProxy from '../../proxy/atom-proxy'\nimport { Elements } from '../../structure/structure-constants'\nimport { FrozenContacts, ContactType, ContactDefaultParams, isMasterContact } from './contact'\nimport { FeatureType } from './features'\n\nexport interface LineOfSightParams {\n lineOfSightDistFactor?: number\n masterModelIndex?: number\n}\n\n// also allows intra-residue contacts\nexport function invalidAtomContact (ap1: AtomProxy, ap2: AtomProxy, masterIdx: number) {\n return !isMasterContact(ap1, ap2, masterIdx) && (\n ap1.modelIndex !== ap2.modelIndex ||\n (ap1.altloc && ap2.altloc && ap1.altloc !== ap2.altloc)\n )\n}\n\nexport function refineLineOfSight (structure: Structure, contacts: FrozenContacts, params: LineOfSightParams = {}) {\n if (Debug) Log.time('refineLineOfSight')\n\n const lineOfSightDistFactor = defaults(params.lineOfSightDistFactor, ContactDefaultParams.lineOfSightDistFactor)\n const masterIdx = defaults(params.masterModelIndex, ContactDefaultParams.masterModelIndex)\n\n const spatialHash = structure.spatialHash!\n const { contactSet, contactStore, features } = contacts\n const { index1, index2 } = contactStore\n const { centers, atomSets } = features\n const { x, y, z } = centers\n\n const ac1 = structure.getAtomProxy()\n const ac2 = structure.getAtomProxy()\n const aw = structure.getAtomProxy()\n\n const c1 = new Vector3()\n const c2 = new Vector3()\n\n const lineOfSightDist = 3 * lineOfSightDistFactor\n const lineOfSightDistFactorSq = lineOfSightDistFactor * lineOfSightDistFactor\n\n contactSet.forEach(i => {\n c1.set(x[index1[i]], y[index1[i]], z[index1[i]])\n c2.set(x[index2[i]], y[index2[i]], z[index2[i]])\n\n const cx = ( c1.x + c2.x ) / 2\n const cy = ( c1.y + c2.y ) / 2\n const cz = ( c1.z + c2.z ) / 2\n\n const as1 = atomSets[ index1[ i ] ]\n const as2 = atomSets[ index2[ i ] ]\n\n ac1.index = as1[ 0 ]\n ac2.index = as2[ 0 ]\n\n spatialHash.eachWithin(cx, cy, cz, lineOfSightDist, (j, dSq) => {\n aw.index = j\n if (\n aw.number !== Elements.H &&\n (aw.vdw * aw.vdw * lineOfSightDistFactorSq) > dSq &&\n !invalidAtomContact(ac1, aw, masterIdx) &&\n !invalidAtomContact(ac2, aw, masterIdx) &&\n !as1.includes(j) &&\n !as2.includes(j) &&\n // to ignore atoms in the center of functional groups\n c1.distanceToSquared(aw as any) > 1 &&\n c2.distanceToSquared(aw as any) > 1\n ) {\n contactSet.clear(i)\n if (Debug) Log.log('removing', ac1.qualifiedName(), ac2.qualifiedName(), 'because', aw.qualifiedName())\n }\n })\n })\n\n if (Debug) Log.timeEnd('refineLineOfSight')\n}\n\n/**\n * For atoms interacting with several atoms in the same residue\n * only the one with the closest distance is kept.\n */\nexport function refineHydrophobicContacts (structure: Structure, contacts: FrozenContacts) {\n const { contactSet, contactStore, features } = contacts\n const { type, index1, index2 } = contactStore\n const { atomSets } = features\n\n const ap1 = structure.getAtomProxy()\n const ap2 = structure.getAtomProxy()\n\n const residueContactDict: { [k: string]: number[] } = {}\n\n /* keep only closest contact between residues */\n const handleResidueContact = function (dist: number, i: number, key: string) {\n const [ minDist, minIndex ] = residueContactDict[ key ] || [ Infinity, -1 ]\n if (dist < minDist) {\n if (minIndex !== -1) contactSet.clear(minIndex)\n residueContactDict[ key ] = [ dist, i ]\n } else {\n contactSet.clear(i)\n }\n }\n\n contactSet.forEach(i => {\n if (type[ i ] !== ContactType.Hydrophobic) return\n\n ap1.index = atomSets[ index1[ i ] ][ 0 ]\n ap2.index = atomSets[ index2[ i ] ][ 0 ]\n\n const dist = ap1.distanceTo(ap2)\n handleResidueContact(dist, i, `${ap1.index}|${ap2.residueIndex}`)\n handleResidueContact(dist, i, `${ap2.index}|${ap1.residueIndex}`)\n })\n}\n\nfunction isHydrogenBondType (type: number) {\n return (\n type === ContactType.HydrogenBond ||\n type === ContactType.WaterHydrogenBond ||\n type === ContactType.BackboneHydrogenBond\n )\n}\n\n/**\n * Remove weak hydrogen bonds when the acceptor is involved in\n * a normal/strong hydrogen bond\n */\nexport function refineWeakHydrogenBonds (structure: Structure, contacts: FrozenContacts) {\n const { contactSet, contactStore, features, adjacencyList } = contacts\n const { type, index1, index2 } = contactStore\n const { types } = features\n\n contactSet.forEach(i => {\n if (type[ i ] !== ContactType.WeakHydrogenBond) return\n\n let accFeat: number\n if (types[ index1[ i ] ] === FeatureType.WeakHydrogenDonor) {\n accFeat = index2[ i ]\n } else {\n accFeat = index1[ i ]\n }\n\n const n = adjacencyList.countArray[ accFeat ]\n const offset = adjacencyList.offsetArray[ accFeat ]\n for (let j = 0; j < n; ++j) {\n const ci = adjacencyList.indexArray[ offset + j ]\n if (isHydrogenBondType(type[ ci ])) {\n contactSet.clear(i)\n return\n }\n }\n })\n}\n\n/**\n * Remove hydrogen bonds between groups that also form\n * a salt bridge between each other\n */\nexport function refineSaltBridges (structure: Structure, contacts: FrozenContacts) {\n const { contactSet, contactStore, features } = contacts\n const { type, index1, index2 } = contactStore\n const { atomSets } = features\n\n const ionicInteractionDict: { [atomIndex: number]: number[] } = {}\n\n const add = function(idx: number, i: number) {\n if (!ionicInteractionDict[ idx ]) ionicInteractionDict[ idx ] = []\n ionicInteractionDict[ idx ].push(i)\n }\n\n contactSet.forEach(i => {\n if (type[ i ] !== ContactType.IonicInteraction) return\n atomSets[ index1[ i ] ].forEach(idx => add(idx, i))\n atomSets[ index2[ i ] ].forEach(idx => add(idx, i))\n })\n\n contactSet.forEach(i => {\n if (!isHydrogenBondType(type[ i ])) return\n\n const iil1 = ionicInteractionDict[ atomSets[ index1[ i ] ][ 0 ] ]\n const iil2 = ionicInteractionDict[ atomSets[ index2[ i ] ][ 0 ] ]\n if (!iil1 || !iil2) return\n\n const n = iil1.length\n for (let j = 0; j < n; ++j) {\n if (iil2.includes(iil1[j])) {\n contactSet.clear(i)\n return\n }\n }\n })\n}\n\n/**\n * Remove hydrophobic and cation-pi interactions between groups that also form\n * a pi-stacking interaction between each other\n */\nexport function refinePiStacking (structure: Structure, contacts: FrozenContacts) {\n const { contactSet, contactStore, features } = contacts\n const { type, index1, index2 } = contactStore\n const { atomSets } = features\n\n const piStackingDict: { [atomIndex: number]: number[] } = {}\n\n const add = function(idx: number, i: number) {\n if (!piStackingDict[ idx ]) piStackingDict[ idx ] = []\n piStackingDict[ idx ].push(i)\n }\n\n contactSet.forEach(i => {\n if (type[ i ] !== ContactType.PiStacking) return\n atomSets[ index1[ i ] ].forEach(idx => add(idx, i))\n atomSets[ index2[ i ] ].forEach(idx => add(idx, i))\n })\n\n contactSet.forEach(i => {\n if (\n type[ i ] !== ContactType.Hydrophobic &&\n type[ i ] !== ContactType.CationPi\n ) return\n\n const pil1 = piStackingDict[ atomSets[ index1[ i ] ][ 0 ] ]\n const pil2 = piStackingDict[ atomSets[ index2[ i ] ][ 0 ] ]\n if (!pil1 || !pil2) return\n\n const n = pil1.length\n for (let j = 0; j < n; ++j) {\n if (pil2.includes(pil1[j])) {\n contactSet.clear(i)\n return\n }\n }\n })\n}\n\n/**\n * Remove ionic interactions between groups that also form\n * a metal coordination between each other\n */\nexport function refineMetalCoordination (structure: Structure, contacts: FrozenContacts) {\n const { contactSet, contactStore, features } = contacts\n const { type, index1, index2 } = contactStore\n const { atomSets } = features\n\n const ionicInteractionDict: { [atomIndex: number]: number[] } = {}\n\n const add = function(idx: number, i: number) {\n if (!ionicInteractionDict[ idx ]) ionicInteractionDict[ idx ] = []\n ionicInteractionDict[ idx ].push(i)\n }\n\n contactSet.forEach(i => {\n if (type[ i ] !== ContactType.IonicInteraction) return\n atomSets[ index1[ i ] ].forEach(idx => add(idx, i))\n atomSets[ index2[ i ] ].forEach(idx => add(idx, i))\n })\n\n contactSet.forEach(i => {\n if (type[ i ] !== ContactType.MetalCoordination) return\n\n const iil1 = ionicInteractionDict[ atomSets[ index1[ i ] ][ 0 ] ]\n const iil2 = ionicInteractionDict[ atomSets[ index2[ i ] ][ 0 ] ]\n if (!iil1 || !iil2) return\n\n const n = iil1.length\n for (let j = 0; j < n; ++j) {\n if (iil2.includes(iil1[j])) {\n contactSet.clear(iil1[j])\n return\n }\n }\n })\n}\n\n// TODO: refactor refineSaltBridges, refinePiStacking and refineMetalCoordination to be DRY\n","/**\n * @file Contact\n * @author Alexander Rose \n */\n\nimport { Color } from 'three'\n\nimport { Debug, Log } from '../../globals'\nimport { createParams } from '../../utils'\nimport { TextBufferData } from '../../buffer/text-buffer'\nimport Structure from '../../structure/structure'\nimport AtomProxy from '../../proxy/atom-proxy'\nimport SpatialHash from '../../geometry/spatial-hash'\nimport { calculateCenterArray, calculateDirectionArray, uniformArray } from '../../math/array-utils'\nimport ContactStore from '../../store/contact-store'\nimport BitArray from '../../utils/bitarray'\nimport Selection from '../../selection/selection'\nimport { ContactPicker } from '../../utils/picker'\nimport { createAdjacencyList, AdjacencyList } from '../../utils/adjacency-list'\nimport { createFeatures, Features } from './features'\nimport { addAromaticRings, addNegativeCharges, addPositiveCharges, addChargedContacts } from './charged'\nimport { addHydrogenAcceptors, addHydrogenDonors, addHydrogenBonds, addWeakHydrogenDonors } from './hydrogen-bonds'\nimport { addMetalBinding, addMetals, addMetalComplexation } from './metal-binding'\nimport { addHydrophobic, addHydrophobicContacts } from './hydrophobic'\nimport { addHalogenAcceptors, addHalogenDonors, addHalogenBonds } from './halogen-bonds'\nimport {\n refineLineOfSight,\n refineHydrophobicContacts, refineSaltBridges, refinePiStacking, refineMetalCoordination\n} from './refine-contacts'\n\nexport interface Contacts {\n features: Features\n spatialHash: SpatialHash\n contactStore: ContactStore\n featureSet: BitArray\n}\n\nexport interface FrozenContacts extends Contacts {\n contactSet: BitArray\n adjacencyList: AdjacencyList\n}\n\nexport const enum ContactType {\n Unknown = 0,\n IonicInteraction = 1,\n CationPi = 2,\n PiStacking = 3,\n HydrogenBond = 4,\n HalogenBond = 5,\n Hydrophobic = 6,\n MetalCoordination = 7,\n WeakHydrogenBond = 8,\n WaterHydrogenBond = 9,\n BackboneHydrogenBond = 10\n}\n\nexport const ContactDefaultParams = {\n maxHydrophobicDist: 4.0,\n maxHbondDist: 3.5,\n maxHbondSulfurDist: 4.1,\n maxHbondAccAngle: 45,\n maxHbondDonAngle: 45,\n maxHbondAccPlaneAngle: 90,\n maxHbondDonPlaneAngle: 30,\n maxPiStackingDist: 5.5,\n maxPiStackingOffset: 2.0,\n maxPiStackingAngle: 30,\n maxCationPiDist: 6.0,\n maxCationPiOffset: 2.0,\n maxIonicDist: 5.0,\n maxHalogenBondDist: 4.0,\n maxHalogenBondAngle: 30,\n maxMetalDist: 3.0,\n refineSaltBridges: true,\n masterModelIndex: -1,\n lineOfSightDistFactor: 1.0\n}\n\nexport function isMasterContact (ap1: AtomProxy, ap2: AtomProxy, masterIdx: number) {\n return (\n (ap1.modelIndex === masterIdx && ap2.modelIndex !== masterIdx) ||\n (ap2.modelIndex === masterIdx && ap1.modelIndex !== masterIdx)\n )\n}\n\nexport function invalidAtomContact (ap1: AtomProxy, ap2: AtomProxy, masterIdx: number) {\n return !isMasterContact(ap1, ap2, masterIdx) && (\n ap1.modelIndex !== ap2.modelIndex ||\n ap1.residueIndex === ap2.residueIndex ||\n (ap1.altloc && ap2.altloc && ap1.altloc !== ap2.altloc)\n )\n}\n\nexport function createContacts (features: Features): Contacts {\n const { types, centers } = features\n\n const spatialHash = new SpatialHash(centers)\n const contactStore = new ContactStore()\n const featureSet = new BitArray(types.length, false)\n\n return { features, spatialHash, contactStore, featureSet }\n}\n\nexport function createFrozenContacts (contacts: Contacts): FrozenContacts {\n const { index1, index2, count } = contacts.contactStore\n\n const adjacencyList = createAdjacencyList({\n nodeArray1: index1,\n nodeArray2: index2,\n edgeCount: count,\n nodeCount: contacts.featureSet.length\n })\n const contactSet = new BitArray(contacts.contactStore.count, true)\n\n return Object.assign({ adjacencyList, contactSet }, contacts)\n}\n\nfunction calculateFeatures (structure: Structure) {\n const features = createFeatures()\n\n if (Debug) Log.time('calculateFeatures')\n\n addPositiveCharges(structure, features)\n addNegativeCharges(structure, features)\n addAromaticRings(structure, features)\n\n addHydrogenAcceptors(structure, features)\n addHydrogenDonors(structure, features)\n addWeakHydrogenDonors(structure, features)\n\n addMetalBinding(structure, features)\n addMetals(structure, features)\n\n addHydrophobic(structure, features)\n\n addHalogenAcceptors(structure, features)\n addHalogenDonors(structure, features)\n\n if (Debug) Log.timeEnd('calculateFeatures')\n\n return features\n}\n\nexport function calculateContacts (structure: Structure, params = ContactDefaultParams) {\n const features = calculateFeatures(structure)\n const contacts = createContacts(features)\n\n if (Debug) Log.time('calculateContacts')\n\n addChargedContacts(structure, contacts, params)\n addHydrogenBonds(structure, contacts, params)\n addMetalComplexation(structure, contacts, params)\n addHydrophobicContacts(structure, contacts, params)\n addHalogenBonds(structure, contacts, params)\n\n const frozenContacts = createFrozenContacts(contacts)\n\n refineLineOfSight(structure, frozenContacts, params)\n refineHydrophobicContacts(structure, frozenContacts)\n if (params.refineSaltBridges) refineSaltBridges(structure, frozenContacts)\n refinePiStacking(structure, frozenContacts)\n refineMetalCoordination(structure, frozenContacts)\n\n if (Debug) Log.timeEnd('calculateContacts')\n\n return frozenContacts\n}\n\nexport function contactTypeName (type: ContactType) {\n switch (type) {\n case ContactType.HydrogenBond:\n case ContactType.WaterHydrogenBond:\n case ContactType.BackboneHydrogenBond:\n return 'hydrogen bond'\n case ContactType.Hydrophobic:\n return 'hydrophobic contact'\n case ContactType.HalogenBond:\n return 'halogen bond'\n case ContactType.IonicInteraction:\n return 'ionic interaction'\n case ContactType.MetalCoordination:\n return 'metal coordination'\n case ContactType.CationPi:\n return 'cation-pi interaction'\n case ContactType.PiStacking:\n return 'pi-pi stacking'\n case ContactType.WeakHydrogenBond:\n return 'weak hydrogen bond'\n default:\n return 'unknown contact'\n }\n}\n\nexport const ContactDataDefaultParams = {\n hydrogenBond: true,\n hydrophobic: true,\n halogenBond: true,\n ionicInteraction: true,\n metalCoordination: true,\n cationPi: true,\n piStacking: true,\n weakHydrogenBond: true,\n waterHydrogenBond: true,\n backboneHydrogenBond: true,\n radius: 1,\n filterSele: ''\n}\nexport type ContactDataParams = typeof ContactDataDefaultParams\n | { filterSele: string|[string, string] }\n\nexport const ContactLabelDefaultParams = {\n unit: '',\n size: 2.0\n}\n\nexport type ContactLabelParams = typeof ContactLabelDefaultParams\n\nconst tmpColor = new Color()\nfunction contactColor (type: ContactType) {\n switch (type) {\n case ContactType.HydrogenBond:\n case ContactType.WaterHydrogenBond:\n case ContactType.BackboneHydrogenBond:\n return tmpColor.setHex(0x2B83BA).toArray()\n case ContactType.Hydrophobic:\n return tmpColor.setHex(0x808080).toArray()\n case ContactType.HalogenBond:\n return tmpColor.setHex(0x40FFBF).toArray()\n case ContactType.IonicInteraction:\n return tmpColor.setHex(0xF0C814).toArray()\n case ContactType.MetalCoordination:\n return tmpColor.setHex(0x8C4099).toArray()\n case ContactType.CationPi:\n return tmpColor.setHex(0xFF8000).toArray()\n case ContactType.PiStacking:\n return tmpColor.setHex(0x8CB366).toArray()\n case ContactType.WeakHydrogenBond:\n return tmpColor.setHex(0xC5DDEC).toArray()\n default:\n return tmpColor.setHex(0xCCCCCC).toArray()\n }\n}\n\nexport interface ContactData {\n position1: Float32Array,\n position2: Float32Array,\n color: Float32Array,\n color2: Float32Array,\n radius: Float32Array,\n picking: ContactPicker\n}\n\nexport function getContactData (contacts: FrozenContacts, structure: Structure, params: ContactDataParams): ContactData {\n const p = createParams(params, ContactDataDefaultParams)\n const types: ContactType[] = []\n if (p.hydrogenBond) types.push(ContactType.HydrogenBond)\n if (p.hydrophobic) types.push(ContactType.Hydrophobic)\n if (p.halogenBond) types.push(ContactType.HalogenBond)\n if (p.ionicInteraction) types.push(ContactType.IonicInteraction)\n if (p.metalCoordination) types.push(ContactType.MetalCoordination)\n if (p.cationPi) types.push(ContactType.CationPi)\n if (p.piStacking) types.push(ContactType.PiStacking)\n if (p.weakHydrogenBond) types.push(ContactType.WeakHydrogenBond)\n if (p.waterHydrogenBond) types.push(ContactType.WaterHydrogenBond)\n if (p.backboneHydrogenBond) types.push(ContactType.BackboneHydrogenBond)\n\n const { features, contactSet, contactStore } = contacts\n const { centers, atomSets } = features\n const { x, y, z } = centers\n const { index1, index2, type } = contactStore\n\n const position1: number[] = []\n const position2: number[] = []\n const color: number[] = []\n const radius: number[] = []\n const picking: number[] = []\n\n let filterSet: BitArray | BitArray[] | undefined\n if (p.filterSele) {\n if (Array.isArray(p.filterSele)) {\n filterSet = p.filterSele.map(sele => {\n return structure.getAtomSet(new Selection(sele))\n })\n } else {\n filterSet = structure.getAtomSet(new Selection(p.filterSele))\n }\n }\n\n contactSet.forEach(i => {\n const ti = type[ i ]\n if (!types.includes(ti)) return\n\n if (filterSet) {\n const idx1 = atomSets[index1[i]][0]\n const idx2 = atomSets[index2[i]][0]\n\n if (Array.isArray(filterSet)) {\n if (!(filterSet[0].isSet(idx1) && filterSet[1].isSet(idx2) || (filterSet[1].isSet(idx1) && filterSet[0].isSet(idx2)))) return\n } else {\n if (!filterSet.isSet(idx1) && !filterSet.isSet(idx2)) return\n }\n }\n\n const k = index1[i]\n const l = index2[i]\n position1.push(x[k], y[k], z[k])\n position2.push(x[l], y[l], z[l])\n color.push(...contactColor(ti))\n radius.push(p.radius)\n picking.push(i)\n })\n\n return {\n position1: new Float32Array(position1),\n position2: new Float32Array(position2),\n color: new Float32Array(color),\n color2: new Float32Array(color),\n radius: new Float32Array(radius),\n picking: new ContactPicker(picking, contacts, structure)\n }\n}\n\nexport function getLabelData (contactData: ContactData, params: ContactLabelParams): TextBufferData {\n\n const position = calculateCenterArray(contactData.position1, contactData.position2)\n const text: string[] = []\n\n const direction = calculateDirectionArray(contactData.position1, contactData.position2)\n\n const n = direction.length / 3\n for (let i=0; i\n */\n\nimport { defaults } from '../../utils'\nimport Structure from '../../structure/structure'\nimport { Elements } from '../../structure/structure-constants'\nimport {\n Features, FeatureType,\n addAtom, addFeature, createFeatureState,\n} from './features'\nimport { Contacts, ContactType, ContactDefaultParams, invalidAtomContact } from './contact'\n\n/**\n * Hydrophobic carbon (only bonded to carbon or hydrogen); fluorine\n */\nexport function addHydrophobic (structure: Structure, features: Features) {\n structure.eachAtom(a => {\n const state = createFeatureState(FeatureType.Hydrophobic)\n let flag = false\n if (a.number === Elements.C) {\n flag = true\n a.eachBondedAtom(ap => {\n const an = ap.number\n if (an !== Elements.C && an !== Elements.H) flag = false\n })\n } else if (a.number === Elements.F) {\n flag = true\n }\n if (flag) {\n addAtom(state, a)\n addFeature(features, state)\n }\n })\n}\n\nfunction isHydrophobicContact (ti: FeatureType, tj: FeatureType) {\n return ti === FeatureType.Hydrophobic && tj === FeatureType.Hydrophobic\n}\n\nexport interface HydrophobicContactsParams {\n maxHydrophobicDist?: number\n masterModelIndex?: number\n}\n\n/**\n * All hydrophobic contacts\n */\nexport function addHydrophobicContacts (structure: Structure, contacts: Contacts, params: HydrophobicContactsParams = {}) {\n const maxHydrophobicDist = defaults(params.maxHydrophobicDist, ContactDefaultParams.maxHydrophobicDist)\n const masterIdx = defaults(params.masterModelIndex, ContactDefaultParams.masterModelIndex)\n\n const { features, spatialHash, contactStore, featureSet } = contacts\n const { types, centers, atomSets } = features\n const { x, y, z } = centers\n const n = types.length\n\n const ap1 = structure.getAtomProxy()\n const ap2 = structure.getAtomProxy()\n\n for (let i = 0; i < n; ++i) {\n spatialHash.eachWithin(x[i], y[i], z[i], maxHydrophobicDist, (j, dSq) => {\n if (j <= i) return\n\n ap1.index = atomSets[ i ][ 0 ]\n ap2.index = atomSets[ j ][ 0 ]\n\n if (invalidAtomContact(ap1, ap2, masterIdx)) return\n if (ap1.number === Elements.F && ap2.number === Elements.F) return\n if (ap1.connectedTo(ap2)) return\n\n if (isHydrophobicContact(types[ i ], types[ j ])) {\n featureSet.setBits(i, j)\n contactStore.addContact(i, j, ContactType.Hydrophobic)\n }\n })\n }\n}\n","/**\n * @file Picker\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { PickerRegistry } from '../globals'\nimport { calculateMeanVector3 } from '../math/vector-utils'\nimport Selection from '../selection/selection'\nimport {\n ArrowPrimitive, BoxPrimitive, ConePrimitive, CylinderPrimitive,\n EllipsoidPrimitive, OctahedronPrimitive, SpherePrimitive,\n TetrahedronPrimitive, TorusPrimitive, PointPrimitive, WidelinePrimitive\n} from '../geometry/primitive'\nimport { contactTypeName, Contacts } from '../chemistry/interactions/contact'\nimport { TypedArray } from '../types';\nimport Component from '../component/component';\nimport { Shape, Structure, Volume } from '../ngl';\nimport BondStore from '../store/bond-store';\nimport Validation from '../structure/validation';\nimport PrincipalAxes from '../math/principal-axes';\nimport Surface from '../surface/surface';\nimport Unitcell from '../symmetry/unitcell';\nimport BondProxy from '../proxy/bond-proxy';\nimport AtomProxy from '../proxy/atom-proxy';\n\n/**\n * Picker class\n * @interface\n */\nclass Picker {\n array: number[]|TypedArray|undefined\n /**\n * @param {Array|TypedArray} [array] - mapping\n */\n constructor (array?: number[]|TypedArray) {\n this.array = array\n }\n\n get type () { return '' }\n get data () { return {} }\n\n /**\n * Get the index for the given picking id\n * @param {Integer} pid - the picking id\n * @return {Integer} the index\n */\n getIndex (pid: number) {\n return this.array ? this.array[ pid ] : pid\n }\n\n /**\n * Get object data\n * @abstract\n * @param {Integer} pid - the picking id\n * @return {Object} the object data\n */\n getObject (pid: number) {\n return {}\n }\n\n _applyTransformations (vector: Vector3, instance: any, component: Component) {\n if (instance) {\n vector.applyMatrix4(instance.matrix)\n }\n if (component) {\n vector.applyMatrix4(component.matrix)\n }\n return vector\n }\n\n /**\n * Get object position\n * @abstract\n * @param {Integer} pid - the picking id\n * @return {Vector3} the object position\n */\n _getPosition (pid: number) {\n return new Vector3()\n }\n\n /**\n * Get position for the given picking id\n * @param {Integer} pid - the picking id\n * @param {Object} instance - the instance that should be applied\n * @param {Component} component - the component of the picked object\n * @return {Vector3} the position\n */\n getPosition (pid: number, instance: any, component: Component) {\n return this._applyTransformations(\n this._getPosition(pid), instance, component\n )\n }\n}\n\n/**\n * Shape picker class\n * @interface\n */\nclass ShapePicker extends Picker {\n shape: Shape\n /**\n * @param {Shape} shape - shape object\n */\n constructor (shape: Shape) {\n super()\n this.shape = shape\n }\n\n get primitive (): any { return }\n\n get data () { return this.shape }\n get type () { return this.primitive.type }\n\n getObject (pid: number) {\n return this.primitive.objectFromShape(this.shape, this.getIndex(pid))\n }\n\n _getPosition (pid: number) {\n return this.primitive.positionFromShape(this.shape, this.getIndex(pid))\n }\n}\n\n//\n\nclass CylinderPicker extends ShapePicker {\n get primitive () { return CylinderPrimitive }\n}\n\nclass ArrowPicker extends ShapePicker {\n get primitive () { return ArrowPrimitive }\n}\n\nclass AtomPicker extends Picker {\n structure: Structure\n constructor (array: Float32Array, structure: Structure) {\n super(array)\n this.structure = structure\n }\n\n get type () { return 'atom' }\n get data () { return this.structure }\n\n getObject (pid: number): AtomProxy {\n return this.structure.getAtomProxy(this.getIndex(pid))\n }\n\n _getPosition (pid: number) {\n return new Vector3().copy(this.getObject(pid) as any)\n }\n}\n\nclass AxesPicker extends Picker {\n axes: PrincipalAxes\n constructor (axes: PrincipalAxes) {\n super()\n this.axes = axes\n }\n\n get type () { return 'axes' }\n get data () { return this.axes }\n\n getObject (/* pid */) {\n return {\n axes: this.axes\n }\n }\n\n _getPosition (/* pid */) {\n return this.axes.center.clone()\n }\n}\n\nclass BondPicker extends Picker {\n structure: Structure\n bondStore: BondStore\n constructor (array: number[]|TypedArray|undefined, structure: Structure, bondStore?: BondStore) {\n super(array)\n this.structure = structure\n this.bondStore = bondStore || structure.bondStore\n }\n\n get type () { return 'bond' }\n get data () { return this.structure }\n\n getObject (pid: number): BondProxy {\n const bp = this.structure.getBondProxy(this.getIndex(pid))\n bp.bondStore = this.bondStore\n return bp\n }\n\n _getPosition (pid: number) {\n const b = this.getObject(pid)\n return new Vector3()\n .copy(b.atom1 as any)\n .add(b.atom2 as any)\n .multiplyScalar(0.5)\n }\n}\n\nclass ContactPicker extends Picker {\n contacts: Contacts\n structure: Structure\n constructor (array: number[]|TypedArray|undefined, contacts: Contacts, structure: Structure) {\n super(array)\n this.contacts = contacts\n this.structure = structure\n }\n\n get type () { return 'contact' }\n get data () { return this.contacts }\n\n getObject (pid: number) {\n const idx = this.getIndex(pid)\n const { features, contactStore } = this.contacts\n const { centers, atomSets } = features\n const { x, y, z } = centers\n const { index1, index2, type } = contactStore\n const k = index1[idx]\n const l = index2[idx]\n return {\n center1: new Vector3(x[k], y[k], z[k]),\n center2: new Vector3(x[l], y[l], z[l]),\n atom1: this.structure.getAtomProxy(atomSets[k][0]),\n atom2: this.structure.getAtomProxy(atomSets[l][0]),\n type: contactTypeName(type[idx])\n }\n }\n\n _getPosition (pid: number) {\n const { center1, center2 } = this.getObject(pid)\n return new Vector3().addVectors(center1, center2).multiplyScalar(0.5)\n }\n}\n\nclass ConePicker extends ShapePicker {\n get primitive () { return ConePrimitive }\n}\n\nclass ClashPicker extends Picker {\n validation: Validation\n structure: Structure\n constructor (array: number[]|TypedArray|undefined, validation: Validation, structure: Structure) {\n super(array)\n this.validation = validation\n this.structure = structure\n }\n\n get type () { return 'clash' }\n get data () { return this.validation }\n\n getObject (pid: number) {\n const val = this.validation\n const idx = this.getIndex(pid)\n return {\n validation: val,\n index: idx,\n clash: val.clashArray[ idx ]\n }\n }\n\n _getAtomProxyFromSele (sele: string) {\n const selection = new Selection(sele)\n const idx = this.structure.getAtomIndices(selection)![ 0 ]\n return this.structure.getAtomProxy(idx)\n }\n\n _getPosition (pid: number) {\n const clash = this.getObject(pid).clash\n const ap1 = this._getAtomProxyFromSele(clash.sele1)\n const ap2 = this._getAtomProxyFromSele(clash.sele2)\n return new Vector3().copy(ap1 as any).add(ap2 as any).multiplyScalar(0.5)\n }\n}\n\nclass DistancePicker extends BondPicker {\n get type () { return 'distance' }\n}\n\nclass EllipsoidPicker extends ShapePicker {\n get primitive () { return EllipsoidPrimitive }\n}\n\nclass OctahedronPicker extends ShapePicker {\n get primitive () { return OctahedronPrimitive }\n}\n\nclass BoxPicker extends ShapePicker {\n get primitive () { return BoxPrimitive }\n}\n\nclass IgnorePicker extends Picker {\n get type () { return 'ignore' }\n}\n\nexport interface MeshData {\n name: string|undefined\n serial: number\n index: Uint32Array|Uint16Array|number[]\n normal?: Float32Array|number[]\n position: Float32Array|number[]\n color: Float32Array|number[]\n}\nclass MeshPicker extends ShapePicker {\n mesh: MeshData\n __position: Vector3\n\n constructor (shape: Shape, mesh: MeshData) {\n super(shape)\n this.mesh = mesh\n }\n\n get type () { return 'mesh' }\n\n getObject (/* pid */) {\n const m = this.mesh\n return {\n shape: this.shape,\n name: m.name,\n serial: m.serial\n }\n }\n\n _getPosition (/* pid */) {\n if (!this.__position) {\n this.__position = calculateMeanVector3(this.mesh.position as any)\n }\n return this.__position\n }\n}\n\nclass SpherePicker extends ShapePicker {\n get primitive () { return SpherePrimitive }\n}\n\nclass SurfacePicker extends Picker {\n surface: Surface\n constructor (array: number[]|TypedArray|undefined, surface: Surface) {\n super(array)\n this.surface = surface\n }\n\n get type () { return 'surface' }\n get data () { return this.surface }\n\n getObject (pid: number) {\n return {\n surface: this.surface,\n index: this.getIndex(pid)\n }\n }\n\n _getPosition (/* pid */) {\n return this.surface.center.clone()\n }\n}\n\nclass TetrahedronPicker extends ShapePicker {\n get primitive () { return TetrahedronPrimitive }\n}\n\nclass TorusPicker extends ShapePicker {\n get primitive () { return TorusPrimitive }\n}\n\nclass UnitcellPicker extends Picker {\n unitcell: Unitcell\n structure: Structure\n\n constructor (unitcell: Unitcell, structure: Structure) {\n super()\n this.unitcell = unitcell\n this.structure = structure\n }\n\n get type () { return 'unitcell' }\n get data () { return this.unitcell }\n\n getObject (/* pid */) {\n return {\n unitcell: this.unitcell,\n structure: this.structure\n }\n }\n\n _getPosition (/* pid */) {\n return this.unitcell.getCenter(this.structure)\n }\n}\n\nclass UnknownPicker extends Picker {\n get type () { return 'unknown' }\n}\n\nclass VolumePicker extends Picker {\n volume: Volume\n constructor (array: TypedArray, volume: Volume) {\n super(array)\n this.volume = volume\n }\n\n get type () { return 'volume' }\n get data () { return this.volume }\n\n getObject (pid: number) {\n const vol = this.volume\n const idx = this.getIndex(pid)\n return {\n volume: vol,\n index: idx,\n value: vol.data[ idx ]\n }\n }\n\n _getPosition (pid: number) {\n const dp = this.volume.position\n const idx = this.getIndex(pid)\n return new Vector3(\n dp[ idx * 3 ],\n dp[ idx * 3 + 1 ],\n dp[ idx * 3 + 2 ]\n )\n }\n}\n\nclass SlicePicker extends VolumePicker {\n get type () { return 'slice' }\n}\n\nclass PointPicker extends ShapePicker {\n get primitive () { return PointPrimitive }\n}\n\nclass WidelinePicker extends ShapePicker {\n get primitive () { return WidelinePrimitive }\n}\n\nPickerRegistry.add('arrow', ArrowPicker)\nPickerRegistry.add('box', BoxPicker)\nPickerRegistry.add('cone', ConePicker)\nPickerRegistry.add('cylinder', CylinderPicker)\nPickerRegistry.add('ellipsoid', EllipsoidPicker)\nPickerRegistry.add('octahedron', OctahedronPicker)\nPickerRegistry.add('sphere', SpherePicker)\nPickerRegistry.add('tetrahedron', TetrahedronPicker)\nPickerRegistry.add('torus', TorusPicker)\nPickerRegistry.add('point', PointPicker)\nPickerRegistry.add('wideline', WidelinePicker)\n\nexport {\n Picker,\n ShapePicker,\n ArrowPicker,\n AtomPicker,\n AxesPicker,\n BondPicker,\n BoxPicker,\n ConePicker,\n ContactPicker,\n CylinderPicker,\n ClashPicker,\n DistancePicker,\n EllipsoidPicker,\n IgnorePicker,\n OctahedronPicker,\n MeshPicker,\n SlicePicker,\n SpherePicker,\n SurfacePicker,\n TetrahedronPicker,\n TorusPicker,\n UnitcellPicker,\n UnknownPicker,\n VolumePicker,\n PointPicker,\n WidelinePicker\n}\n","/**\n * @file Marching Cubes\n * @author Alexander Rose \n * @private\n */\n\nimport { getUintArray } from '../utils'\n\nfunction getEdgeTable () {\n return new Uint32Array([\n 0x0, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,\n 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,\n 0x190, 0x99, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,\n 0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,\n 0x230, 0x339, 0x33, 0x13a, 0x636, 0x73f, 0x435, 0x53c,\n 0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,\n 0x3a0, 0x2a9, 0x1a3, 0xaa, 0x7a6, 0x6af, 0x5a5, 0x4ac,\n 0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,\n 0x460, 0x569, 0x663, 0x76a, 0x66, 0x16f, 0x265, 0x36c,\n 0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,\n 0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff, 0x3f5, 0x2fc,\n 0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,\n 0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55, 0x15c,\n 0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,\n 0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc,\n 0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,\n 0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,\n 0xcc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,\n 0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,\n 0x15c, 0x55, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,\n 0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,\n 0x2fc, 0x3f5, 0xff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,\n 0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,\n 0x36c, 0x265, 0x16f, 0x66, 0x76a, 0x663, 0x569, 0x460,\n 0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,\n 0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa, 0x1a3, 0x2a9, 0x3a0,\n 0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,\n 0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33, 0x339, 0x230,\n 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,\n 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99, 0x190,\n 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,\n 0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0\n ])\n}\n\nfunction getTriTable (): Int32Array {\n return new Int32Array([\n -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1,\n 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1,\n 3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1,\n 3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1,\n 9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1,\n 1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1,\n 9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1,\n 2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1,\n 8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1,\n 9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1,\n 4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1,\n 3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1,\n 1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1,\n 4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1,\n 4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1,\n 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1,\n 1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1,\n 5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1,\n 2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1,\n 9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1,\n 0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1,\n 2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1,\n 10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1,\n 4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1,\n 5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1,\n 5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1,\n 9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1,\n 0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1,\n 1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1,\n 10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1,\n 8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1,\n 2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1,\n 7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1,\n 9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1,\n 2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1,\n 11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1,\n 9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1,\n 5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1,\n 11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1,\n 11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1,\n 1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1,\n 9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1,\n 5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1,\n 2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1,\n 0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1,\n 5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1,\n 6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1,\n 0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1,\n 3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1,\n 6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1,\n 5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1,\n 1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1,\n 10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1,\n 6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1,\n 1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1,\n 8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1,\n 7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1,\n 3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1,\n 5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1,\n 0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1,\n 9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1,\n 8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1,\n 5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1,\n 0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1,\n 6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1,\n 10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1,\n 10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1,\n 8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1,\n 1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1,\n 3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1,\n 0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1,\n 10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1,\n 0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1,\n 3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1,\n 6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1,\n 9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1,\n 8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1,\n 3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1,\n 6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1,\n 0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1,\n 10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1,\n 10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1,\n 1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1,\n 2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1,\n 7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1,\n 7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1,\n 2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1,\n 1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1,\n 11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1,\n 8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1,\n 0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1,\n 7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1,\n 10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1,\n 2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1,\n 6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1,\n 7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1,\n 2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1,\n 1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1,\n 10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1,\n 10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1,\n 0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1,\n 7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1,\n 6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1,\n 8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1,\n 9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1,\n 6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1,\n 1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1,\n 4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1,\n 10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1,\n 8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1,\n 0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1,\n 1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1,\n 8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1,\n 10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1,\n 4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1,\n 10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1,\n 5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1,\n 11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1,\n 9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1,\n 6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1,\n 7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1,\n 3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1,\n 7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1,\n 9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1,\n 3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1,\n 6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1,\n 9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1,\n 1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1,\n 4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1,\n 7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1,\n 6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1,\n 3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1,\n 0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1,\n 6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1,\n 1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1,\n 0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1,\n 11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1,\n 6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1,\n 5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1,\n 9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1,\n 1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1,\n 1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1,\n 10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1,\n 0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1,\n 5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1,\n 10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1,\n 11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1,\n 0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1,\n 9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1,\n 7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1,\n 2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1,\n 8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1,\n 9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1,\n 9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1,\n 1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1,\n 9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1,\n 9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1,\n 5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1,\n 0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1,\n 10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1,\n 2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1,\n 0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1,\n 0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1,\n 9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1,\n 5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1,\n 3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1,\n 5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1,\n 8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1,\n 0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1,\n 9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1,\n 0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1,\n 1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1,\n 3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1,\n 4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1,\n 9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1,\n 11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1,\n 11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1,\n 2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1,\n 9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1,\n 3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1,\n 1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1,\n 4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1,\n 4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1,\n 0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1,\n 3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1,\n 3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1,\n 0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1,\n 9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1,\n 1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n 0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\n -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1\n ])\n}\n\ninterface MarchingCubes {\n new (field: number[], nx: number, ny: number, nz: number, atomindex: number[]): void\n triangulate: (_isolevel: number, _noNormals: boolean, _box: number[][]|undefined, _contour: boolean, _wrap: boolean) => {\n position: Float32Array\n normal: undefined|Float32Array\n index: Uint32Array|Uint16Array\n atomindex: Int32Array|undefined\n contour: boolean\n }\n}\nfunction MarchingCubes (this: MarchingCubes, field: number[], nx: number, ny: number, nz: number, atomindex: number[]) {\n // Based on alteredq / http://alteredqualia.com/\n // port of greggman's ThreeD version of marching cubes to Three.js\n // http://webglsamples.googlecode.com/hg/blob/blob.html\n //\n // Adapted for NGL by Alexander Rose\n\n // Triangles are constructed between points on cube edges.\n // allowedContours[edge1][edge1] indicates which lines from a given\n // triangle should be shown in line mode.\n\n // Values are bitmasks:\n // In loop over cubes we keep another bitmask indicating whether our current\n // cell is the first x-value (1),\n // first y-value (2) or first z-value (4) of the current loop.\n // We draw all lines on leading faces but only draw trailing face lines the first\n // time through the loop\n // A value of 8 below means the edge is always drawn (leading face)\n\n // E.g. the first row, lines between edge0 and other edges in the bottom\n // x-y plane are only drawn for the first value of z, edges in the\n // x-z plane are only drawn for the first value of y. No other lines\n // are drawn as they're redundant\n // The line between edge 1 and 5 is always drawn as it's on the leading edge\n var allowedContours = [\n\n [ 0, 4, 4, 4, 2, 0, 0, 0, 2, 2, 0, 0 ], // 1 2 3 4 8 9\n [ 4, 0, 4, 4, 0, 8, 0, 0, 0, 8, 8, 0 ], // 0 2 3 5 9 10\n [ 4, 4, 0, 4, 0, 0, 8, 0, 0, 0, 8, 8 ], // 0 1 3 6 10 11\n [ 4, 4, 4, 0, 0, 0, 0, 1, 1, 0, 0, 1 ], // 0 1 2 7 8 11\n [ 2, 0, 0, 0, 0, 8, 8, 8, 2, 2, 0, 0 ], // 0 5 6 7 8 9\n [ 0, 8, 0, 0, 8, 0, 8, 8, 0, 8, 8, 0 ], // And rotate it\n [ 0, 0, 8, 0, 8, 8, 0, 8, 0, 0, 8, 8 ],\n [ 0, 0, 0, 1, 8, 8, 8, 0, 1, 0, 0, 1 ],\n [ 2, 0, 0, 1, 2, 0, 0, 1, 0, 2, 0, 1 ], // 0 3 4 7 9 11\n [ 2, 8, 0, 0, 2, 8, 0, 0, 2, 0, 8, 0 ], // And rotate some more\n [ 0, 8, 8, 0, 0, 8, 8, 0, 0, 8, 0, 8 ],\n [ 0, 0, 8, 1, 0, 0, 8, 1, 1, 0, 8, 0 ]\n\n ]\n\n var isolevel = 0\n var noNormals = false\n var contour = false\n var wrap = false\n var isNegativeIso = false\n var normalFactor = -1\n\n\n var n = nx * ny * nz\n\n // deltas\n var yd = nx\n var zd = nx * ny\n\n var normalCache: Float32Array, vertexIndex: Int32Array\n var count: number, icount: number\n\n var ilist = new Int32Array(12)\n\n var positionArray: number[] = []\n var normalArray: number[] = []\n var indexArray: number[] = []\n var atomindexArray: number[] = []\n\n var edgeTable = getEdgeTable()\n var triTable = getTriTable()\n\n var mx: number, my: number, mz: number\n\n //\n\n this.triangulate = function (_isolevel: number, _noNormals: boolean, _box: number[][]|undefined, _contour: boolean, _wrap: boolean) {\n isolevel = _isolevel\n isNegativeIso = isolevel < 0.0\n contour = _contour\n wrap = _wrap\n // Normals currently disabled in contour mode for performance (unused)\n noNormals = _noNormals || contour\n\n if (!noNormals) {\n normalFactor = isolevel > 0 ? -1.0 : 1.0\n if (!normalCache) {\n normalCache = new Float32Array(n * 3)\n } \n }\n\n var vIndexLength = n * 3\n\n if (!vertexIndex || vertexIndex.length !== vIndexLength) {\n vertexIndex = new Int32Array(vIndexLength)\n }\n\n count = 0\n icount = 0\n\n if (_box !== undefined) {\n var min = _box[ 0 ].map(Math.round)\n var max = _box[ 1 ].map(Math.round)\n\n mx = nx * Math.ceil(Math.abs(min[ 0 ]) / nx)\n my = ny * Math.ceil(Math.abs(min[ 1 ]) / ny)\n mz = nz * Math.ceil(Math.abs(min[ 2 ]) / nz)\n\n triangulate(\n min[ 0 ], min[ 1 ], min[ 2 ],\n max[ 0 ], max[ 1 ], max[ 2 ]\n )\n } else {\n mx = my = mz = 0\n\n triangulate()\n }\n\n positionArray.length = count * 3\n if (!noNormals) normalArray.length = count * 3\n indexArray.length = icount\n if (atomindex) atomindexArray.length = count\n\n return {\n position: new Float32Array(positionArray),\n normal: noNormals ? undefined : new Float32Array(normalArray),\n index: getUintArray(indexArray, positionArray.length / 3),\n atomindex: atomindex ? new Int32Array(atomindexArray) : undefined,\n contour: contour\n }\n }\n\n // polygonization\n\n function lerp (a: number, b: number, t: number) { return a + (b - a) * t }\n\n function index (x: number, y: number, z: number) {\n x = (x + mx) % nx\n y = (y + my) % ny\n z = (z + mz) % nz\n return ((zd * z) + yd * y) + x\n }\n\n function VIntX (q: number, offset: number, x: number, y: number, z: number, valp1: number, valp2: number) {\n var _q = 3 * q\n\n if (vertexIndex[ _q ] < 0) {\n var mu = (isolevel - valp1) / (valp2 - valp1)\n var nc = normalCache\n\n var c = count * 3\n\n positionArray[ c ] = x + mu\n positionArray[ c + 1 ] = y\n positionArray[ c + 2 ] = z\n\n if (!noNormals) {\n var q3 = q * 3\n\n normalArray[ c ] = normalFactor * lerp(nc[ q3 ], nc[ q3 + 3 ], mu)\n normalArray[ c + 1 ] = normalFactor * lerp(nc[ q3 + 1 ], nc[ q3 + 4 ], mu)\n normalArray[ c + 2 ] = normalFactor * lerp(nc[ q3 + 2 ], nc[ q3 + 5 ], mu)\n }\n\n if (atomindex) atomindexArray[ count ] = atomindex[ q + Math.round(mu) ]\n\n vertexIndex[ _q ] = count\n ilist[ offset ] = count\n\n count += 1\n } else {\n ilist[ offset ] = vertexIndex[ _q ]\n }\n }\n\n function VIntY (q: number, offset: number, x: number, y: number, z: number, valp1: number, valp2: number) {\n var _q = 3 * q + 1\n\n if (vertexIndex[ _q ] < 0) {\n var mu = (isolevel - valp1) / (valp2 - valp1)\n var nc = normalCache\n\n var c = count * 3\n\n positionArray[ c ] = x\n positionArray[ c + 1 ] = y + mu\n positionArray[ c + 2 ] = z\n\n if (!noNormals) {\n var q3 = q * 3\n var q6 = q3 + yd * 3\n\n normalArray[ c ] = normalFactor * lerp(nc[ q3 ], nc[ q6 ], mu)\n normalArray[ c + 1 ] = normalFactor * lerp(nc[ q3 + 1 ], nc[ q6 + 1 ], mu)\n normalArray[ c + 2 ] = normalFactor * lerp(nc[ q3 + 2 ], nc[ q6 + 2 ], mu)\n }\n\n if (atomindex) atomindexArray[ count ] = atomindex[ q + Math.round(mu) * yd ]\n\n vertexIndex[ _q ] = count\n ilist[ offset ] = count\n\n count += 1\n } else {\n ilist[ offset ] = vertexIndex[ _q ]\n }\n }\n\n function VIntZ (q: number, offset: number, x: number, y: number, z: number, valp1: number, valp2: number) {\n var _q = 3 * q + 2\n\n if (vertexIndex[ _q ] < 0) {\n var mu = (isolevel - valp1) / (valp2 - valp1)\n var nc = normalCache\n\n var c = count * 3\n\n positionArray[ c ] = x\n positionArray[ c + 1 ] = y\n positionArray[ c + 2 ] = z + mu\n\n if (!noNormals) {\n var q3 = q * 3\n var q6 = q3 + zd * 3\n\n normalArray[ c ] = normalFactor * lerp(nc[ q3 ], nc[ q6 ], mu)\n normalArray[ c + 1 ] = normalFactor * lerp(nc[ q3 + 1 ], nc[ q6 + 1 ], mu)\n normalArray[ c + 2 ] = normalFactor * lerp(nc[ q3 + 2 ], nc[ q6 + 2 ], mu)\n }\n\n if (atomindex) atomindexArray[ count ] = atomindex[ q + Math.round(mu) * zd ]\n\n vertexIndex[ _q ] = count\n ilist[ offset ] = count\n\n count += 1\n } else {\n ilist[ offset ] = vertexIndex[ _q ]\n }\n }\n\n function compNorm (q: number) {\n var q3 = q * 3\n\n if (normalCache[ q3 ] === 0.0) {\n normalCache[ q3 ] = field[ (q - 1 + n) % n ] - field[ (q + 1) % n ]\n normalCache[ q3 + 1 ] = field[ (q - yd + n) % n ] - field[ (q + yd) % n ]\n normalCache[ q3 + 2 ] = field[ (q - zd + n) % n ] - field[ (q + zd) % n ]\n }\n }\n\n function polygonize (fx: number, fy: number, fz: number, q: number, edgeFilter: number) {\n // cache indices\n var q1\n var qy\n var qz\n var q1y\n var q1z\n var qyz\n var q1yz\n if (wrap) {\n q = index(fx, fy, fz)\n q1 = index(fx + 1, fy, fz)\n qy = index(fx, fy + 1, fz)\n qz = index(fx, fy, fz + 1)\n q1y = index(fx + 1, fy + 1, fz)\n q1z = index(fx + 1, fy, fz + 1)\n qyz = index(fx, fy + 1, fz + 1)\n q1yz = index(fx + 1, fy + 1, fz + 1)\n } else {\n q1 = q + 1\n qy = q + yd\n qz = q + zd\n q1y = qy + 1\n q1z = qz + 1\n qyz = qy + zd\n q1yz = qyz + 1\n }\n\n var cubeindex = 0\n var field0 = field[ q ]\n var field1 = field[ q1 ]\n var field2 = field[ qy ]\n var field3 = field[ q1y ]\n var field4 = field[ qz ]\n var field5 = field[ q1z ]\n var field6 = field[ qyz ]\n var field7 = field[ q1yz ]\n\n if (field0 < isolevel) cubeindex |= 1\n if (field1 < isolevel) cubeindex |= 2\n if (field2 < isolevel) cubeindex |= 8\n if (field3 < isolevel) cubeindex |= 4\n if (field4 < isolevel) cubeindex |= 16\n if (field5 < isolevel) cubeindex |= 32\n if (field6 < isolevel) cubeindex |= 128\n if (field7 < isolevel) cubeindex |= 64\n\n // if cube is entirely in/out of the surface - bail, nothing to draw\n\n var bits = edgeTable[ cubeindex ]\n if (bits === 0) return 0\n\n var fx2 = fx + 1\n var fy2 = fy + 1\n var fz2 = fz + 1\n\n // top of the cube\n\n if (bits & 1) {\n if (!noNormals) {\n compNorm(q)\n compNorm(q1)\n }\n VIntX(q, 0, fx, fy, fz, field0, field1)\n }\n\n if (bits & 2) {\n if (!noNormals) {\n compNorm(q1)\n compNorm(q1y)\n }\n VIntY(q1, 1, fx2, fy, fz, field1, field3)\n }\n\n if (bits & 4) {\n if (!noNormals) {\n compNorm(qy)\n compNorm(q1y)\n }\n VIntX(qy, 2, fx, fy2, fz, field2, field3)\n }\n\n if (bits & 8) {\n if (!noNormals) {\n compNorm(q)\n compNorm(qy)\n }\n VIntY(q, 3, fx, fy, fz, field0, field2)\n }\n\n // bottom of the cube\n\n if (bits & 16) {\n if (!noNormals) {\n compNorm(qz)\n compNorm(q1z)\n }\n VIntX(qz, 4, fx, fy, fz2, field4, field5)\n }\n\n if (bits & 32) {\n if (!noNormals) {\n compNorm(q1z)\n compNorm(q1yz)\n }\n VIntY(q1z, 5, fx2, fy, fz2, field5, field7)\n }\n\n if (bits & 64) {\n if (!noNormals) {\n compNorm(qyz)\n compNorm(q1yz)\n }\n VIntX(qyz, 6, fx, fy2, fz2, field6, field7)\n }\n\n if (bits & 128) {\n if (!noNormals) {\n compNorm(qz)\n compNorm(qyz)\n }\n VIntY(qz, 7, fx, fy, fz2, field4, field6)\n }\n\n // vertical lines of the cube\n\n if (bits & 256) {\n if (!noNormals) {\n compNorm(q)\n compNorm(qz)\n }\n VIntZ(q, 8, fx, fy, fz, field0, field4)\n }\n\n if (bits & 512) {\n if (!noNormals) {\n compNorm(q1)\n compNorm(q1z)\n }\n VIntZ(q1, 9, fx2, fy, fz, field1, field5)\n }\n\n if (bits & 1024) {\n if (!noNormals) {\n compNorm(q1y)\n compNorm(q1yz)\n }\n VIntZ(q1y, 10, fx2, fy2, fz, field3, field7)\n }\n\n if (bits & 2048) {\n if (!noNormals) {\n compNorm(qy)\n compNorm(qyz)\n }\n VIntZ(qy, 11, fx, fy2, fz, field2, field6)\n }\n\n var triIndex = cubeindex << 4 // re-purpose cubeindex into an offset into triTable\n\n var e1\n var e2\n var e3\n var i = 0\n\n // here is where triangles are created\n\n while (triTable[ triIndex + i ] !== -1) {\n e1 = triTable[ triIndex + i ]\n e2 = triTable[ triIndex + i + 1 ]\n e3 = triTable[ triIndex + i + 2 ]\n\n if (contour) {\n if (allowedContours[ e1 ][ e2 ] & edgeFilter) {\n indexArray[ icount++ ] = ilist[ e1 ]\n indexArray[ icount++ ] = ilist[ e2 ]\n }\n if (allowedContours[ e2 ][ e3 ] & edgeFilter) {\n indexArray[ icount++ ] = ilist[ e2 ]\n indexArray[ icount++ ] = ilist[ e3 ]\n }\n if (allowedContours[ e1 ][ e3 ] & edgeFilter) {\n indexArray[ icount++ ] = ilist[ e1 ]\n indexArray[ icount++ ] = ilist[ e3 ]\n }\n } else {\n indexArray[ icount++ ] = ilist[ isNegativeIso ? e1 : e2 ]\n indexArray[ icount++ ] = ilist[ isNegativeIso ? e2 : e1 ]\n indexArray[ icount++ ] = ilist[ e3 ]\n }\n\n i += 3\n }\n }\n\n function triangulate (xBeg?: number, yBeg?: number, zBeg?: number, xEnd?: number, yEnd?: number, zEnd?: number) {\n let q\n let q3\n let x\n let y\n let z\n let yOffset\n let zOffset\n\n xBeg = xBeg !== undefined ? xBeg : 0\n yBeg = yBeg !== undefined ? yBeg : 0\n zBeg = zBeg !== undefined ? zBeg : 0\n\n xEnd = xEnd !== undefined ? xEnd : nx - 1\n yEnd = yEnd !== undefined ? yEnd : ny - 1\n zEnd = zEnd !== undefined ? zEnd : nz - 1\n\n if (!wrap) {\n if (noNormals) {\n xBeg = Math.max(0, xBeg)\n yBeg = Math.max(0, yBeg)\n zBeg = Math.max(0, zBeg)\n\n xEnd = Math.min(nx - 1, xEnd)\n yEnd = Math.min(ny - 1, yEnd)\n zEnd = Math.min(nz - 1, zEnd)\n } else {\n xBeg = Math.max(1, xBeg)\n yBeg = Math.max(1, yBeg)\n zBeg = Math.max(1, zBeg)\n\n xEnd = Math.min(nx - 2, xEnd)\n yEnd = Math.min(ny - 2, yEnd)\n zEnd = Math.min(nz - 2, zEnd)\n }\n }\n\n let xBeg2, yBeg2, zBeg2, xEnd2, yEnd2, zEnd2\n\n if (!wrap) {\n // init part of the vertexIndex\n // (takes a significant amount of time to do for all)\n\n xBeg2 = Math.max(0, xBeg - 2)\n yBeg2 = Math.max(0, yBeg - 2)\n zBeg2 = Math.max(0, zBeg - 2)\n\n xEnd2 = Math.min(nx, xEnd + 2)\n yEnd2 = Math.min(ny, yEnd + 2)\n zEnd2 = Math.min(nz, zEnd + 2)\n\n for (z = zBeg2; z < zEnd2; ++z) {\n zOffset = zd * z\n for (y = yBeg2; y < yEnd2; ++y) {\n yOffset = zOffset + yd * y\n for (x = xBeg2; x < xEnd2; ++x) {\n q = 3 * (yOffset + x)\n vertexIndex[ q ] = -1\n vertexIndex[ q + 1 ] = -1\n vertexIndex[ q + 2 ] = -1\n }\n }\n }\n } else {\n xBeg2 = xBeg - 2\n yBeg2 = yBeg - 2\n zBeg2 = zBeg - 2\n\n xEnd2 = xEnd + 2\n yEnd2 = yEnd + 2\n zEnd2 = zEnd + 2\n\n for (z = zBeg2; z < zEnd2; ++z) {\n for (y = yBeg2; y < yEnd2; ++y) {\n for (x = xBeg2; x < xEnd2; ++x) {\n q3 = index(x, y, z) * 3\n vertexIndex[ q3 ] = -1\n vertexIndex[ q3 + 1 ] = -1\n vertexIndex[ q3 + 2 ] = -1\n }\n }\n }\n }\n\n if (!wrap) {\n // clip space where the isovalue is too low\n\n var __break\n var __xBeg = xBeg; var __yBeg = yBeg; var __zBeg = zBeg\n var __xEnd = xEnd; var __yEnd = yEnd; var __zEnd = zEnd\n\n __break = false\n for (z = zBeg; z < zEnd; ++z) {\n for (y = yBeg; y < yEnd; ++y) {\n for (x = xBeg; x < xEnd; ++x) {\n q = ((nx * ny) * z) + (nx * y) + x\n if (field[ q ] >= isolevel) {\n __zBeg = z\n __break = true\n break\n }\n }\n if (__break) break\n }\n if (__break) break\n }\n\n __break = false\n for (y = yBeg; y < yEnd; ++y) {\n for (z = __zBeg; z < zEnd; ++z) {\n for (x = xBeg; x < xEnd; ++x) {\n q = ((nx * ny) * z) + (nx * y) + x\n if (field[ q ] >= isolevel) {\n __yBeg = y\n __break = true\n break\n }\n }\n if (__break) break\n }\n if (__break) break\n }\n\n __break = false\n for (x = xBeg; x < xEnd; ++x) {\n for (y = __yBeg; y < yEnd; ++y) {\n for (z = __zBeg; z < zEnd; ++z) {\n q = ((nx * ny) * z) + (nx * y) + x\n if (field[ q ] >= isolevel) {\n __xBeg = x\n __break = true\n break\n }\n }\n if (__break) break\n }\n if (__break) break\n }\n\n __break = false\n for (z = zEnd; z >= zBeg; --z) {\n for (y = yEnd; y >= yBeg; --y) {\n for (x = xEnd; x >= xBeg; --x) {\n q = ((nx * ny) * z) + (nx * y) + x\n if (field[ q ] >= isolevel) {\n __zEnd = z\n __break = true\n break\n }\n }\n if (__break) break\n }\n if (__break) break\n }\n\n __break = false\n for (y = yEnd; y >= yBeg; --y) {\n for (z = __zEnd; z >= zBeg; --z) {\n for (x = xEnd; x >= xBeg; --x) {\n q = ((nx * ny) * z) + (nx * y) + x\n if (field[ q ] >= isolevel) {\n __yEnd = y\n __break = true\n break\n }\n }\n if (__break) break\n }\n if (__break) break\n }\n\n __break = false\n for (x = xEnd; x >= xBeg; --x) {\n for (y = __yEnd; y >= yBeg; --y) {\n for (z = __zEnd; z >= zBeg; --z) {\n q = ((nx * ny) * z) + (nx * y) + x\n if (field[ q ] >= isolevel) {\n __xEnd = x\n __break = true\n break\n }\n }\n if (__break) break\n }\n if (__break) break\n }\n\n //\n\n if (noNormals) {\n xBeg = Math.max(0, __xBeg - 1)\n yBeg = Math.max(0, __yBeg - 1)\n zBeg = Math.max(0, __zBeg - 1)\n\n xEnd = Math.min(nx - 1, __xEnd + 1)\n yEnd = Math.min(ny - 1, __yEnd + 1)\n zEnd = Math.min(nz - 1, __zEnd + 1)\n } else {\n xBeg = Math.max(1, __xBeg - 1)\n yBeg = Math.max(1, __yBeg - 1)\n zBeg = Math.max(1, __zBeg - 1)\n\n xEnd = Math.min(nx - 2, __xEnd + 1)\n yEnd = Math.min(ny - 2, __yEnd + 1)\n zEnd = Math.min(nz - 2, __zEnd + 1)\n }\n }\n\n // polygonize part of the grid\n var edgeFilter = 15\n for (z = zBeg; z < zEnd; ++z, edgeFilter &= ~4) {\n zOffset = zd * z\n edgeFilter |= 2\n for (y = yBeg; y < yEnd; ++y, edgeFilter &= ~2) {\n yOffset = zOffset + yd * y\n edgeFilter |= 1\n for (x = xBeg; x < xEnd; ++x, edgeFilter &= ~1) {\n q = yOffset + x\n polygonize(x, y, z, q, edgeFilter)\n }\n }\n }\n }\n}\nObject.assign(MarchingCubes, {__deps: [ getEdgeTable, getTriTable, getUintArray ]})\n\nexport default MarchingCubes\n","/**\n * @file Matrix Utils\n * @private\n * @author Alexander Rose \n *\n * svd methods from Eugene Zatepyakin / http://inspirit.github.io/jsfeat/\n */\n\nimport { NumberArray } from '../types'\nimport { v3new, v3cross } from './vector-utils'\n\nexport class Matrix {\n size: number\n data: Float32Array\n\n constructor (readonly cols: number, readonly rows: number) {\n this.size = this.cols * this.rows\n this.data = new Float32Array(this.size)\n }\n\n copyTo (matrix: Matrix) {\n matrix.data.set(this.data)\n }\n}\n\nexport function transpose (At: Matrix, A: Matrix) {\n let i = 0\n let j = 0\n const nrows = A.rows\n const ncols = A.cols\n let Ai = 0\n let Ati = 0\n let pAt = 0\n const ad = A.data\n const atd = At.data\n\n for (; i < nrows; Ati += 1, Ai += ncols, i++) {\n pAt = Ati\n for (j = 0; j < ncols; pAt += nrows, j++) atd[pAt] = ad[Ai + j]\n }\n}\n\n// C = A * B\nexport function multiply (C: Matrix, A: Matrix, B: Matrix) {\n let i = 0\n let j = 0\n let k = 0\n let Ap = 0\n let pA = 0\n let pB = 0\n let _pB = 0\n let Cp = 0\n const ncols = A.cols\n const nrows = A.rows\n const mcols = B.cols\n const ad = A.data\n const bd = B.data\n const cd = C.data\n let sum = 0.0\n\n for (; i < nrows; Ap += ncols, i++) {\n for (_pB = 0, j = 0; j < mcols; Cp++, _pB++, j++) {\n pB = _pB\n pA = Ap\n sum = 0.0\n for (k = 0; k < ncols; pA++, pB += mcols, k++) {\n sum += ad[pA] * bd[pB]\n }\n cd[Cp] = sum\n }\n }\n}\n\n// C = A * B'\nexport function multiplyABt (C: Matrix, A: Matrix, B: Matrix) {\n let i = 0\n let j = 0\n let k = 0\n let Ap = 0\n let pA = 0\n let pB = 0\n let Cp = 0\n const ncols = A.cols\n const nrows = A.rows\n const mrows = B.rows\n const ad = A.data\n const bd = B.data\n const cd = C.data\n let sum = 0.0\n\n for (; i < nrows; Ap += ncols, i++) {\n for (pB = 0, j = 0; j < mrows; Cp++, j++) {\n pA = Ap\n sum = 0.0\n for (k = 0; k < ncols; pA++, pB++, k++) {\n sum += ad[pA] * bd[pB]\n }\n cd[Cp] = sum\n }\n }\n}\n\n// C = A' * B\nexport function multiplyAtB (C: Matrix, A: Matrix, B: Matrix) {\n let i = 0\n let j = 0\n let k = 0\n let Ap = 0\n let pA = 0\n let pB = 0\n let _pB = 0\n let Cp = 0\n const ncols = A.cols\n const nrows = A.rows\n const mcols = B.cols\n const ad = A.data\n const bd = B.data\n const cd = C.data\n let sum = 0.0\n\n for (; i < ncols; Ap++, i++) {\n for (_pB = 0, j = 0; j < mcols; Cp++, _pB++, j++) {\n pB = _pB\n pA = Ap\n sum = 0.0\n for (k = 0; k < nrows; pA += ncols, pB += mcols, k++) {\n sum += ad[pA] * bd[pB]\n }\n cd[Cp] = sum\n }\n }\n}\n\nexport function invert3x3 (from: Matrix, to: Matrix) {\n const A = from.data\n const invA = to.data\n const t1 = A[4]\n const t2 = A[8]\n const t4 = A[5]\n const t5 = A[7]\n const t8 = A[0]\n\n const t9 = t8 * t1\n const t11 = t8 * t4\n const t13 = A[3]\n const t14 = A[1]\n const t15 = t13 * t14\n const t17 = A[2]\n const t18 = t13 * t17\n const t20 = A[6]\n const t21 = t20 * t14\n const t23 = t20 * t17\n const t26 = 1.0 / (t9 * t2 - t11 * t5 - t15 * t2 + t18 * t5 + t21 * t4 - t23 * t1)\n invA[0] = (t1 * t2 - t4 * t5) * t26\n invA[1] = -(t14 * t2 - t17 * t5) * t26\n invA[2] = -(-t14 * t4 + t17 * t1) * t26\n invA[3] = -(t13 * t2 - t4 * t20) * t26\n invA[4] = (t8 * t2 - t23) * t26\n invA[5] = -(t11 - t18) * t26\n invA[6] = -(-t13 * t5 + t1 * t20) * t26\n invA[7] = -(t8 * t5 - t21) * t26\n invA[8] = (t9 - t15) * t26\n}\n\nexport function mat3x3determinant (M: Matrix) {\n const md = M.data\n return md[0] * md[4] * md[8] -\n md[0] * md[5] * md[7] -\n md[3] * md[1] * md[8] +\n md[3] * md[2] * md[7] +\n md[6] * md[1] * md[5] -\n md[6] * md[2] * md[4]\n}\n\n// C = A * B\nexport function multiply3x3 (C: Matrix, A: Matrix, B: Matrix) {\n const Cd = C.data\n const Ad = A.data\n const Bd = B.data\n const m10 = Ad[0]\n const m11 = Ad[1]\n const m12 = Ad[2]\n const m13 = Ad[3]\n const m14 = Ad[4]\n const m15 = Ad[5]\n const m16 = Ad[6]\n const m17 = Ad[7]\n const m18 = Ad[8]\n\n const m20 = Bd[0]\n const m21 = Bd[1]\n const m22 = Bd[2]\n const m23 = Bd[3]\n const m24 = Bd[4]\n const m25 = Bd[5]\n const m26 = Bd[6]\n const m27 = Bd[7]\n const m28 = Bd[8]\n\n Cd[0] = m10 * m20 + m11 * m23 + m12 * m26\n Cd[1] = m10 * m21 + m11 * m24 + m12 * m27\n Cd[2] = m10 * m22 + m11 * m25 + m12 * m28\n Cd[3] = m13 * m20 + m14 * m23 + m15 * m26\n Cd[4] = m13 * m21 + m14 * m24 + m15 * m27\n Cd[5] = m13 * m22 + m14 * m25 + m15 * m28\n Cd[6] = m16 * m20 + m17 * m23 + m18 * m26\n Cd[7] = m16 * m21 + m17 * m24 + m18 * m27\n Cd[8] = m16 * m22 + m17 * m25 + m18 * m28\n}\n\nexport function meanRows (A: Matrix) {\n const nrows = A.rows\n const ncols = A.cols\n const Ad = A.data\n const mean = new Array(ncols)\n\n for (let j = 0; j < ncols; ++j) {\n mean[ j ] = 0.0\n }\n\n for (let i = 0, p = 0; i < nrows; ++i) {\n for (let j = 0; j < ncols; ++j, ++p) {\n mean[ j ] += Ad[ p ]\n }\n }\n\n for (let j = 0; j < ncols; ++j) {\n mean[ j ] /= nrows\n }\n\n return mean\n}\n\nexport function meanCols (A: Matrix) {\n const nrows = A.rows\n const ncols = A.cols\n const Ad = A.data\n const mean = new Array(nrows)\n\n for (let j = 0; j < nrows; ++j) {\n mean[ j ] = 0.0\n }\n\n for (let i = 0, p = 0; i < ncols; ++i) {\n for (let j = 0; j < nrows; ++j, ++p) {\n mean[ j ] += Ad[ p ]\n }\n }\n\n for (let j = 0; j < nrows; ++j) {\n mean[ j ] /= ncols\n }\n\n return mean\n}\n\nexport function subRows (A: Matrix, row: number[]) {\n const nrows = A.rows\n const ncols = A.cols\n const Ad = A.data\n\n for (let i = 0, p = 0; i < nrows; ++i) {\n for (let j = 0; j < ncols; ++j, ++p) {\n Ad[ p ] -= row[ j ]\n }\n }\n}\n\nexport function subCols (A: Matrix, col: number[]) {\n const nrows = A.rows\n const ncols = A.cols\n const Ad = A.data\n\n for (let i = 0, p = 0; i < ncols; ++i) {\n for (let j = 0; j < nrows; ++j, ++p) {\n Ad[ p ] -= col[ j ]\n }\n }\n}\n\nexport function addRows (A: Matrix, row: number[]) {\n const nrows = A.rows\n const ncols = A.cols\n const Ad = A.data\n\n for (let i = 0, p = 0; i < nrows; ++i) {\n for (let j = 0; j < ncols; ++j, ++p) {\n Ad[ p ] += row[ j ]\n }\n }\n}\n\nexport function addCols (A: Matrix, col: number[]) {\n const nrows = A.rows\n const ncols = A.cols\n const Ad = A.data\n\n for (let i = 0, p = 0; i < ncols; ++i) {\n for (let j = 0; j < nrows; ++j, ++p) {\n Ad[ p ] += col[ j ]\n }\n }\n}\n\nexport function swap (A: NumberArray, i0: number, i1: number, t: number) {\n t = A[i0]\n A[i0] = A[i1]\n A[i1] = t\n}\n\nexport function hypot (a: number, b: number) {\n a = Math.abs(a)\n b = Math.abs(b)\n if (a > b) {\n b /= a\n return a * Math.sqrt(1.0 + b * b)\n }\n if (b > 0) {\n a /= b\n return b * Math.sqrt(1.0 + a * a)\n }\n return 0.0\n}\n\nconst EPSILON = 0.0000001192092896\nconst FLT_MIN = 1E-37\n\nexport function JacobiSVDImpl (At: NumberArray, astep: number, _W: NumberArray, Vt: NumberArray, vstep: number, m: number, n: number, n1: number) {\n const eps = EPSILON * 2.0\n const minval = FLT_MIN\n let i = 0\n let j = 0\n let k = 0\n let iter = 0\n const maxIter = Math.max(m, 30)\n let Ai = 0\n let Aj = 0\n let Vi = 0\n let Vj = 0\n let changed = 0\n let c = 0.0\n let s = 0.0\n let t = 0.0\n let t0 = 0.0\n let t1 = 0.0\n let sd = 0.0\n let beta = 0.0\n let gamma = 0.0\n let delta = 0.0\n let a = 0.0\n let p = 0.0\n let b = 0.0\n let seed = 0x1234\n let val = 0.0\n let val0 = 0.0\n let asum = 0.0\n\n const W = new Float64Array(n << 3)\n\n for (; i < n; i++) {\n for (k = 0, sd = 0; k < m; k++) {\n t = At[i * astep + k]\n sd += t * t\n }\n W[i] = sd\n\n if (Vt) {\n for (k = 0; k < n; k++) {\n Vt[i * vstep + k] = 0\n }\n Vt[i * vstep + i] = 1\n }\n }\n\n for (; iter < maxIter; iter++) {\n changed = 0\n\n for (i = 0; i < n - 1; i++) {\n for (j = i + 1; j < n; j++) {\n Ai = (i * astep) | 0\n Aj = (j * astep) | 0\n a = W[i]\n p = 0\n b = W[j]\n\n k = 2\n p += At[Ai] * At[Aj]\n p += At[Ai + 1] * At[Aj + 1]\n\n for (; k < m; k++) { p += At[Ai + k] * At[Aj + k] }\n\n if (Math.abs(p) <= eps * Math.sqrt(a * b)) continue\n\n p *= 2.0\n beta = a - b\n gamma = hypot(p, beta)\n if (beta < 0) {\n delta = (gamma - beta) * 0.5\n s = Math.sqrt(delta / gamma)\n c = (p / (gamma * s * 2.0))\n } else {\n c = Math.sqrt((gamma + beta) / (gamma * 2.0))\n s = (p / (gamma * c * 2.0))\n }\n\n a = 0.0\n b = 0.0\n\n k = 2 // unroll\n t0 = c * At[Ai] + s * At[Aj]\n t1 = -s * At[Ai] + c * At[Aj]\n At[Ai] = t0; At[Aj] = t1\n a += t0 * t0; b += t1 * t1\n\n t0 = c * At[Ai + 1] + s * At[Aj + 1]\n t1 = -s * At[Ai + 1] + c * At[Aj + 1]\n At[Ai + 1] = t0; At[Aj + 1] = t1\n a += t0 * t0; b += t1 * t1\n\n for (; k < m; k++) {\n t0 = c * At[Ai + k] + s * At[Aj + k]\n t1 = -s * At[Ai + k] + c * At[Aj + k]\n At[Ai + k] = t0; At[Aj + k] = t1\n\n a += t0 * t0; b += t1 * t1\n }\n\n W[i] = a\n W[j] = b\n\n changed = 1\n\n if (Vt) {\n Vi = (i * vstep) | 0\n Vj = (j * vstep) | 0\n\n k = 2\n t0 = c * Vt[Vi] + s * Vt[Vj]\n t1 = -s * Vt[Vi] + c * Vt[Vj]\n Vt[Vi] = t0; Vt[Vj] = t1\n\n t0 = c * Vt[Vi + 1] + s * Vt[Vj + 1]\n t1 = -s * Vt[Vi + 1] + c * Vt[Vj + 1]\n Vt[Vi + 1] = t0; Vt[Vj + 1] = t1\n\n for (; k < n; k++) {\n t0 = c * Vt[Vi + k] + s * Vt[Vj + k]\n t1 = -s * Vt[Vi + k] + c * Vt[Vj + k]\n Vt[Vi + k] = t0; Vt[Vj + k] = t1\n }\n }\n }\n }\n if (changed === 0) break\n }\n\n for (i = 0; i < n; i++) {\n for (k = 0, sd = 0; k < m; k++) {\n t = At[i * astep + k]\n sd += t * t\n }\n W[i] = Math.sqrt(sd)\n }\n\n for (i = 0; i < n - 1; i++) {\n j = i\n for (k = i + 1; k < n; k++) {\n if (W[j] < W[k]) { j = k }\n }\n if (i !== j) {\n swap(W, i, j, sd)\n if (Vt) {\n for (k = 0; k < m; k++) {\n swap(At, i * astep + k, j * astep + k, t)\n }\n\n for (k = 0; k < n; k++) {\n swap(Vt, i * vstep + k, j * vstep + k, t)\n }\n }\n }\n }\n\n for (i = 0; i < n; i++) {\n _W[i] = W[i]\n }\n\n if (!Vt) {\n return\n }\n\n for (i = 0; i < n1; i++) {\n sd = i < n ? W[i] : 0\n\n while (sd <= minval) {\n // if we got a zero singular value, then in order to get the corresponding left singular vector\n // we generate a random vector, project it to the previously computed left singular vectors,\n // subtract the projection and normalize the difference.\n val0 = (1.0 / m)\n for (k = 0; k < m; k++) {\n seed = (seed * 214013 + 2531011)\n val = (((seed >> 16) & 0x7fff) & 256) !== 0 ? val0 : -val0\n At[i * astep + k] = val\n }\n for (iter = 0; iter < 2; iter++) {\n for (j = 0; j < i; j++) {\n sd = 0\n for (k = 0; k < m; k++) {\n sd += At[i * astep + k] * At[j * astep + k]\n }\n asum = 0.0\n for (k = 0; k < m; k++) {\n t = (At[i * astep + k] - sd * At[j * astep + k])\n At[i * astep + k] = t\n asum += Math.abs(t)\n }\n asum = asum ? 1.0 / asum : 0\n for (k = 0; k < m; k++) {\n At[i * astep + k] *= asum\n }\n }\n }\n sd = 0\n for (k = 0; k < m; k++) {\n t = At[i * astep + k]\n sd += t * t\n }\n sd = Math.sqrt(sd)\n }\n\n s = (1.0 / sd)\n for (k = 0; k < m; k++) {\n At[i * astep + k] *= s\n }\n }\n}\n\nexport function svd (A: Matrix, W: Matrix, U: Matrix, V: Matrix) {\n let at = 0\n let i = 0\n const _m = A.rows\n const _n = A.cols\n let m = _m\n let n = _n\n\n if (m < n) {\n at = 1\n i = m\n m = n\n n = i\n }\n\n const amt = new Matrix(m, m)\n const wmt = new Matrix(1, n)\n const vmt = new Matrix(n, n)\n\n if (at === 0) {\n transpose(amt, A)\n } else {\n for (i = 0; i < _n * _m; i++) {\n amt.data[i] = A.data[i]\n }\n for (; i < n * m; i++) {\n amt.data[i] = 0\n }\n }\n\n JacobiSVDImpl(amt.data, m, wmt.data, vmt.data, n, m, n, m)\n\n if (W) {\n for (i = 0; i < n; i++) {\n W.data[i] = wmt.data[i]\n }\n for (; i < _n; i++) {\n W.data[i] = 0\n }\n }\n\n if (at === 0) {\n if (U) transpose(U, amt)\n if (V) transpose(V, vmt)\n } else {\n if (U) transpose(U, vmt)\n if (V) transpose(V, amt)\n }\n}\n\n//\n\nexport function m4new () {\n return new Float32Array([\n 1, 0, 0, 0,\n 0, 1, 0, 0,\n 0, 0, 1, 0,\n 0, 0, 0, 1\n ])\n}\n\nexport function m4set (out: Float32Array, n11: number, n12: number, n13: number, n14: number, n21: number, n22: number, n23: number, n24: number, n31: number, n32: number, n33: number, n34: number, n41: number, n42: number, n43: number, n44: number) {\n out[ 0 ] = n11; out[ 4 ] = n12; out[ 8 ] = n13; out[ 12 ] = n14\n out[ 1 ] = n21; out[ 5 ] = n22; out[ 9 ] = n23; out[ 13 ] = n24\n out[ 2 ] = n31; out[ 6 ] = n32; out[ 10 ] = n33; out[ 14 ] = n34\n out[ 3 ] = n41; out[ 7 ] = n42; out[ 11 ] = n43; out[ 15 ] = n44\n}\n\nexport function m4identity (out: Float32Array) {\n m4set(out,\n 1, 0, 0, 0,\n 0, 1, 0, 0,\n 0, 0, 1, 0,\n 0, 0, 0, 1\n )\n}\n(m4identity as any).__deps = [ m4set ]\n\nexport function m4multiply (out: Float32Array, a: Float32Array, b: Float32Array) {\n const a11 = a[ 0 ]\n const a12 = a[ 4 ]\n const a13 = a[ 8 ]\n const a14 = a[ 12 ]\n const a21 = a[ 1 ]\n const a22 = a[ 5 ]\n const a23 = a[ 9 ]\n const a24 = a[ 13 ]\n const a31 = a[ 2 ]\n const a32 = a[ 6 ]\n const a33 = a[ 10 ]\n const a34 = a[ 14 ]\n const a41 = a[ 3 ]\n const a42 = a[ 7 ]\n const a43 = a[ 11 ]\n const a44 = a[ 15 ]\n\n const b11 = b[ 0 ]\n const b12 = b[ 4 ]\n const b13 = b[ 8 ]\n const b14 = b[ 12 ]\n const b21 = b[ 1 ]\n const b22 = b[ 5 ]\n const b23 = b[ 9 ]\n const b24 = b[ 13 ]\n const b31 = b[ 2 ]\n const b32 = b[ 6 ]\n const b33 = b[ 10 ]\n const b34 = b[ 14 ]\n const b41 = b[ 3 ]\n const b42 = b[ 7 ]\n const b43 = b[ 11 ]\n const b44 = b[ 15 ]\n\n out[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41\n out[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42\n out[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43\n out[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44\n\n out[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41\n out[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42\n out[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43\n out[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44\n\n out[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41\n out[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42\n out[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43\n out[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44\n\n out[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41\n out[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42\n out[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43\n out[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44\n}\n\nexport function m4makeScale (out: Float32Array, x: number, y: number, z: number) {\n m4set(out,\n x, 0, 0, 0,\n 0, y, 0, 0,\n 0, 0, z, 0,\n 0, 0, 0, 1\n )\n}\n(m4makeScale as any).__deps = [ m4set ]\n\nexport function m4makeTranslation (out: Float32Array, x: number, y: number, z: number) {\n m4set(out,\n 1, 0, 0, x,\n 0, 1, 0, y,\n 0, 0, 1, z,\n 0, 0, 0, 1\n )\n}\n(m4makeTranslation as any).__deps = [ m4set ]\n\nexport function m4makeRotationY (out: Float32Array, theta: number) {\n const c = Math.cos(theta)\n const s = Math.sin(theta)\n m4set(out,\n c, 0, s, 0,\n 0, 1, 0, 0,\n -s, 0, c, 0,\n 0, 0, 0, 1\n )\n}\n(m4makeRotationY as any).__deps = [ m4set ]\n\n//\n\nexport function m3new () {\n return new Float32Array([\n 1, 0, 0,\n 0, 1, 0,\n 0, 0, 1\n ])\n}\n\nexport function m3makeNormal (out: Float32Array, m4: Float32Array) {\n const r0 = v3new([ m4[0], m4[1], m4[2] ])\n const r1 = v3new([ m4[4], m4[5], m4[6] ])\n const r2 = v3new([ m4[8], m4[9], m4[10] ])\n const cp = v3new()\n // [ r0 ] [ r1 x r2 ]\n // M3x3 = [ r1 ] N = [ r2 x r0 ]\n // [ r2 ] [ r0 x r1 ]\n v3cross(cp, r1, r2)\n out[ 0 ] = cp[ 0 ]\n out[ 1 ] = cp[ 1 ]\n out[ 2 ] = cp[ 2 ]\n v3cross(cp, r2, r0)\n out[ 3 ] = cp[ 0 ]\n out[ 4 ] = cp[ 1 ]\n out[ 5 ] = cp[ 2 ]\n v3cross(cp, r0, r1)\n out[ 6 ] = cp[ 0 ]\n out[ 7 ] = cp[ 1 ]\n out[ 8 ] = cp[ 2 ]\n}\n(m3makeNormal as any).__deps = [ v3new, v3cross ]\n","/**\n * @file Surface Utils\n * @author Alexander Rose \n * @private\n */\n\nimport { degToRad } from '../math/math-utils'\nimport {\n m4new, m4multiply, m4makeTranslation, m4makeScale, m4makeRotationY\n} from '../math/matrix-utils'\nimport {\n v3addScalar, v3subScalar, v3divideScalar, v3multiplyScalar,\n v3floor, v3ceil, v3sub, v3negate,\n v3cross, v3fromArray, normalizeVector3array\n} from '../math/vector-utils'\nimport { NumberArray } from '../types'\n\nfunction laplacianSmooth (verts: Float32Array, faces: Float32Array, numiter: number, inflate: boolean) {\n // based on D. Xu, Y. Zhang (2009) Generating Triangulated Macromolecular\n // Surfaces by Euclidean Distance Transform. PLoS ONE 4(12): e8140.\n //\n // Permission to use, copy, modify, and distribute this program for\n // any purpose, with or without fee, is hereby granted, provided that\n // the notices on the head, the reference information, and this\n // copyright notice appear in all copies or substantial portions of\n // the Software. It is provided \"as is\" without express or implied\n // warranty.\n //\n // ported to JavaScript and adapted to NGL by Alexander Rose\n\n numiter = numiter || 1\n inflate = inflate || true\n\n const nv = verts.length / 3\n const nf = faces.length / 3\n let norms: Float32Array | undefined = undefined\n\n if (inflate) {\n norms = new Float32Array(nv * 3)\n }\n\n const tps = new Float32Array(nv * 3)\n\n let i\n const ndeg = 20\n const vertdeg = new Array(ndeg)\n\n for (i = 0; i < ndeg; ++i) {\n vertdeg[ i ] = new Uint32Array(nv)\n }\n\n for (i = 0; i < nv; ++i) {\n vertdeg[ 0 ][ i ] = 0\n }\n\n let j, jl\n let flagvert: boolean\n\n // for each face\n\n for (i = 0; i < nf; ++i) {\n var ao = i * 3\n var bo = i * 3 + 1\n var co = i * 3 + 2\n\n // vertex a\n\n flagvert = true\n for (j = 0, jl = vertdeg[ 0 ][ faces[ao] ]; j < jl; ++j) {\n if (faces[ bo ] === vertdeg[ j + 1 ][ faces[ ao ] ]) {\n flagvert = false\n break\n }\n }\n if (flagvert) {\n vertdeg[ 0 ][ faces[ ao ] ]++\n vertdeg[ vertdeg[ 0 ][ faces[ ao ] ] ][ faces[ ao ] ] = faces[ bo ]\n }\n\n flagvert = true\n for (j = 0, jl = vertdeg[ 0 ][ faces[ ao ] ]; j < jl; ++j) {\n if (faces[ co ] === vertdeg[ j + 1 ][ faces[ ao ] ]) {\n flagvert = false\n break\n }\n }\n if (flagvert) {\n vertdeg[ 0 ][ faces[ ao ] ]++\n vertdeg[ vertdeg[ 0 ][ faces[ ao ] ] ][ faces[ ao ] ] = faces[ co ]\n }\n\n // vertex b\n\n flagvert = true\n for (j = 0, jl = vertdeg[ 0 ][ faces[ bo ] ]; j < jl; ++j) {\n if (faces[ ao ] === vertdeg[ j + 1 ][ faces[ bo ] ]) {\n flagvert = false\n break\n }\n }\n if (flagvert) {\n vertdeg[ 0 ][ faces[ bo ] ]++\n vertdeg[ vertdeg[ 0 ][ faces[ bo ] ] ][ faces[ bo ] ] = faces[ ao ]\n }\n\n flagvert = true\n for (j = 0, jl = vertdeg[ 0 ][ faces[ bo ] ]; j < jl; ++j) {\n if (faces[ co ] === vertdeg[ j + 1 ][ faces[ bo ] ]) {\n flagvert = false\n break\n }\n }\n if (flagvert) {\n vertdeg[ 0 ][ faces[ bo ] ]++\n vertdeg[ vertdeg[ 0 ][ faces[ bo ] ] ][ faces[ bo ] ] = faces[ co ]\n }\n\n // vertex c\n\n flagvert = true\n for (j = 0; j < vertdeg[ 0 ][ faces[ co ] ]; ++j) {\n if (faces[ ao ] === vertdeg[ j + 1 ][ faces[ co ] ]) {\n flagvert = false\n break\n }\n }\n if (flagvert) {\n vertdeg[ 0 ][ faces[ co ] ]++\n vertdeg[ vertdeg[ 0 ][ faces[ co ] ] ][ faces[ co ] ] = faces[ ao ]\n }\n\n flagvert = true\n for (j = 0, jl = vertdeg[ 0 ][ faces[ co ] ]; j < jl; ++j) {\n if (faces[ bo ] === vertdeg[ j + 1 ][ faces[ co ] ]) {\n flagvert = false\n break\n }\n }\n if (flagvert) {\n vertdeg[ 0 ][ faces[ co ] ]++\n vertdeg[ vertdeg[ 0 ][ faces[ co ] ] ][ faces[ co ] ] = faces[ bo ]\n }\n }\n\n var wt = 1.0\n var wt2 = 0.5\n var i3, vi3, vdi, wtvi, wt2vi\n var ssign = -1\n var scaleFactor = 1\n var outwt = 0.75 / (scaleFactor + 3.5) // area-preserving\n\n // smoothing iterations\n\n for (var k = 0; k < numiter; ++k) {\n // for each vertex\n\n for (i = 0; i < nv; ++i) {\n i3 = i * 3\n vdi = vertdeg[ 0 ][ i ]\n\n if (vdi < 3) {\n tps[ i3 ] = verts[ i3 ]\n tps[ i3 + 1 ] = verts[ i3 + 1 ]\n tps[ i3 + 2 ] = verts[ i3 + 2 ]\n } else if (vdi === 3 || vdi === 4) {\n tps[ i3 ] = 0\n tps[ i3 + 1 ] = 0\n tps[ i3 + 2 ] = 0\n\n for (j = 0; j < vdi; ++j) {\n vi3 = vertdeg[ j + 1 ][ i ] * 3\n tps[ i3 ] += verts[ vi3 ]\n tps[ i3 + 1 ] += verts[ vi3 + 1 ]\n tps[ i3 + 2 ] += verts[ vi3 + 2 ]\n }\n\n tps[ i3 ] += wt2 * verts[ i3 ]\n tps[ i3 + 1 ] += wt2 * verts[ i3 + 1 ]\n tps[ i3 + 2 ] += wt2 * verts[ i3 + 2 ]\n\n wt2vi = wt2 + vdi\n tps[ i3 ] /= wt2vi\n tps[ i3 + 1 ] /= wt2vi\n tps[ i3 + 2 ] /= wt2vi\n } else {\n tps[ i3 ] = 0\n tps[ i3 + 1 ] = 0\n tps[ i3 + 2 ] = 0\n\n for (j = 0; j < vdi; ++j) {\n vi3 = vertdeg[ j + 1 ][ i ] * 3\n tps[ i3 ] += verts[ vi3 ]\n tps[ i3 + 1 ] += verts[ vi3 + 1 ]\n tps[ i3 + 2 ] += verts[ vi3 + 2 ]\n }\n\n tps[ i3 ] += wt * verts[ i3 ]\n tps[ i3 + 1 ] += wt * verts[ i3 + 1 ]\n tps[ i3 + 2 ] += wt * verts[ i3 + 2 ]\n\n wtvi = wt + vdi\n tps[ i3 ] /= wtvi\n tps[ i3 + 1 ] /= wtvi\n tps[ i3 + 2 ] /= wtvi\n }\n }\n\n verts.set(tps) // copy smoothed positions\n\n if (inflate) {\n computeVertexNormals(verts, faces, norms)\n var nv3 = nv * 3\n\n for (i3 = 0; i3 < nv3; i3 += 3) {\n // if(verts[i].inout) ssign=1;\n // else ssign=-1;\n\n verts[ i3 ] += ssign * outwt * norms![ i3 ]\n verts[ i3 + 1 ] += ssign * outwt * norms![ i3 + 1 ]\n verts[ i3 + 2 ] += ssign * outwt * norms![ i3 + 2 ]\n }\n }\n }\n}\nObject.assign(laplacianSmooth, {__deps: [ computeVertexNormals ]})\n\nfunction computeVertexNormals (position: Float32Array, index?: NumberArray, normal?: Float32Array) {\n var i, il\n\n if (normal === undefined) {\n normal = new Float32Array(position.length)\n } else {\n // reset existing normals to zero\n for (i = 0, il = normal.length; i < il; i++) {\n normal[ i ] = 0\n }\n }\n\n var a = new Float32Array(3)\n var b = new Float32Array(3)\n var c = new Float32Array(3)\n var cb = new Float32Array(3)\n var ab = new Float32Array(3)\n\n if (index) {\n // indexed elements\n for (i = 0, il = index.length; i < il; i += 3) {\n var ai = index[ i ] * 3\n var bi = index[ i + 1 ] * 3\n var ci = index[ i + 2 ] * 3\n\n v3fromArray(a, position, ai)\n v3fromArray(b, position, bi)\n v3fromArray(c, position, ci)\n\n v3sub(cb, c, b)\n v3sub(ab, a, b)\n v3cross(cb, cb, ab)\n\n normal[ ai ] += cb[ 0 ]\n normal[ ai + 1 ] += cb[ 1 ]\n normal[ ai + 2 ] += cb[ 2 ]\n\n normal[ bi ] += cb[ 0 ]\n normal[ bi + 1 ] += cb[ 1 ]\n normal[ bi + 2 ] += cb[ 2 ]\n\n normal[ ci ] += cb[ 0 ]\n normal[ ci + 1 ] += cb[ 1 ]\n normal[ ci + 2 ] += cb[ 2 ]\n }\n } else {\n // non-indexed elements (unconnected triangle soup)\n for (i = 0, il = position.length; i < il; i += 9) {\n v3fromArray(a, position, i)\n v3fromArray(b, position, i + 3)\n v3fromArray(c, position, i + 6)\n\n v3sub(cb, c, b)\n v3sub(ab, a, b)\n v3cross(cb, cb, ab)\n\n normal[ i ] = cb[ 0 ]\n normal[ i + 1 ] = cb[ 1 ]\n normal[ i + 2 ] = cb[ 2 ]\n\n normal[ i + 3 ] = cb[ 0 ]\n normal[ i + 4 ] = cb[ 1 ]\n normal[ i + 5 ] = cb[ 2 ]\n\n normal[ i + 6 ] = cb[ 0 ]\n normal[ i + 7 ] = cb[ 1 ]\n normal[ i + 8 ] = cb[ 2 ]\n }\n }\n\n normalizeVector3array(normal)\n\n return normal\n}\nObject.assign(computeVertexNormals, {__deps: [\n v3sub, v3cross, v3fromArray, normalizeVector3array\n]})\n\nfunction getRadiusDict (radiusList: number[]) {\n var radiusDict: {[k: number]: boolean} = {}\n for (var i = 0, il = radiusList.length; i < il; ++i) {\n radiusDict[ radiusList[ i ] ] = true\n }\n return radiusDict\n}\n\nfunction getSurfaceGrid (min: Float32Array, max: Float32Array, maxRadius: number, scaleFactor: number, extraMargin: number) {\n // need margin to avoid boundary/round off effects\n var margin = (1 / scaleFactor) * 3\n margin += maxRadius\n\n v3subScalar(min, min, extraMargin + margin)\n v3addScalar(max, max, extraMargin + margin)\n\n v3multiplyScalar(min, min, scaleFactor)\n v3floor(min, min)\n v3divideScalar(min, min, scaleFactor)\n\n v3multiplyScalar(max, max, scaleFactor)\n v3ceil(max, max)\n v3divideScalar(max, max, scaleFactor)\n\n var dim = new Float32Array(3)\n v3sub(dim, max, min)\n v3multiplyScalar(dim, dim, scaleFactor)\n v3ceil(dim, dim)\n v3addScalar(dim, dim, 1)\n\n var maxSize = Math.pow(10, 6) * 256\n var tmpSize = dim[ 0 ] * dim[ 1 ] * dim[ 2 ] * 3\n\n if (maxSize <= tmpSize) {\n scaleFactor *= Math.pow(maxSize / tmpSize, 1 / 3)\n\n v3multiplyScalar(min, min, scaleFactor)\n v3floor(min, min)\n v3divideScalar(min, min, scaleFactor)\n\n v3multiplyScalar(max, max, scaleFactor)\n v3ceil(max, max)\n v3divideScalar(max, max, scaleFactor)\n\n v3sub(dim, max, min)\n v3multiplyScalar(dim, dim, scaleFactor)\n v3ceil(dim, dim)\n v3addScalar(dim, dim, 1)\n }\n\n var tran = new Float32Array(min)\n v3negate(tran, tran)\n\n // coordinate transformation matrix\n var matrix = m4new()\n var mroty = m4new()\n m4makeRotationY(mroty, degToRad(90))\n m4multiply(matrix, matrix, mroty)\n\n var mscale = m4new()\n m4makeScale(\n mscale,\n -1 / scaleFactor,\n 1 / scaleFactor,\n 1 / scaleFactor\n )\n m4multiply(matrix, matrix, mscale)\n\n var mtrans = m4new()\n m4makeTranslation(\n mtrans,\n -scaleFactor * tran[2],\n -scaleFactor * tran[1],\n -scaleFactor * tran[0]\n )\n m4multiply(matrix, matrix, mtrans)\n\n return {\n dim: dim,\n tran: tran,\n matrix: matrix,\n scaleFactor: scaleFactor\n }\n}\nObject.assign(getSurfaceGrid, {__deps: [\n degToRad,\n v3subScalar, v3addScalar, v3divideScalar, v3multiplyScalar,\n v3floor, v3ceil, v3sub, v3negate,\n m4new, m4multiply, m4makeTranslation, m4makeScale, m4makeRotationY\n]})\n\nexport {\n laplacianSmooth,\n computeVertexNormals,\n getRadiusDict,\n getSurfaceGrid\n}\n","/**\n * @file Surface\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Box3, BufferGeometry, Group, Color } from 'three'\n\nimport { Debug, Log, ColormakerRegistry } from '../globals'\nimport { getUintArray } from '../utils'\nimport { AtomPicker, SurfacePicker } from '../utils/picker'\nimport { uniformArray, uniformArray3, serialArray } from '../math/array-utils'\nimport Selection from '../selection/selection'\nimport { ColormakerParameters } from '../color/colormaker';\nimport { Structure, Volume } from '../ngl';\n\nexport interface SurfaceData {\n position: Float32Array\n index: Uint32Array|Uint16Array|undefined\n normal: Float32Array\n color: Float32Array\n atomindex: Int32Array\n contour: boolean\n}\n/**\n * Surface\n */\nclass Surface {\n name: string\n path: string\n position: Float32Array\n index: Uint32Array|Uint16Array|undefined\n normal: Float32Array|undefined\n color: Float32Array|undefined\n atomindex: Int32Array|undefined\n contour: boolean\n center: Vector3\n boundingBox: Box3\n size: number\n info: {\n type?: string\n probeRadius?: number\n scaleFactor?: number\n smooth?: number\n cutoff?: number\n isolevel?: number\n volume?: Volume\n }\n\n /**\n * @param {String} name - surface name\n * @param {String} path - source path\n * @param {Object} data - surface data\n * @param {Float32Array} data.position - surface positions\n * @param {Int32Array} data.index - surface indices\n * @param {Float32Array} data.normal - surface normals\n * @param {Float32Array} data.color - surface colors\n * @param {Int32Array} data.atomindex - atom indices\n * @param {boolean} data.contour - contour mode flag\n */\n constructor (name: string, path: string, data?: SurfaceData) {\n this.name = name || ''\n this.path = path || ''\n this.info = {}\n\n this.center = new Vector3()\n this.boundingBox = new Box3()\n\n if (data instanceof BufferGeometry ||\n data instanceof Group\n ) {\n // to be removed\n this.fromGeometry(data)\n } else if (data) {\n this.set(\n data.position,\n data.index,\n data.normal,\n data.color,\n data.atomindex,\n data.contour\n )\n\n this.boundingBox.setFromArray(data.position)\n this.boundingBox.getCenter(this.center)\n }\n }\n\n get type () { return 'Surface' }\n\n /**\n * set surface data\n * @param {Float32Array} position - surface positions\n * @param {Int32Array} index - surface indices\n * @param {Float32Array} normal - surface normals\n * @param {Float32Array} color - surface colors\n * @param {Int32Array} atomindex - atom indices\n * @param {boolean} contour - contour mode flag\n * @return {undefined}\n */\n set (position: Float32Array,\n index: Uint32Array|Uint16Array|undefined,\n normal: Float32Array|undefined,\n color: Float32Array|undefined,\n atomindex: Int32Array|undefined,\n contour: boolean = false) {\n /**\n * @type {Float32Array}\n */\n this.position = position\n /**\n * @type {Uint32Array|Uint16Array|undefined}\n */\n this.index = index\n /**\n * @type {Float32Array|undefined}\n */\n this.normal = normal\n /**\n * @type {Float32Array|undefined}\n */\n this.color = color\n /**\n * @type {Int32Array|undefined}\n */\n this.atomindex = atomindex\n\n this.size = position.length / 3\n this.contour = contour\n }\n\n fromGeometry (geometry: BufferGeometry|Group) {\n if (Debug) Log.time('GeometrySurface.fromGeometry')\n\n let geo\n\n if (geometry instanceof BufferGeometry) {\n geo = geometry\n } else {\n geo = (geometry as any)[ 0 ]\n }\n\n if (!geo.boundingBox) geo.computeBoundingBox()\n\n this.boundingBox.copy(geo.boundingBox)\n this.boundingBox.getCenter(this.center)\n\n let position, color, index, normal\n\n if (geo instanceof BufferGeometry) {\n const attr = geo.attributes\n const an = (attr as any).normal ? (attr as any).normal.array : false\n\n // assume there are no normals if the first is zero\n if (!an || (an[ 0 ] === 0 && an[ 1 ] === 0 && an[ 2 ] === 0)) {\n geo.computeVertexNormals()\n }\n\n position = (attr).position.array\n index = (attr).index ? (attr).index.array : null\n normal = (attr).normal.array\n }\n\n this.set(position, index, normal, color, undefined)\n\n if (Debug) Log.timeEnd('GeometrySurface.setGeometry')\n }\n\n getPosition () {\n return this.position\n }\n\n getColor (params: ColormakerParameters&{ scheme: string}) {\n const p = params || {}\n p.surface = this\n\n const n = this.size\n const array = new Float32Array(n * 3)\n const colormaker = ColormakerRegistry.getScheme(p)\n\n if (colormaker.volumeColor || p.scheme === 'random') {\n for (let i = 0; i < n; ++i) {\n colormaker.volumeColorToArray(i, array, i * 3)\n }\n } else if (colormaker.positionColor) {\n const v = new Vector3()\n const pos = this.position\n\n for (let i = 0; i < n; ++i) {\n var i3 = i * 3\n v.set(pos[ i3 ], pos[ i3 + 1 ], pos[ i3 + 2 ])\n colormaker.positionColorToArray(v, array, i3)\n }\n } else if (colormaker.atomColor && this.atomindex) {\n const atomProxy = p.structure!.getAtomProxy()\n const atomindex = this.atomindex\n\n for (let i = 0; i < n; ++i) {\n atomProxy.index = atomindex[ i ]\n colormaker.atomColorToArray(atomProxy, array, i * 3)\n }\n } else {\n const tc = new Color(p.value)\n uniformArray3(n, tc.r, tc.g, tc.b, array)\n }\n\n return array\n }\n\n getPicking (structure?: Structure) {\n if (this.atomindex && structure) {\n return new AtomPicker(this.atomindex as any, structure)\n } else {\n return new SurfacePicker(serialArray(this.size), this)\n }\n }\n\n getNormal () {\n return this.normal\n }\n\n getSize (size: number, scale: number) {\n return uniformArray(this.size, size * scale)\n }\n\n getIndex () {\n return this.index\n }\n\n getFilteredIndex (sele: string, structure: Structure) {\n if (sele && this.atomindex) {\n const selection = new Selection(sele)\n const atomSet = structure.getAtomSet(selection)\n const filteredIndex = []\n\n const atomindex = this.atomindex\n const index = this.index\n const n = index!.length\n const elementSize = this.contour ? 2 : 3\n\n let j = 0\n\n for (let i = 0; i < n; i += elementSize) {\n let include = true\n\n for (let a = 0; a < elementSize; a++) {\n const idx = index![ i + a ]\n const ai = atomindex[ idx ]\n if (!atomSet.get(ai)) {\n include = false\n break\n }\n }\n\n if (!include) { continue }\n\n for (let a = 0; a < elementSize; a++, j++) {\n filteredIndex[ j ] = index![ i + a ]\n }\n }\n\n return getUintArray(filteredIndex, this.position.length / 3)\n } else {\n return this.index\n }\n }\n\n getAtomindex () {\n return this.atomindex\n }\n\n dispose () {\n\n //\n\n }\n}\n\nexport default Surface\n","/**\n * @file Volume\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Box3, Matrix3, Matrix4 } from 'three'\n\nimport { WorkerRegistry, ColormakerRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport WorkerPool from '../worker/worker-pool'\nimport { VolumePicker } from '../utils/picker'\nimport {\n uniformArray, serialArray,\n arrayMin, arrayMax, arraySum, arrayMean, arrayRms\n} from '../math/array-utils'\nimport MarchingCubes from './marching-cubes'\nimport { laplacianSmooth, computeVertexNormals } from './surface-utils'\nimport {\n applyMatrix4toVector3array, applyMatrix3toVector3array\n} from '../math/vector-utils'\nimport { m3new, m3makeNormal } from '../math/matrix-utils'\nimport Surface from './surface'\nimport { NumberArray } from '../types';\nimport { ColormakerParameters } from '../color/colormaker';\n\nexport interface VolumeSurface {\n new (data: NumberArray, nx: number, ny: number, nz: number, atomindex: NumberArray): void\n getSurface: (isolevel: number, smooth: boolean|number, box: number[][]|undefined, matrix: Float32Array, contour: boolean, wrap?: boolean) => {\n position: Float32Array\n normal: undefined|Float32Array\n index: Uint32Array|Uint16Array\n atomindex: Int32Array|undefined\n contour: boolean\n }\n}\nexport function VolumeSurface (this: VolumeSurface,data: NumberArray, nx: number, ny: number, nz: number, atomindex: NumberArray) {\n var mc = new (MarchingCubes as any)(data, nx, ny, nz, atomindex) as MarchingCubes\n\n function getSurface (isolevel: number, smooth: boolean|number, box: number[][]|undefined, matrix: Float32Array, contour: boolean, wrap: boolean = false) {\n const sd = mc.triangulate(isolevel, smooth as boolean, box, contour, wrap)\n if (smooth && !contour) {\n laplacianSmooth(sd.position, sd.index as any, smooth as number, true)\n sd.normal = computeVertexNormals(sd.position, sd.index as any)\n }\n if (matrix) {\n applyMatrix4toVector3array(matrix, sd.position)\n if (sd.normal) {\n const normalMatrix = m3new()\n m3makeNormal(normalMatrix, matrix)\n applyMatrix3toVector3array(normalMatrix, sd.normal)\n }\n }\n return sd\n }\n\n this.getSurface = getSurface\n}\nObject.assign(VolumeSurface, {__deps: [\n laplacianSmooth, computeVertexNormals, MarchingCubes,\n applyMatrix4toVector3array, applyMatrix3toVector3array,\n m3new, m3makeNormal\n]})\n\nWorkerRegistry.add('surf', function func (e: any, callback: (data: any, transferList: any) => void) {\n const a = e.data.args\n const p = e.data.params\n if (a) {\n /* global self */\n (self as any).volsurf = new (VolumeSurface as any)(a[0], a[1], a[2], a[3], a[4]) as VolumeSurface\n }\n if (p) {\n const sd = ((self as any).volsurf as VolumeSurface).getSurface(\n p.isolevel, p.smooth, p.box, p.matrix, p.contour, p.wrap\n )\n const transferList = [ sd.position.buffer, sd.index.buffer ]\n if (sd.normal) transferList.push(sd.normal.buffer)\n if (sd.atomindex) transferList.push(sd.atomindex.buffer)\n const data = {\n sd: sd,\n p: p\n }\n callback(data, transferList)\n }\n}, [ VolumeSurface ])\n\nexport type VolumeSize = 'value'|'abs-value'|'value-min'|'deviation'\n/**\n * Volume\n */\nclass Volume {\n name: string\n path: string\n\n matrix: Matrix4\n normalMatrix: Matrix3\n inverseMatrix: Matrix4\n center: Vector3\n boundingBox: Box3\n\n nx: number\n ny: number\n nz: number\n data: Float32Array\n\n worker: Worker\n workerPool: WorkerPool\n _position: Float32Array|undefined\n _min: number|undefined\n _max: number|undefined\n _mean: number|undefined\n _rms: number|undefined\n _sum: number|undefined\n __box: Box3|undefined\n\n atomindex: Int32Array|undefined\n volsurf: VolumeSurface|undefined\n header: any\n /**\n * Make Volume instance\n * @param {String} name - volume name\n * @param {String} path - source path\n * @param {Float32array} data - volume 3d grid\n * @param {Integer} nx - x dimension of the 3d volume\n * @param {Integer} ny - y dimension of the 3d volume\n * @param {Integer} nz - z dimension of the 3d volume\n * @param {Int32Array} atomindex - atom indices corresponding to the cells in the 3d grid\n */\n constructor (name: string, path: string, data?: Float32Array, nx?: number, ny?: number, nz?: number, atomindex?: Int32Array) {\n this.name = name\n this.path = path\n\n this.matrix = new Matrix4()\n this.normalMatrix = new Matrix3()\n this.inverseMatrix = new Matrix4()\n this.center = new Vector3()\n this.boundingBox = new Box3()\n\n this.setData(data, nx, ny, nz, atomindex)\n }\n\n get type () { return 'Volume' }\n\n /**\n * set volume data\n * @param {Float32array} data - volume 3d grid\n * @param {Integer} nx - x dimension of the 3d volume\n * @param {Integer} ny - y dimension of the 3d volume\n * @param {Integer} nz - z dimension of the 3d volume\n * @param {Int32Array} atomindex - atom indices corresponding to the cells in the 3d grid\n * @return {undefined}\n */\n setData (data?: Float32Array, nx?: number, ny?: number, nz?: number, atomindex?: Int32Array) {\n this.nx = nx || 1\n this.ny = ny || 1\n this.nz = nz || 1\n\n this.data = data || new Float32Array(1)\n this.setAtomindex(atomindex)\n\n delete this._position\n\n delete this._min\n delete this._max\n delete this._mean\n delete this._rms\n\n if (this.worker) this.worker.terminate()\n }\n\n /**\n * Set statistics, which can be different from the data in this volume,\n * if this volume is a slice of a bigger volume\n * @param {Number|undefined} min - minimum value of the whole data set\n * @param {Number|undefined} max - maximum value of the whole data set\n * @param {Number|undefined} mean - average value of the whole data set\n * @param {Number|undefined} rms - sigma value of the whole data set\n */\n setStats (min: number|undefined, max: number|undefined, mean: number|undefined, rms: number|undefined) {\n this._min = min\n this._max = max\n this._mean = mean\n this._rms = rms\n }\n\n /**\n * set transformation matrix\n * @param {Matrix4} matrix - 4x4 transformation matrix\n * @return {undefined}\n */\n setMatrix (matrix: Matrix4) {\n this.matrix.copy(matrix)\n\n const bb = this.boundingBox\n const v = this.center // temporary re-purposing\n\n const x = this.nx - 1\n const y = this.ny - 1\n const z = this.nz - 1\n\n bb.makeEmpty()\n\n bb.expandByPoint(v.set(x, y, z))\n bb.expandByPoint(v.set(x, y, 0))\n bb.expandByPoint(v.set(x, 0, z))\n bb.expandByPoint(v.set(x, 0, 0))\n bb.expandByPoint(v.set(0, y, z))\n bb.expandByPoint(v.set(0, 0, z))\n bb.expandByPoint(v.set(0, y, 0))\n bb.expandByPoint(v.set(0, 0, 0))\n\n bb.applyMatrix4(this.matrix)\n bb.getCenter(this.center)\n\n // make normal matrix\n\n const me = this.matrix.elements\n const r0 = new Vector3(me[0], me[1], me[2])\n const r1 = new Vector3(me[4], me[5], me[6])\n const r2 = new Vector3(me[8], me[9], me[10])\n const cp = new Vector3()\n // [ r0 ] [ r1 x r2 ]\n // M3x3 = [ r1 ] N = [ r2 x r0 ]\n // [ r2 ] [ r0 x r1 ]\n const ne = this.normalMatrix.elements\n cp.crossVectors(r1, r2)\n ne[ 0 ] = cp.x\n ne[ 1 ] = cp.y\n ne[ 2 ] = cp.z\n cp.crossVectors(r2, r0)\n ne[ 3 ] = cp.x\n ne[ 4 ] = cp.y\n ne[ 5 ] = cp.z\n cp.crossVectors(r0, r1)\n ne[ 6 ] = cp.x\n ne[ 7 ] = cp.y\n ne[ 8 ] = cp.z\n\n this.inverseMatrix.copy(this.matrix).invert()\n }\n\n /**\n * set atom indices\n * @param {Int32Array} atomindex - atom indices corresponding to the cells in the 3d grid\n * @return {undefined}\n */\n setAtomindex (atomindex?: Int32Array) {\n this.atomindex = atomindex\n }\n\n getBox (center: Vector3, size: number, target: Box3) {\n if (!target) target = new Box3()\n\n target.set(center, center)\n target.expandByScalar(size)\n target.applyMatrix4(this.inverseMatrix)\n\n target.min.round()\n target.max.round()\n\n return target\n }\n\n _getBox (center: Vector3|undefined, size: number) {\n if (!center || !size) return\n\n if (!this.__box) this.__box = new Box3()\n const box = this.getBox(center, size, this.__box)\n return [ box.min.toArray(), box.max.toArray() ]\n }\n\n _makeSurface (sd: any, isolevel: number, smooth: number) {\n const name = this.name + '@' + isolevel.toPrecision(2)\n const surface = new Surface(name, '', sd)\n surface.info.isolevel = isolevel\n surface.info.smooth = smooth\n surface.info.volume = this\n\n return surface\n }\n\n getSurface (isolevel: number, smooth: number, center: Vector3, size: number, contour: boolean, wrap: boolean = false) {\n isolevel = isNaN(isolevel) ? this.getValueForSigma(2) : isolevel\n smooth = defaults(smooth, 0)\n\n //\n\n if (this.volsurf === undefined) {\n this.volsurf = new (VolumeSurface as any)(\n this.data, this.nx, this.ny, this.nz, this.atomindex\n ) as VolumeSurface\n }\n\n const box = this._getBox(center, size)\n const sd = this.volsurf.getSurface(\n isolevel, smooth, box!, this.matrix.elements as unknown as Float32Array, contour, wrap\n )\n\n return this._makeSurface(sd, isolevel, smooth)\n }\n\n getSurfaceWorker (isolevel: number, smooth: number, center: Vector3, size: number, contour: boolean, wrap: boolean, callback: (s: Surface) => void) {\n isolevel = isNaN(isolevel) ? this.getValueForSigma(2) : isolevel\n smooth = smooth || 0\n\n //\n\n if (window.hasOwnProperty('Worker')) {\n if (this.workerPool === undefined) {\n this.workerPool = new WorkerPool('surf', 2)\n }\n\n const msg = {}\n const worker = this.workerPool.getNextWorker()\n\n if (worker!.postCount === 0) {\n Object.assign(msg, {\n args: [\n this.data, this.nx, this.ny, this.nz, this.atomindex\n ]\n })\n }\n\n Object.assign(msg, {\n params: {\n isolevel: isolevel,\n smooth: smooth,\n box: this._getBox(center, size),\n matrix: this.matrix.elements,\n contour: contour,\n wrap: wrap\n }\n })\n\n worker!.post(msg, undefined,\n (e: any) => {\n const sd = e.data.sd\n const p = e.data.p\n callback(this._makeSurface(sd, p.isolevel, p.smooth))\n },\n (e : string) => {\n console.warn(\n 'Volume.getSurfaceWorker error - trying without worker', e\n )\n const surface = this.getSurface(isolevel, smooth, center, size, contour, wrap)\n callback(surface)\n }\n )\n } else {\n const surface = this.getSurface(isolevel, smooth, center, size, contour, wrap)\n callback(surface)\n }\n }\n\n getValueForSigma (sigma: number) {\n return this.mean + defaults(sigma, 2) * this.rms\n }\n\n getSigmaForValue (value: number) {\n return (defaults(value, 0) - this.mean) / this.rms\n }\n\n get position () {\n if (!this._position) {\n const nz = this.nz\n const ny = this.ny\n const nx = this.nx\n const position = new Float32Array(nx * ny * nz * 3)\n\n let p = 0\n for (let z = 0; z < nz; ++z) {\n for (let y = 0; y < ny; ++y) {\n for (let x = 0; x < nx; ++x) {\n position[ p + 0 ] = x\n position[ p + 1 ] = y\n position[ p + 2 ] = z\n p += 3\n }\n }\n }\n\n applyMatrix4toVector3array(this.matrix.elements as unknown as Float32Array, position)\n this._position = position\n }\n\n return this._position\n }\n\n getDataAtomindex () {\n return this.atomindex\n }\n\n getDataPosition () {\n return this.position\n }\n\n getDataColor (params: ColormakerParameters & {scheme: string}) {\n const p = params || {}\n p.volume = this\n p.scale = p.scale || 'Spectral'\n p.domain = p.domain || [ this.min, this.max ]\n\n const colormaker = ColormakerRegistry.getScheme(p)\n\n const n = this.position.length / 3\n const array = new Float32Array(n * 3)\n\n // var atoms = p.structure.atoms;\n // var atomindex = this.atomindex;\n\n for (let i = 0; i < n; ++i) {\n colormaker.volumeColorToArray(i, array, i * 3)\n // a = atoms[ atomindex[ i ] ];\n // if( a ) colormaker.atomColorToArray( a, array, i * 3 );\n }\n\n return array\n }\n\n getDataPicking () {\n const picking = serialArray(this.position.length / 3)\n return new VolumePicker(picking, this)\n }\n\n getDataSize (size: VolumeSize|number, scale: number) {\n const data = this.data\n const n = this.position.length / 3\n let array\n\n switch (size) {\n case 'value':\n array = new Float32Array(data)\n break\n\n case 'abs-value':\n array = new Float32Array(data)\n for (let i = 0; i < n; ++i) {\n array[ i ] = Math.abs(array[ i ])\n }\n break\n\n case 'value-min': {\n array = new Float32Array(data)\n const min = this.min\n for (let i = 0; i < n; ++i) {\n array[ i ] -= min\n }\n break\n }\n\n case 'deviation':\n array = new Float32Array(data)\n break\n\n default:\n array = uniformArray(n, size)\n break\n }\n\n if (scale !== 1.0) {\n for (let i = 0; i < n; ++i) {\n array[ i ] *= scale\n }\n }\n\n return array\n }\n\n get min () {\n if (this._min === undefined) {\n this._min = arrayMin(this.data)\n }\n return this._min\n }\n\n get max () {\n if (this._max === undefined) {\n this._max = arrayMax(this.data)\n }\n return this._max\n }\n\n get sum () {\n if (this._sum === undefined) {\n this._sum = arraySum(this.data)\n }\n return this._sum\n }\n\n get mean () {\n if (this._mean === undefined) {\n this._mean = arrayMean(this.data)\n }\n return this._mean\n }\n\n get rms () {\n if (this._rms === undefined) {\n this._rms = arrayRms(this.data)\n }\n return this._rms\n }\n\n clone () {\n const vol = new Volume(\n this.name,\n this.path,\n\n this.data,\n\n this.nx,\n this.ny,\n this.nz,\n\n this.atomindex\n )\n\n vol.matrix.copy(this.matrix)\n vol.header = Object.assign({}, this.header)\n\n return vol\n }\n\n dispose () {\n if (this.workerPool) this.workerPool.terminate()\n }\n}\n\nexport default Volume\n","/**\n * @file Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport {\n Color, Vector3, Matrix4,\n FrontSide, BackSide, DoubleSide,\n // VertexColors,\n NoBlending,\n BufferGeometry, BufferAttribute,\n UniformsUtils, UniformsLib, Uniform,\n Group, LineSegments, Points, Mesh, Object3D,\n ShaderMaterial,\n DynamicDrawUsage,\n StaticDrawUsage\n} from 'three'\n\nimport { Log } from '../globals'\nimport { createParams, getTypedArray, getUintArray } from '../utils'\nimport { GenericColor, TypedArray } from '../types'\nimport { getShader, ShaderDefines } from '../shader/shader-utils'\nimport { serialArray } from '../math/array-utils'\nimport { Picker } from '../utils/picker'\n\nexport type BufferSide = 'front'|'back'|'double'\n\nfunction getThreeSide (side: BufferSide) {\n if (side === 'front') {\n return FrontSide\n } else if (side === 'back') {\n return BackSide\n } else if (side === 'double') {\n return DoubleSide\n } else {\n return DoubleSide\n }\n}\n\nconst itemSize = {\n 'f': 1, 'v2': 2, 'v3': 3, 'c': 3\n}\n\nfunction setObjectMatrix (object: Object3D, matrix: Matrix4) {\n object.matrix.copy(matrix)\n object.matrix.decompose(object.position, object.quaternion, object.scale)\n object.matrixWorldNeedsUpdate = true\n}\n\nexport type BufferTypes = 'picking'|'background'\nexport type BufferMaterials = 'material'|'wireframeMaterial'|'pickingMaterial'\n\nexport interface _BufferAttribute {\n type: 'f'|'v2'|'v3'|'c'\n value?: TypedArray\n}\n\nexport type Uniforms = { [k: string]: Uniform|{ value: any } }\n\nexport const BufferDefaultParameters = {\n opaqueBack: false,\n side: 'double' as BufferSide, // which triangle sides to render\n opacity: 1.0, // translucency: 1 is fully opaque, 0 is fully transparent\n depthWrite: true,\n clipNear: 0, // position of camera near/front clipping plane in percent of scene bounding box\n clipRadius: 0,\n clipCenter: new Vector3(),\n flatShaded: false, // render flat shaded\n wireframe: false, // render as wireframe\n roughness: 0.4, // how rough the material is, between 0 and 1\n metalness: 0.0, // how metallic the material is, between 0 and 1\n diffuse: 0xffffff, // diffuse color for lighting\n diffuseInterior: false,\n useInteriorColor: false, // render back-side with interior color\n interiorColor: 0xdddddd, // interior color\n interiorDarkening: 0, // interior darkening factor\n forceTransparent: false, // force the material to allow transparency\n matrix: new Matrix4(), // additional transformation matrix\n disablePicking: false, // disable picking\n sortParticles: false,\n background: false\n}\nexport type BufferParameters = Omit & { diffuse: GenericColor; interiorColor: GenericColor }\n\nexport const BufferParameterTypes = {\n opaqueBack: { updateShader: true },\n side: { updateShader: true, property: true },\n opacity: { uniform: true },\n depthWrite: { property: true },\n clipNear: { updateShader: true, property: true },\n clipRadius: { updateShader: true, uniform: true },\n clipCenter: { uniform: true },\n flatShaded: { updateShader: true },\n background: { updateShader: true },\n wireframe: { updateVisibility: true },\n roughness: { uniform: true },\n metalness: { uniform: true },\n diffuse: { uniform: true },\n diffuseInterior: { updateShader: true },\n useInteriorColor: { updateShader: true },\n interiorColor: { uniform: true },\n interiorDarkening: { uniform: true },\n matrix: {}\n}\n\nexport interface BufferData {\n position?: Float32Array\n position1?: Float32Array // TODO\n color?: Float32Array\n index?: Uint32Array|Uint16Array\n normal?: Float32Array\n\n picking?: Picker\n primitiveId?: Float32Array\n}\n\n/**\n * Buffer class. Base class for buffers.\n * @interface\n */\nclass Buffer {\n parameterTypes = BufferParameterTypes\n get defaultParameters() { return BufferDefaultParameters }\n parameters: BufferParameters\n uniforms: Uniforms\n pickingUniforms: Uniforms\n\n private _positionDataSize: number\n\n geometry = new BufferGeometry()\n indexVersion = 0\n wireframeIndexVersion = -1\n group = new Group()\n wireframeGroup = new Group()\n pickingGroup = new Group()\n\n vertexShader = ''\n fragmentShader = ''\n isImpostor = false\n isText = false\n isSurface = false\n isPoint = false\n isLine = false\n dynamic = true\n visible = true\n\n picking?: Picker\n\n material: ShaderMaterial\n wireframeMaterial: ShaderMaterial\n pickingMaterial: ShaderMaterial\n\n wireframeIndex?: Uint32Array|Uint16Array\n wireframeIndexCount = 0\n wireframeGeometry?: BufferGeometry\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.color - colors\n * @param {Uint32Array|Uint16Array} data.index - triangle indices\n * @param {Picker} [data.picking] - picking ids\n * @param {BufferParameters} params - parameters object\n */\n constructor (data: BufferData, params: Partial = {}) {\n this.parameters = createParams(params, this.defaultParameters)\n\n this.uniforms = UniformsUtils.merge([\n UniformsLib.common,\n {\n fogColor: { value: new Color(0x000000) },\n fogNear: { value: 0.0 },\n fogFar: { value: 0.0 },\n opacity: { value: this.parameters.opacity },\n clipNear: { value: 0.0 },\n clipRadius: { value: this.parameters.clipRadius },\n clipCenter: { value: this.parameters.clipCenter }\n },\n {\n emissive: { value: new Color(0x000000) },\n roughness: { value: this.parameters.roughness },\n metalness: { value: this.parameters.metalness },\n interiorColor: { value: new Color(this.parameters.interiorColor) },\n interiorDarkening: { value: this.parameters.interiorDarkening },\n },\n UniformsLib.lights\n ])\n\n this.uniforms.diffuse.value.set(this.parameters.diffuse)\n\n this.pickingUniforms = {\n clipNear: { value: 0.0 },\n objectId: { value: 0 },\n opacity: { value: this.parameters.opacity }\n }\n\n //\n\n const position = data.position || data.position1\n this._positionDataSize = position ? position.length / 3 : 0\n\n if (!data.primitiveId) {\n data.primitiveId = serialArray(this._positionDataSize)\n }\n\n this.addAttributes({\n position: { type: 'v3', value: data.position },\n color: { type: 'c', value: data.color },\n primitiveId: { type: 'f', value: data.primitiveId }\n })\n\n if (params.matrix) {\n this.matrix = params.matrix\n }\n\n if (data.index) {\n this.initIndex(data.index)\n }\n this.picking = data.picking\n\n this.makeWireframeGeometry()\n }\n\n set matrix (m) {\n this.setMatrix(m)\n }\n get matrix () {\n return this.group.matrix.clone()\n }\n\n get transparent () {\n return this.parameters.opacity < 1 || this.parameters.forceTransparent\n }\n\n get size () {\n return this._positionDataSize\n }\n\n get attributeSize () {\n return this.size\n }\n\n get pickable () {\n return !!this.picking && !this.parameters.disablePicking\n }\n\n setMatrix (m: Matrix4) {\n setObjectMatrix(this.group, m)\n setObjectMatrix(this.wireframeGroup, m)\n setObjectMatrix(this.pickingGroup, m)\n }\n\n initIndex (index: Uint32Array|Uint16Array) {\n this.geometry.setIndex(\n new BufferAttribute(index, 1)\n )\n const nindex = this.geometry.getIndex();\n if (!nindex) { Log.error('Index is null'); return; }\n nindex.setUsage(this.dynamic ? DynamicDrawUsage : StaticDrawUsage)\n }\n\n makeMaterial () {\n const side = getThreeSide(this.parameters.side)\n\n const m = new ShaderMaterial({\n uniforms: this.uniforms,\n vertexShader: '',\n fragmentShader: '',\n depthTest: true,\n transparent: this.transparent,\n depthWrite: this.parameters.depthWrite,\n lights: true,\n fog: true,\n side: side\n })\n m.vertexColors = true\n m.extensions.derivatives = true\n m.extensions.fragDepth = this.isImpostor\n\n const wm = new ShaderMaterial({\n uniforms: this.uniforms,\n vertexShader: '',\n fragmentShader: '',\n depthTest: true,\n transparent: this.transparent,\n depthWrite: this.parameters.depthWrite,\n lights: false,\n fog: true,\n side: side\n })\n wm.vertexColors = true\n\n const pm = new ShaderMaterial({\n uniforms: this.pickingUniforms,\n vertexShader: '',\n fragmentShader: '',\n depthTest: true,\n transparent: false,\n depthWrite: this.parameters.depthWrite,\n lights: false,\n fog: false,\n side: side,\n blending: NoBlending\n })\n pm.vertexColors = true\n pm.extensions.fragDepth = this.isImpostor\n\n ;(m as any).clipNear = this.parameters.clipNear\n ;(wm as any).clipNear = this.parameters.clipNear\n ;(pm as any).clipNear = this.parameters.clipNear\n\n this.material = m\n this.wireframeMaterial = wm\n this.pickingMaterial = pm\n\n // also sets vertexShader/fragmentShader\n this.updateShader()\n }\n\n makeWireframeGeometry () {\n this.makeWireframeIndex()\n\n const geometry = this.geometry\n const wireframeIndex = this.wireframeIndex\n const wireframeGeometry = new BufferGeometry()\n\n wireframeGeometry.attributes = geometry.attributes\n if (wireframeIndex) {\n wireframeGeometry.setIndex(\n new BufferAttribute(wireframeIndex, 1).setUsage(this.dynamic ? DynamicDrawUsage : StaticDrawUsage)\n )\n wireframeGeometry.setDrawRange(0, this.wireframeIndexCount)\n }\n\n this.wireframeGeometry = wireframeGeometry\n }\n\n makeWireframeIndex () {\n const edges: number[][] = []\n\n function checkEdge (a: number, b: number) {\n if (a > b) {\n const tmp = a\n a = b\n b = tmp\n }\n\n const list = edges[ a ]\n\n if (list === undefined) {\n edges[ a ] = [ b ]\n return true\n } else if (!list.includes(b)) {\n list.push(b)\n return true\n }\n\n return false\n }\n\n const geometry = this.geometry\n const index = geometry.index\n\n if (!this.parameters.wireframe) {\n this.wireframeIndex = new Uint16Array(0)\n this.wireframeIndexCount = 0\n } else if (index) {\n const array = index.array\n let n = array.length\n if (geometry.drawRange.count !== Infinity) {\n n = geometry.drawRange.count\n }\n let wireframeIndex\n if (this.wireframeIndex && this.wireframeIndex.length > n * 2) {\n wireframeIndex = this.wireframeIndex\n } else {\n const count = (geometry.attributes as any).position.count // TODO\n wireframeIndex = getUintArray(n * 2, count)\n }\n\n let j = 0\n edges.length = 0\n\n for (let i = 0; i < n; i += 3) {\n const a = array[ i + 0 ]\n const b = array[ i + 1 ]\n const c = array[ i + 2 ]\n\n if (checkEdge(a, b)) {\n wireframeIndex[ j + 0 ] = a\n wireframeIndex[ j + 1 ] = b\n j += 2\n }\n if (checkEdge(b, c)) {\n wireframeIndex[ j + 0 ] = b\n wireframeIndex[ j + 1 ] = c\n j += 2\n }\n if (checkEdge(c, a)) {\n wireframeIndex[ j + 0 ] = c\n wireframeIndex[ j + 1 ] = a\n j += 2\n }\n }\n\n this.wireframeIndex = wireframeIndex\n this.wireframeIndexCount = j\n this.wireframeIndexVersion = this.indexVersion\n } else {\n const n = (geometry.attributes as any).position.count // TODO\n\n let wireframeIndex\n if (this.wireframeIndex && this.wireframeIndex.length > n * 2) {\n wireframeIndex = this.wireframeIndex\n } else {\n wireframeIndex = getUintArray(n * 2, n)\n }\n\n for (let i = 0, j = 0; i < n; i += 3) {\n wireframeIndex[ j + 0 ] = i\n wireframeIndex[ j + 1 ] = i + 1\n wireframeIndex[ j + 2 ] = i + 1\n wireframeIndex[ j + 3 ] = i + 2\n wireframeIndex[ j + 4 ] = i + 2\n wireframeIndex[ j + 5 ] = i\n\n j += 6\n }\n\n this.wireframeIndex = wireframeIndex\n this.wireframeIndexCount = n * 2\n this.wireframeIndexVersion = this.indexVersion\n }\n }\n\n updateWireframeIndex () {\n if (!this.wireframeGeometry || !this.wireframeIndex) return\n\n this.wireframeGeometry.setDrawRange(0, Infinity)\n if (this.wireframeIndexVersion < this.indexVersion) this.makeWireframeIndex()\n\n if (this.wireframeGeometry.index &&\n this.wireframeIndex.length > this.wireframeGeometry.index.array.length) {\n this.wireframeGeometry.setIndex(\n new BufferAttribute(this.wireframeIndex, 1).setUsage(this.dynamic ? DynamicDrawUsage : StaticDrawUsage)\n )\n } else {\n const index = this.wireframeGeometry.getIndex()\n if (!index) { Log.error('Index is null'); return; }\n index.set(this.wireframeIndex)\n index.needsUpdate = this.wireframeIndexCount > 0\n index.updateRange.count = this.wireframeIndexCount\n }\n\n this.wireframeGeometry.setDrawRange(0, this.wireframeIndexCount)\n }\n\n getRenderOrder () {\n let renderOrder = 0\n\n if (this.isText) {\n renderOrder = 1\n } else if (this.transparent) {\n if (this.isSurface) {\n renderOrder = 3\n } else {\n renderOrder = 2\n }\n }\n\n return renderOrder\n }\n\n _getMesh (materialName: BufferMaterials) {\n if (!this.material) this.makeMaterial()\n\n const g = this.geometry\n const m = this[ materialName ]\n\n let mesh\n\n if (this.isLine) {\n mesh = new LineSegments(g, m)\n } else if (this.isPoint) {\n mesh = new Points(g, m)\n } else {\n mesh = new Mesh(g, m)\n }\n\n mesh.frustumCulled = false\n mesh.renderOrder = this.getRenderOrder()\n\n return mesh\n }\n\n getMesh () {\n return this._getMesh('material')\n }\n\n getWireframeMesh () {\n let mesh\n\n if (!this.material) this.makeMaterial()\n if (!this.wireframeGeometry) this.makeWireframeGeometry()\n\n mesh = new LineSegments(\n this.wireframeGeometry, this.wireframeMaterial\n )\n\n mesh.frustumCulled = false\n mesh.renderOrder = this.getRenderOrder()\n\n return mesh\n }\n\n getPickingMesh () {\n return this._getMesh('pickingMaterial')\n }\n\n getShader (name: string, type?: BufferTypes) {\n return getShader(name, this.getDefines(type))\n }\n\n getVertexShader (type?: BufferTypes) {\n return this.getShader(this.vertexShader, type)\n }\n\n getFragmentShader (type?: BufferTypes) {\n return this.getShader(this.fragmentShader, type)\n }\n\n getDefines (type?: BufferTypes) {\n const defines: ShaderDefines = {}\n\n if (this.parameters.clipNear) {\n defines.NEAR_CLIP = 1\n }\n\n if (this.parameters.clipRadius) {\n defines.RADIUS_CLIP = 1\n }\n\n if (type === 'picking') {\n defines.PICKING = 1\n } else {\n if (type === 'background' || this.parameters.background) {\n defines.NOLIGHT = 1\n }\n if (this.parameters.flatShaded) {\n defines.FLAT_SHADED = 1\n }\n if (this.parameters.opaqueBack) {\n defines.OPAQUE_BACK = 1\n }\n if (this.parameters.diffuseInterior) {\n defines.DIFFUSE_INTERIOR = 1\n }\n if (this.parameters.useInteriorColor) {\n defines.USE_INTERIOR_COLOR = 1\n }\n }\n\n return defines\n }\n\n getParameters () {\n return this.parameters\n }\n\n addUniforms (uniforms: Uniforms) {\n this.uniforms = UniformsUtils.merge(\n [ this.uniforms, uniforms ]\n )\n\n this.pickingUniforms = UniformsUtils.merge(\n [ this.pickingUniforms, uniforms ]\n )\n }\n\n addAttributes (attributes: { [k: string]: _BufferAttribute }) {\n for (let name in attributes) {\n let buf\n const a = attributes[ name ]\n const arraySize = this.attributeSize * itemSize[ a.type ]\n\n if (a.value) {\n if (arraySize !== a.value.length) {\n Log.error('attribute value has wrong length', name)\n }\n buf = a.value\n } else {\n buf = getTypedArray('float32', arraySize)\n }\n\n this.geometry.setAttribute(\n name,\n new BufferAttribute(buf, itemSize[ a.type ]).setUsage(this.dynamic ? DynamicDrawUsage : StaticDrawUsage)\n )\n }\n }\n\n updateRenderOrder () {\n const renderOrder = this.getRenderOrder()\n function setRenderOrder (mesh: Object3D) {\n mesh.renderOrder = renderOrder\n }\n\n this.group.children.forEach(setRenderOrder)\n if (this.pickingGroup) {\n this.pickingGroup.children.forEach(setRenderOrder)\n }\n }\n\n updateShader () {\n const m = this.material\n const wm = this.wireframeMaterial\n const pm = this.pickingMaterial\n\n m.vertexShader = this.getVertexShader()\n m.fragmentShader = this.getFragmentShader()\n m.needsUpdate = true\n\n wm.vertexShader = this.getShader('Line.vert')\n wm.fragmentShader = this.getShader('Line.frag')\n wm.needsUpdate = true\n\n pm.vertexShader = this.getVertexShader('picking')\n pm.fragmentShader = this.getFragmentShader('picking')\n pm.needsUpdate = true\n }\n\n /**\n * Set buffer parameters\n * @param {BufferParameters} params - buffer parameters object\n * @return {undefined}\n */\n setParameters (params: Partial) {\n const p = params as any\n const pt = this.parameterTypes as any\n const pv = this.parameters as any\n\n const propertyData: { [k: string]: any } = {}\n const uniformData: { [k: string]: any } = {}\n let doShaderUpdate = false\n let doVisibilityUpdate = false\n\n for (const name in p) {\n const value = p[ name ]\n\n if (value === undefined) continue\n pv[ name ] = value\n\n if (pt[ name ] === undefined) continue\n\n if (pt[ name ].property) {\n if (pt[ name ].property !== true) {\n propertyData[ pt[ name ].property as any ] = value\n } else {\n propertyData[ name ] = value\n }\n }\n\n if (pt[ name ].uniform) {\n if (pt[ name ].uniform !== true) {\n uniformData[ pt[ name ].uniform as any ] = value\n } else {\n uniformData[ name ] = value\n }\n }\n\n if (pt[ name ].updateShader) {\n doShaderUpdate = true\n }\n\n if (pt[ name ].updateVisibility) {\n doVisibilityUpdate = true\n }\n\n if (this.dynamic && name === 'wireframe' && value === true) {\n this.updateWireframeIndex()\n }\n\n if (name === 'forceTransparent') {\n propertyData.transparent = this.transparent\n }\n\n if (name === 'matrix') {\n this.matrix = value\n }\n }\n\n this.setProperties(propertyData)\n this.setUniforms(uniformData)\n if (doShaderUpdate) this.updateShader()\n if (doVisibilityUpdate) this.setVisibility(this.visible)\n }\n\n /**\n * Sets buffer attributes\n * @param {Object} data - An object where the keys are the attribute names\n * and the values are the attribute data.\n * @example\n * var buffer = new Buffer();\n * buffer.setAttributes({ attrName: attrData });\n */\n setAttributes (data: any) { // TODO\n const geometry = this.geometry\n const attributes = geometry.attributes as any // TODO\n\n for (const name in data) {\n if (name === 'picking') continue\n\n const array = data[ name ]\n const length = array.length\n\n if (name === 'index') {\n const index = geometry.getIndex()\n if (!index) { Log.error('Index is null'); continue; }\n geometry.setDrawRange(0, Infinity)\n\n if (length > index.array.length) {\n geometry.setIndex(\n new BufferAttribute(array, 1)\n .setUsage(this.dynamic ? DynamicDrawUsage : StaticDrawUsage)\n )\n } else {\n index.set(array)\n index.needsUpdate = length > 0\n index.updateRange.count = length\n geometry.setDrawRange(0, length)\n }\n\n this.indexVersion++\n if (this.parameters.wireframe) this.updateWireframeIndex()\n } else {\n const attribute = attributes[ name ]\n\n if (length > attribute.array.length) {\n geometry.setAttribute(\n name,\n new BufferAttribute(array, attribute.itemSize)\n .setUsage(this.dynamic ? DynamicDrawUsage : StaticDrawUsage)\n )\n } else {\n attributes[ name ].set(array)\n attributes[ name ].needsUpdate = length > 0\n attributes[ name ].updateRange.count = length\n }\n }\n }\n }\n\n setUniforms (data: any) { // TODO\n if (!data) return\n\n const u = this.material.uniforms\n const wu = this.wireframeMaterial.uniforms\n const pu = this.pickingMaterial.uniforms\n\n for (let name in data) {\n if (name === 'opacity') {\n this.setProperties({ transparent: this.transparent })\n }\n\n if (u[ name ] !== undefined) {\n if (u[ name ].value.isVector3) {\n u[ name ].value.copy(data[ name ])\n } else if (u[ name ].value.set) {\n u[ name ].value.set(data[ name ])\n } else {\n u[ name ].value = data[ name ]\n }\n }\n\n if (wu[ name ] !== undefined) {\n if (wu[ name ].value.isVector3) {\n wu[ name ].value.copy(data[ name ])\n } else if (wu[ name ].value.set) {\n wu[ name ].value.set(data[ name ])\n } else {\n wu[ name ].value = data[ name ]\n }\n }\n\n if (pu[ name ] !== undefined) {\n if (pu[ name ].value.isVector3) {\n pu[ name ].value.copy(data[ name ])\n } else if (pu[ name ].value.set) {\n pu[ name ].value.set(data[ name ])\n } else {\n pu[ name ].value = data[ name ]\n }\n }\n }\n }\n\n setProperties (data: any) { // TODO\n if (!data) return\n\n const m = this.material\n const wm = this.wireframeMaterial\n const pm = this.pickingMaterial\n\n for (const _name in data) {\n const name = _name as 'side'|'transparent' // TODO\n\n let value = data[ name ]\n\n if (name === 'transparent') {\n this.updateRenderOrder()\n } else if (name === 'side') {\n value = getThreeSide(value)\n }\n\n (m[ name ] as any) = value;\n (wm[ name ] as any) = value;\n (pm[ name ] as any) = value\n }\n\n m.needsUpdate = true\n wm.needsUpdate = true\n pm.needsUpdate = true\n }\n\n /**\n * Set buffer visibility\n * @param {Boolean} value - visibility value\n * @return {undefined}\n */\n setVisibility (value: boolean) {\n this.visible = value\n\n if (this.parameters.wireframe) {\n this.group.visible = false\n this.wireframeGroup.visible = value\n if (this.pickable) {\n this.pickingGroup.visible = false\n }\n } else {\n this.group.visible = value\n this.wireframeGroup.visible = false\n if (this.pickable) {\n this.pickingGroup.visible = value\n }\n }\n }\n\n /**\n * Free buffer resources\n * @return {undefined}\n */\n dispose () {\n if (this.material) this.material.dispose()\n if (this.wireframeMaterial) this.wireframeMaterial.dispose()\n if (this.pickingMaterial) this.pickingMaterial.dispose()\n\n this.geometry.dispose()\n if (this.wireframeGeometry) this.wireframeGeometry.dispose()\n }\n\n /**\n * Customize JSON serialization to avoid circular references\n */\n toJSON () {\n var result: any = {};\n for (var x in this) {\n if (x !== \"group\" && x !== \"wireframeGroup\" && x != \"pickingGroup\"\n && x !== \"picking\") {\n result[x] = this[x];\n }\n }\n return result;\n }\n}\n\nexport default Buffer\n","/**\n * @file Mesh Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport '../shader/Mesh.vert'\nimport '../shader/Mesh.frag'\n\nimport Buffer, { BufferParameters, BufferData } from './buffer'\n\n/**\n * Mesh buffer. Draws a triangle mesh.\n *\n * @example\n * var meshBuffer = new MeshBuffer({\n * position: new Float32Array(\n * [ 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1 ]\n * ),\n * color: new Float32Array(\n * [ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 ]\n * )\n * });\n */\nclass MeshBuffer extends Buffer {\n vertexShader = 'Mesh.vert'\n fragmentShader = 'Mesh.frag'\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} [data.index] - triangle indices\n * @param {Float32Array} [data.normal] - radii\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: BufferData, params: Partial = {}) {\n super(data, params)\n\n this.addAttributes({\n 'normal': { type: 'v3', value: data.normal }\n })\n\n if (data.normal === undefined) {\n this.geometry.computeVertexNormals()\n }\n }\n}\n\nexport default MeshBuffer\n","/**\n * @file Surface Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport MeshBuffer from './mesh-buffer'\n\n/**\n * Surface buffer. Like a {@link MeshBuffer}, but with `.isSurface` set to `true`.\n */\nclass SurfaceBuffer extends MeshBuffer {\n isSurface = true\n}\n\nexport default SurfaceBuffer\n","/**\n * @file Double Sided Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Vector3, Matrix4 required for declaration only\nimport { Group, BufferGeometry, Object3D, Mesh, LineSegments, Vector3, Matrix4 } from 'three'\n\nimport Buffer, { BufferSide } from './buffer'\nimport { Picker } from '../utils/picker'\n\nfunction setVisibilityTrue (m: Object3D) { m.visible = true }\nfunction setVisibilityFalse (m: Object3D) { m.visible = false }\n\n/**\n * A double-sided mesh buffer. Takes a buffer and renders the front and\n * the back as seperate objects to avoid some artifacts when rendering\n * transparent meshes. Also allows to render the back of a mesh opaque\n * while the front is transparent.\n * @implements {Buffer}\n *\n * @example\n * var sphereGeometryBuffer = new SphereGeometryBuffer({\n * position: new Float32Array([ 0, 0, 0 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * radius: new Float32Array([ 1 ])\n * });\n * var doubleSidedBuffer = new DoubleSidedBuffer(sphereGeometryBuffer);\n */\nclass DoubleSidedBuffer {\n size: number\n side: BufferSide\n visible: boolean\n wireframe: boolean\n geometry: BufferGeometry\n\n picking?: Picker\n\n group = new Group()\n wireframeGroup = new Group()\n pickingGroup = new Group()\n\n frontMeshes: (Mesh|LineSegments)[] = []\n backMeshes: (Mesh|LineSegments)[] = []\n\n buffer: Buffer\n frontBuffer: Buffer\n backBuffer: Buffer\n\n /**\n * Create a double sided buffer\n * @param {Buffer} buffer - the buffer to be rendered double-sided\n */\n constructor (buffer: Buffer) {\n this.size = buffer.size\n this.side = buffer.parameters.side\n this.visible = buffer.visible\n this.geometry = buffer.geometry\n this.picking = buffer.picking\n\n this.group = new Group()\n this.wireframeGroup = new Group()\n this.pickingGroup = new Group()\n\n // requires Group objects to be present\n this.matrix = buffer.matrix\n\n const frontBuffer = buffer\n const backBuffer = new (buffer as any).constructor({ // TODO\n position: new Float32Array(0)\n }) as Buffer\n\n frontBuffer.makeMaterial()\n backBuffer.makeMaterial()\n\n backBuffer.picking = buffer.picking\n backBuffer.geometry = buffer.geometry\n backBuffer.wireframeGeometry = buffer.wireframeGeometry\n backBuffer.setParameters(buffer.getParameters())\n backBuffer.updateShader()\n\n frontBuffer.setParameters({\n side: 'front'\n })\n backBuffer.setParameters({\n side: 'back',\n opacity: backBuffer.parameters.opacity\n })\n\n this.buffer = buffer\n this.frontBuffer = frontBuffer\n this.backBuffer = backBuffer\n }\n\n set matrix (m) {\n Buffer.prototype.setMatrix.call(this, m)\n }\n get matrix () {\n return this.group.matrix.clone()\n }\n\n get pickable () {\n return !!this.picking && !this.parameters.disablePicking\n }\n\n get parameters () {\n return this.buffer.parameters\n }\n\n getParameters () {\n const p = Object.assign({}, this.buffer.parameters)\n p.side = this.side\n return p\n }\n\n getMesh (picking: boolean) {\n let front, back\n\n if (picking) {\n back = this.backBuffer.getPickingMesh()\n front = this.frontBuffer.getPickingMesh()\n } else {\n back = this.backBuffer.getMesh()\n front = this.frontBuffer.getMesh()\n }\n\n this.frontMeshes.push(front)\n this.backMeshes.push(back)\n\n this.setParameters({ side: this.side })\n\n return new Group().add(back, front)\n }\n\n getWireframeMesh () {\n return this.buffer.getWireframeMesh()\n }\n\n getPickingMesh () {\n return this.getMesh(true)\n }\n\n setAttributes (data: any) { // TODO\n this.buffer.setAttributes(data)\n }\n\n setParameters (data: any) { // TODO\n data = Object.assign({}, data)\n\n if (data.side === 'front') {\n this.frontMeshes.forEach(setVisibilityTrue)\n this.backMeshes.forEach(setVisibilityFalse)\n } else if (data.side === 'back') {\n this.frontMeshes.forEach(setVisibilityFalse)\n this.backMeshes.forEach(setVisibilityTrue)\n } else if (data.side === 'double') {\n this.frontMeshes.forEach(setVisibilityTrue)\n this.backMeshes.forEach(setVisibilityTrue)\n }\n\n if (data.side !== undefined) {\n this.side = data.side\n }\n delete data.side\n\n if (data.matrix !== undefined) {\n this.matrix = data.matrix\n }\n delete data.matrix\n\n this.frontBuffer.setParameters(data)\n\n if (data.wireframe !== undefined) {\n this.wireframe = data.wireframe\n this.setVisibility(this.visible)\n }\n delete data.wireframe\n\n this.backBuffer.setParameters(data)\n }\n\n setVisibility (value: boolean) {\n this.visible = value\n\n if (this.parameters.wireframe) {\n this.group.visible = false\n this.wireframeGroup.visible = value\n if (this.pickable) {\n this.pickingGroup.visible = false\n }\n } else {\n this.group.visible = value\n this.wireframeGroup.visible = false\n if (this.pickable) {\n this.pickingGroup.visible = value\n }\n }\n }\n\n dispose () {\n this.frontBuffer.dispose()\n this.backBuffer.dispose()\n }\n\n /**\n * Customize JSON serialization to avoid circular references.\n * Only export simple params which could be useful.\n */\n toJSON () {\n var result: any = {};\n for (var x in this) {\n if (['side', 'size', 'visible', 'matrix', 'parameters'].includes(x)) {\n result[x] = this[x];\n }\n }\n return result;\n }\n}\n\nexport default DoubleSidedBuffer\n","/**\n * @file Contour Buffer\n * @author Fred ludlow \n * @private\n */\n\nimport '../shader/Line.vert'\nimport '../shader/Line.frag'\n\nimport Buffer from './buffer'\n\n/**\n * Contour buffer. A buffer that draws lines (instead of triangle meshes).\n */\nclass ContourBuffer extends Buffer {\n isLine = true\n vertexShader = 'Line.vert'\n fragmentShader = 'Line.frag'\n}\n\nexport default ContourBuffer\n","/**\n * @file Surface Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4, Vector3, Box3 } from 'three'\n\nimport { defaults } from '../utils'\nimport Representation, { RepresentationParameters } from './representation'\nimport Volume from '../surface/volume'\nimport SurfaceBuffer from '../buffer/surface-buffer'\nimport DoubleSidedBuffer from '../buffer/doublesided-buffer'\nimport ContourBuffer from '../buffer/contour-buffer'\nimport Surface from '../surface/surface';\nimport Viewer from '../viewer/viewer';\nimport {SurfaceData} from '../surface/surface'\n// @ts-ignore: unused import ColormakerParameters required for declaration only\nimport { ColormakerParameters } from '../color/colormaker';\nexport type SurfaceDataFields = {position: boolean, color: boolean, index: boolean, normal: boolean, radius: boolean}\n\n/**\n * Surface representation parameter object. Extends {@link RepresentationParameters}\n *\n * @typedef {Object} SurfaceRepresentationParameters - surface representation parameters\n *\n * @property {String} isolevelType - Meaning of the isolevel value. Either *value* for the literal value or *sigma* as a factor of the sigma of the data. For volume data only.\n * @property {Float} isolevel - The value at which to create the isosurface. For volume data only.\n * @property {Boolean} negateIsolevel - For volume data only.\n * @property {Boolean} isolevelScroll - For volume data only\n * @property {Integer} smooth - How many iterations of laplacian smoothing after surface triangulation. For volume data only.\n * @property {Boolean} background - Render the surface in the background, unlit.\n * @property {Boolean} opaqueBack - Render the back-faces (where normals point away from the camera) of the surface opaque, ignoring the transparency parameter.\n * @property {Integer} boxSize - Size of the box to triangulate volume data in. Set to zero to triangulate the whole volume. For volume data only.\n * @property {Boolean} useWorker - Weather or not to triangulate the volume asynchronously in a Web Worker. For volume data only.\n * @property {Boolean} wrap - Wrap volume data around the edges; use in conjuction with boxSize but not larger than the volume dimension. For volume data only.\n */\nexport interface SurfaceRepresentationParameters extends RepresentationParameters {\n isolevelType: 'value'|'sigma'\n isolevel: number\n smooth: number\n background: boolean\n opaqueBack: boolean\n boxSize: number\n useWorker: boolean\n wrap: boolean\n}\n/**\n * Surface representation\n */\n/**\n * Create Surface representation object\n * @param {Surface|Volume} surface - the surface or volume to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {SurfaceRepresentationParameters} params - surface representation parameters\n */\nclass SurfaceRepresentation extends Representation {\n protected surface: Surface|Volume|undefined\n protected volume: Volume|undefined\n protected boxCenter: Vector3\n protected __boxCenter: Vector3\n protected box: Box3\n protected __box: Box3\n protected _position: Vector3\n protected isolevelType: 'value'|'sigma'\n protected isolevel: number\n protected negateIsolevel: boolean\n protected isolevelScroll: boolean\n protected smooth: number\n protected background: boolean\n protected opaqueBack: boolean\n protected boxSize: number\n protected inverseMatrix: Matrix4\n protected colorVolume: Volume\n protected contour: boolean\n protected useWorker: boolean\n protected wrap: boolean\n\n protected __isolevel: number\n protected __smooth: number\n protected __contour: boolean\n protected __wrap: boolean\n protected __boxSize: number\n\n setBox: () => void\n\n constructor (surface: Surface, viewer: Viewer, params: Partial) {\n super(surface, viewer, params)\n\n this.type = 'surface'\n\n this.parameters = Object.assign({\n\n isolevelType: {\n type: 'select',\n options: {\n 'value': 'value', 'sigma': 'sigma'\n }\n },\n isolevel: {\n type: 'number', precision: 2, max: 1000, min: -1000\n },\n negateIsolevel: {\n type: 'boolean'\n },\n isolevelScroll: {\n type: 'boolean'\n },\n smooth: {\n type: 'integer', precision: 1, max: 10, min: 0\n },\n background: {\n type: 'boolean', rebuild: true // FIXME\n },\n opaqueBack: {\n type: 'boolean', buffer: true\n },\n boxSize: {\n type: 'integer', precision: 1, max: 100, min: 0\n },\n colorVolume: {\n type: 'hidden'\n },\n contour: {\n type: 'boolean', rebuild: true\n },\n useWorker: {\n type: 'boolean', rebuild: true\n },\n wrap: {\n type: 'boolean', rebuild: true\n }\n\n }, this.parameters)\n\n if (surface instanceof Volume) {\n this.surface = undefined\n this.volume = surface\n } else {\n this.surface = surface\n this.volume = undefined\n }\n\n this.boxCenter = new Vector3()\n this.__boxCenter = new Vector3()\n this.box = new Box3()\n this.__box = new Box3()\n\n this._position = new Vector3()\n this.inverseMatrix = new Matrix4()\n\n this.setBox = function setBox () {\n this._position.copy(viewer.translationGroup.position).negate()\n this._position.applyMatrix4(this.inverseMatrix)\n if (!this._position.equals(this.boxCenter)) {\n this.setParameters({ 'boxCenter': this._position })\n }\n }\n\n this.toBePrepared = true\n\n this.viewer.signals.ticked.add(this.setBox, this)\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n p.colorScheme = defaults(p.colorScheme, 'uniform')\n p.colorValue = defaults(p.colorValue, 0xDDDDDD)\n\n this.isolevelType = defaults(p.isolevelType, 'sigma')\n this.isolevel = defaults(p.isolevel, 2.0)\n this.negateIsolevel = defaults(p.negateIsolevel, false)\n this.isolevelScroll = defaults(p.isolevelScroll, false)\n this.smooth = defaults(p.smooth, 0)\n this.background = defaults(p.background, false)\n this.opaqueBack = defaults(p.opaqueBack, true)\n this.boxSize = defaults(p.boxSize, 0)\n this.colorVolume = defaults(p.colorVolume, undefined)\n this.contour = defaults(p.contour, false)\n this.useWorker = defaults(p.useWorker, true)\n this.wrap = defaults(p.wrap, false)\n\n super.init(p)\n\n this.inverseMatrix.copy(this.matrix).invert()\n\n this.build()\n }\n\n attach (callback: () => void) {\n this.bufferList.forEach(buffer => {\n this.viewer.add(buffer)\n })\n\n this.setVisibility(this.visible)\n\n callback()\n }\n\n prepare (callback: () => void) {\n if (this.volume) {\n let isolevel\n\n if (this.isolevelType === 'sigma') {\n isolevel = this.volume.getValueForSigma(this.isolevel)\n } else {\n isolevel = this.isolevel\n }\n if (this.negateIsolevel) isolevel *= -1\n\n if (!this.surface ||\n this.__isolevel !== isolevel ||\n this.__smooth !== this.smooth ||\n this.__contour !== this.contour ||\n this.__wrap !== this.wrap ||\n this.__boxSize !== this.boxSize ||\n (this.boxSize > 0 &&\n !this.__boxCenter.equals(this.boxCenter))\n ) {\n this.__isolevel = isolevel\n this.__smooth = this.smooth\n this.__contour = this.contour\n this.__wrap = this.wrap\n this.__boxSize = this.boxSize\n this.__boxCenter.copy(this.boxCenter)\n this.__box.copy(this.box)\n\n const onSurfaceFinish = (surface: Surface) => {\n this.surface = surface\n callback()\n }\n\n if (this.useWorker) {\n this.volume.getSurfaceWorker(\n isolevel, this.smooth, this.boxCenter, this.boxSize,\n this.contour, this.wrap, onSurfaceFinish\n )\n } else {\n onSurfaceFinish(\n this.volume.getSurface(\n isolevel, this.smooth, this.boxCenter, this.boxSize,\n this.contour, this.wrap\n )\n )\n }\n } else {\n callback()\n }\n } else {\n callback()\n }\n }\n\n create () {\n const sd = {\n position: (this.surface as Surface).getPosition(),\n color: (this.surface as Surface).getColor(this.getColorParams()),\n index: (this.surface as Surface).getIndex()\n }\n\n let buffer\n\n if (this.contour) {\n buffer = new ContourBuffer(\n sd,\n this.getBufferParams({ wireframe: false })\n )\n } else {\n Object.assign(sd, {\n normal: (this.surface as Surface).getNormal(),\n picking: (this.surface as Surface).getPicking()\n })\n\n const surfaceBuffer = new SurfaceBuffer(\n sd,\n this.getBufferParams({\n background: this.background,\n opaqueBack: this.opaqueBack,\n dullInterior: false\n })\n )\n\n buffer = new DoubleSidedBuffer(surfaceBuffer)\n }\n\n this.bufferList.push(buffer as ContourBuffer)\n }\n\n update (what: SurfaceDataFields) {\n if (this.bufferList.length === 0) return\n\n what = what || {}\n\n const surfaceData: Partial = {}\n\n if (what.position) {\n surfaceData.position = (this.surface as Surface).getPosition()\n }\n\n if (what.color) {\n surfaceData.color = (this.surface as Surface).getColor(\n this.getColorParams()\n )\n }\n\n if (what.index) {\n surfaceData.index = (this.surface as Surface).getIndex()\n }\n\n if (what.normal) {\n surfaceData.normal = (this.surface as Surface).getNormal()\n }\n\n this.bufferList.forEach(function (buffer) {\n buffer.setAttributes(surfaceData)\n })\n }\n\n /**\n * Set representation parameters\n * @alias SurfaceRepresentation#setParameters\n * @param {SurfaceRepresentationParameters} params - surface parameter object\n * @param {Object} [what] - buffer data attributes to be updated,\n * note that this needs to be implemented in the\n * derived classes. Generally it allows more\n * fine-grained control over updating than\n * forcing a rebuild.\n * @param {Boolean} what.position - update position data\n * @param {Boolean} what.color - update color data\n * @param {Boolean} [rebuild] - whether or not to rebuild the representation\n * @return {SurfaceRepresentation} this object\n */\n setParameters (params: Partial, what?: SurfaceDataFields, rebuild?: boolean) {\n if (params && params.isolevelType !== undefined &&\n this.volume\n ) {\n if (this.isolevelType === 'value' &&\n params.isolevelType === 'sigma'\n ) {\n this.isolevel = this.volume.getSigmaForValue(this.isolevel)\n } else if (this.isolevelType === 'sigma' &&\n params.isolevelType === 'value'\n ) {\n this.isolevel = this.volume.getValueForSigma(this.isolevel)\n }\n\n this.isolevelType = params.isolevelType\n }\n\n if (params && params.boxCenter) {\n this.boxCenter.copy(params.boxCenter)\n delete params.boxCenter\n }\n\n // Forbid wireframe && contour as in molsurface\n if (params && params.wireframe && (\n params.contour || (params.contour === undefined && this.contour)\n )) {\n params.wireframe = false\n }\n\n super.setParameters(params, what, rebuild)\n\n if (params.matrix) {\n this.inverseMatrix.copy(params.matrix).invert()\n }\n\n if (this.volume) {\n this.volume.getBox(this.boxCenter, this.boxSize, this.box)\n }\n\n if (params && params.colorVolume !== undefined) {\n if (what) what.color = true\n }\n\n if (this.surface && (\n params.isolevel !== undefined ||\n params.negateIsolevel !== undefined ||\n params.smooth !== undefined ||\n params.wrap !== undefined ||\n params.boxSize !== undefined ||\n (this.boxSize > 0 &&\n !this.__box.equals(this.box))\n )) {\n this.build({\n 'position': true,\n 'color': true,\n 'index': true,\n 'normal': !this.contour\n })\n }\n\n return this\n }\n\n getColorParams () {\n const p = super.getColorParams()\n\n p.volume = this.colorVolume\n\n return p\n }\n\n dispose () {\n this.viewer.signals.ticked.remove(this.setBox, this)\n\n super.dispose()\n }\n}\n\nexport default SurfaceRepresentation\n","/**\n * @file Mouse Actions\n * @author Alexander Rose \n * @private\n */\n\nimport PickingProxy from './picking-proxy'\nimport { almostIdentity } from '../math/math-utils'\nimport Stage from '../stage/stage'\nimport StructureComponent from '../component/structure-component'\nimport SurfaceRepresentation from '../representation/surface-representation'\n\nexport type ScrollCallback = (stage: Stage, delta: number) => void\nexport type DragCallback = (stage: Stage, dx: number, dy: number) => void\nexport type PickCallback = (stage: Stage, pickingProxy: PickingProxy) => void\nexport type MouseActionCallback = ScrollCallback | DragCallback | PickCallback\n\n/**\n * Mouse actions provided as static methods\n */\nclass MouseActions {\n /**\n * Zoom scene based on scroll-delta\n * @param {Stage} stage - the stage\n * @param {Number} delta - amount to zoom\n * @return {undefined}\n */\n static zoomScroll (stage: Stage, delta: number) {\n stage.trackballControls.zoom(delta)\n }\n\n /**\n * Move near clipping plane based on scroll-delta\n * @param {Stage} stage - the stage\n * @param {Number} delta - amount to move clipping plane\n * @return {undefined}\n */\n static clipNearScroll (stage: Stage, delta: number) {\n const sp = stage.getParameters()\n stage.setParameters({ clipNear: sp.clipNear + delta / 10 })\n }\n\n /**\n * Move clipping planes based on scroll-delta.\n * @param {Stage} stage - the stage\n * @param {Number} delta - direction to move planes\n * @return {undefined}\n */\n static focusScroll (stage: Stage, delta: number) {\n const focus = stage.getFocus()\n const sign = Math.sign(delta)\n const step = sign * almostIdentity((100 - focus) / 10, 5, 0.2)\n stage.setFocus(focus + step)\n }\n\n /**\n * Zoom scene based on scroll-delta and\n * move focus planes based on camera position (zoom)\n * @param {Stage} stage - the stage\n * @param {Number} delta - amount to move focus planes and zoom\n * @return {undefined}\n */\n static zoomFocusScroll (stage: Stage, delta: number) {\n stage.trackballControls.zoom(delta)\n const z = stage.viewer.camera.position.z\n stage.setFocus(100 - Math.abs(z / 8))\n }\n\n /**\n * Change isolevel of volume surfaces based on scroll-delta\n * @param {Stage} stage - the stage\n * @param {Number} delta - amount to change isolevel\n * @return {undefined}\n */\n static isolevelScroll (stage: Stage, delta: number) {\n const d = Math.sign(delta) / 10\n stage.eachRepresentation((reprElem, comp) => {\n if (reprElem.repr instanceof SurfaceRepresentation) {\n const p = reprElem.getParameters() as any // TODO\n if (p.isolevelScroll) {\n reprElem.setParameters({ isolevel: p.isolevel + d })\n }\n }\n })\n }\n\n /**\n * Pan scene based on mouse coordinate changes\n * @param {Stage} stage - the stage\n * @param {Number} dx - amount to pan in x direction\n * @param {Number} dy - amount to pan in y direction\n * @return {undefined}\n */\n static panDrag (stage: Stage, dx: number, dy: number) {\n stage.trackballControls.pan(dx, dy)\n }\n\n /**\n * Rotate scene based on mouse coordinate changes\n * @param {Stage} stage - the stage\n * @param {Number} dx - amount to rotate in x direction\n * @param {Number} dy - amount to rotate in y direction\n * @return {undefined}\n */\n static rotateDrag (stage: Stage, dx: number, dy: number) {\n stage.trackballControls.rotate(dx, dy)\n }\n\n /**\n * Rotate scene around z axis based on mouse coordinate changes\n * @param {Stage} stage - the stage\n * @param {Number} dx - amount to rotate in x direction\n * @param {Number} dy - amount to rotate in y direction\n * @return {undefined}\n */\n static zRotateDrag (stage: Stage, dx: number, dy: number) {\n stage.trackballControls.zRotate(dx, dy)\n }\n\n /**\n * Zoom scene based on mouse coordinate changes\n * @param {Stage} stage - the stage\n * @param {Number} dx - amount to zoom\n * @param {Number} dy - amount to zoom\n * @return {undefined}\n */\n static zoomDrag (stage: Stage, dx: number, dy: number) {\n stage.trackballControls.zoom((dx + dy) / -2)\n }\n\n /**\n * Zoom scene based on mouse coordinate changes and\n * move focus planes based on camera position (zoom)\n * @param {Stage} stage - the stage\n * @param {Number} dx - amount to zoom and focus\n * @param {Number} dy - amount to zoom and focus\n * @return {undefined}\n */\n static zoomFocusDrag (stage: Stage, dx: number, dy: number) {\n stage.trackballControls.zoom((dx + dy) / -2)\n const z = stage.viewer.camera.position.z\n stage.setFocus(100 - Math.abs(z / 8))\n }\n\n /**\n * Pan picked component based on mouse coordinate changes\n * @param {Stage} stage - the stage\n * @param {Number} dx - amount to pan in x direction\n * @param {Number} dy - amount to pan in y direction\n * @return {undefined}\n */\n static panComponentDrag (stage: Stage, dx: number, dy: number) {\n stage.trackballControls.panComponent(dx, dy)\n }\n\n /**\n * Pan picked atom based on mouse coordinate changes\n * @param {Stage} stage - the stage\n * @param {Number} dx - amount to pan in x direction\n * @param {Number} dy - amount to pan in y direction\n * @return {undefined}\n */\n static panAtomDrag (stage: Stage, dx: number, dy: number) {\n stage.trackballControls.panAtom(dx, dy)\n }\n\n /**\n * Rotate picked component based on mouse coordinate changes\n * @param {Stage} stage - the stage\n * @param {Number} dx - amount to rotate in x direction\n * @param {Number} dy - amount to rotate in y direction\n * @return {undefined}\n */\n static rotateComponentDrag (stage: Stage, dx: number, dy: number) {\n stage.trackballControls.rotateComponent(dx, dy)\n }\n\n /**\n * Move picked element to the center of the screen\n * @param {Stage} stage - the stage\n * @param {PickingProxy} pickingProxy - the picking data object\n * @return {undefined}\n */\n static movePick (stage: Stage, pickingProxy: PickingProxy) {\n if (pickingProxy) {\n stage.animationControls.move(pickingProxy.position.clone())\n }\n }\n\n /**\n * Show tooltip with information of picked element\n * @param {Stage} stage - the stage\n * @param {PickingProxy} pickingProxy - the picking data object\n * @return {undefined}\n */\n static tooltipPick (stage: Stage, pickingProxy: PickingProxy) {\n const tt = stage.tooltip\n const sp = stage.getParameters() as any\n if (sp.tooltip && pickingProxy) {\n const mp = pickingProxy.mouse.position\n tt.innerText = pickingProxy.getLabel()\n tt.style.bottom = (window.innerHeight - mp.y + 3) + 'px'\n tt.style.left = (mp.x + 3) + 'px'\n tt.style.display = 'block'\n } else {\n tt.style.display = 'none'\n }\n }\n\n static measurePick (stage: Stage, pickingProxy: PickingProxy) {\n if (pickingProxy && (pickingProxy.atom || pickingProxy.bond)) {\n const atom = pickingProxy.atom || pickingProxy.closestBondAtom\n const sc = pickingProxy.component as StructureComponent\n sc.measurePick(atom)\n } else {\n stage.measureClear()\n }\n }\n}\n\ntype MouseActionPreset = [ string, MouseActionCallback ][]\nexport const MouseActionPresets = {\n default: [\n [ 'scroll', MouseActions.zoomScroll ],\n [ 'scroll-shift', MouseActions.focusScroll ],\n [ 'scroll-ctrl', MouseActions.isolevelScroll ],\n [ 'scroll-shift-ctrl', MouseActions.zoomFocusScroll ],\n\n [ 'drag-left', MouseActions.rotateDrag ],\n [ 'drag-right', MouseActions.panDrag ],\n [ 'drag-ctrl-left', MouseActions.panDrag ],\n [ 'drag-ctrl-right', MouseActions.zRotateDrag ],\n [ 'drag-shift-left', MouseActions.zoomDrag ],\n [ 'drag-middle', MouseActions.zoomFocusDrag ],\n\n [ 'drag-ctrl-shift-right', MouseActions.panComponentDrag ],\n [ 'drag-ctrl-shift-left', MouseActions.rotateComponentDrag ],\n\n [ 'clickPick-right', MouseActions.measurePick ],\n [ 'clickPick-ctrl-left', MouseActions.measurePick ],\n [ 'clickPick-middle', MouseActions.movePick ],\n [ 'clickPick-left', MouseActions.movePick ],\n [ 'hoverPick', MouseActions.tooltipPick ]\n ] as MouseActionPreset,\n pymol: [\n [ 'drag-left', MouseActions.rotateDrag ],\n [ 'drag-middle', MouseActions.panDrag ],\n [ 'drag-right', MouseActions.zoomDrag ],\n [ 'scroll', MouseActions.focusScroll ],\n [ 'drag-shift-right', MouseActions.focusScroll ],\n\n [ 'clickPick-ctrl+shift-middle', MouseActions.movePick ],\n [ 'hoverPick', MouseActions.tooltipPick ]\n ] as MouseActionPreset,\n coot: [\n [ 'scroll', MouseActions.isolevelScroll ],\n\n [ 'drag-left', MouseActions.rotateDrag ],\n [ 'drag-middle', MouseActions.panDrag ],\n [ 'drag-ctrl-left', MouseActions.panDrag ],\n [ 'drag-right', MouseActions.zoomFocusDrag ],\n [ 'drag-ctrl-right', MouseActions.focusScroll ],\n\n [ 'clickPick-middle', MouseActions.movePick ],\n [ 'hoverPick', MouseActions.tooltipPick ]\n ] as MouseActionPreset,\n astexviewer: [\n [ 'drag-left', MouseActions.rotateDrag ],\n [ 'drag-ctrl-left', MouseActions.panDrag ],\n [ 'drag-shift-left', MouseActions.zoomDrag ],\n [ 'scroll', MouseActions.focusScroll ],\n [ 'clickPick-middle', MouseActions.movePick ],\n [ 'hoverPick', MouseActions.tooltipPick ]\n ] as MouseActionPreset\n}\n\nexport default MouseActions\n","/**\n * @file Mouse Controls\n * @author Alexander Rose \n * @private\n */\n\nimport { MouseActionPresets, MouseActionCallback } from './mouse-actions'\nimport Stage from '../stage/stage'\nimport MouseObserver from '../stage/mouse-observer'\n\nexport type MouseControlPreset = keyof typeof MouseActionPresets\nexport interface MouseControlsParams {\n preset?: MouseControlPreset\n disabled?: boolean\n}\n\nexport type MouseActionType = ''|'scroll'|'drag'|'click'|'doubleClick'|'hover'|'clickPick'|'hoverPick'\nexport interface MouseAction {\n type: MouseActionType\n key: number\n button: number\n callback: MouseActionCallback\n}\n\n/**\n * Strings to describe mouse events (including optional keyboard modifiers).\n * Must contain an event type: \"scroll\", \"drag\", \"click\", \"doubleClick\",\n * \"hover\", \"clickPick\" or \"hoverPick\". Optionally contain one or more\n * (seperated by plus signs) keyboard modifiers: \"alt\", \"ctrl\", \"meta\" or\n * \"shift\". Can contain the mouse button performing the event: \"left\",\n * \"middle\" or \"right\". The type, key and button parts must be seperated by\n * dashes.\n *\n * @example\n * // triggered on scroll event (no key or button)\n * \"scroll\"\n *\n * @example\n * // triggered on scroll event while shift key is pressed\n * \"scroll-shift\"\n *\n * @example\n * // triggered on drag event with left mouse button\n * \"drag-left\"\n *\n * @example\n * // triggered on drag event with right mouse button\n * // while ctrl and shift keys are pressed\n * \"drag-right-ctrl+shift\"\n *\n * @typedef {String} TriggerString\n */\n\n/**\n * Get event type, key and button\n * @param {TriggerString} str - input trigger string\n * @return {Array} event type, key and button\n */\nfunction triggerFromString (str: string) {\n const tokens = str.split(/[-+]/)\n\n let type = ''\n if (tokens.includes('scroll')) type = 'scroll'\n if (tokens.includes('drag')) type = 'drag'\n if (tokens.includes('click')) type = 'click'\n if (tokens.includes('doubleClick')) type = 'doubleClick'\n if (tokens.includes('hover')) type = 'hover'\n if (tokens.includes('clickPick')) type = 'clickPick'\n if (tokens.includes('hoverPick')) type = 'hoverPick'\n\n let key = 0\n if (tokens.includes('alt')) key += 1\n if (tokens.includes('ctrl')) key += 2\n if (tokens.includes('meta')) key += 4\n if (tokens.includes('shift')) key += 8\n\n let button = 0\n if (tokens.includes('left')) button += 1\n if (tokens.includes('right')) button += 2\n if (tokens.includes('middle')) button += 4\n\n return [ type, key, button ] as [ MouseActionType, number, number ]\n}\n\n/**\n * Mouse controls\n */\nclass MouseControls {\n actionList: MouseAction[] = []\n mouse: MouseObserver\n\n disabled: boolean // Flag to disable all actions\n\n /**\n * @param {Stage} stage - the stage object\n * @param {Object} [params] - the parameters\n * @param {String} params.preset - one of \"default\", \"pymol\", \"coot\"\n * @param {String} params.disabled - flag to disable all actions\n */\n constructor (readonly stage: Stage, params: MouseControlsParams = {}) {\n this.mouse = stage.mouseObserver\n this.disabled = params.disabled || false\n this.preset(params.preset || 'default')\n }\n\n run (type: MouseActionType, ...args: any[]) {\n if (this.disabled) return\n\n const key = this.mouse.key || 0\n const button = this.mouse.buttons || 0\n\n this.actionList.forEach(a => {\n if (a.type === type && a.key === key && a.button === button) {\n (a.callback as any)(this.stage, ...args) // TODO\n }\n })\n }\n\n /**\n * Add a new mouse action triggered by an event, key and button combination.\n * The {@link MouseActions} class provides a number of static methods for\n * use as callback functions.\n *\n * @example\n * // change ambient light intensity on mouse scroll\n * // while the ctrl and shift keys are pressed\n * stage.mouseControls.add( \"scroll-ctrl+shift\", function( stage, delta ){\n * var ai = stage.getParameters().ambientIntensity;\n * stage.setParameters( { ambientIntensity: Math.max( 0, ai + delta / 50 ) } );\n * } );\n *\n * @example\n * // Call the MouseActions.zoomDrag method on mouse drag events\n * // with left and right mouse buttons simultaneous\n * stage.mouseControls.add( \"drag-left+right\", MouseActions.zoomDrag );\n *\n * @param {TriggerString} triggerStr - the trigger for the action\n * @param {function(stage: Stage, ...args: Any)} callback - the callback function for the action\n * @return {undefined}\n */\n add (triggerStr: string, callback: MouseActionCallback) {\n const [ type, key, button ] = triggerFromString(triggerStr)\n\n this.actionList.push({ type, key, button, callback })\n }\n\n /**\n * Remove a mouse action. The trigger string can contain an asterix (*)\n * as a wildcard for any key or mouse button. When the callback function\n * is given, only actions that call that function are removed.\n *\n * @example\n * // remove actions triggered solely by a scroll event\n * stage.mouseControls.remove( \"scroll\" );\n *\n * @example\n * // remove actions triggered by a scroll event, including\n * // those requiring a key pressed or mouse button used\n * stage.mouseControls.remove( \"scroll-*\" );\n *\n * @example\n * // remove actions triggered by a scroll event\n * // while the shift key is pressed\n * stage.mouseControls.remove( \"scroll-shift\" );\n *\n * @param {TriggerString} triggerStr - the trigger for the action\n * @param {Function} [callback] - the callback function for the action\n * @return {undefined}\n */\n remove (triggerStr: string, callback?: MouseActionCallback) {\n const wildcard = triggerStr.includes('*')\n const [ type, key, button ] = triggerFromString(triggerStr)\n\n const actionList = this.actionList.filter(function (a) {\n return !(\n (a.type === type || (wildcard && type === '')) &&\n (a.key === key || (wildcard && key === 0)) &&\n (a.button === button || (wildcard && button === 0)) &&\n (a.callback === callback || callback === undefined)\n )\n })\n\n this.actionList = actionList\n }\n\n /**\n * Set mouse action preset\n * @param {String} name - one of \"default\", \"pymol\", \"coot\"\n * @return {undefined}\n */\n preset (name: MouseControlPreset) {\n this.clear()\n\n const list = MouseActionPresets[ name ] || []\n\n list.forEach(action => this.add(action[0], action[1]))\n }\n\n /**\n * Remove all mouse actions\n * @return {undefined}\n */\n clear () {\n this.actionList.length = 0\n }\n}\n\nexport default MouseControls\n","/**\n * @file Key Actions\n * @author Alexander Rose \n * @private\n */\n\nimport Stage from '../stage/stage'\n\nexport type KeyActionCallback = (stage: Stage) => void\n\n/**\n * Key actions provided as static methods\n */\nclass KeyActions {\n /**\n * Stage auto view\n */\n static autoView (stage: Stage) {\n stage.autoView(1000)\n }\n\n /**\n * Toggle stage animations\n */\n static toggleAnimations (stage: Stage) {\n stage.animationControls.toggle()\n }\n\n /**\n * Toggle stage rocking\n */\n static toggleRock (stage: Stage) {\n stage.toggleRock()\n }\n\n /**\n * Toggle stage spinning\n */\n static toggleSpin (stage: Stage) {\n stage.toggleSpin()\n }\n\n /**\n * Toggle anti-aliasing\n */\n static toggleAntialiasing (stage: Stage) {\n const p = stage.getParameters()\n stage.setParameters({ sampleLevel: p.sampleLevel === -1 ? 0 : -1 })\n }\n}\n\ntype KeyActionPreset = [ string, KeyActionCallback ][]\nexport const KeyActionPresets = {\n default: [\n [ 'i', KeyActions.toggleSpin ],\n [ 'k', KeyActions.toggleRock ],\n [ 'p', KeyActions.toggleAnimations ],\n [ 'a', KeyActions.toggleAntialiasing ],\n [ 'r', KeyActions.autoView ]\n ] as KeyActionPreset\n}\n\nexport default KeyActions\n","/**\n * @file Key Controls\n * @author Alexander Rose \n * @private\n */\n\nimport { KeyActionPresets, KeyActionCallback } from './key-actions'\nimport Stage from '../stage/stage'\n\nexport type KeyControlPreset = keyof typeof KeyActionPresets\nexport interface KeyControlsParams {\n preset?: KeyControlPreset\n disabled?: boolean\n}\n\nexport interface KeyAction {\n key: string,\n callback: KeyActionCallback\n}\n\n/**\n * Mouse controls\n */\nclass KeyControls {\n actionList: KeyAction[] = []\n\n disabled: boolean // Flag to disable all actions\n\n /**\n * @param {Stage} stage - the stage object\n * @param {Object} [params] - the parameters\n * @param {String} params.preset - one of \"default\"\n * @param {String} params.disabled - flag to disable all actions\n */\n constructor (readonly stage: Stage, params: KeyControlsParams = {}) {\n this.disabled = params.disabled || false\n this.preset(params.preset || 'default')\n }\n\n run (key: string) {\n if (this.disabled) return\n\n this.actionList.forEach(a => {\n if (a.key === key) {\n a.callback(this.stage)\n }\n })\n }\n\n /**\n * Add a key action triggered by pressing the given character.\n * The {@link KeyActions} class provides a number of static methods for\n * use as callback functions.\n *\n * @example\n * // call KeyActions.toggleRock when \"k\" is pressed\n * stage.keyControls.remove( \"k\", KeyActions.toggleRock );\n *\n * @param {Char} char - the key/character\n * @param {Function} callback - the callback function for the action\n * @return {undefined}\n */\n add (char: string, callback: KeyActionCallback) {\n this.actionList.push({ key: char, callback })\n }\n\n /**\n * Remove a key action. When the callback function\n * is given, only actions that call that function are removed.\n *\n * @example\n * // remove all actions triggered by pressing \"k\"\n * stage.keyControls.remove( \"k\" );\n *\n * @example\n * // remove action `toggleRock` triggered by pressing \"k\"\n * stage.keyControls.remove( \"k\", toggleRock );\n *\n * @param {Char} char - the key/character\n * @param {Function} [callback] - the callback function for the action\n * @return {undefined}\n */\n remove (char: string, callback: KeyActionCallback) {\n\n const actionList = this.actionList.filter(function (a) {\n return !(\n (a.key === char) &&\n (a.callback === callback || callback === undefined)\n )\n })\n\n this.actionList = actionList\n }\n\n /**\n * Set key action preset\n * @param {String} name - one of \"default\"\n * @return {undefined}\n */\n preset (name: KeyControlPreset) {\n this.clear()\n\n const list = KeyActionPresets[ name ] || []\n\n list.forEach(action => this.add(action[0], action[1]))\n }\n\n /**\n * Remove all key actions\n * @return {undefined}\n */\n clear () {\n this.actionList.length = 0\n }\n}\n\nexport default KeyControls\n","/**\n * @file Picking Behavior\n * @author Alexander Rose \n * @private\n */\n\nimport Stage from './stage'\nimport MouseObserver from './mouse-observer'\nimport Viewer from '../viewer/viewer'\nimport MouseControls from '../controls/mouse-controls'\n\nclass PickingBehavior {\n viewer: Viewer\n mouse: MouseObserver\n controls: MouseControls\n\n constructor (readonly stage: Stage) {\n this.stage = stage\n this.mouse = stage.mouseObserver\n this.controls = stage.mouseControls\n\n this.mouse.signals.clicked.add(this._onClick, this)\n this.mouse.signals.hovered.add(this._onHover, this)\n }\n\n _onClick (x: number, y: number) {\n const pickingProxy = this.stage.pickingControls.pick(x, y)\n this.stage.signals.clicked.dispatch(pickingProxy)\n this.controls.run('clickPick', pickingProxy)\n }\n\n _onHover (x: number, y: number) {\n const pickingProxy = this.stage.pickingControls.pick(x, y)\n if (pickingProxy && this.mouse.down.equals(this.mouse.position)) {\n this.stage.transformComponent = pickingProxy.component\n this.stage.transformAtom = pickingProxy.atom\n }\n this.stage.signals.hovered.dispatch(pickingProxy)\n this.controls.run('hoverPick', pickingProxy)\n }\n\n dispose () {\n this.mouse.signals.clicked.remove(this._onClick, this)\n this.mouse.signals.hovered.remove(this._onHover, this)\n }\n}\n\nexport default PickingBehavior\n","/**\n * @file Mouse Behavior\n * @author Alexander Rose \n * @private\n */\n\nimport Stage from './stage'\nimport MouseObserver from './mouse-observer'\nimport Viewer from '../viewer/viewer'\nimport MouseControls from '../controls/mouse-controls'\n\nclass MouseBehavior {\n viewer: Viewer\n mouse: MouseObserver\n controls: MouseControls\n domElement: HTMLCanvasElement\n\n constructor (readonly stage: Stage) {\n this.stage = stage\n this.mouse = stage.mouseObserver\n this.controls = stage.mouseControls\n\n this.mouse.signals.moved.add(this._onMove, this)\n this.mouse.signals.scrolled.add(this._onScroll, this)\n this.mouse.signals.dragged.add(this._onDrag, this)\n this.mouse.signals.clicked.add(this._onClick, this)\n this.mouse.signals.hovered.add(this._onHover, this)\n this.mouse.signals.doubleClicked.add(this._onDblclick, this)\n }\n\n _onMove (/* x, y */) {\n this.stage.tooltip.style.display = 'none'\n }\n\n _onScroll (delta: number) {\n this.controls.run('scroll', delta)\n }\n\n _onDrag (dx: number, dy: number) {\n this.controls.run('drag', dx, dy)\n }\n\n _onClick (x: number, y: number) {\n this.controls.run('click', x, y)\n }\n\n _onDblclick (x: number, y: number) {\n this.controls.run('doubleClick', x, y)\n }\n\n _onHover (x: number, y: number) {\n this.controls.run('hover', x, y)\n }\n\n dispose () {\n this.mouse.signals.moved.remove(this._onMove, this)\n this.mouse.signals.scrolled.remove(this._onScroll, this)\n this.mouse.signals.dragged.remove(this._onDrag, this)\n this.mouse.signals.clicked.remove(this._onClick, this)\n this.mouse.signals.hovered.remove(this._onHover, this)\n }\n}\n\nexport default MouseBehavior\n","/**\n * @file Animation Behavior\n * @author Alexander Rose \n * @private\n */\n\nimport Stage from './stage'\nimport Viewer from '../viewer/viewer'\nimport Stats from '../viewer/stats'\nimport AnimationControls from '../controls/animation-controls'\n\nclass AnimationBehavior {\n viewer: Viewer\n animationControls: AnimationControls\n\n constructor (readonly stage: Stage) {\n this.viewer = stage.viewer\n this.animationControls = stage.animationControls\n\n this.viewer.signals.ticked.add(this._onTick, this)\n }\n\n _onTick (stats: Stats) {\n this.animationControls.run(stats)\n }\n\n dispose () {\n this.viewer.signals.ticked.remove(this._onTick, this)\n }\n}\n\nexport default AnimationBehavior\n","/**\n * @file Key Behavior\n * @author Alexander Rose \n * @private\n */\n\nimport { SupportsPassiveEventHandler } from '../globals'\nimport Stage from './stage'\nimport Viewer from '../viewer/viewer'\nimport KeyControls from '../controls/key-controls'\n\nconst passive = SupportsPassiveEventHandler ? { passive: true } : false\n\nclass KeyBehavior {\n viewer: Viewer\n controls: KeyControls\n domElement: HTMLCanvasElement\n\n /**\n * @param {Stage} stage - the stage object\n */\n constructor (readonly stage: Stage) {\n this.stage = stage\n this.controls = stage.keyControls\n this.domElement = stage.viewer.renderer.domElement\n\n // ensure the domElement is focusable\n this.domElement.setAttribute('tabIndex', '-1')\n this.domElement.style.outline = 'none'\n\n this._focusDomElement = this._focusDomElement.bind(this)\n this._onKeydown = this._onKeydown.bind(this)\n this._onKeyup = this._onKeyup.bind(this)\n this._onKeypress = this._onKeypress.bind(this)\n\n this.domElement.addEventListener('mousedown', this._focusDomElement)\n this.domElement.addEventListener('touchstart', this._focusDomElement, passive as any) // TODO\n this.domElement.addEventListener('keydown', this._onKeydown)\n this.domElement.addEventListener('keyup', this._onKeyup)\n this.domElement.addEventListener('keypress', this._onKeypress)\n }\n\n /**\n * handle key down\n * @param {Event} event - key event\n * @return {undefined}\n */\n _onKeydown (/* event */) {\n // console.log( \"down\", event.keyCode, String.fromCharCode( event.keyCode ) );\n }\n\n /**\n * handle key up\n * @param {Event} event - key event\n * @return {undefined}\n */\n _onKeyup (/* event */) {\n // console.log( \"up\", event.keyCode, String.fromCharCode( event.keyCode ) );\n }\n\n /**\n * handle key press\n * @param {Event} event - key event\n * @return {undefined}\n */\n _onKeypress (event: KeyboardEvent) {\n // console.log( \"press\", event.keyCode, String.fromCharCode( event.keyCode ) );\n let pressedKey: string;\n if (\"key\" in KeyboardEvent.prototype) {\n pressedKey = event.key;\n // some mobile browsers don't support this attribute\n } else {\n pressedKey = String.fromCharCode(event.which || event.keyCode);\n }\n this.controls.run(pressedKey);\n }\n\n _focusDomElement () {\n this.domElement.focus()\n }\n\n dispose () {\n this.domElement.removeEventListener('mousedown', this._focusDomElement)\n this.domElement.removeEventListener('touchstart', this._focusDomElement, passive as any) // TODO\n this.domElement.removeEventListener('keydown', this._onKeypress)\n this.domElement.removeEventListener('keyup', this._onKeypress)\n this.domElement.removeEventListener('keypress', this._onKeypress)\n }\n}\n\nexport default KeyBehavior\n","/**\n * @file Annotation\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector2, Vector3 } from 'three'\n\nimport { defaults } from '../utils'\nimport { smoothstep } from '../math/math-utils'\nimport Stage from '../stage/stage'\nimport Viewer from '../viewer/viewer'\nimport Component from './component'\n\nexport interface AnnotationParams {\n offsetX?: number\n offsetY?: number\n visible?: boolean\n}\n\n/**\n * Annotation HTML element floating on top of a position rendered in 3d\n */\nexport default class Annotation {\n offsetX: number\n offsetY: number\n visible: boolean\n\n stage: Stage\n viewer: Viewer\n element: HTMLElement\n\n private _viewerPosition: Vector3\n private _canvasPosition: Vector2\n private _cameraPosition: Vector3\n private _clientRect: ClientRect\n\n /**\n * @param {Component} component - the associated component\n * @param {Vector3} position - position in 3d\n * @param {String|Element} content - HTML content\n * @param {Object} [params] - parameters\n * @param {Integer} params.offsetX - 2d offset in x direction\n * @param {Integer} params.offsetY - 2d offset in y direction\n * @param {Boolean} params.visible - visibility flag\n */\n constructor (readonly component: Component, readonly position: Vector3, content: string|HTMLElement, params: AnnotationParams = {}) {\n this.offsetX = defaults(params.offsetX, 0)\n this.offsetY = defaults(params.offsetY, 0)\n this.visible = defaults(params.visible, true)\n\n this.stage = component.stage\n this.viewer = component.stage.viewer\n\n this._viewerPosition = new Vector3()\n this._updateViewerPosition()\n this._canvasPosition = new Vector2()\n this._cameraPosition = new Vector3()\n\n this.element = document.createElement('div')\n Object.assign(this.element.style, {\n display: 'block',\n position: 'absolute',\n pointerEvents: 'none',\n whiteSpace: 'nowrap',\n left: '-10000px'\n })\n\n this.viewer.wrapper.appendChild(this.element)\n this.setContent(content)\n this.updateVisibility()\n this.viewer.signals.rendered.add(this._update, this)\n this.component.signals.matrixChanged.add(this._updateViewerPosition, this)\n }\n\n /**\n * Set HTML content of the annotation\n * @param {String|Element} value - HTML content\n * @return {undefined}\n */\n setContent (value: string|HTMLElement) {\n const displayValue = this.element.style.display\n if (displayValue === 'none') {\n this.element.style.left = '-10000px'\n this.element.style.display = 'block'\n }\n\n if (value instanceof HTMLElement) {\n this.element.appendChild(value)\n } else {\n const content = document.createElement('div')\n content.innerText = value\n Object.assign(content.style, {\n backgroundColor: 'rgba( 0, 0, 0, 0.6 )',\n color: 'lightgrey',\n padding: '8px',\n fontFamily: 'sans-serif',\n })\n this.element.appendChild(content)\n }\n\n this._clientRect = this.element.getBoundingClientRect()\n\n if (displayValue === 'none') {\n this.element.style.display = displayValue\n }\n }\n\n /**\n * Set visibility of the annotation\n * @param {Boolean} value - visibility flag\n * @return {undefined}\n */\n setVisibility (value: boolean) {\n this.visible = value\n this.updateVisibility()\n }\n\n getVisibility () {\n return this.visible && this.component.parameters.visible\n }\n\n updateVisibility () {\n this.element.style.display = this.getVisibility() ? 'block' : 'none'\n }\n\n _updateViewerPosition () {\n this._viewerPosition\n .copy(this.position)\n .applyMatrix4(this.component.matrix)\n }\n\n _update () {\n if (!this.getVisibility()) return\n\n const s = this.element.style\n const cp = this._canvasPosition\n const vp = this._viewerPosition\n const cr = this._clientRect\n\n this._cameraPosition.copy(vp)\n .add(this.viewer.translationGroup.position)\n .applyMatrix4(this.viewer.rotationGroup.matrix)\n .sub(this.viewer.camera.position)\n\n if (this._cameraPosition.z < 0) {\n s.display = 'none'\n return\n } else {\n s.display = 'block'\n }\n\n const depth = this._cameraPosition.length()\n const fog = this.viewer.scene.fog as any // TODO\n\n s.opacity = (1 - smoothstep(fog.near, fog.far, depth)).toString()\n s.zIndex = (Math.round((fog.far - depth) * 100)).toString()\n\n this.stage.viewerControls.getPositionOnCanvas(vp, cp)\n\n s.bottom = (this.offsetX + cp.y + cr.height / 2) + 'px'\n s.left = (this.offsetY + cp.x - cr.width / 2) + 'px'\n }\n\n /**\n * Safely remove the annotation\n * @return {undefined}\n */\n dispose () {\n this.viewer.wrapper.removeChild(this.element)\n this.viewer.signals.ticked.remove(this._update, this)\n this.component.signals.matrixChanged.remove(this._updateViewerPosition, this)\n }\n}","/**\n * @file Component Controls\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Matrix4, Quaternion } from 'three'\nimport * as signalsWrapper from 'signals'\n\nimport { ensureVector3 } from '../utils'\nimport Component from '../component/component'\nimport Stage from '../stage/stage'\nimport Viewer from '../viewer/viewer'\n\nconst tmpRotateMatrix = new Matrix4()\nconst tmpRotateVector = new Vector3()\nconst tmpRotateQuaternion = new Quaternion()\n\n/**\n * Component controls\n */\nclass ComponentControls {\n signals = {\n changed: new signalsWrapper.Signal()\n }\n\n stage: Stage\n viewer: Viewer\n\n /**\n * @param {Component} component - the component object\n */\n constructor (readonly component: Component) {\n this.stage = component.stage\n this.viewer = component.stage.viewer\n }\n\n /**\n * component center position\n * @type {Vector3}\n */\n get position () {\n return this.component.position\n }\n\n /**\n * component rotation\n * @type {Quaternion}\n */\n get rotation () {\n return this.component.quaternion\n }\n\n /**\n * Trigger render and emit changed event\n * @emits {ComponentControls.signals.changed}\n * @return {undefined}\n */\n changed () {\n this.component.updateMatrix()\n this.viewer.requestRender()\n this.signals.changed.dispatch()\n }\n\n /**\n * spin component on axis\n * @param {Vector3|Array} axis - rotation axis\n * @param {Number} angle - amount to spin\n * @return {undefined}\n */\n spin (axis: Vector3, angle: number) {\n tmpRotateMatrix.copy(this.viewer.rotationGroup.matrix).invert()\n tmpRotateVector\n .copy(ensureVector3(axis)).applyMatrix4(tmpRotateMatrix)\n\n tmpRotateMatrix.extractRotation(this.component.transform)\n tmpRotateMatrix.premultiply(this.viewer.rotationGroup.matrix)\n tmpRotateMatrix.invert()\n\n tmpRotateVector.copy(ensureVector3(axis))\n tmpRotateVector.applyMatrix4(tmpRotateMatrix)\n tmpRotateMatrix.makeRotationAxis(tmpRotateVector, angle)\n tmpRotateQuaternion.setFromRotationMatrix(tmpRotateMatrix)\n\n this.component.quaternion.premultiply(tmpRotateQuaternion)\n this.changed()\n }\n}\n\nexport default ComponentControls\n","/**\n * @file Radius Factory\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport { NucleicBackboneAtoms } from '../structure/structure-constants'\nimport AtomProxy from '../proxy/atom-proxy'\n\nexport const RadiusFactoryTypes = {\n '': '',\n 'vdw': 'by vdW radius',\n 'covalent': 'by covalent radius',\n 'sstruc': 'by secondary structure',\n 'bfactor': 'by bfactor',\n 'size': 'size',\n 'data': 'data',\n 'explicit' : 'explicit'\n}\nexport type RadiusType = keyof typeof RadiusFactoryTypes\n\nexport interface RadiusParams {\n type?: RadiusType\n scale?: number\n size?: number\n data?: { [k: number]: number }\n}\n\nclass RadiusFactory {\n max = 10\n\n static types = RadiusFactoryTypes\n\n readonly type: RadiusType\n readonly scale: number\n readonly size: number\n readonly data: { [k: number]: number }\n\n constructor (params: RadiusParams = {}) {\n this.type = defaults(params.type, 'size')\n this.scale = defaults(params.scale, 1)\n this.size = defaults(params.size, 1)\n this.data = defaults(params.data, {})\n }\n\n atomRadius (a: AtomProxy) {\n let r\n\n switch (this.type) {\n case 'vdw':\n r = a.vdw\n break\n\n case 'covalent':\n r = a.covalent\n break\n\n case 'bfactor':\n r = a.bfactor || 1.0\n break\n\n case 'sstruc':\n const sstruc = a.sstruc\n if (sstruc === 'h') {\n r = 0.25\n } else if (sstruc === 'g') {\n r = 0.25\n } else if (sstruc === 'i') {\n r = 0.25\n } else if (sstruc === 'e') {\n r = 0.25\n } else if (sstruc === 'b') {\n r = 0.25\n } else if (NucleicBackboneAtoms.includes(a.atomname)) {\n r = 0.4\n } else {\n r = 0.1\n }\n break\n\n case 'data':\n r = defaults(this.data[ a.index ], 1.0)\n break\n\n case 'explicit':\n // defaults is inappropriate as AtomProxy.radius returns\n // null for missing radii\n r = a.radius\n if (r === null) r = this.size\n break\n\n default:\n r = this.size\n break\n }\n\n return Math.min(r * this.scale, this.max)\n }\n\n}\n\nexport default RadiusFactory\n","/**\n * @file Principal Axes\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Matrix4, Quaternion } from 'three'\n\nimport {\n Matrix, meanRows, subRows, transpose, multiplyABt, svd\n} from './matrix-utils'\nimport { projectPointOnVector } from './vector-utils'\nimport Structure from '../structure/structure'\nimport AtomProxy from '../proxy/atom-proxy'\n\nconst negateVector = new Vector3(-1, -1, -1)\nconst tmpMatrix = new Matrix4()\n\n/**\n * Principal axes\n */\nclass PrincipalAxes {\n begA: Vector3\n endA: Vector3\n begB: Vector3\n endB: Vector3\n begC: Vector3\n endC: Vector3\n\n center: Vector3\n\n vecA: Vector3\n vecB: Vector3\n vecC: Vector3\n\n normVecA: Vector3\n normVecB: Vector3\n normVecC: Vector3\n\n /**\n * @param {Matrix} points - 3 by N matrix\n */\n constructor (points: Matrix) {\n // console.time( \"PrincipalAxes\" );\n\n const n = points.rows\n const n3 = n / 3\n const pointsT = new Matrix(n, 3)\n const A = new Matrix(3, 3)\n const W = new Matrix(1, 3)\n const U = new Matrix(3, 3)\n const V = new Matrix(3, 3)\n\n // calculate\n const mean = meanRows(points)\n subRows(points, mean)\n transpose(pointsT, points)\n multiplyABt(A, pointsT, pointsT)\n svd(A, W, U, V)\n\n // console.log( points, pointsT, mean )\n // console.log( n, A, W, U, V );\n\n // center\n const vm = new Vector3(mean[0], mean[1], mean[2])\n\n // normalized\n const van = new Vector3(U.data[0], U.data[3], U.data[6])\n const vbn = new Vector3(U.data[1], U.data[4], U.data[7])\n const vcn = new Vector3(U.data[2], U.data[5], U.data[8])\n\n // scaled\n const va = van.clone().multiplyScalar(Math.sqrt(W.data[0] / n3))\n const vb = vbn.clone().multiplyScalar(Math.sqrt(W.data[1] / n3))\n const vc = vcn.clone().multiplyScalar(Math.sqrt(W.data[2] / n3))\n\n // points\n this.begA = vm.clone().sub(va)\n this.endA = vm.clone().add(va)\n this.begB = vm.clone().sub(vb)\n this.endB = vm.clone().add(vb)\n this.begC = vm.clone().sub(vc)\n this.endC = vm.clone().add(vc)\n\n //\n\n this.center = vm\n\n this.vecA = va\n this.vecB = vb\n this.vecC = vc\n\n this.normVecA = van\n this.normVecB = vbn\n this.normVecC = vcn\n\n // console.timeEnd( \"PrincipalAxes\" );\n }\n\n /**\n * Get the basis matrix descriping the axes\n * @param {Matrix4} [optionalTarget] - target object\n * @return {Matrix4} the basis\n */\n getBasisMatrix (optionalTarget = new Matrix4()) {\n const basis = optionalTarget\n\n basis.makeBasis(this.normVecB, this.normVecA, this.normVecC)\n if (basis.determinant() < 0) {\n basis.scale(negateVector)\n }\n\n return basis\n }\n\n /**\n * Get a quaternion descriping the axes rotation\n * @param {Quaternion} [optionalTarget] - target object\n * @return {Quaternion} the rotation\n */\n getRotationQuaternion (optionalTarget = new Quaternion()) {\n const q = optionalTarget\n q.setFromRotationMatrix(this.getBasisMatrix(tmpMatrix))\n\n return q.invert()\n }\n\n /**\n * Get the scale/length for each dimension for a box around the axes\n * to enclose the atoms of a structure\n * @param {Structure|StructureView} structure - the structure\n * @return {{d1a: Number, d2a: Number, d3a: Number, d1b: Number, d2b: Number, d3b: Number}} scale\n */\n getProjectedScaleForAtoms (structure: Structure) {\n let d1a = -Infinity\n let d1b = -Infinity\n let d2a = -Infinity\n let d2b = -Infinity\n let d3a = -Infinity\n let d3b = -Infinity\n\n const p = new Vector3()\n const t = new Vector3()\n\n const center = this.center\n const ax1 = this.normVecA\n const ax2 = this.normVecB\n const ax3 = this.normVecC\n\n structure.eachAtom(function (ap: AtomProxy) {\n projectPointOnVector(p.copy(ap as any), ax1, center) // TODO\n const dp1 = t.subVectors(p, center).normalize().dot(ax1)\n const dt1 = p.distanceTo(center)\n if (dp1 > 0) {\n if (dt1 > d1a) d1a = dt1\n } else {\n if (dt1 > d1b) d1b = dt1\n }\n\n projectPointOnVector(p.copy(ap as any), ax2, center)\n const dp2 = t.subVectors(p, center).normalize().dot(ax2)\n const dt2 = p.distanceTo(center)\n if (dp2 > 0) {\n if (dt2 > d2a) d2a = dt2\n } else {\n if (dt2 > d2b) d2b = dt2\n }\n\n projectPointOnVector(p.copy(ap as any), ax3, center)\n const dp3 = t.subVectors(p, center).normalize().dot(ax3)\n const dt3 = p.distanceTo(center)\n if (dp3 > 0) {\n if (dt3 > d3a) d3a = dt3\n } else {\n if (dt3 > d3b) d3b = dt3\n }\n })\n\n return {\n d1a: d1a,\n d2a: d2a,\n d3a: d3a,\n d1b: -d1b,\n d2b: -d2b,\n d3b: -d3b\n }\n }\n}\n\nexport default PrincipalAxes\n","/**\n * @file Filtered Volume\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport Volume from './volume'\nimport { Box3, Matrix4, Matrix3, Vector3 } from 'three';\n\nclass FilteredVolume {\n volume: Volume\n data: Float32Array\n position: Float32Array\n atomindex: Int32Array\n _filterHash: string\n _dataBuffer: ArrayBuffer\n _positionBuffer: ArrayBuffer\n _atomindexBuffer: ArrayBuffer\n getValueForSigma: typeof Volume.prototype.getValueForSigma\n getSigmaForValue: typeof Volume.prototype.getSigmaForValue\n getDataAtomindex: typeof Volume.prototype.getDataAtomindex\n getDataPosition: typeof Volume.prototype.getDataPosition\n getDataColor: typeof Volume.prototype.getDataColor\n getDataPicking: typeof Volume.prototype.getDataPicking\n getDataSize: typeof Volume.prototype.getDataSize\n\n\n constructor (volume: Volume, minValue?: number, maxValue?: number, outside?: boolean) {\n this.volume = volume\n this.setFilter(minValue, maxValue, outside)\n }\n\n get header () { return this.volume.header }\n get matrix (): Matrix4 { return this.volume.matrix }\n get normalMatrix (): Matrix3 { return this.volume.normalMatrix }\n get inverseMatrix (): Matrix4 { return this.volume.inverseMatrix }\n get center (): Vector3 { return this.volume.center }\n get boundingBox (): Box3 { return this.volume.boundingBox }\n get min () { return this.volume.min }\n get max () { return this.volume.max }\n get mean () { return this.volume.mean }\n get rms () { return this.volume.rms }\n\n _getFilterHash (minValue: number, maxValue: number, outside: boolean) {\n return JSON.stringify([ minValue, maxValue, outside ])\n }\n\n setFilter (minValue: number|undefined, maxValue: number|undefined, outside: boolean|undefined) {\n if (isNaN(minValue) && this.header) {\n minValue = this.header.DMEAN + 2.0 * this.header.ARMS\n }\n\n minValue = (minValue !== undefined && !isNaN(minValue)) ? minValue : -Infinity\n maxValue = defaults(maxValue, Infinity) as number\n outside = defaults(outside, false) as boolean\n\n const data = this.volume.data\n const position = this.volume.position\n const atomindex = this.volume.atomindex\n\n const filterHash = this._getFilterHash(minValue, maxValue, outside)\n\n if (filterHash === this._filterHash) {\n // already filtered\n return\n } else if (minValue === -Infinity && maxValue === Infinity) {\n this.data = data\n this.position = position\n this.atomindex = atomindex!\n } else {\n const n = data.length\n\n if (!this._dataBuffer) {\n // ArrayBuffer for re-use as Float32Array backend\n\n this._dataBuffer = new ArrayBuffer(n * 4)\n this._positionBuffer = new ArrayBuffer(n * 3 * 4)\n if (atomindex) this._atomindexBuffer = new ArrayBuffer(n * 4)\n }\n\n const filteredData = new Float32Array(this._dataBuffer)\n const filteredPosition = new Float32Array(this._positionBuffer)\n let filteredAtomindex\n if (atomindex) filteredAtomindex = new Uint32Array(this._atomindexBuffer)\n\n let j = 0\n\n for (let i = 0; i < n; ++i) {\n const i3 = i * 3\n const v = data[ i ]\n\n if ((!outside && v >= minValue && v <= maxValue) ||\n (outside && (v < minValue || v > maxValue))\n ) {\n const j3 = j * 3\n\n filteredData[ j ] = v\n\n filteredPosition[ j3 + 0 ] = position[ i3 + 0 ]\n filteredPosition[ j3 + 1 ] = position[ i3 + 1 ]\n filteredPosition[ j3 + 2 ] = position[ i3 + 2 ]\n\n if (atomindex && filteredAtomindex) filteredAtomindex[ j ] = atomindex[ i ]\n\n j += 1\n }\n }\n\n // set views\n\n this.data = new Float32Array(this._dataBuffer, 0, j)\n this.position = new Float32Array(this._positionBuffer, 0, j * 3)\n if (atomindex) this.atomindex = new Int32Array(this._atomindexBuffer, 0, j)\n }\n\n this._filterHash = filterHash\n }\n}\n\nFilteredVolume.prototype.getValueForSigma = Volume.prototype.getValueForSigma\nFilteredVolume.prototype.getSigmaForValue = Volume.prototype.getSigmaForValue\n\nFilteredVolume.prototype.getDataAtomindex = Volume.prototype.getDataAtomindex\nFilteredVolume.prototype.getDataPosition = Volume.prototype.getDataPosition\nFilteredVolume.prototype.getDataColor = Volume.prototype.getDataColor\nFilteredVolume.prototype.getDataPicking = Volume.prototype.getDataPicking\nFilteredVolume.prototype.getDataSize = Volume.prototype.getDataSize\n\nexport default FilteredVolume\n","/**\n * @file Bond Hash\n * @author Alexander Rose \n * @private\n */\n\nimport BondStore from './bond-store'\nimport { createAdjacencyList } from '../utils/adjacency-list'\n\nclass BondHash {\n countArray: Uint8Array\n offsetArray: Int32Array\n indexArray: Int32Array\n\n constructor (bondStore: BondStore, atomCount: number) {\n const al = createAdjacencyList({\n nodeArray1: bondStore.atomIndex1,\n nodeArray2: bondStore.atomIndex2,\n edgeCount: bondStore.count,\n nodeCount: atomCount\n })\n\n this.countArray = al.countArray\n this.offsetArray = al.offsetArray\n this.indexArray = al.indexArray\n }\n}\n\nexport default BondHash\n","/**\n * @file Bond Store\n * @author Alexander Rose \n * @private\n */\n\nimport Store, { StoreField } from './store'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Bond store\n */\nexport default class BondStore extends Store {\n atomIndex1: Uint32Array\n atomIndex2: Uint32Array\n bondOrder: Uint8Array\n\n get _defaultFields () {\n return [\n [ 'atomIndex1', 1, 'int32' ],\n [ 'atomIndex2', 1, 'int32' ],\n [ 'bondOrder', 1, 'int8' ]\n ] as StoreField[]\n }\n\n addBond (atom1: AtomProxy, atom2: AtomProxy, bondOrder?: number) {\n this.growIfFull()\n\n const i = this.count\n const ai1 = atom1.index\n const ai2 = atom2.index\n\n if (ai1 < ai2) {\n this.atomIndex1[ i ] = ai1\n this.atomIndex2[ i ] = ai2\n } else {\n this.atomIndex2[ i ] = ai1\n this.atomIndex1[ i ] = ai2\n }\n if (bondOrder) this.bondOrder[ i ] = bondOrder\n\n this.count += 1\n }\n\n addBondIfConnected (atom1: AtomProxy, atom2: AtomProxy, bondOrder?: number) {\n if (atom1.connectedTo(atom2)) {\n this.addBond(atom1, atom2, bondOrder)\n return true\n }\n\n return false\n }\n}","/**\n * @file Atom Store\n * @author Alexander Rose \n * @private\n */\n\nimport Store, { StoreField } from './store'\n\n/**\n * Atom store\n */\nexport default class AtomStore extends Store {\n residueIndex: Uint32Array\n atomTypeId: Uint16Array\n\n x: Float32Array\n y: Float32Array\n z: Float32Array\n serial: Int32Array\n bfactor: Float32Array\n altloc: Uint8Array\n occupancy: Float32Array\n\n partialCharge?: Float32Array\n formalCharge?: Int8Array\n\n get _defaultFields () {\n return [\n [ 'residueIndex', 1, 'uint32' ],\n [ 'atomTypeId', 1, 'uint16' ],\n\n [ 'x', 1, 'float32' ],\n [ 'y', 1, 'float32' ],\n [ 'z', 1, 'float32' ],\n [ 'serial', 1, 'int32' ],\n [ 'bfactor', 1, 'float32' ],\n [ 'altloc', 1, 'uint8' ],\n [ 'occupancy', 1, 'float32' ]\n ] as StoreField[]\n }\n\n setAltloc (i: number, str: string) {\n this.altloc[ i ] = str.charCodeAt(0)\n }\n\n getAltloc (i: number) {\n const code = this.altloc[ i ]\n return code ? String.fromCharCode(code) : ''\n }\n}","/**\n * @file Residue Store\n * @author Alexander Rose \n * @private\n */\n\nimport Store, { StoreField } from './store'\n\n/**\n * Residue store\n */\nexport default class ResidueStore extends Store {\n chainIndex: Uint32Array\n atomOffset: Uint32Array\n atomCount: Uint32Array\n residueTypeId: Uint16Array\n\n resno: Uint32Array\n sstruc: Uint8Array\n inscode: Uint8Array\n\n get _defaultFields () {\n return [\n [ 'chainIndex', 1, 'uint32' ],\n [ 'atomOffset', 1, 'uint32' ],\n [ 'atomCount', 1, 'uint32' ],\n [ 'residueTypeId', 1, 'uint16' ],\n\n [ 'resno', 1, 'int32' ],\n [ 'sstruc', 1, 'uint8' ],\n [ 'inscode', 1, 'uint8' ]\n ] as StoreField[]\n }\n\n setSstruc (i: number, str: string) {\n this.sstruc[ i ] = str.charCodeAt(0)\n }\n\n getSstruc (i: number) {\n const code = this.sstruc[ i ]\n return code ? String.fromCharCode(code) : ''\n }\n\n setInscode (i: number, str: string) {\n this.inscode[ i ] = str.charCodeAt(0)\n }\n\n getInscode (i: number) {\n const code = this.inscode[ i ]\n return code ? String.fromCharCode(code) : ''\n }\n}","/**\n * @file Chain Store\n * @author Alexander Rose \n * @private\n */\n\nimport Store, { StoreField } from './store'\n\n/**\n * Chain store\n */\nexport default class ChainStore extends Store {\n entityIndex: Uint16Array\n modelIndex: Uint16Array\n residueOffset: Uint32Array\n residueCount: Uint32Array\n\n chainname: Uint8Array\n chainid: Uint8Array\n\n get _defaultFields () {\n return [\n [ 'entityIndex', 1, 'uint16' ],\n [ 'modelIndex', 1, 'uint16' ],\n [ 'residueOffset', 1, 'uint32' ],\n [ 'residueCount', 1, 'uint32' ],\n\n [ 'chainname', 4, 'uint8' ],\n [ 'chainid', 4, 'uint8' ]\n ] as StoreField[]\n }\n\n setChainname (i: number, str: string) {\n const j = 4 * i\n this.chainname[ j ] = str.charCodeAt(0)\n this.chainname[ j + 1 ] = str.charCodeAt(1)\n this.chainname[ j + 2 ] = str.charCodeAt(2)\n this.chainname[ j + 3 ] = str.charCodeAt(3)\n }\n\n getChainname (i: number) {\n let chainname = ''\n for (let k = 0; k < 4; ++k) {\n const code = this.chainname[ 4 * i + k ]\n if (code) {\n chainname += String.fromCharCode(code)\n } else {\n break\n }\n }\n return chainname\n }\n\n setChainid (i: number, str: string) {\n const j = 4 * i\n this.chainid[ j ] = str.charCodeAt(0)\n this.chainid[ j + 1 ] = str.charCodeAt(1)\n this.chainid[ j + 2 ] = str.charCodeAt(2)\n this.chainid[ j + 3 ] = str.charCodeAt(3)\n }\n\n getChainid (i: number) {\n let chainid = ''\n for (let k = 0; k < 4; ++k) {\n const code = this.chainid[ 4 * i + k ]\n if (code) {\n chainid += String.fromCharCode(code)\n } else {\n break\n }\n }\n return chainid\n }\n}\n","/**\n * @file Model Store\n * @author Alexander Rose \n * @private\n */\n\nimport Store, { StoreField } from './store'\n\n/**\n * Model store\n */\nexport default class ModelStore extends Store {\n\tchainOffset: Uint32Array\n\tchainCount: Uint32Array\n\n get _defaultFields () {\n return [\n [ 'chainOffset', 1, 'uint32' ],\n [ 'chainCount', 1, 'uint32' ]\n ] as StoreField[]\n }\n}","/**\n * @file Helixorient\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { ColormakerRegistry } from '../globals'\nimport { ColormakerParameters } from '../color/colormaker'\nimport { AtomPicker } from '../utils/picker'\nimport RadiusFactory, { RadiusParams } from '../utils/radius-factory'\nimport { copyArray } from '../math/array-utils'\nimport { projectPointOnVector } from '../math/vector-utils'\nimport Polymer from '../proxy/polymer'\n\nexport interface HelixIterator {\n size: number\n next: () => Vector3\n get: (idx: number) => Vector3\n reset: () => void\n}\n\nexport interface HelixPosition {\n center: Float32Array\n axis: Float32Array\n bending: Float32Array\n radius: Float32Array\n rise: Float32Array\n twist: Float32Array\n resdir: Float32Array\n}\n\nclass Helixorient {\n size: number\n\n constructor (readonly polymer: Polymer) {\n this.size = polymer.residueCount\n }\n\n getCenterIterator (smooth = 0): HelixIterator {\n const center = this.getPosition().center\n const size = center.length / 3\n\n let i = 0\n let j = -1\n\n const cache = [\n new Vector3(),\n new Vector3(),\n new Vector3(),\n new Vector3()\n ]\n\n function next (this: HelixIterator) {\n const vector = this.get(j)\n j += 1\n return vector\n }\n\n function get (idx: number) {\n idx = Math.min(size - 1, Math.max(0, idx))\n const v = cache[ i % 4 ]\n const idx3 = 3 * idx\n v.fromArray(center as any, idx3) // TODO\n if (smooth) {\n const w = Math.min(smooth, idx, size - idx - 1)\n for (let k = 1; k <= w; ++k) {\n const l = k * 3\n const t = (w + 1 - k) / (w + 1)\n v.x += t * center[ idx3 - l + 0 ] + t * center[ idx3 + l + 0 ]\n v.y += t * center[ idx3 - l + 1 ] + t * center[ idx3 + l + 1 ]\n v.z += t * center[ idx3 - l + 2 ] + t * center[ idx3 + l + 2 ]\n }\n v.x /= w + 1\n v.y /= w + 1\n v.z /= w + 1\n }\n i += 1\n return v\n }\n\n function reset () {\n i = 0\n j = -1\n }\n\n return { size, next, get, reset }\n }\n\n getColor (params: { scheme: string } & ColormakerParameters) {\n const polymer = this.polymer\n const structure = polymer.structure\n const n = polymer.residueCount\n const residueIndexStart = polymer.residueIndexStart\n\n const col = new Float32Array(n * 3)\n\n const p = params || {}\n p.structure = structure\n\n const colormaker = ColormakerRegistry.getScheme(p)\n\n const rp = structure.getResidueProxy()\n const ap = structure.getAtomProxy()\n\n for (let i = 0; i < n; ++i) {\n rp.index = residueIndexStart + i\n ap.index = rp.traceAtomIndex\n\n colormaker.atomColorToArray(ap, col, i * 3)\n }\n\n return {\n 'color': col\n }\n }\n\n getPicking () {\n const polymer = this.polymer\n const structure = polymer.structure\n const n = polymer.residueCount\n const residueIndexStart = polymer.residueIndexStart\n\n const pick = new Float32Array(n)\n const rp = structure.getResidueProxy()\n\n for (let i = 0; i < n; ++i) {\n rp.index = residueIndexStart + i\n pick[ i ] = rp.traceAtomIndex\n }\n\n return {\n 'picking': new AtomPicker(pick, structure)\n }\n }\n\n getSize (params: RadiusParams) {\n const polymer = this.polymer\n const structure = polymer.structure\n const n = polymer.residueCount\n const residueIndexStart = polymer.residueIndexStart\n\n const size = new Float32Array(n)\n const radiusFactory = new RadiusFactory(params)\n\n const rp = structure.getResidueProxy()\n const ap = structure.getAtomProxy()\n\n for (let i = 0; i < n; ++i) {\n rp.index = residueIndexStart + i\n ap.index = rp.traceAtomIndex\n size[ i ] = radiusFactory.atomRadius(ap)\n }\n\n return { size }\n }\n\n getPosition (): HelixPosition {\n const polymer = this.polymer\n const structure = polymer.structure\n const n = polymer.residueCount\n const n3 = n - 3\n\n const center = new Float32Array(3 * n)\n const axis = new Float32Array(3 * n)\n const diff = new Float32Array(n)\n const radius = new Float32Array(n)\n const rise = new Float32Array(n)\n const twist = new Float32Array(n)\n const resdir = new Float32Array(3 * n)\n\n const r12 = new Vector3()\n const r23 = new Vector3()\n const r34 = new Vector3()\n\n const diff13 = new Vector3()\n const diff24 = new Vector3()\n\n const v1 = new Vector3()\n const v2 = new Vector3()\n const vt = new Vector3()\n\n const _axis = new Vector3()\n const _prevAxis = new Vector3()\n\n const _resdir = new Vector3()\n const _center = new Vector3(0, 0, 0)\n\n const type = 'trace'\n const a1 = structure.getAtomProxy()\n const a2 = structure.getAtomProxy(polymer.getAtomIndexByType(0, type))\n const a3 = structure.getAtomProxy(polymer.getAtomIndexByType(1, type))\n const a4 = structure.getAtomProxy(polymer.getAtomIndexByType(2, type))\n\n for (let i = 0; i < n3; ++i) {\n a1.index = a2.index\n a2.index = a3.index\n a3.index = a4.index\n a4.index = polymer.getAtomIndexByType(i + 3, type)! // TODO\n\n const j = 3 * i\n\n // ported from GROMACS src/tools/gmx_helixorient.c\n\n r12.subVectors(a2 as any, a1 as any) // TODO\n r23.subVectors(a3 as any, a2 as any) // TODO\n r34.subVectors(a4 as any, a3 as any) // TODO\n\n diff13.subVectors(r12, r23)\n diff24.subVectors(r23, r34)\n\n _axis.crossVectors(diff13, diff24).normalize()\n _axis.toArray(axis as any, j) // TODO\n\n if (i > 0) {\n diff[ i ] = _axis.angleTo(_prevAxis)\n }\n\n const tmp = Math.cos(diff13.angleTo(diff24))\n twist[ i ] = 180.0 / Math.PI * Math.acos(tmp)\n\n const diff13Length = diff13.length()\n const diff24Length = diff24.length()\n\n radius[ i ] = (\n Math.sqrt(diff24Length * diff13Length) /\n // clamp, to avoid instabilities for when\n // angle between diff13 and diff24 is near 0\n Math.max(2.0, 2.0 * (1.0 - tmp))\n )\n\n rise[ i ] = Math.abs(r23.dot(_axis))\n\n //\n\n v1.copy(diff13).multiplyScalar(radius[ i ] / diff13Length)\n v2.copy(diff24).multiplyScalar(radius[ i ] / diff24Length)\n\n v1.subVectors(a2 as any, v1) // TODO\n v2.subVectors(a3 as any, v2) // TODO\n\n v1.toArray(center as any, j + 3) // TODO\n v2.toArray(center as any, j + 6) // TODO\n\n //\n\n _resdir.subVectors(a1 as any, _center) // TODO\n _resdir.toArray(resdir as any, j) // TODO\n\n _prevAxis.copy(_axis)\n _center.copy(v1)\n }\n\n //\n\n // calc axis as dir of second and third center pos\n // project first traceAtom onto axis to get first center pos\n v1.fromArray(center as any, 3) // TODO\n v2.fromArray(center as any, 6) // TODO\n _axis.subVectors(v1, v2).normalize()\n // _center.copy( res[ 0 ].getTraceAtom() );\n a1.index = polymer.getAtomIndexByType(0, type)! // TODO\n _center.copy(a1 as any) // TODO\n vt.copy(a1 as any) // TODO\n projectPointOnVector(vt, _axis, v1)\n vt.toArray(center as any, 0) // TODO\n\n // calc first resdir\n _resdir.subVectors(_center, v1)\n _resdir.toArray(resdir as any, 0) // TODO\n\n // calc axis as dir of n-1 and n-2 center pos\n // project last traceAtom onto axis to get last center pos\n v1.fromArray(center as any, 3 * n - 6) // TODO\n v2.fromArray(center as any, 3 * n - 9) // TODO\n _axis.subVectors(v1, v2).normalize()\n // _center.copy( res[ n - 1 ].getTraceAtom() );\n a1.index = polymer.getAtomIndexByType(n - 1, type)! // TODO\n _center.copy(a1 as any) // TODO\n vt.copy(a1 as any) // TODO\n projectPointOnVector(vt, _axis, v1)\n vt.toArray(center as any, 3 * n - 3) // TODO\n\n // calc last three resdir\n for (let i = n - 3; i < n; ++i) {\n v1.fromArray(center as any, 3 * i) // TODO\n // _center.copy( res[ i ].getTraceAtom() );\n a1.index = polymer.getAtomIndexByType(i, type)! // TODO\n _center.copy(a1 as any) // TODO\n\n _resdir.subVectors(_center, v1)\n _resdir.toArray(resdir as any, 3 * i) // TODO\n }\n\n // average measures to define them on the residues\n\n const resRadius = new Float32Array(n)\n const resTwist = new Float32Array(n)\n const resRise = new Float32Array(n)\n const resBending = new Float32Array(n)\n\n resRadius[ 1 ] = radius[ 0 ]\n resTwist[ 1 ] = twist[ 0 ]\n resRise[ 1 ] = radius[ 0 ]\n\n for (let i = 2; i < n - 2; ++i) {\n resRadius[ i ] = 0.5 * (radius[ i - 2 ] + radius[ i - 1 ])\n resTwist[ i ] = 0.5 * (twist[ i - 2 ] + twist[ i - 1 ])\n resRise[ i ] = 0.5 * (rise[ i - 2 ] + rise[ i - 1 ])\n\n v1.fromArray(axis as any, 3 * (i - 2)) // TODO\n v2.fromArray(axis as any, 3 * (i - 1)) // TODO\n resBending[ i ] = 180.0 / Math.PI * Math.acos(Math.cos(v1.angleTo(v2)))\n }\n\n resRadius[ n - 2 ] = radius[ n - 4 ]\n resTwist[ n - 2 ] = twist[ n - 4 ]\n resRise[ n - 2 ] = rise[ n - 4 ]\n\n // average helix axes to define them on the residues\n\n const resAxis = new Float32Array(3 * n)\n\n copyArray(axis, resAxis, 0, 0, 3)\n copyArray(axis, resAxis, 0, 3, 3)\n\n for (let i = 2; i < n - 2; ++i) {\n v1.fromArray(axis as any, 3 * (i - 2)) // TODO\n v2.fromArray(axis as any, 3 * (i - 1)) // TODO\n\n _axis.addVectors(v2, v1).multiplyScalar(0.5).normalize()\n _axis.toArray(resAxis as any, 3 * i) // TODO\n }\n\n copyArray(axis, resAxis, 3 * n - 12, 3 * n - 6, 3)\n copyArray(axis, resAxis, 3 * n - 12, 3 * n - 3, 3)\n\n return {\n center,\n axis: resAxis,\n bending: resBending,\n radius: resRadius,\n rise: resRise,\n twist: resTwist,\n resdir: resdir\n }\n }\n\n}\n\nexport default Helixorient\n","/**\n * @file Helixbundle\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { ColormakerRegistry } from '../globals'\nimport { AtomPicker } from '../utils/picker'\nimport RadiusFactory, { RadiusParams } from '../utils/radius-factory'\nimport Helixorient, { HelixPosition } from './helixorient'\nimport { calculateMeanVector3, projectPointOnVector } from '../math/vector-utils'\nimport Polymer from '../proxy/polymer'\nimport { ColormakerParameters } from '../color/colormaker';\n\nexport interface Axis {\n axis: Float32Array\n center: Float32Array\n begin: Float32Array\n end: Float32Array\n color: Float32Array\n picking: AtomPicker\n size: Float32Array\n residueOffset: number[]\n residueCount: number[]\n}\n\nclass Helixbundle {\n helixorient: Helixorient;\n position: HelixPosition;\n\n constructor (readonly polymer: Polymer) {\n\n this.helixorient = new Helixorient(polymer)\n this.position = this.helixorient.getPosition()\n }\n\n getAxis (localAngle: number, centerDist: number, ssBorder: boolean, colorParams: { scheme: string} & ColormakerParameters, radiusParams: RadiusParams): Axis {\n localAngle = localAngle || 30\n centerDist = centerDist || 2.5\n ssBorder = ssBorder === undefined ? false : ssBorder\n\n const polymer = this.polymer\n const structure = polymer.structure\n const n = polymer.residueCount\n const residueIndexStart = polymer.residueIndexStart\n\n const pos = this.position\n\n const cp = colorParams || {}\n cp.structure = structure\n\n const colormaker = ColormakerRegistry.getScheme(cp)\n\n const radiusFactory = new RadiusFactory(radiusParams)\n\n let j = 0\n let k = 0\n\n const axis: number[] = []\n const center: number[] = []\n const beg: number[] = []\n const end: number[] = []\n const col: number[] = []\n const pick = []\n const size = []\n const residueOffset = []\n const residueCount = []\n\n let tmpAxis = new Float32Array(n * 3)\n let tmpCenter = new Float32Array(n * 3)\n\n let _axis, _center\n const _beg = new Vector3()\n const _end = new Vector3()\n\n const rp1 = structure.getResidueProxy()\n const rp2 = structure.getResidueProxy()\n const ap = structure.getAtomProxy()\n\n const c1 = new Vector3()\n const c2 = new Vector3()\n\n let split = false\n\n for (let i = 0; i < n; ++i) {\n rp1.index = residueIndexStart + i\n c1.fromArray(pos.center as any, i * 3)\n\n if (i === n - 1) {\n split = true\n } else {\n rp2.index = residueIndexStart + i + 1\n c2.fromArray(pos.center as any, i * 3 + 3)\n\n if (ssBorder && rp1.sstruc !== rp2.sstruc) {\n split = true\n } else if (c1.distanceTo(c2) > centerDist) {\n split = true\n } else if (pos.bending[ i ] > localAngle) {\n split = true\n }\n }\n\n if (split) {\n if (i - j < 4) {\n j = i\n split = false\n continue\n }\n\n ap.index = rp1.traceAtomIndex\n\n // ignore first and last axis\n tmpAxis = pos.axis.subarray(j * 3 + 3, i * 3)\n tmpCenter = pos.center.subarray(j * 3, i * 3 + 3)\n\n _axis = calculateMeanVector3(tmpAxis).normalize()\n _center = calculateMeanVector3(tmpCenter)\n\n _beg.fromArray(tmpCenter as any)\n projectPointOnVector(_beg, _axis, _center)\n\n _end.fromArray(tmpCenter as any, tmpCenter.length - 3)\n projectPointOnVector(_end, _axis, _center)\n\n _axis.subVectors(_end, _beg)\n\n _axis.toArray(axis as any, k)\n _center.toArray(center as any, k)\n _beg.toArray(beg as any, k)\n _end.toArray(end as any, k)\n\n colormaker.atomColorToArray(ap, col, k)\n\n pick.push(ap.index)\n\n size.push(radiusFactory.atomRadius(ap))\n\n residueOffset.push(residueIndexStart + j)\n residueCount.push(residueIndexStart + i + 1 - j)\n\n k += 3\n j = i\n split = false\n }\n }\n\n const picking = new Float32Array(pick)\n\n return {\n axis: new Float32Array(axis),\n center: new Float32Array(center),\n begin: new Float32Array(beg),\n end: new Float32Array(end),\n color: new Float32Array(col),\n picking: new AtomPicker(picking, structure),\n size: new Float32Array(size),\n residueOffset: residueOffset,\n residueCount: residueCount\n }\n }\n}\n\nexport default Helixbundle\n","/**\n * @file Binary Heap\n * @author Alexander Rose \n * @private\n */\n\n/**\n * Binary heap implementation\n * @class\n * @author http://eloquentjavascript.net/appendix2.htm\n * @param {Function} scoreFunction - the heap scoring function\n */\nclass BinaryHeap {\n content: T[] = []\n\n constructor(readonly scoreFunction: (x: T) => number) {\n\n this.scoreFunction = scoreFunction\n }\n\n push (element: T) {\n // Add the new element to the end of the array.\n this.content.push(element)\n\n // Allow it to bubble up.\n this.bubbleUp(this.content.length - 1)\n }\n\n pop () {\n // Store the first element so we can return it later.\n const result = this.content[ 0 ]\n\n // Get the element at the end of the array.\n const end = this.content.pop()\n\n // If there are any elements left, put the end element at the\n // start, and let it sink down.\n if (end && this.content.length > 0) {\n this.content[ 0 ] = end\n this.sinkDown(0)\n }\n\n return result\n }\n\n peek () {\n return this.content[ 0 ]\n }\n\n remove (element: T) {\n const len = this.content.length\n\n // To remove a value, we must search through the array to find it.\n for (let i = 0; i < len; i++) {\n if (this.content[ i ] === element) {\n // When it is found, the process seen in 'pop' is repeated\n // to fill up the hole.\n const end = this.content.pop()\n\n if (end && i !== len - 1) {\n this.content[ i ] = end\n\n if (this.scoreFunction(end) < this.scoreFunction(element)) {\n this.bubbleUp(i)\n } else {\n this.sinkDown(i)\n }\n }\n\n return\n }\n }\n\n throw new Error('Node not found.')\n }\n\n size () {\n return this.content.length\n }\n\n bubbleUp (n: number) {\n // Fetch the element that has to be moved.\n const element = this.content[ n ]\n\n // When at 0, an element can not go up any further.\n while (n > 0) {\n // Compute the parent element's index, and fetch it.\n const parentN = Math.floor((n + 1) / 2) - 1\n const parent = this.content[ parentN ]\n\n // Swap the elements if the parent is greater.\n if (this.scoreFunction(element) < this.scoreFunction(parent)) {\n this.content[ parentN ] = element\n this.content[ n ] = parent\n\n // Update 'n' to continue at the new position.\n n = parentN\n } else {\n // Found a parent that is less, no need to move it further.\n break\n }\n }\n }\n\n sinkDown (n: number) {\n // Look up the target element and its score.\n const length = this.content.length\n const element = this.content[ n ]\n const elemScore = this.scoreFunction(element)\n\n let child1Score = 0\n let child2Score = 0\n\n while (true) {\n // Compute the indices of the child elements.\n const child2N = (n + 1) * 2\n const child1N = child2N - 1\n\n // This is used to store the new position of the element, if any.\n let swap = null\n\n // If the first child exists (is inside the array)...\n if (child1N < length) {\n // Look it up and compute its score.\n const child1 = this.content[ child1N ]\n child1Score = this.scoreFunction(child1)\n\n // If the score is less than our element's, we need to swap.\n if (child1Score < elemScore) swap = child1N\n }\n\n // Do the same checks for the other child.\n if (child2N < length) {\n const child2 = this.content[ child2N ]\n child2Score = this.scoreFunction(child2)\n\n if (child2Score < (swap === null ? elemScore : child1Score)) swap = child2N\n }\n\n // If the element needs to be moved, swap it, and continue.\n if (swap !== null) {\n this.content[ n ] = this.content[ swap ]\n this.content[ swap ] = element\n n = swap\n } else {\n // Otherwise, we are done.\n break\n }\n }\n }\n\n}\n\nexport default BinaryHeap\n","/**\n * @file Kdtree\n * @author Alexander Rose \n * @private\n */\n\nimport { NumberArray } from '../types'\nimport BinaryHeap from './binary-heap'\n\n/**\n * Kdtree\n * @class\n * @author Alexander Rose , 2016\n * @author Roman Bolzern , 2013\n * @author I4DS http://www.fhnw.ch/i4ds, 2013\n * @license MIT License \n * @description\n * k-d Tree for typed arrays of 3d points (e.g. for Float32Array), in-place\n * provides fast nearest neighbour search\n *\n * Based on https://github.com/ubilabs/kd-tree-javascript by Ubilabs\n *\n * Further information (including mathematical properties)\n * http://en.wikipedia.org/wiki/Binary_tree\n * http://en.wikipedia.org/wiki/K-d_tree\n *\n * @example\n * points: [x, y, z, x, y, z, x, y, z, ...]\n * metric: function(a, b){\n * return Math.pow(a[0]-b[0], 2) + Math.pow(a[1]-b[1], 2) + Math.pow(a[2]-b[2], 2);\n * }\n *\n * @param {Float32Array} points - points\n * @param {Function} metric - metric\n */\nclass Kdtree {\n indices: Uint32Array\n nodes: Int32Array\n rootIndex: number\n\n maxDepth = 0\n currentNode = 0\n\n constructor(readonly points: NumberArray, readonly metric: (a: NumberArray, b: NumberArray) => number) {\n const n = points.length / 3\n\n const indices = new Uint32Array(n)\n for (let i = 0; i < n; ++i) {\n indices[ i ] = i\n }\n this.indices = indices\n this.nodes = new Int32Array(n * 4)\n this.rootIndex = this.buildTree(0, -1, 0, n)\n }\n\n buildTree (depth: number, parent: number, arrBegin: number, arrEnd: number) {\n if (depth > this.maxDepth) this.maxDepth = depth\n\n const plength = arrEnd - arrBegin\n if (plength === 0) {\n return -1\n }\n\n const nodeIndex = this.currentNode * 4\n const nodes = this.nodes\n\n this.currentNode += 1\n if (plength === 1) {\n nodes[ nodeIndex ] = arrBegin\n nodes[ nodeIndex + 1 ] = -1\n nodes[ nodeIndex + 2 ] = -1\n nodes[ nodeIndex + 3 ] = parent\n return nodeIndex\n }\n // if(plength <= 32){\n // return nodeIndex;\n // }\n\n const indices = this.indices\n const points = this.points\n\n const arrMedian = arrBegin + Math.floor(plength / 2)\n const currentDim = depth % 3\n\n // inlined quickselect function\n let j, tmp, pivotIndex, pivotValue, storeIndex\n let left = arrBegin\n let right = arrEnd - 1\n while (right > left) {\n pivotIndex = (left + right) >> 1\n pivotValue = points[ indices[ pivotIndex ] * 3 + currentDim ]\n // swap( pivotIndex, right );\n tmp = indices[ pivotIndex ]\n indices[ pivotIndex ] = indices[ right ]\n indices[ right ] = tmp\n storeIndex = left\n for (j = left; j < right; ++j) {\n if (points[ indices[ j ] * 3 + currentDim ] < pivotValue) {\n // swap( storeIndex, j );\n tmp = indices[ storeIndex ]\n indices[ storeIndex ] = indices[ j ]\n indices[ j ] = tmp\n ++storeIndex\n }\n }\n // swap( right, storeIndex );\n tmp = indices[ right ]\n indices[ right ] = indices[ storeIndex ]\n indices[ storeIndex ] = tmp\n pivotIndex = storeIndex\n if (arrMedian === pivotIndex) {\n break\n } else if (arrMedian < pivotIndex) {\n right = pivotIndex - 1\n } else {\n left = pivotIndex + 1\n }\n }\n\n nodes[ nodeIndex ] = arrMedian\n nodes[ nodeIndex + 1 ] = this.buildTree(depth + 1, nodeIndex, arrBegin, arrMedian)\n nodes[ nodeIndex + 2 ] = this.buildTree(depth + 1, nodeIndex, arrMedian + 1, arrEnd)\n nodes[ nodeIndex + 3 ] = parent\n\n return nodeIndex\n }\n\n getNodeDepth (nodeIndex: number): number {\n const parentIndex = this.nodes[ nodeIndex + 3 ]\n return (parentIndex === -1) ? 0 : this.getNodeDepth(parentIndex) + 1\n }\n\n // TODO\n // function getNodePos (node) {}\n\n /**\n * find nearest points\n * @param {Array} point - array of size 3\n * @param {Integer} maxNodes - max amount of nodes to return\n * @param {Float} maxDistance - maximum distance of point to result nodes\n * @return {Array} array of point, distance pairs\n */\n nearest (point: NumberArray, maxNodes: number, maxDistance: number) {\n const bestNodes = new BinaryHeap<[number, number]>(e => -e[ 1 ])\n\n const nodes = this.nodes\n const points = this.points\n const indices = this.indices\n\n const nearestSearch = (nodeIndex: number) => {\n let bestChild, otherChild\n const dimension = this.getNodeDepth(nodeIndex) % 3\n const pointIndex = indices[ nodes[ nodeIndex ] ] * 3\n const ownPoint = [\n points[ pointIndex + 0 ],\n points[ pointIndex + 1 ],\n points[ pointIndex + 2 ]\n ]\n const ownDistance = this.metric(point, ownPoint)\n\n function saveNode (nodeIndex: number, distance: number) {\n bestNodes.push([ nodeIndex, distance ])\n if (bestNodes.size() > maxNodes) {\n bestNodes.pop()\n }\n }\n\n const leftIndex = nodes[ nodeIndex + 1 ]\n const rightIndex = nodes[ nodeIndex + 2 ]\n\n // if it's a leaf\n if (rightIndex === -1 && leftIndex === -1) {\n if ((bestNodes.size() < maxNodes || ownDistance < bestNodes.peek()[ 1 ]) &&\n ownDistance <= maxDistance\n ) {\n saveNode(nodeIndex, ownDistance)\n }\n return\n }\n\n if (rightIndex === -1) {\n bestChild = leftIndex\n } else if (leftIndex === -1) {\n bestChild = rightIndex\n } else {\n if (point[ dimension ] <= points[ pointIndex + dimension ]) {\n bestChild = leftIndex\n } else {\n bestChild = rightIndex\n }\n }\n\n // recursive search\n nearestSearch(bestChild)\n\n if ((bestNodes.size() < maxNodes || ownDistance < bestNodes.peek()[ 1 ]) &&\n ownDistance <= maxDistance\n ) {\n saveNode(nodeIndex, ownDistance)\n }\n\n // if there's still room or the current distance is nearer than the best distance\n const linearPoint = []\n for (let i = 0; i < 3; i += 1) {\n if (i === dimension) {\n linearPoint[ i ] = point[ i ]\n } else {\n linearPoint[ i ] = points[ pointIndex + i ]\n }\n }\n const linearDistance = this.metric(linearPoint, ownPoint)\n\n if ((bestNodes.size() < maxNodes || Math.abs(linearDistance) < bestNodes.peek()[ 1 ]) &&\n Math.abs(linearDistance) <= maxDistance\n ) {\n if (bestChild === leftIndex) {\n otherChild = rightIndex\n } else {\n otherChild = leftIndex\n }\n if (otherChild !== -1) {\n nearestSearch(otherChild)\n }\n }\n }\n\n nearestSearch(this.rootIndex)\n\n const result = []\n for (let i = 0, il = Math.min(bestNodes.size(), maxNodes); i < il; i += 1) {\n result.push(bestNodes.content[ i ])\n }\n\n return result\n }\n\n verify (nodeIndex?: number, depth = 0) {\n let count = 1\n\n if (nodeIndex === undefined) {\n nodeIndex = this.rootIndex\n }\n\n if (nodeIndex === -1) {\n throw new Error('node is null')\n }\n\n const dim = depth % 3\n const nodes = this.nodes\n const points = this.points\n const indices = this.indices\n\n const leftIndex = nodes[ nodeIndex + 1 ]\n const rightIndex = nodes[ nodeIndex + 2 ]\n\n if (leftIndex !== -1) {\n if (points[ indices[ nodes[ leftIndex ] ] * 3 + dim ] >\n points[ indices[ nodes[ nodeIndex ] ] * 3 + dim ]\n ) {\n throw new Error('left child is > parent!')\n }\n count += this.verify(leftIndex, depth + 1)\n }\n\n if (rightIndex !== -1) {\n if (points[ indices[ nodes[ rightIndex ] ] * 3 + dim ] <\n points[ indices[ nodes[ nodeIndex ] ] * 3 + dim ]\n ) {\n throw new Error('right child is < parent!')\n }\n count += this.verify(rightIndex, depth + 1)\n }\n\n return count\n }\n}\n\nexport default Kdtree\n","/**\n * @file Atom Proxy\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { NumberArray } from '../types'\nimport {\n Elements,\n SecStrucHelix, SecStrucSheet, SecStrucTurn,\n ProteinType, RnaType, DnaType, WaterType, IonType, SaccharideType,\n CgProteinBackboneType, CgRnaBackboneType, CgDnaBackboneType\n} from '../structure/structure-constants'\n\nimport Structure from '../structure/structure'\n\nimport ChainStore from '../store/chain-store'\nimport ResidueStore from '../store/residue-store'\nimport AtomStore from '../store/atom-store'\n\nimport AtomMap from '../store/atom-map'\nimport ResidueMap from '../store/residue-map'\n\nimport BondProxy from '../proxy/bond-proxy'\nimport AtomType from '../store/atom-type';\nimport ResidueType from '../store/residue-type';\nimport ResidueProxy from './residue-proxy';\nimport Entity from '../structure/entity';\nimport BondHash from '../store/bond-hash';\n\n/**\n * Atom proxy\n */\nclass AtomProxy {\n index: number\n\n chainStore: ChainStore\n residueStore: ResidueStore\n atomStore: AtomStore\n\n residueMap: ResidueMap\n atomMap: AtomMap\n\n /**\n * @param {Structure} structure - the structure\n * @param {Integer} index - the index\n */\n constructor (readonly structure: Structure, index = 0) {\n this.index = index\n this.chainStore = structure.chainStore\n this.residueStore = structure.residueStore\n this.atomStore = structure.atomStore\n this.residueMap = structure.residueMap\n this.atomMap = structure.atomMap\n }\n\n /**\n * @type {BondHash}\n */\n get bondHash (): BondHash|undefined { return this.structure.bondHash }\n\n /**\n * Molecular enity\n * @type {Entity}\n */\n get entity (): Entity {\n return this.structure.entityList[ this.entityIndex ]\n }\n get entityIndex () {\n return this.chainStore.entityIndex[ this.chainIndex ]\n }\n get modelIndex () {\n return this.chainStore.modelIndex[ this.chainIndex ]\n }\n get chainIndex () {\n return this.residueStore.chainIndex[ this.residueIndex ]\n }\n /**\n * @type {ResidueProxy}\n */\n get residue (): ResidueProxy {\n console.warn('residue - might be expensive')\n return this.structure.getResidueProxy(this.residueIndex)\n }\n\n get residueIndex () {\n return this.atomStore.residueIndex[ this.index ]\n }\n set residueIndex (value) {\n this.atomStore.residueIndex[ this.index ] = value\n }\n\n //\n\n /**\n * Secondary structure code\n * @type {String}\n */\n get sstruc () {\n return this.residueStore.getSstruc(this.residueIndex)\n }\n /**\n * Insertion code\n * @type {String}\n */\n get inscode () {\n return this.residueStore.getInscode(this.residueIndex)\n }\n /**\n * Residue number/label\n * @type {Integer}\n */\n get resno () {\n return this.residueStore.resno[ this.residueIndex ]\n }\n /**\n * Chain name\n * @type {String}\n */\n get chainname () {\n return this.chainStore.getChainname(this.chainIndex)\n }\n /**\n * Chain id\n * @type {String}\n */\n get chainid () {\n return this.chainStore.getChainid(this.chainIndex)\n }\n\n //\n\n /**\n * @type {ResidueType}\n */\n get residueType (): ResidueType {\n return this.residueMap.get(this.residueStore.residueTypeId[ this.residueIndex ])\n }\n /**\n * @type {AtomType}\n */\n get atomType (): AtomType {\n return this.atomMap.get(this.atomStore.atomTypeId[ this.index ])\n }\n get residueAtomOffset () {\n return this.residueStore.atomOffset[ this.residueIndex ]\n }\n\n //\n\n /**\n * Residue name\n */\n get resname () {\n return this.residueType.resname\n }\n /**\n * Hetero flag\n */\n get hetero () {\n return this.residueType.hetero\n }\n\n //\n\n /**\n * Atom name\n */\n get atomname () {\n return this.atomType.atomname\n }\n /**\n * Atomic number\n */\n get number () {\n return this.atomType.number\n }\n /**\n * Element\n */\n get element () {\n return this.atomType.element\n }\n /**\n * Van-der-Waals radius\n */\n get vdw () {\n return this.atomType.vdw\n }\n /**\n * Covalent radius\n */\n get covalent () {\n return this.atomType.covalent\n }\n\n //\n\n /**\n * X coordinate\n */\n get x () {\n return this.atomStore.x[ this.index ]\n }\n set x (value) {\n this.atomStore.x[ this.index ] = value\n }\n\n /**\n * Y coordinate\n */\n get y () {\n return this.atomStore.y[ this.index ]\n }\n set y (value) {\n this.atomStore.y[ this.index ] = value\n }\n\n /**\n * Z coordinate\n */\n get z () {\n return this.atomStore.z[ this.index ]\n }\n set z (value) {\n this.atomStore.z[ this.index ] = value\n }\n\n /**\n * Serial number\n */\n get serial () {\n return this.atomStore.serial[ this.index ]\n }\n set serial (value) {\n this.atomStore.serial[ this.index ] = value\n }\n\n /**\n * B-factor value\n */\n get bfactor () {\n return this.atomStore.bfactor[ this.index ]\n }\n set bfactor (value) {\n this.atomStore.bfactor[ this.index ] = value\n }\n\n /**\n * Occupancy value\n */\n get occupancy () {\n return this.atomStore.occupancy[ this.index ]\n }\n set occupancy (value) {\n this.atomStore.occupancy[ this.index ] = value\n }\n\n /**\n * Alternate location identifier\n */\n get altloc () {\n return this.atomStore.getAltloc(this.index)\n }\n set altloc (value) {\n this.atomStore.setAltloc(this.index, value)\n }\n\n /**\n * Partial charge\n */\n get partialCharge () {\n return this.atomStore.partialCharge ? this.atomStore.partialCharge[ this.index ] : null\n }\n set partialCharge (value) {\n if (this.atomStore.partialCharge) {\n this.atomStore.partialCharge[ this.index ] = value as number\n }\n }\n\n /**\n * Explicit radius\n */\n get radius () {\n return this.atomStore.radius ? this.atomStore.radius[ this.index ] : null\n }\n set radius (value) {\n if (this.atomStore.radius) {\n this.atomStore.radius[ this.index ] = value as number\n }\n }\n\n /**\n * Formal charge\n */\n get formalCharge () {\n return this.atomStore.formalCharge ? this.atomStore.formalCharge[ this.index ] : null\n }\n set formalCharge (value) {\n if (this.atomStore.formalCharge) {\n this.atomStore.formalCharge[ this.index ] = value as number\n }\n }\n\n /**\n * Aromaticity flag\n */\n get aromatic () {\n if (this.atomStore.aromatic) {\n return this.atomStore.aromatic[ this.index ] as number\n } else {\n return this.residueType.isAromatic(this) ? 1 : 0\n }\n }\n set aromatic (value) {\n if (this.atomStore.aromatic) {\n this.atomStore.aromatic[ this.index ] = value as number\n }\n }\n\n //\n\n get bondCount () {\n return this.bondHash!.countArray[ this.index ] // TODO\n }\n\n //\n\n /**\n * Iterate over each bond\n * @param {function(bond: BondProxy)} callback - iterator callback function\n * @param {BondProxy} [bp] - optional target bond proxy for use in the callback\n * @return {undefined}\n */\n eachBond (callback: (bp: BondProxy) => void, bp?: BondProxy) {\n bp = bp || this.structure._bp\n const idx = this.index\n const bondHash = this.bondHash! // TODO\n const indexArray = bondHash.indexArray\n const n = bondHash.countArray[ idx ]\n const offset = bondHash.offsetArray[ idx ]\n\n for (let i = 0; i < n; ++i) {\n bp.index = indexArray[ offset + i ]\n callback(bp)\n }\n }\n\n /**\n * Iterate over each bonded atom\n * @param {function(atom: AtomProxy)} callback - iterator callback function\n * @param {AtomProxy} [ap] - optional target atom proxy for use in the callback\n * @return {undefined}\n */\n eachBondedAtom (callback: (ap: AtomProxy) => void, _ap?: AtomProxy) {\n const ap = _ap ? _ap : this.structure._ap\n const idx = this.index\n\n this.eachBond(function (bp) {\n ap.index = idx !== bp.atomIndex1 ? bp.atomIndex1 : bp.atomIndex2\n callback(ap)\n })\n this.index = idx\n }\n\n /**\n * Check if this atom is bonded to the given atom,\n * assumes both atoms are from the same structure\n * @param {AtomProxy} ap - the given atom\n * @return {Boolean} whether a bond exists or not\n */\n hasBondTo (ap: AtomProxy) {\n let flag = false\n this.eachBondedAtom(function (bap) {\n if (ap.index === bap.index) flag = true\n })\n return flag\n }\n\n bondToElementCount (element: Elements) {\n let count = 0\n const idx = this.index // Avoid reentrancy problems\n this.eachBondedAtom(function (bap) {\n if (bap.number === element) count += 1\n })\n this.index = idx\n return count\n }\n\n hasBondToElement (element: Elements) {\n return this.bondToElementCount(element) > 0\n }\n\n //\n\n /**\n * If atom is part of a backbone\n * @return {Boolean} flag\n */\n isBackbone () {\n const backboneIndexList = this.residueType.backboneIndexList\n if (backboneIndexList.length > 0) {\n return backboneIndexList.includes(this.index - this.residueAtomOffset)\n } else {\n return false\n }\n }\n\n /**\n * If atom is part of a polymer\n * @return {Boolean} flag\n */\n isPolymer () {\n if (this.structure.entityList.length > 0) {\n return this.entity.isPolymer()\n } else {\n const moleculeType = this.residueType.moleculeType\n return (\n moleculeType === ProteinType ||\n moleculeType === RnaType ||\n moleculeType === DnaType\n )\n }\n }\n\n /**\n * If atom is part of a sidechin\n * @return {Boolean} flag\n */\n isSidechain () {\n return this.isPolymer() && !this.isBackbone()\n }\n\n /**\n * If atom is part of a coarse-grain group\n * @return {Boolean} flag\n */\n isCg () {\n const backboneType = this.residueType.backboneType\n return (\n backboneType === CgProteinBackboneType ||\n backboneType === CgRnaBackboneType ||\n backboneType === CgDnaBackboneType\n )\n }\n\n isTrace () {\n return this.index === (this.residueType.traceAtomIndex + this.residueAtomOffset)\n }\n\n /**\n * If atom is part of a hetero group\n * @return {Boolean} flag\n */\n isHetero () {\n return this.residueType.hetero === 1\n }\n\n /**\n * If atom is part of a protein molecule\n * @return {Boolean} flag\n */\n isProtein () {\n return this.residueType.moleculeType === ProteinType\n }\n\n /**\n * If atom is part of a nucleic molecule\n * @return {Boolean} flag\n */\n isNucleic () {\n const moleculeType = this.residueType.moleculeType\n return moleculeType === RnaType || moleculeType === DnaType\n }\n\n /**\n * If atom is part of a rna\n * @return {Boolean} flag\n */\n isRna () {\n return this.residueType.moleculeType === RnaType\n }\n\n /**\n * If atom is part of a dna\n * @return {Boolean} flag\n */\n isDna () {\n return this.residueType.moleculeType === DnaType\n }\n\n /**\n * If atom is part of a water molecule\n * @return {Boolean} flag\n */\n isWater () {\n return this.residueType.moleculeType === WaterType\n }\n\n /**\n * If atom is part of an ion\n * @return {Boolean} flag\n */\n isIon () {\n return this.residueType.moleculeType === IonType\n }\n\n /**\n * If atom is part of a saccharide\n * @return {Boolean} flag\n */\n isSaccharide () {\n return this.residueType.moleculeType === SaccharideType\n }\n\n /**\n * If atom is part of a helix\n * @return {Boolean} flag\n */\n isHelix () {\n return SecStrucHelix.includes(this.sstruc)\n }\n\n /**\n * If atom is part of a sheet\n * @return {Boolean} flag\n */\n isSheet () {\n return SecStrucSheet.includes(this.sstruc)\n }\n\n /**\n * If atom is part of a turn\n * @return {Boolean} flag\n */\n isTurn () {\n return SecStrucTurn.includes(this.sstruc) && this.isProtein()\n }\n\n isBonded () {\n return this.bondHash!.countArray[ this.index ] !== 0 // TODO\n }\n\n /**\n * If atom is part of a ring\n * @return {Boolean} flag\n */\n isRing () {\n const atomRings = this.residueType.getRings()!.atomRings // TODO\n return atomRings[ this.index - this.residueAtomOffset ] !== undefined\n }\n\n isAromatic () {\n return this.aromatic === 1\n }\n\n isPolarHydrogen () {\n let result = false\n\n if (this.number !== 1) return result\n\n result = !this.hasBondToElement(Elements.C)\n\n return result\n }\n\n isMetal () { return this.atomType.isMetal() }\n isNonmetal () { return this.atomType.isNonmetal() }\n isMetalloid () { return this.atomType.isMetalloid() }\n isHalogen () { return this.atomType.isHalogen() }\n isDiatomicNonmetal () { return this.atomType.isDiatomicNonmetal() }\n isPolyatomicNonmetal () { return this.atomType.isPolyatomicNonmetal() }\n isAlkaliMetal () { return this.atomType.isAlkaliMetal() }\n isAlkalineEarthMetal () { return this.atomType.isAlkalineEarthMetal() }\n isNobleGas () { return this.atomType.isNobleGas() }\n isTransitionMetal () { return this.atomType.isTransitionMetal() }\n isPostTransitionMetal () { return this.atomType.isPostTransitionMetal() }\n isLanthanide () { return this.atomType.isLanthanide() }\n isActinide () { return this.atomType.isActinide() }\n\n getDefaultValence () { return this.atomType.getDefaultValence() }\n getValenceList () { return this.atomType.getValenceList() }\n getOuterShellElectronCount () { return this.atomType.getOuterShellElectronCount() }\n\n /**\n * Distance to another atom\n * @param {AtomProxy} atom - the other atom\n * @return {Number} the distance\n */\n distanceTo (atom: AtomProxy) {\n const taa = this.atomStore\n const aaa = atom.atomStore\n const ti = this.index\n const ai = atom.index\n const x = taa.x[ ti ] - aaa.x[ ai ]\n const y = taa.y[ ti ] - aaa.y[ ai ]\n const z = taa.z[ ti ] - aaa.z[ ai ]\n const distSquared = x * x + y * y + z * z\n return Math.sqrt(distSquared)\n }\n\n /**\n * If connected to another atom\n * @param {AtomProxy} atom - the other atom\n * @return {Boolean} flag\n */\n connectedTo (atom: AtomProxy) {\n const taa = this.atomStore\n const aaa = atom.atomStore\n const ti = this.index\n const ai = atom.index\n\n if (taa.altloc && aaa.altloc) {\n const ta = taa.altloc[ ti ] // use Uint8 value to compare\n const aa = aaa.altloc[ ai ] // no need to convert to char\n // 0 is the Null character, 32 is the space character\n if (!(ta === 0 || aa === 0 || ta === 32 || aa === 32 || (ta === aa))) return false\n }\n\n const x = taa.x[ ti ] - aaa.x[ ai ]\n const y = taa.y[ ti ] - aaa.y[ ai ]\n const z = taa.z[ ti ] - aaa.z[ ai ]\n\n const distSquared = x * x + y * y + z * z\n\n // if( this.isCg() ) console.log( this.qualifiedName(), Math.sqrt( distSquared ), distSquared )\n if (distSquared < 48.0 && this.isCg()) return true\n\n if (isNaN(distSquared)) return false\n\n const d = this.covalent + atom.covalent\n const d1 = d + 0.3\n const d2 = d - 0.5\n\n return distSquared < (d1 * d1) && distSquared > (d2 * d2)\n }\n\n /**\n * Set atom position from array\n * @param {Array|TypedArray} array - input array\n * @param {Integer} [offset] - the offset\n * @return {AtomProxy} this object\n */\n positionFromArray (array: NumberArray, offset = 0) {\n this.x = array[ offset + 0 ]\n this.y = array[ offset + 1 ]\n this.z = array[ offset + 2 ]\n\n return this\n }\n\n /**\n * Write atom position to array\n * @param {Array|TypedArray} [array] - target array\n * @param {Integer} [offset] - the offset\n * @return {Array|TypedArray} target array\n */\n positionToArray (array: NumberArray = [], offset = 0) {\n const index = this.index\n const atomStore = this.atomStore\n\n array[ offset + 0 ] = atomStore.x[ index ]\n array[ offset + 1 ] = atomStore.y[ index ]\n array[ offset + 2 ] = atomStore.z[ index ]\n\n return array\n }\n\n /**\n * Write atom position to vector\n * @param {Vector3} [v] - target vector\n * @return {Vector3} target vector\n */\n positionToVector3 (v?: Vector3) {\n if (v === undefined) v = new Vector3()\n\n v.x = this.x\n v.y = this.y\n v.z = this.z\n\n return v\n }\n\n /**\n * Set atom position from vector\n * @param {Vector3} v - input vector\n * @return {AtomProxy} this object\n */\n positionFromVector3 (v: Vector3) {\n this.x = v.x\n this.y = v.y\n this.z = v.z\n\n return this\n }\n\n /**\n * Add vector to atom position\n * @param {Vector3} v - input vector\n * @return {AtomProxy} this object\n */\n positionAdd (v: Vector3|AtomProxy) {\n this.x += v.x\n this.y += v.y\n this.z += v.z\n\n return this\n }\n\n /**\n * Subtract vector from atom position\n * @param {Vector3} v - input vector\n * @return {AtomProxy} this object\n */\n positionSub (v: Vector3|AtomProxy) {\n this.x -= v.x\n this.y -= v.y\n this.z -= v.z\n\n return this\n }\n\n /**\n * Get intra group/residue bonds\n * @param {Boolean} firstOnly - immediately return the first connected atomIndex\n * @return {Integer[]|Integer|undefined} connected atomIndices\n */\n getResidueBonds (firstOnly = false) {\n const residueAtomOffset = this.residueAtomOffset\n const relativeIndex = this.index - this.residueAtomOffset\n const bonds = this.residueType.getBonds()! // TODO\n const atomIndices1 = bonds.atomIndices1\n const atomIndices2 = bonds.atomIndices2\n let idx1, idx2, connectedAtomIndex\n let connectedAtomIndices: number[]|undefined\n\n if (!firstOnly) connectedAtomIndices = []\n\n idx1 = atomIndices1.indexOf(relativeIndex)\n while (idx1 !== -1) {\n connectedAtomIndex = atomIndices2[ idx1 ] + residueAtomOffset\n if (connectedAtomIndices) {\n connectedAtomIndices.push(connectedAtomIndex)\n idx1 = atomIndices1.indexOf(relativeIndex, idx1 + 1)\n } else {\n return connectedAtomIndex\n }\n }\n\n idx2 = atomIndices2.indexOf(relativeIndex)\n while (idx2 !== -1) {\n connectedAtomIndex = atomIndices1[ idx2 ] + residueAtomOffset\n if (connectedAtomIndices) {\n connectedAtomIndices.push(connectedAtomIndex)\n idx2 = atomIndices2.indexOf(relativeIndex, idx2 + 1)\n } else {\n return connectedAtomIndex\n }\n }\n\n return connectedAtomIndices\n }\n\n //\n\n qualifiedName (noResname = false) {\n var name = ''\n if (this.resname && !noResname) name += '[' + this.resname + ']'\n if (this.resno !== undefined) name += this.resno\n if (this.inscode) name += '^' + this.inscode\n if (this.chainname) name += ':' + this.chainname\n if (this.atomname) name += '.' + this.atomname\n if (this.altloc) name += '%' + this.altloc\n if (this.structure.modelStore.count > 1) name += '/' + this.modelIndex\n return name\n }\n\n /**\n * Clone object\n * @return {AtomProxy} cloned atom\n */\n clone () {\n return new AtomProxy(this.structure, this.index)\n }\n\n toObject () {\n return {\n index: this.index,\n residueIndex: this.residueIndex,\n\n resname: this.resname,\n x: this.x,\n y: this.y,\n z: this.z,\n element: this.element,\n chainname: this.chainname,\n resno: this.resno,\n serial: this.serial,\n vdw: this.vdw,\n covalent: this.covalent,\n hetero: this.hetero,\n bfactor: this.bfactor,\n altloc: this.altloc,\n atomname: this.atomname,\n modelIndex: this.modelIndex\n }\n }\n}\n\nexport default AtomProxy\n","/**\n * @file Kdtree\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { Debug, Log } from '../globals'\nimport _Kdtree from '../utils/kdtree'\nimport Structure from '../structure/structure'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ResidueProxy from '../proxy/residue-proxy'\n\nfunction euclideanDistSq(a: number[], b: number[]) {\n const dx = a[0] - b[0]\n const dy = a[1] - b[1]\n const dz = a[2] - b[2]\n return dx * dx + dy * dy + dz * dz\n}\n\nfunction euclideanDist(a: number[], b: number[]) {\n return Math.sqrt(euclideanDistSq(a, b))\n}\n\nconst pointArray = new Float32Array(3)\n\nclass Kdtree {\n points: Float32Array\n atomIndices: Uint32Array\n kdtree: _Kdtree\n\n constructor(structure: Structure|ResidueProxy, useSquaredDist = false) {\n if (Debug) Log.time('Kdtree build')\n\n const metric = useSquaredDist ? euclideanDistSq : euclideanDist\n\n const points = new Float32Array(structure.atomCount * 3)\n const atomIndices = new Uint32Array(structure.atomCount)\n let i = 0\n\n structure.eachAtom(function (ap) {\n points[ i + 0 ] = ap.x\n points[ i + 1 ] = ap.y\n points[ i + 2 ] = ap.z\n atomIndices[ i / 3 ] = ap.index\n i += 3\n })\n\n this.atomIndices = atomIndices\n this.points = points\n this.kdtree = new _Kdtree(points, metric)\n\n if (Debug) Log.timeEnd('Kdtree build')\n\n // console.log(\"this.kdtree.verify()\", this.kdtree.verify())\n }\n\n nearest (point: number[]|Vector3, maxNodes: number, maxDistance: number) {\n // Log.time( \"Kdtree nearest\" );\n\n if (point instanceof Vector3) {\n point.toArray(pointArray as any)\n } else if (point instanceof AtomProxy) {\n point.positionToArray(pointArray)\n }\n\n const nodeList = this.kdtree.nearest(pointArray, maxNodes, maxDistance)\n\n const indices = this.kdtree.indices\n const nodes = this.kdtree.nodes\n const atomIndices = this.atomIndices\n const resultList = []\n\n for (let i = 0, n = nodeList.length; i < n; ++i) {\n const d = nodeList[ i ]\n const nodeIndex = d[ 0 ]\n const dist = d[ 1 ]\n\n resultList.push({\n index: atomIndices[ indices[ nodes[ nodeIndex ] ] ],\n distance: dist\n })\n }\n\n // Log.timeEnd( \"Kdtree nearest\" );\n\n return resultList\n }\n}\n\nexport default Kdtree\n","/**\n * @file Symmetry Constants\n * @author Alexander Rose \n * @private\n */\n\nexport const SymOpCode: { [k: string]: string } = {\n ' ': 'X',\n '!': 'Y',\n '#': 'Z',\n '$': '-X',\n '%': '-Y',\n '&': '-Z',\n \"'\": 'Y+1/2',\n '(': '1/2+X',\n ')': '1/2+Y',\n '*': '1/2-X',\n '+': '1/2+Z',\n ',': '1/2-Y',\n '-': '1/2-Z',\n '.': 'X+1/2',\n '/': 'Z+1/2',\n '0': '-X+1/2',\n '1': '-Y+1/2',\n '2': '-Z+1/2',\n '3': '1/4+X',\n '4': '1/4-Y',\n '5': '1/4+Z',\n '6': '1/4-X',\n '7': '1/4+Y',\n '8': '3/4-Y',\n '9': '3/4+Z',\n ':': '3/4+Y',\n ';': '3/4+X',\n '<': '3/4-X',\n '=': '1/4-Z',\n '>': '3/4-Z',\n '?': 'X-Y',\n '@': 'Y-X',\n 'A': 'Z+1/3',\n 'B': 'Z+2/3',\n 'C': 'X+2/3',\n 'D': 'Y+1/3',\n 'E': '-Y+2/3',\n 'F': 'X-Y+1/3',\n 'G': 'Y-X+2/3',\n 'H': '-X+1/3',\n 'I': 'X+1/3',\n 'J': 'Y+2/3',\n 'K': '-Y+1/3',\n 'L': 'X-Y+2/3',\n 'M': 'Y-X+1/3',\n 'N': '-X+2/3',\n 'O': '2/3+X',\n 'P': '1/3+Y',\n 'Q': '1/3+Z',\n 'R': '2/3-Y',\n 'S': '1/3+X-Y',\n 'T': '2/3+Y-X',\n 'U': '1/3-X',\n 'V': '2/3-X',\n 'W': '1/3-Y',\n 'X': '1/3-Z',\n 'Y': '2/3+Y',\n 'Z': '1/3+Y-X',\n '[': '2/3+X-Y',\n ']': '1/3+X',\n '^': '2/3+Z',\n '_': '2/3-Z',\n '`': '5/6+Z',\n 'a': '1/6+Z',\n 'b': '5/6-Z',\n 'c': '1/6-Z',\n 'd': 'Z+5/6',\n 'e': 'Z+1/6',\n 'f': 'Z+1/4',\n 'g': '+Y'\n}\n\n// encoded, originally from CCP4 symop.lib\nexport const EncodedSymOp: { [k: string]: string } = {\n 'P 1': ' !#',\n 'P -1': ' !#$%&',\n 'P 1 2 1': ' !#$!&',\n 'P 1 21 1': \" !#$'&\",\n 'C 1 2 1': ' !#$!&()#*)&',\n 'P 1 m 1': ' !# %#',\n 'P 1 c 1': ' !# %+',\n 'C 1 m 1': ' !# %#()#(,#',\n 'C 1 c 1': ' !# %+()#(,+',\n 'P 1 2/m 1': ' !# %#$!&$%&',\n 'P 1 21/m 1': ' !#$)&$%& ,#',\n 'C 1 2/m 1': ' !# %#$!&$%&()#(,#*)&*,&',\n 'P 1 2/c 1': ' !#$!-$%& %+',\n 'P 1 21/c 1': ' !#$%&$)- ,+',\n 'C 1 2/c 1': ' !#$!-$%& %+()#*)-*,&(,+',\n 'P 2 2 2': ' !#$%#$!& %&',\n 'P 2 2 21': ' !#$%+$!- %&',\n 'P 21 21 2': ' !#$%#*)&(,&',\n 'P 21 21 21': ' !#*%+$)-(,&',\n 'C 2 2 21': ' !#$%+$!- %&()#*,+*)-(,&',\n 'C 2 2 2': ' !#$%#$!& %&()#*,#*)&(,&',\n 'F 2 2 2': ' !#$%#$!& %& )+$,+$)- ,-(!+*%+*!-(%-()#*,#*)&(,&',\n 'I 2 2 2': \" !#$%# %&$!&.'/01/.120'2\",\n 'I 21 21 21': ' !#*%+$)-(,&()+$,#*!& %-',\n 'P m m 2': ' !#$%# %#$!#',\n 'P m c 21': ' !#$%+ %+$!#',\n 'P c c 2': ' !#$%# %+$!+',\n 'P m a 2': ' !#$%#(%#*!#',\n 'P c a 21': ' !#$%+(%#*!+',\n 'P n c 2': ' !#$%# ,+$)+',\n 'P m n 21': ' !#*%+(%+$!#',\n 'P b a 2': ' !#$%#(,#*)#',\n 'P n a 21': ' !#$%+(,#*)+',\n 'P n n 2': ' !#$%#(,+*)+',\n 'C m m 2': ' !#$%# %#$!#()#*,#(,#*)#',\n 'C m c 21': ' !#$%+ %+$!#()#*,+(,+*)#',\n 'C c c 2': ' !#$%# %+$!+()#*,#(,+*)+',\n 'A m m 2': ' !#$%# %#$!# )+$,+ ,+$)+',\n 'A b m 2': ' !#$%# ,#$)# )+$,+ %+$!+',\n 'A m a 2': ' !#$%#(%#*!# )+$,+(,+*)+',\n 'A b a 2': ' !#$%#(,#*)# )+$,+(%+*!+',\n 'F m m 2': ' !#$%# %#$!# )+$,+ ,+$)+(!+*%+(%+*!+()#*,#(,#*)#',\n 'F d d 2': ' !#$%#345675 )+$,+3896:9(!+*%+;49<79()#*,#;85<:5',\n 'I m m 2': ' !#$%# %#$!#()+*,+(,+*)+',\n 'I b a 2': ' !#$%#(,#*)#()+*,+ %+$!+',\n 'I m a 2': ' !#$%#(%#*!#()+*,+ ,+$)+',\n 'P 2/m 2/m 2/m': ' !#$%#$!& %&$%& !& %#$!#',\n 'P 2/n 2/n 2/n': ' !#$%#$!& %&*,-()-(,+*)+',\n 'P 2/c 2/c 2/m': ' !#$%#$!- %-$%& !& %+$!+',\n 'P 2/b 2/a 2/n': ' !#$%#$!& %&*,&()&(,#*)#',\n 'P 21/m 2/m 2/a': ' !#*%#$!&(%&$%&(!& %#*!#',\n 'P 2/n 21/n 2/a': ' !#*%#*)- ,-$%&(!&(,+$)+',\n 'P 2/m 2/n 21/a': ' !#*%+*!- %&$%&(!-(%+$!#',\n 'P 21/c 2/c 2/a': ' !#*%#$!-(%-$%&(!& %+*!+',\n 'P 21/b 21/a 2/m': ' !#$%#*)&(,&$%& !&(,#*)#',\n 'P 21/c 21/c 2/n': ' !#*,#$)-(%-$%&()& ,+*!+',\n 'P 2/b 21/c 21/m': ' !#$%+$)- ,&$%& !- ,+$)#',\n 'P 21/n 21/n 2/m': ' !#$%#*)-(,-$%& !&(,+*)+',\n 'P 21/m 21/m 2/n': \" !#$%#*'&.,&*,&.'& %#$!#\",\n 'P 21/b 2/c 21/n': ' !#*,+$!-(,&$%&()- %+*)#',\n 'P 21/b 21/c 21/a': ' !#*%+$)-(,&$%&(!- ,+*)#',\n 'P 21/n 21/m 21/a': \" !#0%/$'&.12$%&.!2 1#0'/\",\n 'C 2/m 2/c 21/m': ' !#$%+$!- %&$%& !- %+$!#()#*,+*)-(,&*,&()-(,+*)#',\n 'C 2/m 2/c 21/a': ' !#$,+$)- %&$%& )- ,+$!#()#*%+*!-(,&*,&(!-(%+*)#',\n 'C 2/m 2/m 2/m': ' !#$%#$!& %&$%& !& %#$!#()#*,#*)&(,&*,&()&(,#*)#',\n 'C 2/c 2/c 2/m': ' !#$%#$!- %-$%& !& %+$!+()#*,#*)-(,-*,&()&(,+*)+',\n 'C 2/m 2/m 2/a': ' !#$,#$)& %&$%& )& ,#$!#()#*%#*!&(,&*,&(!&(%#*)#',\n 'C 2/c 2/c 2/a': ' !#*,#$!&(,&$,-(!- ,+*!+()#$%#*)& %&*%- )-(%+$)+',\n 'F 2/m 2/m 2/m': ' !#$%#$!& %&$%& !& %#$!# )+$,+$)- ,-$,- )- ,+$)+(!+*%+*!-(%-*%-(!-(%+*!+()#*,#*)&(,&*,&()&(,#*)#',\n 'F 2/d 2/d 2/d': ' !#$%#$!& %&64=37=345675 )+$,+$)- ,-68>3:>3896:9(!+*%+*!-(%-<4>;7>;49<79()#*,#*)&(,&<8=;:=;85<:5',\n 'I 2/m 2/m 2/m': ' !#$%#$!& %&$%& !& %#$!#()+*,+*)-(,-*,-()-(,+*)+',\n 'I 2/b 2/a 2/m': ' !#$%#*)&(,&$%& !&(,#*)#()+*,+$!- %-*,-()- %+$!+',\n 'I 21/b 21/c 21/a': ' !#*%+$)-(,&$%&(!- ,+*)#()+$,#*!& %-*,- )&(%#$!+',\n 'I 21/m 21/m 21/a': ' !#$,#$)& %&$%& )& ,#$!#()+*%+*!-(,-*,-(!-(%+*)+',\n 'P 4': ' !#$%#% #!$#',\n 'P 41': ' !#$%+% 5!$9',\n 'P 42': ' !#$%#% +!$+',\n 'P 43': ' !#$%+% 9!$5',\n 'I 4': ' !#$%#% #!$#()+*,+,(+)*+',\n 'I 41': ' !#*,+%(5)$9()+$%#, 9!*5',\n 'P -4': ' !#$%#!$&% &',\n 'I -4': ' !#$%#!$&% &()+*,+)*-,(-',\n 'P 4/m': ' !#$%#% #!$#$%& !&!$&% &',\n 'P 42/m': ' !#$%#% +!$+$%& !&!$-% -',\n 'P 4/n': ' !#$%#,(#)*#*,&()&!$&% &',\n 'P 42/n': ' !#$%#,(+)*+*,-()-!$&% &',\n 'I 4/m': ' !#$%#% #!$#$%& !&!$&% &()+*,+,(+)*+*,-()-)*-,(-',\n 'I 41/a': ' !#*,+%(5)$9$,=(!>!$&,(-()+$%#, 9!*5*%> )=)*-% &',\n 'P 4 2 2': ' !#$%#% #!$#$!& %&! &%$&',\n 'P 4 21 2': ' !#$%#,(#)*#*)&(,&! &%$&',\n 'P 41 2 2': ' !#$%+% 5!$9$!& %-! >%$=',\n 'P 41 21 2': ' !#$%+,(5)*9*)=(,>! &%$-',\n 'P 42 2 2': ' !#$%#% +!$+$!& %&! -%$-',\n 'P 42 21 2': ' !#$%#,(+)*+*)-(,-! &%$&',\n 'P 43 2 2': ' !#$%+% 9!$5$!& %-! =%$>',\n 'P 43 21 2': ' !#$%+,(9)*5*)>(,=! &%$-',\n 'I 4 2 2': ' !#$%#% #!$#$!& %&! &%$&()+*,+,(+)*+*)-(,-)(-,*-',\n 'I 41 2 2': ' !#*,+%(5)$9*!> ,=)(-%$&()+$%#, 9!*5$)=(%>! &,*-',\n 'P 4 m m': ' !#$%#% #!$# %#$!#%$#! #',\n 'P 4 b m': ' !#$%#% #!$#(,#*)#,*#)(#',\n 'P 42 c m': ' !#$%#% +!$+ %+$!+%$#! #',\n 'P 42 n m': ' !#$%#,(+)*+(,+*)+%$#! #',\n 'P 4 c c': ' !#$%#% #!$# %+$!+%$+! +',\n 'P 4 n c': ' !#$%#% #!$#(,+*)+,*+)(+',\n 'P 42 m c': ' !#$%#% +!$+ %#$!#%$+! +',\n 'P 42 b c': ' !#$%#% +!$+(,#*)#,*+)(+',\n 'I 4 m m': ' !#$%#% #!$# %#$!#%$#! #()+*,+,(+)*+(,+*)+,*+)(+',\n 'I 4 c m': ' !#$%#% #!$# %+$!+%$+! +()+*,+,(+)*+(,#*)#,*#)(#',\n 'I 41 m d': ' !#*,+%(5)$9 %#*)+%*5) 9()+$%#, 9!*5(,+$!#,$9!(5',\n 'I 41 c d': ' !#*,+%(5)$9 %+*)#%*9) 5()+$%#, 9!*5(,#$!+,$5!(9',\n 'P -4 2 m': ' !#$%#% &!$&$!& %&%$#! #',\n 'P -4 2 c': ' !#$%#% &!$&$!- %-%$+! +',\n 'P -4 21 m': ' !#$%#% &!$&*)&(,&,*#)(#',\n 'P -4 21 c': ' !#$%#% &!$&*)-(,-,*+)(+',\n 'P -4 m 2': ' !#$%#!$&% & %#$!#! &%$&',\n 'P -4 c 2': ' !#$%#% &!$& %+$!+! -%$-',\n 'P -4 b 2': ' !#$%#% &!$&(,#*)#)(&,*&',\n 'P -4 n 2': ' !#$%#% &!$&(,+*)+)(-,*-',\n 'I -4 m 2': ' !#$%#% &!$& %#$!#! &%$&()+*,+,(-)*-(,+*)+)(-,*-',\n 'I -4 c 2': ' !#$%#% &!$& %+$!+! -%$-()+*,+,(-)*-(,#*)#)(&,*&',\n 'I -4 2 m': ' !#$%#% &!$&$!& %&%$#! #()+*,+,(-)*-*)-(,-,*+)(+',\n 'I -4 2 d': ' !#$%#% &!$&*!>(%>,$9) 9()+*,+,(-)*-$)= ,=%*5!(5',\n 'P 4/m 2/m 2/m': ' !#$%#% #!$#$!& %&! &%$&$%& !&!$&% & %#$!#%$#! #',\n 'P 4/m 2/c 2/c': ' !#$%#% #!$#$!- %-! -%$-$%& !&!$&% & %+$!+%$+! +',\n 'P 4/n 2/b 2/m': ' !#$%#% #!$#$!& %&! &%$&*,&()&)*&,(&(,#*)#,*#)(#',\n 'P 4/n 2/n 2/c': ' !#$%#% #!$#$!& %&! &%$&*,-()-)*-,(-(,+*)+,*+)(+',\n 'P 4/m 21/b 2/m': ' !#$%#% #!$#*)&(,&)(&,*&$%& !&!$&% &(,#*)#,*#)(#',\n 'P 4/m 21/n 2/c': ' !#$%#% #!$#*)-(,-)(-,*-$%& !&!$&% &(,+*)+,*+)(+',\n 'P 4/n 21/m 2/m': ' !#$%#,(#)*#*)&(,&! &%$&*,&()&!$&% & %#$!#,*#)(#',\n 'P 4/n 2/c 2/c': ' !#$%#,(#)*#*)-(,-! -%$-*,&()&!$&% & %+$!+,*+)(+',\n 'P 42/m 2/m 2/c': ' !#$%#% +!$+$!& %&! -%$-$%& !&!$-% - %#$!#%$+! +',\n 'P 42/m 2/c 2/m': ' !#$%#% +!$+$!- %-! &%$&$%& !&!$-% - %+$!+%$#! #',\n 'P 42/n 2/b 2/c': ' !#$%#,(+)*+$!- %-)(&,*&*,-()-!$&% &(,#*)#%$+! +',\n 'P 42/n 2/n 2/m': ' !#$%#,(+)*+$!& %&)(-,*-*,-()-!$&% &(,+*)+%$#! #',\n 'P 42/m 21/b 2/c': ' !#$%#% +!$+*)&(,&)(-,*-$%& !&!$-% -(,#*)#,*+)(+',\n 'P 42/m 21/n 2/m': \" !#$%#,./'*/*'-.,-! &%$&$%& !&'*-,.-.,/*'/%$#! #\",\n 'P 42/n 21/m 2/c': ' !#$%#,(+)*+*)-(,-! &%$&*,-()-!$&% & %#$!#,*+)(+',\n 'P 42/n 21/c 2/m': ' !#$%#,(+)*+*)&(,&! -%$-*,-()-!$&% & %+$!+,*#)(#',\n 'I 4/m 2/m 2/m': ' !#$%#% #!$#$!& %&! &%$&$%& !&!$&% & %#$!#%$#! #()+*,+,(+)*+*)-(,-)(-,*-*,-()-)*-,(-(,+*)+,*+)(+',\n 'I 4/m 2/c 2/m': ' !#$%#% #!$#$!- %-! -%$-$%& !&!$&% & %+$!+%$+! +()+*,+,(+)*+*)&(,&)(&,*&*,-()-)*-,(-(,#*)#,*#)(#',\n 'I 41/a 2/m 2/d': ' !#*,+%(5)$9*!> ,=)(-%$&$,=(!>!$&,(-(,+$!#,$9!(5()+$%#, 9!*5$)=(%>! &,*-*%> )=)*-% & %#*)+%*5) 9',\n 'I 41/a 2/c 2/d': ' !#*,+%(5)$9*!= ,>)(&%$-$,=(!>!$&,(-(,#$!+,$5!(9()+$%#, 9!*5$)>(%=! -,*&*%> )=)*-% & %+*)#%*9) 5',\n 'P 3': ' !#%?#@$#',\n 'P 31': ' !#%?A@$B',\n 'P 32': ' !#%?B@$A',\n 'H 3': ' !#%?#@$#CDAEFAGHAIJBKLBMNB',\n 'R 3': ' !## !!# ',\n 'P -3': ' !#%?#@$#$%&!@&? &',\n 'H -3': ' !#%?#@$#$%&!@&? &OPQRSQTUQVWXYZX[]X]Y^W[^ZV^UR_PT_SO_',\n 'R -3': ' !## !!# $%&&$%%&$',\n 'P 3 1 2': ' !#%?#@$#%$&@!& ?&',\n 'P 3 2 1': ' !#%?#@$#! &?%&$@&',\n 'P 31 1 2': ' !#%?Q@$^%$_@!X ?&',\n 'P 31 2 1': ' !#%?A@$B! &?%_$@X',\n 'P 32 1 2': ' !#%?^@$Q%$X@!_ ?&',\n 'P 32 2 1': ' !#%?B@$A! &?%X$@_',\n 'H 3 2': ' !#%?#@$#! &?%&$@&OPQRSQTUQY]X[WXVZX]Y^W[^ZV^PO_SR_UT_',\n 'R 3 2': ' !## !!# %$&$&%&%$',\n 'P 3 m 1': ' !#%?#@$#%$#@!# ?#',\n 'P 3 1 m': ' !#%?#@$#! #?%#$@#',\n 'P 3 c 1': ' !#%?#@$#%$+@!+ ?+',\n 'P 3 1 c': ' !#%?#@$#! +?%+$@+',\n 'H 3 m': ' !#%?#@$#%$#@!# ?#OPQRSQTUQRUQTPQOSQ]Y^W[^ZV^WV^ZY^][^',\n 'R 3 m': ' !## !!# ! # #!#! ',\n 'H 3 c': ' !#%?#@$#%$+@!+ ?+OPQRSQTUQRU`TP`OS`]Y^W[^ZV^WVaZYa][a',\n 'R 3 c': \" !## !!# '././'/'.\",\n 'P -3 1 2/m': ' !#%?#@$#%$&@!& ?&$%&!@&? &! #?%#$@#',\n 'P -3 1 2/c': ' !#%?#@$#%$-@!- ?-$%&!@&? &! +?%+$@+',\n 'P -3 2/m 1': ' !#%?#@$#! &?%&$@&$%&!@&? &%$#@!# ?#',\n 'P -3 2/c 1': ' !#%?#@$#! -?%-$@-$%&!@&? &%$+@!+ ?+',\n 'H -3 2/m': ' !#%?#@$#! &?%&$@&$%&!@&? &%$#@!# ?#OPQRSQTUQY]X[WXVZXVWXYZX[]XRUQTPQOSQ]Y^W[^ZV^PO_SR_UT_UR_PT_SO_WV^ZY^][^',\n 'R -3 2/m': ' !## !!# %$&$&%&%$$%&&$%%&$! # #!#! ',\n 'H -3 2/c': ' !#%?#@$#! -?%-$@-$%&!@&? &%$+@!+ ?+OPQRSQTUQY]b[WbVZbVWXYZX[]XRU`TP`OS`]Y^W[^ZV^POcSRcUTcUR_PT_SO_WVaZYa][a',\n 'R -3 2/c': \" !## !!# 102021210$%&&$%%&$'././'/'.\",\n 'P 6': ' !#%?#@$#$%#!@#? #',\n 'P 61': ' !#%?A@$B$%/!@d? e',\n 'P 65': ' !#%?B@$A$%/!@e? d',\n 'P 62': ' !#%?^@$Q$%#!@^? Q',\n 'P 64': ' !#%?Q@$^$%#!@Q? ^',\n 'P 63': ' !#%?#@$#$%+!@+? +',\n 'P -6': ' !#%?#@$# !&%?&@$&',\n 'P 6/m': ' !#%?#@$#$%#!@#? #$%&!@&? & !&%?&@$&',\n 'P 63/m': ' !#%?#@$#$%+!@+? +$%&!@&? & !-%?-@$-',\n 'P 6 2 2': ' !#%?#@$#$%#!@#? #! &?%&$@&%$&@!& ?&',\n 'P 61 2 2': ' !#%?Q@$^$%+!@`? a! X?%&$@_%$b@!- ?c',\n 'P 65 2 2': ' !#%?^@$Q$%+!@a? `! _?%&$@X%$c@!- ?b',\n 'P 62 2 2': ' !#%?^@$Q$%#!@^? Q! _?%&$@X%$_@!& ?X',\n 'P 64 2 2': ' !#%?Q@$^$%#!@Q? ^! X?%&$@_%$X@!& ?_',\n 'P 63 2 2': ' !#%?#@$#$%+!@+? +! &?%&$@&%$-@!- ?-',\n 'P 6 m m': ' !#%?#@$#$%#!@#? #%$#@!# ?#! #?%#$@#',\n 'P 6 c c': ' !#%?#@$#$%#!@#? #%$+@!+ ?+! +?%+$@+',\n 'P 63 c m': ' !#%?#@$#$%+!@+? +%$+@!+ ?+! #?%#$@#',\n 'P 63 m c': ' !#%?#@$#$%+!@+? +%$#@!# ?#! +?%+$@+',\n 'P -6 m 2': ' !#%?#@$# !&%?&@$&%$#@!# ?#%$&@!& ?&',\n 'P -6 c 2': ' !#%?#@$# !-%?-@$-%$+@!+ ?+%$&@!& ?&',\n 'P -6 2 m': ' !#%?#@$# !&%?&@$&! &?%&$@&! #?%#$@#',\n 'P -6 2 c': ' !#%?#@$# !-%?-@$-! &?%&$@&! +?%+$@+',\n 'P 6/m 2/m 2/m': ' !#%?#@$#$%#!@#? #! &?%&$@&%$&@!& ?&$%&!@&? & !&@$&%?&%$#@!# ?#! #?%#$@#',\n 'P 6/m 2/c 2/c': ' !#%?#@$#$%#!@#? #! -?%-$@-%$-@!- ?-$%&!@&? & !&@$&%?&%$+@!+ ?+! +?%+$@+',\n 'P 63/m 2/c 2/m': ' !#%?#@$#$%+!@+? +! -?%-$@-%$&@!& ?&$%&!@&? & !-@$-%?-%$+@!+ ?+! #?%#$@#',\n 'P 63/m 2/m 2/c': ' !#%?#@$#$%+!@+? +! &?%&$@&%$-@!- ?-$%&!@&? & !-@$-%?-%$#@!# ?#! +?%+$@+',\n 'P 2 3': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ',\n 'F 2 3': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-((!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- ',\n 'I 2 3': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-(',\n 'P 21 3': ' !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(',\n 'I 21 3': ' !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(()+$,#*!& %-+()#$,&*!- %)+(,#$!&*%- ',\n 'P 2/m -3': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& $%& !& %#$!#&$%& !# %#$!%&$!& %# !#$',\n 'P 2/n -3': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& *,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*',\n 'F 2/m -3': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& $%& !& %#$!#&$%& !# %#$!%&$!& %# !#$ )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-($,- )- ,+$)+&*,&()#(,#*)%-*!-(%+(!+*(!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(*%-(!-(%+*!+-$,- )+ ,+$),&*)&(,#()#*()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- *,&()&(,#*)#-*%-(!+(%+*!,-$)- ,+ )+$',\n 'F 2/d -3': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& 64=37=345675=64=375345674=67=3453756 )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-(68>3:>3896:9=<8=;:5;85<:4><7>;49;79<(!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(<4>;7>;49<79>68>3:93896:8=<:=;85;:5<()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- <8=;:=;8f<:f><4>;79;49<78>6:>3893:96',\n 'I 2/m -3': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& $%& !& %#$!#&$%& !# %#$!%&$!& %# !#$()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-(*,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*',\n 'P 21/a -3': ' !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&($%&(!- ,+*)#&$%-(!+ ,#*)%&$!-(,+ )#*',\n 'I 21/a -3': ' !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&($%&(!- ,+*)#&$%-(!+ ,#*)%&$!-(,+ )#*()+$,#*g& %-+()#$,&*!- %)+(,#$!&*%- *,- )&(%#$!+-*,& )#(%+$!,-*)& %#(!+$',\n 'P 4 3 2': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$',\n 'P 42 3 2': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,*',\n 'F 4 3 2': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$ )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-(!(-%*-!*+%(+ +,$+)$-, -)#)*#,(&)(&,*(!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&() -,$-)$+, +(#,*#)*&,(&)+!*+%(-!(-%*()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- )(&,*&)*#,(#(+%*+!*-%(-!+)$+, -) -,$',\n 'F 41 3 2': ' !#$,+*)&(%-# !+$,&*)-(%!# ,+$)&*%-(:3>46=7<98;5;58<976=43>:97<58;>:3=46 )+$%#*!-(,&#()+*%&$!- ,!+(,#*)-$%& :;=4<>765839;94<5:6>83=79:6543>7;=8<(!+*,#$)- %&+ )#$%-*!&(,)#(%+*!&$,- 73=86>:<54;935469:<=8;>7576983=:;>4<()#*%+$!& ,-+(!#*,-$)& %)+ %#$!-*,&(7;>8<=:69435398657<>4;=:5:<94;=73>86',\n 'I 4 3 2': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-()(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,*',\n 'P 43 3 2': ' !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(7;>46=:<5839398<5:6=4;>75:<983>7;=46',\n 'P 41 3 2': ' !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(:3=8<>7694;5;54697<>83=:97654;=:3>8<',\n 'I 41 3 2': ' !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(:3=8<>7694;5;54697<>83=:97654;=:3>8<()+$,#*!& %-+()#$,&*!- %)+(,#$!&*%- 7;>46=:<5839398<5:6=4;>75:<983>7;=46',\n 'P -4 3 m': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! #%$#!$&% & #!$#%$&! &%#! #%$&!$&% ',\n 'F -4 3 m': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! #%$#!$&% & #!$#%$&! &%#! #%$&!$&% )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-(!(+%*+!*-%(- +)$+,$-) -,#)(#,*&)*&,((!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&() +,$+)$-, -(#)*#,*&)(&,+!(+%*-!*-%(()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- )(#,*#)*&,(&(+!*+%*-!(-%+) +,$-)$-, ',\n 'I -4 3 m': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! #%$#!$&% & #!$#%$&! &%#! #%$&!$&% ()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-()(+,*+)*-,(-(+)*+,*-)(-,+)(+,*-)*-,(',\n 'P -4 3 n': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(+,*+)*-,(-(+)*+,*-)(-,+)(+,*-)*-,(',\n 'F -4 3 c': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(+,*+)*-,(-(+)*+,*-)(-,+)(+,*-)*-,( )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-() #,$#)$&, &(#!*#%*&!(&%+! +%$-!$-% (!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(!(#%*#!*&%(& +!$+%$-! -%#) #,$&)$&, ()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- ! +%$+!$-% - #)$#,$&) &,#!(#%*&!*&%(',\n 'I -4 3 d': ' !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(7354<9:6>8;=357<946>:;=857394<>:6=8;()+$,#*!& %-+()#$,&*!- %)+(,#$!&*%- :;98657<=43>;9:658<=73>49:;586=7<>43',\n 'P 4/m -3 2/m': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$%$#! #% &!$&$&! &% #!$#%&% &!$#%$#! ',\n 'P 4/n -3 2/n': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$*,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*,*+)(+,(-)*-*-)(-,(+)*+,-,(-)*+,*+)(',\n 'P 42/m -3 2/n': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,*$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$,*+)(+,(-)*-*-)(-,(+)*+,-,(-)*+,*+)(',\n 'P 42/n -3 2/m': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,**,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*%$#! #% &!$&$&! &% #!$#%&% &!$#%$#! ',\n 'F 4/m -3 2/m': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$%$#! #% &!$&$&! &% #!$#%&% &!$#%$#! )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-(!(-%*-!*+%(+ +,$+)$-, -)#)*#,(&)(&,*$,- )- ,+$)+&*,&()#(,#*)%-*!-(%+(!+*%*+!(+%(-!*-$-) -, +)$+,&,(&)*#,*#)((!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&() -,$-)$+, +(#,*#)*&,(&)+!*+%(-!(-%**%-(!-(%+*!+-$,- )+ ,+$),&*)&(,#()#*,$+) +, -)$-*&)(&,(#)*#,-%(-!*+%*+!(()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- )(&,*&)*#,(#(+%*+!*-%(-!+)$+, -) -,$*,&()&(,#*)#-*%-(!+(%+*!,-$)- ,+ )+$,*#)(#,(&)*&*-!(-%(+!*+%-, -)$+,$+) ',\n 'F 4/m -3 2/c': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& )(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,*$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$,*+)(+,(-)*-*-)(-,(+)*+,-,(-)*+,*+)( )+$,+$)- ,-#()#*,&*)&(,!+(%+*!-*%-() &,$&)$#, #(#%*#!*&%(&!+!$+% -! -%$$,- )- ,+$)+&*,&()#(,#*)%-*!-(%+(!+*,$#) #, &)$&*&!(&%(#!*#%-% -!$+%$+! (!+*%+*!-(%-+ )+$,-$)- ,)#(,#*)&*,&(!(&%*&!*#%(# +%$+!$-% -!#)$#, &) &,$*%-(!-(%+*!+-$,- )+ ,+$),&*)&(,#()#*%*#!(#%(&!*&$-! -% +!$+%&, &)$#,$#) ()#*,#*)&(,&+(!+*%-*!-(%)+ ,+$)-$,- ! -%$-!$+% + #,$#)$&, &)#!*#%(&!(&%**,&()&(,#*)#-*%-(!+(%+*!,-$)- ,+ )+$%$+! +% -!$-$&) &, #)$#,&%(&!*#%*#!(',\n 'F 41/d -3 2/m': ' !#$,+*)&(%-# !+$,&*)-(%!# ,+$)&*%-(:3>46=7<98;5;58<976=43>:97<58;>:3=4664=3:>;85<79=64>3:5;89<74=6:>385;79<,$+! #%(-)*&*&)(-% #!$+,-%(&)*+,$#! )+$%#*!-(,&#()+*%&$!- ,!+(,#*)-$%& :;=4<>765839;94<5:6>83=79:6543>7;=8<68>37=;49<:5=<8>;753496:4><:=;893756,*#!(+% &)$-*-!(&, +)$#%-, &!$+%*#)((!+*,#$)- %&+ )#$%-*!&(,)#(%+*!&$,- 73=86>:<54;935469:<=8;>7576983=:;>4<<4>;:=389675>68=379;45<:8=<7>;453:96%$#) +,(&!*-$&! -,(#)*+%&% -)$#,*+!(()#*%+$!& ,-+(!#*,-$)& %)+ %#$!-*,&(7;>8<=:69435398657<>4;=:5:<94;=73>86<8=;7>3456:9><4=;:9385678>67=349;:5<%*+)(#, -!$&$-) &%(+!*#,&,(-!*#%$+) ',\n 'F 41/d -3 2/c': ' !#$,+*)&(%-# !+$,&*)-(%!# ,+$)&*%-(:3>46=7<98;5;58<976=43>:97<58;>:3=46<8>;7=3496:5><8=;793456:8><7=;493:56%*#)(+, &!$-$-! &,(+)*#%&, -!$#%*+)( )+$%#*!-(,&#()+*%&$!- ,!+(,#*)-$%& :;=4<>765839;94<5:6>83=79:6543>7;=8<<4=;:>385679>64=3:9;85<78=67>345;:9<%$+) #,(-!*&$&) -%(#!*+,&%(-)*#,$+! (!+*,#$)- %&+ )#$%-*!&(,)#(%+*!&$,- 73=86>:<54;935469:<=8;>7576983=:;>4<68=37>;45<:9=<4>;:5389674>6:=389;75<,*+!(#% -)$&*-)(&% +!$#,-,(&!*+%$#) ()#*%+$!& ,-+(!#*,-$)& %)+ %#$!-*,&(7;>8<=:69435398657<>4;=:5:<94;=73>8664>3:=;89<75=68>375;49<:4=<:>;853796,$#! +%(&)*-*&!(-, #)$+%-% &)$+,*#!(',\n 'I 4/m -3 2/m': ' !#$%#$!& %&# !#$%&$!& %!# %#$!&$%& ! &%$&!$#% # #%$#!$&% &!#!$#% &! &%$$%& !& %#$!#&$%& !# %#$!%&$!& %# !#$%$#! #% &!$&$&! &% #!$#%&% &!$#%$#! ()+*,+*)-(,-+()+*,-*)-(,)+(,+*)-*,-()(-,*-)*+,(+(+,*+)*-,(-)+)*+,(-)(-,**,-()-(,+*)+-*,-()+(,+*),-*)-(,+()+*,*+)(+,(-)*-*-)(-,(+)*+,-,(-)*+,*+)(',\n 'I 41/a -3 2/d': ' !#*%+$)-(,&# !+*%-$)&(,!# %+*)-$,&(:3=8<>7694;5;54697<>83=:97654;=:3>8<$%&(!- ,+*)#&$%-(!+ ,#*)%&$!-(,+ )#*4<97358;=:6>6>:;=8357<94=8;>:694<573()+$,#*!& %-+()#$,&*!- %)+(,#$!&*%- 7;>46=:<5839398<5:6=4;>75:<983>7;=46*,- )&(%#$!+-*,& )#(%+$!,-*)& %#(!+$865:;943>7<=<=73>4;9:658>43=7<5869:;',\n 'P 1 1 2': ' !#$%#',\n 'P 1 1 21': ' !#$%+',\n 'B 1 1 2': ' !#$%#(g+*%+',\n 'A 1 2 1': ' !#$!& )+$)-',\n 'C 1 21 1': ' !#$)&()#*!&',\n 'I 1 2 1': \" !#$!&.'/0'2\",\n 'I 1 21 1': \" !#$)&.'/0!-\",\n 'P 1 1 m': ' !# !&',\n 'P 1 1 b': ' !# )&',\n 'B 1 1 m': ' !# !&(!+(!-',\n 'B 1 1 b': ' !# )&(!+()-',\n 'P 1 1 2/m': ' !# !&$%#$%&',\n 'P 1 1 21/m': ' !#$%+$%& !-',\n 'B 1 1 2/m': ' !# !&$%#$%&(!+(!-*%+*%-',\n 'P 1 1 2/b': ' !#$,#$%& )&',\n 'P 1 1 21/b': ' !#$%&$,+ )-',\n 'B 1 1 2/b': ' !#$,#$%& )&(!+*,+*%-()-',\n 'P 21 2 2': ' !#$!&(%&*%#',\n 'P 2 21 2': ' !# ,&$)&$%#',\n 'P 21 21 2 (a)': \" !#*,#.%&$'&\",\n 'P 21 2 21': ' !#$!&(%-*%+',\n 'P 2 21 21': ' !# %&$)-$,+',\n 'C 2 2 21a)': ' !#*%+(,&$)-()#$,+ %&*!-',\n 'C 2 2 2a': \" !#*,#.%&$'&()#$%# ,&*!&\",\n 'F 2 2 2a': \" !#*,#.%&$'& '/*%/.12$!2.!/$,/ %20'2.'#$%# 1&0!&\",\n 'I 2 2 2a': \" !#*,#.%&$'&()+$%+*!- ,-\",\n 'P 21/m 21/m 2/n a': \" !#*,#$)&(%&$%&.'& ,#*!#\",\n 'P 42 21 2a': \" !#*,#%.+'$+$'&.%&! -,*-\",\n 'I 2 3a': \" !#*,#.%&$'&!# ,- '&$%/$# !-*!/$%&.%()+$%+ ,-*!-)+(%&(!-*,#*+()&$)#*,- ,\"\n}\n","/**\n * @file Symmetry Utils\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4 } from 'three'\n\nimport { Log } from '../globals'\nimport { EncodedSymOp, SymOpCode } from './symmetry-constants'\n\nconst reInteger = /^[1-9]$/\n\nexport function getSymmetryOperations (spacegroup: string) {\n const encodedSymopList = EncodedSymOp[ spacegroup ]\n const matrixDict: { [k: string]: Matrix4 } = {}\n\n if (encodedSymopList === undefined) {\n console.warn(`spacegroup '${spacegroup}' not found in symop library`)\n return matrixDict\n }\n\n const symopList = []\n for (let i = 0, il = encodedSymopList.length; i < il; i += 3) {\n const symop = []\n for (let j = 0; j < 3; ++j) {\n symop.push(SymOpCode[ encodedSymopList[ i + j ] ])\n }\n symopList.push(symop)\n }\n\n symopList.forEach(function (symop) {\n let row = 0\n const matrix = new Matrix4().set(\n 0, 0, 0, 0,\n 0, 0, 0, 0,\n 0, 0, 0, 0,\n 0, 0, 0, 1\n )\n const me = matrix.elements\n\n matrixDict[ symop.toString() ] = matrix\n\n symop.forEach(function (elm) {\n let negate = false\n let denominator = false\n\n for (let i = 0, n = elm.length; i < n; ++i) {\n const c = elm[ i ]\n\n if (c === '-') {\n negate = true\n } else if (c === '+') {\n negate = false\n } else if (c === '/') {\n denominator = true\n } else if (c === 'X') {\n me[ 0 + row ] = negate ? -1 : 1\n } else if (c === 'Y') {\n me[ 4 + row ] = negate ? -1 : 1\n } else if (c === 'Z') {\n me[ 8 + row ] = negate ? -1 : 1\n } else if (reInteger.test(c)) {\n const integer = parseInt(c)\n if (denominator) {\n me[ 12 + row ] /= integer\n } else {\n me[ 12 + row ] = integer\n }\n } else {\n Log.warn(`getSymmetryOperations: unknown token '${c}'`)\n }\n }\n\n row += 1\n })\n })\n\n return matrixDict\n}\n","/**\n * @file Assembly\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4, Box3, Vector3 } from 'three'\n\nimport { uniqueArray } from '../utils'\nimport Selection from '../selection/selection'\nimport Structure from '../structure/structure'\nimport StructureView from '../structure/structure-view';\n\nfunction selectionFromChains (chainList: string[]) {\n let sele = ''\n if (chainList.length > 0) {\n sele = ':' + uniqueArray(chainList).join(' OR :')\n }\n return new Selection(sele)\n}\n\n/**\n * Assembly of transformed parts of a {@link Structure}\n */\nclass Assembly {\n partList: AssemblyPart[] = []\n\n /**\n * @param {String} name - assembly name\n */\n constructor (readonly name = '') {}\n\n get type () { return 'Assembly' }\n\n /**\n * Add transformed parts to the assembly\n * @example\n * var m1 = new NGL.Matrix4().set( ... );\n * var m2 = new NGL.Matrix4().set( ... );\n * var assembly = new NGL.Assembly( \"myAssembly\" );\n * // add part that transforms chain 'A' and 'B' using matrices `m1` and `m2`\n * assembly.addPart( [ m1, m2 ], [ \"A\", \"B\" ] )\n *\n * @param {Matrix4[]} matrixList - array of 4x4 transformation matrices\n * @param {String[]} chainList - array of chain names\n * @return {AssemblyPart} the added assembly part\n */\n addPart (matrixList?: Matrix4[], chainList?: string[]) {\n const part = new AssemblyPart(matrixList, chainList)\n this.partList.push(part)\n return part\n }\n\n /**\n * Get the number of atom for a given structure\n * @param {Structure} structure - the given structure\n * @return {Integer} number of atoms in the assembly\n */\n getAtomCount (structure: Structure) {\n return this.partList.reduce(\n (count, part) => count + part.getAtomCount(structure), 0\n )\n }\n\n /**\n * Get the number of residues for a given structure\n * @param {Structure} structure - the given structure\n * @return {Integer} number of residues in the assembly\n */\n getResidueCount (structure: Structure) {\n return this.partList.reduce(\n (count, part) => count + part.getResidueCount(structure), 0\n )\n }\n\n /**\n * Get number of instances the assembly will produce, i.e.\n * the number of transformations performed by the assembly\n * @return {Integer} number of instances\n */\n getInstanceCount () {\n let instanceCount = 0\n\n this.partList.forEach(function (part) {\n instanceCount += part.matrixList.length\n })\n\n return instanceCount\n }\n\n /**\n * Determine if the assembly is the full and untransformed structure\n * @param {Structure} structure - the given structure\n * @return {Boolean} whether the assembly is identical to the structure\n */\n isIdentity (structure: Structure) {\n if (this.partList.length !== 1) return false\n\n const part = this.partList[ 0 ]\n if (part.matrixList.length !== 1) return false\n\n const identityMatrix = new Matrix4()\n if (!identityMatrix.equals(part.matrixList[ 0 ])) return false\n\n let structureChainList: string[] = []\n structure.eachChain(function (cp) {\n structureChainList.push(cp.chainname)\n })\n structureChainList = uniqueArray(structureChainList)\n if (part.chainList.length !== structureChainList.length) return false\n\n return true\n }\n\n getBoundingBox (structure: Structure) {\n const boundingBox = new Box3()\n\n this.partList.forEach(function (part) {\n const partBox = part.getBoundingBox(structure)\n boundingBox.expandByPoint(partBox.min)\n boundingBox.expandByPoint(partBox.max)\n })\n\n return boundingBox\n }\n\n getCenter (structure: Structure) {\n return this.getBoundingBox(structure).getCenter(new Vector3())\n }\n\n getSelection () {\n let chainList: string[] = []\n this.partList.forEach(function (part) {\n chainList = chainList.concat(part.chainList)\n })\n return selectionFromChains(chainList)\n }\n}\n\nexport class AssemblyPart {\n constructor (readonly matrixList: Matrix4[] = [], readonly chainList: string[] = []) {}\n\n get type () { return 'AssemblyPart' }\n\n _getCount (structure: Structure, propertyName: 'atomCount'|'residueCount') {\n let count = 0\n\n structure.eachChain(cp => {\n if (this.chainList.length === 0 || this.chainList.includes(cp.chainname)) {\n count += cp[ propertyName ]\n }\n })\n\n return this.matrixList.length * count\n }\n\n getAtomCount (structure: Structure) {\n return this._getCount(structure, 'atomCount')\n }\n\n getResidueCount (structure: Structure) {\n return this._getCount(structure, 'residueCount')\n }\n\n getBoundingBox (structure: Structure) {\n const partBox = new Box3()\n const instanceBox = new Box3()\n\n const selection = this.getSelection()\n const structureBox = structure.getBoundingBox(selection)\n\n this.matrixList.forEach(function (matrix) {\n instanceBox.copy(structureBox).applyMatrix4(matrix)\n partBox.expandByPoint(instanceBox.min)\n partBox.expandByPoint(instanceBox.max)\n })\n\n return partBox\n }\n\n getSelection () {\n return selectionFromChains(this.chainList)\n }\n\n getView (structure: Structure): Structure | StructureView {\n const selection = this.getSelection()\n if (selection) {\n return structure.getView(selection)\n } else {\n return structure\n }\n }\n\n getInstanceList () {\n const instanceList = []\n for (let j = 0, jl = this.matrixList.length; j < jl; ++j) {\n instanceList.push({\n id: j + 1,\n name: j,\n matrix: this.matrixList[ j ]\n })\n }\n return instanceList\n }\n}\n\nexport default Assembly\n","/**\n * @file Structure Builder\n * @author Alexander Rose \n * @private\n */\n\nimport Structure from './structure'\n\nclass StructureBuilder {\n currentModelindex: number|null = null\n currentChainid: string|null = null\n currentResname: string|null = null\n currentResno: number|null = null\n currentInscode: string|undefined = undefined\n currentHetero: boolean|null = null\n\n previousResname: string|null = ''\n previousHetero: boolean|null = null\n\n ai = -1\n ri = -1\n ci = -1\n mi = -1\n\n constructor(readonly structure: Structure) {}\n\n addResidueType (ri: number) {\n const atomStore = this.structure.atomStore\n const residueStore = this.structure.residueStore\n const residueMap = this.structure.residueMap\n const cc = this.structure.chemCompMap?.dict[this.previousResname!]\n\n const count = residueStore.atomCount[ ri ]\n const offset = residueStore.atomOffset[ ri ]\n const atomTypeIdList = new Array(count)\n for (let i = 0; i < count; ++i) {\n atomTypeIdList[ i ] = atomStore.atomTypeId[ offset + i ]\n }\n const chemCompType = cc?.chemCompType\n const bonds = cc ? this.structure.chemCompMap?.getBonds(this.previousResname!, atomTypeIdList) : undefined\n residueStore.residueTypeId[ ri ] = residueMap.add(\n this.previousResname!, atomTypeIdList, this.previousHetero!, chemCompType, bonds\n )\n }\n\n addAtom (modelindex: number, chainname: string, chainid: string, resname: string, resno: number, hetero: boolean, sstruc?: string|undefined, inscode?: string|undefined) {\n const atomStore = this.structure.atomStore\n const residueStore = this.structure.residueStore\n const chainStore = this.structure.chainStore\n const modelStore = this.structure.modelStore\n\n let addModel = false\n let addChain = false\n let addResidue = false\n\n if (this.currentModelindex !== modelindex) {\n addModel = true\n addChain = true\n addResidue = true\n this.mi += 1\n this.ci += 1\n this.ri += 1\n } else if (this.currentChainid !== chainid) {\n addChain = true\n addResidue = true\n this.ci += 1\n this.ri += 1\n } else if (this.currentResno !== resno || this.currentResname !== resname || this.currentInscode !== inscode) {\n addResidue = true\n this.ri += 1\n }\n this.ai += 1\n\n if (addModel) {\n modelStore.growIfFull()\n modelStore.chainOffset[ this.mi ] = this.ci\n modelStore.chainCount[ this.mi ] = 0\n modelStore.count += 1\n chainStore.modelIndex[ this.ci ] = this.mi\n }\n\n if (addChain) {\n chainStore.growIfFull()\n chainStore.setChainname(this.ci, chainname)\n chainStore.setChainid(this.ci, chainid)\n chainStore.residueOffset[ this.ci ] = this.ri\n chainStore.residueCount[ this.ci ] = 0\n chainStore.count += 1\n chainStore.modelIndex[ this.ci ] = this.mi\n modelStore.chainCount[ this.mi ] += 1\n residueStore.chainIndex[ this.ri ] = this.ci\n }\n\n if (addResidue) {\n this.previousResname = this.currentResname\n this.previousHetero = this.currentHetero\n if (this.ri > 0) this.addResidueType(this.ri - 1)\n residueStore.growIfFull()\n residueStore.resno[ this.ri ] = resno\n if (sstruc !== undefined) {\n residueStore.sstruc[ this.ri ] = sstruc.charCodeAt(0)\n }\n if (inscode !== undefined) {\n residueStore.inscode[ this.ri ] = inscode.charCodeAt(0)\n }\n residueStore.atomOffset[ this.ri ] = this.ai\n residueStore.atomCount[ this.ri ] = 0\n residueStore.count += 1\n residueStore.chainIndex[ this.ri ] = this.ci\n chainStore.residueCount[ this.ci ] += 1\n }\n\n atomStore.count += 1\n atomStore.residueIndex[ this.ai ] = this.ri\n residueStore.atomCount[ this.ri ] += 1\n\n this.currentModelindex = modelindex\n this.currentChainid = chainid\n this.currentResname = resname\n this.currentResno = resno\n this.currentInscode = inscode\n this.currentHetero = hetero\n }\n\n finalize () {\n this.previousResname = this.currentResname\n this.previousHetero = this.currentHetero\n if (this.ri > -1) this.addResidueType(this.ri)\n }\n}\n\nexport default StructureBuilder\n","/**\n * @file Structure Utils\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Matrix4 } from 'three'\n\nimport { Debug, Log } from '../globals'\nimport { binarySearchIndexOf } from '../utils'\nimport Helixbundle from '../geometry/helixbundle'\nimport Kdtree from '../geometry/kdtree'\nimport { getSymmetryOperations } from '../symmetry/symmetry-utils'\nimport Assembly from '../symmetry/assembly'\nimport Structure from '../structure/structure'\nimport StructureBuilder from '../structure/structure-builder'\nimport Polymer from '../proxy/polymer'\nimport ResidueProxy from '../proxy/residue-proxy'\n\nimport { UnknownBackboneType, AA3, Bases, AtomicNumbers } from './structure-constants'\n\nexport function reorderAtoms (structure: Structure) {\n if (Debug) Log.time('reorderAtoms')\n\n var ap1 = structure.getAtomProxy()\n var ap2 = structure.getAtomProxy()\n\n function compareModelChainResno (index1: number, index2: number) {\n ap1.index = index1\n ap2.index = index2\n if (ap1.modelIndex < ap2.modelIndex) {\n return -1\n } else if (ap1.modelIndex > ap2.modelIndex) {\n return 1\n } else {\n if (ap1.chainname < ap2.chainname) {\n return -1\n } else if (ap1.chainname > ap2.chainname) {\n return 1\n } else {\n if (ap1.resno < ap2.resno) {\n return -1\n } else if (ap1.resno > ap2.resno) {\n return 1\n } else {\n return 0\n }\n }\n }\n }\n\n structure.atomStore.sort(compareModelChainResno)\n\n if (Debug) Log.timeEnd('reorderAtoms')\n}\n\nexport interface SecStruct {\n helices: [string, number, string, string, number, string, number][]\n sheets: [string, number, string, string, number, string][]\n}\n\nexport function assignSecondaryStructure (structure: Structure, secStruct: SecStruct) {\n if (!secStruct) return\n\n if (Debug) Log.time('assignSecondaryStructure')\n\n const chainnames: string[] = []\n structure.eachModel(function (mp) {\n mp.eachChain(function (cp) {\n chainnames.push(cp.chainname)\n })\n })\n\n const chainnamesSorted = chainnames.slice().sort()\n const chainnamesIndex: number[] = []\n chainnamesSorted.forEach(function (c) {\n chainnamesIndex.push(chainnames.indexOf(c))\n })\n\n // helix assignment\n\n const helices = secStruct.helices.filter(function (h) {\n return binarySearchIndexOf(chainnamesSorted, h[ 0 ]) >= 0\n })\n\n helices.sort(function (h1, h2) {\n const c1 = h1[ 0 ]\n const c2 = h2[ 0 ]\n const r1 = h1[ 1 ]\n const r2 = h2[ 1 ]\n\n if (c1 === c2) {\n if (r1 === r2) {\n return 0\n } else {\n return r1 < r2 ? -1 : 1\n }\n } else {\n const idx1 = binarySearchIndexOf(chainnamesSorted, c1)\n const idx2 = binarySearchIndexOf(chainnamesSorted, c2)\n return chainnamesIndex[ idx1 ] < chainnamesIndex[ idx2 ] ? -1 : 1\n }\n })\n\n const residueStore = structure.residueStore\n\n structure.eachModel(function (mp) {\n let i = 0\n const n = helices.length\n if (n === 0) return\n let helix = helices[ i ]\n let helixRun = false\n let done = false\n\n mp.eachChain(function (cp) {\n let chainChange = false\n\n if (cp.chainname === helix[ 0 ]) {\n const count = cp.residueCount\n const offset = cp.residueOffset\n const end = offset + count\n\n for (let j = offset; j < end; ++j) {\n if (residueStore.resno[ j ] === helix[ 1 ] && // resnoBeg\n residueStore.getInscode(j) === helix[ 2 ] // inscodeBeg\n ) {\n helixRun = true\n }\n\n if (helixRun) {\n residueStore.sstruc[ j ] = helix[ 6 ]\n\n if (residueStore.resno[ j ] === helix[ 4 ] && // resnoEnd\n residueStore.getInscode(j) === helix[ 5 ] // inscodeEnd\n ) {\n helixRun = false\n i += 1\n\n if (i < n) {\n // must look at previous residues as\n // residues may not be ordered by resno\n j = offset - 1\n helix = helices[ i ]\n chainChange = cp.chainname !== helix[ 0 ]\n } else {\n done = true\n }\n }\n }\n\n if (chainChange || done) return\n }\n }\n })\n })\n\n // sheet assignment\n\n const sheets = secStruct.sheets.filter(function (s) {\n return binarySearchIndexOf(chainnamesSorted, s[ 0 ]) >= 0\n })\n\n sheets.sort(function (s1, s2) {\n const c1 = s1[ 0 ]\n const c2 = s2[ 0 ]\n\n if (c1 === c2) return 0\n const idx1 = binarySearchIndexOf(chainnamesSorted, c1)\n const idx2 = binarySearchIndexOf(chainnamesSorted, c2)\n return chainnamesIndex[ idx1 ] < chainnamesIndex[ idx2 ] ? -1 : 1\n })\n\n const strandCharCode = 'e'.charCodeAt(0)\n structure.eachModel(function (mp) {\n let i = 0\n const n = sheets.length\n if (n === 0) return\n let sheet = sheets[ i ]\n let sheetRun = false\n let done = false\n\n mp.eachChain(function (cp) {\n let chainChange = false\n\n if (cp.chainname === sheet[ 0 ]) {\n const count = cp.residueCount\n const offset = cp.residueOffset\n const end = offset + count\n\n for (let j = offset; j < end; ++j) {\n if (residueStore.resno[ j ] === sheet[ 1 ] && // resnoBeg\n residueStore.getInscode(j) === sheet[ 2 ] // inscodeBeg\n ) {\n sheetRun = true\n }\n\n if (sheetRun) {\n residueStore.sstruc[ j ] = strandCharCode\n\n if (residueStore.resno[ j ] === sheet[ 4 ] && // resnoEnd\n residueStore.getInscode(j) === sheet[ 5 ] // inscodeEnd\n ) {\n sheetRun = false\n i += 1\n\n if (i < n) {\n // must look at previous residues as\n // residues may not be ordered by resno\n j = offset - 1\n sheet = sheets[ i ]\n chainChange = cp.chainname !== sheet[ 0 ]\n } else {\n done = true\n }\n }\n }\n\n if (chainChange || done) return\n }\n }\n })\n })\n\n if (Debug) Log.timeEnd('assignSecondaryStructure')\n}\n\nexport const calculateSecondaryStructure = (function () {\n // Implementation for proteins based on \"pv\"\n //\n // assigns secondary structure information based on a simple and very fast\n // algorithm published by Zhang and Skolnick in their TM-align paper.\n // Reference:\n //\n // TM-align: a protein structure alignment algorithm based on the Tm-score\n // (2005) NAR, 33(7) 2302-2309\n\n const zhangSkolnickSS = function (polymer: Polymer, i: number, distances: number[], delta: number) {\n const structure = polymer.structure\n const offset = polymer.residueIndexStart\n const rp1 = structure.getResidueProxy()\n const rp2 = structure.getResidueProxy()\n const ap1 = structure.getAtomProxy()\n const ap2 = structure.getAtomProxy()\n\n for (let j = Math.max(0, i - 2); j <= i; ++j) {\n for (let k = 2; k < 5; ++k) {\n if (j + k >= polymer.residueCount) {\n continue\n }\n\n rp1.index = offset + j\n rp2.index = offset + j + k\n ap1.index = rp1.traceAtomIndex\n ap2.index = rp2.traceAtomIndex\n\n const d = ap1.distanceTo(ap2)\n\n if (Math.abs(d - distances[ k - 2 ]) > delta) {\n return false\n }\n }\n }\n\n return true\n }\n\n const isHelical = function (polymer: Polymer, i: number) {\n const helixDistances = [ 5.45, 5.18, 6.37 ]\n const helixDelta = 2.1\n return zhangSkolnickSS(polymer, i, helixDistances, helixDelta)\n }\n\n const isSheet = function (polymer: Polymer, i: number) {\n const sheetDistances = [ 6.1, 10.4, 13.0 ]\n const sheetDelta = 1.42\n return zhangSkolnickSS(polymer, i, sheetDistances, sheetDelta)\n }\n\n const proteinPolymer = function (p: Polymer) {\n const residueStore = p.residueStore\n const offset = p.residueIndexStart\n for (let i = 0, il = p.residueCount; i < il; ++i) {\n let sstruc = 'c'\n if (isHelical(p, i)) {\n sstruc = 'h'\n } else if (isSheet(p, i)) {\n sstruc = 'e'\n }\n residueStore.sstruc[ offset + i ] = sstruc.charCodeAt(0)\n }\n }\n\n const cgPolymer = function (p: Polymer) {\n const localAngle = 20\n const centerDist = 2.0\n\n const residueStore = p.residueStore\n const offset = p.residueIndexStart\n\n const helixbundle = new Helixbundle(p)\n const pos = helixbundle.position\n\n const c1 = new Vector3()\n const c2 = new Vector3()\n\n for (let i = 0, il = p.residueCount; i < il; ++i) {\n c1.fromArray(pos.center as any, i * 3) // TODO\n c2.fromArray(pos.center as any, i * 3 + 3) // TODO\n const d = c1.distanceTo(c2)\n\n if (d < centerDist && d > 1.0 && pos.bending[ i ] < localAngle) {\n residueStore.sstruc[ offset + i ] = 'h'.charCodeAt(0)\n residueStore.sstruc[ offset + i + 1 ] = 'h'.charCodeAt(0)\n }\n }\n }\n\n return function calculateSecondaryStructure (structure: Structure) {\n if (Debug) Log.time('calculateSecondaryStructure')\n\n structure.eachPolymer(function (p) {\n // assign secondary structure\n if (p.residueCount < 4) return\n if (p.isCg()) {\n cgPolymer(p)\n } else if (p.isProtein()) {\n proteinPolymer(p)\n } else {\n return\n }\n\n // set lone secondary structure assignments to \"c\"\n let prevSstruc: string\n let sstrucCount = 0\n p.eachResidue(function (r: ResidueProxy) {\n if (r.sstruc === prevSstruc) {\n sstrucCount += 1\n } else {\n if (sstrucCount === 1) {\n r.index -= 1\n r.sstruc = 'c'\n }\n sstrucCount = 1\n prevSstruc = r.sstruc\n }\n })\n })\n\n if (Debug) Log.timeEnd('calculateSecondaryStructure')\n }\n}())\n\n// const ChainnameAlphabet = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\" +\n// \"abcdefghijklmnopqrstuvwxyz\" +\n// \"0123456789\";\nconst ChainnameAlphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'\n\nexport function getChainname (index: number) {\n const n = ChainnameAlphabet.length\n let j = index\n let k = 0\n let chainname = ChainnameAlphabet[j % n]\n while (j >= n) {\n j = Math.floor(j / n)\n chainname += ChainnameAlphabet[j % n]\n k += 1\n }\n if (k >= 5) {\n Log.warn('chainname overflow')\n }\n return chainname\n}\n\ninterface ChainData {\n mIndex: number\n chainname: string\n rStart: number\n rCount: number\n}\n\n/**\n * When no chain names are set for the given structure, calculates\n * chains based on:\n * - polymer connectivity: when adjacent residues are not bonded, a new chain is created.\n * - non polymer chemical type: adjacent residues which are not polymers but are of the same\n * chemical type (e.g. water molecules) are grouped into the same chain.\n **/\nexport function calculateChainnames (structure: Structure, useExistingBonds = false) {\n if (Debug) Log.time('calculateChainnames')\n\n let doAutoChainName = true\n structure.eachChain(function (c) {\n if (c.chainname) doAutoChainName = false\n })\n\n if (doAutoChainName) {\n const modelStore = structure.modelStore\n const chainStore = structure.chainStore\n const residueStore = structure.residueStore\n\n const addChain = function (mIndex: number, chainname: string, rOffset: number, rCount: number) {\n const ci = chainStore.count\n for (let i = 0; i < rCount; ++i) {\n residueStore.chainIndex[ rOffset + i ] = ci\n }\n chainStore.growIfFull()\n chainStore.modelIndex[ ci ] = mIndex\n chainStore.setChainname(ci, chainname)\n chainStore.setChainid(ci, chainname)\n chainStore.residueOffset[ ci ] = rOffset\n chainStore.residueCount[ ci ] = rCount\n chainStore.count += 1\n modelStore.chainCount[ mIndex ] += 1\n }\n\n const ap1 = structure.getAtomProxy()\n const ap2 = structure.getAtomProxy()\n\n let i = 0\n let mi = 0\n let rStart = 0\n let rEnd = 0\n const chainData: ChainData[] = []\n\n if (residueStore.count === 1) {\n chainData.push({\n mIndex: 0,\n chainname: 'A',\n rStart: 0,\n rCount: 1\n })\n } else {\n structure.eachResidueN(2, function (rp1: ResidueProxy, rp2: ResidueProxy) {\n let newChain = false\n\n const bbType1 = rp1.backboneType\n const bbType2 = rp2.backboneType\n const bbTypeUnk = UnknownBackboneType\n\n rEnd = rp1.index\n\n if (rp1.modelIndex !== rp2.modelIndex) {\n newChain = true\n } else if (rp1.moleculeType !== rp2.moleculeType) {\n newChain = true\n } else if (bbType1 !== bbTypeUnk && bbType1 === bbType2) {\n ap1.index = rp1.backboneEndAtomIndex\n ap2.index = rp2.backboneStartAtomIndex\n if (useExistingBonds) {\n newChain = !ap1.hasBondTo(ap2)\n } else {\n newChain = !ap1.connectedTo(ap2)\n }\n }\n\n // current chain goes to end of the structure\n if (!newChain && rp2.index === residueStore.count - 1) {\n newChain = true\n rEnd = rp2.index\n }\n\n if (newChain) {\n chainData.push({\n mIndex: mi,\n chainname: getChainname(i),\n rStart: rStart,\n rCount: rEnd - rStart + 1\n })\n\n i += 1\n\n if (rp1.modelIndex !== rp2.modelIndex) {\n i = 0\n mi += 1\n }\n\n // new chain for the last residue of the structure\n if (rp2.index === residueStore.count - 1 && rEnd !== rp2.index) {\n chainData.push({\n mIndex: mi,\n chainname: getChainname(i),\n rStart: residueStore.count - 1,\n rCount: 1\n })\n }\n\n rStart = rp2.index\n rEnd = rp2.index\n }\n })\n }\n\n //\n\n chainStore.count = 0\n modelStore.chainCount.fill(0, 0, modelStore.count)\n modelStore.chainOffset.fill(0, 0, modelStore.count)\n chainData.forEach(function (d) {\n addChain(d.mIndex, d.chainname, d.rStart, d.rCount)\n })\n\n let chainOffset = 0\n structure.eachModel(function (mp) {\n modelStore.chainOffset[ mp.index ] = chainOffset\n chainOffset += modelStore.chainCount[ mp.index ]\n })\n }\n\n if (Debug) Log.timeEnd('calculateChainnames')\n}\n\nexport function calculateBonds (structure: Structure, inferBonds: InferBondsOptions='all') {\n if (inferBonds === 'none') return \n if (Debug) Log.time('calculateBonds')\n\n calculateBondsWithin(structure, false, inferBonds)\n calculateBondsBetween(structure)\n\n if (Debug) Log.timeEnd('calculateBonds')\n}\n\n/**\n * Should Bonds be inferred for `all` atoms, `none` or `auto`\n * If `auto`, any hetgroup residue with at least one CONECT record will \n * not have bonding inferred, and will rely on the CONECT records\n */\nexport type InferBondsOptions = 'all' | 'none' | 'auto'\n\nexport interface ResidueBonds {\n atomIndices1: number[]\n atomIndices2: number[]\n bondOrders: number[]\n}\n\n\nconst BondOrderTable: { [k: string]: number } = {\n 'HIS|CD2|CG': 2,\n 'HIS|CE1|ND1': 2,\n 'ARG|CZ|NH2': 2,\n 'PHE|CE1|CZ': 2,\n 'PHE|CD2|CE2': 2,\n 'PHE|CD1|CG': 2,\n 'TRP|CD1|CG': 2,\n 'TRP|CD2|CE2': 2,\n 'TRP|CE3|CZ3': 2,\n 'TRP|CH2|CZ2': 2,\n 'ASN|CG|OD1': 2,\n 'GLN|CD|OE1': 2,\n 'TYR|CD1|CG': 2,\n 'TYR|CD2|CE2': 2,\n 'TYR|CE1|CZ': 2,\n 'ASP|CG|OD1': 2,\n 'GLU|CD|OE1': 2,\n\n 'G|C8|N7': 2,\n 'G|C4|C5': 2,\n 'G|C2|N3': 2,\n 'G|C6|O6': 2,\n 'C|C4|N3': 2,\n 'C|C5|C6': 2,\n 'C|C2|O2': 2,\n 'A|C2|N3': 2,\n 'A|C6|N1': 2,\n 'A|C4|C5': 2,\n 'A|C8|N7': 2,\n 'U|C5|C6': 2,\n 'U|C2|O2': 2,\n 'U|C4|O4': 2,\n\n 'DG|C8|N7': 2,\n 'DG|C4|C5': 2,\n 'DG|C2|N3': 2,\n 'DG|C6|O6': 2,\n 'DC|C4|N3': 2,\n 'DC|C5|C6': 2,\n 'DC|C2|O2': 2,\n 'DA|C2|N3': 2,\n 'DA|C6|N1': 2,\n 'DA|C4|C5': 2,\n 'DA|C8|N7': 2,\n 'DT|C5|C6': 2,\n 'DT|C2|O2': 2,\n 'DT|C4|O4': 2\n}\nfunction getBondOrderFromTable (resname: string, atomname1: string, atomname2: string) {\n [ atomname1, atomname2 ] = atomname1 < atomname2 ? [ atomname1, atomname2 ] : [ atomname2, atomname1 ]\n if (AA3.includes(resname) && atomname1 === 'C' && atomname2 === 'O') return 2\n if (Bases.includes(resname) && atomname1 === 'OP1' && atomname2 === 'P') return 2\n return BondOrderTable[ `${resname}|${atomname1}|${atomname2}` ] || 1\n}\n\nexport function calculateResidueBonds (r: ResidueProxy) {\n const structure = r.structure\n const a1 = structure.getAtomProxy()\n const a2 = structure.getAtomProxy()\n\n const count = r.atomCount\n const offset = r.atomOffset\n const end = offset + count\n const end1 = end - 1\n\n const atomIndices1 = []\n const atomIndices2 = []\n const bondOrders = []\n\n if (count > 500) {\n if (Debug) Log.warn('more than 500 atoms, skip residue for auto-bonding', r.qualifiedName())\n } else {\n if (count > 50) {\n const kdtree = new Kdtree(r, true)\n const radius = r.isCg() ? 1.2 : 2.3\n\n for (let i = offset; i < end1; ++i) {\n a1.index = i\n const maxd = a1.covalent + radius + 0.3\n const nearestAtoms = kdtree.nearest(a1 as any, Infinity, maxd * maxd) // TODO\n const m = nearestAtoms.length\n for (let j = 0; j < m; ++j) {\n a2.index = nearestAtoms[ j ].index\n if (a1.index < a2.index) {\n if (a1.connectedTo(a2)) {\n atomIndices1.push(a1.index - offset)\n atomIndices2.push(a2.index - offset)\n bondOrders.push(getBondOrderFromTable(a1.resname, a1.atomname, a2.atomname))\n }\n }\n }\n }\n } else {\n for (let i = offset; i < end1; ++i) {\n a1.index = i\n for (let j = i + 1; j <= end1; ++j) {\n a2.index = j\n if (a1.connectedTo(a2)) {\n atomIndices1.push(i - offset)\n atomIndices2.push(j - offset)\n bondOrders.push(getBondOrderFromTable(a1.resname, a1.atomname, a2.atomname))\n }\n }\n }\n }\n }\n\n return {\n atomIndices1: atomIndices1,\n atomIndices2: atomIndices2,\n bondOrders: bondOrders\n }\n}\n\nexport function calculateAtomBondMap (structure: Structure) {\n if (Debug) Log.time('calculateAtomBondMap')\n\n var atomBondMap: number[][] = []\n\n structure.eachBond(function (bp) {\n var ai1 = bp.atomIndex1\n var ai2 = bp.atomIndex2\n if (atomBondMap[ ai1 ] === undefined) atomBondMap[ ai1 ] = []\n atomBondMap[ ai1 ][ ai2 ] = bp.index\n })\n\n if (Debug) Log.timeEnd('calculateAtomBondMap')\n\n return atomBondMap\n}\n\nexport function calculateBondsWithin (structure: Structure, onlyAddRung = false, inferBonds: InferBondsOptions='all') {\n if (Debug) Log.time('calculateBondsWithin')\n\n const bondStore = structure.bondStore\n const rungBondStore = structure.rungBondStore\n const rungAtomSet = structure.getAtomSet(false)\n const a1 = structure.getAtomProxy()\n const a2 = structure.getAtomProxy()\n const bp = structure.getBondProxy()\n const atomBondMap = onlyAddRung ? null : calculateAtomBondMap(structure)\n\n let bondedAtoms: Set\n if (!onlyAddRung && inferBonds === 'auto') {\n bondedAtoms = new Set()\n atomBondMap!.forEach((a, i) => {\n bondedAtoms.add(i)\n a.forEach(j => {bondedAtoms.add(j)})\n })\n }\n\n structure.eachResidue(function (r) {\n if (!onlyAddRung && atomBondMap) {\n const count = r.atomCount\n const offset = r.atomOffset\n\n if (count > 500) {\n Log.warn('more than 500 atoms, skip residue for auto-bonding', r.qualifiedName())\n return\n }\n\n if (inferBonds === 'auto' && r.hetero) {\n // Are bonds present on this residue?\n for (let rai=r.atomOffset; rai {\n ncsMatrixList.forEach(nm => {\n ncsUnitcellMatrixList.push(sm.clone().multiply(nm))\n })\n })\n unitcellAssembly.addPart(ncsUnitcellMatrixList)\n } else {\n unitcellAssembly.addPart(unitcellMatrixList)\n }\n\n const vec = new Vector3()\n const supercellAssembly = new Assembly('SUPERCELL')\n const supercellMatrixList = Array.prototype.concat.call(\n getMatrixList(vec.set(1, 0, 0)), // 655\n getMatrixList(vec.set(0, 1, 0)), // 565\n getMatrixList(vec.set(0, 0, 1)), // 556\n\n getMatrixList(vec.set(-1, 0, 0)), // 455\n getMatrixList(vec.set(0, -1, 0)), // 545\n getMatrixList(vec.set(0, 0, -1)), // 554\n\n getMatrixList(vec.set(1, 1, 0)), // 665\n getMatrixList(vec.set(1, 0, 1)), // 656\n getMatrixList(vec.set(0, 1, 1)), // 566\n\n getMatrixList(vec.set(-1, -1, 0)), // 445\n getMatrixList(vec.set(-1, 0, -1)), // 454\n getMatrixList(vec.set(0, -1, -1)), // 544\n\n getMatrixList(vec.set(1, -1, -1)), // 644\n getMatrixList(vec.set(1, 1, -1)), // 664\n getMatrixList(vec.set(1, -1, 1)), // 646\n getMatrixList(vec.set(-1, 1, 1)), // 466\n getMatrixList(vec.set(-1, -1, 1)), // 446\n getMatrixList(vec.set(-1, 1, -1)), // 464\n\n getMatrixList(vec.set(0, 1, -1)), // 564\n getMatrixList(vec.set(0, -1, 1)), // 546\n getMatrixList(vec.set(1, 0, -1)), // 654\n getMatrixList(vec.set(-1, 0, 1)), // 456\n getMatrixList(vec.set(1, -1, 0)), // 645\n getMatrixList(vec.set(-1, 1, 0)), // 465\n\n getMatrixList(), // 555\n getMatrixList(vec.set(1, 1, 1)), // 666\n getMatrixList(vec.set(-1, -1, -1)) // 444\n )\n if (structure.biomolDict.NCS) {\n const ncsSupercellMatrixList: Matrix4[] = []\n supercellMatrixList.forEach(function (sm: Matrix4) {\n ncsMatrixList.forEach(function (nm) {\n ncsSupercellMatrixList.push(sm.clone().multiply(nm))\n })\n })\n supercellAssembly.addPart(ncsSupercellMatrixList)\n } else {\n supercellAssembly.addPart(supercellMatrixList)\n }\n\n structure.biomolDict.UNITCELL = unitcellAssembly\n structure.biomolDict.SUPERCELL = supercellAssembly\n\n if (Debug) Log.timeEnd('buildUnitcellAssembly')\n}\n\nconst elm1 = [ 'H', 'C', 'O', 'N', 'S', 'P' ]\nconst elm2 = [ 'NA', 'CL', 'FE' ]\n\nexport function guessElement (atomName: string) {\n // Retain first group of letters in atomName\n let at = atomName.toUpperCase()\n let begin = 0, end = 0\n for (let i = 0; i < at.length ; i++) {\n if (at.charCodeAt(i) < 65) {\n if (end > 0) break\n ++begin\n }\n else end = i + 1\n }\n if (begin > 0 || end < at.length) at = at.substring(begin, end)\n \n const n = at.length\n\n if (n === 0) return ''\n if (n === 1) return at\n if (n === 2) {\n if (elm2.indexOf(at) !== -1) return at\n if (elm1.indexOf(at[0]) !== -1) return at[0]\n if (at in AtomicNumbers) return at\n }\n if (n >= 3) {\n if (elm1.indexOf(at[0]) !== -1) return at[0]\n }\n return ''\n}\n\n/**\n * Assigns ResidueType bonds.\n * @param {Structure} structure - the structure object\n * @return {undefined}\n */\nexport function assignResidueTypeBonds (structure: Structure) {\n // if( Debug ) Log.time( \"assignResidueTypeBonds\" )\n\n const bondHash = structure.bondHash! // TODO\n const countArray = bondHash.countArray\n const offsetArray = bondHash.offsetArray\n const indexArray = bondHash.indexArray\n const bp = structure.getBondProxy()\n\n structure.eachResidue(function (rp) {\n const residueType = rp.residueType\n if (residueType.bonds !== undefined) return\n\n var atomOffset = rp.atomOffset\n var atomIndices1: number[] = []\n var atomIndices2: number[] = []\n var bondOrders: number[] = []\n var bondDict: { [k: string]: boolean } = {}\n\n const nextAtomOffset = atomOffset + rp.atomCount\n\n rp.eachAtom(function (ap) {\n const index = ap.index\n const offset = offsetArray[ index ]\n const count = countArray[ index ]\n for (let i = 0, il = count; i < il; ++i) {\n bp.index = indexArray[ offset + i ]\n let idx1 = bp.atomIndex1\n if (idx1 < atomOffset || idx1 >= nextAtomOffset) {\n // Don't add bonds outside of this resiude\n continue\n }\n let idx2 = bp.atomIndex2\n if (idx2 < atomOffset || idx2 >= nextAtomOffset) {\n continue\n }\n\n if (idx1 > idx2) {\n const tmp = idx2\n idx2 = idx1\n idx1 = tmp\n }\n const hash = idx1 + '|' + idx2\n if (bondDict[ hash ] === undefined) {\n bondDict[ hash ] = true\n atomIndices1.push(idx1 - atomOffset)\n atomIndices2.push(idx2 - atomOffset)\n bondOrders.push(bp.bondOrder)\n }\n }\n })\n\n residueType.bonds = {\n atomIndices1: atomIndices1,\n atomIndices2: atomIndices2,\n bondOrders: bondOrders\n }\n })\n\n // if( Debug ) Log.timeEnd( \"assignResidueTypeBonds\" )\n}\n\nexport function concatStructures (name: string, ...structures: Structure[]) {\n if( Debug ) Log.time( \"concatStructures\" )\n\n const s = new Structure(name, '')\n const sb = new StructureBuilder(s)\n\n const atomStore = s.atomStore as any\n const atomMap = s.atomMap\n atomStore.addField('formalCharge', 1, 'int8')\n atomStore.addField('partialCharge', 1, 'float32')\n\n const atomIndexDict: { [k: number]: number } = {}\n\n let idx = 0\n let atomCount = 0\n let modelCount = 0\n structures.forEach(structure => {\n structure.eachAtom(a => {\n atomStore.growIfFull()\n atomStore.atomTypeId[ idx ] = atomMap.add(a.atomname, a.element)\n\n atomStore.x[ idx ] = a.x\n atomStore.y[ idx ] = a.y\n atomStore.z[ idx ] = a.z\n atomStore.serial[ idx ] = a.serial\n atomStore.formalCharge[ idx ] = a.formalCharge\n atomStore.partialCharge[ idx ] = a.partialCharge\n atomStore.altloc[ idx ] = a.altloc\n atomStore.occupancy[ idx ] = a.occupancy\n atomStore.bfactor[ idx ] = a.bfactor\n\n sb.addAtom(\n a.modelIndex + modelCount,\n a.chainname,\n a.chainid,\n a.resname,\n a.resno,\n a.hetero === 1,\n a.sstruc,\n a.inscode\n )\n\n atomIndexDict[a.index + atomCount] = idx\n idx += 1\n })\n atomCount += structure.atomStore.count\n modelCount += structure.modelStore.count\n })\n\n const bondStore = s.bondStore\n const a1 = s.getAtomProxy()\n const a2 = s.getAtomProxy()\n\n atomCount = 0\n structures.forEach(structure => {\n structure.eachBond(b => {\n a1.index = atomIndexDict[ b.atomIndex1 + atomCount ]\n a2.index = atomIndexDict[ b.atomIndex2 + atomCount ]\n bondStore.addBond(a1, a2, b.bondOrder)\n })\n atomCount += structure.atomStore.count\n })\n\n sb.finalize()\n\n calculateBondsBetween(s, true) // calculate backbone bonds\n calculateBondsWithin(s, true) // calculate rung bonds\n\n s.finalizeAtoms()\n s.finalizeBonds()\n assignResidueTypeBonds(s)\n\n if( Debug ) Log.timeEnd( \"concatStructures\" )\n\n return s\n}\n","/**\n * @file Atom Type\n * @author Alexander Rose \n * @private\n */\n\nimport { guessElement } from '../structure/structure-utils'\nimport {\n AtomicNumbers, DefaultAtomicNumber,\n VdwRadii, DefaultVdwRadius,\n CovalentRadii, DefaultCovalentRadius,\n Valences, DefaultValence,\n OuterShellElectronCounts, DefaultOuterShellElectronCount\n} from '../structure/structure-constants'\nimport Structure from '../structure/structure'\n\n// Li, Na, K, Rb, Cs Fr\nconst AlkaliMetals = [ 3, 11, 19, 37, 55, 87 ]\n\n// Be, Mg, Ca, Sr, Ba, Ra\nconst AlkalineEarthMetals = [ 4, 12, 20, 38, 56, 88 ]\n\n// C, P, S, Se\nconst PolyatomicNonmetals = [ 6, 15, 16, 34, ]\n\n// H, N, O, F, Cl, Br, I\nconst DiatomicNonmetals = [ 1, 7, 8, 9, 17, 35, 53 ]\n\n// He, Ne, Ar, Kr, Xe, Rn\nconst NobleGases = [ 2, 10, 18, 36, 54, 86 ]\n\n// Zn, Ga, Cd, In, Sn, Hg, Ti, Pb, Bi, Po, Cn\nconst PostTransitionMetals = [ 13, 30, 31, 48, 49, 50, 80, 81, 82, 83, 84, 85, 112 ]\n\n// B, Si, Ge, As, Sb, Te, At\nconst Metalloids = [ 5, 14, 32, 33, 51, 52, 85 ]\n\n// F, Cl, Br, I, At\nconst Halogens = [ 9, 17, 35, 53, 85 ]\n\n/**\n * Atom type\n */\nclass AtomType {\n element: string\n number: number\n vdw: number\n covalent: number\n\n /**\n * @param {Structure} structure - the structure object\n * @param {String} atomname - the name of the atom\n * @param {String} element - the chemical element\n */\n constructor (readonly structure: Structure, readonly atomname: string, element?: string) {\n element = element || guessElement(atomname)\n\n this.element = element\n this.number = AtomicNumbers[ element ] || DefaultAtomicNumber\n this.vdw = VdwRadii[ this.number ] || DefaultVdwRadius\n this.covalent = CovalentRadii[ this.number ] || DefaultCovalentRadius\n }\n\n getDefaultValence() {\n const vl = Valences[ this.number ]\n return vl ? vl[ 0 ] : DefaultValence\n }\n\n getValenceList () {\n return Valences[ this.number ] || []\n }\n\n getOuterShellElectronCount () {\n return OuterShellElectronCounts[ this.number ] || DefaultOuterShellElectronCount\n }\n\n isMetal () {\n return (\n this.isAlkaliMetal() ||\n this.isAlkalineEarthMetal() ||\n this.isLanthanide() ||\n this.isActinide() ||\n this.isTransitionMetal() ||\n this.isPostTransitionMetal()\n )\n }\n\n isNonmetal () {\n return (\n this.isDiatomicNonmetal() ||\n this.isPolyatomicNonmetal() ||\n this.isNobleGas()\n )\n }\n\n isMetalloid () {\n return Metalloids.includes(this.number)\n }\n\n isHalogen () {\n return Halogens.includes(this.number)\n }\n\n isDiatomicNonmetal () {\n return DiatomicNonmetals.includes(this.number)\n }\n\n isPolyatomicNonmetal () {\n return PolyatomicNonmetals.includes(this.number)\n }\n\n isAlkaliMetal () {\n return AlkaliMetals.includes(this.number)\n }\n\n isAlkalineEarthMetal () {\n return AlkalineEarthMetals.includes(this.number)\n }\n\n isNobleGas () {\n return NobleGases.includes(this.number)\n }\n\n isTransitionMetal () {\n const no = this.number\n return (\n (no >= 21 && no <= 29) ||\n (no >= 39 && no <= 47) ||\n (no >= 72 && no <= 79) ||\n (no >= 104 && no <= 108)\n )\n }\n\n isPostTransitionMetal () {\n return PostTransitionMetals.includes(this.number)\n }\n\n isLanthanide () {\n return this.number >= 57 && this.number <= 71\n }\n\n isActinide () {\n return this.number >= 89 && this.number <= 103\n }\n\n}\n\nexport default AtomType","/**\n * @file Atom Map\n * @author Alexander Rose \n * @private\n */\n\nimport AtomType from './atom-type'\nimport { guessElement } from '../structure/structure-utils'\nimport Structure from '../structure/structure'\n\nfunction getHash (atomname: string, element: string) {\n return atomname + '|' + element\n}\n\nclass AtomMap {\n dict: { [k: string]: number } = {}\n list: AtomType[] = []\n\n constructor (readonly structure: Structure) {\n this.structure = structure\n }\n\n add (atomname: string, element?: string) {\n atomname = atomname.toUpperCase()\n if (!element) {\n element = guessElement(atomname)\n } else {\n element = element.toUpperCase()\n }\n const hash = getHash(atomname, element)\n let id = this.dict[ hash ]\n if (id === undefined) {\n const atomType = new AtomType(this.structure, atomname, element)\n id = this.list.length\n this.dict[ hash ] = id\n this.list.push(atomType)\n }\n return id\n }\n\n get (id: number) {\n return this.list[ id ]\n }\n}\n\nexport default AtomMap\n","/**\n * @file Residue Type\n * @author Alexander Rose \n * @author Fred Ludlow\n * @private\n */\n\nimport { defaults } from '../utils'\nimport PrincipalAxes from '../math/principal-axes'\nimport { Matrix } from '../math/matrix-utils'\nimport { calculateResidueBonds, ResidueBonds } from '../structure/structure-utils'\nimport {\n Elements,\n ProteinType, RnaType, DnaType, WaterType, IonType, SaccharideType, UnknownType,\n ProteinBackboneType, RnaBackboneType, DnaBackboneType, UnknownBackboneType,\n CgProteinBackboneType, CgRnaBackboneType, CgDnaBackboneType,\n ChemCompProtein, ChemCompRna, ChemCompDna, ChemCompSaccharide,\n AA3, PurinBases, RnaBases, DnaBases, Bases, IonNames, WaterNames, SaccharideNames,\n ProteinBackboneAtoms, NucleicBackboneAtoms, ResidueTypeAtoms\n} from '../structure/structure-constants'\nimport Structure from '../structure/structure'\nimport ResidueProxy from '../proxy/residue-proxy'\nimport AtomProxy from '../proxy/atom-proxy'\n\nexport interface BondGraph {\n [k: number]: number[]\n}\n\nexport interface RingData {\n atomRings: number[][] // sparse array:\n // atomRings[atomIdx] -> array of ring indices\n rings: number[][] // rings as arrays of indices\n}\n\n/**\n * Residue type\n */\nexport default class ResidueType {\n resname: string\n atomTypeIdList: number[]\n hetero: number\n chemCompType: string\n bonds?: ResidueBonds\n rings?: RingData\n bondGraph?: BondGraph\n aromaticAtoms?: Uint8Array\n aromaticRings?: number[][]\n\n atomCount: number\n\n moleculeType: number\n backboneType: number\n backboneEndType: number\n backboneStartType: number\n backboneIndexList: number[]\n\n traceAtomIndex: number\n direction1AtomIndex: number\n direction2AtomIndex: number\n backboneStartAtomIndex: number\n backboneEndAtomIndex: number\n rungEndAtomIndex: number\n\n // Sparse array containing the reference atom index for each bond.\n bondReferenceAtomIndices: number[] = []\n\n /**\n * @param {Structure} structure - the structure object\n * @param {String} resname - name of the residue\n * @param {Array} atomTypeIdList - list of IDs of {@link AtomType}s corresponding\n * to the atoms of the residue\n * @param {Boolean} hetero - hetero flag\n * @param {String} chemCompType - chemical component type\n * @param {Object} [bonds] - TODO\n */\n constructor (readonly structure: Structure, resname: string, atomTypeIdList: number[], hetero: boolean, chemCompType: string, bonds?: ResidueBonds) {\n this.resname = resname\n this.atomTypeIdList = atomTypeIdList\n this.hetero = hetero ? 1 : 0\n this.chemCompType = chemCompType\n this.bonds = bonds\n this.atomCount = atomTypeIdList.length\n\n this.moleculeType = this.getMoleculeType()\n this.backboneType = this.getBackboneType(0)\n this.backboneEndType = this.getBackboneType(-1)\n this.backboneStartType = this.getBackboneType(1)\n this.backboneIndexList = this.getBackboneIndexList()\n\n const atomnames = ResidueTypeAtoms[ this.backboneType ]\n const atomnamesStart = ResidueTypeAtoms[ this.backboneStartType ]\n const atomnamesEnd = ResidueTypeAtoms[ this.backboneEndType ]\n\n const traceIndex = this.getAtomIndexByName(atomnames.trace)\n this.traceAtomIndex = defaults(traceIndex, -1)\n\n const dir1Index = this.getAtomIndexByName(atomnames.direction1)\n this.direction1AtomIndex = defaults(dir1Index, -1)\n\n const dir2Index = this.getAtomIndexByName(atomnames.direction2)\n this.direction2AtomIndex = defaults(dir2Index, -1)\n\n const bbStartIndex = this.getAtomIndexByName(atomnamesStart.backboneStart)\n this.backboneStartAtomIndex = defaults(bbStartIndex, -1)\n\n const bbEndIndex = this.getAtomIndexByName(atomnamesEnd.backboneEnd)\n this.backboneEndAtomIndex = defaults(bbEndIndex, -1)\n\n let rungEndIndex\n if (PurinBases.includes(resname)) {\n rungEndIndex = this.getAtomIndexByName('N1')\n } else {\n rungEndIndex = this.getAtomIndexByName('N3')\n }\n this.rungEndAtomIndex = defaults(rungEndIndex, -1)\n }\n\n getBackboneIndexList () {\n const backboneIndexList: number[] = []\n let atomnameList\n switch (this.moleculeType) {\n case ProteinType:\n atomnameList = ProteinBackboneAtoms\n break\n case RnaType:\n case DnaType:\n atomnameList = NucleicBackboneAtoms\n break\n default:\n return backboneIndexList\n }\n const atomMap = this.structure.atomMap\n const atomTypeIdList = this.atomTypeIdList\n for (let i = 0, il = this.atomCount; i < il; ++i) {\n const atomType = atomMap.get(atomTypeIdList[ i ])\n if (atomnameList.includes(atomType.atomname)) {\n backboneIndexList.push(i)\n }\n }\n return backboneIndexList\n }\n\n getMoleculeType () {\n if (this.isProtein()) {\n return ProteinType\n } else if (this.isRna()) {\n return RnaType\n } else if (this.isDna()) {\n return DnaType\n } else if (this.isWater()) {\n return WaterType\n } else if (this.isIon()) {\n return IonType\n } else if (this.isSaccharide()) {\n return SaccharideType\n } else {\n return UnknownType\n }\n }\n\n getBackboneType (position: number) {\n if (this.hasProteinBackbone(position)) {\n return ProteinBackboneType\n } else if (this.hasRnaBackbone(position)) {\n return RnaBackboneType\n } else if (this.hasDnaBackbone(position)) {\n return DnaBackboneType\n } else if (this.hasCgProteinBackbone(position)) {\n return CgProteinBackboneType\n } else if (this.hasCgRnaBackbone(position)) {\n return CgRnaBackboneType\n } else if (this.hasCgDnaBackbone(position)) {\n return CgDnaBackboneType\n } else {\n return UnknownBackboneType\n }\n }\n\n isProtein () {\n if (this.chemCompType) {\n return ChemCompProtein.includes(this.chemCompType)\n } else {\n return (\n this.hasAtomWithName('CA', 'C', 'N') ||\n AA3.includes(this.resname)\n )\n }\n }\n\n isCg () {\n const backboneType = this.backboneType\n return (\n backboneType === CgProteinBackboneType ||\n backboneType === CgRnaBackboneType ||\n backboneType === CgDnaBackboneType\n )\n }\n\n isNucleic () {\n return this.isRna() || this.isDna()\n }\n\n isRna () {\n if (this.chemCompType) {\n return ChemCompRna.includes(this.chemCompType)\n } else if (this.hetero === 1) {\n return false\n } else {\n return (\n this.hasAtomWithName(\n [ 'P', \"O3'\", 'O3*' ], [ \"C4'\", 'C4*' ], [ \"O2'\", 'O2*', \"F2'\", 'F2*' ]\n ) ||\n (RnaBases.includes(this.resname) &&\n (this.hasAtomWithName([ \"O2'\", 'O2*', \"F2'\", 'F2*' ])))\n )\n }\n }\n\n isDna () {\n if (this.chemCompType) {\n return ChemCompDna.includes(this.chemCompType)\n } else if (this.hetero === 1) {\n return false\n } else {\n return (\n (this.hasAtomWithName([ 'P', \"O3'\", 'O3*' ], [ \"C3'\", 'C3*' ]) &&\n !this.hasAtomWithName([ \"O2'\", 'O2*', \"F2'\", 'F2*' ])) ||\n DnaBases.includes(this.resname)\n )\n }\n }\n\n isHetero () {\n return this.hetero === 1\n }\n\n isIon () {\n return IonNames.includes(this.resname)\n }\n\n isWater () {\n return WaterNames.includes(this.resname)\n }\n\n isSaccharide () {\n if (this.chemCompType) {\n return ChemCompSaccharide.includes(this.chemCompType)\n } else {\n return SaccharideNames.includes(this.resname)\n }\n }\n\n isStandardAminoacid () {\n return AA3.includes(this.resname)\n }\n\n isStandardBase () {\n return Bases.includes(this.resname)\n }\n\n hasBackboneAtoms (position: number, type: number) {\n const atomnames = ResidueTypeAtoms[ type ]\n if (position === -1) {\n return this.hasAtomWithName(\n atomnames.trace,\n atomnames.backboneEnd,\n atomnames.direction1,\n atomnames.direction2\n )\n } else if (position === 0) {\n return this.hasAtomWithName(\n atomnames.trace,\n atomnames.direction1,\n atomnames.direction2\n )\n } else if (position === 1) {\n return this.hasAtomWithName(\n atomnames.trace,\n atomnames.backboneStart,\n atomnames.direction1,\n atomnames.direction2\n )\n } else {\n return this.hasAtomWithName(\n atomnames.trace,\n atomnames.backboneStart,\n atomnames.backboneEnd,\n atomnames.direction1,\n atomnames.direction2\n )\n }\n }\n\n hasProteinBackbone (position: number) {\n return (\n this.isProtein() &&\n this.hasBackboneAtoms(position, ProteinBackboneType)\n )\n }\n\n hasRnaBackbone (position: number) {\n return (\n this.isRna() &&\n this.hasBackboneAtoms(position, RnaBackboneType)\n )\n }\n\n hasDnaBackbone (position: number) {\n return (\n this.isDna() &&\n this.hasBackboneAtoms(position, DnaBackboneType)\n )\n }\n\n hasCgProteinBackbone (position: number) {\n return (\n this.atomCount < 7 &&\n this.isProtein() &&\n this.hasBackboneAtoms(position, CgProteinBackboneType)\n )\n }\n\n hasCgRnaBackbone (position: number) {\n return (\n this.atomCount < 11 &&\n this.isRna() &&\n this.hasBackboneAtoms(position, CgRnaBackboneType)\n )\n }\n\n hasCgDnaBackbone (position: number) {\n return (\n this.atomCount < 11 &&\n this.isDna() &&\n this.hasBackboneAtoms(position, CgDnaBackboneType)\n )\n }\n\n hasBackbone (position: number) {\n return (\n this.hasProteinBackbone(position) ||\n this.hasRnaBackbone(position) ||\n this.hasDnaBackbone(position) ||\n this.hasCgProteinBackbone(position) ||\n this.hasCgRnaBackbone(position) ||\n this.hasCgDnaBackbone(position)\n )\n }\n\n getAtomIndexByName (atomname: string|string[]) {\n const n = this.atomCount\n const atomMap = this.structure.atomMap\n const atomTypeIdList = this.atomTypeIdList\n if (Array.isArray(atomname)) {\n for (let i = 0; i < n; ++i) {\n const index = atomTypeIdList[ i ]\n if (atomname.includes(atomMap.get(index).atomname)) {\n return i\n }\n }\n } else {\n for (let i = 0; i < n; ++i) {\n const index = atomTypeIdList[ i ]\n if (atomname === atomMap.get(index).atomname) {\n return i\n }\n }\n }\n return undefined\n }\n\n hasAtomWithName (...atomnames: (string|string[])[]) {\n const n = atomnames.length\n for (let i = 0; i < n; ++i) {\n if (atomnames[ i ] === undefined) continue\n if (this.getAtomIndexByName(atomnames[ i ]) === undefined) {\n return false\n }\n }\n return true\n }\n\n getBonds (r?: ResidueProxy) {\n if (this.bonds === undefined) {\n this.bonds = calculateResidueBonds(r!) // TODO\n }\n return this.bonds\n }\n\n getRings () {\n if (this.rings === undefined) {\n this.calculateRings()\n }\n return this.rings\n }\n\n getBondGraph () {\n if (this.bondGraph === undefined) {\n this.calculateBondGraph()\n }\n return this.bondGraph\n }\n\n getAromatic (a?: AtomProxy) {\n if (this.aromaticAtoms === undefined) {\n this.calculateAromatic(this.structure.getResidueProxy((a!).residueIndex)) // TODO\n }\n return this.aromaticAtoms\n }\n\n getAromaticRings (r?: ResidueProxy) {\n if (this.aromaticRings === undefined) {\n this.calculateAromatic(r!) // TODO\n }\n return this.aromaticRings\n }\n\n /**\n * @return {Object} bondGraph - represents the bonding in this\n * residue: { ai1: [ ai2, ai3, ...], ...}\n */\n calculateBondGraph () {\n const bondGraph: BondGraph = this.bondGraph = {}\n const bonds = this.getBonds()\n const nb = bonds.atomIndices1.length\n const atomIndices1 = bonds.atomIndices1\n const atomIndices2 = bonds.atomIndices2\n\n for (let i = 0; i < nb; ++i) {\n const ai1 = atomIndices1[i]\n const ai2 = atomIndices2[i]\n\n const a1 = bondGraph[ ai1 ] = bondGraph[ ai1 ] || []\n a1.push(ai2)\n\n const a2 = bondGraph[ ai2 ] = bondGraph[ ai2 ] || []\n a2.push(ai1)\n }\n }\n\n /**\n * Find all rings up to 2 * RingFinderMaxDepth\n */\n calculateRings () {\n const bondGraph = this.getBondGraph()! // TODO\n const state = RingFinderState(bondGraph, this.atomCount)\n\n for (let i = 0; i < state.count; i++) {\n if (state.visited[i] >= 0) continue\n findRings(state, i)\n }\n\n this.rings = { atomRings: state.atomRings, rings: state.rings }\n }\n\n isAromatic (atom: AtomProxy) {\n this.aromaticAtoms = this.getAromatic(atom)! // TODO\n return this.aromaticAtoms[atom.index - atom.residueAtomOffset] === 1\n }\n\n calculateAromatic (r: ResidueProxy) {\n const aromaticAtoms = this.aromaticAtoms = new Uint8Array(this.atomCount)\n const rings = this.getRings()!.rings\n\n const aromaticRingFlags = rings.map(ring => {\n return isRingAromatic(ring.map(idx => {\n return this.structure.getAtomProxy(idx + r.atomOffset)\n }))\n })\n\n const aromaticRings: number[][] = this.aromaticRings = []\n rings.forEach((ring, i) => {\n if (aromaticRingFlags[i]) {\n aromaticRings.push(ring)\n ring.forEach(idx => aromaticAtoms[idx] = 1)\n }\n })\n }\n\n /**\n * For bonds with order > 1, pick a reference atom\n * @return {undefined}\n */\n assignBondReferenceAtomIndices () {\n const bondGraph = this.getBondGraph()! // TODO\n const rings = this.getRings()! // TODO\n const atomRings = rings.atomRings\n const ringData = rings.rings\n\n const bonds = this.bonds! // TODO\n const atomIndices1 = bonds.atomIndices1\n const atomIndices2 = bonds.atomIndices2\n const bondOrders = bonds.bondOrders\n const bondReferenceAtomIndices = this.bondReferenceAtomIndices\n\n const nb = bonds.atomIndices1.length\n\n bondReferenceAtomIndices.length = 0 // reset array\n\n for (let i = 0; i < nb; ++i) {\n // Not required for single bonds\n if (bondOrders[i] <= 1) continue\n\n let refRing\n\n const ai1 = atomIndices1[i]\n const ai2 = atomIndices2[i]\n\n const rings1 = atomRings[ ai1 ]\n const rings2 = atomRings[ ai2 ]\n // Are both atoms in a ring?\n if (rings1 && rings2) {\n // Are they in the same ring? (If not, ignore ring info)\n for (let ri1 = 0; ri1 < rings1.length; ri1++){\n if (rings2.indexOf(rings1[ ri1 ]) !== -1) {\n refRing = ringData[ rings1[ ri1 ] ]\n break\n }\n }\n }\n\n // Find the first neighbour.\n if (bondGraph[ ai1 ].length > 1) {\n for (let j = 0; j < bondGraph[ ai1 ].length; ++j) {\n const ai3 = bondGraph[ ai1 ][ j ]\n if (ai3 !== ai2) {\n if (refRing === undefined || refRing.indexOf(ai3) !== -1){\n bondReferenceAtomIndices[i] = ai3\n break\n }\n }\n }\n } else if (bondGraph[ ai2 ].length > 1) {\n for (let j = 0; j < bondGraph[ ai2 ].length; ++j) {\n const ai3 = bondGraph[ ai2 ][ j ]\n if (ai3 !== ai1) {\n if (refRing === undefined || refRing.indexOf(ai3) !== -1){\n bondReferenceAtomIndices[i] = ai3\n break\n }\n }\n }\n } // No reference atom could be found (e.g. diatomic molecule/fragment)\n }\n }\n\n getBondIndex (atomIndex1: number, atomIndex2: number) {\n const bonds = this.bonds! // TODO\n const atomIndices1 = bonds.atomIndices1\n const atomIndices2 = bonds.atomIndices2\n let idx1 = atomIndices1.indexOf(atomIndex1)\n let idx2 = atomIndices2.indexOf(atomIndex2)\n const _idx2 = idx2\n while (idx1 !== -1) {\n while (idx2 !== -1) {\n if (idx1 === idx2) return idx1\n idx2 = atomIndices2.indexOf(atomIndex2, idx2 + 1)\n }\n idx1 = atomIndices1.indexOf(atomIndex1, idx1 + 1)\n idx2 = _idx2\n }\n // returns undefined when no bond is found\n }\n\n getBondReferenceAtomIndex (atomIndex1: number, atomIndex2: number) {\n const bondIndex = this.getBondIndex(atomIndex1, atomIndex2)\n if (bondIndex === undefined) return undefined\n if (this.bondReferenceAtomIndices.length === 0) {\n this.assignBondReferenceAtomIndices()\n }\n return this.bondReferenceAtomIndices[ bondIndex ]\n }\n}\n\n//\n\nconst AromaticRingElements = [\n Elements.B, Elements.C, Elements.N, Elements.O,\n Elements.SI, Elements.P, Elements.S,\n Elements.GE, Elements.AS,\n Elements.SN, Elements.SB,\n Elements.BI\n]\nconst AromaticRingPlanarityThreshold = 0.05\n\nfunction isRingAromatic (ring: AtomProxy[]) {\n if (ring.some(a => !AromaticRingElements.includes(a.number))) return false\n\n let i = 0\n const coords = new Matrix(3, ring.length)\n const cd = coords.data\n\n ring.forEach(a => {\n cd[ i + 0 ] = a.x\n cd[ i + 1 ] = a.y\n cd[ i + 2 ] = a.z\n i += 3\n })\n\n const pa = new PrincipalAxes(coords)\n\n return pa.vecC.length() < AromaticRingPlanarityThreshold\n}\n\n//\n\n/**\n * Ring finding code below adapted from MolQL\n * Copyright (c) 2017 MolQL contributors, licensed under MIT\n * @author David Sehnal \n */\n\nfunction addRing(state: RingFinderState, a: number, b: number) {\n // only \"monotonous\" rings\n if (b < a) return\n\n const { pred, color, left, right } = state\n const nc = ++state.currentColor\n\n let current = a\n\n for (let t = 0; t < RingFinderMaxDepth; t++) {\n color[current] = nc\n current = pred[current]\n if (current < 0) break\n }\n\n let leftOffset = 0\n let rightOffset = 0\n\n let found = false\n let target = 0\n current = b\n for (let t = 0; t < RingFinderMaxDepth; t++) {\n if (color[current] === nc) {\n target = current\n found = true\n break\n }\n right[rightOffset++] = current\n current = pred[current]\n if (current < 0) break\n }\n if (!found) return\n\n current = a\n for (let t = 0; t < RingFinderMaxDepth; t++) {\n left[leftOffset++] = current\n if (target === current) break\n current = pred[current]\n if (current < 0) break\n }\n\n const rn = leftOffset + rightOffset\n const ring: number[] = new Array(rn)\n let ringOffset = 0;\n for (let t = 0; t < leftOffset; t++) {\n ring[ringOffset++] = left[t]\n }\n for (let t = rightOffset - 1; t >= 0; t--) {\n ring[ringOffset++] = right[t]\n }\n\n const ri = state.rings.length\n // set atomRing indices:\n for (let i = 0; i < rn; ++i) {\n const ai = ring[i]\n if (state.atomRings[ai]) {\n state.atomRings[ai].push(ri)\n } else {\n state.atomRings[ai] = [ri]\n }\n }\n\n state.rings.push(ring)\n}\n\nfunction findRings(state: RingFinderState, from: number) {\n const { bonds, visited, queue, pred } = state\n\n visited[from] = 1\n queue[0] = from\n\n let head = 0\n let size = 1\n\n while (head < size) {\n const top = queue[head++]\n const start = 0\n if (bonds[top] === undefined) {\n continue\n }\n const end = bonds[top].length\n\n for (let i = start; i < end; i++) {\n const other = bonds[top][i]\n\n if (visited[other] > 0) {\n if (pred[other] !== top && pred[top] !== other) {\n addRing(state, top, other)\n }\n continue\n }\n\n visited[other] = 1\n queue[size++] = other\n pred[other] = top\n }\n }\n}\n\nconst RingFinderMaxDepth = 4\n\ninterface RingFinderState {\n count: number,\n visited: Int32Array,\n queue: Int32Array,\n color: Int32Array,\n pred: Int32Array,\n\n left: Int32Array,\n right: Int32Array,\n\n currentColor: number,\n\n rings: number[][],\n atomRings: number[][],\n\n bonds: BondGraph\n}\n\nfunction RingFinderState(bonds: BondGraph, capacity: number): RingFinderState {\n const state = {\n count: capacity,\n visited: new Int32Array(capacity),\n queue: new Int32Array(capacity),\n pred: new Int32Array(capacity),\n left: new Int32Array(RingFinderMaxDepth),\n right: new Int32Array(RingFinderMaxDepth),\n color: new Int32Array(capacity),\n currentColor: 0,\n rings: [],\n atomRings: [],\n bonds\n }\n for (let i = 0; i < capacity; i++) {\n state.visited[i] = -1\n state.pred[i] = -1\n }\n return state\n}\n","/**\n * @file Residue Map\n * @author Alexander Rose \n * @private\n */\n\nimport Structure from '../structure/structure'\nimport { ResidueBonds } from '../structure/structure-utils'\nimport ResidueType from './residue-type'\n\nfunction getHash (resname: string, atomTypeIdList: number[], hetero: boolean, chemCompType = '') {\n return (\n resname + '|' +\n atomTypeIdList.join(',') + '|' +\n (hetero ? 1 : 0) + '|' +\n chemCompType\n )\n}\n\nclass ResidueMap {\n dict: { [k: string]: number } = {}\n list: ResidueType[] = []\n\n constructor (readonly structure: Structure) {}\n\n add (resname: string, atomTypeIdList: number[], hetero: boolean, chemCompType = '', bonds?: ResidueBonds) {\n resname = resname.toUpperCase()\n const hash = getHash(resname, atomTypeIdList, hetero, chemCompType)\n let id = this.dict[ hash ]\n if (id === undefined) {\n const residueType = new ResidueType(\n this.structure, resname, atomTypeIdList, hetero, chemCompType, bonds\n )\n id = this.list.length\n this.dict[ hash ] = id\n this.list.push(residueType)\n }\n return id\n }\n\n get (id: number) {\n return this.list[ id ]\n }\n}\n\nexport default ResidueMap\n","/**\n * @file Bond Proxy\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport Structure from '../structure/structure'\nimport BondStore from '../store/bond-store'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Bond proxy\n */\nclass BondProxy {\n index: number\n\n bondStore: BondStore\n\n private _v12: Vector3\n private _v13: Vector3\n private _ap1: AtomProxy\n private _ap2: AtomProxy\n private _ap3: AtomProxy\n\n /**\n * @param {Structure} structure - the structure\n * @param {Integer} index - the index\n */\n constructor (readonly structure: Structure, index = 0) {\n this.index = index\n this.bondStore = structure.bondStore\n\n this._v12 = new Vector3()\n this._v13 = new Vector3()\n this._ap1 = this.structure.getAtomProxy()\n this._ap2 = this.structure.getAtomProxy()\n this._ap3 = this.structure.getAtomProxy()\n }\n\n /**\n * @type {AtomProxy}\n */\n get atom1 () {\n return this.structure.getAtomProxy(this.atomIndex1)\n }\n\n /**\n * @type {AtomProxy}\n */\n get atom2 () {\n return this.structure.getAtomProxy(this.atomIndex2)\n }\n\n /**\n * @type {Integer}\n */\n get atomIndex1 () {\n return this.bondStore.atomIndex1[ this.index ]\n }\n set atomIndex1 (value) {\n this.bondStore.atomIndex1[ this.index ] = value\n }\n\n /**\n * @type {Integer}\n */\n get atomIndex2 () {\n return this.bondStore.atomIndex2[ this.index ]\n }\n set atomIndex2 (value) {\n this.bondStore.atomIndex2[ this.index ] = value\n }\n\n /**\n * @type {Integer}\n */\n get bondOrder () {\n return this.bondStore.bondOrder[ this.index ]\n }\n set bondOrder (value) {\n this.bondStore.bondOrder[ this.index ] = value\n }\n\n getOtherAtomIndex (atomIndex: number) {\n return atomIndex === this.atomIndex1 ? this.atomIndex2 : this.atomIndex1\n }\n\n getOtherAtom (atom: AtomProxy) {\n return this.structure.getAtomProxy(this.getOtherAtomIndex(atom.index))\n }\n\n /**\n * Get reference atom index for the bond\n * @return {Integer|undefined} atom index, or `undefined` if unavailable\n */\n getReferenceAtomIndex () {\n const ap1 = this._ap1\n const ap2 = this._ap2\n ap1.index = this.atomIndex1\n ap2.index = this.atomIndex2\n if (ap1.residueIndex !== ap2.residueIndex) {\n return undefined // Bond between residues, for now ignore (could detect)\n }\n const typeAtomIndex1 = ap1.index - ap1.residueAtomOffset\n const typeAtomIndex2 = ap2.index - ap2.residueAtomOffset\n const residueType = ap1.residueType\n const ix = residueType.getBondReferenceAtomIndex(typeAtomIndex1, typeAtomIndex2)\n if (ix !== undefined) {\n return ix + ap1.residueAtomOffset\n } else {\n console.warn('No reference atom found', ap1.index, ap2.index)\n }\n }\n\n /**\n * calculate shift direction for displaying double/triple bonds\n * @param {Vector3} [v] pre-allocated output vector\n * @return {Vector3} the shift direction vector\n */\n calculateShiftDir (v = new Vector3()) {\n const ap1 = this._ap1\n const ap2 = this._ap2\n const ap3 = this._ap3\n const v12 = this._v12\n const v13 = this._v13\n\n ap1.index = this.atomIndex1\n ap2.index = this.atomIndex2\n const ai3 = this.getReferenceAtomIndex()\n\n v12.subVectors(ap1 as any, ap2 as any).normalize() // TODO\n if (ai3 !== undefined) {\n ap3.index = ai3\n v13.subVectors(ap1 as any, ap3 as any) // TODO\n } else {\n v13.copy(ap1 as any) // no reference point, use origin // TODO\n }\n v13.normalize()\n\n // make sure v13 and v12 are not colinear\n let dp = v12.dot(v13)\n if (1 - Math.abs(dp) < 1e-5) {\n v13.set(1, 0, 0)\n dp = v12.dot(v13)\n if (1 - Math.abs(dp) < 1e-5) {\n v13.set(0, 1, 0)\n dp = v12.dot(v13)\n }\n }\n\n return v.copy(v13.sub(v12.multiplyScalar(dp))).normalize()\n }\n\n qualifiedName () {\n return this.atomIndex1 + '=' + this.atomIndex2\n }\n\n /**\n * Clone object\n * @return {BondProxy} cloned bond\n */\n clone () {\n return new BondProxy(this.structure, this.index)\n }\n\n toObject () {\n return {\n atomIndex1: this.atomIndex1,\n atomIndex2: this.atomIndex2,\n bondOrder: this.bondOrder\n }\n }\n}\n\nexport default BondProxy\n","/**\n * @file Residue Proxy\n * @author Alexander Rose \n * @private\n */\n\nimport { NumberArray } from '../types'\nimport { defaults } from '../utils'\nimport {\n SecStrucHelix, SecStrucSheet, SecStrucTurn,\n ProteinType, RnaType, DnaType, WaterType, IonType, SaccharideType,\n CgProteinBackboneType, CgRnaBackboneType, CgDnaBackboneType,\n AA1\n} from '../structure/structure-constants'\n\nimport Structure from '../structure/structure'\nimport Selection from '../selection/selection'\n\nimport ChainStore from '../store/chain-store'\nimport ResidueStore from '../store/residue-store'\nimport AtomStore from '../store/atom-store'\n\nimport AtomMap from '../store/atom-map'\nimport ResidueMap from '../store/residue-map'\n\nimport AtomProxy from '../proxy/atom-proxy'\nimport ResidueType, { RingData } from '../store/residue-type';\nimport { ResidueBonds } from '../structure/structure-utils';\nimport AtomType from '../store/atom-type';\nimport ChainProxy from './chain-proxy';\nimport Entity from '../structure/entity';\n\n/**\n * Residue proxy\n */\nclass ResidueProxy {\n index: number\n\n chainStore: ChainStore\n residueStore: ResidueStore\n atomStore: AtomStore\n\n residueMap: ResidueMap\n atomMap: AtomMap\n\n /**\n * @param {Structure} structure - the structure\n * @param {Integer} index - the index\n */\n constructor (readonly structure: Structure, index = 0) {\n this.index = index\n this.chainStore = structure.chainStore\n this.residueStore = structure.residueStore\n this.atomStore = structure.atomStore\n this.residueMap = structure.residueMap\n this.atomMap = structure.atomMap\n }\n\n /**\n * Entity\n * @type {Entity}\n */\n get entity (): Entity {\n return this.structure.entityList[ this.entityIndex ]\n }\n get entityIndex () {\n return this.chainStore.entityIndex[ this.chainIndex ]\n }\n /**\n * Chain\n * @type {ChainProxy}\n */\n get chain (): ChainProxy {\n return this.structure.getChainProxy(this.chainIndex)\n }\n\n get chainIndex () {\n return this.residueStore.chainIndex[ this.index ]\n }\n set chainIndex (value) {\n this.residueStore.chainIndex[ this.index ] = value\n }\n\n get atomOffset () {\n return this.residueStore.atomOffset[ this.index ]\n }\n set atomOffset (value) {\n this.residueStore.atomOffset[ this.index ] = value\n }\n\n /**\n * Atom count\n * @type {Integer}\n */\n get atomCount () {\n return this.residueStore.atomCount[ this.index ]\n }\n set atomCount (value) {\n this.residueStore.atomCount[ this.index ] = value\n }\n\n get atomEnd () {\n return this.atomOffset + this.atomCount - 1\n }\n\n //\n\n get modelIndex () {\n return this.chainStore.modelIndex[ this.chainIndex ]\n }\n /**\n * Chain name\n * @type {String}\n */\n get chainname () {\n return this.chainStore.getChainname(this.chainIndex)\n }\n /**\n * Chain id\n * @type {String}\n */\n get chainid () {\n return this.chainStore.getChainid(this.chainIndex)\n }\n\n //\n\n /**\n * Residue number/label\n * @type {Integer}\n */\n get resno () {\n return this.residueStore.resno[ this.index ]\n }\n set resno (value) {\n this.residueStore.resno[ this.index ] = value\n }\n\n /**\n * Secondary structure code\n * @type {String}\n */\n get sstruc () {\n return this.residueStore.getSstruc(this.index)\n }\n set sstruc (value) {\n this.residueStore.setSstruc(this.index, value)\n }\n\n /**\n * Insertion code\n * @type {String}\n */\n get inscode () {\n return this.residueStore.getInscode(this.index)\n }\n set inscode (value) {\n this.residueStore.setInscode(this.index, value)\n }\n\n //\n\n get residueType (): ResidueType {\n return this.residueMap.get(this.residueStore.residueTypeId[ this.index ])\n }\n\n /**\n * Residue name\n * @type {String}\n */\n get resname () {\n return this.residueType.resname\n }\n /**\n * Hetero flag\n * @type {Boolean}\n */\n get hetero () {\n return this.residueType.hetero\n }\n get moleculeType () {\n return this.residueType.moleculeType\n }\n get backboneType () {\n return this.residueType.backboneType\n }\n get backboneStartType () {\n return this.residueType.backboneStartType\n }\n get backboneEndType () {\n return this.residueType.backboneEndType\n }\n get traceAtomIndex () {\n return this.residueType.traceAtomIndex + this.atomOffset\n }\n get direction1AtomIndex () {\n return this.residueType.direction1AtomIndex + this.atomOffset\n }\n get direction2AtomIndex () {\n return this.residueType.direction2AtomIndex + this.atomOffset\n }\n get backboneStartAtomIndex () {\n return this.residueType.backboneStartAtomIndex + this.atomOffset\n }\n get backboneEndAtomIndex () {\n return this.residueType.backboneEndAtomIndex + this.atomOffset\n }\n get rungEndAtomIndex () {\n return this.residueType.rungEndAtomIndex + this.atomOffset\n }\n\n //\n\n get x () {\n let x = 0\n for (let i = this.atomOffset; i <= this.atomEnd; ++i) {\n x += this.atomStore.x[ i ]\n }\n return x / this.atomCount\n }\n\n get y () {\n let y = 0\n for (let i = this.atomOffset; i <= this.atomEnd; ++i) {\n y += this.atomStore.y[ i ]\n }\n return y / this.atomCount\n }\n\n get z () {\n let z = 0\n for (let i = this.atomOffset; i <= this.atomEnd; ++i) {\n z += this.atomStore.z[ i ]\n }\n return z / this.atomCount\n }\n\n //\n\n /**\n * Atom iterator\n * @param {function(atom: AtomProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachAtom (callback: (ap: AtomProxy) => void, selection?: Selection) {\n const count = this.atomCount\n const offset = this.atomOffset\n const ap = this.structure._ap\n const end = offset + count\n\n if (selection && selection.atomOnlyTest) {\n const atomOnlyTest = selection.atomOnlyTest\n for (let i = offset; i < end; ++i) {\n ap.index = i\n if (atomOnlyTest(ap)) callback(ap)\n }\n } else {\n for (let i = offset; i < end; ++i) {\n ap.index = i\n callback(ap)\n }\n }\n }\n\n //\n\n /**\n * Write residue center position to array\n * @param {Array|TypedArray} [array] - target array\n * @param {Integer} [offset] - the offset\n * @return {Array|TypedArray} target array\n */\n positionToArray (array: NumberArray = [], offset = 0) {\n array[ offset + 0 ] = this.x\n array[ offset + 1 ] = this.y\n array[ offset + 2 ] = this.z\n\n return array\n }\n\n //\n\n /**\n * If residue is from a protein\n * @return {Boolean} flag\n */\n isProtein () {\n return this.residueType.moleculeType === ProteinType\n }\n\n /**\n * If residue is nucleic\n * @return {Boolean} flag\n */\n isNucleic () {\n const moleculeType = this.residueType.moleculeType\n return moleculeType === RnaType || moleculeType === DnaType\n }\n\n /**\n * If residue is rna\n * @return {Boolean} flag\n */\n isRna () {\n return this.residueType.moleculeType === RnaType\n }\n\n /**\n * If residue is dna\n * @return {Boolean} flag\n */\n isDna () {\n return this.residueType.moleculeType === DnaType\n }\n\n /**\n * If residue is coarse-grain\n * @return {Boolean} flag\n */\n isCg () {\n const backboneType = this.residueType.backboneType\n return (\n backboneType === CgProteinBackboneType ||\n backboneType === CgRnaBackboneType ||\n backboneType === CgDnaBackboneType\n )\n }\n\n /**\n * If residue is from a polymer\n * @return {Boolean} flag\n */\n isPolymer () {\n if (this.structure.entityList.length > 0) {\n return this.entity.isPolymer()\n } else {\n const moleculeType = this.residueType.moleculeType\n return (\n moleculeType === ProteinType ||\n moleculeType === RnaType ||\n moleculeType === DnaType\n )\n }\n }\n\n /**\n * If residue is hetero\n * @return {Boolean} flag\n */\n isHetero () {\n return this.residueType.hetero === 1\n }\n\n /**\n * If residue is a water molecule\n * @return {Boolean} flag\n */\n isWater () {\n return this.residueType.moleculeType === WaterType\n }\n\n /**\n * If residue is an ion\n * @return {Boolean} flag\n */\n isIon () {\n return this.residueType.moleculeType === IonType\n }\n\n /**\n * If residue is a saccharide\n * @return {Boolean} flag\n */\n isSaccharide () {\n return this.residueType.moleculeType === SaccharideType\n }\n\n isStandardAminoacid () {\n return this.residueType.isStandardAminoacid()\n }\n\n isStandardBase () {\n return this.residueType.isStandardBase()\n }\n\n /**\n * If residue is part of a helix\n * @return {Boolean} flag\n */\n isHelix () {\n return SecStrucHelix.includes(this.sstruc)\n }\n\n /**\n * If residue is part of a sheet\n * @return {Boolean} flag\n */\n isSheet () {\n return SecStrucSheet.includes(this.sstruc)\n }\n\n /**\n * If residue is part of a turn\n * @return {Boolean} flag\n */\n isTurn () {\n return SecStrucTurn.includes(this.sstruc) && this.isProtein()\n }\n\n getAtomType (index: number): AtomType {\n return this.atomMap.get(this.atomStore.atomTypeId[ index ])\n }\n\n getResname1 () {\n // FIXME nucleic support\n return AA1[ this.resname.toUpperCase() ] || 'X'\n }\n\n getBackboneType (position: number) {\n switch (position) {\n case -1:\n return this.residueType.backboneStartType\n case 1:\n return this.residueType.backboneEndType\n default:\n return this.residueType.backboneType\n }\n }\n\n getAtomIndexByName (atomname: string) {\n let index = this.residueType.getAtomIndexByName(atomname)\n if (index !== undefined) {\n index += this.atomOffset\n }\n return index\n }\n\n hasAtomWithName (atomname: string) {\n return this.residueType.hasAtomWithName(atomname)\n }\n\n getAtomnameList () {\n console.warn('getAtomnameList - might be expensive')\n\n const n = this.atomCount\n const offset = this.atomOffset\n const list = new Array(n)\n for (let i = 0; i < n; ++i) {\n list[ i ] = this.getAtomType(offset + i).atomname\n }\n return list\n }\n\n /**\n * If residue is connected to another\n * @param {ResidueProxy} rNext - the other residue\n * @return {Boolean} - flag\n */\n connectedTo (rNext: ResidueProxy) {\n const bbAtomEnd = this.structure.getAtomProxy(this.backboneEndAtomIndex)\n const bbAtomStart = this.structure.getAtomProxy(rNext.backboneStartAtomIndex)\n if (bbAtomEnd && bbAtomStart) {\n return bbAtomEnd.connectedTo(bbAtomStart)\n } else {\n return false\n }\n }\n\n getNextConnectedResidue () {\n const rOffset = this.chainStore.residueOffset[ this.chainIndex ]\n const rCount = this.chainStore.residueCount[ this.chainIndex ]\n const nextIndex = this.index + 1\n if (nextIndex < rOffset + rCount) {\n const rpNext = this.structure.getResidueProxy(nextIndex)\n if (this.connectedTo(rpNext)) {\n return rpNext\n }\n } else if (nextIndex === rOffset + rCount) { // cyclic\n const rpFirst = this.structure.getResidueProxy(rOffset)\n if (this.connectedTo(rpFirst)) {\n return rpFirst\n }\n }\n return undefined\n }\n\n getPreviousConnectedResidue (residueProxy?: ResidueProxy) {\n const rOffset = this.chainStore.residueOffset[ this.chainIndex ]\n const prevIndex = this.index - 1\n if (prevIndex >= rOffset) {\n const rpPrev = defaults(residueProxy, this.structure.getResidueProxy())\n rpPrev.index = prevIndex\n if (rpPrev.connectedTo(this)) {\n return rpPrev\n }\n } else if (prevIndex === rOffset - 1) { // cyclic\n const rCount = this.chainStore.residueCount[ this.chainIndex ]\n const rpLast = defaults(residueProxy, this.structure.getResidueProxy())\n rpLast.index = rOffset + rCount - 1\n if (rpLast.connectedTo(this)) {\n return rpLast\n }\n }\n return undefined\n }\n\n getBonds (): ResidueBonds {\n return this.residueType.getBonds(this)\n }\n\n getRings (): RingData|undefined {\n return this.residueType.getRings()\n }\n\n getAromaticRings () {\n return this.residueType.getAromaticRings(this)\n }\n\n qualifiedName (noResname = false) {\n let name = ''\n if (this.resname && !noResname) name += '[' + this.resname + ']'\n if (this.resno !== undefined) name += this.resno\n if (this.inscode) name += '^' + this.inscode\n if (this.chain) name += ':' + this.chainname\n name += '/' + this.modelIndex\n return name\n }\n\n /**\n * Clone object\n * @return {ResidueProxy} cloned residue\n */\n clone () {\n return new ResidueProxy(this.structure, this.index)\n }\n\n toObject () {\n return {\n index: this.index,\n chainIndex: this.chainIndex,\n atomOffset: this.atomOffset,\n atomCount: this.atomCount,\n\n resno: this.resno,\n resname: this.resname,\n sstruc: this.sstruc\n }\n }\n}\n\nexport default ResidueProxy\n","/**\n * @file Polymer\n * @author Alexander Rose \n * @private\n */\n\n// import { Log } from '../globals'\n\nimport Structure from '../structure/structure'\nimport Selection from '../selection/selection'\n\nimport ChainStore from '../store/chain-store'\nimport ResidueStore from '../store/residue-store'\nimport AtomStore from '../store/atom-store'\n\nimport ResidueProxy from '../proxy/residue-proxy'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Polymer\n */\nclass Polymer {\n chainStore: ChainStore\n residueStore: ResidueStore\n atomStore: AtomStore\n\n residueCount: number\n\n isPrevConnected: boolean\n isNextConnected: boolean\n isNextNextConnected: boolean\n isCyclic: boolean\n\n private __residueProxy: ResidueProxy\n\n /**\n * @param {Structure} structure - the structure\n * @param {Integer} residueIndexStart - the index of the first residue\n * @param {Integer} residueIndexEnd - the index of the last residue\n */\n constructor (readonly structure: Structure, readonly residueIndexStart: number, readonly residueIndexEnd: number) {\n this.chainStore = structure.chainStore\n this.residueStore = structure.residueStore\n this.atomStore = structure.atomStore\n\n /**\n * @type {Integer}\n */\n this.residueCount = residueIndexEnd - residueIndexStart + 1\n\n const rpStart = this.structure.getResidueProxy(this.residueIndexStart)\n const rpEnd = this.structure.getResidueProxy(this.residueIndexEnd)\n this.isPrevConnected = rpStart.getPreviousConnectedResidue() !== undefined\n const rpNext = rpEnd.getNextConnectedResidue()\n this.isNextConnected = rpNext !== undefined\n this.isNextNextConnected = rpNext !== undefined && rpNext.getNextConnectedResidue() !== undefined\n this.isCyclic = rpEnd.connectedTo(rpStart)\n\n this.__residueProxy = this.structure.getResidueProxy()\n\n // console.log( this.qualifiedName(), this );\n }\n\n get chainIndex () {\n return this.residueStore.chainIndex[ this.residueIndexStart ]\n }\n get modelIndex () {\n return this.chainStore.modelIndex[ this.chainIndex ]\n }\n\n /**\n * @type {String}\n */\n get chainname () {\n return this.chainStore.getChainname(this.chainIndex)\n }\n\n //\n\n /**\n * If first residue is from aprotein\n * @return {Boolean} flag\n */\n isProtein () {\n this.__residueProxy.index = this.residueIndexStart\n return this.__residueProxy.isProtein()\n }\n\n /**\n * If atom is part of a coarse-grain group\n * @return {Boolean} flag\n */\n isCg () {\n this.__residueProxy.index = this.residueIndexStart\n return this.__residueProxy.isCg()\n }\n\n /**\n * If atom is part of a nucleic molecule\n * @return {Boolean} flag\n */\n isNucleic () {\n this.__residueProxy.index = this.residueIndexStart\n return this.__residueProxy.isNucleic()\n }\n\n getMoleculeType () {\n this.__residueProxy.index = this.residueIndexStart\n return this.__residueProxy.moleculeType\n }\n\n getBackboneType (position: number) {\n this.__residueProxy.index = this.residueIndexStart\n return this.__residueProxy.getBackboneType(position)\n }\n\n getAtomIndexByType (index: number, type: string) {\n // TODO pre-calculate, add to residueStore???\n\n if (this.isCyclic) {\n if (index === -1) {\n index = this.residueCount - 1\n } else if (index === this.residueCount) {\n index = 0\n }\n } else {\n if (index === -1 && !this.isPrevConnected) index += 1\n if (index === this.residueCount && !this.isNextNextConnected) index -= 1\n // if( index === this.residueCount - 1 && !this.isNextConnected ) index -= 1;\n }\n\n const rp = this.__residueProxy\n rp.index = this.residueIndexStart + index\n let aIndex\n\n switch (type) {\n case 'trace':\n aIndex = rp.traceAtomIndex\n break\n case 'direction1':\n aIndex = rp.direction1AtomIndex\n break\n case 'direction2':\n aIndex = rp.direction2AtomIndex\n break\n default:\n aIndex = rp.getAtomIndexByName(type)\n }\n\n // if (!ap){\n // console.log(this, type, rp.residueType)\n // // console.log(rp.qualifiedName(), rp.index, index, this.residueCount - 1)\n // // rp.index = this.residueIndexStart;\n // // console.log(rp.qualifiedName(), this.residueIndexStart)\n // // rp.index = this.residueIndexEnd;\n // // console.log(rp.qualifiedName(), this.residueIndexEnd)\n // }\n\n return aIndex\n }\n\n /**\n * Atom iterator\n * @param {function(atom: AtomProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachAtom (callback: (ap: AtomProxy) => void, selection?: Selection) {\n this.eachResidue(function (rp) {\n rp.eachAtom(callback, selection)\n })\n }\n\n eachAtomN (n: number, callback: (...apArray: AtomProxy[]) => void, type: string) {\n const m = this.residueCount\n const array: AtomProxy[] = new Array(n)\n\n for (let i = 0; i < n; ++i) {\n array[ i ] = this.structure.getAtomProxy(this.getAtomIndexByType(i, type))\n }\n callback.apply(this, array)\n\n for (var j = n; j < m; ++j) {\n for (let i = 1; i < n; ++i) {\n array[ i - 1 ].index = array[ i ].index\n }\n array[ n - 1 ].index = this.getAtomIndexByType(j, type)! // TODO\n callback.apply(this, array)\n }\n }\n\n /**\n * Residue iterator\n * @param {function(residue: ResidueProxy)} callback - the callback\n * @return {undefined}\n */\n eachResidue (callback: (rp: ResidueProxy) => void) {\n const rp = this.structure.getResidueProxy()\n const n = this.residueCount\n const rStartIndex = this.residueIndexStart\n\n for (let i = 0; i < n; ++i) {\n rp.index = rStartIndex + i\n callback(rp)\n }\n }\n\n qualifiedName () {\n const rpStart = this.structure.getResidueProxy(this.residueIndexStart)\n const rpEnd = this.structure.getResidueProxy(this.residueIndexEnd)\n return rpStart.qualifiedName() + ' - ' + rpEnd.qualifiedName()\n }\n}\n\nexport default Polymer\n","/**\n * @file Chain Proxy\n * @author Alexander Rose \n * @private\n */\n\nimport { UnknownBackboneType } from '../structure/structure-constants'\n\nimport Structure from '../structure/structure'\nimport Selection from '../selection/selection'\n\nimport ChainStore from '../store/chain-store'\nimport ResidueStore from '../store/residue-store'\n\nimport Polymer from '../proxy/polymer'\nimport ResidueProxy from '../proxy/residue-proxy'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ModelProxy from './model-proxy';\nimport Entity from '../structure/entity';\n\n/**\n * Chain proxy\n */\nclass ChainProxy {\n index: number\n\n chainStore: ChainStore\n residueStore: ResidueStore\n\n /**\n * @param {Structure} structure - the structure\n * @param {Integer} index - the index\n */\n constructor (readonly structure: Structure, index = 0) {\n this.index = index\n this.chainStore = structure.chainStore\n this.residueStore = structure.residueStore\n }\n\n /**\n * Entity\n * @type {Entity}\n */\n get entity (): Entity {\n return this.structure.entityList[ this.entityIndex ]\n }\n /**\n * Model\n * @type {ModelProxy}\n */\n get model (): ModelProxy {\n return this.structure.getModelProxy(this.modelIndex)\n }\n\n get entityIndex () {\n return this.chainStore.entityIndex[ this.index ]\n }\n set entityIndex (value) {\n this.chainStore.entityIndex[ this.index ] = value\n }\n\n get modelIndex () {\n return this.chainStore.modelIndex[ this.index ]\n }\n set modelIndex (value) {\n this.chainStore.modelIndex[ this.index ] = value\n }\n\n get residueOffset () {\n return this.chainStore.residueOffset[ this.index ]\n }\n set residueOffset (value) {\n this.chainStore.residueOffset[ this.index ] = value\n }\n\n /**\n * Residue count\n * @type {Integer}\n */\n get residueCount () {\n return this.chainStore.residueCount[ this.index ]\n }\n set residueCount (value) {\n this.chainStore.residueCount[ this.index ] = value\n }\n\n get residueEnd () {\n return this.residueOffset + this.residueCount - 1\n }\n\n get atomOffset () {\n return this.residueStore.atomOffset[ this.residueOffset ]\n }\n get atomEnd () {\n return (\n this.residueStore.atomOffset[ this.residueEnd ] +\n this.residueStore.atomCount[ this.residueEnd ] - 1\n )\n }\n /**\n * Atom count\n * @type {Integer}\n */\n get atomCount () {\n if (this.residueCount === 0) {\n return 0\n } else {\n return this.atomEnd - this.atomOffset + 1\n }\n }\n\n //\n\n /**\n * Chain name\n * @type {String}\n */\n get chainname () {\n return this.chainStore.getChainname(this.index)\n }\n set chainname (value) {\n this.chainStore.setChainname(this.index, value)\n }\n\n /**\n * Chain id\n * @type {String}\n */\n get chainid () {\n return this.chainStore.getChainid(this.index)\n }\n set chainid (value) {\n this.chainStore.setChainid(this.index, value)\n }\n\n //\n\n /**\n * Atom iterator\n * @param {function(atom: AtomProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachAtom (callback: (ap: AtomProxy) => void, selection?: Selection) {\n this.eachResidue(function (rp) {\n rp.eachAtom(callback, selection)\n }, selection)\n }\n\n /**\n * Residue iterator\n * @param {function(residue: ResidueProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachResidue (callback: (rp: ResidueProxy) => void, selection?: Selection) {\n const count = this.residueCount\n const offset = this.residueOffset\n const rp = this.structure._rp\n const end = offset + count\n\n if (selection && selection.test) {\n const residueOnlyTest = selection.residueOnlyTest\n if (residueOnlyTest) {\n for (let i = offset; i < end; ++i) {\n rp.index = i\n if (residueOnlyTest(rp)) {\n callback(rp)\n }\n }\n } else {\n for (let i = offset; i < end; ++i) {\n rp.index = i\n callback(rp)\n }\n }\n } else {\n for (let i = offset; i < end; ++i) {\n rp.index = i\n callback(rp)\n }\n }\n }\n\n /**\n * Multi-residue iterator\n * @param {Integer} n - window size\n * @param {function(residueList: ResidueProxy[])} callback - the callback\n * @return {undefined}\n */\n eachResidueN (n: number, callback: (...rpArray: ResidueProxy[]) => void) {\n const count = this.residueCount\n const offset = this.residueOffset\n const end = offset + count\n if (count < n) return\n const array: ResidueProxy[] = new Array(n)\n\n for (let i = 0; i < n; ++i) {\n array[ i ] = this.structure.getResidueProxy(offset + i)\n }\n callback.apply(this, array)\n\n for (let j = offset + n; j < end; ++j) {\n for (let i = 0; i < n; ++i) {\n array[ i ].index += 1\n }\n callback.apply(this, array)\n }\n }\n\n /**\n * Polymer iterator\n * @param {function(polymer: Polymer)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachPolymer (callback: (p: Polymer) => void, selection?: Selection) {\n let rStartIndex = 0\n let rNextIndex = 0\n const test = selection ? selection.residueOnlyTest : undefined\n const structure = this.model.structure\n\n const count = this.residueCount\n const offset = this.residueOffset\n const end = offset + count\n\n const rp1 = this.structure.getResidueProxy()\n const rp2 = this.structure.getResidueProxy(offset)\n\n const ap1 = this.structure.getAtomProxy()\n const ap2 = this.structure.getAtomProxy()\n\n let first = true\n\n for (let i = offset + 1; i < end; ++i) {\n rp1.index = rp2.index\n rp2.index = i\n\n const bbType1 = first ? rp1.backboneEndType : rp1.backboneType\n const bbType2 = rp2.backboneType\n\n if (first) {\n rStartIndex = rp1.index\n first = false\n }\n rNextIndex = rp2.index\n\n if (bbType1 !== UnknownBackboneType && bbType1 === bbType2) {\n ap1.index = rp1.backboneEndAtomIndex\n ap2.index = rp2.backboneStartAtomIndex\n } else {\n if (bbType1 !== UnknownBackboneType) {\n if (rp1.index - rStartIndex > 1) {\n // console.log(\"FOO1\",rStartIndex, rp1.index)\n callback(new Polymer(structure, rStartIndex, rp1.index))\n }\n }\n rStartIndex = rNextIndex\n\n continue\n }\n\n if (!ap1 || !ap2 || !ap1.connectedTo(ap2) ||\n (test && (!test(rp1) || !test(rp2)))\n ) {\n if (rp1.index - rStartIndex > 1) {\n // console.log(\"FOO2\",rStartIndex, rp1.index)\n callback(new Polymer(structure, rStartIndex, rp1.index))\n }\n rStartIndex = rNextIndex\n }\n }\n\n if (rNextIndex - rStartIndex > 1) {\n if (this.structure.getResidueProxy(rStartIndex).backboneEndType) {\n // console.log(\"FOO3\",rStartIndex, rNextIndex)\n callback(new Polymer(structure, rStartIndex, rNextIndex))\n }\n }\n }\n\n //\n\n qualifiedName () {\n var name = ':' + this.chainname + '/' + this.modelIndex\n return name\n }\n\n /**\n * Clone object\n * @return {ChainProxy} cloned chain\n */\n clone () {\n return new ChainProxy(this.structure, this.index)\n }\n\n toObject () {\n return {\n index: this.index,\n residueOffset: this.residueOffset,\n residueCount: this.residueCount,\n\n chainname: this.chainname\n }\n }\n}\n\nexport default ChainProxy\n","/**\n * @file Model Proxy\n * @author Alexander Rose \n * @private\n */\n\nimport Structure from '../structure/structure'\nimport Selection from '../selection/selection'\n\nimport ModelStore from '../store/model-store'\nimport ChainStore from '../store/chain-store'\nimport ResidueStore from '../store/residue-store'\n\nimport ChainProxy from '../proxy/chain-proxy'\nimport Polymer from '../proxy/polymer'\nimport ResidueProxy from '../proxy/residue-proxy'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Model proxy\n */\nclass ModelProxy {\n index: number\n\n modelStore: ModelStore\n chainStore: ChainStore\n residueStore: ResidueStore\n\n /**\n * @param {Structure} structure - the structure\n * @param {Integer} index - the index\n */\n constructor (readonly structure: Structure, index = 0) {\n this.index = index\n this.modelStore = structure.modelStore\n this.chainStore = structure.chainStore\n this.residueStore = structure.residueStore\n }\n\n get chainOffset () {\n return this.modelStore.chainOffset[ this.index ]\n }\n set chainOffset (value) {\n this.modelStore.chainOffset[ this.index ] = value\n }\n\n get chainCount () {\n return this.modelStore.chainCount[ this.index ]\n }\n set chainCount (value) {\n this.modelStore.chainCount[ this.index ] = value\n }\n\n get residueOffset () {\n return this.chainStore.residueOffset[ this.chainOffset ]\n }\n get atomOffset () {\n return this.residueStore.atomOffset[ this.residueOffset ]\n }\n\n get chainEnd () {\n return this.chainOffset + this.chainCount - 1\n }\n get residueEnd () {\n return (\n this.chainStore.residueOffset[ this.chainEnd ] +\n this.chainStore.residueCount[ this.chainEnd ] - 1\n )\n }\n get atomEnd () {\n return (\n this.residueStore.atomOffset[ this.residueEnd ] +\n this.residueStore.atomCount[ this.residueEnd ] - 1\n )\n }\n\n /**\n * Residue count\n * @type {Integer}\n */\n get residueCount () {\n if (this.chainCount === 0) {\n return 0\n } else {\n return this.residueEnd - this.residueOffset + 1\n }\n }\n\n /**\n * Atom count\n * @type {Integer}\n */\n get atomCount () {\n if (this.residueCount === 0) {\n return 0\n } else {\n return this.atomEnd - this.atomOffset + 1\n }\n }\n\n //\n\n /**\n * Atom iterator\n * @param {function(atom: AtomProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachAtom (callback: (ap: AtomProxy) => void, selection?: Selection) {\n this.eachChain(function (cp) {\n cp.eachAtom(callback, selection)\n }, selection)\n }\n\n /**\n * Residue iterator\n * @param {function(residue: ResidueProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachResidue (callback: (rp: ResidueProxy) => void, selection?: Selection) {\n this.eachChain(function (cp) {\n cp.eachResidue(callback, selection)\n }, selection)\n }\n\n /**\n * Polymer iterator\n * @param {function(polymer: Polymer)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachPolymer (callback: (p: Polymer) => void, selection?: Selection) {\n if (selection && selection.chainOnlyTest) {\n const chainOnlyTest = selection.chainOnlyTest\n\n this.eachChain(function (cp) {\n if (chainOnlyTest(cp)) {\n cp.eachPolymer(callback, selection)\n }\n })\n } else {\n this.eachChain(function (cp) {\n cp.eachPolymer(callback, selection)\n })\n }\n }\n\n /**\n * Chain iterator\n * @param {function(chain: ChainProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachChain (callback: (cp: ChainProxy) => void, selection?: Selection) {\n const count = this.chainCount\n const offset = this.chainOffset\n const cp = this.structure._cp\n const end = offset + count\n\n if (selection && selection.test) {\n const chainOnlyTest = selection.chainOnlyTest\n if (chainOnlyTest) {\n for (let i = offset; i < end; ++i) {\n cp.index = i\n if (chainOnlyTest(cp)) {\n callback(cp)\n }\n }\n } else {\n for (let i = offset; i < end; ++i) {\n cp.index = i\n callback(cp)\n }\n }\n } else {\n for (let i = offset; i < end; ++i) {\n cp.index = i\n callback(cp)\n }\n }\n }\n\n //\n\n qualifiedName () {\n const name = '/' + this.index\n return name\n }\n\n /**\n * Clone object\n * @return {ModelProxy} cloned model\n */\n clone () {\n return new ModelProxy(this.structure, this.index)\n }\n\n toObject () {\n return {\n index: this.index,\n chainOffset: this.chainOffset,\n chainCount: this.chainCount\n }\n }\n}\n\nexport default ModelProxy\n","/**\n * @file Structure\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Box3 } from 'three'\nimport { Signal } from 'signals'\nimport { CifBlock } from 'molstar/lib/mol-io/reader/cif'\n\nimport { Debug, Log, ColormakerRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport { AtomPicker, BondPicker } from '../utils/picker'\nimport { copyWithin, arrayMin, arrayMax } from '../math/array-utils'\nimport BitArray from '../utils/bitarray'\nimport RadiusFactory, { RadiusParams } from '../utils/radius-factory'\nimport { Matrix } from '../math/matrix-utils'\nimport PrincipalAxes from '../math/principal-axes'\nimport SpatialHash from '../geometry/spatial-hash'\nimport FilteredVolume from '../surface/filtered-volume'\nimport StructureView from './structure-view'\nimport { AtomDataParams, AtomData, BondDataParams, BondData } from './structure-data'\nimport { Data, createData } from './data'\n\nimport Entity from './entity'\nimport Unitcell from '../symmetry/unitcell'\nimport Validation from './validation'\nimport Selection from '../selection/selection'\nimport Assembly from '../symmetry/assembly'\nimport Volume from '../surface/volume'\nimport Polymer from '../proxy/polymer'\n\nimport BondHash from '../store/bond-hash'\nimport BondStore from '../store/bond-store'\nimport AtomStore from '../store/atom-store'\nimport ResidueStore from '../store/residue-store'\nimport ChainStore from '../store/chain-store'\nimport ModelStore from '../store/model-store'\n\nimport AtomMap from '../store/atom-map'\nimport ResidueMap from '../store/residue-map'\n\nimport BondProxy from '../proxy/bond-proxy'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ResidueProxy from '../proxy/residue-proxy'\nimport ChainProxy from '../proxy/chain-proxy'\nimport ModelProxy from '../proxy/model-proxy'\nimport ChemCompMap from '../store/chemcomp-map'\n\ninterface Structure {\n signals: StructureSignals\n\n name: string\n path: string\n title: string\n id: string\n\n data: Data\n\n atomCount: number\n bondCount: number\n\n header: StructureHeader\n extraData: StructureExtraData\n\n atomSetCache: { [k: string]: BitArray }\n atomSetDict: { [k: string]: BitArray }\n biomolDict: { [k: string]: Assembly }\n\n entityList: Entity[]\n unitcell?: Unitcell\n\n frames: Float32Array[]\n boxes: Float32Array[]\n\n validation?: Validation\n\n bondStore: BondStore\n backboneBondStore: BondStore\n rungBondStore: BondStore\n atomStore: AtomStore\n residueStore: ResidueStore\n chainStore: ChainStore\n modelStore: ModelStore\n\n atomMap: AtomMap\n residueMap: ResidueMap\n chemCompMap?: ChemCompMap\n\n bondHash?: BondHash\n spatialHash?: SpatialHash\n\n atomSet?: BitArray\n bondSet?: BitArray\n\n center: Vector3\n boundingBox: Box3\n\n trajectory?: {\n name: string\n frame: number\n }\n\n getView(selection: Selection): StructureView\n\n _hasCoords?: boolean\n\n _bp: BondProxy\n _ap: AtomProxy\n _rp: ResidueProxy\n _cp: ChainProxy\n}\n\nexport type StructureHeader = {\n releaseDate?: string\n depositionDate?: string\n resolution?: number\n rFree?: number\n rWork?: number\n experimentalMethods?: string[]\n}\n\nexport type StructureExtraData = {\n cif?: CifBlock\n sdf?: object[]\n}\n\nexport type StructureSignals = {\n refreshed: Signal\n}\n\n/**\n * Structure\n */\nclass Structure implements Structure{\n signals: StructureSignals = {\n refreshed: new Signal()\n }\n\n /**\n * @param {String} name - structure name\n * @param {String} path - source path\n */\n constructor (name = '', path = '') {\n this.init(name, path)\n }\n\n init (name: string, path: string) {\n this.name = name\n this.path = path\n this.title = ''\n this.id = ''\n\n this.data = createData(this)\n\n this.header = {}\n this.extraData = {}\n\n this.atomSetCache = {}\n this.atomSetDict = {}\n this.biomolDict = {}\n\n this.entityList = []\n this.unitcell = undefined\n\n this.frames = []\n this.boxes = []\n\n this.validation = undefined\n\n this.bondStore = new BondStore(0)\n this.backboneBondStore = new BondStore(0)\n this.rungBondStore = new BondStore(0)\n this.atomStore = new AtomStore(0)\n this.residueStore = new ResidueStore(0)\n this.chainStore = new ChainStore(0)\n this.modelStore = new ModelStore(0)\n\n this.atomMap = new AtomMap(this)\n this.residueMap = new ResidueMap(this)\n this.chemCompMap = undefined\n\n this.bondHash = undefined\n this.spatialHash = undefined\n\n this.atomSet = undefined\n this.bondSet = undefined\n\n this.center = new Vector3()\n this.boundingBox = new Box3()\n\n this._bp = this.getBondProxy()\n this._ap = this.getAtomProxy()\n this._rp = this.getResidueProxy()\n this._cp = this.getChainProxy()\n }\n\n get type () { return 'Structure' }\n\n finalizeAtoms () {\n this.atomSet = this.getAtomSet()\n this.atomCount = this.atomStore.count\n this.boundingBox = this.getBoundingBox(undefined, this.boundingBox)\n this.center = this.boundingBox.getCenter(new Vector3())\n this.spatialHash = new SpatialHash(this.atomStore, this.boundingBox)\n }\n\n finalizeBonds () {\n this.bondSet = this.getBondSet()\n this.bondCount = this.bondStore.count\n this.bondHash = new BondHash(this.bondStore, this.atomStore.count)\n\n this.atomSetCache = {}\n if (!this.atomSetDict.rung) {\n this.atomSetDict.rung = this.getAtomSet(false)\n }\n\n for (let name in this.atomSetDict) {\n this.atomSetCache[ '__' + name ] = this.atomSetDict[ name ].clone()\n }\n }\n\n //\n\n getBondProxy (index?: number) {\n return new BondProxy(this, index)\n }\n\n getAtomProxy (index?: number) {\n return new AtomProxy(this, index)\n }\n\n getResidueProxy (index?: number) {\n return new ResidueProxy(this, index)\n }\n\n getChainProxy (index?: number) {\n return new ChainProxy(this, index)\n }\n\n getModelProxy (index?: number) {\n return new ModelProxy(this, index)\n }\n\n //\n\n getBondSet (/* selection */) {\n // TODO implement selection parameter\n\n const n = this.bondStore.count\n const bondSet = new BitArray(n)\n const atomSet = this.atomSet\n\n if (atomSet) {\n if (atomSet.isAllSet()) {\n bondSet.setAll()\n } else if (atomSet.isAllClear()) {\n bondSet.clearAll()\n } else {\n const bp = this.getBondProxy()\n\n for (let i = 0; i < n; ++i) {\n bp.index = i\n if (atomSet.isSet(bp.atomIndex1, bp.atomIndex2)) {\n bondSet.set(bp.index)\n }\n }\n }\n } else {\n bondSet.setAll()\n }\n\n return bondSet\n }\n\n getBackboneBondSet (/* selection */) {\n // TODO implement selection parameter\n\n const n = this.backboneBondStore.count\n const backboneBondSet = new BitArray(n)\n const backboneAtomSet = this.atomSetCache.__backbone\n\n if (backboneAtomSet) {\n const bp = this.getBondProxy()\n bp.bondStore = this.backboneBondStore\n\n for (let i = 0; i < n; ++i) {\n bp.index = i\n if (backboneAtomSet.isSet(bp.atomIndex1, bp.atomIndex2)) {\n backboneBondSet.set(bp.index)\n }\n }\n } else {\n backboneBondSet.setAll()\n }\n\n return backboneBondSet\n }\n\n getRungBondSet (/* selection */) {\n // TODO implement selection parameter\n\n const n = this.rungBondStore.count\n const rungBondSet = new BitArray(n)\n const rungAtomSet = this.atomSetCache.__rung\n\n if (rungAtomSet) {\n const bp = this.getBondProxy()\n bp.bondStore = this.rungBondStore\n\n for (let i = 0; i < n; ++i) {\n bp.index = i\n if (rungAtomSet.isSet(bp.atomIndex1, bp.atomIndex2)) {\n rungBondSet.set(bp.index)\n }\n }\n } else {\n rungBondSet.setAll()\n }\n\n return rungBondSet\n }\n\n /**\n * Get a set of atoms\n * @param {Boolean|Selection|BitArray} selection - object defining how to\n * initialize the atom set.\n * Boolean: init with value;\n * Selection: init with selection;\n * BitArray: return bit array\n * @return {BitArray} set of atoms\n */\n getAtomSet (selection?: boolean|Selection|BitArray) {\n const n = this.atomStore.count\n\n if (selection === undefined) {\n return new BitArray(n, true)\n } else if (selection instanceof BitArray) {\n return selection\n } else if (selection === true) {\n return new BitArray(n, true)\n } else if (selection && selection.test) {\n const seleString = selection.string\n if (seleString in this.atomSetCache) {\n return this.atomSetCache[ seleString ]\n } else {\n if (seleString === '') {\n return new BitArray(n, true)\n } else {\n const atomSet = new BitArray(n)\n this.eachAtom(function (ap: AtomProxy) {\n atomSet.set(ap.index)\n }, selection)\n this.atomSetCache[ seleString ] = atomSet\n return atomSet\n }\n }\n } else if (selection === false) {\n return new BitArray(n)\n }\n\n return new BitArray(n, true)\n }\n\n /**\n * Get set of atoms around a set of atoms from a selection\n * @param {Selection} selection - the selection object\n * @param {Number} radius - radius to select within\n * @return {BitArray} set of atoms\n */\n getAtomSetWithinSelection (selection: boolean|Selection|BitArray, radius: number) {\n const spatialHash = this.spatialHash\n const atomSet = this.getAtomSet(false)\n const ap = this.getAtomProxy()\n\n if (!spatialHash) return atomSet\n\n this.getAtomSet(selection).forEach(function (idx: number) {\n ap.index = idx\n spatialHash.within(ap.x, ap.y, ap.z, radius).forEach(function (idx2: number) {\n atomSet.set(idx2)\n })\n })\n\n return atomSet\n }\n\n /**\n * Get set of atoms around a point\n * @param {Vector3|AtomProxy} point - the point\n * @param {Number} radius - radius to select within\n * @return {BitArray} set of atoms\n */\n getAtomSetWithinPoint (point: Vector3|AtomProxy, radius: number) {\n const p = point\n const atomSet = this.getAtomSet(false)\n\n if (!this.spatialHash) return atomSet\n\n this.spatialHash.within(p.x, p.y, p.z, radius).forEach(function (idx: number) {\n atomSet.set(idx)\n })\n\n return atomSet\n }\n\n /**\n * Get set of atoms within a volume\n * @param {Volume} volume - the volume\n * @param {Number} radius - radius to select within\n * @param {[type]} minValue - minimum value to be considered as within the volume\n * @param {[type]} maxValue - maximum value to be considered as within the volume\n * @param {[type]} outside - use only values falling outside of the min/max values\n * @return {BitArray} set of atoms\n */\n getAtomSetWithinVolume (volume: Volume, radius: number, minValue: number, maxValue: number, outside: boolean) {\n const fv = new FilteredVolume(volume, minValue, maxValue, outside) as any // TODO\n\n const dp = fv.getDataPosition()\n const n = dp.length\n const r = fv.matrix.getMaxScaleOnAxis()\n const atomSet = this.getAtomSet(false)\n\n if (!this.spatialHash) return atomSet\n\n for (let i = 0; i < n; i += 3) {\n this.spatialHash.within(dp[ i ], dp[ i + 1 ], dp[ i + 2 ], r).forEach(function (idx) {\n atomSet.set(idx)\n })\n }\n\n return atomSet\n }\n\n /**\n * Get set of all atoms within the groups of a selection\n * @param {Selection} selection - the selection object\n * @return {BitArray} set of atoms\n */\n getAtomSetWithinGroup (selection: boolean|Selection|BitArray) {\n const atomResidueIndex = this.atomStore.residueIndex\n const atomSet = this.getAtomSet(false)\n const rp = this.getResidueProxy()\n\n this.getAtomSet(selection).forEach(function (idx) {\n rp.index = atomResidueIndex[ idx ]\n for (let idx2 = rp.atomOffset; idx2 <= rp.atomEnd; ++idx2) {\n atomSet.set(idx2)\n }\n })\n\n return atomSet\n }\n\n //\n\n getSelection (): undefined|Selection {\n return\n }\n\n getStructure (): Structure|StructureView {\n return this\n }\n\n /**\n * Entity iterator\n * @param {function(entity: Entity)} callback - the callback\n * @param {EntityType} type - entity type\n * @return {undefined}\n */\n eachEntity (callback: (entity: Entity) => void, type: number) {\n this.entityList.forEach(function (entity) {\n if (type === undefined || entity.getEntityType() === type) {\n callback(entity)\n }\n })\n }\n\n /**\n * Bond iterator\n * @param {function(bond: BondProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachBond (callback: (entity: BondProxy) => void, selection?: Selection) {\n const bp = this.getBondProxy()\n let bondSet\n\n if (selection && selection.test) {\n bondSet = this.getBondSet(/*selection*/)\n if (this.bondSet) {\n bondSet.intersection(this.bondSet)\n }\n }\n\n if (bondSet) {\n bondSet.forEach(function (index) {\n bp.index = index\n callback(bp)\n })\n } else {\n const n = this.bondStore.count\n for (let i = 0; i < n; ++i) {\n bp.index = i\n callback(bp)\n }\n }\n }\n\n /**\n * Atom iterator\n * @param {function(atom: AtomProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachAtom (callback: (entity: AtomProxy) => void, selection?: Selection) {\n if (selection && selection.test) {\n this.eachModel(function (mp) {\n mp.eachAtom(callback, selection)\n }, selection)\n } else {\n const an = this.atomStore.count\n const ap = this.getAtomProxy()\n for (let i = 0; i < an; ++i) {\n ap.index = i\n callback(ap)\n }\n }\n }\n\n /**\n * Residue iterator\n * @param {function(residue: ResidueProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachResidue (callback: (entity: ResidueProxy) => void, selection?: Selection) {\n if (selection && selection.test) {\n const mn = this.modelStore.count\n const mp = this.getModelProxy()\n const modelOnlyTest = selection.modelOnlyTest\n if (modelOnlyTest) {\n for (let i = 0; i < mn; ++i) {\n mp.index = i\n if (modelOnlyTest(mp)) {\n mp.eachResidue(callback, selection)\n }\n }\n } else {\n for (let i = 0; i < mn; ++i) {\n mp.index = i\n mp.eachResidue(callback, selection)\n }\n }\n } else {\n const rn = this.residueStore.count\n const rp = this.getResidueProxy()\n for (let i = 0; i < rn; ++i) {\n rp.index = i\n callback(rp)\n }\n }\n }\n\n /**\n * Multi-residue iterator\n * @param {Integer} n - window size\n * @param {function(residueList: ResidueProxy[])} callback - the callback\n * @return {undefined}\n */\n eachResidueN (n: number, callback: (...entityArray: ResidueProxy[]) => void) {\n const rn = this.residueStore.count\n if (rn < n) return\n const array: ResidueProxy[] = new Array(n)\n\n for (let i = 0; i < n; ++i) {\n array[ i ] = this.getResidueProxy(i)\n }\n callback.apply(this, array)\n\n for (let j = n; j < rn; ++j) {\n for (let i = 0; i < n; ++i) {\n array[ i ].index += 1\n }\n callback.apply(this, array)\n }\n }\n\n /**\n * Polymer iterator\n * @param {function(polymer: Polymer)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachPolymer (callback: (entity: Polymer) => void, selection?: Selection) {\n if (selection && selection.modelOnlyTest) {\n const modelOnlyTest = selection.modelOnlyTest\n\n this.eachModel(function (mp) {\n if (modelOnlyTest(mp)) {\n mp.eachPolymer(callback, selection)\n }\n })\n } else {\n this.eachModel(function (mp) {\n mp.eachPolymer(callback, selection)\n })\n }\n }\n\n /**\n * Chain iterator\n * @param {function(chain: ChainProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachChain (callback: (entity: ChainProxy) => void, selection?: Selection) {\n if (selection && selection.test) {\n this.eachModel(function (mp) {\n mp.eachChain(callback, selection)\n })\n } else {\n const cn = this.chainStore.count\n const cp = this.getChainProxy()\n for (let i = 0; i < cn; ++i) {\n cp.index = i\n callback(cp)\n }\n }\n }\n\n /**\n * Model iterator\n * @param {function(model: ModelProxy)} callback - the callback\n * @param {Selection} [selection] - the selection\n * @return {undefined}\n */\n eachModel (callback: (entity: ModelProxy) => void, selection?: Selection) {\n const n = this.modelStore.count\n const mp = this.getModelProxy()\n\n if (selection && selection.test) {\n const modelOnlyTest = selection.modelOnlyTest\n if (modelOnlyTest) {\n for (let i = 0; i < n; ++i) {\n mp.index = i\n if (modelOnlyTest(mp)) {\n callback(mp)\n }\n }\n } else {\n for (let i = 0; i < n; ++i) {\n mp.index = i\n callback(mp)\n }\n }\n } else {\n for (let i = 0; i < n; ++i) {\n mp.index = i\n callback(mp)\n }\n }\n }\n\n //\n\n getAtomData (params: AtomDataParams) {\n const p = Object.assign({}, params)\n if (p.colorParams) p.colorParams.structure = this.getStructure()\n\n const what = p.what\n const atomSet = defaults(p.atomSet, this.atomSet)\n\n let radiusFactory: any // TODO\n let colormaker: any // TODO\n\n const atomData: AtomData = {}\n const ap = this.getAtomProxy()\n const atomCount = atomSet.getSize()\n\n if (!what || what.position) {\n atomData.position = new Float32Array(atomCount * 3)\n }\n if ((!what || what.color) && p.colorParams) {\n atomData.color = new Float32Array(atomCount * 3)\n colormaker = ColormakerRegistry.getScheme(p.colorParams)\n }\n if (!what || what.picking) {\n atomData.picking = new AtomPicker(new Float32Array(atomCount), this.getStructure())\n }\n if (!what || what.radius) {\n atomData.radius = new Float32Array(atomCount)\n radiusFactory = new RadiusFactory(p.radiusParams as RadiusParams)\n }\n if (!what || what.index) {\n atomData.index = new Uint32Array(atomCount)\n }\n\n const {position, color, picking, radius, index} = atomData\n\n atomSet.forEach((idx: number, i: number) => {\n const i3 = i * 3\n ap.index = idx\n if (position) {\n ap.positionToArray(position, i3)\n }\n if (color) {\n colormaker.atomColorToArray(ap, color, i3)\n }\n if (picking) {\n picking.array![ i ] = idx\n }\n if (radius) {\n radius[ i ] = radiusFactory.atomRadius(ap)\n }\n if (index) {\n index[ i ] = idx\n }\n })\n return atomData\n }\n\n getBondData (params: BondDataParams) {\n const p = Object.assign({}, params)\n if (p.colorParams) p.colorParams.structure = this.getStructure()\n\n const what = p.what\n const bondSet = defaults(p.bondSet, this.bondSet)\n const multipleBond = defaults(p.multipleBond, 'off')\n const isMulti = multipleBond !== 'off'\n const isOffset = multipleBond === 'offset'\n const bondScale = defaults(p.bondScale, 0.4)\n const bondSpacing = defaults(p.bondSpacing, 1.0)\n\n let radiusFactory: any // TODO\n let colormaker: any // TODO\n\n const bondData: BondData = {}\n const bp = this.getBondProxy()\n if (p.bondStore) bp.bondStore = p.bondStore\n const ap1 = this.getAtomProxy()\n const ap2 = this.getAtomProxy()\n\n let bondCount: number\n if (isMulti) {\n const storeBondOrder = bp.bondStore.bondOrder\n bondCount = 0\n bondSet.forEach(function (index: number) {\n bondCount += storeBondOrder[ index ]\n })\n } else {\n bondCount = bondSet.getSize()\n }\n\n if (!what || what.position) {\n bondData.position1 = new Float32Array(bondCount * 3)\n bondData.position2 = new Float32Array(bondCount * 3)\n }\n if ((!what || what.color) && p.colorParams) {\n bondData.color = new Float32Array(bondCount * 3)\n bondData.color2 = new Float32Array(bondCount * 3)\n colormaker = ColormakerRegistry.getScheme(p.colorParams)\n }\n if (!what || what.picking) {\n bondData.picking = new BondPicker(new Float32Array(bondCount), this.getStructure(), p.bondStore)\n }\n if (!what || what.radius || (isMulti && what.position)) {\n radiusFactory = new RadiusFactory(p.radiusParams as RadiusParams)\n }\n if (!what || what.radius) {\n bondData.radius = new Float32Array(bondCount)\n if (p.radius2) {\n bondData.radius2 = new Float32Array(bondCount)\n }\n }\n\n const {position1, position2, color, color2, picking, radius, radius2} = bondData\n\n let i = 0\n let j, i3, k, bondOrder, absOffset\n let multiRadius\n\n const vt = new Vector3()\n const vShortening = new Vector3()\n const vShift = new Vector3()\n\n bondSet.forEach((index: number) => {\n i3 = i * 3\n bp.index = index\n ap1.index = bp.atomIndex1\n ap2.index = bp.atomIndex2\n bondOrder = bp.bondOrder\n if (position1) {\n if (isMulti && bondOrder > 1) {\n const atomRadius = radiusFactory.atomRadius(ap1)\n multiRadius = atomRadius * bondScale / (0.5 * bondOrder)\n\n bp.calculateShiftDir(vShift)\n\n if (isOffset) {\n absOffset = 2 * bondSpacing * atomRadius\n vShift.multiplyScalar(absOffset)\n vShift.negate()\n\n // Shortening is calculated so that neighbouring double\n // bonds on tetrahedral geometry (e.g. sulphonamide)\n // are not quite touching (arccos(1.9 / 2) ~ 109deg)\n // but don't shorten beyond 10% each end or it looks odd\n vShortening.subVectors(ap2 as any, ap1 as any).multiplyScalar( // TODO\n Math.max(0.1, absOffset / 1.88)\n )\n ap1.positionToArray(position1, i3)\n ap2.positionToArray(position2, i3)\n\n if (bondOrder >= 2) {\n vt.addVectors(ap1 as any, vShift).add(vShortening).toArray(position1 as any, i3 + 3) // TODO\n vt.addVectors(ap2 as any, vShift).sub(vShortening).toArray(position2 as any, i3 + 3) // TODO\n\n if (bondOrder >= 3) {\n vt.subVectors(ap1 as any, vShift).add(vShortening).toArray(position1 as any, i3 + 6) // TODO\n vt.subVectors(ap2 as any, vShift).sub(vShortening).toArray(position2 as any, i3 + 6) // TODO\n }\n }\n } else {\n absOffset = (bondSpacing - bondScale) * atomRadius\n vShift.multiplyScalar(absOffset)\n\n if (bondOrder === 2) {\n vt.addVectors(ap1 as any, vShift).toArray(position1 as any, i3) // TODO\n vt.subVectors(ap1 as any, vShift).toArray(position1 as any, i3 + 3) // TODO\n vt.addVectors(ap2 as any, vShift).toArray(position2 as any, i3) // TODO\n vt.subVectors(ap2 as any, vShift).toArray(position2 as any, i3 + 3) // TODO\n } else if (bondOrder === 3) {\n ap1.positionToArray(position1, i3)\n vt.addVectors(ap1 as any, vShift).toArray(position1 as any, i3 + 3) // TODO\n vt.subVectors(ap1 as any, vShift).toArray(position1 as any, i3 + 6) // TODO\n ap2.positionToArray(position2, i3)\n vt.addVectors(ap2 as any, vShift).toArray(position2 as any, i3 + 3) // TODO\n vt.subVectors(ap2 as any, vShift).toArray(position2 as any, i3 + 6) // TODO\n } else {\n // todo, better fallback\n ap1.positionToArray(position1, i3)\n ap2.positionToArray(position2, i3)\n }\n }\n } else {\n ap1.positionToArray(position1, i3)\n ap2.positionToArray(position2, i3)\n }\n }\n if (color && color2) {\n colormaker.bondColorToArray(bp, 1, color, i3)\n colormaker.bondColorToArray(bp, 0, color2, i3)\n if (isMulti && bondOrder > 1) {\n for (j = 1; j < bondOrder; ++j) {\n k = j * 3 + i3\n copyWithin(color, i3, k, 3)\n copyWithin(color2, i3, k, 3)\n }\n }\n }\n if (picking && picking.array) {\n picking.array[ i ] = index\n if (isMulti && bondOrder > 1) {\n for (j = 1; j < bondOrder; ++j) {\n picking.array[ i + j ] = index\n }\n }\n }\n if (radius) {\n radius[ i ] = radiusFactory.atomRadius(ap1)\n if (isMulti && bondOrder > 1) {\n multiRadius = radius[ i ] * bondScale / (isOffset ? 1 : (0.5 * bondOrder))\n for (j = isOffset ? 1 : 0; j < bondOrder; ++j) {\n radius[ i + j ] = multiRadius\n }\n }\n }\n if (radius2) {\n radius2[ i ] = radiusFactory.atomRadius(ap2)\n if (isMulti && bondOrder > 1) {\n multiRadius = radius2[ i ] * bondScale / (isOffset ? 1 : (0.5 * bondOrder))\n for (j = isOffset ? 1 : 0; j < bondOrder; ++j) {\n radius2[ i + j ] = multiRadius\n }\n }\n }\n i += isMulti ? bondOrder : 1\n })\n\n return bondData\n }\n\n getBackboneAtomData (params: AtomDataParams) {\n params = Object.assign({\n atomSet: this.atomSetCache.__backbone\n }, params)\n\n return this.getAtomData(params)\n }\n\n getBackboneBondData (params: BondDataParams) {\n params = Object.assign({\n bondSet: this.getBackboneBondSet(),\n bondStore: this.backboneBondStore\n }, params)\n\n return this.getBondData(params)\n }\n\n getRungAtomData (params: AtomDataParams) {\n params = Object.assign({\n atomSet: this.atomSetCache.__rung\n }, params)\n\n return this.getAtomData(params)\n }\n\n getRungBondData (params: BondDataParams) {\n params = Object.assign({\n bondSet: this.getRungBondSet(),\n bondStore: this.rungBondStore\n }, params)\n\n return this.getBondData(params)\n }\n\n //\n\n /**\n * Gets the bounding box of the (selected) structure atoms\n * @param {Selection} [selection] - the selection\n * @param {Box3} [box] - optional target\n * @return {Vector3} the box\n */\n getBoundingBox (selection?: Selection, box?: Box3) {\n if (Debug) Log.time('getBoundingBox')\n\n box = box || new Box3()\n\n let minX = +Infinity\n let minY = +Infinity\n let minZ = +Infinity\n\n let maxX = -Infinity\n let maxY = -Infinity\n let maxZ = -Infinity\n\n this.eachAtom(ap => {\n const x = ap.x\n const y = ap.y\n const z = ap.z\n\n if (x < minX) minX = x\n if (y < minY) minY = y\n if (z < minZ) minZ = z\n\n if (x > maxX) maxX = x\n if (y > maxY) maxY = y\n if (z > maxZ) maxZ = z\n }, selection)\n\n box.min.set(minX, minY, minZ)\n box.max.set(maxX, maxY, maxZ)\n\n if (Debug) Log.timeEnd('getBoundingBox')\n\n return box\n }\n\n /**\n * Gets the principal axes of the (selected) structure atoms\n * @param {Selection} [selection] - the selection\n * @return {PrincipalAxes} the principal axes\n */\n getPrincipalAxes (selection?: Selection) {\n if (Debug) Log.time('getPrincipalAxes')\n\n let i = 0\n const coords = new Matrix(3, this.atomCount)\n const cd = coords.data\n\n this.eachAtom(a => {\n cd[ i + 0 ] = a.x\n cd[ i + 1 ] = a.y\n cd[ i + 2 ] = a.z\n i += 3\n }, selection)\n\n if (Debug) Log.timeEnd('getPrincipalAxes')\n\n return new PrincipalAxes(coords)\n }\n\n /**\n * Gets the center of the (selected) structure atoms\n * @param {Selection} [selection] - the selection\n * @return {Vector3} the center\n */\n atomCenter (selection?: Selection) {\n if (selection) {\n return this.getBoundingBox(selection).getCenter(new Vector3())\n } else {\n return this.center.clone()\n }\n }\n\n hasCoords () {\n if (this._hasCoords === undefined) {\n const atomStore = this.atomStore\n this._hasCoords = (\n arrayMin(atomStore.x) !== 0 || arrayMax(atomStore.x) !== 0 ||\n arrayMin(atomStore.y) !== 0 || arrayMax(atomStore.y) !== 0 ||\n arrayMin(atomStore.z) !== 0 || arrayMax(atomStore.z) !== 0\n ) || (\n // allow models with a single atom at the origin\n atomStore.count / this.modelStore.count === 1\n )\n }\n return this._hasCoords;\n }\n\n getSequence (selection?: Selection) {\n const seq: string[] = []\n const rp = this.getResidueProxy()\n\n this.eachAtom(function (ap: AtomProxy) {\n rp.index = ap.residueIndex\n if (ap.index === rp.traceAtomIndex) {\n seq.push(rp.getResname1())\n }\n }, selection)\n\n return seq\n }\n\n getAtomIndices (selection?: Selection) {\n if (selection && selection.string) {\n const indices: number[] = []\n this.eachAtom(function (ap: AtomProxy) {\n indices.push(ap.index)\n }, selection)\n return new Uint32Array(indices)\n } else {\n const p = { what: { index: true } }\n return this.getAtomData(p).index\n }\n }\n\n /**\n * Get number of unique chainnames\n * @param {Selection} selection - limit count to selection\n * @return {Integer} count\n */\n getChainnameCount (selection?: Selection) {\n const chainnames = new Set()\n this.eachChain(function (cp: ChainProxy) {\n if (cp.residueCount) {\n chainnames.add(cp.chainname)\n }\n }, selection)\n\n return chainnames.size\n }\n\n /**\n * Update atomic positions\n * @param position - Array to copy positions from\n * @param refresh - Whether or not to issue a full refresh (automatically\n * triggers re-calculation of bounding boxes, spatial hash,\n * representations etc etc). This provides compatibility with\n * the old behaviour\n */\n updatePosition (position: Float32Array|number[], refresh: boolean = true) {\n let i = 0\n\n this.eachAtom(function (ap: AtomProxy) {\n ap.positionFromArray(position, i)\n i += 3\n }, undefined)\n\n this._hasCoords = undefined // to trigger recalculation (of the _hasCoords value)\n\n if (refresh) { \n this.refreshPosition() // Recalculate bounds - structure-component listener will \n // trigger representation rebuild\n }\n\n }\n\n refreshPosition () {\n this.getBoundingBox(undefined, this.boundingBox)\n this.boundingBox.getCenter(this.center)\n this.spatialHash = new SpatialHash(this.atomStore, this.boundingBox)\n\n this.signals.refreshed.dispatch(this)\n }\n\n /**\n * Calls dispose() method of property objects.\n * Unsets properties to help garbage collection.\n * @return {undefined}\n */\n dispose () {\n if (this.frames) this.frames.length = 0\n if (this.boxes) this.boxes.length = 0\n\n this.bondStore.dispose()\n this.backboneBondStore.dispose()\n this.rungBondStore.dispose()\n this.atomStore.dispose()\n this.residueStore.dispose()\n this.chainStore.dispose()\n this.modelStore.dispose()\n\n // can't delete non-optional properties as of TS 4\n // and since we've already disposed them, don't need to.\n\n delete this.bondSet\n delete this.atomSet\n }\n}\n\nexport default Structure\n","/**\n * @file Shape\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Matrix4 required for declaration only\nimport { Box3, Vector3, Color, Matrix4 } from 'three'\n\nimport { createParams, ensureFloat32Array, getUintArray } from '../utils'\nimport {\n ArrowPrimitive, BoxPrimitive, ConePrimitive, CylinderPrimitive, EllipsoidPrimitive,\n OctahedronPrimitive, SpherePrimitive, TetrahedronPrimitive, TextPrimitive,\n TorusPrimitive, PointPrimitive, WidelinePrimitive\n} from './primitive'\nimport { MeshPicker } from '../utils/picker'\nimport Buffer from '../buffer/buffer'\nimport MeshBuffer from '../buffer/mesh-buffer'\nimport { TextBufferParameters } from '../buffer/text-buffer'\n\nconst tmpBox = new Box3()\n\nconst Primitives = [\n ArrowPrimitive, BoxPrimitive, ConePrimitive, CylinderPrimitive,\n EllipsoidPrimitive, OctahedronPrimitive, SpherePrimitive, TetrahedronPrimitive,\n TextPrimitive, TorusPrimitive, PointPrimitive, WidelinePrimitive\n]\n\nexport const ShapeDefaultParameters = {\n aspectRatio: 1.5,\n sphereDetail: 2,\n radialSegments: 50,\n disableImpostor: false,\n openEnded: false,\n dashedCylinder: false,\n labelParams: {} as Partial,\n pointSize: 2,\n sizeAttenuation: false,\n useTexture: true,\n linewidth: 2\n}\nexport type ShapeParameters = typeof ShapeDefaultParameters\n\n/**\n * Class for building custom shapes.\n *\n * @example\n * var shape = new NGL.Shape('shape', { disableImpostor: true });\n * shape.addSphere([ 0, 0, 9 ], [ 1, 0, 0 ], 1.5 );\n * shape.addEllipsoid([ 6, 0, 0 ], [ 1, 0, 0 ], 1.5, [ 3, 0, 0 ], [ 0, 2, 0 ]);\n * shape.addCylinder([ 0, 2, 7 ], [ 0, 0, 9 ], [ 1, 1, 0 ], 0.5);\n * shape.addCone([ 0, 2, 7 ], [ 0, 3, 3 ], [ 1, 1, 0 ], 1.5);\n * shape.addArrow([ 1, 2, 7 ], [ 30, 3, 3 ], [ 1, 0, 1 ], 1.0);\n * shape.addBox([ 0, 3, 0 ], [ 1, 0, 1 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]);\n * var shapeComp = stage.addComponentFromObject(shape);\n * geoComp.addRepresentation('buffer');\n */\nclass Shape {\n name: string\n parameters: ShapeParameters\n\n boundingBox = new Box3()\n bufferList: Buffer[] = []\n meshCount = 0\n\n _center?: Vector3\n _primitiveData: { [k: string]: any } = {}\n\n /**\n * @param {String} name - name\n * @param {Object} params - parameter object\n * @param {Integer} params.aspectRatio - arrow aspect ratio, used for cylinder radius and cone length\n * @param {Integer} params.sphereDetail - sphere quality (icosahedron subdivisions)\n * @param {Integer} params.radialSegments - cylinder quality (number of segments)\n * @param {Boolean} params.disableImpostor - disable use of raycasted impostors for rendering\n * @param {Boolean} params.openEnded - capped or not\n * @param {TextBufferParameters} params.labelParams - label parameters\n */\n constructor (name = 'shape', params: Partial = {}) {\n this.name = name\n\n this.parameters = createParams(params, ShapeDefaultParameters)\n\n Primitives.forEach(P => {\n Object.keys(P.fields).forEach(name => {\n this._primitiveData[ P.getShapeKey(name) ] = []\n })\n this._primitiveData[ P.getShapeKey('name') ] = []\n })\n }\n\n /**\n * Add a buffer\n * @param {Buffer} buffer - buffer object\n * @return {Shape} this object\n */\n addBuffer (buffer: Buffer) {\n this.bufferList.push(buffer)\n\n const geometry = (buffer as any).geometry // TODO\n if (!geometry.boundingBox) {\n geometry.computeBoundingBox()\n }\n this.boundingBox.union(geometry.boundingBox)\n\n return this\n }\n\n /**\n * Add a mesh\n * @example\n * shape.addMesh(\n * [ 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1 ],\n * [ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0 ]\n * );\n *\n * @param {Float32Array|Array} position - positions\n * @param {Float32Array|Array} color - colors\n * @param {Uint32Array|Uint16Array|Array} [index] - indices\n * @param {Float32Array|Array} [normal] - normals\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addMesh (position: Float32Array|number[], color:Float32Array|number[], index: Uint32Array|Uint16Array|number[], normal?: Float32Array|number[], name?: string) {\n position = ensureFloat32Array(position)\n color = ensureFloat32Array(color)\n\n if (Array.isArray(index)) {\n index = getUintArray(index, position.length)\n }\n if (normal) {\n normal = ensureFloat32Array(normal)\n }\n\n let data\n if (normal === undefined || normal.length == 0 ) {\n data = { position, color, index }\n } else {\n data = { position, color, index, normal }\n }\n //const data = { position, color, index, normal }\n const picking = new MeshPicker(\n this, Object.assign({ serial: this.meshCount, name }, data)\n )\n const meshBuffer = new MeshBuffer(\n Object.assign({ picking }, data) as any\n )\n this.bufferList.push(meshBuffer)\n\n tmpBox.setFromArray(position)\n this.boundingBox.union(tmpBox)\n this.meshCount += 1\n\n return this\n }\n\n /**\n * Add a sphere\n * @example\n * shape.addSphere([ 0, 0, 9 ], [ 1, 0, 0 ], 1.5);\n *\n * @param {Vector3|Array} position - position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} radius - radius value\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addSphere (position: Vector3|[number, number, number], color: Color|[number, number, number], radius: number, name: string) {\n SpherePrimitive.objectToShape(\n this, { position, color, radius, name }\n )\n return this\n }\n\n /**\n * Add an ellipsoid\n * @example\n * shape.addEllipsoid([ 6, 0, 0 ], [ 1, 0, 0 ], 1.5, [ 3, 0, 0 ], [ 0, 2, 0 ]);\n *\n * @param {Vector3|Array} position - position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} radius - radius value\n * @param {Vector3|Array} majorAxis - major axis vector or array\n * @param {Vector3|Array} minorAxis - minor axis vector or array\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addEllipsoid (position: Vector3|[number, number, number], color: Color|[number, number, number], radius: number, majorAxis: Vector3|[number, number, number], minorAxis: Vector3|[number, number, number], name: string) {\n EllipsoidPrimitive.objectToShape(\n this, { position, color, radius, majorAxis, minorAxis, name }\n )\n return this\n }\n\n /**\n * Add a torus\n * @example\n * shape.addTorus([ 6, 0, 0 ], [ 1, 0, 0 ], 1.5, [ 3, 0, 0 ], [ 0, 2, 0 ]);\n *\n * @param {Vector3|Array} position - position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} radius - radius value\n * @param {Vector3|Array} majorAxis - major axis vector or array\n * @param {Vector3|Array} minorAxis - minor axis vector or array\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addTorus (position: Vector3|[number, number, number], color: Color|[number, number, number], radius: number, majorAxis: Vector3|[number, number, number], minorAxis: Vector3|[number, number, number], name: string) {\n TorusPrimitive.objectToShape(\n this, { position, color, radius, majorAxis, minorAxis, name }\n )\n return this\n }\n\n /**\n * Add a cylinder\n * @example\n * shape.addCylinder([ 0, 2, 7 ], [ 0, 0, 9 ], [ 1, 1, 0 ], 0.5);\n *\n * @param {Vector3|Array} position1 - from position vector or array\n * @param {Vector3|Array} position2 - to position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} radius - radius value\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addCylinder (position1: Vector3|[number, number, number], position2: Vector3|[number, number, number], color: Color|[number, number, number], radius: number, name: string) {\n CylinderPrimitive.objectToShape(\n this, { position1, position2, color, radius, name }\n )\n return this\n }\n\n /**\n * Add a cone\n * @example\n * shape.addCone([ 0, 2, 7 ], [ 0, 3, 3 ], [ 1, 1, 0 ], 1.5);\n *\n * @param {Vector3|Array} position1 - from position vector or array\n * @param {Vector3|Array} position2 - to position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} radius - radius value\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addCone (position1: Vector3|[number, number, number], position2: Vector3|[number, number, number], color: Color|[number, number, number], radius: number, name: string) {\n ConePrimitive.objectToShape(\n this, { position1, position2, color, radius, name }\n )\n return this\n }\n\n /**\n * Add an arrow\n * @example\n * shape.addArrow([ 0, 2, 7 ], [ 0, 0, 9 ], [ 1, 1, 0 ], 0.5);\n *\n * @param {Vector3|Array} position1 - from position vector or array\n * @param {Vector3|Array} position2 - to position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} radius - radius value\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addArrow (position1: Vector3|[number, number, number], position2: Vector3|[number, number, number], color: Color|[number, number, number], radius: number, name: string) {\n ArrowPrimitive.objectToShape(\n this, { position1, position2, color, radius, name }\n )\n return this\n }\n\n /**\n * Add a box\n * @example\n * shape.addBox([ 0, 3, 0 ], [ 1, 0, 1 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]);\n *\n * @param {Vector3|Array} position - position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} size - size value\n * @param {Vector3|Array} heightAxis - height axis vector or array\n * @param {Vector3|Array} depthAxis - depth axis vector or array\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addBox (position: Vector3|[number, number, number], color: Color|[number, number, number], size: number, heightAxis: Vector3|[number, number, number], depthAxis: Vector3|[number, number, number], name: string) {\n BoxPrimitive.objectToShape(\n this, { position, color, size, heightAxis, depthAxis, name }\n )\n return this\n }\n\n /**\n * Add an octahedron\n * @example\n * shape.addOctahedron([ 0, 3, 0 ], [ 1, 0, 1 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]);\n *\n * @param {Vector3|Array} position - position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} size - size value\n * @param {Vector3|Array} heightAxis - height axis vector or array\n * @param {Vector3|Array} depthAxis - depth axis vector or array\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addOctahedron (position: Vector3|[number, number, number], color: Color|[number, number, number], size: number, heightAxis: Vector3|[number, number, number], depthAxis: Vector3|[number, number, number], name: string) {\n OctahedronPrimitive.objectToShape(\n this, { position, color, size, heightAxis, depthAxis, name }\n )\n return this\n }\n\n /**\n * Add a tetrahedron\n * @example\n * shape.addTetrahedron([ 0, 3, 0 ], [ 1, 0, 1 ], 2, [ 0, 1, 1 ], [ 1, 0, 1 ]);\n *\n * @param {Vector3|Array} position - position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} size - size value\n * @param {Vector3|Array} heightAxis - height axis vector or array\n * @param {Vector3|Array} depthAxis - depth axis vector or array\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addTetrahedron (position: Vector3|[number, number, number], color: Color|[number, number, number], size: number, heightAxis: Vector3|[number, number, number], depthAxis: Vector3|[number, number, number], name: string) {\n TetrahedronPrimitive.objectToShape(\n this, { position, color, size, heightAxis, depthAxis, name }\n )\n return this\n }\n\n /**\n * Add text\n * @example\n * shape.addText([ 10, -2, 4 ], [ 0.2, 0.5, 0.8 ], 0.5, \"Hello\");\n *\n * @param {Vector3|Array} position - position vector or array\n * @param {Color|Array} color - color object or array\n * @param {Float} size - size value\n * @param {String} text - text value\n * @return {Shape} this object\n */\n addText (position: Vector3|[number, number, number], color: Color|[number, number, number], size: number, text: string) {\n TextPrimitive.objectToShape(\n this, { position, color, size, text }\n )\n return this\n }\n\n /**\n * Add point\n * @example\n * shape.addPoint([ 10, -2, 4 ], [ 0.2, 0.5, 0.8 ]);\n *\n * @param {Vector3|Array} position - position vector or array\n * @param {Color|Array} color - color object or array\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addPoint (position: Vector3|[number, number, number], color: Color|[number, number, number], name: string) {\n PointPrimitive.objectToShape(\n this, { position, color, name }\n )\n return this\n }\n\n /**\n * Add a wideline\n * @example\n * shape.addWideline([ 0, 2, 7 ], [ 0, 0, 9 ], [ 1, 1, 0 ]);\n *\n * @param {Vector3|Array} position1 - from position vector or array\n * @param {Vector3|Array} position2 - to position vector or array\n * @param {Color|Array} color - color object or array\n * @param {String} [name] - text\n * @return {Shape} this object\n */\n addWideline (position1: Vector3|[number, number, number], position2: Vector3|[number, number, number], color: Color|[number, number, number], linewidth: number, name: string) {\n this.parameters.linewidth = linewidth\n WidelinePrimitive.objectToShape(\n this, { position1, position2, color, name }\n )\n return this\n }\n\n /**\n * Deprecated, use `.addText`\n */\n addLabel (position: Vector3|[number, number, number], color: Color|[number, number, number], size: number, text: string) {\n console.warn('Shape.addLabel is deprecated, use .addText instead')\n return this.addText(position, color, size, text)\n }\n\n getBufferList () {\n const buffers: Buffer[] = []\n\n Primitives.forEach(P => {\n if (this._primitiveData[ P.getShapeKey('color') ].length) {\n buffers.push(P.bufferFromShape(this, this.parameters))\n }\n })\n\n return this.bufferList.concat(buffers)\n }\n\n dispose () {\n this.bufferList.forEach(function (buffer) {\n buffer.dispose()\n })\n this.bufferList.length = 0\n\n Primitives.forEach(P => {\n Object.keys(P.fields).forEach(name => {\n this._primitiveData[ P.getShapeKey(name) ].length = 0\n })\n this._primitiveData[ P.getShapeKey('name') ].length = 0\n })\n }\n\n get center () {\n if (!this._center) {\n this._center = this.boundingBox.getCenter(new Vector3())\n }\n return this._center\n }\n\n get type () { return 'Shape' }\n}\n\nexport default Shape\n","/**\n * @file Buffer Representation\n * @author Alexander Rose \n * @private\n */\n\nimport Representation, { RepresentationParameters } from './representation'\nimport Viewer from '../viewer/viewer';\n\n/**\n * Representation for showing buffer objects. Good for efficiently showing\n * large amounts of geometric primitives e.g. spheres via {@link SphereBuffer}.\n * Smaller numbers of geometric primitives are more easily shown with help\n * from the {@link Shape} class.\n *\n * __Name:__ _buffer_\n *\n * @example\n * // add a single red sphere from a buffer to a shape instance\n * var shape = new NGL.Shape( \"shape\" );\n * var sphereBuffer = new NGL.SphereBuffer( {\n * position: new Float32Array( [ 0, 0, 0 ] ),\n * color: new Float32Array( [ 1, 0, 0 ] ),\n * radius: new Float32Array( [ 1 ] )\n * } );\n * shape.addBuffer( sphereBuffer );\n * var shapeComp = stage.addComponentFromObject( shape );\n * shapeComp.addRepresentation( \"buffer\" );\n *\n * @example\n * // add a single red sphere from a buffer to a structure component instance\n * stage.loadFile( \"rcsb://1crn\" ).then( function( o ){\n * var sphereBuffer = new NGL.SphereBuffer( {\n * position: new Float32Array( [ 0, 0, 0 ] ),\n * color: new Float32Array( [ 1, 0, 0 ] ),\n * radius: new Float32Array( [ 1 ] )\n * } );\n * o.addBufferRepresentation( sphereBuffer, { opacity: 0.5 } );\n * } );\n */\nclass BufferRepresentation extends Representation {\n buffer: Buffer[]\n /**\n * Create Buffer representation\n * @param {Buffer} buffer - a buffer object\n * @param {Viewer} viewer - a viewer object\n * @param {RepresentationParameters} params - representation parameters\n */\n constructor (buffer: Buffer|Buffer[], viewer: Viewer, params: Partial) {\n if (!Array.isArray(buffer)) {\n buffer = [ buffer ]\n }\n\n super(buffer, viewer, params)\n\n this.type = 'buffer'\n\n this.parameters = Object.assign({\n\n }, this.parameters, {\n\n colorScheme: null,\n colorScale: null,\n colorValue: null,\n colorDomain: null,\n colorMode: null\n\n })\n\n this.buffer = buffer\n\n this.init(params)\n }\n\n init (params: Partial) {\n super.init(params)\n\n this.build()\n }\n\n create () {\n this.bufferList.push.apply(this.bufferList, this.buffer)\n }\n\n attach (callback: ()=> void) {\n this.bufferList.forEach(buffer => {\n this.viewer.add(buffer)\n buffer.setParameters(this.getBufferParams())\n })\n this.setVisibility(this.visible)\n\n callback()\n }\n}\n\nexport default BufferRepresentation\n","/**\n * @file Geometry Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Vector3 required for declaration only\n import { Vector3, Matrix4, Matrix3, BufferGeometry } from 'three'\n\nimport { getUintArray } from '../utils'\nimport { serialBlockArray } from '../math/array-utils'\nimport { applyMatrix3toVector3array, applyMatrix4toVector3array } from '../math/vector-utils'\nimport MeshBuffer from './mesh-buffer'\nimport { BufferParameters, BufferData } from './buffer'\nimport {Log} from \"../globals\";\n\nconst matrix = new Matrix4()\nconst normalMatrix = new Matrix3()\n\nfunction getData(data: BufferData, geo: BufferGeometry){\n const geoPosition = (geo.attributes as any).position.array\n const geoIndex = geo.index ? geo.index.array : undefined\n\n const n = data.position!.length / 3\n const m = geoPosition.length / 3\n\n const size = n * m\n\n const meshPosition = new Float32Array(size * 3)\n const meshNormal = new Float32Array(size * 3)\n const meshColor = new Float32Array(size * 3)\n\n let meshIndex\n if (geoIndex) {\n meshIndex = getUintArray(n * geoIndex.length, size)\n }\n\n return {\n position: meshPosition,\n color: meshColor,\n index: meshIndex,\n normal: meshNormal,\n primitiveId: data.primitiveId || serialBlockArray(n, m) as Float32Array,\n picking: data.picking\n }\n}\n\n/**\n * Geometry buffer. Base class for geometry-based buffers. Used to draw\n * geometry primitives given a mesh.\n * @interface\n */\nabstract class GeometryBuffer extends MeshBuffer {\n updateNormals = false\n\n geoPosition: Float32Array\n geoNormal: Float32Array\n geoIndex?: Uint32Array|Uint16Array\n\n positionCount: number\n geoPositionCount: number\n\n transformedGeoPosition: Float32Array\n transformedGeoNormal: Float32Array\n\n meshPosition: Float32Array\n meshColor: Float32Array\n meshIndex: Uint32Array|Uint16Array\n meshNormal: Float32Array\n\n /**\n * @param {Object} data - buffer data\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} data.radius - radii\n * @param {Picker} [data.picking] - picking ids\n * @param {BufferParameters} [params] - parameters object\n * @param {BufferGeometry} geo - geometry object\n */\n constructor (data: BufferData, params: Partial = {}, geo: BufferGeometry) {\n super(getData(data, geo), params)\n\n const geoPosition = (geo.attributes as any).position.array\n const geoNormal = (geo.attributes as any).normal.array\n const geoIndex = geo.index ? (geo.index.array as Uint32Array|Uint16Array) : undefined\n\n this.geoPosition = geoPosition\n this.geoNormal = geoNormal\n this.geoIndex = geoIndex\n\n this.positionCount = data.position!.length / 3\n this.geoPositionCount = geoPosition.length / 3\n\n this.transformedGeoPosition = new Float32Array(this.geoPositionCount * 3)\n this.transformedGeoNormal = new Float32Array(this.geoPositionCount * 3)\n\n const attributes = this.geometry.attributes as any // TODO\n this.meshPosition = attributes.position.array\n this.meshColor = attributes.color.array\n this.meshNormal = attributes.normal.array\n\n this.setAttributes(data)\n\n if (geoIndex) {\n const index = this.geometry.getIndex()\n if (!index) { Log.error('Index is null'); return; }\n this.meshIndex = index.array as Uint32Array|Uint16Array\n this.makeIndex()\n }\n }\n\n abstract applyPositionTransform (matrix: Matrix4, i: number, i3?: number): void\n\n setAttributes (data: Partial = {}, initNormals = false) {\n const attributes = this.geometry.attributes as any // TODO\n\n let position, color\n let geoPosition, geoNormal\n let transformedGeoPosition, transformedGeoNormal\n let meshPosition, meshColor, meshNormal\n\n const updateNormals = this.updateNormals\n\n if (data.position) {\n position = data.position\n geoPosition = this.geoPosition\n meshPosition = this.meshPosition\n transformedGeoPosition = this.transformedGeoPosition\n attributes.position.needsUpdate = true\n if (updateNormals || initNormals) {\n geoNormal = this.geoNormal\n meshNormal = this.meshNormal\n transformedGeoNormal = this.transformedGeoNormal\n attributes.normal.needsUpdate = true\n }\n }\n\n if (data.color) {\n color = data.color\n meshColor = this.meshColor\n attributes.color.needsUpdate = true\n }\n\n const n = this.positionCount\n const m = this.geoPositionCount\n\n for (let i = 0; i < n; ++i) {\n let j, l\n const k = i * m * 3\n const i3 = i * 3\n\n if (position && transformedGeoPosition && meshPosition && meshNormal && geoPosition && geoNormal) {\n transformedGeoPosition.set(geoPosition)\n matrix.makeTranslation(\n position[ i3 ], position[ i3 + 1 ], position[ i3 + 2 ]\n )\n this.applyPositionTransform(matrix, i, i3)\n applyMatrix4toVector3array(matrix.elements as unknown as Float32Array,\n transformedGeoPosition)\n\n meshPosition.set(transformedGeoPosition, k)\n\n if (updateNormals && transformedGeoNormal) {\n transformedGeoNormal.set(geoNormal)\n normalMatrix.getNormalMatrix(matrix)\n applyMatrix3toVector3array(normalMatrix.elements as unknown as Float32Array,\n transformedGeoNormal)\n\n meshNormal.set(transformedGeoNormal, k)\n } else if (initNormals) {\n meshNormal.set(geoNormal, k)\n }\n }\n\n if (color && meshColor) {\n for (j = 0; j < m; ++j) {\n l = k + 3 * j\n\n meshColor[ l ] = color[ i3 ]\n meshColor[ l + 1 ] = color[ i3 + 1 ]\n meshColor[ l + 2 ] = color[ i3 + 2 ]\n }\n }\n }\n }\n\n makeIndex () {\n const geoIndex = this.geoIndex\n const meshIndex = this.meshIndex\n\n if (!geoIndex) return\n\n const n = this.positionCount\n const m = this.geoPositionCount\n const o = geoIndex.length / 3\n\n const o3 = o * 3\n\n for (let i = 0; i < n; ++i) {\n const j = i * o3\n const q = j + o3\n\n meshIndex.set(geoIndex, j)\n for (let p = j; p < q; ++p) meshIndex[ p ] += i * m\n }\n }\n}\n\nexport default GeometryBuffer\n","/**\n * @file Sphere Geometry Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { IcosahedronGeometry, Vector3, Matrix4 } from 'three'\nimport { defaults } from '../utils'\nimport GeometryBuffer from './geometry-buffer'\nimport { SphereBufferData } from './sphere-buffer'\nimport { BufferDefaultParameters, BufferParameters } from './buffer'\n\nconst scale = new Vector3()\n\nexport const SphereGeometryBufferDefaultParameters = Object.assign({\n sphereDetail: 1\n}, BufferDefaultParameters)\nexport type SphereGeometryBufferParameters = BufferParameters & { sphereDetail: number }\n\n/**\n * Sphere geometry buffer.\n *\n * @example\n * var sphereGeometryBuffer = new SphereGeometryBuffer({\n * position: new Float32Array([ 0, 0, 0 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * radius: new Float32Array([ 1 ])\n * });\n */\nclass SphereGeometryBuffer extends GeometryBuffer {\n get defaultParameters() { return SphereGeometryBufferDefaultParameters }\n parameters: SphereGeometryBufferParameters\n\n private _radius: Float32Array\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} data.radius - radii\n * @param {Picker} [data.picking] - picking ids\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: SphereBufferData, params: Partial = {}) {\n super(data, params, new IcosahedronGeometry(1, defaults(params.sphereDetail, 1)))\n\n this.setAttributes(data, true)\n }\n\n applyPositionTransform (matrix: Matrix4, i: number) {\n const r = this._radius[ i ]\n scale.set(r, r, r)\n matrix.scale(scale)\n }\n\n setAttributes (data: Partial = {}, initNormals?: boolean) {\n if (data.radius) this._radius = data.radius\n\n super.setAttributes(data, initNormals)\n }\n}\n\nexport default SphereGeometryBuffer\n","/**\n * @file Mapped Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { getUintArray } from '../utils'\nimport { calculateCenterArray, serialArray } from '../math/array-utils'\nimport Buffer, { BufferParameters, BufferData } from './buffer'\n\nexport type MappingType = 'v2'|'v3'\n\n/**\n * Mapped buffer. Sends mapping attribute to the GPU and repeats data in\n * others attributes. Used to render imposters.\n * @interface\n */\nabstract class MappedBuffer extends Buffer {\n index: Uint32Array|Uint16Array\n\n constructor (mappingType: MappingType, data: BufferData, params: Partial = {}) {\n super(data, params)\n\n this.index = getUintArray(this.indexSize, this.attributeSize)\n this.makeIndex()\n this.initIndex(this.index)\n\n this.addAttributes({\n 'mapping': { type: mappingType, value: null }\n })\n\n this.setAttributes({ primitiveId: serialArray(this.size) })\n }\n\n abstract get mapping (): Float32Array\n abstract get mappingIndices (): Uint32Array|Uint16Array\n abstract get mappingIndicesSize (): number\n abstract get mappingSize (): number\n abstract get mappingItemSize (): number\n\n get attributeSize () {\n return this.size * this.mappingSize\n }\n\n get indexSize () {\n return this.size * this.mappingIndicesSize\n }\n\n addAttributes (attributes: any) {\n const nullValueAttributes: any = {}\n for (const name in attributes) {\n const a = attributes[ name ]\n nullValueAttributes[ name ] = {\n type: a.type,\n value: null\n }\n }\n\n super.addAttributes(nullValueAttributes)\n }\n\n getAttributeIndex (dataIndex: number) {\n return dataIndex * 3 * this.mappingSize\n }\n\n setAttributes (data: any) { // TODO\n if (data && !data.position && data.position1 && data.position2) {\n data.position = calculateCenterArray(data.position1, data.position2)\n }\n\n const size = this.size\n const mappingSize = this.mappingSize\n const attributes = this.geometry.attributes as any // TODO\n\n let a, d, itemSize, array, n, i, j\n\n for (const name in data) {\n if (name === 'index' || name === 'picking') continue\n\n d = data[ name ]\n a = attributes[ name ]\n itemSize = a.itemSize\n array = a.array\n\n for (let k = 0; k < size; ++k) {\n n = k * itemSize\n i = n * mappingSize\n\n for (let l = 0; l < mappingSize; ++l) {\n j = i + (itemSize * l)\n\n for (let m = 0; m < itemSize; ++m) {\n array[ j + m ] = d[ n + m ]\n }\n }\n }\n\n a.needsUpdate = true\n }\n }\n\n makeMapping () {\n const size = this.size\n const mapping = this.mapping\n const mappingSize = this.mappingSize\n const mappingItemSize = this.mappingItemSize\n\n const attributes = this.geometry.attributes as any // TODO\n const aMapping = attributes.mapping.array\n\n for (let v = 0; v < size; v++) {\n aMapping.set(mapping, v * mappingItemSize * mappingSize)\n }\n }\n\n makeIndex () {\n const size = this.size\n const mappingSize = this.mappingSize\n const mappingIndices = this.mappingIndices\n const mappingIndicesSize = this.mappingIndicesSize\n\n const index = this.index\n\n for (let v = 0; v < size; v++) {\n const ix = v * mappingIndicesSize\n const it = v * mappingSize\n\n index.set(mappingIndices, ix)\n\n for (let s = 0; s < mappingIndicesSize; ++s) {\n index[ ix + s ] += it\n }\n }\n }\n}\n\nexport default MappedBuffer\n","/**\n * @file Mapped Quad Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { BufferParameters, BufferData } from './buffer'\nimport MappedBuffer from './mapped-buffer'\n\nconst mapping = new Float32Array([\n -1.0, 1.0,\n -1.0, -1.0,\n 1.0, 1.0,\n 1.0, -1.0\n])\n\nconst mappingIndices = new Uint16Array([\n 0, 1, 2,\n 1, 3, 2\n])\n\n/**\n * Mapped Quad buffer. Draws screen-aligned quads. Used to render impostors.\n * @interface\n */\nclass MappedQuadBuffer extends MappedBuffer {\n constructor(data: BufferData, params: Partial = {}) {\n super('v2', data, params)\n }\n get mapping () { return mapping }\n get mappingIndices () { return mappingIndices }\n get mappingIndicesSize () { return 6 }\n get mappingSize () { return 4 }\n get mappingItemSize () { return 2 }\n}\n\nexport default MappedQuadBuffer\n","/**\n * @file Sphere Impostor Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4 } from 'three'\n\nimport '../shader/SphereImpostor.vert'\nimport '../shader/SphereImpostor.frag'\n\nimport MappedQuadBuffer from './mappedquad-buffer'\nimport { SphereBufferData } from './sphere-buffer'\nimport { BufferParameters } from './buffer'\n\n/**\n * Sphere impostor buffer.\n *\n * @example\n * var sphereImpostorBuffer = new SphereImpostorBuffer({\n * position: new Float32Array([ 0, 0, 0 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * radius: new Float32Array([ 1 ])\n * });\n */\nclass SphereImpostorBuffer extends MappedQuadBuffer {\n isImpostor = true\n vertexShader = 'SphereImpostor.vert'\n fragmentShader = 'SphereImpostor.frag'\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} data.radius - radii\n * @param {Picker} [data.picking] - picking ids\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: SphereBufferData, params: Partial = {}) {\n super(data, params)\n\n this.addUniforms({\n 'projectionMatrixInverse': { value: new Matrix4() },\n 'ortho': { value: 0.0 }\n })\n\n this.addAttributes({\n 'radius': { type: 'f', value: null }\n })\n\n this.setAttributes(data)\n this.makeMapping()\n }\n}\n\nexport default SphereImpostorBuffer\n","/**\n * @file Sphere Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Vector3, Matrix4 required for declaration only \nimport { Vector3, Matrix4 } from 'three'\nimport { BufferRegistry, ExtensionFragDepth } from '../globals'\nimport SphereGeometryBuffer, { SphereGeometryBufferDefaultParameters, SphereGeometryBufferParameters } from './spheregeometry-buffer'\nimport SphereImpostorBuffer from './sphereimpostor-buffer'\nimport { BufferData } from './buffer'\n\nexport interface SphereBufferData extends BufferData {\n radius: Float32Array\n}\n\nexport const SphereBufferDefaultParameters = Object.assign({\n disableImpostor: false\n}, SphereGeometryBufferDefaultParameters)\nexport type SphereBufferParameters = SphereGeometryBufferParameters & { disableImpostor: boolean }\n\nclass SphereBufferImpl {\n /**\n * @param {Object} data - buffer data\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} data.radius - radii\n * @param {Picker} [data.picking] - picking ids\n * @param {BufferParameters} params - parameters object\n * @return {SphereGeometryBuffer|SphereImpostorBuffer} the buffer object\n */\n constructor (data: SphereBufferData, params: SphereBufferParameters) {\n if (!ExtensionFragDepth || (params && params.disableImpostor)) {\n return new SphereGeometryBuffer(data, params)\n } else {\n return new SphereImpostorBuffer(data, params)\n }\n }\n}\n\n/**\n * Sphere buffer. Depending on the value {@link ExtensionFragDepth} and\n * `params.disableImpostor` the constructor returns either a\n * {@link SphereGeometryBuffer} or a {@link SphereImpostorBuffer}\n * @implements {Buffer}\n *\n * @example\n * var sphereBuffer = new SphereBuffer( {\n * position: new Float32Array( [ 0, 0, 0 ] ),\n * color: new Float32Array( [ 1, 0, 0 ] ),\n * radius: new Float32Array( [ 1 ] )\n * } );\n */\n//@ts-expect-error Incompatible constructor signatures\nconst SphereBuffer: {\n new(data: SphereBufferData, params: SphereBufferParameters): SphereGeometryBuffer | SphereImpostorBuffer;\n} = SphereBufferImpl;\n\ntype SphereBuffer = SphereGeometryBuffer | SphereImpostorBuffer;\n\nBufferRegistry.add('sphere', SphereBuffer)\n\nexport default SphereBuffer\n","/**\n * @file Point Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Vector3, Matrix4 required for declaration only\nimport { DataTexture, Vector3, Matrix4 } from 'three'\n\nimport '../shader/Point.vert'\nimport '../shader/Point.frag'\n\nimport { BufferRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport { smoothstep } from '../math/math-utils'\nimport Buffer, { BufferDefaultParameters, BufferParameterTypes, BufferData, BufferTypes, BufferParameters } from './buffer'\n\nfunction distance (x0: number, y0: number, x1: number, y1: number) {\n const dx = x1 - x0\n const dy = y1 - y0\n return Math.sqrt(dx * dx + dy * dy)\n}\n\ninterface PointTextureParams {\n width?: number\n height?: number\n delta?: number\n}\n\nfunction makePointTexture (params: PointTextureParams) {\n const p = params || {}\n\n const width = defaults(p.width, 256)\n const height = defaults(p.height, 256)\n const center = [ width / 2, height / 2 ]\n const radius = Math.min(width / 2, height / 2)\n const delta = defaults(p.delta, 1 / (radius + 1)) * radius\n\n let x = 0\n let y = 0\n const data = new Uint8Array(width * height * 4)\n\n for (let i = 0, il = data.length; i < il; i += 4) {\n const dist = distance(x, y, center[ 0 ], center[ 1 ])\n const value = 1 - smoothstep(radius - delta, radius, dist)\n\n data[ i ] = value * 255\n data[ i + 1 ] = value * 255\n data[ i + 2 ] = value * 255\n data[ i + 3 ] = value * 255\n\n if (++x === width) {\n x = 0\n y++\n }\n }\n\n const tex = new DataTexture(data, width, height)\n tex.needsUpdate = true\n\n return tex\n}\n\nexport const PointBufferDefaultParameters = Object.assign({\n pointSize: 1,\n sizeAttenuation: true,\n sortParticles: false,\n alphaTest: 0.5,\n useTexture: false,\n forceTransparent: false,\n edgeBleach: 0.0\n}, BufferDefaultParameters)\nexport type PointBufferParameters = BufferParameters & {\n pointSize: number,\n sizeAttenuation: boolean,\n sortParticles: boolean,\n alphaTest: number,\n useTexture: boolean,\n forceTransparent: boolean,\n edgeBleach: number\n}\n\nconst PointBufferParameterTypes = Object.assign({\n pointSize: { uniform: 'size' },\n sizeAttenuation: { updateShader: true },\n sortParticles: {},\n alphaTest: { uniform: true },\n useTexture: { updateShader: true },\n forceTransparent: {},\n edgeBleach: { uniform: true }\n}, BufferParameterTypes)\n\n/**\n * Point buffer. Draws points. Optionally textured.\n *\n * @example\n * var pointBuffer = new PointBuffer( {\n * position: new Float32Array( [ 0, 0, 0 ] ),\n * color: new Float32Array( [ 1, 0, 0 ] )\n * } );\n */\nclass PointBuffer extends Buffer {\n parameterTypes = PointBufferParameterTypes\n get defaultParameters() { return PointBufferDefaultParameters }\n parameters: PointBufferParameters\n\n vertexShader = 'Point.vert'\n fragmentShader ='Point.frag'\n\n isPoint = true\n tex: DataTexture\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.color - colors\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: BufferData, params: Partial = {}) {\n super(data, params)\n\n this.addUniforms({\n 'size': { value: this.parameters.pointSize },\n 'canvasHeight': { value: 1.0 },\n 'pixelRatio': { value: 1.0 },\n 'map': { value: null },\n 'alphaTest': {value: this.parameters.alphaTest}\n })\n }\n\n makeMaterial () {\n super.makeMaterial()\n\n this.makeTexture()\n\n const m = this.material\n const wm = this.wireframeMaterial\n const pm = this.pickingMaterial\n\n m.uniforms.map.value = this.tex\n m.needsUpdate = true\n\n wm.uniforms.map.value = this.tex\n wm.needsUpdate = true\n\n pm.uniforms.map.value = this.tex\n pm.needsUpdate = true\n }\n\n makeTexture () {\n if (this.tex) this.tex.dispose()\n this.tex = makePointTexture({ delta: this.parameters.edgeBleach })\n }\n\n getDefines (type?: BufferTypes) {\n const defines = super.getDefines(type)\n\n if (this.parameters.sizeAttenuation) {\n defines.USE_SIZEATTENUATION = 1\n }\n\n if (this.parameters.useTexture) {\n defines.USE_MAP = 1\n }\n\n if (this.parameters.alphaTest > 0 && this.parameters.alphaTest <= 1) {\n defines.USE_ALPHATEST = 1\n }\n\n return defines\n }\n\n setUniforms (data: any) {\n if (data && data.edgeBleach !== undefined) {\n this.makeTexture()\n data.map = this.tex\n }\n\n super.setUniforms(data)\n }\n\n dispose () {\n super.dispose()\n\n if (this.tex) this.tex.dispose()\n }\n}\n\nBufferRegistry.add('point', PointBuffer)\n\nexport default PointBuffer\n","/**\n * @file Dot Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { ExtensionFragDepth } from '../globals'\nimport { defaults } from '../utils'\nimport Representation, { RepresentationParameters } from './representation'\nimport Volume from '../surface/volume'\nimport FilteredVolume from '../surface/filtered-volume'\nimport SphereBuffer, { SphereBufferData, SphereBufferParameters } from '../buffer/sphere-buffer'\nimport PointBuffer from '../buffer/point-buffer'\nimport Surface from '../surface/surface';\nimport Viewer from '../viewer/viewer';\nimport SphereGeometryBuffer from '../buffer/spheregeometry-buffer';\n\nexport interface DotDataFields {\n color?: boolean,\n radius?: boolean,\n scale?: boolean\n}\n\n/**\n * Dot representation parameter object. Extends {@link RepresentationParameters}\n *\n * @typedef {Object} DotRepresentationParameters - dot representation parameters\n *\n * @property {String} thresholdType - Meaning of the threshold values. Either *value* for the literal value or *sigma* as a factor of the sigma of the data. For volume data only.\n * @property {Number} thresholdMin - Minimum value to be displayed. For volume data only.\n * @property {Number} thresholdMax - Maximum value to be displayed. For volume data only.\n * @property {Number} thresholdOut - Show only values falling outside of the treshold minumum and maximum. For volume data only.\n */\nexport interface DotRepresentationParameters extends RepresentationParameters {\n thresholdType: 'value'|'value'|'sigma'|'sigma'\n thresholdMin: number\n thresholdMax: number\n thresholdOut: boolean\n dotType: ''|'sphere'|'point'\n radiusType: ''|'value'|'abs-value'|'value-min'|'deviation'|'size'|'radius' //TODO had to add 'radius' because of test in line 333\n radius: number\n scale: number\n sphereDetail: number\n disableImpostor: boolean\n pointSize: number\n sizeAttenuation: boolean\n sortParticles: boolean\n useTexture: boolean\n alphaTest: number\n forceTransparent: boolean\n edgeBleach: number\n}\n/**\n * Dot representation\n */\nclass DotRepresentation extends Representation {\n protected thresholdType: 'value'|'value'|'sigma'|'sigma'\n protected thresholdMin: number\n protected thresholdMax: number\n protected thresholdOut: boolean\n protected dotType: ''|'sphere'|'point'\n protected radiusType: ''|'value'|'abs-value'|'value-min'|'deviation'|'size'|'radius' //TODO had to add 'radius' because of test in line 333\n protected radius: number\n protected scale: number\n protected sphereDetail: number\n protected disableImpostor: boolean\n protected pointSize: number\n protected sizeAttenuation: boolean\n protected sortParticles: boolean\n protected useTexture: boolean\n protected alphaTest: number\n protected forceTransparent: boolean\n protected edgeBleach: number\n\n protected surface: Surface|undefined\n protected volume: FilteredVolume|undefined\n protected dotBuffer: SphereBuffer|PointBuffer\n /**\n * Create Dot representation object\n * @param {Surface|Volume} surface - the surface or volume to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {DotRepresentationParameters} params - dot representation parameters\n */\n constructor (surface: Surface, viewer: Viewer, params: Partial) {\n super(surface, viewer, params)\n\n this.type = 'dot'\n\n this.parameters = Object.assign({\n\n thresholdType: {\n type: 'select',\n rebuild: true,\n options: {\n 'value': 'value', 'sigma': 'sigma'\n }\n },\n thresholdMin: {\n type: 'number', precision: 3, max: Infinity, min: -Infinity, rebuild: true\n },\n thresholdMax: {\n type: 'number', precision: 3, max: Infinity, min: -Infinity, rebuild: true\n },\n thresholdOut: {\n type: 'boolean', rebuild: true\n },\n dotType: {\n type: 'select',\n rebuild: true,\n options: {\n '': '',\n 'sphere': 'sphere',\n 'point': 'point'\n }\n },\n radiusType: {\n type: 'select',\n options: {\n '': '',\n 'value': 'value',\n 'abs-value': 'abs-value',\n 'value-min': 'value-min',\n 'deviation': 'deviation',\n 'size': 'size'\n }\n },\n radius: {\n type: 'number', precision: 3, max: 10.0, min: 0.001, property: 'size'\n },\n scale: {\n type: 'number', precision: 3, max: 10.0, min: 0.001\n },\n sphereDetail: true,\n disableImpostor: true,\n\n pointSize: {\n type: 'number', precision: 1, max: 100, min: 0, buffer: true\n },\n sizeAttenuation: {\n type: 'boolean', buffer: true\n },\n sortParticles: {\n type: 'boolean', rebuild: true\n },\n useTexture: {\n type: 'boolean', buffer: true\n },\n alphaTest: {\n type: 'range', step: 0.001, max: 1, min: 0, buffer: true\n },\n forceTransparent: {\n type: 'boolean', buffer: true\n },\n edgeBleach: {\n type: 'range', step: 0.001, max: 1, min: 0, buffer: true\n }\n\n }, this.parameters, {\n\n colorScheme: {\n type: 'select',\n update: 'color',\n options: {\n '': '',\n 'value': 'value',\n 'uniform': 'uniform',\n 'random': 'random'\n }\n }\n\n })\n\n if (surface instanceof Volume) {\n this.surface = undefined\n this.volume = new FilteredVolume(surface)\n } else {\n this.surface = surface\n this.volume = undefined\n }\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n p.colorScheme = defaults(p.colorScheme, 'uniform')\n p.colorValue = defaults(p.colorValue, 0xDDDDDD)\n\n this.thresholdType = defaults(p.thresholdType, 'sigma')\n this.thresholdMin = defaults(p.thresholdMin, 2.0)\n this.thresholdMax = defaults(p.thresholdMax, Infinity)\n this.thresholdOut = defaults(p.thresholdOut, false)\n this.dotType = defaults(p.dotType, 'point')\n this.radius = defaults(p.radius, 0.1)\n this.scale = defaults(p.scale, 1.0)\n\n this.pointSize = defaults(p.pointSize, 1)\n this.sizeAttenuation = defaults(p.sizeAttenuation, true)\n this.sortParticles = defaults(p.sortParticles, false)\n this.useTexture = defaults(p.useTexture, false)\n this.alphaTest = defaults(p.alphaTest, 0.5)\n this.forceTransparent = defaults(p.forceTransparent, false)\n this.edgeBleach = defaults(p.edgeBleach, 0.0)\n\n super.init(p)\n\n this.build()\n }\n\n attach (callback: () => void) {\n this.bufferList.forEach(buffer => {\n this.viewer.add(buffer)\n })\n this.setVisibility(this.visible)\n\n callback()\n }\n\n create () {\n var dotData: SphereBufferData|{} = {}\n\n if (this.volume) {\n var volume = this.volume\n var thresholdMin, thresholdMax\n\n if (this.thresholdType === 'sigma') {\n thresholdMin = volume.getValueForSigma(this.thresholdMin)\n thresholdMax = volume.getValueForSigma(this.thresholdMax)\n } else {\n thresholdMin = this.thresholdMin\n thresholdMax = this.thresholdMax\n }\n volume.setFilter(thresholdMin, thresholdMax, this.thresholdOut)\n\n Object.assign(dotData, {\n position: volume.getDataPosition(),\n color: volume.getDataColor(this.getColorParams())\n })\n if (this.dotType === 'sphere') {\n Object.assign(dotData, {\n radius: volume.getDataSize(this.radius, this.scale),\n picking: volume.getDataPicking()\n })\n }\n } else {\n var surface = this.surface\n Object.assign(dotData, {\n position: (surface as Surface).getPosition(),\n color: (surface as Surface).getColor(this.getColorParams())\n })\n if (this.dotType === 'sphere') {\n Object.assign(dotData, {\n radius: (surface as Surface).getSize(this.radius, this.scale),\n picking: (surface as Surface).getPicking()\n })\n }\n }\n\n if (this.dotType === 'sphere') {\n this.dotBuffer = new SphereBuffer(\n dotData as SphereBufferData,\n this.getBufferParams({\n sphereDetail: this.sphereDetail,\n disableImpostor: this.disableImpostor,\n dullInterior: false\n }) as SphereBufferParameters\n ) as SphereGeometryBuffer\n } else {\n this.dotBuffer = new PointBuffer(\n dotData,\n this.getBufferParams({\n pointSize: this.pointSize,\n sizeAttenuation: this.sizeAttenuation,\n sortParticles: this.sortParticles,\n useTexture: this.useTexture,\n alphaTest: this.alphaTest,\n forceTransparent: this.forceTransparent,\n edgeBleach: this.edgeBleach\n })\n )\n }\n\n this.bufferList.push(this.dotBuffer as SphereGeometryBuffer)\n }\n\n update (what: DotDataFields = {}) {\n if (this.bufferList.length === 0) return\n\n const dotData: SphereBufferData|{} = {}\n\n if (what.color) {\n if (this.volume) {\n Object.assign(dotData, {\n color: this.volume.getDataColor(\n this.getColorParams()\n )\n })\n } else {\n Object.assign(dotData, {\n color: (this.surface as Surface).getColor(\n this.getColorParams()\n )\n })\n }\n }\n\n if (this.dotType === 'sphere' && (what.radius || what.scale)) {\n if (this.volume) {\n Object.assign(dotData, {\n radius: this.volume.getDataSize(\n this.radius, this.scale\n )\n })\n } else {\n Object.assign(dotData, {\n radius: (this.surface as Surface).getSize(\n this.radius, this.scale\n )\n })\n }\n }\n\n (this.dotBuffer as SphereGeometryBuffer).setAttributes(dotData)\n }\n\n setParameters (params: Partial, what: DotDataFields = {}, rebuild: boolean) {\n \n if (params && params.thresholdType !== undefined &&\n this.volume instanceof Volume\n ) {\n if (this.thresholdType === 'value' &&\n params.thresholdType === 'sigma'\n ) {\n this.thresholdMin = this.volume.getSigmaForValue(\n this.thresholdMin\n )\n this.thresholdMax = this.volume.getSigmaForValue(\n this.thresholdMax\n )\n } else if (this.thresholdType === 'sigma' &&\n params.thresholdType === 'value'\n ) {\n this.thresholdMin = this.volume.getValueForSigma(\n this.thresholdMin\n )\n this.thresholdMax = this.volume.getValueForSigma(\n this.thresholdMax\n )\n }\n\n this.thresholdType = params.thresholdType\n }\n\n if (params && params.radiusType !== undefined) {\n if (params.radiusType === 'radius') {\n this.radius = 0.1\n } else {\n this.radius = parseFloat(params.radiusType)\n }\n what.radius = true\n if (this.dotType === 'sphere' &&\n (!ExtensionFragDepth || this.disableImpostor)\n ) {\n rebuild = true\n }\n }\n\n if (params && params.radius !== undefined) {\n what.radius = true\n if (this.dotType === 'sphere' &&\n (!ExtensionFragDepth || this.disableImpostor)\n ) {\n rebuild = true\n }\n }\n\n if (params && params.scale !== undefined) {\n what.scale = true\n if (this.dotType === 'sphere' &&\n (!ExtensionFragDepth || this.disableImpostor)\n ) {\n rebuild = true\n }\n }\n\n super.setParameters(params, what, rebuild)\n\n return this\n }\n}\n\nexport default DotRepresentation\n","/**\n * @file Image Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport {\n // @ts-ignore: unused import Vector3, Matrix4 required for declaration only\n Vector2, Vector3, Matrix4, BufferAttribute, DataTexture,\n NormalBlending, NearestFilter, LinearFilter\n} from 'three'\n\nimport '../shader/Image.vert'\nimport '../shader/Image.frag'\n\nimport { Picker } from '../utils/picker'\nimport Buffer, { BufferDefaultParameters, BufferParameterTypes, BufferTypes } from './buffer'\n\n\nconst quadIndices = new Uint16Array([\n 0, 1, 2,\n 1, 3, 2\n])\n\nconst quadUvs = new Float32Array([\n 0, 1,\n 0, 0,\n 1, 1,\n 1, 0\n])\n\ntype ImageFilterTypes = 'nearest'|'linear'|'cubic-bspline'|'cubic-catmulrom'|'cubic-mitchell'\n\nexport interface ImageBufferData {\n position: Float32Array\n imageData: Uint8Array\n width: number\n height: number\n\n picking?: Picker\n}\n\nexport const ImageBufferDefaultParameters = Object.assign({\n filter: 'nearest' as ImageFilterTypes,\n forceTransparent: true\n}, BufferDefaultParameters)\nexport type ImageBufferParameters = typeof ImageBufferDefaultParameters\n\nexport const ImageBufferParameterTypes = Object.assign({\n filter: { updateShader: true, uniform: true }\n}, BufferParameterTypes)\n\n/**\n * Image buffer. Draw a single image. Optionally interpolate.\n */\nclass ImageBuffer extends Buffer {\n parameterTypes = ImageBufferParameterTypes\n get defaultParameters() { return ImageBufferDefaultParameters }\n parameters: ImageBufferParameters\n\n alwaysTransparent = true\n hasWireframe = false\n vertexShader = 'Image.vert'\n fragmentShader = 'Image.frag'\n\n tex: DataTexture\n pickingTex: DataTexture\n\n /**\n * @param {Object} data - buffer data\n * @param {Float32Array} data.position - image position\n * @param {Float32Array} data.imageData - image data, rgba channels\n * @param {Float32Array} data.width - image width\n * @param {Float32Array} data.height - image height\n * @param {Picker} [data.picking] - picking ids\n * @param {BufferParameters} [params] - parameters object\n */\n constructor (data: ImageBufferData, params: ImageBufferParameters) {\n super({\n position: data.position,\n index: quadIndices,\n picking: data.picking\n }, params)\n\n const {imageData, width, height} = data\n\n const tex = new DataTexture(imageData, width, height)\n tex.flipY = true\n this.tex = tex\n\n const n = imageData.length\n const pickingData = new Uint8Array(n)\n for (let i = 0; i < n; i += 4) {\n const j = i / 4\n pickingData[ i ] = j >> 16 & 255\n pickingData[ i + 1 ] = j >> 8 & 255\n pickingData[ i + 2 ] = j & 255\n }\n\n const pickingTex = new DataTexture(pickingData, width, height)\n pickingTex.flipY = true\n pickingTex.minFilter = NearestFilter\n pickingTex.magFilter = NearestFilter\n this.pickingTex = pickingTex\n\n this.addUniforms({\n 'map': { value: tex },\n 'pickingMap': { value: pickingTex },\n 'mapSize': { value: new Vector2(width, height) }\n })\n\n this.geometry.setAttribute('uv', new BufferAttribute(quadUvs, 2))\n }\n\n getDefines (type: BufferTypes) {\n const defines = super.getDefines(type)\n const filter = this.parameters.filter\n\n if (filter.startsWith('cubic')) {\n defines.CUBIC_INTERPOLATION = 1\n if (filter.endsWith('bspline')) {\n defines.BSPLINE_FILTER = 1\n } else if (filter.endsWith('catmulrom')) {\n defines.CATMULROM_FILTER = 1\n } else if (filter.endsWith('mitchell')) {\n defines.MITCHELL_FILTER = 1\n }\n }\n\n return defines\n }\n\n updateTexture () {\n const tex = this.tex\n const filter = this.parameters.filter\n\n if (filter.startsWith('cubic')) {\n tex.minFilter = NearestFilter\n tex.magFilter = NearestFilter\n } else if (filter === 'linear') {\n tex.minFilter = LinearFilter\n tex.magFilter = LinearFilter\n } else { // filter === \"nearest\"\n tex.minFilter = NearestFilter\n tex.magFilter = NearestFilter\n }\n\n tex.needsUpdate = true\n this.pickingTex.needsUpdate = true\n }\n\n makeMaterial () {\n super.makeMaterial()\n this.updateTexture()\n\n const m = this.material\n m.uniforms.map.value = this.tex\n m.blending = NormalBlending\n m.needsUpdate = true\n\n const wm = this.wireframeMaterial\n wm.uniforms.map.value = this.tex\n wm.blending = NormalBlending\n wm.needsUpdate = true\n\n const pm = this.pickingMaterial\n pm.uniforms.map.value = this.tex\n pm.uniforms.pickingMap.value = this.pickingTex\n pm.blending = NormalBlending\n pm.needsUpdate = true\n }\n\n setUniforms (data: any) { // TODO\n if (data && data.filter !== undefined) {\n this.updateTexture()\n data.map = this.tex\n }\n\n super.setUniforms(data)\n }\n}\n\nexport default ImageBuffer\n","/**\n * @file Volume Slice\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { ColormakerRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport { SlicePicker } from '../utils/picker'\nimport { Volume } from '../ngl';\nimport { SliceRepresentationParameters } from '../representation/slice-representation';\n\nclass VolumeSlice {\n dimension: 'x'|'y'|'z'\n positionType: 'percent'|'coordinate'\n position: number\n thresholdType: 'sigma'|'value'\n thresholdMin: number\n thresholdMax: number\n normalize: boolean\n volume: Volume\n\n constructor (volume: Volume, params: Partial) {\n const p = params || {}\n\n this.dimension = defaults(p.dimension, 'x')\n this.positionType = defaults(p.positionType, 'percent')\n this.position = defaults(p.position, 30)\n this.thresholdType = defaults(p.thresholdType, 'sigma')\n this.thresholdMin = defaults(p.thresholdMin, -Infinity)\n this.thresholdMax = defaults(p.thresholdMax, Infinity)\n this.normalize = defaults(p.normalize, false)\n\n this.volume = volume\n }\n\n getPositionFromCoordinate (coord: number) {\n const dim = this.dimension\n const v = this.volume\n const m = v.matrix\n\n const mp = new Vector3().setFromMatrixPosition(m)[ dim ]\n const ms = new Vector3().setFromMatrixScale(m)[ dim ]\n\n let vn\n if (dim === 'x') {\n vn = v.nx\n } else if (dim === 'y') {\n vn = v.ny\n } else {\n vn = v.nz\n }\n\n return Math.round((((coord - mp) / (vn / 100)) + 1) / ms)\n }\n\n getData (params: any) {\n params = params || {}\n\n const v = this.volume\n const d = v.data\n const m = v.matrix\n\n let p: number\n if (this.positionType === 'coordinate') {\n p = this.getPositionFromCoordinate(this.position)\n } else {\n p = this.position\n }\n\n function pos (dimLen: number) {\n return Math.round((dimLen / 100) * (p - 1))\n }\n\n function index (x: number, y: number, z: number, i: number) {\n return (z * v.ny * v.nx + y * v.nx + x) * 3 + i\n }\n\n const position = new Float32Array(4 * 3)\n const vec = new Vector3()\n\n let width, height\n let x\n let y\n let z\n let x0 = 0\n let y0 = 0\n let z0 = 0\n let nx = v.nx\n let ny = v.ny\n let nz = v.nz\n\n function setVec (x: number, y: number, z: number, offset: number) {\n vec.set(x, y, z).applyMatrix4(m).toArray(position as any, offset)\n }\n\n if (this.dimension === 'x') {\n x = pos(v.nx)\n y = v.ny - 1\n z = v.nz - 1\n\n width = v.nz\n height = v.ny\n\n x0 = x\n nx = x0 + 1\n\n setVec(x, 0, 0, 0)\n setVec(x, y, 0, 3)\n setVec(x, 0, z, 6)\n setVec(x, y, z, 9)\n } else if (this.dimension === 'y') {\n x = v.nx - 1\n y = pos(v.ny)\n z = v.nz - 1\n\n width = v.nz\n height = v.nx\n\n y0 = y\n ny = y0 + 1\n\n setVec(0, y, 0, 0)\n setVec(x, y, 0, 3)\n setVec(0, y, z, 6)\n setVec(x, y, z, 9)\n } else if (this.dimension === 'z') {\n x = v.nx - 1\n y = v.ny - 1\n z = pos(v.nz)\n\n width = v.nx\n height = v.ny\n\n z0 = z\n nz = z0 + 1\n\n setVec(0, 0, z, 0)\n setVec(0, y, z, 3)\n setVec(x, 0, z, 6)\n setVec(x, y, z, 9)\n }\n\n let i = 0\n let j = 0\n const imageData = new Uint8Array(width * height * 4)\n const pickingArray = new Float32Array(width * height)\n\n let tMin, tMax\n if (this.thresholdType === 'sigma') {\n tMin = v.getValueForSigma(this.thresholdMin)\n tMax = v.getValueForSigma(this.thresholdMax)\n } else {\n tMin = this.thresholdMin\n tMax = this.thresholdMax\n }\n\n const cp = Object.assign({}, params.colorParams, { volume: v })\n if (this.normalize) {\n cp.domain = [ 0, 1 ]\n }\n const colormaker = ColormakerRegistry.getScheme(cp)\n const tmp = new Float32Array(3)\n const scale = colormaker.getScale()\n\n let min = 0, max, diff = 0\n if (this.normalize) {\n min = +Infinity\n max = -Infinity\n for (let iy = y0; iy < ny; ++iy) {\n for (let ix = x0; ix < nx; ++ix) {\n for (let iz = z0; iz < nz; ++iz) {\n const idx = index(ix, iy, iz, 0) / 3\n const val = d[ idx ]\n if (val < min) min = val\n if (val > max) max = val\n }\n }\n }\n diff = max - min\n }\n\n for (let iy = y0; iy < ny; ++iy) {\n for (let ix = x0; ix < nx; ++ix) {\n for (let iz = z0; iz < nz; ++iz) {\n const idx = index(ix, iy, iz, 0) / 3\n let val = d[ idx ]\n if (this.normalize) {\n val = (val - min) / diff\n }\n\n colormaker.colorToArray(scale(val), tmp)\n imageData[ i ] = Math.round(tmp[ 0 ] * 255)\n imageData[ i + 1 ] = Math.round(tmp[ 1 ] * 255)\n imageData[ i + 2 ] = Math.round(tmp[ 2 ] * 255)\n imageData[ i + 3 ] = (val > tMin && val < tMax) ? 255 : 0\n\n pickingArray[ j ] = idx\n\n ++j\n i += 4\n }\n }\n }\n\n const picking = new SlicePicker(pickingArray, v)\n\n return { position, imageData, width, height, picking }\n }\n}\n\nexport default VolumeSlice\n","/**\n * @file Slice Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport Representation, { RepresentationParameters } from './representation'\nimport ImageBuffer, { ImageBufferParameters, ImageBufferData } from '../buffer/image-buffer'\nimport VolumeSlice from '../surface/volume-slice'\nimport Viewer from '../viewer/viewer';\nimport { Volume } from '../ngl';\n\n/**\n * Slice representation parameter object. Extends {@link RepresentationParameters}\n *\n * @typedef {Object} SliceRepresentationParameters - slice representation parameters\n *\n * @property {String} filter - filter applied to map the volume data on the slice, one of \"nearest\", \"linear\", \"cubic-bspline\", \"cubic-catmulrom\", \"cubic-mitchell\".\n * @property {String} positionType - Meaning of the position value. Either \"percent\" od \"coordinate\".\n * @property {Number} position - position of the slice.\n * @property {String} dimension - one of \"x\", \"y\" or \"z\"\n * @property {String} thresholdType - Meaning of the threshold values. Either *value* for the literal value or *sigma* as a factor of the sigma of the data. For volume data only.\n * @property {Number} thresholdMin - Minimum value to be displayed. For volume data only.\n * @property {Number} thresholdMax - Maximum value to be displayed. For volume data only.\n * @property {Boolean} normalize - Flag indicating wheather to normalize the data in a slice when coloring.\n */\nexport interface SliceRepresentationParameters extends RepresentationParameters {\n filter: 'nearest'|'linear'|'cubic-bspline'|'cubic-catmulrom'|'cubic-mitchell'\n positionType: 'percent'|'coordinate'\n position: number\n dimension: 'x'|'y'|'z'\n thresholdType: 'value'|'sigma'\n thresholdMin: number\n thresholdMax: number\n normalize: boolean\n}\n/**\n * Slice representation\n */\nclass SliceRepresentation extends Representation {\n protected filter: 'nearest'|'linear'|'cubic-bspline'|'cubic-catmulrom'|'cubic-mitchell'\n protected positionType: 'percent'|'coordinate'\n protected position: number\n protected dimension: 'x'|'y'|'z'\n protected thresholdType: 'value'|'sigma'\n protected thresholdMin: number\n protected thresholdMax: number\n protected normalize: boolean\n protected volume: Volume\n /**\n * Create Slice representation object\n * @param {Volume} surface - the volume to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {SliceRepresentationParameters} params - slice representation parameters\n */\n constructor (volume: Volume, viewer: Viewer, params: Partial) {\n super(volume, viewer, params)\n\n this.type = 'slice'\n\n this.parameters = Object.assign({\n\n filter: {\n type: 'select',\n buffer: true,\n options: {\n 'nearest': 'nearest',\n 'linear': 'linear',\n 'cubic-bspline': 'cubic-bspline',\n 'cubic-catmulrom': 'cubic-catmulrom',\n 'cubic-mitchell': 'cubic-mitchell'\n }\n },\n positionType: {\n type: 'select',\n rebuild: true,\n options: {\n 'percent': 'percent', 'coordinate': 'coordinate'\n }\n },\n position: {\n type: 'range',\n step: 0.1,\n max: 100,\n min: 1,\n rebuild: true\n },\n dimension: {\n type: 'select',\n rebuild: true,\n options: {\n 'x': 'x', 'y': 'y', 'z': 'z'\n }\n },\n thresholdType: {\n type: 'select',\n rebuild: true,\n options: {\n 'value': 'value', 'sigma': 'sigma'\n }\n },\n thresholdMin: {\n type: 'number', precision: 3, max: Infinity, min: -Infinity, rebuild: true\n },\n thresholdMax: {\n type: 'number', precision: 3, max: Infinity, min: -Infinity, rebuild: true\n },\n normalize: {\n type: 'boolean', rebuild: true\n }\n\n }, this.parameters, {\n\n flatShaded: null,\n side: null,\n wireframe: null,\n linewidth: null,\n colorScheme: null,\n\n roughness: null,\n metalness: null,\n diffuse: null\n\n })\n\n this.volume = volume\n\n this.init(params)\n }\n\n init (params: Partial) {\n const v = this.volume\n const p = params || {}\n p.colorDomain = defaults(p.colorDomain, [ v.min, v.max ])\n p.colorScheme = defaults(p.colorScheme, 'value')\n p.colorScale = defaults(p.colorScale, 'Spectral')\n\n this.colorScheme = 'value'\n this.dimension = defaults(p.dimension, 'x')\n this.filter = defaults(p.filter, 'cubic-bspline')\n this.positionType = defaults(p.positionType, 'percent')\n this.position = defaults(p.position, 30)\n this.thresholdType = defaults(p.thresholdType, 'sigma')\n this.thresholdMin = defaults(p.thresholdMin, -Infinity)\n this.thresholdMax = defaults(p.thresholdMax, Infinity)\n this.normalize = defaults(p.normalize, false)\n\n super.init(p)\n\n this.build()\n }\n\n attach (callback: () => void) {\n this.bufferList.forEach(buffer => {\n this.viewer.add(buffer)\n })\n this.setVisibility(this.visible)\n\n callback()\n }\n\n create () {\n const volumeSlice = new VolumeSlice(this.volume, {\n positionType: this.positionType,\n position: this.position,\n dimension: this.dimension,\n thresholdType: this.thresholdType,\n thresholdMin: this.thresholdMin,\n thresholdMax: this.thresholdMax,\n normalize: this.normalize\n })\n\n const sliceBuffer = new ImageBuffer(\n volumeSlice.getData({ colorParams: this.getColorParams() }) as ImageBufferData,\n this.getBufferParams({\n filter: this.filter\n }) as ImageBufferParameters\n )\n\n this.bufferList.push(sliceBuffer)\n }\n}\n\nexport default SliceRepresentation\n","/**\n * @file Representation Utils\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, RepresentationRegistry } from '../globals'\n\nimport Viewer from '../viewer/viewer'\nimport Structure from '../structure/structure'\nimport Surface from '../surface/surface'\nimport Volume from '../surface/volume'\nimport Shape from '../geometry/shape'\n\nimport BufferRepresentation from './buffer-representation'\nimport SurfaceRepresentation from './surface-representation'\nimport DotRepresentation from './dot-representation'\nimport SliceRepresentation from './slice-representation'\n\nfunction logReprUnknown (type: string) {\n Log.error(`makeRepresentation: representation type ${type} unknown`)\n}\n\nexport function makeRepresentation (type: string, object: any, viewer: Viewer, params: any) { // TODO\n if (Debug) Log.time('makeRepresentation ' + type)\n\n var ReprClass\n\n if (object instanceof Structure) {\n ReprClass = RepresentationRegistry.get(type)\n\n if (!ReprClass) {\n logReprUnknown(type)\n return\n }\n } else if (object instanceof Surface) {\n if (type === 'surface') {\n ReprClass = SurfaceRepresentation\n } else if (type === 'dot') {\n ReprClass = DotRepresentation\n } else {\n logReprUnknown(type)\n return\n }\n } else if (object instanceof Volume) {\n if (type === 'surface') {\n ReprClass = SurfaceRepresentation\n } else if (type === 'dot') {\n ReprClass = DotRepresentation\n } else if (type === 'slice') {\n ReprClass = SliceRepresentation\n } else {\n logReprUnknown(type)\n return\n }\n } else if (object instanceof Shape) {\n ReprClass = BufferRepresentation\n object = object.getBufferList()\n } else if (type === 'buffer') {\n ReprClass = BufferRepresentation\n } else {\n Log.error('makeRepresentation: object ' + object + ' unknown')\n return\n }\n\n const repr = new ReprClass(object, viewer, params)\n\n if (Debug) Log.timeEnd('makeRepresentation ' + type)\n\n return repr\n}\n","/**\n * @file Element\n * @author Alexander Rose \n * @private\n */\n\nimport { Signal } from 'signals'\n\nimport { createParams } from '../utils'\nimport { generateUUID } from '../math/math-utils'\nimport Stage from '../stage/stage'\n\nexport const ElementDefaultParameters = {\n name: 'some element',\n status: ''\n}\nexport type ElementParameters = typeof ElementDefaultParameters\n\nexport interface ElementSignals {\n statusChanged: Signal // on status change\n nameChanged: Signal // on name change\n disposed: Signal // on dispose\n}\n\n/**\n * Element base class\n */\nabstract class Element {\n /**\n * Events emitted by the element\n */\n signals: ElementSignals = {\n statusChanged: new Signal(),\n nameChanged: new Signal(),\n disposed: new Signal()\n }\n readonly parameters: ElementParameters\n readonly uuid: string\n\n get defaultParameters() { return ElementDefaultParameters }\n\n /**\n * @param {Stage} stage - stage object the component belongs to\n * @param {ElementParameters} params - component parameters\n */\n constructor (readonly stage: Stage, params: Partial = {}) {\n this.parameters = createParams(params, this.defaultParameters)\n this.uuid = generateUUID()\n }\n\n abstract get type (): string\n\n get name () { return this.parameters.name }\n\n setStatus (value: string) {\n this.parameters.status = value\n this.signals.statusChanged.dispatch(value)\n\n return this\n }\n\n setName (value: string) {\n this.parameters.name = value\n this.signals.nameChanged.dispatch(value)\n\n return this\n }\n\n dispose () {\n this.signals.disposed.dispatch()\n }\n}\n\nexport default Element\n","/**\n * @file Representation Element\n * @author Alexander Rose \n * @private\n */\n\nimport { Signal } from 'signals'\nimport { Color } from 'three'\n\nimport Stage from '../stage/stage'\nimport Representation, { RepresentationParameters } from '../representation/representation'\nimport Component from './component'\nimport Element, { ElementDefaultParameters, ElementSignals } from './element'\n\nexport const RepresentationElementDefaultParameters = Object.assign({\n visible: true\n}, ElementDefaultParameters)\nexport type RepresentationElementParameters = typeof RepresentationElementDefaultParameters\n\nexport interface RepresentationElementSignals extends ElementSignals {\n visibilityChanged: Signal // on visibility change\n parametersChanged: Signal // on parameters change\n}\n\n/**\n * Element wrapping a {@link Representation} object\n */\nclass RepresentationElement extends Element {\n signals: RepresentationElementSignals\n parameters: RepresentationElementParameters\n get defaultParameters() { return RepresentationElementDefaultParameters }\n\n repr: Representation\n\n /**\n * Create representation component\n * @param {Stage} stage - stage object the component belongs to\n * @param {Representation} repr - representation object to wrap\n * @param {RepresentationParameters} [params] - component parameters\n * @param {Component} [parent] - parent component\n */\n constructor (stage: Stage, repr: Representation, params: Partial = {}, readonly parent: Component) {\n super(stage, Object.assign({ name: repr.type }, params))\n\n this.signals = Object.assign({\n visibilityChanged: new Signal(),\n parametersChanged: new Signal()\n }, this.signals)\n\n this.setRepresentation(repr)\n }\n\n get visible () { return this.parameters.visible }\n\n /**\n * Component type\n * @type {String}\n */\n get type () { return 'representation' }\n\n getType () {\n return this.repr.type\n }\n\n setRepresentation (repr: Representation) {\n this._disposeRepresentation()\n this.repr = repr\n // this.name = repr.type;\n this.stage.tasks.listen(this.repr.tasks)\n this.updateVisibility()\n }\n\n _disposeRepresentation () {\n if (this.repr) {\n this.stage.tasks.unlisten(this.repr.tasks)\n this.repr.dispose()\n }\n }\n\n dispose () {\n if (this.parent && this.parent.hasRepresentation(this)) {\n this.parent.removeRepresentation(this)\n } else {\n this._disposeRepresentation()\n this.signals.disposed.dispatch()\n }\n }\n\n /**\n * Set the visibility of the component, takes parent visibility into account\n * @param {Boolean} value - visibility flag\n * @return {RepresentationElement} this object\n */\n setVisibility (value: boolean) {\n this.parameters.visible = value\n this.updateVisibility()\n this.signals.visibilityChanged.dispatch(this.parameters.visible)\n\n return this\n }\n\n getVisibility () {\n if (this.parent) {\n return this.parent.parameters.visible && this.parameters.visible\n } else {\n return this.parameters.visible\n }\n }\n\n /**\n * Toggle visibility of the component, takes parent visibility into account\n * @return {RepresentationElement} this object\n */\n toggleVisibility () {\n return this.setVisibility(!this.parameters.visible)\n }\n\n updateVisibility () {\n this.repr.setVisibility(this.getVisibility())\n }\n\n /**\n * Set selection\n * @param {Object} what - flags indicating what attributes to update\n * @param {Boolean} what.position - update position attribute\n * @param {Boolean} what.color - update color attribute\n * @param {Boolean} what.radius - update radius attribute\n * @return {RepresentationElement} this object\n */\n update (what: any) { // TODO\n (this.repr as any).update(what) // TODO\n\n return this\n }\n\n build (params?: any) { // TODO\n this.repr.build(params)\n\n return this\n }\n\n /**\n * Set selection\n * @param {String} string - selection string\n * @return {RepresentationElement} this object\n */\n setSelection (string: string) {\n const repr: any = this.repr // TODO\n\n if (repr.setSelection) {\n repr.setSelection(string)\n }\n\n return this\n }\n\n /**\n * Set representation parameters\n * @param {RepresentationParameters} params - parameter object\n * @return {RepresentationElement} this object\n */\n setParameters (params: any) { // TODO\n this.repr.setParameters(params)\n this.signals.parametersChanged.dispatch(\n this.repr.getParameters()\n )\n\n return this\n }\n\n /**\n * Get representation parameters\n * @return {RepresentationParameters} parameter object\n */\n getParameters (): Partial {\n return this.repr.getParameters()\n }\n\n /**\n * Set color\n * @param {String|Color|Hex} value - color value\n * @return {RepresentationElement} this object\n */\n setColor (value: string|number|Color) {\n this.repr.setColor(value)\n\n return this\n }\n}\n\nexport default RepresentationElement\n","\n/**\n * @file Component\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Quaternion, Matrix4, Euler, Box3 } from 'three'\nimport { Signal } from 'signals'\n\nimport { defaults, createParams } from '../utils'\nimport { generateUUID } from '../math/math-utils'\nimport Annotation, { AnnotationParams } from '../component/annotation'\nimport ComponentControls from '../controls/component-controls'\nimport { makeRepresentation } from '../representation/representation-utils'\nimport RepresentationElement from './representation-element'\nimport Stage from '../stage/stage'\nimport Viewer from '../viewer/viewer'\n\nconst _m = new Matrix4()\nconst _v = new Vector3()\n\nexport const ComponentDefaultParameters = {\n name: '',\n status: '',\n visible: true\n}\nexport type ComponentParameters = typeof ComponentDefaultParameters\n\n\nexport interface ComponentSignals {\n representationAdded: Signal // when a representation is added\n representationRemoved: Signal // when a representation is removed\n visibilityChanged: Signal // on visibility change\n matrixChanged: Signal // on matrix change\n statusChanged: Signal // on status change\n nameChanged: Signal // on name change\n disposed: Signal // on dispose\n}\n\n/**\n * Base class for components\n */\nabstract class Component {\n /**\n * Events emitted by the component\n */\n readonly signals: ComponentSignals = {\n representationAdded: new Signal(),\n representationRemoved: new Signal(),\n visibilityChanged: new Signal(),\n matrixChanged: new Signal(),\n statusChanged: new Signal(),\n nameChanged: new Signal(),\n disposed: new Signal()\n }\n\n readonly parameters: ComponentParameters\n get defaultParameters () { return ComponentDefaultParameters }\n\n readonly uuid: string\n readonly viewer: Viewer\n\n reprList: RepresentationElement[] = []\n annotationList: Annotation[] = []\n\n matrix = new Matrix4()\n position = new Vector3()\n quaternion = new Quaternion()\n scale = new Vector3(1, 1, 1)\n transform = new Matrix4()\n\n controls: ComponentControls\n\n /**\n * @param {Stage} stage - stage object the component belongs to\n * @param {ComponentParameters} params - parameter object\n */\n constructor (readonly stage: Stage, readonly object: any, params: Partial = {}) {\n this.parameters = createParams(params, this.defaultParameters)\n this.uuid = generateUUID()\n this.viewer = stage.viewer\n\n this.controls = new ComponentControls(this)\n }\n\n abstract get type (): string\n\n get name () { return this.parameters.name }\n get status () { return this.parameters.status }\n get visible () { return this.parameters.visible }\n\n /**\n * Set position transform\n *\n * @example\n * // translate by 25 angstrom along x axis\n * component.setPosition([ 25, 0, 0 ]);\n *\n * @param {Vector3|Array} p - the coordinates\n * @return {Component} this object\n */\n setPosition (p: [number, number, number]|Vector3) {\n if (Array.isArray(p)) {\n this.position.fromArray(p)\n } else {\n this.position.copy(p)\n }\n this.updateMatrix()\n\n return this\n }\n\n /**\n * Set local rotation transform\n * (for global rotation use setTransform)\n *\n * @example\n * // rotate by 2 degree radians on x axis\n * component.setRotation( [ 2, 0, 0 ] );\n *\n * @param {Quaternion|Euler|Array} r - the rotation\n * @return {Component} this object\n */\n setRotation (r: [number, number, number]|Euler|Quaternion) {\n if (Array.isArray(r)) {\n if (r.length === 3) {\n const e = new Euler().fromArray(r)\n this.quaternion.setFromEuler(e)\n } else {\n this.quaternion.fromArray(r)\n }\n } else if (r instanceof Euler) {\n this.quaternion.setFromEuler(r)\n } else {\n this.quaternion.copy(r)\n }\n this.updateMatrix()\n\n return this\n }\n\n /**\n * Set scale transform\n *\n * @example\n * // scale by factor of two\n * component.setScale( 2 );\n *\n * @param {Number} s - the scale\n * @return {Component} this object\n */\n setScale (s: number) {\n this.scale.set(s, s, s)\n this.updateMatrix()\n\n return this\n }\n\n /**\n * Set general transform. Is applied before and in addition\n * to the position, rotation and scale transformations\n *\n * @example\n * component.setTransform( matrix );\n *\n * @param {Matrix4} m - the matrix\n * @return {Component} this object\n */\n setTransform (m: Matrix4) {\n this.transform.copy(m)\n this.updateMatrix()\n\n return this\n }\n\n updateMatrix () {\n const c = this.getCenterUntransformed(_v)\n this.matrix.makeTranslation(-c.x, -c.y, -c.z)\n\n _m.makeRotationFromQuaternion(this.quaternion)\n this.matrix.premultiply(_m)\n\n _m.makeScale(this.scale.x, this.scale.y, this.scale.z)\n this.matrix.premultiply(_m)\n\n const p = this.position\n _m.makeTranslation(p.x + c.x, p.y + c.y, p.z + c.z)\n this.matrix.premultiply(_m)\n\n this.matrix.premultiply(this.transform)\n\n this.updateRepresentationMatrices()\n\n this.stage.viewer.updateBoundingBox()\n\n this.signals.matrixChanged.dispatch(this.matrix)\n }\n\n /**\n * Propogates our matrix to each representation\n */\n updateRepresentationMatrices () {\n this.reprList.forEach(repr => {\n repr.setParameters({ matrix: this.matrix })\n })\n }\n\n /**\n * Add an anotation object\n * @param {Vector3} position - the 3d position\n * @param {String|Element} content - the HTML content\n * @param {Object} [params] - parameters\n * @param {Integer} params.offsetX - 2d offset in x direction\n * @param {Integer} params.offsetY - 2d offset in y direction\n * @return {Annotation} the added annotation object\n */\n addAnnotation (position: Vector3, content: string|HTMLElement, params: AnnotationParams) {\n const annotation = new Annotation(this, position, content, params)\n this.annotationList.push(annotation)\n\n return annotation\n }\n\n /**\n * Iterator over each annotation and executing the callback\n * @param {Function} callback - function to execute\n * @return {undefined}\n */\n eachAnnotation (callback: (a: Annotation) => void) {\n this.annotationList.slice().forEach(callback)\n }\n\n /**\n * Remove the give annotation from the component\n * @param {Annotation} annotation - the annotation to remove\n * @return {undefined}\n */\n removeAnnotation (annotation: Annotation) {\n const idx = this.annotationList.indexOf(annotation)\n if (idx !== -1) {\n this.annotationList.splice(idx, 1)\n annotation.dispose()\n }\n }\n\n /**\n * Remove all annotations from the component\n * @return {undefined}\n */\n removeAllAnnotations () {\n this.eachAnnotation(annotation => annotation.dispose())\n this.annotationList.length = 0\n }\n\n /**\n * Add a new representation to the component\n * @param {String} type - the name of the representation\n * @param {Object} object - the object on which the representation should be based\n * @param {RepresentationParameters} [params] - representation parameters\n * @return {RepresentationElement} the created representation wrapped into\n * a representation element object\n */\n protected _addRepresentation (type: string, object: any, params: any, hidden = false) { // TODO\n const p = params || {}\n const sp = this.stage.getParameters() as any // TODO\n p.matrix = this.matrix.clone()\n p.quality = p.quality || sp.quality\n p.disableImpostor = defaults(p.disableImpostor, !sp.impostor)\n p.useWorker = defaults(p.useWorker, sp.workerDefault)\n p.visible = defaults(p.visible, true)\n\n const p2 = Object.assign({}, p, { visible: this.parameters.visible && p.visible })\n const repr = makeRepresentation(type, object, this.viewer, p2)\n const reprElem = new RepresentationElement(this.stage, repr, p, this)\n\n if (!hidden) {\n this.reprList.push(reprElem)\n this.signals.representationAdded.dispatch(reprElem)\n }\n return reprElem\n }\n\n abstract addRepresentation (type: any, params: any): any\n\n addBufferRepresentation (buffer: any, params: any) { // TODO\n return this._addRepresentation.call(this, 'buffer', buffer, params)\n }\n\n hasRepresentation (repr: RepresentationElement) {\n return this.reprList.indexOf(repr) !== -1\n }\n\n /**\n * Iterator over each representation and executing the callback\n * @param {Function} callback - function to execute\n * @return {undefined}\n */\n eachRepresentation (callback: (repr: RepresentationElement) => void) {\n this.reprList.slice().forEach(callback)\n }\n\n /**\n * Removes a representation component\n * @param {RepresentationElement} repr - the representation element\n * @return {undefined}\n */\n removeRepresentation (repr: RepresentationElement) {\n const idx = this.reprList.indexOf(repr)\n if (idx !== -1) {\n this.reprList.splice(idx, 1)\n repr.dispose()\n this.signals.representationRemoved.dispatch(repr)\n }\n }\n\n updateRepresentations (what: any) { // TODO\n this.reprList.forEach(repr => repr.update(what))\n this.stage.viewer.requestRender()\n }\n\n /**\n * Removes all representation components\n * @return {undefined}\n */\n removeAllRepresentations () {\n this.eachRepresentation(repr => repr.dispose())\n }\n\n dispose () {\n this.removeAllAnnotations()\n this.removeAllRepresentations()\n\n this.reprList.length = 0\n\n this.signals.disposed.dispatch()\n }\n\n /**\n * Set the visibility of the component, including added representations\n * @param {Boolean} value - visibility flag\n * @return {Component} this object\n */\n setVisibility (value: boolean) {\n this.parameters.visible = value\n\n this.eachRepresentation((repr: RepresentationElement) => repr.updateVisibility())\n this.eachAnnotation((annotation: Annotation) => annotation.updateVisibility())\n\n this.signals.visibilityChanged.dispatch(value)\n\n return this\n }\n\n setStatus (value: string) {\n this.parameters.status = value\n this.signals.statusChanged.dispatch(value)\n\n return this\n }\n\n setName (value: string) {\n this.parameters.name = value\n this.signals.nameChanged.dispatch(value)\n\n return this\n }\n\n /**\n * @return {Box3} the component's bounding box\n */\n getBox (...args: any[]) {\n return this.getBoxUntransformed(...args)\n .clone().applyMatrix4(this.matrix)\n }\n\n /**\n * @return {Vector3} the component's center position\n */\n getCenter (...args: any[]) {\n return this.getCenterUntransformed(...args)\n .clone().applyMatrix4(this.matrix)\n }\n\n getZoom (...args: any[]) {\n return this.stage.getZoomForBox(this.getBox(...args))\n }\n\n /**\n * @abstract\n * @return {Box3} the untransformed component's bounding box\n */\n getBoxUntransformed (...args: any[]): Box3 {\n return new Box3()\n }\n\n getCenterUntransformed (...args: any[]) {\n return this.getBoxUntransformed().getCenter(new Vector3())\n }\n\n /**\n * Automatically center and zoom the component\n * @param {Integer} [duration] - duration of the animation, defaults to 0\n * @return {undefined}\n */\n autoView (duration?: number) {\n this.stage.animationControls.zoomMove(\n this.getCenter(),\n this.getZoom(),\n defaults(duration, 0)\n )\n }\n}\n\nexport default Component\n","/**\n * @file Collection\n * @author Alexander Rose \n * @private\n */\n\nimport Component from './component'\nimport Element from './element'\n\nclass Collection {\n constructor (readonly list: T[] = []) {\n // remove elements from list when they get disposed\n const n = list.length\n\n for (let i = 0; i < n; ++i) {\n const elm = list[ i ]\n elm.signals.disposed.add(this._remove, this)\n }\n }\n\n _remove (elm: T) {\n const idx = this.list.indexOf(elm)\n\n if (idx !== -1) {\n this.list.splice(idx, 1)\n }\n }\n\n get first () {\n return this.list.length > 0 ? this.list[0] : undefined\n }\n\n forEach (fn: (x: T) => any) {\n this.list.forEach(fn)\n\n return this\n }\n\n dispose () {\n return this.forEach((elm) => elm.dispose())\n }\n}\n\nexport default Collection\n","/**\n * @file Component Collection\n * @author Alexander Rose \n * @private\n */\n\nimport RepresentationElement from './representation-element'\nimport Collection from './collection'\nimport { GenericColor } from '../types'\n\nclass RepresentationCollection extends Collection {\n setParameters (params: any) {\n return this.forEach((repr) => repr.setParameters(params))\n }\n\n setVisibility (value: boolean) {\n return this.forEach((repr) => repr.setVisibility(value))\n }\n\n setSelection (string: string) {\n return this.forEach((repr) => repr.setSelection(string))\n }\n\n setColor (color: GenericColor) {\n return this.forEach((repr) => repr.setColor(color))\n }\n\n update (what: any) {\n return this.forEach((repr) => repr.update(what))\n }\n\n build (params?: any) {\n return this.forEach((repr) => repr.build(params))\n }\n\n dispose (params?: any) {\n return this.forEach((repr) => repr.dispose())\n }\n}\n\nexport default RepresentationCollection\n","/**\n * @file Trajectory Component\n * @author Alexander Rose \n * @private\n */\n\nimport { Signal } from 'signals'\n\nimport Element, { ElementSignals, ElementDefaultParameters } from './element'\nimport Stage from '../stage/stage'\nimport Trajectory, { TrajectoryParameters } from '../trajectory/trajectory'\nimport TrajectoryPlayer, {\n TrajectoryPlayerDirection, TrajectoryPlayerMode, TrajectoryPlayerInterpolateType\n} from '../trajectory/trajectory-player'\n\n/**\n * Trajectory component parameter object.\n * @typedef {Object} TrajectoryComponentParameters - component parameters\n *\n * @property {String} name - component name\n * @property {Integer} initialFrame - initial frame the trajectory is set to\n * @property {Integer} defaultStep - default step size to be used by trajectory players\n * @property {Integer} defaultTimeout - default timeout to be used by trajectory players\n * @property {String} defaultInterpolateType - one of \"\" (empty string), \"linear\" or \"spline\"\n * @property {Integer} defaultInterpolateStep - window size used for interpolation\n * @property {String} defaultMode - either \"loop\" or \"once\"\n * @property {String} defaultDirection - either \"forward\" or \"backward\"\n */\n\nexport const TrajectoryElementDefaultParameters = Object.assign({\n defaultStep: 1,\n defaultTimeout: 50,\n defaultInterpolateType: '' as TrajectoryPlayerInterpolateType,\n defaultInterpolateStep: 5,\n defaultMode: 'loop' as TrajectoryPlayerMode,\n defaultDirection: 'forward' as TrajectoryPlayerDirection,\n initialFrame: 0\n}, ElementDefaultParameters)\nexport type TrajectoryElementParameters = typeof TrajectoryElementDefaultParameters\n\nexport interface TrajectoryElementSignals extends ElementSignals {\n frameChanged: Signal // on frame change\n playerChanged: Signal // on player change\n countChanged: Signal // when frame count is available\n parametersChanged: Signal // on parameters change\n}\n\n/**\n * Component wrapping a {@link Trajectory} object\n */\nclass TrajectoryElement extends Element {\n signals: TrajectoryElementSignals\n parameters: TrajectoryElementParameters\n get defaultParameters () { return TrajectoryElementDefaultParameters }\n\n /**\n * @param {Stage} stage - stage object the component belongs to\n * @param {Trajectory} trajectory - the trajectory object\n * @param {TrajectoryComponentParameters} params - component parameters\n * @param {StructureComponent} parent - the parent structure\n */\n constructor (stage: Stage, readonly trajectory: Trajectory, params: Partial = {}) {\n super(stage, Object.assign({ name: trajectory.name }, params))\n\n this.signals = Object.assign(this.signals, {\n frameChanged: new Signal(),\n playerChanged: new Signal(),\n countChanged: new Signal(),\n parametersChanged: new Signal()\n })\n\n // signals\n\n trajectory.signals.frameChanged.add((i: number) => {\n this.signals.frameChanged.dispatch(i)\n })\n\n trajectory.signals.playerChanged.add((player: TrajectoryPlayer) => {\n this.signals.playerChanged.dispatch(player)\n })\n\n trajectory.signals.countChanged.add((n: number) => {\n this.signals.countChanged.dispatch(n)\n })\n\n //\n\n if (params.initialFrame !== undefined) {\n this.setFrame(params.initialFrame)\n }\n }\n\n /**\n * Component type\n * @type {String}\n */\n get type () { return 'trajectory' }\n\n /**\n * Set the frame of the trajectory\n * @param {Integer} i - frame number\n * @return {undefined}\n */\n setFrame (i: number) {\n this.trajectory.setFrame(i)\n }\n\n /**\n * Set trajectory parameters\n * @param {TrajectoryParameters} params - trajectory parameters\n * @return {undefined}\n */\n setParameters (params: Partial = {}) {\n this.trajectory.setParameters(params)\n this.signals.parametersChanged.dispatch(params)\n }\n\n dispose () {\n this.trajectory.dispose()\n super.dispose()\n }\n}\n\nexport default TrajectoryElement\n","/**\n * @file Frames\n * @author Alexander Rose \n * @private\n */\n\nexport default class Frames {\n coordinates = []\n boxes = []\n times = []\n\n timeOffset = 0\n deltaTime = 1\n\n constructor (readonly name: string, readonly path: string) {}\n\n get type () { return 'Frames' }\n}\n","/**\n * @file Superposition\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4 } from 'three'\nimport { Debug, Log } from '../globals'\nimport {\n Matrix, svd, meanRows, subRows, transpose,\n multiplyABt, invert3x3, multiply3x3, mat3x3determinant, multiply\n} from '../math/matrix-utils'\nimport Structure from '../structure/structure'\n\nclass Superposition {\n coords1t: Matrix\n coords2t: Matrix\n\n transformationMatrix: Matrix4\n\n mean1: number[]\n mean2: number[]\n\n A = new Matrix(3, 3)\n W = new Matrix(1, 3)\n U = new Matrix(3, 3)\n V = new Matrix(3, 3)\n VH = new Matrix(3, 3)\n R = new Matrix(3, 3)\n\n private tmp = new Matrix(3, 3)\n private c = new Matrix(3, 3)\n\n constructor (atoms1: Structure|Float32Array, atoms2: Structure|Float32Array) {\n // allocate & init data structures\n\n let n1\n if (atoms1 instanceof Structure) {\n n1 = atoms1.atomCount\n } else if (atoms1 instanceof Float32Array) {\n n1 = atoms1.length / 3\n } else {\n return\n }\n\n let n2\n if (atoms2 instanceof Structure) {\n n2 = atoms2.atomCount\n } else if (atoms2 instanceof Float32Array) {\n n2 = atoms2.length / 3\n } else {\n return\n }\n\n const n = Math.min(n1, n2)\n\n const coords1 = new Matrix(3, n)\n const coords2 = new Matrix(3, n)\n\n this.coords1t = new Matrix(n, 3)\n this.coords2t = new Matrix(n, 3)\n\n this.transformationMatrix = new Matrix4()\n\n this.c.data.set([ 1, 0, 0, 0, 1, 0, 0, 0, -1 ])\n\n // prep coords\n\n this.prepCoords(atoms1, coords1, n, false)\n this.prepCoords(atoms2, coords2, n, false)\n\n // superpose\n\n this._superpose(coords1, coords2)\n }\n\n _superpose (coords1: Matrix, coords2: Matrix) {\n this.mean1 = meanRows(coords1)\n this.mean2 = meanRows(coords2)\n\n subRows(coords1, this.mean1)\n subRows(coords2, this.mean2)\n\n transpose(this.coords1t, coords1)\n transpose(this.coords2t, coords2)\n\n multiplyABt(this.A, this.coords2t, this.coords1t)\n\n svd(this.A, this.W, this.U, this.V)\n\n invert3x3(this.V, this.VH)\n multiply3x3(this.R, this.U, this.VH)\n\n if (mat3x3determinant(this.R) < 0.0) {\n if (Debug) Log.log('R not a right handed system')\n\n multiply3x3(this.tmp, this.c, this.VH)\n multiply3x3(this.R, this.U, this.tmp)\n }\n\n //get the transformation matrix\n\n const transformMat_ = new Matrix(4,4)\n const tmp_1 = new Matrix(4,4)\n const tmp_2 = new Matrix(4,4)\n\n const sub = new Matrix(4,4)\n const mult = new Matrix(4,4)\n const add = new Matrix(4,4)\n\n const R = this.R.data\n const M1 = this.mean1\n const M2 = this.mean2\n\n sub.data.set([ 1, 0, 0, -M1[0],\n 0, 1, 0, -M1[1],\n 0, 0, 1, -M1[2],\n 0, 0, 0, 1 ])\n\n mult.data.set([ R[0], R[1], R[2], 0,\n R[3], R[4], R[5], 0,\n R[6], R[7], R[8], 0,\n 0, 0, 0, 1 ])\n\n add.data.set([ 1, 0, 0, M2[0],\n 0, 1, 0, M2[1],\n 0, 0, 1, M2[2],\n 0, 0, 0, 1 ])\n\n transpose(tmp_1,sub)\n multiplyABt(transformMat_,mult,tmp_1)\n transpose(tmp_2,transformMat_)\n multiplyABt(tmp_1,add,tmp_2)\n\n transpose(transformMat_,tmp_1)\n this.transformationMatrix.elements = transformMat_.data as unknown as number[]\n\n }\n\n prepCoords (atoms: Structure|Float32Array, coords: Matrix, n: number, is4X4: boolean) {\n let i = 0\n const cd = coords.data\n\n let c = 3\n let d = n * 3\n\n if (is4X4) {\n d = n * 4\n c = 4\n }\n if (atoms instanceof Structure) {\n atoms.eachAtom(function (a) {\n if (i < d) {\n cd[ i + 0 ] = a.x\n cd[ i + 1 ] = a.y\n cd[ i + 2 ] = a.z\n if (is4X4) cd[ i + 3 ] = 1\n\n i += c\n }\n })\n } else if (atoms instanceof Float32Array) {\n for (; i < d; i += c){\n if (i < d) {\n cd[ i ] = atoms[ i ]\n cd[ i + 1 ] = atoms[ i + 1 ]\n cd[ i + 2 ] = atoms[ i + 2 ]\n if (is4X4) cd[ i + 3 ] = 1\n }\n }\n } else {\n Log.warn('prepCoords: input type unknown')\n }\n }\n\n transform (atoms: Structure|Float32Array) {\n // allocate data structures\n\n let n\n if (atoms instanceof Structure) {\n n = atoms.atomCount\n } else if (atoms instanceof Float32Array) {\n n = atoms.length / 3\n } else {\n return\n }\n\n const coords = new Matrix(4, n)\n const tCoords = new Matrix(n,4)\n\n // prep coords\n\n this.prepCoords(atoms, coords, n, true)\n\n // check for transformation matrix correctness\n\n const transform = this.transformationMatrix\n const det = transform.determinant()\n if (!det){\n return det\n }\n\n // do transform\n\n const mult = new Matrix(4,4)\n mult.data = transform.elements as unknown as Float32Array\n multiply(tCoords,coords,mult)\n\n let i = 0\n const cd = tCoords.data\n if (atoms instanceof Structure) {\n atoms.eachAtom(function (a) {\n a.x = cd[ i ]\n a.y = cd[ i + 1 ]\n a.z = cd[ i + 2 ]\n i += 4\n })\n\n //update transformation matrices for each assembly\n\n const invertTrasform = new Matrix4()\n invertTrasform.copy(transform).invert()\n\n const biomolDict = atoms.biomolDict\n\n for (let key in biomolDict) {\n\n if (biomolDict.hasOwnProperty(key)) {\n let assembly = biomolDict[key]\n\n assembly.partList.forEach(function(part){\n\n part.matrixList.forEach(function(mat){\n\n mat.premultiply(transform)\n mat.multiply(invertTrasform)\n\n })\n })\n }\n }\n } else if (atoms instanceof Float32Array) {\n\n const n4 = n * 4\n for (; i < n4; i += 4){\n\n atoms[ i ] = cd[ i ]\n atoms[ i + 1 ] = cd[ i + 1 ]\n atoms[ i + 2 ] = cd[ i + 2 ]\n\n }\n } else {\n Log.warn('transform: input type unknown')\n }\n\n return this.transformationMatrix\n }\n}\nexport default Superposition\n","/**\n * @file Trajectory Player\n * @author Alexander Rose \n * @private\n */\n\nimport { Signal } from 'signals'\n\nimport { defaults, createParams, updateParams } from '../utils'\nimport Trajectory from './trajectory'\n\nexport type TrajectoryPlayerInterpolateType = ''|'linear'|'spline'\nexport type TrajectoryPlayerMode = 'loop'|'once'\nexport type TrajectoryPlayerDirection = 'forward'|'backward'|'bounce'\n\nexport const TrajectoryPlayerDefaultParameters = {\n step: 1, // how many frames to advance when playing\n timeout: 50, // how many milliseconds to wait between playing frames\n start: 0, // first frame to play\n end: 0, // last frame to play\n interpolateType: '' as TrajectoryPlayerInterpolateType,\n interpolateStep: 5, // window size used for interpolation\n mode: 'loop' as TrajectoryPlayerMode,\n direction: 'forward' as TrajectoryPlayerDirection\n}\nexport type TrajectoryPlayerParameters = typeof TrajectoryPlayerDefaultParameters\n\nexport interface TrajectoryPlayerSignals {\n startedRunning: Signal\n haltedRunning: Signal\n}\n\n/**\n * Trajectory player for animating coordinate frames\n * @example\n * var player = new TrajectoryPlayer(trajectory, {step: 1, timeout: 50});\n * player.play();\n */\nclass TrajectoryPlayer {\n signals: TrajectoryPlayerSignals = {\n startedRunning: new Signal(),\n haltedRunning: new Signal()\n }\n\n parameters: TrajectoryPlayerParameters\n traj: Trajectory\n\n private _run = false\n private _previousTime = 0\n private _currentTime = 0\n private _currentStep = 1\n private _currentFrame: number|[number, number, number, number]\n private _direction: TrajectoryPlayerDirection\n\n /**\n * make trajectory player\n * @param {Trajectory} traj - the trajectory\n * @param {TrajectoryPlayerParameters} [params] - parameter object\n */\n constructor (traj: Trajectory, params: Partial = {}) {\n traj.signals.playerChanged.add((player: TrajectoryPlayer) => {\n if (player !== this) {\n this.pause()\n }\n }, this)\n\n const n = defaults(traj.frameCount, 1)\n\n this.traj = traj\n this.parameters = createParams(params, TrajectoryPlayerDefaultParameters)\n this.parameters.end = Math.min(defaults(params.end, n - 1), n - 1)\n this.parameters.step = defaults(params.step, Math.ceil((n + 1) / 100))\n\n this._currentFrame = this.parameters.start\n this._direction = this.parameters.direction === 'bounce' ? 'forward' : this.parameters.direction\n\n traj.signals.countChanged.add((n: number) => {\n this.parameters.end = Math.min(defaults(this.parameters.end, n - 1), n - 1)\n }, this)\n\n this._animate = this._animate.bind(this)\n }\n\n get isRunning () { return this._run }\n\n /**\n * set player parameters\n * @param {TrajectoryPlayerParameters} [params] - parameter object\n */\n setParameters (params: Partial = {}) {\n updateParams(this.parameters, params)\n\n if (params.direction !== undefined && this.parameters.direction !== 'bounce') {\n this._direction = this.parameters.direction\n }\n }\n\n _animate () {\n if (!this._run) return\n\n this._currentTime = window.performance.now()\n const dt = this._currentTime - this._previousTime\n const step = this.parameters.interpolateType ? this.parameters.interpolateStep : 1\n const timeout = this.parameters.timeout / step\n const traj = this.traj\n\n if (traj && traj.frameCount && !traj.inProgress && dt >= timeout) {\n if (this.parameters.interpolateType) {\n if (this._currentStep > this.parameters.interpolateStep) {\n this._currentStep = 1\n }\n if (this._currentStep === 1) {\n this._currentFrame = this._nextInterpolated()\n }\n if (traj.hasFrame(this._currentFrame)) {\n this._currentStep += 1\n const t = this._currentStep / (this.parameters.interpolateStep + 1)\n const [i, ip, ipp, ippp] = this._currentFrame as [number, number, number, number]\n traj.setFrameInterpolated(\n i, ip, ipp, ippp, t, this.parameters.interpolateType\n )\n this._previousTime = this._currentTime\n } else {\n traj.loadFrame(this._currentFrame)\n }\n } else {\n const i = this._next()\n if (traj.hasFrame(i)) {\n traj.setFrame(i)\n this._previousTime = this._currentTime\n } else {\n traj.loadFrame(i)\n }\n }\n }\n\n window.requestAnimationFrame(this._animate)\n }\n\n _next () {\n const p = this.parameters\n let i\n\n if (this._direction === 'forward') {\n i = this.traj.currentFrame + p.step\n } else {\n i = this.traj.currentFrame - p.step\n }\n\n if (i > p.end || i < p.start) {\n if (p.direction === 'bounce') {\n if (this._direction === 'forward') {\n this._direction = 'backward'\n } else {\n this._direction = 'forward'\n }\n }\n\n if (p.mode === 'once') {\n this.pause()\n\n if (p.direction === 'forward') {\n i = p.end\n } else if (p.direction === 'backward') {\n i = p.start\n } else {\n if (this._direction === 'forward') {\n i = p.start\n } else {\n i = p.end\n }\n }\n } else {\n if (this._direction === 'forward') {\n i = p.start\n if (p.interpolateType) {\n i = Math.min(p.end, i + p.step)\n }\n } else {\n i = p.end\n if (p.interpolateType) {\n i = Math.max(p.start, i - p.step)\n }\n }\n }\n }\n\n return i\n }\n\n _nextInterpolated () {\n const p = this.parameters\n const i = this._next()\n let ip, ipp, ippp\n\n if (this._direction === 'forward') {\n ip = Math.max(p.start, i - p.step)\n ipp = Math.max(p.start, i - 2 * p.step)\n ippp = Math.max(p.start, i - 3 * p.step)\n } else {\n ip = Math.min(p.end, i + p.step)\n ipp = Math.min(p.end, i + 2 * p.step)\n ippp = Math.min(p.end, i + 3 * p.step)\n }\n\n return [i, ip, ipp, ippp] as [number, number, number, number]\n }\n\n /**\n * toggle between playing and pausing the animation\n * @return {undefined}\n */\n toggle () {\n if (this._run) {\n this.pause()\n } else {\n this.play()\n }\n }\n\n /**\n * start the animation\n * @return {undefined}\n */\n play () {\n if (!this._run) {\n if (this.traj.player !== this) {\n this.traj.setPlayer(this)\n }\n this._currentStep = 1\n\n const p = this.parameters\n const frame = this.traj.currentFrame\n\n // snap to the grid implied by this.step division and multiplication\n // thus minimizing cache misses\n let i = Math.ceil(frame / p.step) * p.step\n // wrap when restarting from the limit (i.e. end or start)\n if (p.direction === 'forward' && frame >= p.end) {\n i = p.start\n } else if (p.direction === 'backward' && frame <= p.start) {\n i = p.end\n }\n\n this.traj.setFrame(i)\n\n this._run = true\n this._animate()\n this.signals.startedRunning.dispatch()\n }\n }\n\n /**\n * pause the animation\n * @return {undefined}\n */\n pause () {\n this._run = false\n this.signals.haltedRunning.dispatch()\n }\n\n /**\n * stop the animation (pause and go to start-frame)\n * @return {undefined}\n */\n stop () {\n this.pause()\n this.traj.setFrame(this.parameters.start)\n }\n}\n\nexport default TrajectoryPlayer\n","/**\n * @file Trajectory\n * @author Alexander Rose \n * @private\n */\n\nimport { Signal } from 'signals'\n\nimport { Log } from '../globals'\nimport { defaults } from '../utils'\nimport { NumberArray } from '../types'\nimport { circularMean, arrayMean } from '../math/array-utils'\nimport { lerp, spline } from '../math/math-utils'\nimport Selection from '../selection/selection'\nimport Superposition from '../align/superposition'\nimport Structure from '../structure/structure'\nimport AtomProxy from '../proxy/atom-proxy'\nimport TrajectoryPlayer, { TrajectoryPlayerInterpolateType } from './trajectory-player'\n\n\nfunction centerPbc (coords: NumberArray, mean: number[], box: ArrayLike) {\n if (box[ 0 ] === 0 || box[ 8 ] === 0 || box[ 4 ] === 0) {\n return\n }\n\n const n = coords.length\n\n const bx = box[ 0 ]\n const by = box[ 1 ]\n const bz = box[ 2 ]\n const mx = mean[ 0 ]\n const my = mean[ 1 ]\n const mz = mean[ 2 ]\n\n const fx = -mx + bx + bx / 2\n const fy = -my + by + by / 2\n const fz = -mz + bz + bz / 2\n\n for (let i = 0; i < n; i += 3) {\n coords[ i + 0 ] = (coords[ i + 0 ] + fx) % bx\n coords[ i + 1 ] = (coords[ i + 1 ] + fy) % by\n coords[ i + 2 ] = (coords[ i + 2 ] + fz) % bz\n }\n}\n\nfunction removePbc (x: NumberArray, box: ArrayLike) {\n if (box[ 0 ] === 0 || box[ 8 ] === 0 || box[ 4 ] === 0) {\n return\n }\n\n // ported from GROMACS src/gmxlib/rmpbc.c:rm_gropbc()\n // in-place\n\n const n = x.length\n\n for (let i = 3; i < n; i += 3) {\n for (let j = 0; j < 3; ++j) {\n const dist = x[ i + j ] - x[ i - 3 + j ]\n\n if (Math.abs(dist) > 0.9 * box[ j * 3 + j ]) {\n if (dist > 0) {\n for (let d = 0; d < 3; ++d) {\n x[ i + d ] -= box[ j * 3 + d ]\n }\n } else {\n for (let d = 0; d < 3; ++d) {\n x[ i + d ] += box[ j * 3 + d ]\n }\n }\n }\n }\n }\n\n return x\n}\n\nfunction removePeriodicity (x: NumberArray, box: ArrayLike, mean: number[]) {\n if (box[ 0 ] === 0 || box[ 8 ] === 0 || box[ 4 ] === 0) {\n return\n }\n\n const n = x.length\n for (let i = 3; i < n; i += 3) {\n for (let j = 0; j < 3; ++j) {\n const f = (x[ i + j ] - mean[ j ]) / box[ j * 3 + j ]\n if (Math.abs(f) > 0.5) {\n x[ i + j ] -= box[ j * 3 + j ] * Math.round(f)\n }\n }\n }\n\n return x\n}\n\nfunction circularMean3 (indices: NumberArray, coords: NumberArray, box: ArrayLike) {\n return [\n circularMean(coords, box[ 0 ], 3, 0, indices),\n circularMean(coords, box[ 1 ], 3, 1, indices),\n circularMean(coords, box[ 2 ], 3, 2, indices)\n ]\n}\n\nfunction arrayMean3 (coords: NumberArray) {\n return [\n arrayMean(coords, 3, 0),\n arrayMean(coords, 3, 1),\n arrayMean(coords, 3, 2)\n ]\n}\n\nfunction interpolateSpline (c: NumberArray, cp: NumberArray, cpp: NumberArray, cppp: NumberArray, t: number) {\n const m = c.length\n const coords = new Float32Array(m)\n\n for (let j0 = 0; j0 < m; j0 += 3) {\n const j1 = j0 + 1\n const j2 = j0 + 2\n coords[ j0 ] = spline(cppp[ j0 ], cpp[ j0 ], cp[ j0 ], c[ j0 ], t, 1)\n coords[ j1 ] = spline(cppp[ j1 ], cpp[ j1 ], cp[ j1 ], c[ j1 ], t, 1)\n coords[ j2 ] = spline(cppp[ j2 ], cpp[ j2 ], cp[ j2 ], c[ j2 ], t, 1)\n }\n\n return coords\n}\n\nfunction interpolateLerp (c: NumberArray, cp: NumberArray, t: number) {\n const m = c.length\n const coords = new Float32Array(m)\n\n for (let j0 = 0; j0 < m; j0 += 3) {\n const j1 = j0 + 1\n const j2 = j0 + 2\n coords[ j0 ] = lerp(cp[ j0 ], c[ j0 ], t)\n coords[ j1 ] = lerp(cp[ j1 ], c[ j1 ], t)\n coords[ j2 ] = lerp(cp[ j2 ], c[ j2 ], t)\n }\n\n return coords\n}\n\n/**\n * Trajectory parameter object.\n * @typedef {Object} TrajectoryParameters - parameters\n *\n * @property {Number} deltaTime - timestep between frames in picoseconds\n * @property {Number} timeOffset - starting time of frames in picoseconds\n * @property {String} sele - to restrict atoms used for superposition\n * @property {Boolean} centerPbc - center on initial frame\n * @property {Boolean} removePeriodicity - move atoms into the origin box\n * @property {Boolean} remo - try fixing periodic boundary discontinuities\n * @property {Boolean} superpose - superpose on initial frame\n */\n\n/**\n * @example\n * trajectory.signals.frameChanged.add( function(i){ ... } );\n *\n * @typedef {Object} TrajectorySignals\n * @property {Signal} countChanged - when the frame count is changed\n * @property {Signal} frameChanged - when the set frame is changed\n * @property {Signal} playerChanged - when the player is changed\n */\n\nexport interface TrajectoryParameters {\n deltaTime: number // timestep between frames in picoseconds\n timeOffset: number // starting time of frames in picoseconds\n sele: string // to restrict atoms used for superposition\n centerPbc: boolean // center on initial frame\n removePbc: boolean // move atoms into the origin box\n removePeriodicity: boolean // try fixing periodic boundary discontinuities\n superpose: boolean // superpose on initial frame\n}\n\nexport interface TrajectorySignals {\n countChanged: Signal\n frameChanged: Signal\n playerChanged: Signal\n}\n\n/**\n * Base class for trajectories, tying structures and coordinates together\n * @interface\n */\nclass Trajectory {\n signals: TrajectorySignals = {\n countChanged: new Signal(),\n frameChanged: new Signal(),\n playerChanged: new Signal()\n }\n\n deltaTime: number\n timeOffset: number\n sele: string\n centerPbc: boolean\n removePbc: boolean\n removePeriodicity: boolean\n superpose: boolean\n\n name: string\n frame: number\n trajPath: string\n\n initialCoords: Float32Array\n structureCoords: Float32Array\n selectionIndices: NumberArray\n backboneIndices: NumberArray\n\n coords1: Float32Array\n coords2: Float32Array\n\n frameCache: { [k: number]: Float32Array } = {}\n loadQueue: { [k: number]: boolean } = {}\n boxCache: { [k: number]: ArrayLike } = {}\n pathCache = {}\n frameCacheSize = 0\n\n atomCount: number\n inProgress: boolean\n\n selection: Selection // selection to restrict atoms used for superposition\n structure: Structure\n player: TrajectoryPlayer\n\n private _frameCount = 0\n private _currentFrame = -1\n private _disposed = false\n\n /**\n * @param {String} trajPath - trajectory source\n * @param {Structure} structure - the structure object\n * @param {TrajectoryParameters} params - trajectory parameters\n */\n constructor (trajPath: string, structure: Structure, params: Partial = {}) {\n this.deltaTime = defaults(params.deltaTime, 0)\n this.timeOffset = defaults(params.timeOffset, 0)\n this.centerPbc = defaults(params.centerPbc, false)\n this.removePbc = defaults(params.removePbc, false)\n this.removePeriodicity = defaults(params.removePeriodicity, false)\n this.superpose = defaults(params.superpose, false)\n\n this.name = trajPath.replace(/^.*[\\\\/]/, '')\n this.trajPath = trajPath\n\n this.selection = new Selection(\n defaults(params.sele, 'backbone and not hydrogen')\n )\n\n this.selection.signals.stringChanged.add(() => {\n this.selectionIndices = this.structure.getAtomIndices(this.selection)!\n this._resetCache()\n this._saveInitialCoords()\n this.setFrame(this._currentFrame)\n })\n }\n\n /**\n * Number of frames in the trajectory\n */\n get frameCount () {\n return this._frameCount\n }\n\n /**\n * Currently set frame of the trajectory\n */\n get currentFrame () {\n return this._currentFrame\n }\n\n _init (structure: Structure) {\n this.setStructure(structure)\n this._loadFrameCount()\n this.setPlayer(new TrajectoryPlayer(this))\n }\n\n _loadFrameCount () {}\n\n setStructure (structure: Structure) {\n this.structure = structure\n this.atomCount = structure.atomCount\n\n this.backboneIndices = this._getIndices(\n new Selection('backbone and not hydrogen')\n )\n this._makeAtomIndices()\n this._saveStructureCoords()\n\n this.selectionIndices = this._getIndices(this.selection)\n this._resetCache()\n this._saveInitialCoords()\n this.setFrame(this._currentFrame)\n }\n\n _saveInitialCoords () {\n if (this.structure.hasCoords()) {\n this.initialCoords = new Float32Array(this.structureCoords)\n this._makeSuperposeCoords()\n } else if (this.frameCache[0]) {\n this.initialCoords = new Float32Array(this.frameCache[0])\n this._makeSuperposeCoords()\n } else {\n this.loadFrame(0, () => this._saveInitialCoords())\n }\n }\n\n _saveStructureCoords () {\n const p = { what: { position: true } }\n this.structureCoords = this.structure.getAtomData(p).position!\n }\n\n setSelection (string: string) {\n this.selection.setString(string)\n return this\n }\n\n _getIndices (selection: Selection) {\n let i = 0\n const test = selection.test\n const indices: number[] = []\n\n if (test) {\n this.structure.eachAtom((ap: AtomProxy) => {\n if (test(ap)) indices.push(i)\n i += 1\n })\n }\n\n return indices\n }\n\n _makeSuperposeCoords () {\n const n = this.selectionIndices.length * 3\n\n this.coords1 = new Float32Array(n)\n this.coords2 = new Float32Array(n)\n\n const y = this.initialCoords\n const coords2 = this.coords2\n\n for (let i = 0; i < n; i += 3) {\n const j = this.selectionIndices[ i / 3 ] * 3\n\n coords2[ i + 0 ] = y[ j + 0 ]\n coords2[ i + 1 ] = y[ j + 1 ]\n coords2[ i + 2 ] = y[ j + 2 ]\n }\n }\n\n _makeAtomIndices () {\n Log.error('Trajectory._makeAtomIndices not implemented')\n }\n\n _resetCache () {\n this.frameCache = {}\n this.loadQueue = {}\n this.boxCache = {}\n this.pathCache = {}\n this.frameCacheSize = 0\n this.initialCoords = new Float32Array(0)\n }\n\n setParameters (params: Partial = {}) {\n let resetCache = false\n\n if (params.centerPbc !== undefined && params.centerPbc !== this.centerPbc) {\n this.centerPbc = params.centerPbc\n resetCache = true\n }\n\n if (params.removePeriodicity !== undefined && params.removePeriodicity !== this.removePeriodicity) {\n this.removePeriodicity = params.removePeriodicity\n resetCache = true\n }\n\n if (params.removePbc !== undefined && params.removePbc !== this.removePbc) {\n this.removePbc = params.removePbc\n resetCache = true\n }\n\n if (params.superpose !== undefined && params.superpose !== this.superpose) {\n this.superpose = params.superpose\n resetCache = true\n }\n\n this.deltaTime = defaults(params.deltaTime, this.deltaTime)\n this.timeOffset = defaults(params.timeOffset, this.timeOffset)\n\n if (resetCache) {\n this._resetCache()\n this.setFrame(this._currentFrame)\n }\n }\n\n /**\n * Check if a frame is available\n * @param {Integer|Integer[]} i - the frame index\n * @return {Boolean} frame availability\n */\n hasFrame (i: number|number[]) {\n if (Array.isArray(i)) {\n return i.every(j => !!this.frameCache[j])\n } else {\n return !!this.frameCache[i]\n }\n }\n\n /**\n * Set trajectory to a frame index\n * @param {Integer} i - the frame index\n * @param {Function} [callback] - fired when the frame has been set\n */\n setFrame (i: number, callback?: Function) {\n if (i === undefined) return this\n\n this.inProgress = true\n\n // i = parseInt(i) // TODO\n\n if (i === -1 || this.frameCache[ i ]) {\n this._updateStructure(i)\n if (callback) callback()\n } else {\n this.loadFrame(i, () => {\n this._updateStructure(i)\n if (callback) callback()\n })\n }\n\n return this\n }\n\n _interpolate (i: number, ip: number, ipp: number, ippp: number, t: number, type: TrajectoryPlayerInterpolateType) {\n const fc = this.frameCache\n\n let coords\n if (type === 'spline') {\n coords = interpolateSpline(fc[ i ], fc[ ip ], fc[ ipp ], fc[ ippp ], t)\n } else {\n coords = interpolateLerp(fc[ i ], fc[ ip ], t)\n }\n\n this.structure.updatePosition(coords)\n this._currentFrame = i\n this.signals.frameChanged.dispatch(i)\n }\n\n /**\n * Interpolated and set trajectory to frame indices\n * @param {Integer} i - the frame index\n * @param {Integer} ip - one before frame index\n * @param {Integer} ipp - two before frame index\n * @param {Integer} ippp - three before frame index\n * @param {Number} t - interpolation step [0,1]\n * @param {String} type - interpolation type, '', 'spline' or 'linear'\n * @param {Function} callback - fired when the frame has been set\n */\n setFrameInterpolated (i: number, ip: number, ipp: number, ippp: number, t: number, type: TrajectoryPlayerInterpolateType, callback?: Function) {\n if (i === undefined) return this\n\n const fc = this.frameCache\n const iList: number[] = []\n\n if (!fc[ ippp ]) iList.push(ippp)\n if (!fc[ ipp ]) iList.push(ipp)\n if (!fc[ ip ]) iList.push(ip)\n if (!fc[ i ]) iList.push(i)\n\n if (iList.length) {\n this.loadFrame(iList, () => {\n this._interpolate(i, ip, ipp, ippp, t, type)\n if (callback) callback()\n })\n } else {\n this._interpolate(i, ip, ipp, ippp, t, type)\n if (callback) callback()\n }\n\n return this\n }\n\n /**\n * Load frame index\n * @param {Integer|Integer[]} i - the frame index\n * @param {Function} callback - fired when the frame has been loaded\n */\n loadFrame (i: number|number[], callback?: Function) {\n if (Array.isArray(i)) {\n i.forEach(j => {\n if (!this.loadQueue[j] && !this.frameCache[j]) {\n this.loadQueue[j] = true\n this._loadFrame(j, () => {\n delete this.loadQueue[j]\n })\n }\n })\n } else {\n if (!this.loadQueue[i] && !this.frameCache[i]) {\n this.loadQueue[i] = true\n this._loadFrame(i, () => {\n delete this.loadQueue[i]\n if (callback) callback()\n })\n }\n }\n }\n\n /**\n * Load frame index\n * @abstract\n * @param {Integer} i - the frame index\n * @param {Function} callback - fired when the frame has been loaded\n */\n _loadFrame (i: number, callback?: Function) {\n Log.error('Trajectory._loadFrame not implemented', i, callback)\n }\n\n _updateStructure (i: number) {\n if (this._disposed) {\n console.error('updateStructure: traj disposed')\n return\n }\n\n if (i === -1) {\n if (this.structureCoords) {\n this.structure.updatePosition(this.structureCoords)\n }\n } else {\n this.structure.updatePosition(this.frameCache[ i ])\n }\n\n this.structure.trajectory = {\n name: this.trajPath,\n frame: i\n }\n\n this._currentFrame = i\n this.inProgress = false\n this.signals.frameChanged.dispatch(i)\n }\n\n _doSuperpose (x: Float32Array) {\n const n = this.selectionIndices.length * 3\n\n const coords1 = this.coords1\n const coords2 = this.coords2\n\n for (let i = 0; i < n; i += 3) {\n const j = this.selectionIndices[ i / 3 ] * 3\n\n coords1[ i + 0 ] = x[ j + 0 ]\n coords1[ i + 1 ] = x[ j + 1 ]\n coords1[ i + 2 ] = x[ j + 2 ]\n }\n\n // TODO re-use superposition object\n const sp = new Superposition(coords1, coords2)\n sp.transform(x)\n }\n\n _process (i: number, box: ArrayLike, coords: Float32Array, frameCount: number) {\n this._setFrameCount(frameCount)\n\n if (box) {\n if (this.backboneIndices.length > 0 && this.centerPbc) {\n const box2 = [ box[ 0 ], box[ 4 ], box[ 8 ] ]\n const circMean = circularMean3(this.backboneIndices, coords, box2)\n centerPbc(coords, circMean, box2)\n }\n\n if (this.removePeriodicity) {\n const mean = arrayMean3(coords)\n removePeriodicity(coords, box, mean)\n }\n\n if (this.removePbc) {\n removePbc(coords, box)\n }\n }\n\n if (this.selectionIndices.length > 0 && this.coords1 && this.superpose) {\n this._doSuperpose(coords)\n }\n\n this.frameCache[ i ] = coords\n this.boxCache[ i ] = box\n this.frameCacheSize += 1\n }\n\n _setFrameCount (n: number) {\n if (n !== this._frameCount) {\n this._frameCount = n\n this.signals.countChanged.dispatch(n)\n }\n }\n\n /**\n * Dispose of the trajectory object\n * @return {undefined}\n */\n dispose () {\n this._resetCache() // aid GC\n this._disposed = true\n if (this.player) this.player.stop()\n }\n\n /**\n * Set player for this trajectory\n * @param {TrajectoryPlayer} player - the player\n */\n setPlayer (player: TrajectoryPlayer) {\n this.player = player\n this.signals.playerChanged.dispatch(player)\n }\n\n /**\n * Get time for frame\n * @param {Integer} i - frame index\n * @return {Number} time in picoseconds\n */\n getFrameTime (i: number) {\n return this.timeOffset + i * this.deltaTime\n }\n}\n\nexport default Trajectory\n","/**\n * @file Frames Trajectory\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport Structure from '../structure/structure'\nimport Frames from './frames'\nimport Trajectory, { TrajectoryParameters } from './trajectory'\n\n/**\n * Frames trajectory class. Gets data from a frames object.\n */\nclass FramesTrajectory extends Trajectory {\n path: string\n\n frames: ArrayLike[]\n boxes: ArrayLike[]\n\n atomIndices?: ArrayLike\n\n constructor (frames: Frames, structure: Structure, params: TrajectoryParameters) {\n const p = params || {}\n p.timeOffset = defaults(p.timeOffset, frames.timeOffset)\n p.deltaTime = defaults(p.deltaTime, frames.deltaTime)\n\n super('', structure, p)\n\n this.name = frames.name\n this.path = frames.path\n\n this.frames = frames.coordinates\n this.boxes = frames.boxes\n\n this._init(structure)\n }\n\n get type () { return 'frames' }\n\n _makeAtomIndices () {\n if (this.structure.type === 'StructureView') {\n this.atomIndices = this.structure.getAtomIndices()\n } else {\n this.atomIndices = undefined\n }\n }\n\n _loadFrame (i: number, callback?: Function) {\n let coords\n const frame = this.frames[ i ]\n\n if (this.atomIndices) {\n const indices = this.atomIndices\n const m = indices.length\n\n coords = new Float32Array(m * 3)\n\n for (let j = 0; j < m; ++j) {\n const j3 = j * 3\n const idx3 = indices[ j ] * 3\n\n coords[ j3 + 0 ] = frame[ idx3 + 0 ]\n coords[ j3 + 1 ] = frame[ idx3 + 1 ]\n coords[ j3 + 2 ] = frame[ idx3 + 2 ]\n }\n } else {\n coords = new Float32Array(frame)\n }\n\n const box = this.boxes[ i ]\n const frameCount = this.frames.length\n\n this._process(i, box, coords, frameCount)\n\n if (typeof callback === 'function') {\n callback()\n }\n }\n\n _loadFrameCount () {\n if (this.frames) {\n this._setFrameCount(this.frames.length)\n }\n }\n}\n\nexport default FramesTrajectory\n","/**\n * @file Structure Trajectory\n * @author Alexander Rose \n * @private\n */\n\nimport Structure from '../structure/structure'\nimport Trajectory, { TrajectoryParameters } from './trajectory'\n\n/**\n * Structure trajectory class. Gets data from a structure object.\n */\nclass StructureTrajectory extends Trajectory {\n atomIndices?: ArrayLike\n\n constructor (trajPath: string, structure: Structure, params: TrajectoryParameters) {\n super('', structure, params)\n this._init(structure)\n }\n\n get type () { return 'structure' }\n\n _makeAtomIndices () {\n if (this.structure.atomSet && this.structure.atomSet.getSize() < this.structure.atomStore.count) {\n this.atomIndices = this.structure.getAtomIndices()\n } else {\n this.atomIndices = undefined\n }\n }\n\n _loadFrame (i: number, callback?: Function) {\n let coords\n const structure = this.structure\n const frame = structure.frames[ i ]\n\n if (this.atomIndices) {\n const indices = this.atomIndices\n const m = indices.length\n\n coords = new Float32Array(m * 3)\n\n for (let j = 0; j < m; ++j) {\n const j3 = j * 3\n const idx3 = indices[ j ] * 3\n\n coords[ j3 + 0 ] = frame[ idx3 + 0 ]\n coords[ j3 + 1 ] = frame[ idx3 + 1 ]\n coords[ j3 + 2 ] = frame[ idx3 + 2 ]\n }\n } else {\n coords = new Float32Array(frame)\n }\n\n const box = structure.boxes[ i ]\n const frameCount = structure.frames.length\n\n this._process(i, box, coords, frameCount)\n\n if (typeof callback === 'function') {\n callback()\n }\n }\n\n _loadFrameCount () {\n this._setFrameCount(this.structure.frames.length)\n }\n}\n\nexport default StructureTrajectory\n","/**\n * @file Remote Trajectory\n * @author Alexander Rose \n * @private\n */\n\nimport { Log, TrajectoryDatasource } from '../globals'\nimport Structure from '../structure/structure'\nimport Trajectory, { TrajectoryParameters } from './trajectory'\n\n/**\n * Remote trajectory class. Gets data from an MDsrv instance.\n */\nclass RemoteTrajectory extends Trajectory {\n atomIndices: number[][]\n\n constructor (trajPath: string, structure: Structure, params: TrajectoryParameters) {\n super(trajPath, structure, params)\n this._init(structure)\n }\n\n get type () { return 'remote' }\n\n _makeAtomIndices () {\n const atomIndices = []\n\n if (this.structure.type === 'StructureView') {\n const indices = this.structure.getAtomIndices()! // TODO\n const n = indices.length\n\n let p = indices[ 0 ]\n let q = indices[ 0 ]\n\n for (let i = 1; i < n; ++i) {\n const r = indices[ i ]\n\n if (q + 1 < r) {\n atomIndices.push([ p, q + 1 ])\n p = r\n }\n\n q = r\n }\n\n atomIndices.push([ p, q + 1 ])\n } else {\n atomIndices.push([ 0, this.atomCount ])\n }\n\n this.atomIndices = atomIndices\n }\n\n _loadFrame (i: number, callback?: Function) {\n // TODO implement max frameCache size, re-use arrays\n\n const request = new XMLHttpRequest()\n\n const url = TrajectoryDatasource.getFrameUrl(this.trajPath, i)\n const params = TrajectoryDatasource.getFrameParams(this.trajPath, this.atomIndices)\n\n request.open('POST', url, true)\n request.responseType = 'arraybuffer'\n request.setRequestHeader(\n 'Content-type', 'application/x-www-form-urlencoded'\n )\n\n request.addEventListener('load', () => {\n const arrayBuffer = request.response\n if (!arrayBuffer) {\n Log.error(`empty arrayBuffer for '${url}'`)\n return\n }\n\n const frameCount = new Int32Array(arrayBuffer, 0, 1)[ 0 ]\n // const time = new Float32Array( arrayBuffer, 1 * 4, 1 )[ 0 ];\n const box = new Float32Array(arrayBuffer, 2 * 4, 9)\n const coords = new Float32Array(arrayBuffer, 11 * 4)\n\n this._process(i, box, coords, frameCount)\n if (typeof callback === 'function') {\n callback()\n }\n }, false)\n\n request.send(params)\n }\n\n _loadFrameCount () {\n const request = new XMLHttpRequest()\n\n const url = TrajectoryDatasource.getCountUrl(this.trajPath)\n\n request.open('GET', url, true)\n request.addEventListener('load', () => {\n this._setFrameCount(parseInt(request.response))\n }, false)\n request.send()\n }\n}\n\nexport default RemoteTrajectory\n","/**\n * @file Callback Trajectory\n * @author Tarn W. Burton \n * @private\n */\n\nimport Structure from '../structure/structure'\nimport Trajectory, { TrajectoryParameters } from './trajectory'\n\ntype RequestCallback = (responseCallback: Function, i?: number, atomIndices?: number[][]) => void\n\n/**\n * Callback trajectory class. Gets data from an JavaScript function.\n */\nclass CallbackTrajectory extends Trajectory {\n atomIndices: number[][]\n requestCallback: RequestCallback\n\n constructor (requestCallback: RequestCallback, structure: Structure, params: TrajectoryParameters) {\n super('', structure, params)\n this.requestCallback = requestCallback;\n this._init(structure)\n }\n\n get type () { return 'callback' }\n\n _makeAtomIndices () {\n const atomIndices = []\n\n if (this.structure.type === 'StructureView') {\n const indices = this.structure.getAtomIndices()! // TODO\n const n = indices.length\n\n let p = indices[ 0 ]\n let q = indices[ 0 ]\n\n for (let i = 1; i < n; ++i) {\n const r = indices[ i ]\n\n if (q + 1 < r) {\n atomIndices.push([ p, q + 1 ])\n p = r\n }\n\n q = r\n }\n\n atomIndices.push([ p, q + 1 ])\n } else {\n atomIndices.push([ 0, this.atomCount ])\n }\n\n this.atomIndices = atomIndices\n }\n\n _loadFrame (i: number, callback?: Function) {\n this.requestCallback(\n (i: number, box: ArrayLike, coords: Float32Array, frameCount: number) => {\n this._process(i, box, coords, frameCount)\n if (typeof callback === 'function') {\n callback()\n }\n }, i, this.atomIndices)\n }\n\n _loadFrameCount () {\n this.requestCallback((count: number) => this._setFrameCount(count))\n }\n}\n\nexport default CallbackTrajectory\n\n","/**\n * @file Structure View\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Box3 } from 'three'\n\nimport { Debug, Log } from '../globals'\nimport Structure from './structure'\nimport Selection from '../selection/selection'\nimport BitArray from '../utils/bitarray'\n\nimport BondProxy from '../proxy/bond-proxy'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ResidueProxy from '../proxy/residue-proxy'\nimport ChainProxy from '../proxy/chain-proxy'\nimport ModelProxy from '../proxy/model-proxy'\nimport SpatialHash from '../geometry/spatial-hash';\nimport BondHash from '../store/bond-hash';\nimport ResidueMap from '../store/residue-map';\nimport AtomMap from '../store/atom-map';\nimport ModelStore from '../store/model-store';\nimport ChainStore from '../store/chain-store';\nimport ResidueStore from '../store/residue-store';\nimport AtomStore from '../store/atom-store';\nimport BondStore from '../store/bond-store';\nimport Validation from './validation';\nimport Unitcell from '../symmetry/unitcell';\nimport Entity from './entity';\nimport Assembly from '../symmetry/assembly';\nimport { Data } from './data';\n\n/**\n * Get view on structure restricted to the selection\n * @param {Selection} selection - the selection\n * @return {StructureView} the view on the structure\n */\nStructure.prototype.getView = function (this: Structure, selection: Selection) {\n // added here to avoid cyclic import dependency\n return new StructureView(this, selection)\n}\n\n/**\n * View on the structure, restricted to the selection\n */\nclass StructureView extends Structure {\n structure: Structure\n selection: Selection\n\n /**\n * @param {Structure} structure - the structure\n * @param {Selection} selection - the selection\n */\n constructor (structure: Structure, selection: Selection) {\n super()\n\n this.structure = structure\n this.selection = selection\n\n this.center = new Vector3()\n this.boundingBox = new Box3()\n\n this._bp = this.getBondProxy()\n this._ap = this.getAtomProxy()\n this._rp = this.getResidueProxy()\n this._cp = this.getChainProxy()\n\n if (this.selection) {\n this.selection.signals.stringChanged.add(this.refresh, this)\n }\n\n this.structure.signals.refreshed.add(this.refresh, this)\n\n this.refresh()\n }\n\n init () {}\n\n get type () { return 'StructureView' }\n\n get name () { return this.structure.name }\n get path () { return this.structure.path }\n get title () { return this.structure.title }\n get id () { return this.structure.id }\n get data (): Data { return this.structure.data }\n get atomSetDict () { return this.structure.atomSetDict }\n get biomolDict (): {[k: string]: Assembly} { return this.structure.biomolDict }\n get entityList (): Entity[] { return this.structure.entityList }\n get unitcell (): Unitcell|undefined { return this.structure.unitcell }\n get frames () { return this.structure.frames }\n get boxes () { return this.structure.boxes }\n get validation (): Validation|undefined { return this.structure.validation }\n get bondStore () { return this.structure.bondStore }\n get backboneBondStore () { return this.structure.backboneBondStore }\n get rungBondStore (): BondStore { return this.structure.rungBondStore }\n get atomStore (): AtomStore { return this.structure.atomStore }\n get residueStore (): ResidueStore { return this.structure.residueStore }\n get chainStore (): ChainStore { return this.structure.chainStore }\n get modelStore (): ModelStore { return this.structure.modelStore }\n get atomMap (): AtomMap { return this.structure.atomMap }\n get residueMap (): ResidueMap { return this.structure.residueMap }\n get bondHash (): BondHash|undefined { return this.structure.bondHash }\n get spatialHash (): SpatialHash|undefined { return this.structure.spatialHash }\n\n get _hasCoords () { return this.structure._hasCoords }\n set _hasCoords (value) { this.structure._hasCoords = value }\n\n /**\n * Updates atomSet, bondSet, atomSetCache, atomCount, bondCount, boundingBox, center.\n * @emits {Structure.signals.refreshed} when refreshed\n * @return {undefined}\n */\n refresh () {\n if (Debug) Log.time('StructureView.refresh')\n\n this.atomSetCache = {}\n const structure = this.structure\n\n if (this.selection.isAllSelection() &&\n structure !== this && structure.atomSet && structure.bondSet\n ) {\n this.atomSet = structure.atomSet.clone()\n this.bondSet = structure.bondSet.clone()\n\n for (let name in this.atomSetDict) {\n const atomSet = this.atomSetDict[ name ]\n this.atomSetCache[ '__' + name ] = atomSet.clone()\n }\n\n this.atomCount = structure.atomCount\n this.bondCount = structure.bondCount\n\n this.boundingBox.copy(structure.boundingBox)\n this.center.copy(structure.center)\n } else if (this.selection.isNoneSelection() &&\n structure !== this && structure.atomSet && structure.bondSet\n ) {\n this.atomSet = new BitArray(structure.atomCount)\n this.bondSet = new BitArray(structure.bondCount)\n\n for (let name in this.atomSetDict) {\n this.atomSetCache[ '__' + name ] = new BitArray(structure.atomCount)\n }\n\n this.atomCount = 0\n this.bondCount = 0\n\n this.boundingBox.makeEmpty()\n this.center.set(0, 0, 0)\n } else {\n this.atomSet = this.getAtomSet(this.selection, true)\n if (structure.atomSet) {\n this.atomSet = this.atomSet.intersection(structure.atomSet)\n }\n\n this.bondSet = this.getBondSet()\n\n for (let name in this.atomSetDict) {\n const atomSet = this.atomSetDict[ name ]\n this.atomSetCache[ '__' + name ] = atomSet.makeIntersection(this.atomSet)\n }\n\n this.atomCount = this.atomSet.getSize()\n this.bondCount = this.bondSet.getSize()\n\n this.boundingBox = this.getBoundingBox()\n this.center = this.boundingBox.getCenter(new Vector3())\n }\n\n if (Debug) Log.timeEnd('StructureView.refresh')\n\n this.signals.refreshed.dispatch()\n }\n\n //\n\n setSelection (selection: Selection) {\n this.selection = selection\n\n this.refresh()\n }\n\n getSelection (selection?: Selection) {\n const seleList: string[] = []\n\n if (selection && selection.string) {\n seleList.push(selection.string)\n }\n\n const parentSelection = this.structure.getSelection()\n if (parentSelection && parentSelection.string) {\n seleList.push(parentSelection.string)\n }\n\n if (this.selection && this.selection.string) {\n seleList.push(this.selection.string)\n }\n\n let sele = ''\n if (seleList.length > 0) {\n sele = `( ${seleList.join(' ) AND ( ')} )`\n }\n\n return new Selection(sele)\n }\n\n getStructure () {\n return this.structure.getStructure()\n }\n\n //\n\n eachBond (callback: (entity: BondProxy) => any, selection?: Selection) {\n this.structure.eachBond(callback, this.getSelection(selection))\n }\n\n eachAtom (callback: (entity: AtomProxy) => any, selection?: Selection) {\n const ap = this.getAtomProxy()\n const atomSet = this.getAtomSet(selection)\n const n = this.atomStore.count\n\n if (atomSet.getSize() < n) {\n atomSet.forEach(function (index) {\n ap.index = index\n callback(ap)\n })\n } else {\n for (let i = 0; i < n; ++i) {\n ap.index = i\n callback(ap)\n }\n }\n }\n\n eachResidue (callback: (entity: ResidueProxy) => any, selection?: Selection) {\n this.structure.eachResidue(callback, this.getSelection(selection))\n }\n\n /**\n * Not implemented\n * @alias StructureView#eachResidueN\n * @return {undefined}\n */\n eachResidueN (n: number, callback: (entity: ResidueProxy) => any) {\n console.error('StructureView.eachResidueN() not implemented')\n }\n\n eachChain (callback: (entity: ChainProxy) => any, selection?: Selection) {\n this.structure.eachChain(callback, this.getSelection(selection))\n }\n\n eachModel (callback: (entity: ModelProxy) => any, selection?: Selection) {\n this.structure.eachModel(callback, this.getSelection(selection))\n }\n\n //\n\n getAtomSet (selection?: boolean|Selection|BitArray, ignoreView = false) {\n let atomSet = this.structure.getAtomSet(selection)\n if (!ignoreView && this.atomSet) {\n atomSet = atomSet.makeIntersection(this.atomSet)\n }\n\n return atomSet\n }\n\n //\n\n getAtomIndices (selection?: Selection) {\n return this.structure.getAtomIndices(this.getSelection(selection))\n }\n\n refreshPosition () {\n return this.structure.refreshPosition()\n }\n\n //\n\n dispose () {\n if (this.selection) {\n this.selection.signals.stringChanged.remove(this.refresh, this)\n }\n\n this.structure.signals.refreshed.remove(this.refresh, this)\n\n this.structure = new Structure() // delete old data\n\n delete this.atomSet\n delete this.bondSet\n\n }\n}\n\nexport default StructureView\n","/**\n * @file Alignment\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log } from '../globals'\n\n// const nucleotides = 'ACTG';\nconst aminoacidsX = 'ACDEFGHIKLMNPQRSTVWY'\nconst aminoacids = 'ARNDCQEGHILKMFPSTWYVBZ?'\n\nconst blosum62x = [\n [4, 0, -2, -1, -2, 0, -2, -1, -1, -1, -1, -2, -1, -1, -1, 1, 0, 0, -3, -2], // A\n [0, 9, -3, -4, -2, -3, -3, -1, -3, -1, -1, -3, -3, -3, -3, -1, -1, -1, -2, -2], // C\n [-2, -3, 6, 2, -3, -1, -1, -3, -1, -4, -3, 1, -1, 0, -2, 0, -1, -3, -4, -3], // D\n [-1, -4, 2, 5, -3, -2, 0, -3, 1, -3, -2, 0, -1, 2, 0, 0, -1, -2, -3, -2], // E\n [-2, -2, -3, -3, 6, -3, -1, 0, -3, 0, 0, -3, -4, -3, -3, -2, -2, -1, 1, 3], // F\n [0, -3, -1, -2, -3, 6, -2, -4, -2, -4, -3, 0, -2, -2, -2, 0, -2, -3, -2, -3], // G\n [-2, -3, -1, 0, -1, -2, 8, -3, -1, -3, -2, 1, -2, 0, 0, -1, -2, -3, -2, 2], // H\n [-1, -1, -3, -3, 0, -4, -3, 4, -3, 2, 1, -3, -3, -3, -3, -2, -1, 3, -3, -1], // I\n [-1, -3, -1, 1, -3, -2, -1, -3, 5, -2, -1, 0, -1, 1, 2, 0, -1, -2, -3, -2], // K\n [-1, -1, -4, -3, 0, -4, -3, 2, -2, 4, 2, -3, -3, -2, -2, -2, -1, 1, -2, -1], // L\n [-1, -1, -3, -2, 0, -3, -2, 1, -1, 2, 5, -2, -2, 0, -1, -1, -1, 1, -1, -1], // M\n [-2, -3, 1, 0, -3, 0, 1, -3, 0, -3, -2, 6, -2, 0, 0, 1, 0, -3, -4, -2], // N\n [-1, -3, -1, -1, -4, -2, -2, -3, -1, -3, -2, -2, 7, -1, -2, -1, -1, -2, -4, -3], // P\n [-1, -3, 0, 2, -3, -2, 0, -3, 1, -2, 0, 0, -1, 5, 1, 0, -1, -2, -2, -1], // Q\n [-1, -3, -2, 0, -3, -2, 0, -3, 2, -2, -1, 0, -2, 1, 5, -1, -1, -3, -3, -2], // R\n [1, -1, 0, 0, -2, 0, -1, -2, 0, -2, -1, 1, -1, 0, -1, 4, 1, -2, -3, -2], // S\n [0, -1, -1, -1, -2, -2, -2, -1, -1, -1, -1, 0, -1, -1, -1, 1, 5, 0, -2, -2], // T\n [0, -1, -3, -2, -1, -3, -3, 3, -2, 1, 1, -3, -2, -2, -3, -2, 0, 4, -3, -1], // V\n [-3, -2, -4, -3, 1, -2, -2, -3, -3, -2, -1, -4, -4, -2, -3, -3, -2, -3, 11, 2], // W\n [-2, -2, -3, -2, 3, -3, 2, -1, -2, -1, -1, -2, -3, -1, -2, -2, -2, -1, 2, 7] // Y\n]\n\nconst blosum62 = [\n // A R N D C Q E G H I L K M F P S T W Y V B Z X\n [4, -1, -2, -2, 0, -1, -1, 0, -2, -1, -1, -1, -1, -2, -1, 1, 0, -3, -2, 0, -2, -1, 0], // A\n [-1, 5, 0, -2, -3, 1, 0, -2, 0, -3, -2, 2, -1, -3, -2, -1, -1, -3, -2, -3, -1, 0, -1], // R\n [-2, 0, 6, 1, -3, 0, 0, 0, 1, -3, -3, 0, -2, -3, -2, 1, 0, -4, -2, -3, 3, 0, -1], // N\n [-2, -2, 1, 6, -3, 0, 2, -1, -1, -3, -4, -1, -3, -3, -1, 0, -1, -4, -3, -3, 4, 1, -1], // D\n [0, -3, -3, -3, 9, -3, -4, -3, -3, -1, -1, -3, -1, -2, -3, -1, -1, -2, -2, -1, -3, -3, -2], // C\n [-1, 1, 0, 0, -3, 5, 2, -2, 0, -3, -2, 1, 0, -3, -1, 0, -1, -2, -1, -2, 0, 3, -1], // Q\n [-1, 0, 0, 2, -4, 2, 5, -2, 0, -3, -3, 1, -2, -3, -1, 0, -1, -3, -2, -2, 1, 4, -1], // E\n [0, -2, 0, -1, -3, -2, -2, 6, -2, -4, -4, -2, -3, -3, -2, 0, -2, -2, -3, -3, -1, -2, -1], // G\n [-2, 0, 1, -1, -3, 0, 0, -2, 8, -3, -3, -1, -2, -1, -2, -1, -2, -2, 2, -3, 0, 0, -1], // H\n [-1, -3, -3, -3, -1, -3, -3, -4, -3, 4, 2, -3, 1, 0, -3, -2, -1, -3, -1, 3, -3, -3, -1], // I\n [-1, -2, -3, -4, -1, -2, -3, -4, -3, 2, 4, -2, 2, 0, -3, -2, -1, -2, -1, 1, -4, -3, -1], // L\n [-1, 2, 0, -1, -3, 1, 1, -2, -1, -3, -2, 5, -1, -3, -1, 0, -1, -3, -2, -2, 0, 1, -1], // K\n [-1, -1, -2, -3, -1, 0, -2, -3, -2, 1, 2, -1, 5, 0, -2, -1, -1, -1, -1, 1, -3, -1, -1], // M\n [-2, -3, -3, -3, -2, -3, -3, -3, -1, 0, 0, -3, 0, 6, -4, -2, -2, 1, 3, -1, -3, -3, -1], // F\n [-1, -2, -2, -1, -3, -1, -1, -2, -2, -3, -3, -1, -2, -4, 7, -1, -1, -4, -3, -2, -2, -1, -2], // P\n [1, -1, 1, 0, -1, 0, 0, 0, -1, -2, -2, 0, -1, -2, -1, 4, 1, -3, -2, -2, 0, 0, 0], // S\n [0, -1, 0, -1, -1, -1, -1, -2, -2, -1, -1, -1, -1, -2, -1, 1, 5, -2, -2, 0, -1, -1, 0], // T\n [-3, -3, -4, -4, -2, -2, -3, -2, -2, -3, -2, -3, -1, 1, -4, -3, -2, 11, 2, -3, -4, -3, -2], // W\n [-2, -2, -2, -3, -2, -1, -2, -3, 2, -1, -1, -2, -1, 3, -3, -2, -2, 2, 7, -1, -3, -2, -1], // Y\n [0, -3, -3, -3, -1, -2, -2, -3, -3, 3, 1, -2, 1, -1, -2, -2, 0, -3, -1, 4, -3, -2, -1], // V\n [-2, -1, 3, 4, -3, 0, 1, -1, 0, -3, -4, 0, -3, -3, -2, 0, -1, -4, -3, -3, 4, 1, -1], // B\n [-1, 0, 0, 1, -3, 3, 4, -2, 0, -3, -3, 1, -1, -3, -1, 0, -1, -3, -2, -2, 1, 4, -1], // Z\n [0, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, 0, 0, -2, -1, -1, -1, -1, -1] // X\n]\n\nfunction prepareMatrix (cellNames: string, mat: number[][]) {\n let j: number\n let i = 0\n const matDict: { [k: string]: { [k: string]: number } } = {}\n mat.forEach(function (row) {\n j = 0\n const rowDict: { [k: string]: number } = {}\n row.forEach(function (elm) {\n rowDict[ cellNames[ j++ ] ] = elm\n })\n matDict[ cellNames[ i++ ] ] = rowDict\n })\n return matDict\n}\n\nconst SubstitutionMatrices = (function () {\n return {\n blosum62: prepareMatrix(aminoacids, blosum62),\n blosum62x: prepareMatrix(aminoacidsX, blosum62x)\n }\n}())\nexport type SubstitutionMatrix = ''|'blosum62'|'blosum62x'\n\nclass Alignment {\n substMatrix: { [k: string]: { [k: string]: number } }\n\n n: number\n m: number\n score?: number\n ali: string\n\n S: number[][]\n V: number[][]\n H: number[][]\n\n ali1: string\n ali2: string\n\n constructor (readonly seq1: string, readonly seq2: string, readonly gapPenalty = -10, readonly gapExtensionPenalty = -1, substMatrix: SubstitutionMatrix = 'blosum62') {\n // TODO try encoding seqs as integers and use array subst matrix, maybe faster\n\n if (substMatrix) {\n this.substMatrix = SubstitutionMatrices[ substMatrix ]\n }\n }\n\n initMatrices () {\n this.n = this.seq1.length\n this.m = this.seq2.length\n\n // Log.log(this.n, this.m);\n\n this.score = undefined\n this.ali = ''\n\n this.S = []\n this.V = []\n this.H = []\n\n for (let i = 0; i <= this.n; ++i) {\n this.S[ i ] = []\n this.V[ i ] = []\n this.H[ i ] = []\n\n for (let j = 0; j <= this.m; ++j) {\n this.S[ i ][ j ] = 0\n this.V[ i ][ j ] = 0\n this.H[ i ][ j ] = 0\n }\n }\n\n for (let i = 0; i <= this.n; ++i) {\n this.S[ i ][ 0 ] = this.gap(0)\n this.H[ i ][ 0 ] = -Infinity\n }\n\n for (let j = 0; j <= this.m; ++j) {\n this.S[ 0 ][ j ] = this.gap(0)\n this.V[ 0 ][ j ] = -Infinity\n }\n\n this.S[ 0 ][ 0 ] = 0\n\n // Log.log(this.S, this.V, this.H);\n }\n\n gap (len: number) {\n return this.gapPenalty + len * this.gapExtensionPenalty\n }\n\n makeScoreFn () {\n const seq1 = this.seq1\n const seq2 = this.seq2\n\n const substMatrix = this.substMatrix\n\n if (substMatrix) {\n return function score (i: number, j: number) {\n const c1 = seq1[ i ]\n const c2 = seq2[ j ]\n\n try {\n return substMatrix[ c1 ][ c2 ]\n } catch (e) {\n return -4\n }\n }\n } else {\n Log.warn('Alignment: no subst matrix')\n\n return function scoreNoSubstMat (i: number, j: number) {\n const c1 = seq1[ i ]\n const c2 = seq2[ j ]\n\n return c1 === c2 ? 5 : -3\n }\n }\n }\n\n calc () {\n if (Debug) Log.time('Alignment.calc')\n\n this.initMatrices()\n\n const gap0 = this.gap(0)\n const scoreFn = this.makeScoreFn()\n const gapExtensionPenalty = this.gapExtensionPenalty\n\n const V = this.V\n const H = this.H\n const S = this.S\n\n const n = this.n\n const m = this.m\n\n let Vi1, Si1, Vi, Hi, Si\n\n for (let i = 1; i <= n; ++i) {\n Si1 = S[ i - 1 ]\n Vi1 = V[ i - 1 ]\n\n Vi = V[ i ]\n Hi = H[ i ]\n Si = S[ i ]\n\n for (let j = 1; j <= m; ++j) {\n Vi[j] = Math.max(\n Si1[ j ] + gap0,\n Vi1[ j ] + gapExtensionPenalty\n )\n\n Hi[j] = Math.max(\n Si[ j - 1 ] + gap0,\n Hi[ j - 1 ] + gapExtensionPenalty\n )\n\n Si[j] = Math.max(\n Si1[ j - 1 ] + scoreFn(i - 1, j - 1), // match\n Vi[ j ], // del\n Hi[ j ] // ins\n )\n }\n }\n\n if (Debug) Log.timeEnd('Alignment.calc')\n\n if (Debug) Log.log(this.S, this.V, this.H)\n }\n\n trace () {\n if (Debug) Log.time('Alignment.trace')\n\n this.ali1 = ''\n this.ali2 = ''\n\n const scoreFn = this.makeScoreFn()\n\n let i = this.n\n let j = this.m\n let mat\n\n if (this.S[i][j] >= this.V[i][j]) {\n mat = 'S'\n this.score = this.S[i][j]\n } else if (this.V[i][j] >= this.H[i][j]) {\n mat = 'V'\n this.score = this.V[i][j]\n } else {\n mat = 'H'\n this.score = this.H[i][j]\n }\n\n if (Debug) Log.log('Alignment: SCORE', this.score)\n if (Debug) Log.log('Alignment: S, V, H', this.S[i][j], this.V[i][j], this.H[i][j])\n\n while (i > 0 && j > 0) {\n if (mat === 'S') {\n if (this.S[i][j] === this.S[i - 1][j - 1] + scoreFn(i - 1, j - 1)) {\n this.ali1 = this.seq1[i - 1] + this.ali1\n this.ali2 = this.seq2[j - 1] + this.ali2\n --i\n --j\n mat = 'S'\n } else if (this.S[i][j] === this.V[i][j]) {\n mat = 'V'\n } else if (this.S[i][j] === this.H[i][j]) {\n mat = 'H'\n } else {\n // Log.debug('Alignment: S');\n --i\n --j\n }\n } else if (mat === 'V') {\n if (this.V[i][j] === this.V[i - 1][j] + this.gapExtensionPenalty) {\n this.ali1 = this.seq1[i - 1] + this.ali1\n this.ali2 = '-' + this.ali2\n --i\n mat = 'V'\n } else if (this.V[i][j] === this.S[i - 1][j] + this.gap(0)) {\n this.ali1 = this.seq1[i - 1] + this.ali1\n this.ali2 = '-' + this.ali2\n --i\n mat = 'S'\n } else {\n // Log.debug('Alignment: V');\n --i\n }\n } else if (mat === 'H') {\n if (this.H[i][j] === this.H[i][j - 1] + this.gapExtensionPenalty) {\n this.ali1 = '-' + this.ali1\n this.ali2 = this.seq2[j - 1] + this.ali2\n --j\n mat = 'H'\n } else if (this.H[i][j] === this.S[i][j - 1] + this.gap(0)) {\n this.ali1 = '-' + this.ali1\n this.ali2 = this.seq2[j - 1] + this.ali2\n --j\n mat = 'S'\n } else {\n // Log.debug('Alignment: H');\n --j\n }\n } else {\n Log.error('Alignment: no matrix')\n }\n }\n\n while (i > 0) {\n this.ali1 = this.seq1[ i - 1 ] + this.ali1\n this.ali2 = '-' + this.ali2\n --i\n }\n\n while (j > 0) {\n this.ali1 = '-' + this.ali1\n this.ali2 = this.seq2[ j - 1 ] + this.ali2\n --j\n }\n\n if (Debug) Log.timeEnd('Alignment.trace')\n\n if (Debug) Log.log([this.ali1, this.ali2])\n }\n}\n\nexport default Alignment\n","/**\n * @file Align Utils\n * @author Alexander Rose \n * @private\n */\n\nimport Structure from '../structure/structure'\nimport Selection from '../selection/selection'\nimport Alignment from './alignment'\nimport Superposition from './superposition'\n\n/**\n * Perform structural superposition of two structures,\n * optionally guided by a sequence alignment\n * @param {Structure|StructureView} s1 - structure 1 which is superposed onto structure 2\n * @param {Structure|StructureView} s2 - structure 2 onto which structure 1 is superposed\n * @param {Boolean} [align] - guide the superposition by a sequence alignment\n * @param {String} [sele1] - selection string for structure 1\n * @param {String} [sele2] - selection string for structure 2\n * @return {undefined}\n */\nfunction superpose (s1: Structure, s2: Structure, align = false, sele1 = '', sele2 = '') {\n let i: number\n let j: number\n let n: number\n let atoms1\n let atoms2\n\n if (align) {\n let _s1 = s1\n let _s2 = s2\n\n if (sele1 && sele2) {\n _s1 = s1.getView(new Selection(sele1))\n _s2 = s2.getView(new Selection(sele2))\n }\n\n const seq1 = _s1.getSequence()\n const seq2 = _s2.getSequence()\n\n // Log.log( seq1.join(\"\") );\n // Log.log( seq2.join(\"\") );\n\n const ali = new Alignment(seq1.join(''), seq2.join(''))\n\n ali.calc()\n ali.trace()\n\n // Log.log( \"superpose alignment score\", ali.score );\n\n // Log.log( ali.ali1 );\n // Log.log( ali.ali2 );\n\n let _i, _j\n i = 0\n j = 0\n n = ali.ali1.length\n const aliIdx1: boolean[] = []\n const aliIdx2: boolean[] = []\n\n for (let l = 0; l < n; ++l) {\n const x = ali.ali1[ l ]\n const y = ali.ali2[ l ]\n\n _i = 0\n _j = 0\n\n if (x === '-') {\n aliIdx2[ j ] = false\n } else {\n aliIdx2[ j ] = true\n _i = 1\n }\n\n if (y === '-') {\n aliIdx1[ i ] = false\n } else {\n aliIdx1[ i ] = true\n _j = 1\n }\n\n i += _i\n j += _j\n }\n\n // Log.log( i, j );\n\n // Log.log( aliIdx1 );\n // Log.log( aliIdx2 );\n\n const _atoms1: number[] = []\n const _atoms2: number[] = []\n const ap1 = _s1.getAtomProxy()\n const ap2 = _s2.getAtomProxy()\n\n i = 0\n _s1.eachResidue(function (r) {\n if (r.traceAtomIndex === undefined ||\n r.traceAtomIndex !== r.getAtomIndexByName('CA')) return\n\n if (aliIdx1[ i ]) {\n ap1.index = r.getAtomIndexByName('CA')! // TODO\n _atoms1.push(ap1.x, ap1.y, ap1.z)\n }\n i += 1\n })\n\n i = 0\n _s2.eachResidue(function (r) {\n if (r.traceAtomIndex === undefined ||\n r.traceAtomIndex !== r.getAtomIndexByName('CA')) return\n\n if (aliIdx2[ i ]) {\n ap2.index = r.getAtomIndexByName('CA')! // TODO\n _atoms2.push(ap2.x, ap2.y, ap2.z)\n }\n i += 1\n })\n\n atoms1 = new Float32Array(_atoms1)\n atoms2 = new Float32Array(_atoms2)\n } else {\n const sviewCa1 = s1.getView(new Selection(`${sele1} and .CA`))\n const sviewCa2 = s2.getView(new Selection(`${sele2} and .CA`))\n\n atoms1 = sviewCa1\n atoms2 = sviewCa2\n }\n\n const superpose = new Superposition(atoms1, atoms2)\n const result = superpose.transform(s1)\n s1.refreshPosition()\n return result\n}\n\nexport {\n superpose\n}\n","/**\n * @file Sturucture Component\n * @author Alexander Rose \n * @private\n */\n\nimport { Signal } from 'signals'\n\nimport { ComponentRegistry, MeasurementDefaultParams } from '../globals'\nimport {\n defaults, /*deepEqual, */createRingBuffer, RingBuffer, createSimpleDict, SimpleDict\n} from '../utils'\nimport { smoothstep } from '../math/math-utils'\nimport Component, { ComponentSignals, ComponentDefaultParameters } from './component'\nimport RepresentationCollection from './representation-collection'\nimport TrajectoryElement from './trajectory-element'\nimport RepresentationElement from './representation-element'\nimport { makeTrajectory } from '../trajectory/trajectory-utils'\nimport { TrajectoryParameters } from '../trajectory/trajectory'\nimport Selection from '../selection/selection'\nimport Structure from '../structure/structure'\nimport StructureView from '../structure/structure-view'\nimport { superpose } from '../align/align-utils'\nimport Stage from '../stage/stage'\nimport StructureRepresentation, { StructureRepresentationParameters } from '../representation/structure-representation'\nimport AtomProxy from '../proxy/atom-proxy'\nimport { Vector3, Box3 } from 'three';\nimport { AngleRepresentationParameters } from '../representation/angle-representation';\nimport { AxesRepresentationParameters } from '../representation/axes-representation';\nimport { BallAndStickRepresentationParameters } from '../representation/ballandstick-representation';\nimport { CartoonRepresentationParameters } from '../representation/cartoon-representation';\nimport { ContactRepresentationParameters } from '../representation/contact-representation';\nimport { DihedralRepresentationParameters } from '../representation/dihedral-representation';\nimport { DihedralHistogramRepresentationParameters } from '../representation/dihedral-histogram-representation';\nimport { DistanceRepresentationParameters } from '../representation/distance-representation';\nimport { HyperballRepresentationParameters } from '../representation/hyperball-representation';\nimport { LabelRepresentationParameters } from '../representation/label-representation';\nimport { LineRepresentationParameters } from '../representation/line-representation';\nimport { PointRepresentationParameters } from '../representation/point-representation';\nimport { SurfaceRepresentationParameters } from '../representation/surface-representation';\nimport { RibbonRepresentationParameters } from '../representation/ribbon-representation';\nimport { RocketRepresentationParameters } from '../representation/rocket-representation';\nimport { TraceRepresentationParameters } from '../representation/trace-representation';\nimport { UnitcellRepresentationParameters } from '../representation/unitcell-representation';\nimport { SliceRepresentationParameters } from '../representation/slice-representation'\nimport { MolecularSurfaceRepresentationParameters } from '../representation/molecularsurface-representation'\nimport { DotRepresentationParameters } from '../representation/dot-representation'\n\nexport type StructureRepresentationType = keyof StructureRepresentationParametersMap\n\ninterface StructureRepresentationParametersMap {\n 'angle': AngleRepresentationParameters,\n 'axes' : AxesRepresentationParameters,\n 'backbone': BallAndStickRepresentationParameters,\n 'ball+stick': BallAndStickRepresentationParameters,\n 'base': BallAndStickRepresentationParameters,\n 'cartoon': CartoonRepresentationParameters,\n 'contact': ContactRepresentationParameters,\n 'dihedral': DihedralRepresentationParameters,\n 'dihedral-histogram': DihedralHistogramRepresentationParameters,\n 'distance': DistanceRepresentationParameters,\n 'dot': DotRepresentationParameters,\n 'helixorient': StructureRepresentationParameters,\n 'hyperball': HyperballRepresentationParameters,\n 'label': LabelRepresentationParameters,\n 'licorice': BallAndStickRepresentationParameters,\n 'line': LineRepresentationParameters,\n 'molecularsurface': MolecularSurfaceRepresentationParameters,\n 'point': PointRepresentationParameters,\n 'ribbon': RibbonRepresentationParameters,\n 'rocket': RocketRepresentationParameters,\n 'rope': CartoonRepresentationParameters,\n 'slice': SliceRepresentationParameters,\n 'spacefill': BallAndStickRepresentationParameters,\n 'surface': SurfaceRepresentationParameters,\n 'trace': TraceRepresentationParameters,\n 'tube': CartoonRepresentationParameters,\n 'unitcell': UnitcellRepresentationParameters,\n 'validation': StructureRepresentationParameters\n}\n\nexport const StructureComponentDefaultParameters = Object.assign({\n sele: '',\n defaultAssembly: ''\n}, ComponentDefaultParameters)\nexport type StructureComponentParameters = typeof StructureComponentDefaultParameters\n\nexport interface StructureComponentSignals extends ComponentSignals {\n trajectoryAdded: Signal // when a trajectory is added\n trajectoryRemoved: Signal // when a trajectory is removed\n defaultAssemblyChanged: Signal // on default assembly change\n}\n\n/**\n * Component wrapping a {@link Structure} object\n *\n * @example\n * // get a structure component by loading a structure file into the stage\n * stage.loadFile( \"rcsb://4opj\" ).then( function( structureComponent ){\n * structureComponent.addRepresentation( \"cartoon\" );\n * structureComponent.autoView();\n * } );\n */\nclass StructureComponent extends Component {\n readonly signals: StructureComponentSignals\n readonly parameters: StructureComponentParameters\n get defaultParameters () { return StructureComponentDefaultParameters }\n\n selection: Selection\n structureView: StructureView\n readonly trajList: TrajectoryElement[] = []\n\n pickBuffer: RingBuffer\n pickDict: SimpleDict\n lastPick?: number\n\n spacefillRepresentation: RepresentationElement\n distanceRepresentation: RepresentationElement\n angleRepresentation: RepresentationElement\n dihedralRepresentation: RepresentationElement\n\n measureRepresentations: RepresentationCollection\n\n constructor (stage: Stage, readonly structure: Structure, params: Partial = {}) {\n super(stage, structure, Object.assign({ name: structure.name }, params))\n\n this.signals = Object.assign(this.signals, {\n trajectoryAdded: new Signal(),\n trajectoryRemoved: new Signal(),\n defaultAssemblyChanged: new Signal()\n })\n\n this.initSelection(this.parameters.sele)\n\n //\n\n this.pickBuffer = createRingBuffer(4)\n this.pickDict = createSimpleDict()\n\n this.spacefillRepresentation = this.addRepresentation('spacefill', {\n sele: 'none',\n opacity: MeasurementDefaultParams.opacity,\n color: MeasurementDefaultParams.color,\n disablePicking: true,\n radiusType: 'data'\n }, true)\n\n this.distanceRepresentation = this.addRepresentation(\n 'distance', MeasurementDefaultParams, true\n )\n this.angleRepresentation = this.addRepresentation(\n 'angle', MeasurementDefaultParams, true\n )\n this.dihedralRepresentation = this.addRepresentation(\n 'dihedral', MeasurementDefaultParams, true\n )\n\n this.measureRepresentations = new RepresentationCollection([\n this.spacefillRepresentation,\n this.distanceRepresentation,\n this.angleRepresentation,\n this.dihedralRepresentation\n ])\n\n //\n\n this.setDefaultAssembly(this.parameters.defaultAssembly)\n\n this.structure.signals.refreshed.add(() => {\n this.updateRepresentations({ position: true })\n })\n }\n\n /**\n * Component type\n * @type {String}\n */\n get type () { return 'structure' }\n\n /**\n * Initialize selection\n * @private\n * @param {String} sele - selection string\n * @return {undefined}\n */\n initSelection (sele: string) {\n /**\n * Selection for {@link StructureComponent#structureView}\n * @private\n * @type {Selection}\n */\n this.selection = new Selection(sele)\n\n /**\n * View on {@link StructureComponent#structure}.\n * Change its selection via {@link StructureComponent#setSelection}.\n * @type {StructureView}\n */\n this.structureView = new StructureView(\n this.structure, this.selection\n )\n\n this.selection.signals.stringChanged.add(() => {\n this.structureView.setSelection(this.selection)\n\n this.rebuildRepresentations()\n this.rebuildTrajectories()\n })\n }\n\n /**\n * Set selection of {@link StructureComponent#structureView}\n * @param {String} string - selection string\n * @return {StructureComponent} this object\n */\n setSelection (string: string) {\n this.parameters.sele = string\n this.selection.setString(string)\n return this\n }\n\n /**\n * Set the default assembly\n * @param {String} value - assembly name\n * @return {undefined}\n */\n setDefaultAssembly (value:string) {\n // filter out non-exsisting assemblies\n if (this.structure.biomolDict[value] === undefined) value = ''\n // only set default assembly when changed\n if (this.parameters.defaultAssembly !== value) {\n const reprParams = { defaultAssembly: value }\n this.reprList.forEach(repr => repr.setParameters(reprParams))\n this.measureRepresentations.setParameters(reprParams)\n this.parameters.defaultAssembly = value\n this.signals.defaultAssemblyChanged.dispatch(value)\n }\n return this\n }\n\n /**\n * Rebuild all representations\n * @return {undefined}\n */\n rebuildRepresentations () {\n this.reprList.forEach((repr: RepresentationElement) => {\n repr.build()\n })\n this.measureRepresentations.build()\n }\n\n /**\n * Rebuild all trajectories\n * @return {undefined}\n */\n rebuildTrajectories () {\n this.trajList.forEach(trajComp => {\n trajComp.trajectory.setStructure(this.structureView)\n })\n }\n\n updateRepresentations (what: any) {\n super.updateRepresentations(what)\n this.measureRepresentations.update(what)\n }\n\n /**\n * Overrides {@link Component.updateRepresentationMatrices} \n * to also update matrix for measureRepresentations \n */\n updateRepresentationMatrices () {\n super.updateRepresentationMatrices()\n this.measureRepresentations.setParameters({ matrix: this.matrix })\n }\n\n addRepresentation (\n type: K,\n params: Partial|{defaultAssembly: string} = {},\n hidden = false\n ) {\n params.defaultAssembly = this.parameters.defaultAssembly\n\n const reprComp = this._addRepresentation(type, this.structureView, params, hidden)\n if (!hidden) {\n reprComp.signals.parametersChanged.add(() => this.measureUpdate())\n }\n return reprComp\n }\n\n /**\n * Add a new trajectory component to the structure\n */\n addTrajectory (trajPath = '', params: { [k: string]: any } = {}) {\n const traj = makeTrajectory(trajPath, this.structureView, params as TrajectoryParameters)\n\n const trajComp = new TrajectoryElement(this.stage, traj, params)\n this.trajList.push(trajComp)\n this.signals.trajectoryAdded.dispatch(trajComp)\n\n return trajComp\n }\n\n removeTrajectory (traj: TrajectoryElement) {\n const idx = this.trajList.indexOf(traj)\n if (idx !== -1) {\n this.trajList.splice(idx, 1)\n }\n\n traj.dispose()\n\n this.signals.trajectoryRemoved.dispatch(traj)\n }\n\n dispose () {\n // copy via .slice because side effects may change trajList\n this.trajList.slice().forEach(traj => traj.dispose())\n\n this.trajList.length = 0\n this.structure.dispose()\n this.measureRepresentations.dispose()\n\n super.dispose()\n }\n\n /**\n * Automatically center and zoom the component\n * @param {String|Integer} [sele] - selection string or duration if integer\n * @param {Integer} [duration] - duration of the animation, defaults to 0\n * @return {undefined}\n */\n autoView (sele?: string|number, duration?: number) {\n if (typeof sele === 'number') {\n duration = sele\n sele = ''\n }\n\n this.stage.animationControls.zoomMove(\n this.getCenter(sele),\n this.getZoom(sele),\n defaults(duration, 0)\n )\n }\n\n getBoxUntransformed (sele: string): Box3 {\n let bb\n\n if (sele) {\n bb = this.structureView.getBoundingBox(new Selection(sele))\n } else {\n bb = this.structureView.boundingBox\n }\n\n return bb\n }\n\n getCenterUntransformed (sele: string): Vector3 {\n if (sele && typeof sele === 'string') {\n return this.structure.atomCenter(new Selection(sele))\n } else {\n return this.structure.center\n }\n }\n\n superpose (component: StructureComponent, align: boolean, sele1: string, sele2: string) {\n superpose(\n this.structureView, component.structureView, align, sele1, sele2\n )\n\n this.updateRepresentations({ 'position': true })\n\n return this\n }\n\n getMaxRepresentationRadius (atomIndex: number) {\n let maxRadius = 0\n const atom = this.structure.getAtomProxy(atomIndex)\n this.eachRepresentation(reprElem => {\n if (reprElem.getVisibility()) {\n const repr: StructureRepresentation = reprElem.repr as any // TODO\n maxRadius = Math.max(repr.getAtomRadius(atom), maxRadius)\n }\n })\n return maxRadius\n }\n\n measurePick (atom: AtomProxy) {\n const pickCount = this.pickBuffer.count\n\n if (this.lastPick === atom.index && pickCount >= 1) {\n if (pickCount > 1) {\n const atomList = this.pickBuffer.data\n const atomListSorted = this.pickBuffer.data.sort()\n if (this.pickDict.has(atomListSorted)) {\n this.pickDict.del(atomListSorted)\n } else {\n this.pickDict.add(atomListSorted, atomList)\n }\n if (pickCount === 2) {\n this.distanceRepresentation.setParameters({\n atomPair: this.pickDict.values.filter(l => l.length === 2)\n })\n } else if (pickCount === 3) {\n this.angleRepresentation.setParameters({\n atomTriple: this.pickDict.values.filter(l => l.length === 3)\n })\n } else if (pickCount === 4) {\n this.dihedralRepresentation.setParameters({\n atomQuad: this.pickDict.values.filter(l => l.length === 4)\n })\n }\n }\n this.pickBuffer.clear()\n this.lastPick = undefined\n } else {\n if (!this.pickBuffer.has(atom.index)) {\n this.pickBuffer.push(atom.index)\n }\n this.lastPick = atom.index\n }\n\n this.measureUpdate()\n }\n\n measureClear () {\n this.pickBuffer.clear()\n this.lastPick = undefined\n this.spacefillRepresentation.setSelection('none')\n }\n\n measureBuild () {\n const md = this.measureData()\n this.distanceRepresentation.setParameters({ atomPair: md.distance })\n this.angleRepresentation.setParameters({ atomTriple: md.angle })\n this.dihedralRepresentation.setParameters({ atomQuad: md.dihedral })\n }\n\n measureUpdate () {\n const pickData = this.pickBuffer.data\n const radiusData: { [k: number]: number } = {}\n pickData.forEach(ai => {\n const r = Math.max(0.1, this.getMaxRepresentationRadius(ai))\n radiusData[ ai ] = r * (2.3 - smoothstep(0.1, 2, r))\n })\n this.spacefillRepresentation.setSelection(\n pickData.length ? ( '@' + pickData.join(',') ) : 'none'\n )\n if (pickData.length)\n this.spacefillRepresentation.setParameters({ radiusData })\n }\n\n measureData () {\n const pv = this.pickDict.values\n return {\n distance: pv.filter(l => l.length === 2),\n angle: pv.filter(l => l.length === 3),\n dihedral: pv.filter(l => l.length === 4)\n }\n }\n\n /**\n * Remove all measurements, optionally limit to distance, angle or dihedral\n */\n removeAllMeasurements (type?: MeasurementFlags) {\n const pd = this.pickDict\n const pv = pd.values\n const remove = function (len: number) {\n pv.filter(l => l.length === len).forEach(l => pd.del(l.slice().sort()))\n }\n if (!type || type & MeasurementFlags.Distance) remove(2)\n if (!type || type & MeasurementFlags.Angle) remove(3)\n if (!type || type & MeasurementFlags.Dihedral) remove(4)\n this.measureBuild()\n }\n\n /**\n * Remove a measurement given as a pair, triple, quad of atom indices\n */\n removeMeasurement (atomList: number[]) {\n this.pickDict.del(atomList.slice().sort())\n this.measureBuild()\n }\n\n /**\n * Add a measurement given as a pair, triple, quad of atom indices\n */\n addMeasurement (atomList: number[]) {\n if (atomList.length < 2 || atomList.length > 4) return\n const atomListSorted = atomList.slice().sort()\n if (!this.pickDict.has(atomListSorted)) {\n this.pickDict.add(atomListSorted, atomList)\n }\n this.measureBuild()\n }\n}\n\nexport const enum MeasurementFlags {\n Distance = 0x1,\n Angle = 0x2,\n Dihedral = 0x4\n}\n\nComponentRegistry.add('structure', StructureComponent)\nComponentRegistry.add('structureview', StructureComponent)\n\nexport default StructureComponent\n","/**\n * @file Trajectory Utils\n * @author Alexander Rose \n * @private\n */\n\nimport Structure from '../structure/structure'\nimport Frames from './frames'\nimport { TrajectoryParameters } from './trajectory'\nimport FramesTrajectory from './frames-trajectory'\nimport StructureTrajectory from './structure-trajectory'\nimport RemoteTrajectory from './remote-trajectory'\nimport CallbackTrajectory from './callback-trajectory'\n\nexport function makeTrajectory (trajSrc: string|Frames, structure: Structure, params: TrajectoryParameters) {\n let traj\n\n if (trajSrc && trajSrc instanceof Frames) {\n traj = new FramesTrajectory(trajSrc, structure, params)\n } else if (!trajSrc && structure.frames) {\n traj = new StructureTrajectory(trajSrc, structure, params)\n } else if (trajSrc && typeof trajSrc === 'function') {\n traj = new CallbackTrajectory(trajSrc, structure, params)\n } else {\n traj = new RemoteTrajectory(trajSrc, structure, params)\n }\n\n return traj\n}\n\n","/**\n * @file Surface Component\n * @author Alexander Rose \n * @private\n */\n\nimport { ComponentRegistry } from '../globals'\nimport Component, { ComponentParameters } from './component'\nimport Stage from '../stage/stage'\nimport Surface from '../surface/surface'\nimport { Vector3, Box3 } from 'three';\nimport RepresentationElement from './representation-element';\n\nexport type SurfaceRepresentationType = 'surface'|'dot'\n\n/**\n * Component wrapping a {@link Surface} object\n *\n * @example\n * // get a surface component by loading a surface file into the stage\n * stage.loadFile( \"url/for/surface\" ).then( function( surfaceComponent ){\n * surfaceComponent.addRepresentation( \"surface\" );\n * surfaceComponent.autoView();\n * } );\n */\nclass SurfaceComponent extends Component {\n /**\n * @param {Stage} stage - stage object the component belongs to\n * @param {Surface} surface - surface object to wrap\n * @param {ComponentParameters} params - component parameters\n */\n constructor (stage: Stage, readonly surface: Surface, params: Partial = {}) {\n super(stage, surface, Object.assign({ name: surface.name }, params))\n }\n\n /**\n * Component type\n * @type {String}\n */\n get type () { return 'surface' }\n\n /**\n * Add a new surface representation to the component\n * @param {String} type - the name of the representation, one of:\n * surface, dot.\n * @param {SurfaceRepresentationParameters} params - representation parameters\n * @return {RepresentationComponent} the created representation wrapped into\n * a representation component object\n */\n addRepresentation (type: SurfaceRepresentationType, params: { [k: string]: any } = {}): RepresentationElement {\n return this._addRepresentation(type, this.surface, params)\n }\n\n getBoxUntransformed (): Box3 {\n return this.surface.boundingBox\n }\n\n getCenterUntransformed (): Vector3 {\n return this.surface.center\n }\n\n dispose () {\n this.surface.dispose()\n super.dispose()\n }\n}\n\nComponentRegistry.add('surface', SurfaceComponent)\n\nexport default SurfaceComponent\n","/**\n * @file Volume Component\n * @author Alexander Rose \n * @private\n */\n\nimport { ComponentRegistry } from '../globals'\nimport Component, { ComponentParameters } from './component'\nimport Stage from '../stage/stage'\nimport Volume from '../surface/volume'\nimport { Box3, Vector3 } from 'three';\nimport RepresentationElement from './representation-element';\n\nexport type VolumeRepresentationType = 'surface'|'slice'|'dot'\n\n/**\n * Component wrapping a {@link Volume} object\n *\n * @example\n * // get a volume component by loading a volume file into the stage\n * stage.loadFile( \"url/for/volume\" ).then(function(volumeComponent){\n * volumeComponent.addRepresentation('surface');\n * volumeComponent.autoView();\n * });\n */\nclass VolumeComponent extends Component {\n /**\n * @param {Stage} stage - stage object the component belongs to\n * @param {Volume} volume - volume object to wrap\n * @param {ComponentParameters} params - component parameters\n */\n constructor (stage: Stage, readonly volume: Volume, params: Partial = {}) {\n super(stage, volume, Object.assign({ name: volume.name }, params))\n }\n\n /**\n * Component type\n * @type {String}\n */\n get type () { return 'volume' }\n\n /**\n * Add a new volume representation to the component\n */\n addRepresentation (type: VolumeRepresentationType, params: { [k: string]: any } = {}): RepresentationElement {\n return this._addRepresentation(type, this.volume, params)\n }\n\n getBoxUntransformed (): Box3 {\n return this.volume.boundingBox\n }\n\n getCenterUntransformed (): Vector3 {\n return this.volume.center\n }\n\n dispose () {\n this.volume.dispose()\n\n super.dispose()\n }\n}\n\nComponentRegistry.add('volume', VolumeComponent)\n\nexport default VolumeComponent\n","/**\n * @file Component Collection\n * @author Alexander Rose \n * @private\n */\n\nimport Component from './component'\nimport Collection from './collection'\n\nclass ComponentCollection extends Collection {\n addRepresentation (name: string, params: any) {\n \treturn this.forEach((comp) => comp.addRepresentation(name, params))\n }\n\n autoView (duration: number) {\n return this.forEach((comp) => comp.autoView(duration))\n }\n}\n\nexport default ComponentCollection\n","/**\n * @file Stage\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3, Box3 } from 'three'\nimport { Signal } from 'signals'\n\nimport {\n Debug, Log, Mobile, ComponentRegistry, ParserRegistry\n} from '../globals'\nimport { defaults, createParams, updateParams } from '../utils'\nimport { degToRad, clamp, pclamp } from '../math/math-utils'\nimport Counter from '../utils/counter'\nimport Viewer from '../viewer/viewer'\nimport { ImageParameters } from '../viewer/viewer-utils'\nimport MouseObserver from './mouse-observer'\n\nimport TrackballControls from '../controls/trackball-controls'\nimport PickingControls from '../controls/picking-controls'\nimport ViewerControls from '../controls/viewer-controls'\nimport AnimationControls from '../controls/animation-controls'\nimport MouseControls, { MouseControlPreset } from '../controls/mouse-controls'\nimport KeyControls from '../controls/key-controls'\n\nimport PickingBehavior from './picking-behavior'\nimport MouseBehavior from './mouse-behavior'\nimport AnimationBehavior from './animation-behavior'\nimport KeyBehavior from './key-behavior'\n\nimport Component, { ComponentParameters } from '../component/component'\nimport RepresentationElement from '../component/representation-element'\nimport StructureComponent from '../component/structure-component'\nimport SurfaceComponent from '../component/surface-component'\nimport VolumeComponent from '../component/volume-component'\nimport ComponentCollection from '../component/component-collection'\nimport RepresentationCollection from '../component/representation-collection'\nimport { autoLoad, getFileInfo, LoaderParameters } from '../loader/loader-utils'\nimport { ParserParams } from '../loader/parser-loader'\nimport AtomProxy from '../proxy/atom-proxy'\nimport Animation from '../animation/animation'\nimport Selection from '../selection/selection'\n\nimport Structure from '../structure/structure'\nimport Surface from '../surface/surface'\nimport Volume from '../surface/volume'\nimport Shape from '../geometry/shape'\nimport Script from '../script'\nimport { GenericColor } from '../types'\n\nfunction matchName (name: string|RegExp, object: { name: string }) {\n if (name instanceof RegExp) {\n return object.name.match(name) !== null\n } else {\n return object.name === name\n }\n}\n\nconst tmpZoomVector = new Vector3()\n\ndeclare global {\n interface Document {\n mozFullScreen: boolean\n mozFullScreenEnabled: boolean\n mozFullScreenElement: Element\n mozCancelFullScreen(): void\n\n msFullscreenEnabled: boolean\n msFullscreenElement: Element\n msExitFullscreen(): void\n }\n\n interface Element {\n mozRequestFullScreen(): void\n msRequestFullscreen(): void\n }\n}\n\n/**\n * Stage parameter object.\n * @typedef {Object} StageParameters - stage parameters\n * @property {Color} backgroundColor - background color\n * @property {Integer} sampleLevel - sampling level for antialiasing, between -1 and 5;\n * -1: no sampling, 0: only sampling when not moving\n * @property {Boolean} workerDefault - default value for useWorker parameter of representations\n * @property {Float} rotateSpeed - camera-controls rotation speed, between 0 and 10\n * @property {Float} zoomSpeed - camera-controls zoom speed, between 0 and 10\n * @property {Float} panSpeed - camera-controls pan speed, between 0 and 10\n * @property {Float} clipNear - position of camera near/front clipping plane\n * in percent of scene bounding box\n * @property {Float} clipFar - position of camera far/back clipping plane\n * in percent of scene bounding box\n * @property {Float} clipDist - camera clipping distance in Angstrom\n * @property {String} clipMode - how to interpret clipNear/Far and fogNear/Far values: \"scene\" for scene-relative, \"camera\" for camera-relative\n * @property {String} clipScale - \"relative\" or \"absolute\": interpret clipNear/Far and fogNear/Far as percentage of bounding box or absolute Angstroms (ignored when clipMode==camera)\n * @property {Float} fogNear - position of the start of the fog effect\n * in percent of scene bounding box\n * @property {Float} fogFar - position where the fog is in full effect\n * in percent of scene bounding box\n * @property {String} cameraType - type of camera, either 'persepective' or 'orthographic'\n * @property {Float} cameraFov - perspective camera field of view in degree, between 15 and 120\n * @property {Float} cameraEyeSep - stereo camera eye seperation\n * @property {Color} lightColor - point light color\n * @property {Float} lightIntensity - point light intensity\n * @property {Color} ambientColor - ambient light color\n * @property {Float} ambientIntensity - ambient light intensity\n * @property {Integer} hoverTimeout - timeout for hovering\n */\n\nexport interface StageSignals {\n parametersChanged: Signal\n fullscreenChanged: Signal\n componentAdded: Signal\n componentRemoved: Signal\n clicked: Signal\n hovered: Signal\n}\n\nexport type RenderQualityType = 'auto'|'low'|'medium'|'high'\n\nexport const StageDefaultParameters = {\n impostor: true,\n quality: 'medium' as RenderQualityType,\n workerDefault: true,\n sampleLevel: 0,\n backgroundColor: 'black' as GenericColor,\n rotateSpeed: 2.0,\n zoomSpeed: 1.2,\n panSpeed: 1.0,\n clipNear: 0,\n clipFar: 100,\n clipDist: 10,\n clipMode: 'scene',\n clipScale: 'relative',\n fogNear: 50,\n fogFar: 100,\n cameraFov: 40,\n cameraEyeSep: 0.3,\n cameraType: 'perspective' as 'perspective'|'orthographic'|'stereo',\n lightColor: 0xdddddd as GenericColor,\n lightIntensity: 1.2,\n ambientColor: 0xdddddd as GenericColor,\n ambientIntensity: 0.3,\n hoverTimeout: 0,\n tooltip: true,\n mousePreset: 'default' as MouseControlPreset\n}\nexport type StageParameters = typeof StageDefaultParameters\n\nexport interface StageLoadFileParams extends LoaderParameters {\n defaultRepresentation: boolean,\n assembly: string\n}\n\n/**\n * Stage class, central for creating molecular scenes with NGL.\n *\n * @example\n * var stage = new Stage( \"elementId\", { backgroundColor: \"white\" } );\n */\nclass Stage {\n signals: StageSignals = {\n parametersChanged: new Signal(),\n fullscreenChanged: new Signal(),\n componentAdded: new Signal(),\n componentRemoved: new Signal(),\n clicked: new Signal(),\n hovered: new Signal()\n }\n parameters: StageParameters\n\n /**\n * Counter that keeps track of various potentially long-running tasks,\n * including file loading and surface calculation.\n */\n tasks = new Counter()\n compList: Component[] = []\n defaultFileParams = {}\n logList: string[] = []\n\n transformComponent?: Component\n transformAtom?: AtomProxy\n\n viewer: Viewer\n tooltip: HTMLElement\n lastFullscreenElement: HTMLElement\n\n mouseObserver: MouseObserver\n viewerControls: ViewerControls\n trackballControls: TrackballControls\n pickingControls: PickingControls\n animationControls: AnimationControls\n mouseControls: MouseControls\n keyControls: KeyControls\n\n pickingBehavior: PickingBehavior\n mouseBehavior: MouseBehavior\n animationBehavior: AnimationBehavior\n keyBehavior: KeyBehavior\n\n spinAnimation: Animation\n rockAnimation: Animation\n\n constructor (idOrElement: string|HTMLElement, params: Partial = {}) {\n this.viewer = new Viewer(idOrElement)\n if (!this.viewer.renderer) return\n\n this.tooltip = document.createElement('div')\n Object.assign(this.tooltip.style, {\n display: 'none',\n position: 'fixed',\n zIndex: '1000000',\n pointerEvents: 'none',\n backgroundColor: 'rgba( 0, 0, 0, 0.6 )',\n color: 'lightgrey',\n padding: '8px',\n fontFamily: 'sans-serif'\n })\n this.viewer.container.appendChild(this.tooltip)\n\n this.mouseObserver = new MouseObserver(this.viewer.renderer.domElement)\n this.viewerControls = new ViewerControls(this)\n this.trackballControls = new TrackballControls(this)\n this.pickingControls = new PickingControls(this)\n this.animationControls = new AnimationControls(this)\n this.mouseControls = new MouseControls(this)\n this.keyControls = new KeyControls(this)\n\n this.pickingBehavior = new PickingBehavior(this)\n this.mouseBehavior = new MouseBehavior(this)\n this.animationBehavior = new AnimationBehavior(this)\n this.keyBehavior = new KeyBehavior(this)\n\n this.spinAnimation = this.animationControls.spin([ 0, 1, 0 ], 0.005)\n this.spinAnimation.pause(true)\n this.rockAnimation = this.animationControls.rock([ 0, 1, 0 ], 0.005)\n this.rockAnimation.pause(true)\n\n // must come after the viewer has been instantiated\n this.parameters = createParams(params, StageDefaultParameters)\n this.setParameters(this.parameters)\n\n this.viewer.animate()\n }\n\n /**\n * Set stage parameters\n */\n setParameters (params: Partial = {}) {\n updateParams(this.parameters, params)\n\n const p = params\n const tp = this.parameters\n\n const viewer = this.viewer\n const controls = this.trackballControls\n\n // apply parameters\n if (p.quality !== undefined) this.setQuality(tp.quality)\n if (p.impostor !== undefined) this.setImpostor(tp.impostor)\n if (p.rotateSpeed !== undefined) controls.rotateSpeed = tp.rotateSpeed\n if (p.zoomSpeed !== undefined) controls.zoomSpeed = tp.zoomSpeed\n if (p.panSpeed !== undefined) controls.panSpeed = tp.panSpeed\n if (p.mousePreset !== undefined) this.mouseControls.preset(tp.mousePreset)\n this.mouseObserver.setParameters({ hoverTimeout: tp.hoverTimeout })\n viewer.setClip(tp.clipNear, tp.clipFar, tp.clipDist, tp.clipMode, tp.clipScale)\n viewer.setFog(undefined, tp.fogNear, tp.fogFar)\n viewer.setCamera(tp.cameraType, tp.cameraFov, tp.cameraEyeSep)\n viewer.setSampling(tp.sampleLevel)\n viewer.setBackground(tp.backgroundColor)\n viewer.setLight(tp.lightColor, tp.lightIntensity, tp.ambientColor, tp.ambientIntensity)\n\n this.signals.parametersChanged.dispatch(this.getParameters())\n\n return this\n }\n\n log (msg: string) {\n console.log('STAGE LOG', msg)\n this.logList.push(msg)\n }\n\n /**\n * Get stage parameters\n */\n getParameters () {\n return Object.assign({}, this.parameters)\n }\n\n /**\n * Create default representations for the given component\n * @param {StructureComponent|SurfaceComponent} object - component to create the representations for\n * @return {undefined}\n */\n defaultFileRepresentation (component: Component) {\n if (component instanceof StructureComponent) {\n component.setSelection('/0')\n\n let atomCount, residueCount, instanceCount\n const structure = component.structure\n\n if (structure.biomolDict.BU1) {\n const assembly = structure.biomolDict.BU1\n atomCount = assembly.getAtomCount(structure)\n residueCount = assembly.getResidueCount(structure)\n instanceCount = assembly.getInstanceCount()\n component.setDefaultAssembly('BU1')\n } else {\n atomCount = structure.getModelProxy(0).atomCount\n residueCount = structure.getModelProxy(0).residueCount\n instanceCount = 1\n }\n\n let sizeScore = atomCount\n\n if (Mobile) {\n sizeScore *= 4\n }\n\n const backboneOnly = structure.atomStore.count / structure.residueStore.count < 2\n if (backboneOnly) {\n sizeScore *= 10\n }\n\n let colorScheme = 'chainname'\n let colorScale = 'RdYlBu'\n let colorReverse = false\n if (structure.getChainnameCount(new Selection('polymer and /0')) === 1) {\n colorScheme = 'residueindex'\n colorScale = 'Spectral'\n colorReverse = true\n }\n\n if (Debug) console.log(sizeScore, atomCount, instanceCount, backboneOnly)\n\n if (residueCount / instanceCount < 4) {\n component.addRepresentation('ball+stick', {\n colorScheme: 'element',\n radiusScale: 2.0,\n aspectRatio: 1.5,\n bondScale: 0.3,\n bondSpacing: 0.75,\n quality: 'auto'\n })\n } else if ((instanceCount > 5 && sizeScore > 15000) || sizeScore > 700000) {\n let scaleFactor = (\n Math.min(\n 2.0,\n Math.max(\n 0.1,\n 6000 / (sizeScore / instanceCount)\n )\n )\n )\n if (backboneOnly) scaleFactor = Math.min(scaleFactor, 0.5)\n\n component.addRepresentation('surface', {\n colorScheme, colorScale, colorReverse,\n sele: 'polymer',\n surfaceType: 'av',\n probeRadius: 1.4,\n scaleFactor: scaleFactor,\n useWorker: false\n })\n } else if (sizeScore > 250000) {\n component.addRepresentation('backbone', {\n colorScheme, colorScale, colorReverse,\n lineOnly: true\n })\n } else if (sizeScore > 100000) {\n component.addRepresentation('backbone', {\n colorScheme, colorScale, colorReverse,\n quality: 'low',\n disableImpostor: true,\n radiusScale: 2.0\n })\n } else if (sizeScore > 80000) {\n component.addRepresentation('backbone', {\n colorScheme, colorScale, colorReverse,\n radiusScale: 2.0\n })\n } else {\n component.addRepresentation('cartoon', {\n colorScheme, colorScale, colorReverse,\n radiusScale: 0.7,\n aspectRatio: 5,\n quality: 'auto'\n })\n if (sizeScore < 50000) {\n component.addRepresentation('base', {\n colorScheme, colorScale, colorReverse,\n quality: 'auto'\n })\n }\n component.addRepresentation('ball+stick', {\n sele: 'ligand',\n colorScheme: 'element',\n radiusScale: 2.0,\n aspectRatio: 1.5,\n bondScale: 0.3,\n bondSpacing: 0.75,\n quality: 'auto'\n })\n }\n\n // add frames as trajectory\n if (component.structure.frames.length) {\n component.addTrajectory()\n }\n } else if (component instanceof SurfaceComponent) {\n component.addRepresentation('surface')\n } else if (component instanceof VolumeComponent) {\n component.addRepresentation('surface')\n }\n\n this.tasks.onZeroOnce(this.autoView, this)\n }\n\n /**\n * Load a file onto the stage\n *\n * @example\n * // load from URL\n * stage.loadFile( \"http://files.rcsb.org/download/5IOS.cif\" );\n *\n * @example\n * // load binary data in CCP4 format via a Blob\n * var binaryBlob = new Blob( [ ccp4Data ], { type: 'application/octet-binary'} );\n * stage.loadFile( binaryBlob, { ext: \"ccp4\" } );\n *\n * @example\n * // load string data in PDB format via a Blob\n * var stringBlob = new Blob( [ pdbData ], { type: 'text/plain'} );\n * stage.loadFile( stringBlob, { ext: \"pdb\" } );\n *\n * @example\n * // load a File object\n * stage.loadFile( file );\n *\n * @example\n * // load from URL and add a 'ball+stick' representation with double/triple bonds\n * stage.loadFile( \"http://files.rcsb.org/download/1crn.cif\" ).then( function( comp ){\n * comp.addRepresentation( \"ball+stick\", { multipleBond: true } );\n * } );\n *\n * @param {String|File|Blob} path - either a URL or an object containing the file data\n * @param {LoaderParameters} params - loading parameters\n * @param {Boolean} params.asTrajectory - load multi-model structures as a trajectory\n * @return {Promise} A Promise object that resolves to a {@link StructureComponent},\n * a {@link SurfaceComponent} or a {@link ScriptComponent} object,\n * depending on the type of the loaded file.\n */\n loadFile (path: string|File|Blob, params: Partial = {}) {\n const p = Object.assign({}, this.defaultFileParams, params)\n const name = getFileInfo(path).name\n\n this.tasks.increment()\n this.log(`loading file '${name}'`)\n\n const onLoadFn = (object: Structure|Surface|Volume) => {\n this.log(`loaded '${name}'`)\n\n const component = this.addComponentFromObject(object, p)\n if (p.defaultRepresentation) {\n this.defaultFileRepresentation(component as Component)\n }\n this.tasks.decrement()\n\n return component\n }\n\n const onErrorFn = (e: Error|string) => {\n this.tasks.decrement()\n const errorMsg = `error loading file: '${e}'`\n this.log(errorMsg)\n throw errorMsg // throw so it can be catched\n }\n\n const ext = defaults(p.ext, getFileInfo(path).ext)\n let promise: Promise\n\n if (ParserRegistry.isTrajectory(ext)) {\n promise = Promise.reject(\n new Error(`loadFile: ext '${ext}' is a trajectory and must be loaded into a structure component`)\n )\n } else {\n promise = autoLoad(path, p)\n }\n\n return promise.then(onLoadFn, onErrorFn)\n }\n\n loadScript (path: string|File|Blob) {\n const name = getFileInfo(path).name\n\n this.log(`loading script '${name}'`)\n\n return autoLoad(path).then(\n (script: Script) => {\n this.tasks.increment()\n this.log(`running script '${name}'`)\n script.run(this).then(() => {\n this.tasks.decrement()\n this.log(`finished script '${name}'`)\n })\n this.log(`called script '${name}'`)\n },\n (error: Error|string) => {\n this.tasks.decrement()\n const errorMsg = `errored script '${name}' \"${error}\"`\n this.log(errorMsg)\n throw errorMsg // throw so it can be catched\n }\n )\n }\n\n /**\n * Add the given component to the stage\n * @param {Component} component - the component to add\n * @return {undefined}\n */\n addComponent (component: Component) {\n if (!component) {\n Log.warn('Stage.addComponent: no component given')\n return\n }\n\n this.compList.push(component)\n this.signals.componentAdded.dispatch(component)\n }\n\n /**\n * Create a component from the given object and add to the stage\n */\n addComponentFromObject (object: Structure|Surface|Volume|Shape, params: Partial = {}): void|Component {\n const CompClass = ComponentRegistry.get(object.type)\n\n if (CompClass) {\n const component = new CompClass(this, object, params)\n this.addComponent(component)\n return component\n }\n\n Log.warn('no component for object type', object.type)\n }\n\n /**\n * Remove the given component\n * @param {Component} component - the component to remove\n * @return {undefined}\n */\n removeComponent (component: Component) {\n const idx = this.compList.indexOf(component)\n if (idx !== -1) {\n this.compList.splice(idx, 1)\n component.dispose()\n this.signals.componentRemoved.dispatch(component)\n }\n }\n\n /**\n * Remove all components from the stage\n */\n removeAllComponents () {\n this.compList.slice().forEach(o => this.removeComponent(o))\n }\n\n /**\n * Handle any size-changes of the container element\n * @return {undefined}\n */\n handleResize () {\n this.viewer.handleResize()\n }\n\n /**\n * Set width and height\n * @param {String} width - CSS width value\n * @param {String} height - CSS height value\n * @return {undefined}\n */\n setSize (width: string, height: string) {\n const container = this.viewer.container\n\n if (container !== document.body) {\n if (width !== undefined) container.style.width = width\n if (height !== undefined) container.style.height = height\n this.handleResize()\n }\n }\n\n /**\n * Toggle fullscreen\n * @param {Element} [element] - document element to put into fullscreen,\n * defaults to the viewer container\n * @return {undefined}\n */\n toggleFullscreen (element: HTMLElement) {\n if (!document.fullscreenEnabled && !document.mozFullScreenEnabled &&\n !(document as any).webkitFullscreenEnabled && !document.msFullscreenEnabled\n ) {\n Log.log('fullscreen mode (currently) not possible')\n return\n }\n\n const self = this\n element = element || this.viewer.container\n this.lastFullscreenElement = element\n\n //\n\n function getFullscreenElement () {\n return document.fullscreenElement || document.mozFullScreenElement ||\n (document as any).webkitFullscreenElement || document.msFullscreenElement\n }\n\n function resizeElement () {\n if (!getFullscreenElement() && self.lastFullscreenElement) {\n const element = self.lastFullscreenElement\n element.style.width = element.dataset.normalWidth || ''\n element.style.height = element.dataset.normalHeight || ''\n\n document.removeEventListener('fullscreenchange', resizeElement)\n document.removeEventListener('mozfullscreenchange', resizeElement)\n document.removeEventListener('webkitfullscreenchange', resizeElement)\n document.removeEventListener('MSFullscreenChange', resizeElement)\n\n self.handleResize()\n self.signals.fullscreenChanged.dispatch(false)\n }\n }\n\n //\n\n if (!getFullscreenElement()) {\n element.dataset.normalWidth = element.style.width || ''\n element.dataset.normalHeight = element.style.height || ''\n element.style.width = window.screen.width + 'px'\n element.style.height = window.screen.height + 'px'\n\n if (element.requestFullscreen) {\n element.requestFullscreen()\n } else if (element.msRequestFullscreen) {\n element.msRequestFullscreen()\n } else if (element.mozRequestFullScreen) {\n element.mozRequestFullScreen()\n } else if ((element as any).webkitRequestFullscreen) {\n (element as any).webkitRequestFullscreen()\n }\n\n document.addEventListener('fullscreenchange', resizeElement)\n document.addEventListener('mozfullscreenchange', resizeElement)\n document.addEventListener('webkitfullscreenchange', resizeElement)\n document.addEventListener('MSFullscreenChange', resizeElement)\n\n this.handleResize()\n this.signals.fullscreenChanged.dispatch(true)\n\n // workaround for Safari\n setTimeout(function () { self.handleResize() }, 100)\n } else {\n if (document.exitFullscreen) {\n document.exitFullscreen()\n } else if (document.msExitFullscreen) {\n document.msExitFullscreen()\n } else if (document.mozCancelFullScreen) {\n document.mozCancelFullScreen()\n } else if ((document as any).webkitExitFullscreen) {\n (document as any).webkitExitFullscreen()\n }\n }\n }\n\n /**\n * Set spin\n * @param {Boolean} flag - if true start rocking and stop spinning\n * @return {undefined}\n */\n setSpin (flag: boolean) {\n if (flag) {\n this.spinAnimation.resume(true)\n this.rockAnimation.pause(true)\n } else {\n this.spinAnimation.pause(true)\n }\n }\n\n /**\n * Set rock\n * @param {Boolean} flag - if true start rocking and stop spinning\n * @return {undefined}\n */\n setRock (flag: boolean) {\n if (flag) {\n this.rockAnimation.resume(true)\n this.spinAnimation.pause(true)\n } else {\n this.rockAnimation.pause(true)\n }\n }\n\n /**\n * Toggle spin\n * @return {undefined}\n */\n toggleSpin () {\n this.setSpin(this.spinAnimation.paused)\n }\n\n /**\n * Toggle rock\n * @return {undefined}\n */\n toggleRock () {\n this.setRock(this.rockAnimation.paused)\n }\n\n /**\n * Get the current focus from the current clipNear value expressed\n * as 0 (full view) to 100 (completely clipped)\n * Negative values may be returned in some cases.\n *\n * In 'camera' clipMode focus isn't applicable, this method returns 0.0\n *\n * @return {number} focus\n */\n getFocus () : number {\n const p = this.parameters\n if (p.clipMode !== 'scene') return 0.0\n\n let clipNear = p.clipNear\n if (p.clipScale === 'absolute') {\n clipNear = this.viewer.absoluteToRelative(clipNear)\n }\n return clipNear * 2\n }\n\n\n /**\n * Set the focus, a value of 0 sets clipping planes to show full scene,\n * while a value of 100 will compltely clip the scene.\n *\n * @param {number} value focus\n */\n setFocus (value: number) {\n if (this.parameters.clipMode !== 'scene') return\n\n let clipNear\n let clipFar\n let fogNear\n let fogFar\n\n if (this.parameters.clipScale === 'relative') {\n clipNear = clamp(value / 2.0, 0.0, 49.9)\n clipFar = 100 - clipNear\n fogNear = 50\n fogFar = pclamp(2 * clipFar - 50)\n\n } else {\n clipNear = this.viewer.relativeToAbsolute(value / 2.0)\n clipFar = clipNear\n fogNear = 0\n fogFar = 2 * clipFar\n }\n\n this.setParameters({ clipNear, clipFar, fogNear, fogFar })\n }\n\n getZoomForBox (boundingBox: Box3) {\n const bbSize = boundingBox.getSize(tmpZoomVector)\n const maxSize = Math.max(bbSize.x, bbSize.y, bbSize.z)\n const minSize = Math.min(bbSize.x, bbSize.y, bbSize.z)\n let distance = maxSize + Math.sqrt(minSize)\n\n const fov = degToRad(this.viewer.perspectiveCamera.fov)\n const width = this.viewer.width\n const height = this.viewer.height\n const aspect = width / height\n const aspectFactor = (height < width ? 1 : aspect)\n\n distance = Math.abs(\n ((distance * 0.5) / aspectFactor) / Math.sin(fov / 2)\n )\n distance += this.parameters.clipDist\n return -distance\n }\n\n getBox () {\n return this.viewer.boundingBox\n }\n\n getZoom () {\n return this.getZoomForBox(this.getBox())\n }\n\n getCenter (optionalTarget?: Vector3) {\n return this.getBox().getCenter(optionalTarget || new Vector3())\n }\n\n /**\n * Add a zoom and a move animation with automatic targets\n * @param {Integer} duration - animation time in milliseconds\n * @return {undefined}\n */\n autoView (duration?: number) {\n this.animationControls.zoomMove(\n this.getCenter(),\n this.getZoom(),\n defaults(duration, 0)\n )\n }\n\n /**\n * Make image from what is shown in a viewer canvas\n */\n makeImage (params: Partial = {}) {\n return new Promise((resolve, reject) => {\n this.tasks.onZeroOnce(() => {\n this.tasks.increment()\n this.viewer.makeImage(params).then(blob => {\n this.tasks.decrement()\n resolve(blob)\n }).catch(e => {\n this.tasks.decrement()\n reject(e)\n })\n })\n })\n }\n\n setImpostor (value: boolean) {\n this.parameters.impostor = value\n\n const types = [\n 'spacefill', 'ball+stick', 'licorice', 'hyperball',\n 'backbone', 'rocket', 'helixorient', 'contact', 'distance',\n 'dot'\n ]\n\n this.eachRepresentation(function (reprElem) {\n if (!types.includes(reprElem.getType())) return\n\n const p = reprElem.getParameters() as any // TODO\n p.disableImpostor = !value\n reprElem.build(p)\n })\n }\n\n setQuality (value: RenderQualityType) {\n this.parameters.quality = value\n\n const types = [\n 'tube', 'cartoon', 'ribbon', 'trace', 'rope'\n ]\n\n const impostorTypes = [\n 'spacefill', 'ball+stick', 'licorice', 'hyperball',\n 'backbone', 'rocket', 'helixorient', 'contact', 'distance',\n 'dot'\n ]\n\n this.eachRepresentation(function (repr) {\n const p = repr.getParameters() as any // TODO\n\n if (!types.includes(repr.getType())) {\n if (!impostorTypes.includes(repr.getType())) return\n\n if (!p.disableImpostor) {\n (repr.repr as any).quality = value // TODO\n return\n }\n }\n\n p.quality = value\n repr.build(p)\n })\n }\n\n /**\n * Iterator over each component and executing the callback\n */\n eachComponent (callback: (comp: Component) => void, type?: string) {\n this.compList.slice().forEach(comp => {\n if (type === undefined || type === comp.type) callback(comp)\n })\n }\n\n /**\n * Iterator over each representation and executing the callback\n */\n eachRepresentation (callback: (reprElem: RepresentationElement, comp: Component) => void, type?: string) {\n this.eachComponent(comp => {\n comp.reprList.slice().forEach(reprElem => {\n if (type === undefined || type === reprElem.getType()) callback(reprElem, comp)\n })\n })\n }\n\n /**\n * Get collection of components by name\n */\n getComponentsByName (name: string|RegExp) {\n const compList: Component[] = []\n\n this.eachComponent(comp => {\n if (name === undefined || matchName(name, comp)) compList.push(comp)\n })\n\n return new ComponentCollection(compList)\n }\n\n /**\n * Get collection of components by object\n */\n getComponentsByObject (object: Structure|Surface|Volume|Shape) {\n const compList: Component[] = []\n\n this.eachComponent(comp => {\n if (comp.object === object) compList.push(comp)\n })\n\n return new ComponentCollection(compList)\n }\n\n /**\n * Get collection of representations by name\n */\n getRepresentationsByName (name: string|RegExp) {\n const reprList: RepresentationElement[] = []\n\n this.eachRepresentation((repr, comp) => {\n if (name === undefined || matchName(name, repr)) reprList.push(repr)\n })\n\n return new RepresentationCollection(reprList)\n }\n\n measureClear () {\n this.eachComponent((sc: StructureComponent) => sc.measureClear(), 'structure')\n }\n\n measureUpdate () {\n this.eachComponent((sc: StructureComponent) => sc.measureUpdate(), 'structure')\n }\n\n /**\n * Cleanup when disposing of a stage object\n */\n dispose () {\n this.tasks.dispose()\n this.viewer.dispose()\n this.mouseObserver.dispose()\n }\n}\n\nexport default Stage\n","/**\n * @file Shape Component\n * @author Alexander Rose \n * @private\n */\n\nimport { ComponentRegistry } from '../globals'\nimport Component, { ComponentParameters } from './component'\nimport Stage from '../stage/stage'\nimport Shape from '../geometry/shape'\nimport { Vector3, Box3 } from 'three';\nimport RepresentationElement from './representation-element';\n\nexport type ShapeRepresentationType = 'buffer'\n\n/**\n * Component wrapping a {@link Shape} object\n *\n * @example\n * // get a shape component by adding a shape object to the stage\n * var shape = new NGL.Shape( \"shape\" );\n * shape.addSphere( [ 0, 0, 0 ], [ 1, 0, 0 ], 1.5 );\n * var shapeComponent = stage.addComponentFromObject( shape );\n * shapeComponent.addRepresentation( \"buffer\" );\n */\nclass ShapeComponent extends Component {\n constructor (stage: Stage, readonly shape: Shape, params: Partial = {}) {\n super(stage, shape, Object.assign({ name: shape.name }, params))\n }\n\n /**\n * Component type\n * @type {String}\n */\n get type () { return 'shape' }\n\n /**\n * Add a new shape representation to the component\n * @param {String} type - the name of the representation, one of:\n * buffer.\n * @param {BufferRepresentationParameters} params - representation parameters\n * @return {RepresentationComponent} the created representation wrapped into\n * a representation component object\n */\n addRepresentation (type: ShapeRepresentationType, params: { [k: string]: any } = {}): RepresentationElement {\n return this._addRepresentation(type, this.shape, params)\n }\n\n getBoxUntransformed (): Box3 {\n return this.shape.boundingBox\n }\n\n getCenterUntransformed (): Vector3 {\n return this.shape.center\n }\n\n dispose () {\n this.shape.dispose()\n super.dispose()\n }\n}\n\nComponentRegistry.add('shape', ShapeComponent)\n\nexport default ShapeComponent\n","/******************************************************************************\r\nCopyright (c) Microsoft Corporation.\r\n\r\nPermission to use, copy, modify, and/or distribute this software for any\r\npurpose with or without fee is hereby granted.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\r\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\r\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\r\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\r\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\r\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\r\nPERFORMANCE OF THIS SOFTWARE.\r\n***************************************************************************** */\r\n/* global Reflect, Promise, SuppressedError, Symbol */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n if (typeof b !== \"function\" && b !== null)\r\n throw new TypeError(\"Class extends value \" + String(b) + \" is not a constructor or null\");\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {\r\n function accept(f) { if (f !== void 0 && typeof f !== \"function\") throw new TypeError(\"Function expected\"); return f; }\r\n var kind = contextIn.kind, key = kind === \"getter\" ? \"get\" : kind === \"setter\" ? \"set\" : \"value\";\r\n var target = !descriptorIn && ctor ? contextIn[\"static\"] ? ctor : ctor.prototype : null;\r\n var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});\r\n var _, done = false;\r\n for (var i = decorators.length - 1; i >= 0; i--) {\r\n var context = {};\r\n for (var p in contextIn) context[p] = p === \"access\" ? {} : contextIn[p];\r\n for (var p in contextIn.access) context.access[p] = contextIn.access[p];\r\n context.addInitializer = function (f) { if (done) throw new TypeError(\"Cannot add initializers after decoration has completed\"); extraInitializers.push(accept(f || null)); };\r\n var result = (0, decorators[i])(kind === \"accessor\" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);\r\n if (kind === \"accessor\") {\r\n if (result === void 0) continue;\r\n if (result === null || typeof result !== \"object\") throw new TypeError(\"Object expected\");\r\n if (_ = accept(result.get)) descriptor.get = _;\r\n if (_ = accept(result.set)) descriptor.set = _;\r\n if (_ = accept(result.init)) initializers.unshift(_);\r\n }\r\n else if (_ = accept(result)) {\r\n if (kind === \"field\") initializers.unshift(_);\r\n else descriptor[key] = _;\r\n }\r\n }\r\n if (target) Object.defineProperty(target, contextIn.name, descriptor);\r\n done = true;\r\n};\r\n\r\nexport function __runInitializers(thisArg, initializers, value) {\r\n var useValue = arguments.length > 2;\r\n for (var i = 0; i < initializers.length; i++) {\r\n value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);\r\n }\r\n return useValue ? value : void 0;\r\n};\r\n\r\nexport function __propKey(x) {\r\n return typeof x === \"symbol\" ? x : \"\".concat(x);\r\n};\r\n\r\nexport function __setFunctionName(f, name, prefix) {\r\n if (typeof name === \"symbol\") name = name.description ? \"[\".concat(name.description, \"]\") : \"\";\r\n return Object.defineProperty(f, \"name\", { configurable: true, value: prefix ? \"\".concat(prefix, \" \", name) : name });\r\n};\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport var __createBinding = Object.create ? (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n var desc = Object.getOwnPropertyDescriptor(m, k);\r\n if (!desc || (\"get\" in desc ? !m.__esModule : desc.writable || desc.configurable)) {\r\n desc = { enumerable: true, get: function() { return m[k]; } };\r\n }\r\n Object.defineProperty(o, k2, desc);\r\n}) : (function(o, m, k, k2) {\r\n if (k2 === undefined) k2 = k;\r\n o[k2] = m[k];\r\n});\r\n\r\nexport function __exportStar(m, o) {\r\n for (var p in m) if (p !== \"default\" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p);\r\n}\r\n\r\nexport function __values(o) {\r\n var s = typeof Symbol === \"function\" && Symbol.iterator, m = s && o[s], i = 0;\r\n if (m) return m.call(o);\r\n if (o && typeof o.length === \"number\") return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n throw new TypeError(s ? \"Object is not iterable.\" : \"Symbol.iterator is not defined.\");\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\n/** @deprecated */\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n}\r\n\r\nexport function __spreadArray(to, from, pack) {\r\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\r\n if (ar || !(i in from)) {\r\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\r\n ar[i] = from[i];\r\n }\r\n }\r\n return to.concat(ar || Array.prototype.slice.call(from));\r\n}\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nvar __setModuleDefault = Object.create ? (function(o, v) {\r\n Object.defineProperty(o, \"default\", { enumerable: true, value: v });\r\n}) : function(o, v) {\r\n o[\"default\"] = v;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (k !== \"default\" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);\r\n __setModuleDefault(result, mod);\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n\r\nexport function __classPrivateFieldGet(receiver, state, kind, f) {\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\r\n return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\r\n}\r\n\r\nexport function __classPrivateFieldSet(receiver, state, value, kind, f) {\r\n if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\r\n if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\r\n if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\r\n return (kind === \"a\" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;\r\n}\r\n\r\nexport function __classPrivateFieldIn(state, receiver) {\r\n if (receiver === null || (typeof receiver !== \"object\" && typeof receiver !== \"function\")) throw new TypeError(\"Cannot use 'in' operator on non-object\");\r\n return typeof state === \"function\" ? receiver === state : state.has(receiver);\r\n}\r\n\r\nexport function __addDisposableResource(env, value, async) {\r\n if (value !== null && value !== void 0) {\r\n if (typeof value !== \"object\" && typeof value !== \"function\") throw new TypeError(\"Object expected.\");\r\n var dispose;\r\n if (async) {\r\n if (!Symbol.asyncDispose) throw new TypeError(\"Symbol.asyncDispose is not defined.\");\r\n dispose = value[Symbol.asyncDispose];\r\n }\r\n if (dispose === void 0) {\r\n if (!Symbol.dispose) throw new TypeError(\"Symbol.dispose is not defined.\");\r\n dispose = value[Symbol.dispose];\r\n }\r\n if (typeof dispose !== \"function\") throw new TypeError(\"Object not disposable.\");\r\n env.stack.push({ value: value, dispose: dispose, async: async });\r\n }\r\n else if (async) {\r\n env.stack.push({ async: true });\r\n }\r\n return value;\r\n}\r\n\r\nvar _SuppressedError = typeof SuppressedError === \"function\" ? SuppressedError : function (error, suppressed, message) {\r\n var e = new Error(message);\r\n return e.name = \"SuppressedError\", e.error = error, e.suppressed = suppressed, e;\r\n};\r\n\r\nexport function __disposeResources(env) {\r\n function fail(e) {\r\n env.error = env.hasError ? new _SuppressedError(e, env.error, \"An error was suppressed during disposal.\") : e;\r\n env.hasError = true;\r\n }\r\n function next() {\r\n while (env.stack.length) {\r\n var rec = env.stack.pop();\r\n try {\r\n var result = rec.dispose && rec.dispose.call(rec.value);\r\n if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); });\r\n }\r\n catch (e) {\r\n fail(e);\r\n }\r\n }\r\n if (env.hasError) throw env.error;\r\n }\r\n return next();\r\n}\r\n\r\nexport default {\r\n __extends: __extends,\r\n __assign: __assign,\r\n __rest: __rest,\r\n __decorate: __decorate,\r\n __param: __param,\r\n __metadata: __metadata,\r\n __awaiter: __awaiter,\r\n __generator: __generator,\r\n __createBinding: __createBinding,\r\n __exportStar: __exportStar,\r\n __values: __values,\r\n __read: __read,\r\n __spread: __spread,\r\n __spreadArrays: __spreadArrays,\r\n __spreadArray: __spreadArray,\r\n __await: __await,\r\n __asyncGenerator: __asyncGenerator,\r\n __asyncDelegator: __asyncDelegator,\r\n __asyncValues: __asyncValues,\r\n __makeTemplateObject: __makeTemplateObject,\r\n __importStar: __importStar,\r\n __importDefault: __importDefault,\r\n __classPrivateFieldGet: __classPrivateFieldGet,\r\n __classPrivateFieldSet: __classPrivateFieldSet,\r\n __classPrivateFieldIn: __classPrivateFieldIn,\r\n __addDisposableResource: __addDisposableResource,\r\n __disposeResources: __disposeResources,\r\n};\r\n","/**\n * @file Atomindex Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ModelProxy from '../proxy/model-proxy'\n\n/**\n * Color by atom index. The {@link AtomProxy.index} property is used for coloring.\n * Each {@link ModelProxy} of a {@link Structure} is colored seperately. The\n * `params.domain` parameter is ignored.\n *\n * __Name:__ _atomindex_\n *\n * @example\n * stage.loadFile( \"rcsb://1crn\" ).then( function( o ){\n * o.addRepresentation( \"ball+stick\", { colorScheme: \"atomindex\" } );\n * o.autoView();\n * } );\n */\nclass AtomindexColormaker extends Colormaker {\n scalePerModel: { [k: number]: ColormakerScale }\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'rainbow'\n this.parameters.reverse = defaults(params.reverse, true)\n }\n\n this.scalePerModel = {}\n\n params.structure.eachModel((mp: ModelProxy) => {\n this.parameters.domain = [ mp.atomOffset, mp.atomEnd ]\n this.scalePerModel[ mp.index ] = this.getScale() // TODO\n })\n }\n\n /**\n * get color for an atom\n * @param {AtomProxy} atom - atom to get color for\n * @return {Integer} hex atom color\n */\n @manageColor\n atomColor (atom: AtomProxy) {\n return this.scalePerModel[ atom.modelIndex ](atom.index)\n }\n}\n\nColormakerRegistry.add('atomindex', AtomindexColormaker)\n\nexport default AtomindexColormaker\n","/**\n * @file Bfactor Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport Selection from '../selection/selection'\n\n/**\n * Color by b-factor. The {@link AtomProxy.bfactor} property is used for coloring.\n * By default the min and max b-factor values are used for the scale`s domain.\n *\n * __Name:__ _bfactor_\n *\n * @example\n * stage.loadFile( \"rcsb://1crn\" ).then( function( o ){\n * o.addRepresentation( \"ball+stick\", { colorScheme: \"bfactor\" } );\n * o.autoView();\n * } );\n */\nclass BfactorColormaker extends Colormaker {\n bfactorScale: ColormakerScale\n\n constructor (params: { sele?: string } & StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'OrRd'\n }\n\n if (!params.domain) {\n let selection\n let min = Infinity\n let max = -Infinity\n\n if (params.sele) {\n selection = new Selection(params.sele)\n }\n\n params.structure.eachAtom(function (a) {\n const bfactor = a.bfactor\n min = Math.min(min, bfactor)\n max = Math.max(max, bfactor)\n }, selection)\n\n this.parameters.domain = [ min, max ]\n }\n\n this.bfactorScale = this.getScale()\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n return this.bfactorScale(a.bfactor)\n }\n}\n\nColormakerRegistry.add('bfactor', BfactorColormaker)\n\nexport default BfactorColormaker\n","/**\n * @file Chainid Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ChainProxy from '../proxy/chain-proxy'\nimport ModelProxy from '../proxy/model-proxy'\n\nexport type ChainidDict = { [k: string]: number }\n\n/**\n * Color by chain id\n */\nclass ChainidColormaker extends Colormaker {\n chainidDictPerModel: { [k: number]: ChainidDict } = {}\n scalePerModel: { [k: number]: ColormakerScale } = {}\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'Spectral'\n }\n\n params.structure.eachModel((mp: ModelProxy) => {\n let i = 0\n const chainidDict: ChainidDict = {}\n mp.eachChain(function (cp: ChainProxy) {\n if (chainidDict[ cp.chainid ] === undefined) {\n chainidDict[ cp.chainid ] = i\n i += 1\n }\n })\n this.parameters.domain = [ 0, i - 1 ]\n this.chainidDictPerModel[ mp.index ] = chainidDict\n this.scalePerModel[ mp.index ] = this.getScale()\n })\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n const chainidDict = this.chainidDictPerModel[ a.modelIndex ]\n return this.scalePerModel[ a.modelIndex ](chainidDict[ a.chainid ])\n }\n}\n\nColormakerRegistry.add('chainid', ChainidColormaker)\n\nexport default ChainidColormaker\n","/**\n * @file Chainindex Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ModelProxy from '../proxy/model-proxy'\n\n/**\n * Color by chain index\n */\nclass ChainindexColormaker extends Colormaker {\n scalePerModel: { [k: number]: ColormakerScale } = {}\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'Spectral'\n }\n\n params.structure.eachModel((mp: ModelProxy) => {\n this.parameters.domain = [ mp.chainOffset, mp.chainEnd ]\n this.scalePerModel[ mp.index ] = this.getScale()\n })\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n return this.scalePerModel[ a.modelIndex ](a.chainIndex)\n }\n}\n\nColormakerRegistry.add('chainindex', ChainindexColormaker)\n\nexport default ChainindexColormaker\n","/**\n * @file Chainname Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ChainProxy from '../proxy/chain-proxy'\nimport ModelProxy from '../proxy/model-proxy'\n\nexport type ChainnameDict = { [k: string]: number }\n\n/**\n * Color by chain name\n */\nclass ChainnameColormaker extends Colormaker {\n chainnameDictPerModel: { [k: number]: ChainnameDict } = {}\n scalePerModel: { [k: number]: ColormakerScale } = {}\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'Spectral'\n }\n\n params.structure.eachModel((mp: ModelProxy) => {\n let i = 0\n const chainnameDict: ChainnameDict = {}\n mp.eachChain(function (cp: ChainProxy) {\n if (chainnameDict[ cp.chainname ] === undefined) {\n chainnameDict[ cp.chainname ] = i\n i += 1\n }\n })\n this.parameters.domain = [ 0, i - 1 ]\n this.chainnameDictPerModel[ mp.index ] = chainnameDict\n this.scalePerModel[ mp.index ] = this.getScale()\n })\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n const chainnameDict = this.chainnameDictPerModel[ a.modelIndex ]\n return this.scalePerModel[ a.modelIndex ](chainnameDict[ a.chainname ])\n }\n}\n\nColormakerRegistry.add('chainname', ChainnameColormaker)\n\nexport default ChainnameColormaker\n","/**\n * @file Densityfit Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Color by validation density fit\n */\nclass DensityfitColormaker extends Colormaker {\n rsrzScale: ColormakerScale\n rsccScale: ColormakerScale\n\n rsrzDict: { [k: string]: number|undefined } = {}\n rsccDict: { [k: string]: number|undefined } = {}\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'RdYlBu'\n }\n\n this.rsrzScale = this.getScale({ domain: [ 2, 0 ] })\n this.rsccScale = this.getScale({ domain: [ 0.678, 1.0 ] })\n\n const val = params.structure.validation\n if (val) {\n this.rsrzDict = val.rsrzDict\n this.rsccDict = val.rsccDict\n }\n\n }\n\n @manageColor\n atomColor (atom: AtomProxy) {\n let sele = atom.resno + ''\n if (atom.inscode) sele += '^' + atom.inscode\n if (atom.chainname) sele += ':' + atom.chainname\n sele += '/' + atom.modelIndex\n\n const rsrz = this.rsrzDict[ sele ]\n if (rsrz !== undefined) {\n return this.rsrzScale(rsrz)\n }\n\n const rscc = this.rsccDict[ sele ]\n if (rscc !== undefined) {\n return this.rsccScale(rscc)\n }\n\n return 0x909090\n }\n}\n\nColormakerRegistry.add('densityfit', DensityfitColormaker)\n\nexport default DensityfitColormaker\n","/**\n * @file Atomindex Colormaker\n * @author Fred Ludlow \n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport SpatialHash from '../geometry/spatial-hash'\n\n// from CHARMM\nconst partialCharges: { [k: string]: { [k: string]: number } } = {\n 'ARG': {\n 'CD': 0.1,\n 'CZ': 0.5,\n 'NE': -0.1\n },\n 'ASN': {\n 'CG': 0.55,\n 'OD1': -0.55\n },\n 'ASP': {\n 'CB': -0.16,\n 'CG': 0.36,\n 'OD1': -0.6,\n 'OD2': -0.6\n },\n 'CYS': {\n 'CB': 0.19,\n 'SG': -0.19\n },\n 'GLN': {\n 'CD': 0.55,\n 'OE1': -0.55\n },\n 'GLU': {\n 'CD': 0.36,\n 'CG': -0.16,\n 'OE1': -0.6,\n 'OE2': -0.6\n },\n 'HIS': {\n 'CB': 0.1,\n 'CD2': 0.2,\n 'CE1': 0.45,\n 'CG': 0.15,\n 'ND1': 0.05,\n 'NE2': 0.05\n },\n 'LYS': {\n 'CE': 0.25,\n 'NZ': 0.75\n },\n 'MET': {\n 'CE': 0.06,\n 'CG': 0.06,\n 'SD': -0.12\n },\n 'PTR': {\n 'C': 0.55,\n 'CA': 0.1,\n 'CZ': 0.25,\n 'N': -0.35,\n 'O': -0.55,\n 'O1P': -0.85,\n 'O2P': -0.85,\n 'O3P': -0.85,\n 'OG1': -1.1,\n 'P': 1.4\n },\n 'SEP': {\n 'C': 0.55,\n 'CA': 0.1,\n 'CB': 0.25,\n 'N': -0.35,\n 'O': -0.55,\n 'O1P': -0.85,\n 'O2P': -0.85,\n 'O3P': -0.85,\n 'OG1': -1.1,\n 'P': 1.4\n },\n 'SER': {\n 'CB': 0.25,\n 'OG': -0.25\n },\n 'THR': {\n 'CB': 0.25,\n 'OG1': -0.25\n },\n 'TPO': {\n 'C': 0.55,\n 'CA': 0.1,\n 'CB': 0.25,\n 'N': -0.35,\n 'O': -0.55,\n 'OG1': -1.1,\n 'O1P': -0.85,\n 'O2P': -0.85,\n 'O3P': -0.85,\n 'P': 1.4\n },\n 'TRP': {\n 'CD1': 0.06,\n 'CD2': 0.1,\n 'CE2': -0.04,\n 'CE3': -0.03,\n 'CG': -0.03,\n 'NE1': -0.06\n },\n 'TYR': {\n 'CZ': 0.25,\n 'OH': -0.25\n },\n 'backbone': {\n 'C': 0.55,\n 'O': -0.55,\n 'N': -0.35,\n 'CA': 0.1\n }\n}\n\nconst maxRadius = 12.0\nconst nHBondDistance = 1.04\nconst nHCharge = 0.25\n\n/**\n * Populates position vector with location of implicit or explicit H\n * Returns position or undefined if not able to locate H\n *\n * @param {AtomProxy} ap - the nitrogen atom\n * @param {Vector3} [position] - optional target\n * @return {Vectors|undefined} the hydrogen atom position\n */\nfunction backboneNHPosition (ap: AtomProxy, position = new Vector3()) {\n let h = false\n let ca = false\n let c = false\n position.set(2 * ap.x, 2 * ap.y, 2 * ap.z)\n\n ap.eachBondedAtom(function (a2: AtomProxy) {\n // Any time we detect H, reset position and skip\n // future tests\n if (h) return\n if (a2.atomname === 'H') {\n position.set(a2.x, a2.y, a2.z)\n h = true\n return\n }\n if (!ca && a2.atomname === 'CA') {\n position.sub(a2 as any) // TODO\n ca = true\n } else if (!c && a2.atomname === 'C') {\n c = true\n position.sub(a2 as any) // TODO\n }\n })\n\n if (h) { return position }\n\n if (ca && c) {\n position.normalize()\n position.multiplyScalar(nHBondDistance)\n position.add(ap as any)\n return position\n }\n}\n\n/**\n * Takes an array of Vector3 objects and\n * converts to an object that looks like an AtomStore\n *\n * @param {Vector3[]} positions - array of positions\n * @return {Object} AtomStore-like object\n */\nfunction buildStoreLike (positions: Vector3[]) {\n const n = positions.length\n const x = new Float32Array(n)\n const y = new Float32Array(n)\n const z = new Float32Array(n)\n\n for (let i = 0; i < positions.length; i++) {\n const v = positions[ i ]\n x[ i ] = v.x\n y[ i ] = v.y\n z[ i ] = v.z\n }\n\n return { x: x, y: y, z: z, count: n }\n}\n\nfunction chargeForAtom (a: AtomProxy): number {\n if (a.partialCharge !== null) return a.partialCharge\n if (!a.isProtein()) { return 0.0 }\n return (\n (partialCharges[ a.resname ] &&\n partialCharges[ a.resname ][ a.atomname ]) ||\n partialCharges[ 'backbone' ][ a.atomname ] || 0.0\n )\n}\n\n/**\n * Color a surface by electrostatic charge. This is a highly approximate\n * calculation! The partial charges are CHARMM with hydrogens added to heavy\n * atoms and hydrogen positions generated for amides.\n *\n * __Name:__ _electrostatic_\n *\n * @example\n * stage.loadFile( \"rcsb://3dqb\" ).then( function( o ){\n * o.addRepresentation( \"surface\", { colorScheme: \"electrostatic\" } );\n * o.autoView();\n * } );\n */\nclass ElectrostaticColormaker extends Colormaker {\n scale: ColormakerScale\n hHash: SpatialHash\n hash: SpatialHash\n charges: Float32Array\n hStore: { x: Float32Array, y: Float32Array, z: Float32Array, count: number }\n atomProxy: AtomProxy\n\n delta = new Vector3()\n hCharges: number[] = []\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'rwb'\n }\n if (!params.domain) {\n this.parameters.domain = [ -50, 50 ]\n }\n\n this.scale = this.getScale()\n\n this.charges = new Float32Array(params.structure.atomCount)\n const hPositions: Vector3[] = []\n\n params.structure.eachAtom((ap: AtomProxy) => {\n this.charges[ ap.index ] = chargeForAtom(ap) * ap.occupancy\n if (ap.atomname === 'N') {\n\n // In the specific case where N forms two bonds to\n // CA and C, try and place a dummy hydrogen\n\n if (ap.bondCount >= 3) return; // Skip if 3 bonds already (e.g. PRO)\n\n if (ap.bondToElementCount(1)) return; // Skip if any H specificed\n\n const hPos = backboneNHPosition(ap)\n if (hPos !== undefined) {\n hPositions.push(hPos)\n this.hCharges.push(nHCharge * ap.occupancy)\n }\n }\n })\n\n const bbox = params.structure.getBoundingBox()\n bbox.expandByScalar(nHBondDistance) // Worst case\n\n // SpatialHash requires x,y,z and count\n this.hStore = buildStoreLike(hPositions)\n this.hHash = new SpatialHash(this.hStore as any, bbox) // TODO\n this.hash = new SpatialHash(params.structure.atomStore, bbox)\n }\n\n @manageColor\n positionColor (v: Vector3) {\n\n const charges = this.charges\n const hCharges = this.hCharges\n\n let p = 0.0\n this.hash.eachWithin(v.x, v.y, v.z, maxRadius, (atomIndex, dSq) => {\n const charge = charges[atomIndex]\n if (charge === 0.0) return\n p += charge / dSq\n })\n\n this.hHash.eachWithin(v.x, v.y, v.z, maxRadius, (atomIndex, dSq) => {\n const charge = hCharges[atomIndex]\n if (charge === 0.0) return\n p += charge / dSq\n })\n\n return this.scale(p * 332) // 332 to convert to kcal/mol\n }\n}\n\nColormakerRegistry.add('electrostatic', ElectrostaticColormaker)\n\nexport default ElectrostaticColormaker\n","/**\n * @file Element Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport Colormaker, { ColormakerParameters, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\n// from Jmol http://jmol.sourceforge.net/jscolors/ (or 0xFFFFFF)\nconst ElementColors: { [k: string]: number } = {\n 'H': 0xFFFFFF,\n 'HE': 0xD9FFFF,\n 'LI': 0xCC80FF,\n 'BE': 0xC2FF00,\n 'B': 0xFFB5B5,\n 'C': 0x909090,\n 'N': 0x3050F8,\n 'O': 0xFF0D0D,\n 'F': 0x90E050,\n 'NE': 0xB3E3F5,\n 'NA': 0xAB5CF2,\n 'MG': 0x8AFF00,\n 'AL': 0xBFA6A6,\n 'SI': 0xF0C8A0,\n 'P': 0xFF8000,\n 'S': 0xFFFF30,\n 'CL': 0x1FF01F,\n 'AR': 0x80D1E3,\n 'K': 0x8F40D4,\n 'CA': 0x3DFF00,\n 'SC': 0xE6E6E6,\n 'TI': 0xBFC2C7,\n 'V': 0xA6A6AB,\n 'CR': 0x8A99C7,\n 'MN': 0x9C7AC7,\n 'FE': 0xE06633,\n 'CO': 0xF090A0,\n 'NI': 0x50D050,\n 'CU': 0xC88033,\n 'ZN': 0x7D80B0,\n 'GA': 0xC28F8F,\n 'GE': 0x668F8F,\n 'AS': 0xBD80E3,\n 'SE': 0xFFA100,\n 'BR': 0xA62929,\n 'KR': 0x5CB8D1,\n 'RB': 0x702EB0,\n 'SR': 0x00FF00,\n 'Y': 0x94FFFF,\n 'ZR': 0x94E0E0,\n 'NB': 0x73C2C9,\n 'MO': 0x54B5B5,\n 'TC': 0x3B9E9E,\n 'RU': 0x248F8F,\n 'RH': 0x0A7D8C,\n 'PD': 0x006985,\n 'AG': 0xC0C0C0,\n 'CD': 0xFFD98F,\n 'IN': 0xA67573,\n 'SN': 0x668080,\n 'SB': 0x9E63B5,\n 'TE': 0xD47A00,\n 'I': 0x940094,\n 'XE': 0x940094,\n 'CS': 0x57178F,\n 'BA': 0x00C900,\n 'LA': 0x70D4FF,\n 'CE': 0xFFFFC7,\n 'PR': 0xD9FFC7,\n 'ND': 0xC7FFC7,\n 'PM': 0xA3FFC7,\n 'SM': 0x8FFFC7,\n 'EU': 0x61FFC7,\n 'GD': 0x45FFC7,\n 'TB': 0x30FFC7,\n 'DY': 0x1FFFC7,\n 'HO': 0x00FF9C,\n 'ER': 0x00E675,\n 'TM': 0x00D452,\n 'YB': 0x00BF38,\n 'LU': 0x00AB24,\n 'HF': 0x4DC2FF,\n 'TA': 0x4DA6FF,\n 'W': 0x2194D6,\n 'RE': 0x267DAB,\n 'OS': 0x266696,\n 'IR': 0x175487,\n 'PT': 0xD0D0E0,\n 'AU': 0xFFD123,\n 'HG': 0xB8B8D0,\n 'TL': 0xA6544D,\n 'PB': 0x575961,\n 'BI': 0x9E4FB5,\n 'PO': 0xAB5C00,\n 'AT': 0x754F45,\n 'RN': 0x428296,\n 'FR': 0x420066,\n 'RA': 0x007D00,\n 'AC': 0x70ABFA,\n 'TH': 0x00BAFF,\n 'PA': 0x00A1FF,\n 'U': 0x008FFF,\n 'NP': 0x0080FF,\n 'PU': 0x006BFF,\n 'AM': 0x545CF2,\n 'CM': 0x785CE3,\n 'BK': 0x8A4FE3,\n 'CF': 0xA136D4,\n 'ES': 0xB31FD4,\n 'FM': 0xB31FBA,\n 'MD': 0xB30DA6,\n 'NO': 0xBD0D87,\n 'LR': 0xC70066,\n 'RF': 0xCC0059,\n 'DB': 0xD1004F,\n 'SG': 0xD90045,\n 'BH': 0xE00038,\n 'HS': 0xE6002E,\n 'MT': 0xEB0026,\n 'DS': 0xFFFFFF,\n 'RG': 0xFFFFFF,\n 'CN': 0xFFFFFF,\n 'UUT': 0xFFFFFF,\n 'FL': 0xFFFFFF,\n 'UUP': 0xFFFFFF,\n 'LV': 0xFFFFFF,\n 'UUH': 0xFFFFFF,\n\n 'D': 0xFFFFC0,\n 'T': 0xFFFFA0\n}\nconst DefaultElementColor = 0xFFFFFF\n\n/**\n * Color by element\n */\nclass ElementColormaker extends Colormaker {\n constructor (params: ColormakerParameters) {\n params.value = defaults(params.value, ElementColors.C)\n\n super(params)\n }\n\n\n @manageColor\n atomColor (a: AtomProxy) {\n const element = a.element\n\n if (element === 'C') {\n return this.parameters.value\n } else {\n return ElementColors[ element ] || DefaultElementColor\n }\n }\n}\n\nColormakerRegistry.add('element', ElementColormaker)\n\nexport default ElementColormaker\n","/**\n * @file Entityindex Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Color by entity index\n */\nclass EntityindexColormaker extends Colormaker {\n entityindexScale: ColormakerScale\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'Spectral'\n }\n if (!params.domain) {\n this.parameters.domain = [ 0, params.structure.entityList.length - 1 ]\n }\n\n this.entityindexScale = this.getScale()\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n return this.entityindexScale(a.entityIndex)\n }\n}\n\nColormakerRegistry.add('entityindex', EntityindexColormaker)\n\nexport default EntityindexColormaker\n","/**\n * @file Entitytype Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\nimport {\n PolymerEntity, NonPolymerEntity, MacrolideEntity, WaterEntity\n} from '../structure/structure-constants'\n\n/**\n * Color by entity type\n */\nclass EntitytypeColormaker extends Colormaker {\n @manageColor\n atomColor (a: AtomProxy) {\n const e = a.entity\n const et = e ? e.entityType : undefined\n switch (et) {\n case PolymerEntity:\n return 0x7fc97f\n case NonPolymerEntity:\n return 0xfdc086\n case MacrolideEntity:\n return 0xbeaed4\n case WaterEntity:\n return 0x386cb0\n default:\n return 0xffff99\n }\n }\n}\n\nColormakerRegistry.add('entitytype', EntitytypeColormaker)\n\nexport default EntitytypeColormaker\n","/**\n * @file Geoquality Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport { countSetBits } from '../math/math-utils'\n\n/**\n * Color by validation gometry quality\n */\nclass GeoqualityColormaker extends Colormaker {\n geoAtomDict: { [k: string]: { [k: string]: number } } = {}\n geoDict: { [k: string]: number|undefined } = {}\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n const val = params.structure.validation\n if (val) {\n this.geoAtomDict = val.geoAtomDict\n this.geoDict = val.geoDict\n }\n }\n\n @manageColor\n atomColor (atom: AtomProxy) {\n let sele = atom.resno + ''\n if (atom.inscode) sele += '^' + atom.inscode\n if (atom.chainname) sele += ':' + atom.chainname\n sele += '/' + atom.modelIndex\n\n let geoProblemCount\n const geoAtom = this.geoAtomDict[ sele ]\n if (geoAtom !== undefined) {\n const atomProblems: number = geoAtom[ atom.atomname ] || 0\n geoProblemCount = countSetBits(atomProblems)\n } else {\n geoProblemCount = this.geoDict[ sele ] || 0\n }\n\n if (geoProblemCount === 0) {\n return 0x2166ac\n } else if (geoProblemCount === 1) {\n return 0xfee08b\n } else if (geoProblemCount === 2) {\n return 0xf46d43\n } else if (geoProblemCount >= 3) {\n return 0xa50026\n }\n return 0x909090\n }\n}\n\nColormakerRegistry.add('geoquality', GeoqualityColormaker)\n\nexport default GeoqualityColormaker\n","/**\n * @file Hydrophobicity Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { ColormakerParameters, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\nimport {\n ResidueHydrophobicity, DefaultResidueHydrophobicity\n} from '../structure/structure-constants'\n\n/**\n * Color by hydrophobicity\n */\nclass HydrophobicityColormaker extends Colormaker {\n hfScale: ColormakerScale\n resHF: { [k: string]: number } = {}\n defaultResidueHydrophobicity: number\n\n constructor (params: ColormakerParameters) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'RdYlGn'\n }\n\n const idx = 0 // 0: DGwif, 1: DGwoct, 2: Oct-IF\n\n for (const name in ResidueHydrophobicity) {\n this.resHF[ name ] = ResidueHydrophobicity[ name ][ idx ]\n }\n this.defaultResidueHydrophobicity = DefaultResidueHydrophobicity[idx]\n\n if (!params.domain) {\n let min = Infinity\n let max = -Infinity\n\n for (const name in this.resHF) {\n const val = this.resHF[ name ]\n min = Math.min(min, val)\n max = Math.max(max, val)\n }\n\n this.parameters.domain = [ min, 0, max ]\n }\n\n this.hfScale = this.getScale()\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n return this.hfScale(this.resHF[ a.resname ] || this.defaultResidueHydrophobicity)\n }\n}\n\nColormakerRegistry.add('hydrophobicity', HydrophobicityColormaker)\n\nexport default HydrophobicityColormaker\n","/**\n * @file Modelindex Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Color by model index\n */\nclass ModelindexColormaker extends Colormaker {\n modelindexScale: ColormakerScale\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'rainbow'\n }\n if (!params.domain) {\n this.parameters.domain = [ 0, params.structure.modelStore.count ]\n }\n\n this.modelindexScale = this.getScale()\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n return this.modelindexScale(a.modelIndex)\n }\n}\n\nColormakerRegistry.add('modelindex', ModelindexColormaker)\n\nexport default ModelindexColormaker\n","/**\n * @file Moleculetype Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\nimport {\n WaterType, IonType, ProteinType, RnaType, DnaType, SaccharideType\n} from '../structure/structure-constants'\n\n/**\n * Color by molecule type\n */\nclass MoleculetypeColormaker extends Colormaker {\n @manageColor\n atomColor (a: AtomProxy) {\n switch (a.residueType.moleculeType) {\n case WaterType:\n return 0x386cb0\n case IonType:\n return 0xf0027f\n case ProteinType:\n return 0xbeaed4\n case RnaType:\n return 0xfdc086\n case DnaType:\n return 0xbf5b17\n case SaccharideType:\n return 0x7fc97f\n default:\n return 0xffff99\n }\n }\n}\n\nColormakerRegistry.add('moleculetype', MoleculetypeColormaker)\n\nexport default MoleculetypeColormaker\n","/**\n * @file Occupancy Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { ColormakerParameters, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Color by occupancy\n */\nclass OccupancyColormaker extends Colormaker {\n occupancyScale: ColormakerScale\n\n constructor (params: ColormakerParameters) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'PuBu'\n }\n\n if (!params.domain) {\n this.parameters.domain = [ 0.0, 1.0 ]\n }\n\n this.occupancyScale = this.getScale()\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n return this.occupancyScale(a.occupancy)\n }\n}\n\nColormakerRegistry.add('occupancy', OccupancyColormaker)\n\nexport default OccupancyColormaker\n","/**\n * @file Partialcharge Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { ColormakerParameters, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Color by partial charge. The {@link AtomProxy.partialCharge} property is used for coloring.\n * The default domain is [-1, 1].\n *\n * __Name:__ _partialCharge_\n *\n * @example\n * stage.loadFile(\"rcsb://1crn\").then(function (o) {\n * o.addRepresentation(\"ball+stick\", {colorScheme: \"partialCharge\"});\n * o.autoView();\n * });\n */\nclass PartialchargeColormaker extends Colormaker {\n partialchargeScale: ColormakerScale\n\n constructor (params: ColormakerParameters) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'rwb'\n }\n\n if (!params.domain) {\n this.parameters.domain = [-1, 1]\n }\n\n this.partialchargeScale = this.getScale()\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n return this.partialchargeScale(a.partialCharge || 0)\n }\n}\n\nColormakerRegistry.add('partialcharge', PartialchargeColormaker)\n\nexport default PartialchargeColormaker\n","/**\n * @file Random Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { manageColor } from './colormaker'\n\nfunction randomColor () {\n return Math.random() * 0xFFFFFF\n}\n\n/**\n * Class by random color\n */\nclass RandomColormaker extends Colormaker {\n /**\n * get color for an atom\n * @return {Integer} random hex color\n */\n @manageColor\n atomColor () {\n return randomColor()\n }\n\n /**\n * get color for volume cell\n * @return {Integer} random hex color\n */\n @manageColor\n volumeColor () {\n return randomColor()\n }\n\n /**\n * get color for coordinates in space\n * @return {Integer} random hex color\n */\n @manageColor\n positionColor () {\n return randomColor()\n }\n}\n\nColormakerRegistry.add('random', RandomColormaker)\n\nexport default RandomColormaker\n","/**\n * @file Randomcoilindex Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\n/**\n * Color by random coil index\n */\nclass RandomcoilindexColormaker extends Colormaker {\n rciScale: ColormakerScale\n rciDict: { [k: string]: number|undefined } = {}\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'RdYlBu'\n }\n\n this.rciScale = this.getScale({ domain: [ 0.6, 0 ] })\n\n const val = params.structure.validation\n if (val) this.rciDict = val.rciDict\n\n }\n\n @manageColor\n atomColor (atom: AtomProxy) {\n let sele = `[${atom.resname}]${atom.resno}`\n if (atom.chainname) sele += ':' + atom.chainname\n\n const rci = this.rciDict[ sele ]\n return rci !== undefined ? this.rciScale(rci) : 0x909090\n }\n}\n\nColormakerRegistry.add('randomcoilindex', RandomcoilindexColormaker)\n\nexport default RandomcoilindexColormaker\n","/**\n * @file Residueindex Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport Colormaker, { StuctureColormakerParams, ColormakerScale, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ChainProxy from '../proxy/chain-proxy'\n\n/**\n * Color by residue index\n */\nclass ResidueindexColormaker extends Colormaker {\n scalePerChain: { [k: number]: ColormakerScale } = {}\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n if (!params.scale) {\n this.parameters.scale = 'rainbow'\n this.parameters.reverse = defaults(params.reverse, true)\n }\n\n params.structure.eachChain((cp: ChainProxy) => {\n this.parameters.domain = [ cp.residueOffset, cp.residueEnd ]\n this.scalePerChain[ cp.index ] = this.getScale()\n })\n }\n\n @manageColor\n atomColor (a: AtomProxy) {\n return this.scalePerChain[ a.chainIndex ](a.residueIndex)\n }\n}\n\nColormakerRegistry.add('residueindex', ResidueindexColormaker)\n\nexport default ResidueindexColormaker\n","/**\n * @file Resname Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\n\n// protein colors from Jmol http://jmol.sourceforge.net/jscolors/\nconst ResidueColors: { [k: string]: number } = {\n 'ALA': 0x8CFF8C,\n 'ARG': 0x00007C,\n 'ASN': 0xFF7C70,\n 'ASP': 0xA00042,\n 'CYS': 0xFFFF70,\n 'GLN': 0xFF4C4C,\n 'GLU': 0x660000,\n 'GLY': 0xFFFFFF,\n 'HIS': 0x7070FF,\n 'ILE': 0x004C00,\n 'LEU': 0x455E45,\n 'LYS': 0x4747B8,\n 'MET': 0xB8A042,\n 'PHE': 0x534C52,\n 'PRO': 0x525252,\n 'SER': 0xFF7042,\n 'THR': 0xB84C00,\n 'TRP': 0x4F4600,\n 'TYR': 0x8C704C,\n 'VAL': 0xFF8CFF,\n\n 'ASX': 0xFF00FF,\n 'GLX': 0xFF00FF,\n 'ASH': 0xFF00FF,\n 'GLH': 0xFF00FF,\n\n 'A': 0xDC143C, // Crimson Red\n 'G': 0x32CD32, // Lime Green\n 'I': 0x9ACD32, // Yellow Green\n 'X': 0x7CFC00, // Lawn Green\n 'C': 0xFFD700, // Gold Yellow\n 'T': 0x4169E1, // Royal Blue\n 'U': 0x40E0D0, // Turquoise Cyan\n 'D': 0x008B8B, // Dark Cyan\n\n 'DA': 0xDC143C,\n 'DG': 0x32CD32,\n 'DI': 0x9ACD32,\n 'DX': 0x7CFC00,\n 'DC': 0xFFD700,\n 'DT': 0x4169E1,\n 'DU': 0x40E0D0,\n 'DD': 0x008B8B\n}\nconst DefaultResidueColor = 0xFF00FF\n\n/**\n * Color by residue name\n */\nclass ResnameColormaker extends Colormaker {\n @manageColor\n atomColor (a: AtomProxy) {\n return ResidueColors[ a.resname ] || DefaultResidueColor\n }\n}\n\nColormakerRegistry.add('resname', ResnameColormaker)\n\nexport default ResnameColormaker\n","/**\n * @file Sstruc Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { StuctureColormakerParams, manageColor } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport ResidueProxy from '../proxy/residue-proxy'\n\n// from Jmol http://jmol.sourceforge.net/jscolors/ (shapely)\nconst StructureColors = {\n 'alphaHelix': 0xFF0080,\n 'threeTenHelix': 0xA00080,\n 'piHelix': 0x600080,\n 'betaStrand': 0xFFC800,\n 'betaTurn': 0x6080FF,\n 'coil': 0xFFFFFF,\n\n 'dna': 0xAE00FE,\n 'rna': 0xFD0162,\n\n 'carbohydrate': 0xA6A6FA\n}\nconst DefaultStructureColor = 0x808080\n\n/**\n * Color by secondary structure\n */\nclass SstrucColormaker extends Colormaker {\n residueProxy: ResidueProxy\n\n constructor (params: StuctureColormakerParams) {\n super(params)\n\n this.residueProxy = params.structure.getResidueProxy()\n }\n\n @manageColor\n atomColor (ap: AtomProxy) {\n const sstruc = ap.sstruc\n const rp = this.residueProxy\n\n if (sstruc === 'h') {\n return StructureColors.alphaHelix\n } else if (sstruc === 'g') {\n return StructureColors.threeTenHelix\n } else if (sstruc === 'i') {\n return StructureColors.piHelix\n } else if (sstruc === 'e' || sstruc === 'b') {\n return StructureColors.betaStrand\n } else if (sstruc === 't') {\n return StructureColors.betaTurn\n } else {\n rp.index = ap.residueIndex\n if (rp.isDna()) {\n return StructureColors.dna\n } else if (rp.isRna()) {\n return StructureColors.rna\n } else if (rp.isSaccharide()) {\n return StructureColors.carbohydrate\n } else if (rp.isProtein() || sstruc === 's' || sstruc === 'l') {\n return StructureColors.coil\n } else {\n return DefaultStructureColor\n }\n }\n }\n}\n\nColormakerRegistry.add('sstruc', SstrucColormaker)\n\nexport default SstrucColormaker\n","/**\n * @file Colordata Colormaker\n * @author Fred Ludlow \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { ColorData, ColormakerScale, manageColor, StuctureColormakerParams } from './colormaker'\nimport AtomProxy from '../proxy/atom-proxy'\nimport BondProxy from '../proxy/bond-proxy'\n\n\nclass StructuredataColormaker extends Colormaker {\n atomData?: ColorData['atomData']\n bondData?: ColorData['bondData']\n scale: ColormakerScale\n\n constructor(params: StuctureColormakerParams) {\n super(params)\n if (!params.scale) {\n this.parameters.scale = 'rwb'\n }\n this.atomData = this.parameters.data?.atomData\n this.bondData = this.parameters.data?.bondData\n this.scale = this.getScale(this.parameters)\n }\n\n @manageColor\n atomColor(a: AtomProxy) {\n const val = this.atomData?.[a.index]\n return (val !== undefined) ? this.scale(val) : this.parameters.value\n }\n\n @manageColor\n bondColor(bond: BondProxy, fromTo: boolean) {\n const val = this.bondData?.[bond.index]\n \n // Explicit bond data?\n if (val !== undefined) return this.scale(val)\n \n \n if (this.atomProxy) {\n this.atomProxy.index = fromTo ? bond.atomIndex1 : bond.atomIndex2\n return this.atomColor(this.atomProxy)\n } \n \n // Fallback\n return this.parameters.value\n }\n}\n\nColormakerRegistry.add('structuredata', StructuredataColormaker)\n\nexport default StructuredataColormaker","/**\n * @file Uniform Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { manageColor } from './colormaker'\n\n/**\n * Color by uniform color\n */\nclass UniformColormaker extends Colormaker {\n @manageColor\n atomColor () {\n return this.parameters.value\n }\n\n @manageColor\n bondColor () {\n return this.parameters.value\n }\n\n @manageColor\n valueColor () {\n return this.parameters.value\n }\n\n @manageColor\n volumeColor () {\n return this.parameters.value\n }\n}\n\nColormakerRegistry.add('uniform', UniformColormaker)\n\nexport default UniformColormaker\n","/**\n * @file Value Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { VolumeColormakerParams, ColormakerScale, manageColor } from './colormaker'\n\n/**\n * Color by volume value\n */\nclass ValueColormaker extends Colormaker {\n valueScale: ColormakerScale\n\n constructor (params: VolumeColormakerParams) {\n super(params)\n this.valueScale = this.getScale()\n }\n\n /**\n * return the color for a volume cell\n * @param {Integer} index - volume cell index\n * @return {Integer} hex cell color\n */\n @manageColor\n volumeColor (index: number) {\n return this.valueScale((this.parameters.volume! as any).data[ index ]) // TODO\n }\n}\n\nColormakerRegistry.add('value', ValueColormaker)\n\nexport default ValueColormaker\n","/**\n * @file Volume Colormaker\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\nimport { lerp } from '../math/math-utils'\n\nimport { ColormakerRegistry } from '../globals'\nimport Colormaker, { VolumeColormakerParams, ColormakerScale, manageColor } from './colormaker'\n\n/**\n * Color by volume position\n */\nclass VolumeColormaker extends Colormaker {\n valueScale: ColormakerScale\n vec = new Vector3()\n\n constructor (params: VolumeColormakerParams) {\n super(params)\n this.valueScale = this.getScale()\n }\n\n /**\n * return the color for coordinates in space\n * @param {Vector3} coords - xyz coordinates\n * @return {Integer} hex coords color\n */\n @manageColor\n positionColor (coords: Vector3) {\n const volume = this.parameters.volume as any // TODO\n\n if (!volume || !volume.inverseMatrix) {\n return this.parameters.value\n }\n\n const vec = this.vec\n const data = volume.data\n const nx = volume.nx\n const ny = volume.ny\n const nxy = nx * ny\n\n vec.copy(coords)\n vec.applyMatrix4(volume.inverseMatrix)\n\n // position of grid cell\n const x0 = Math.floor(vec.x)\n const y0 = Math.floor(vec.y)\n const z0 = Math.floor(vec.z)\n\n // Indices\n const i = ((((z0 * ny) + y0) * nx) + x0)\n const i1 = i + 1\n const iy = i + nx\n const iz = i + nxy\n const i1y = iy + 1\n const i1z = iz + 1\n const iyz = iy + nxy\n const i1yz = iyz + 1\n\n // Values\n const v = data[ i ]\n const v1 = data[ i1 ]\n const vy = data[ iy ]\n const vz = data[ iz ]\n const v1y = data[ i1y ]\n const v1z = data[ i1z ]\n const vyz = data[ iyz ]\n const v1yz = data[ i1yz ]\n\n // Position of point in fraction of grid\n const xd = vec.x - x0\n const yd = vec.y - y0\n const zd = vec.z - z0\n\n // 1st Dimension\n const c00 = lerp(v, v1, xd)\n const c01 = lerp(vz, v1z, xd)\n const c10 = lerp(vy, v1y, xd)\n const c11 = lerp(vyz, v1yz, xd)\n\n // 2nd Dimension\n const c0 = lerp(c00, c10, yd)\n const c1 = lerp(c01, c11, yd)\n\n // 3rd Dimension\n const c = lerp(c0, c1, zd)\n\n return this.valueScale(c)\n }\n}\n\nColormakerRegistry.add('volume', VolumeColormaker)\n\nexport default VolumeColormaker\n","/**\n * @file Structure Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { ExtensionFragDepth, Mobile } from '../globals'\nimport { defaults } from '../utils'\nimport { RepresentationParameters, default as Representation } from './representation'\nimport Selection from '../selection/selection'\nimport RadiusFactory, { RadiusFactoryTypes, RadiusType } from '../utils/radius-factory'\nimport Structure from '../structure/structure'\nimport Viewer from '../viewer/viewer'\n// @ts-ignore: unused import Volume required for declaration only\nimport { Assembly, Volume } from '../ngl';\nimport StructureView from '../structure/structure-view';\nimport AtomProxy from '../proxy/atom-proxy';\nimport Polymer from '../proxy/polymer';\nimport Buffer from '../buffer/buffer';\nimport { AtomDataFields, BondDataFields, AtomDataParams, BondDataParams } from '../structure/structure-data';\n// @ts-ignore: unused import Surface required for declaration only\nimport Surface from '../surface/surface'\n\n/**\n * Structure representation parameter object.\n * @typedef {Object} StructureRepresentationParameters - structure representation parameters\n * @mixes RepresentationParameters\n *\n * @property {String} radiusType - A list of possible sources of the radius used for rendering the representation. The radius can be based on the *vdW radius*, the *covalent radius* or the *B-factor* value of the corresponding atom. Additionally the radius can be based on the *secondary structure*. Alternatively, when set to *size*, the value from the *radius* parameter is used for all atoms.\n * @property {Float} radius - A number providing a fixed radius used for rendering the representation.\n * @property {Float} scale - A number that scales the value defined by the *radius* or the *radiusType* parameter.\n * @property {String} assembly - name of an assembly object. Included are the asymmetric unit (*AU*) corresponding to the coordinates given in the structure file, biological assemblies from *PDB*, *mmCIF* or *MMTF* files (*BU1*, *BU2*, ...), a filled (crystallographic) unitcell of a given space group (*UNITCELL*), a supercell consisting of a center unitcell and its 26 direct neighbors (*SUPERCELL*). Set to *default* to use the default asemmbly of the structure object.\n */\nexport interface StructureRepresentationParameters extends RepresentationParameters {\n radiusType: string\n radius: number\n scale: number\n assembly: string\n}\nexport interface StructureRepresentationData {\n bufferList: Buffer[]\n polymerList?: Polymer[]\n sview?: StructureView | Structure\n [k: string]: any\n}\n/**\n * Structure representation\n * @interface\n */\nabstract class StructureRepresentation extends Representation {\n\n protected selection: Selection\n protected dataList: StructureRepresentationData[]\n structure: Structure\n structureView: StructureView\n\n protected radiusType: RadiusType\n protected radiusData: {[k: number]: number}\n protected radiusSize: number\n protected radiusScale: number\n protected assembly: string\n protected defaultAssembly: string\n protected needsBuild: boolean\n\n /**\n * Create Structure representation object\n * @param {Structure} structure - the structure to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {StructureRepresentationParameters} params - structure representation parameters\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n const p = params || {}\n\n super(structure, viewer, p)\n\n this.type = 'structure'\n\n this.parameters = Object.assign({\n radiusType: {\n type: 'select', options: RadiusFactory.types\n },\n radiusData: {\n type: 'hidden'\n },\n radiusSize: {\n type: 'number', precision: 3, max: 10.0, min: 0.001\n },\n radiusScale: {\n type: 'number', precision: 3, max: 10.0, min: 0.001\n },\n assembly: null,\n defaultAssembly: {\n type: 'hidden'\n }\n }, this.parameters)\n\n /**\n * @type {Selection}\n * @private\n */\n this.selection = new Selection(p.sele)\n\n /**\n * @type {Array}\n * @private\n */\n this.dataList = []\n\n /**\n * @type {Structure}\n */\n this.structure = structure\n\n /**\n * @type {StructureView}\n */\n this.structureView = this.structure.getView(this.selection)\n\n if (structure.biomolDict) {\n const biomolOptions:{[key: string]: string} = {\n 'default': 'default',\n '': (structure.unitcell ? 'AU' : 'FULL')\n }\n Object.keys(structure.biomolDict).forEach(function (k) {\n biomolOptions[ k ] = k\n })\n this.parameters.assembly = {\n type: 'select',\n options: biomolOptions,\n rebuild: true\n }\n } else {\n this.parameters.assembly = null\n }\n }\n\n get defaultScale () {\n return {\n 'vdw': 1.0,\n 'covalent': 1.0,\n 'bfactor': 0.01,\n 'sstruc': 1.0\n }\n }\n\n init (params: Partial) {\n const p = params || {}\n p.colorScheme = defaults(p.colorScheme, 'element')\n\n this.setRadius(p.radius, p)\n\n this.radiusType = defaults(p.radiusType, 'vdw')\n this.radiusData = defaults(p.radiusData, {})\n this.radiusSize = defaults(p.radiusSize, 1.0)\n this.radiusScale = defaults(p.radiusScale, 1.0)\n this.assembly = defaults(p.assembly, 'default')\n this.defaultAssembly = defaults(p.defaultAssembly, '')\n\n if (p.quality === 'auto') {\n p.quality = this.getQuality()\n }\n\n super.init(p)\n\n this.selection.signals.stringChanged.add((/* sele */) => {\n this.build()\n })\n\n this.build()\n }\n\n setRadius (value: string | number | undefined, p: Partial) {\n const types = Object.keys(RadiusFactoryTypes)\n\n if (typeof value === 'string' && types.includes(value.toLowerCase())) {\n p.radiusType = value\n } else if (value !== undefined) {\n p.radiusType = 'size'\n p.radiusSize = value\n }\n\n return this\n }\n\n getAssembly (): Assembly {\n const name = this.assembly === 'default' ? this.defaultAssembly : this.assembly\n return this.structure.biomolDict[ name ]\n }\n\n getQuality () {\n let atomCount\n const s = this.structureView\n const assembly = this.getAssembly()\n if (assembly) {\n atomCount = assembly.getAtomCount(s)\n } else {\n atomCount = s.atomCount\n }\n if (Mobile) {\n atomCount *= 4\n }\n const backboneOnly = s.atomStore.count / s.residueStore.count < 2\n if (backboneOnly) {\n atomCount *= 10\n }\n\n if (atomCount < 15000) {\n return 'high'\n } else if (atomCount < 80000) {\n return 'medium'\n } else {\n return 'low'\n }\n }\n\n create () {\n if (this.structureView.atomCount === 0) return\n\n if (!this.structureView.hasCoords()) {\n this.needsBuild = true\n return\n } else {\n this.needsBuild = false\n }\n\n const assembly = this.getAssembly()\n\n if (assembly) {\n assembly.partList.forEach((part, i) => {\n const sview = part.getView(this.structureView)\n if (sview.atomCount === 0) return\n const data = this.createData(sview, i)\n if (data) {\n data.sview = sview\n data.instanceList = part.getInstanceList()\n this.dataList.push(data)\n }\n })\n } else {\n const data = this.createData(this.structureView, 0)\n if (data) {\n data.sview = this.structureView\n this.dataList.push(data)\n }\n }\n }\n\n abstract createData (sview: StructureView, k?: number): StructureRepresentationData|undefined\n\n update (what: AtomDataFields|BondDataFields) {\n if (this.lazy && !this.visible) {\n Object.assign(this.lazyProps.what, what)\n return\n }\n\n if (this.needsBuild) {\n this.build()\n return\n }\n\n this.dataList.forEach((data) => {\n if (data.bufferList.length > 0) {\n this.updateData(what, data)\n }\n }, this)\n }\n\n updateData (what?: AtomDataFields|BondDataFields, data?: any) {\n this.build()\n }\n\n getColorParams () {\n return {\n ...super.getColorParams(),\n structure: this.structure\n }\n }\n\n getRadiusParams (param?: any) {\n return {\n type: this.radiusType,\n scale: this.radiusScale,\n size: this.radiusSize,\n data: this.radiusData\n }\n }\n\n getAtomParams (what?: AtomDataFields, params?: AtomDataParams) {\n return Object.assign({\n what: what,\n colorParams: this.getColorParams(),\n radiusParams: this.getRadiusParams()\n }, params)\n }\n\n getBondParams (what?: BondDataFields, params?: BondDataParams) {\n return Object.assign({\n what: what,\n colorParams: this.getColorParams(),\n radiusParams: this.getRadiusParams()\n }, params)\n }\n\n getAtomRadius (atom: AtomProxy) {\n if (this.structureView.atomSet!.isSet(atom.index)) {\n const radiusFactory = new RadiusFactory(this.getRadiusParams())\n return radiusFactory.atomRadius(atom)\n }\n return 0\n }\n\n /**\n * Set representation parameters\n * @alias StructureRepresentation#setSelection\n * @param {String} string - selection string, see {@tutorial selection-language}\n * @param {Boolean} [silent] - don't trigger a change event in the selection\n * @return {StructureRepresentation} this object\n */\n setSelection (string: string, silent?: boolean) {\n this.selection.setString(string, silent)\n\n return this\n }\n\n /**\n * Set representation parameters\n * @alias StructureRepresentation#setParameters\n * @param {StructureRepresentationParameters} params - structure parameter object\n * @param {Object} [what] - buffer data attributes to be updated,\n * note that this needs to be implemented in the\n * derived classes. Generally it allows more\n * fine-grained control over updating than\n * forcing a rebuild.\n * @param {Boolean} what.position - update position data\n * @param {Boolean} what.color - update color data\n * @param {Boolean} [rebuild] - whether or not to rebuild the representation\n * @return {StructureRepresentation} this object\n */\n setParameters (params: Partial, what: AtomDataFields = {}, rebuild = false) {\n const p = params || {}\n\n this.setRadius(p.radius, p)\n\n if (p.radiusType !== undefined || p.radiusData !== undefined || p.radiusSize !== undefined || p.radiusScale !== undefined) {\n what.radius = true\n if (!ExtensionFragDepth || this.disableImpostor) {\n rebuild = true\n }\n }\n\n if (p.defaultAssembly !== undefined &&\n p.defaultAssembly !== this.defaultAssembly &&\n ((this.assembly === 'default' && p.assembly === undefined) ||\n p.assembly === 'default')\n ) {\n rebuild = true\n }\n\n super.setParameters(p, what, rebuild)\n\n return this\n }\n\n getParameters () {\n const params = Object.assign(\n super.getParameters(),\n {\n sele: this.selection ? this.selection.string : undefined,\n defaultAssembly: this.defaultAssembly\n }\n )\n\n return params\n }\n\n attach (callback: ()=> void) {\n const viewer = this.viewer\n const bufferList = this.bufferList\n\n this.dataList.forEach(function (data) {\n data.bufferList.forEach(function (buffer) {\n bufferList.push(buffer)\n viewer.add(buffer, data.instanceList)\n })\n })\n\n this.setVisibility(this.visible)\n callback()\n }\n\n clear () {\n this.dataList.length = 0\n\n super.clear()\n }\n\n dispose () {\n this.structureView.dispose()\n\n super.dispose()\n }\n}\n\nexport default StructureRepresentation\n","/**\n * @file Measurement Representation\n * @author Fred Ludlow \n * @private\n */\n\n// @ts-ignore: unused import Vector3, Matrix4 required for declaration only\nimport { Color, Vector3, Matrix4 } from 'three'\n\nimport Selection from '../selection/selection'\nimport { Browser } from '../globals'\nimport { defaults } from '../utils'\nimport StructureRepresentation, { StructureRepresentationParameters } from './structure-representation'\nimport { uniformArray, uniformArray3 } from '../math/array-utils'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport StructureView from '../structure/structure-view';\nimport { LabelRepresentationParameters } from './label-representation';\nimport TextBuffer, { TextBufferData } from '../buffer/text-buffer';\nimport { GenericColor } from '../types'\n\nexport interface LabelDataField {\n position?: boolean\n labelColor?: boolean\n labelSize?: boolean\n radius?: boolean\n labelText?: boolean\n}\n\n/**\n * Measurement representation parameter object.\n * @typedef {Object} MeasurementRepresentationParameters - measurement representation parameters\n * @mixes RepresentationParameters\n * @mixes StructureRepresentationParameters\n *\n * @property {Float} labelSize - size of the distance label\n * @property {Color} labelColor - color of the distance label\n * @property {Boolean} labelVisible - visibility of the distance label\n * @property {Float} labelZOffset - offset in z-direction (i.e. in camera direction)\n */\nexport interface MeasurementRepresentationParameters extends StructureRepresentationParameters {\n labelVisible: boolean\n labelSize: number\n labelColor: GenericColor\n labelType: 'atomname'|'atomindex'|'occupancy'|'bfactor'|'serial'|'element'|'atom'|'resname'|'resno'|'res'|'text'|'qualified'\n labelText: string\n labelFormat: string\n labelGrouping: 'atom'|'residue'\n labelFontFamily: 'sans-serif'|'monospace'|'serif'\n labelFontStyle: 'normal'|'italic'\n labelFontWeight: 'normal'|'bold'\n labelsdf: boolean\n labelXOffset: number\n labelYOffset: number\n labelZOffset: number\n labelAttachment: 'bottom-left'|'bottom-center'|'bottom-right'|'middle-left'|'middle-center'|'middle-right'|'top-left'|'top-center'|'top-right'\n labelBorder: boolean\n labelBorderColor: GenericColor\n labelBorderWidth: number\n labelBackground: boolean\n labelBackgroundColor: GenericColor\n labelBackgroundMargin: number\n labelBackgroundOpacity: number\n labelFixedSize: boolean\n lineOpacity: number\n linewidth: number\n}\n\n/**\n * Measurement representation\n * @interface\n */\nabstract class MeasurementRepresentation extends StructureRepresentation {\n protected n: number\n protected labelVisible: boolean\n protected labelSize: number\n protected labelColor: GenericColor\n protected labelType: 'atomname'|'atomindex'|'occupancy'|'bfactor'|'serial'|'element'|'atom'|'resname'|'resno'|'res'|'text'|'qualified'\n protected labelText: string\n protected labelFormat: string\n protected labelGrouping: 'atom'|'residue'\n protected labelFontFamily: 'sans-serif'|'monospace'|'serif'\n protected labelFontStyle: 'normal'|'italic'\n protected labelFontWeight: 'normal'|'bold'\n protected labelsdf: boolean\n protected labelXOffset: number\n protected labelYOffset: number\n protected labelZOffset: number\n protected labelAttachment: 'bottom-left'|'bottom-center'|'bottom-right'|'middle-left'|'middle-center'|'middle-right'|'top-left'|'top-center'|'top-right'\n protected labelBorder: boolean\n protected labelBorderColor: GenericColor\n protected labelBorderWidth: number\n protected labelBackground: boolean\n protected labelBackgroundColor: GenericColor\n protected labelBackgroundMargin: number\n protected labelBackgroundOpacity: number\n protected labelFixedSize: boolean\n protected lineOpacity: number\n protected linewidth: number\n protected lineVisible: boolean\n\n protected textBuffer: TextBuffer\n /**\n * Handles common label settings and position logic for\n * distance, angle and dihedral representations\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.n = 0 // Subclass create sets value\n this.parameters = Object.assign({\n labelVisible: {\n type: 'boolean'\n },\n labelSize: {\n type: 'number', precision: 3, max: 10.0, min: 0.001\n },\n labelColor: {\n type: 'color'\n },\n labelFontFamily: {\n type: 'select',\n options: {\n 'sans-serif': 'sans-serif',\n 'monospace': 'monospace',\n 'serif': 'serif'\n },\n buffer: 'fontFamily'\n },\n labelFontStyle: {\n type: 'select',\n options: {\n 'normal': 'normal',\n 'italic': 'italic'\n },\n buffer: 'fontStyle'\n },\n labelFontWeight: {\n type: 'select',\n options: {\n 'normal': 'normal',\n 'bold': 'bold'\n },\n buffer: 'fontWeight'\n },\n labelsdf: {\n type: 'boolean', buffer: 'sdf'\n },\n labelXOffset: {\n type: 'number', precision: 1, max: 20, min: -20, buffer: 'xOffset'\n },\n labelYOffset: {\n type: 'number', precision: 1, max: 20, min: -20, buffer: 'yOffset'\n },\n labelZOffset: {\n type: 'number', precision: 1, max: 20, min: -20, buffer: 'zOffset'\n },\n labelAttachment: {\n type: 'select',\n options: {\n 'bottom-left': 'bottom-left',\n 'bottom-center': 'bottom-center',\n 'bottom-right': 'bottom-right',\n 'middle-left': 'middle-left',\n 'middle-center': 'middle-center',\n 'middle-right': 'middle-right',\n 'top-left': 'top-left',\n 'top-center': 'top-center',\n 'top-right': 'top-right'\n },\n rebuild: true\n },\n labelBorder: {\n type: 'boolean', buffer: 'showBorder'\n },\n labelBorderColor: {\n type: 'color', buffer: 'borderColor'\n },\n labelBorderWidth: {\n type: 'number', precision: 2, max: 0.3, min: 0, buffer: 'borderWidth'\n },\n labelBackground: {\n type: 'boolean', rebuild: true\n },\n labelBackgroundColor: {\n type: 'color', buffer: 'backgroundColor'\n },\n labelBackgroundMargin: {\n type: 'number', precision: 2, max: 2, min: 0, rebuild: true\n },\n labelBackgroundOpacity: {\n type: 'range', step: 0.01, max: 1, min: 0, buffer: 'backgroundOpacity'\n },\n labelFixedSize: {\n type: 'boolean', buffer: 'fixedSize'\n },\n lineOpacity: {\n type: 'range', min: 0.0, max: 1.0, step: 0.01\n },\n linewidth: {\n type: 'integer', max: 50, min: 1, buffer: true\n }\n }, this.parameters, {\n flatShaded: null\n })\n }\n\n init (params: Partial) {\n const p = params || {}\n this.labelVisible = defaults(p.labelVisible, true)\n this.labelSize = defaults(p.labelSize, 2.0)\n this.labelColor = defaults(p.labelColor, 0xFFFFFF)\n this.labelFontFamily = defaults(p.labelFontFamily, 'sans-serif')\n this.labelFontStyle = defaults(p.labelFontstyle, 'normal')\n this.labelFontWeight = defaults(p.labelFontWeight, 'bold')\n this.labelsdf = defaults(p.labelsdf, Browser === 'Chrome')\n this.labelXOffset = defaults(p.labelXOffset, 0.0)\n this.labelYOffset = defaults(p.labelYOffset, 0.0)\n this.labelZOffset = defaults(p.labelZOffset, 0.5)\n this.labelAttachment = defaults(p.labelAttachment, 'bottom-left')\n this.labelBorder = defaults(p.labelBorder, false)\n this.labelBorderColor = defaults(p.labelBorderColor, 'lightgrey')\n this.labelBorderWidth = defaults(p.labelBorderWidth, 0.15)\n this.labelBackground = defaults(p.labelBackground, false)\n this.labelBackgroundColor = defaults(p.labelBackgroundColor, 'lightgrey')\n this.labelBackgroundMargin = defaults(p.labelBackgroundMargin, 0.5)\n this.labelBackgroundOpacity = defaults(p.labelBackgroundOpacity, 1.0)\n this.labelFixedSize = defaults(p.labelFixedSize, false)\n this.lineOpacity = defaults(p.lineOpacity, 1.0)\n this.linewidth = defaults(p.linewidth, 2)\n\n super.init(p)\n }\n\n // All measurements need to rebuild on position change\n update (what: LabelDataField) {\n if (what.position) {\n this.build()\n } else {\n super.update(what)\n }\n }\n\n updateData (what: LabelDataField & {[k: string]: any}, data: any) {\n const textData: TextBufferData | {} = {}\n if (!what || what.labelSize) {\n Object.assign(textData, {size: uniformArray(this.n, this.labelSize)})\n }\n\n if (!what || what.labelColor) {\n const c = new Color(this.labelColor)\n Object.assign(textData, {color: uniformArray3(this.n, c.r, c.g, c.b)})\n }\n\n this.textBuffer.setAttributes(textData as TextBufferData)\n }\n\n setParameters (params: Partial, what: LabelDataField = {}, rebuild = false) {\n if (params && params.labelSize) {\n what.labelSize = true\n }\n\n if (params && (params.labelColor || params.labelColor === 0x000000)) {\n what.labelColor = true\n rebuild = true\n }\n\n super.setParameters(params, what, rebuild)\n\n if (params && params.opacity !== undefined) {\n this.textBuffer.setParameters({ opacity: 1.0 }) // only opaque labels\n }\n\n if (params && params.labelVisible !== undefined) {\n this.setVisibility(this.visible)\n }\n\n return this\n }\n\n setVisibility (value: boolean, noRenderRequest?: boolean) {\n super.setVisibility(value, true)\n if (this.textBuffer) {\n this.textBuffer.setVisibility(\n this.labelVisible && this.visible\n )\n }\n\n if (!noRenderRequest) this.viewer.requestRender()\n\n return this\n }\n\n getLabelBufferParams (params: Partial = {}) {\n return super.getBufferParams(Object.assign({\n fontFamily: this.labelFontFamily,\n fontStyle: this.labelFontStyle,\n fontWeight: this.labelFontWeight,\n sdf: this.labelsdf,\n xOffset: this.labelXOffset,\n yOffset: this.labelYOffset,\n zOffset: this.labelZOffset,\n attachment: this.labelAttachment,\n showBorder: this.labelBorder,\n borderColor: this.labelBorderColor,\n borderWidth: this.labelBorderWidth,\n showBackground: this.labelBackground,\n backgroundColor: this.labelBackgroundColor,\n backgroundMargin: this.labelBackgroundMargin,\n backgroundOpacity: this.labelBackgroundOpacity,\n fixedSize: this.labelFixedSize,\n disablePicking: true,\n visible: this.labelVisible\n }, params, {\n opacity: 1.0 // only opaque labels\n }))\n }\n\n getAtomRadius () {\n return 0\n }\n}\n\n/**\n * MeasurementRepresentations take atom[Pair|Triple|Quad] parameters.\n *\n * Parses nested array of either integer atom indices or selection\n * expressions into a flat array of coordinates.\n *\n * @param {Structure} sview The structure to which the atoms refer\n * @param {Array} atoms Nested array of atom pairs|triples|quads as\n * Integer indices or selection expressions\n * @return {Float32Array} Flattened array of position coordinates\n */\nfunction parseNestedAtoms (sview: StructureView, atoms: (number|string)[][]) {\n const ap = sview.getAtomProxy()\n const sele = new Selection()\n\n const nSets = atoms.length\n if (nSets === 0) return new Float32Array(0)\n\n // Peek-ahead at first item to determine order and parse mode\n const order = atoms[ 0 ].length\n const selected = sview.getAtomSet()\n\n const a = new Float32Array(nSets * order * 3)\n\n let p = 0\n atoms.forEach(function (group) {\n let _break = false\n for (let j = 0; j < order; j++) {\n const value = group[ j ]\n if (typeof (value) === 'number' && Number.isInteger(value)) {\n if (selected.get(value)) {\n ap.index = value\n } else {\n _break = true\n break\n }\n } else {\n sele.setString(value as string)\n const atomIndices = sview.getAtomIndices(sele)\n if (atomIndices!.length) {\n ap.index = atomIndices![ 0 ]\n } else {\n _break = true\n break\n }\n }\n\n let offset = p + j * 3\n a[ offset++ ] = ap.x\n a[ offset++ ] = ap.y\n a[ offset++ ] = ap.z\n }\n if (!_break) p += 3 * order\n })\n\n return a.subarray(0, p)\n}\n\n/* out = v1 * cos(angle) + v2 * sin(angle) */\nfunction calcArcPoint (out: Float32Array, center: Float32Array, v1: Float32Array, v2: Float32Array, angle: number) {\n const x = Math.cos(angle)\n const y = Math.sin(angle)\n out[ 0 ] = center[ 0 ] + v1[ 0 ] * x + v2[ 0 ] * y\n out[ 1 ] = center[ 1 ] + v1[ 1 ] * x + v2[ 1 ] * y\n out[ 2 ] = center[ 2 ] + v1[ 2 ] * x + v2[ 2 ] * y\n}\n\nexport {\n MeasurementRepresentation as default,\n calcArcPoint,\n parseNestedAtoms\n}\n","/**\n * @file Edt\n * @author Alexander Rose \n * @private\n */\n\nimport { NumberArray } from '../types'\n\n// 2D Euclidean distance transform by Felzenszwalb & Huttenlocher https://cs.brown.edu/~pff/papers/dt-final.pdf\nexport function edt(data: NumberArray, width: number, height: number, f: NumberArray, d: NumberArray, v: NumberArray, z: NumberArray) {\n for (let x = 0; x < width; x++) {\n for (let y = 0; y < height; y++) {\n f[y] = data[y * width + x]\n }\n edt1d(f, d, v, z, height)\n for (let y = 0; y < height; y++) {\n data[y * width + x] = d[y]\n }\n }\n for (let y = 0; y < height; y++) {\n for (let x = 0; x < width; x++) {\n f[x] = data[y * width + x]\n }\n edt1d(f, d, v, z, width)\n for (let x = 0; x < width; x++) {\n data[y * width + x] = Math.sqrt(d[x])\n }\n }\n}\n\n// 1D squared distance transform\nfunction edt1d(f: NumberArray, d: NumberArray, v: NumberArray, z: NumberArray, n: number) {\n v[0] = 0\n z[0] = Number.MIN_SAFE_INTEGER\n z[1] = Number.MAX_SAFE_INTEGER\n\n for (let q = 1, k = 0; q < n; q++) {\n let s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k])\n while (s <= z[k]) {\n k--\n s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k])\n }\n k++\n v[k] = q\n z[k] = s\n z[k + 1] = Number.MAX_SAFE_INTEGER\n }\n\n for (let q = 0, k = 0; q < n; q++) {\n while (z[k + 1] < q) k++\n d[q] = (q - v[k]) * (q - v[k]) + f[v[k]]\n }\n}\n","/**\n * @file Text Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Vector3, Matrix4 required for declaration only\nimport { Color, CanvasTexture, Vector3, Matrix4 } from 'three'\n\nimport '../shader/SDFFont.vert'\nimport '../shader/SDFFont.frag'\n\nimport { BufferRegistry } from '../globals'\nimport { createParams } from '../utils'\nimport MappedQuadBuffer from './mappedquad-buffer'\nimport { IgnorePicker } from '../utils/picker'\nimport { edt } from '../utils/edt'\nimport { BufferDefaultParameters, BufferParameterTypes, BufferData, BufferTypes, BufferParameters } from './buffer'\nimport { GenericColor } from '../types'\n\nconst TextAtlasCache: { [k: string]: TextAtlas } = {}\n\nfunction getTextAtlas (params: Partial) {\n const hash = JSON.stringify(params)\n if (TextAtlasCache[ hash ] === undefined) {\n TextAtlasCache[ hash ] = new TextAtlas(params)\n }\n return TextAtlasCache[ hash ]\n}\n\ntype TextFonts = 'sans-serif'|'monospace'|'serif'\ntype TextStyles = 'normal'|'italic'\ntype TextVariants = 'normal'\ntype TextWeights = 'normal'|'bold'\n\nexport const TextAtlasDefaultParams = {\n font: 'sans-serif' as TextFonts,\n size: 36,\n style: 'normal' as TextStyles,\n variant: 'normal' as TextVariants,\n weight: 'normal' as TextWeights,\n outline: 3,\n width: 1024,\n height: 1024\n}\nexport type TextAtlasParams = typeof TextAtlasDefaultParams\n\nexport type TextAtlasMap = { x: number, y: number, w: number, h: number }\n\nexport class TextAtlas {\n parameters: TextAtlasParams\n\n gamma = 1\n mapped: { [k: string]: TextAtlasMap } = {}\n scratchW = 0\n scratchH = 0\n currentX = 0\n currentY = 0\n\n cutoff = 0.25\n padding: number\n radius: number\n\n gridOuter: Float64Array\n gridInner: Float64Array\n f: Float64Array\n d: Float64Array\n z: Float64Array\n v: Int16Array\n\n paddedSize: number\n middle: number\n\n texture: CanvasTexture\n canvas: HTMLCanvasElement\n context: CanvasRenderingContext2D\n\n lineHeight: number\n maxWidth: number\n colors: string[]\n scratch: Uint8Array\n canvas2: HTMLCanvasElement\n context2: CanvasRenderingContext2D\n data: Uint8Array\n\n placeholder: TextAtlasMap\n\n constructor (params: Partial = {}) {\n this.parameters = createParams(params, TextAtlasDefaultParams)\n const p = this.parameters\n\n this.radius = p.size / 8\n this.padding = p.size / 3\n\n // Prepare line-height with room for outline and descenders/ascenders\n const lineHeight = this.lineHeight = p.size + 2 * p.outline + Math.round(p.size / 4)\n const maxWidth = this.maxWidth = p.width / 4\n\n // Prepare scratch canvas\n const canvas = this.canvas = document.createElement('canvas')\n canvas.width = maxWidth\n canvas.height = lineHeight\n\n const ctx = this.context = this.canvas.getContext('2d', { willReadFrequently: true})!\n ctx.font = `${p.style} ${p.variant} ${p.weight} ${p.size}px ${p.font}`\n ctx.fillStyle = 'black'\n ctx.textAlign = 'left'\n ctx.textBaseline = 'bottom'\n ctx.lineJoin = 'round'\n\n // temporary arrays for the distance transform\n this.gridOuter = new Float64Array(lineHeight * maxWidth)\n this.gridInner = new Float64Array(lineHeight * maxWidth)\n this.f = new Float64Array(Math.max(lineHeight, maxWidth))\n this.d = new Float64Array(Math.max(lineHeight, maxWidth))\n this.z = new Float64Array(Math.max(lineHeight, maxWidth) + 1)\n this.v = new Int16Array(Math.max(lineHeight, maxWidth))\n\n //\n this.data = new Uint8Array(p.width * p.height * 4)\n this.canvas2 = document.createElement('canvas')\n this.canvas2.width = p.width\n this.canvas2.height = p.height\n this.context2 = this.canvas2.getContext('2d')!\n\n // Replacement Character\n this.placeholder = this.map(String.fromCharCode(0xFFFD))\n\n // Basic Latin (subset)\n for (let i = 0x0020; i <= 0x007E; ++i) {\n this.map(String.fromCharCode(i))\n }\n\n // TODO: to slow to always prepare them\n // // Latin-1 Supplement (subset)\n // for (let i = 0x00A1; i <= 0x00FF; ++i) {\n // this.map(String.fromCharCode(i))\n // }\n\n // Degree sign\n this.map(String.fromCharCode(0x00B0))\n\n // // Greek and Coptic (subset)\n // for (let i = 0x0391; i <= 0x03C9; ++i) {\n // this.map(String.fromCharCode(i))\n // }\n\n // // Cyrillic (subset)\n // for (let i = 0x0400; i <= 0x044F; ++i) {\n // this.map(String.fromCharCode(i))\n // }\n\n // Angstrom Sign\n this.map(String.fromCharCode(0x212B))\n\n this.texture = new CanvasTexture(this.canvas2)\n this.texture.flipY = false\n this.texture.needsUpdate = true\n }\n\n map (text: string) {\n const p = this.parameters\n\n if (this.mapped[ text ] === undefined) {\n this.draw(text)\n\n if (this.currentX + this.scratchW > p.width) {\n this.currentX = 0\n this.currentY += this.scratchH\n }\n if (this.currentY + this.scratchH > p.height) {\n console.warn('canvas to small')\n }\n\n this.mapped[ text ] = {\n x: this.currentX,\n y: this.currentY,\n w: this.scratchW,\n h: this.scratchH\n }\n\n this.context2.drawImage(\n this.canvas,\n 0, 0,\n this.scratchW, this.scratchH,\n this.currentX, this.currentY,\n this.scratchW, this.scratchH\n )\n\n this.currentX += this.scratchW\n }\n\n return this.mapped[ text ]\n }\n\n get (text: string) {\n return this.mapped[ text ] || this.placeholder\n }\n\n draw (text: string) {\n const p = this.parameters\n\n const h = this.lineHeight\n const o = p.outline\n const ctx = this.context\n // const dst = this.scratch\n const max = this.maxWidth\n // const colors = this.colors\n\n // Bottom aligned, take outline into account\n const x = o\n const y = h - p.outline\n\n // Measure text\n const m = ctx.measureText(text)\n const w = Math.min(max, Math.ceil(m.width + 2 * x + 1))\n\n const n = w * h\n\n // Clear scratch area\n ctx.clearRect(0, 0, w, h)\n\n // Draw text\n ctx.fillText(text, x, y)\n\n const imageData = ctx.getImageData(0, 0, w, h)\n const data = imageData.data\n\n for (let i = 0; i < n; i++) {\n const a = imageData.data[i * 4 + 3] / 255; // alpha value\n this.gridOuter[i] = a === 1 ? 0 : a === 0 ? Number.MAX_SAFE_INTEGER : Math.pow(Math.max(0, 0.5 - a), 2);\n this.gridInner[i] = a === 1 ? Number.MAX_SAFE_INTEGER : a === 0 ? 0 : Math.pow(Math.max(0, a - 0.5), 2);\n }\n\n edt(this.gridOuter, w, h, this.f, this.d, this.v, this.z);\n edt(this.gridInner, w, h, this.f, this.d, this.v, this.z);\n\n for (let i = 0; i < n; i++) {\n const d = this.gridOuter[i] - this.gridInner[i];\n data[i * 4 + 3] = Math.max(0, Math.min(255, Math.round(255 - 255 * (d / this.radius + this.cutoff))));\n }\n\n ctx.putImageData(imageData, 0, 0)\n this.scratchW = w\n this.scratchH = h\n }\n}\n\n/**\n * Text buffer parameter object.\n * @typedef {Object} TextBufferParameters - text buffer parameters\n *\n * @property {Float} opacity - translucency: 1 is fully opaque, 0 is fully transparent\n * @property {Integer} clipNear - position of camera near/front clipping plane\n * in percent of scene bounding box\n * @property {String} labelType - type of the label, one of:\n * \"atomname\", \"atomindex\", \"occupancy\", \"bfactor\",\n * \"serial\", \"element\", \"atom\", \"resname\", \"resno\",\n * \"res\", \"text\", \"qualified\". When set to \"text\", the\n * `labelText` list is used.\n * @property {String[]} labelText - list of label strings, must set `labelType` to \"text\"\n * to take effect\n * @property {String} fontFamily - font family, one of: \"sans-serif\", \"monospace\", \"serif\"\n * @property {String} fontStyle - font style, \"normal\" or \"italic\"\n * @property {String} fontWeight - font weight, \"normal\" or \"bold\"\n * @property {Float} xOffset - offset in x-direction\n * @property {Float} yOffset - offset in y-direction\n * @property {Float} zOffset - offset in z-direction (i.e. in camera direction)\n * @property {String} attachment - attachment of the label, one of:\n * \"bottom-left\", \"bottom-center\", \"bottom-right\",\n * \"middle-left\", \"middle-center\", \"middle-right\",\n * \"top-left\", \"top-center\", \"top-right\"\n * @property {Boolean} showBorder - show border/outline\n * @property {Color} borderColor - color of the border/outline\n * @property {Float} borderWidth - width of the border/outline\n * @property {Boolean} showBackground - show background rectangle\n * @property {Color} backgroundColor - color of the background\n * @property {Float} backgroundMargin - width of the background\n * @property {Float} backgroundOpacity - opacity of the background\n * @property {Boolean} fixedSize - show text with a fixed pixel size\n */\n\nexport interface TextBufferData extends BufferData {\n size: Float32Array\n text: string[]\n}\n\ntype TextAttachments = 'bottom-left'|'bottom-center'|'bottom-right'|'middle-left'|'middle-center'|'middle-right'|'top-left'|'top-center'|'top-right'\n\nexport const TextBufferDefaultParameters = Object.assign({\n fontFamily: 'sans-serif' as TextFonts,\n fontStyle: 'normal' as TextStyles,\n fontWeight: 'bold' as TextWeights,\n fontSize: 36,\n xOffset: 0.0,\n yOffset: 0.0,\n zOffset: 0.5,\n attachment: 'bottom-left' as TextAttachments,\n showBorder: false,\n borderColor: 'lightgrey' as number|string,\n borderWidth: 0.15,\n showBackground: false,\n backgroundColor: 'lightgrey' as number|string,\n backgroundMargin: 0.5,\n backgroundOpacity: 1.0,\n forceTransparent: true,\n fixedSize: false\n}, BufferDefaultParameters)\nexport type TextBufferParameters = BufferParameters & {\n fontFamily: TextFonts,\n fontStyle: TextStyles,\n fontWeight: TextWeights,\n fontSize: number,\n xOffset: number,\n yOffset: number,\n zOffset: number,\n attachment: TextAttachments,\n showBorder: boolean,\n borderColor: GenericColor,\n borderWidth: number,\n showBackground: boolean,\n backgroundColor: GenericColor,\n backgroundMargin: number,\n backgroundOpacity: number,\n forceTransparent: boolean,\n fixedSize: boolean\n}\n\nconst TextBufferParameterTypes = Object.assign({\n fontFamily: { uniform: true },\n fontStyle: { uniform: true },\n fontWeight: { uniform: true },\n fontSize: { uniform: true },\n xOffset: { uniform: true },\n yOffset: { uniform: true },\n zOffset: { uniform: true },\n showBorder: { uniform: true },\n borderColor: { uniform: true },\n borderWidth: { uniform: true },\n backgroundColor: { uniform: true },\n backgroundOpacity: { uniform: true },\n fixedSize: { updateShader: true }\n}, BufferParameterTypes)\n\nfunction getCharCount (data: TextBufferData, params: Partial) {\n const n = data.position!.length / 3\n let charCount = 0\n for (let i = 0; i < n; ++i) {\n charCount += data.text[ i ].length\n }\n if (params.showBackground) charCount += n\n\n return charCount\n}\n\n/**\n * Text buffer. Renders screen-aligned text strings.\n *\n * @example\n * var textBuffer = new TextBuffer({\n * position: new Float32Array([ 0, 0, 0 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * size: new Float32Array([ 2 ]),\n * text: [ \"Hello\" ]\n * });\n */\nclass TextBuffer extends MappedQuadBuffer {\n parameterTypes = TextBufferParameterTypes\n get defaultParameters() { return TextBufferDefaultParameters }\n parameters: TextBufferParameters\n\n alwaysTransparent = true\n hasWireframe = false\n isText = true\n vertexShader = 'SDFFont.vert'\n fragmentShader = 'SDFFont.frag'\n\n text: string[]\n positionCount: number\n texture: CanvasTexture\n textAtlas: TextAtlas\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} data.size - sizes\n * @param {String[]} data.text - text strings\n * @param {TextBufferParameters} params - parameters object\n */\n constructor (data: TextBufferData, params: Partial = {}) {\n super({\n position: new Float32Array(getCharCount(data, params) * 3),\n color: new Float32Array(getCharCount(data, params) * 3),\n picking: new IgnorePicker()\n }, params)\n\n this.text = data.text\n this.positionCount = data.position!.length / 3\n\n this.addUniforms({\n 'fontTexture': { value: null },\n 'xOffset': { value: this.parameters.xOffset },\n 'yOffset': { value: this.parameters.yOffset },\n 'zOffset': { value: this.parameters.zOffset },\n 'ortho': { value: false },\n 'showBorder': { value: this.parameters.showBorder },\n 'borderColor': { value: new Color(this.parameters.borderColor as number) },\n 'borderWidth': { value: this.parameters.borderWidth },\n 'backgroundColor': { value: new Color(this.parameters.backgroundColor as number) },\n 'backgroundOpacity': { value: this.parameters.backgroundOpacity },\n 'canvasHeight': { value: 1.0 },\n 'pixelRatio': { value: 1.0 }\n })\n\n this.addAttributes({\n 'inputTexCoord': { type: 'v2', value: null },\n 'inputSize': { type: 'f', value: null }\n })\n\n this.setAttributes(data)\n\n this.makeTexture()\n this.makeMapping()\n }\n\n makeMaterial () {\n super.makeMaterial()\n\n const tex = this.texture\n\n const m = this.material\n m.transparent = true\n m.extensions.derivatives = true\n m.lights = false\n m.uniforms.fontTexture.value = tex\n m.needsUpdate = true\n\n const wm = this.wireframeMaterial\n wm.transparent = true\n wm.extensions.derivatives = true\n wm.lights = false\n wm.uniforms.fontTexture.value = tex\n wm.needsUpdate = true\n\n const pm = this.pickingMaterial\n pm.extensions.derivatives = true\n pm.lights = false\n pm.uniforms.fontTexture.value = tex\n pm.needsUpdate = true\n }\n\n setAttributes (data: Partial = {}) {\n let position, size, color\n let aPosition, inputSize, aColor\n\n const text = this.text\n const attributes = this.geometry.attributes as any // TODO\n\n if (data.position) {\n position = data.position\n aPosition = attributes.position.array\n attributes.position.needsUpdate = true\n }\n\n if (data.size) {\n size = data.size\n inputSize = attributes.inputSize.array\n attributes.inputSize.needsUpdate = true\n }\n\n if (data.color) {\n color = data.color\n aColor = attributes.color.array\n attributes.color.needsUpdate = true\n }\n\n const n = this.positionCount\n\n let j, o\n let iCharAll = 0\n let txt, iChar, nChar\n\n for (let v = 0; v < n; ++v) {\n o = 3 * v\n txt = text[ v ]\n nChar = txt.length\n if (this.parameters.showBackground) nChar += 1\n\n for (iChar = 0; iChar < nChar; ++iChar, ++iCharAll) {\n for (let m = 0; m < 4; m++) {\n j = iCharAll * 4 * 3 + (3 * m)\n\n if (position) {\n aPosition[ j ] = position[ o ]\n aPosition[ j + 1 ] = position[ o + 1 ]\n aPosition[ j + 2 ] = position[ o + 2 ]\n }\n\n if (size) {\n inputSize[ (iCharAll * 4) + m ] = size[ v ]\n }\n\n if (color) {\n aColor[ j ] = color[ o ]\n aColor[ j + 1 ] = color[ o + 1 ]\n aColor[ j + 2 ] = color[ o + 2 ]\n }\n }\n }\n }\n }\n\n makeTexture () {\n this.textAtlas = getTextAtlas({\n font: this.parameters.fontFamily,\n style: this.parameters.fontStyle,\n weight: this.parameters.fontWeight,\n size: this.parameters.fontSize\n })\n\n this.texture = this.textAtlas.texture\n }\n\n makeMapping () {\n const ta = this.textAtlas\n const text = this.text\n const attachment = this.parameters.attachment\n const margin = (ta.lineHeight * this.parameters.backgroundMargin * 0.1) - 10\n\n const attribs = this.geometry.attributes as any // TODO\n const inputTexCoord = attribs.inputTexCoord.array\n const inputMapping = attribs.mapping.array\n\n const n = this.positionCount\n let iCharAll = 0\n let c, i, txt, xadvance, iChar, nChar, xShift, yShift\n\n for (let v = 0; v < n; ++v) {\n txt = text[ v ]\n xadvance = 0\n nChar = txt.length\n\n // calculate width\n for (iChar = 0; iChar < nChar; ++iChar) {\n c = ta.get(txt[ iChar ])\n xadvance += c.w - 2 * ta.parameters.outline\n }\n\n // attachment\n if (attachment.startsWith('top')) {\n yShift = ta.lineHeight / 1.25\n } else if (attachment.startsWith('middle')) {\n yShift = ta.lineHeight / 2.5\n } else {\n yShift = 0 // \"bottom\"\n }\n if (attachment.endsWith('right')) {\n xShift = xadvance\n } else if (attachment.endsWith('center')) {\n xShift = xadvance / 2\n } else {\n xShift = 0 // \"left\"\n }\n xShift += ta.parameters.outline\n yShift += ta.parameters.outline\n\n // background\n if (this.parameters.showBackground) {\n i = iCharAll * 2 * 4\n inputMapping[ i + 0 ] = -ta.lineHeight / 6 - xShift - margin // top left\n inputMapping[ i + 1 ] = ta.lineHeight - yShift + margin\n inputMapping[ i + 2 ] = -ta.lineHeight / 6 - xShift - margin // bottom left\n inputMapping[ i + 3 ] = 0 - yShift - margin\n inputMapping[ i + 4 ] = xadvance + ta.lineHeight / 6 - xShift + 2 * ta.parameters.outline + margin // top right\n inputMapping[ i + 5 ] = ta.lineHeight - yShift + margin\n inputMapping[ i + 6 ] = xadvance + ta.lineHeight / 6 - xShift + 2 * ta.parameters.outline + margin // bottom right\n inputMapping[ i + 7 ] = 0 - yShift - margin\n inputTexCoord[ i + 0 ] = 10\n inputTexCoord[ i + 2 ] = 10\n inputTexCoord[ i + 4 ] = 10\n inputTexCoord[ i + 6 ] = 10\n iCharAll += 1\n }\n\n xadvance = 0\n\n for (iChar = 0; iChar < nChar; ++iChar, ++iCharAll) {\n c = ta.get(txt[ iChar ])\n i = iCharAll * 2 * 4\n\n inputMapping[ i + 0 ] = xadvance - xShift // top left\n inputMapping[ i + 1 ] = c.h - yShift\n inputMapping[ i + 2 ] = xadvance - xShift // bottom left\n inputMapping[ i + 3 ] = 0 - yShift\n inputMapping[ i + 4 ] = xadvance + c.w - xShift // top right\n inputMapping[ i + 5 ] = c.h - yShift\n inputMapping[ i + 6 ] = xadvance + c.w - xShift // bottom right\n inputMapping[ i + 7 ] = 0 - yShift\n\n const texWidth = ta.parameters.width\n const texHeight = ta.parameters.height\n\n const texCoords = [\n c.x / texWidth, c.y / texHeight, // top left\n c.x / texWidth, (c.y + c.h) / texHeight, // bottom left\n (c.x + c.w) / texWidth, c.y / texHeight, // top right\n (c.x + c.w) / texWidth, (c.y + c.h) / texHeight // bottom right\n ]\n inputTexCoord.set(texCoords, i)\n\n xadvance += c.w - 2 * ta.parameters.outline\n }\n }\n\n attribs.inputTexCoord.needsUpdate = true\n attribs.mapping.needsUpdate = true\n }\n\n getDefines (type: BufferTypes) {\n const defines = super.getDefines(type)\n\n if (this.parameters.fixedSize) {\n defines.FIXED_SIZE = 1\n }\n\n return defines\n }\n\n setUniforms (data: any) { // TODO\n if (data && (\n data.fontFamily !== undefined ||\n data.fontStyle !== undefined ||\n data.fontWeight !== undefined ||\n data.fontSize !== undefined\n )) {\n this.makeTexture()\n this.makeMapping()\n this.texture.needsUpdate = true\n data.fontTexture = this.texture\n }\n\n super.setUniforms(data)\n }\n}\n\nBufferRegistry.add('text', TextBuffer)\n\nexport default TextBuffer\n","/**\n * @file Wide Line Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Vector3 required for declaration only\nimport { Vector2, Vector3, Matrix4 } from 'three'\n\nimport '../shader/WideLine.vert'\nimport '../shader/WideLine.frag'\n\nimport { BufferRegistry } from '../globals'\nimport MappedQuadBuffer from './mappedquad-buffer'\nimport { BufferDefaultParameters, BufferParameterTypes, BufferData, BufferParameters } from './buffer'\n\nexport interface WideLineBufferData extends BufferData {\n position1: Float32Array\n position2: Float32Array\n color2: Float32Array\n}\n\nexport const WideLineBufferDefaultParameters = Object.assign({\n linewidth: 2\n}, BufferDefaultParameters)\nexport type WideLineBufferParameters = BufferParameters & { linewidth: number }\n\nconst WideLineBufferParameterTypes = Object.assign({\n linewidth: { uniform: true }\n}, BufferParameterTypes)\n\n/**\n * Wide Line buffer. Draws lines with a fixed width in pixels.\n *\n * @example\n * var lineBuffer = new WideLineBuffer({\n * position1: new Float32Array([ 0, 0, 0 ]),\n * position2: new Float32Array([ 1, 1, 1 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * color2: new Float32Array([ 0, 1, 0 ])\n * });\n */\nclass WideLineBuffer extends MappedQuadBuffer {\n parameterTypes = WideLineBufferParameterTypes\n get defaultParameters() { return WideLineBufferDefaultParameters }\n parameters: WideLineBufferParameters\n\n vertexShader = 'WideLine.vert'\n fragmentShader ='WideLine.frag'\n\n constructor (data: Partial, params: Partial = {}) {\n super(data, params)\n\n if (!data.color2 && data.color) data.color2 = data.color\n\n this.addUniforms({\n 'linewidth': { value: this.parameters.linewidth },\n 'resolution': { value: new Vector2() },\n 'projectionMatrixInverse': { value: new Matrix4() }\n })\n\n this.addAttributes({\n 'position1': { type: 'v3', value: null },\n 'position2': { type: 'v3', value: null },\n 'color2': { type: 'c', value: null }\n })\n\n this.setAttributes(data)\n this.makeMapping()\n }\n\n setParameters (params: Partial) {\n super.setParameters(params)\n }\n}\n\nBufferRegistry.add('wideline', WideLineBuffer)\n\nexport default WideLineBuffer\n","/**\n * @file Angle Representation\n * @author Fred Ludlow \n * @private\n */\nimport { Color } from 'three'\n\nimport { RepresentationRegistry } from '../globals'\nimport MeasurementRepresentation, { parseNestedAtoms, calcArcPoint, MeasurementRepresentationParameters, LabelDataField } from './measurement-representation'\nimport { defaults } from '../utils'\n\nimport MeshBuffer from '../buffer/mesh-buffer'\nimport TextBuffer, { TextBufferData, TextBufferParameters } from '../buffer/text-buffer'\nimport WideLineBuffer, { WideLineBufferData } from '../buffer/wideline-buffer'\n\nimport { v3add, v3cross, v3dot, v3fromArray, v3length, v3new,\n v3normalize, v3sub, v3toArray } from '../math/vector-utils'\nimport { copyArray, uniformArray, uniformArray3 } from '../math/array-utils'\nimport { RAD2DEG } from '../math/math-constants'\nimport { getFixedLengthWrappedDashData } from '../geometry/dash'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport StructureView from '../structure/structure-view';\nimport { BufferData } from '../buffer/buffer';\nimport { StructureRepresentationData, StructureRepresentationParameters } from './structure-representation';\n\n/**\n * @typedef {Object} AngleRepresentationParameters - angle representation parameters\n * @mixes RepresentationParameters\n * @mixes StructureRepresentationParameters\n * @mixes MeasurementRepresentationParameters\n *\n * @property {String} atomTriple - list of triplets of selection strings\n * or atom indices\n * @property {Boolean} vectorVisible - Indicate the 3 points for each angle by drawing lines 1-2-3\n * @property {Boolean} arcVisible - Show the arc outline for each angle\n * @property {Number} lineOpacity - opacity for the line part of the representation\n * @property {Number} linewidth - width for line part of representation\n * @property {Boolean} sectorVisible - Show the filled arc for each angle\n */\n\nexport interface AngleRepresentationParameters extends MeasurementRepresentationParameters {\n atomTriple: (number|string)[][]\n vectorVisible: boolean\n arcVisible: boolean\n lineOpacity: number\n lineWidth: number\n sectorVisible: boolean\n}\n\n/**\n * Angle representation object\n *\n * Reperesentation consists of four parts, visibility can be set for each\n * label - the text label with the angle size\n * vectors - lines joining the three points\n * sector - triangles representing the angle\n * arc - line bordering the sector\n *\n * @param {Structure} structure - the structure to measure angles in\n * @param {Viewer} viewer - a viewer object\n * @param {AngleRepresentationParameters} params - angle representation parameters\n */\nclass AngleRepresentation extends MeasurementRepresentation {\n protected atomTriple: (number|string)[][]\n protected vectorVisible: boolean\n protected arcVisible: boolean\n protected lineOpacity: number\n protected lineWidth: number\n protected sectorVisible: boolean\n protected vectorBuffer: WideLineBuffer\n arcLength: number\n sectorLength: number\n arcBuffer: WideLineBuffer\n sectorBuffer: MeshBuffer\n\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'angle'\n\n this.parameters = Object.assign({\n atomTriple: {\n type: 'hidden', rebuild: true\n },\n vectorVisible: {\n type: 'boolean', default: true\n },\n arcVisible: {\n type: 'boolean', default: true\n },\n sectorVisible: {\n type: 'boolean', default: true\n }\n }, this.parameters)\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n p.side = defaults(p.side, 'double')\n p.opacity = defaults(p.opacity, 0.5)\n\n this.atomTriple = defaults(p.atomTriple, [])\n this.arcVisible = defaults(p.arcVisible, true)\n this.sectorVisible = defaults(p.sectorVisible, true)\n this.vectorVisible = defaults(p.vectorVisible, true)\n\n super.init(p)\n }\n\n createData (sview: StructureView) {\n if (!sview.atomCount || !this.atomTriple.length) return\n\n const atomPosition = atomTriplePositions(sview, this.atomTriple)\n const angleData = getAngleData(atomPosition)\n const n = this.n = angleData.labelPosition.length / 3\n\n const labelColor = new Color(this.labelColor)\n\n // Create buffers\n this.textBuffer = new TextBuffer({\n position: angleData.labelPosition,\n size: uniformArray(n, this.labelSize),\n color: uniformArray3(n, labelColor.r, labelColor.g, labelColor.b),\n text: angleData.labelText\n } as TextBufferData, this.getLabelBufferParams() as TextBufferParameters)\n\n const c = new Color(this.colorValue)\n\n this.vectorBuffer = new WideLineBuffer(\n getFixedLengthWrappedDashData({\n position1: angleData.vectorPosition1,\n position2: angleData.vectorPosition2,\n color: uniformArray3(2 * n, c.r, c.g, c.b),\n color2: uniformArray3(2 * n, c.r, c.g, c.b)\n } as WideLineBufferData),\n this.getBufferParams({\n linewidth: this.linewidth,\n visible: this.vectorVisible,\n opacity: this.lineOpacity\n })\n )\n\n this.arcLength = angleData.arcPosition1.length / 3\n\n this.arcBuffer = new WideLineBuffer(\n getFixedLengthWrappedDashData({\n position1: angleData.arcPosition1,\n position2: angleData.arcPosition2,\n color: uniformArray3(this.arcLength, c.r, c.g, c.b),\n color2: uniformArray3(this.arcLength, c.r, c.g, c.b)\n } as WideLineBufferData), this.getBufferParams({\n linewidth: this.linewidth,\n visible: this.arcVisible,\n opacity: this.lineOpacity\n }))\n\n this.sectorLength = angleData.sectorPosition.length / 3\n\n this.sectorBuffer = new MeshBuffer({\n position: angleData.sectorPosition,\n color: uniformArray3(this.sectorLength, c.r, c.g, c.b)\n } as BufferData, this.getBufferParams({\n visible: this.sectorVisible\n }))\n\n return {\n bufferList: [\n this.textBuffer,\n this.vectorBuffer,\n this.arcBuffer,\n this.sectorBuffer\n ]\n }\n }\n\n updateData (what: LabelDataField & {color?: boolean}, data: StructureRepresentationData) {\n super.updateData(what, data)\n const vectorData = {}\n const arcData = {}\n const sectorData = {}\n\n if (what.color) {\n const c = new Color(this.colorValue)\n Object.assign(vectorData, {\n color: uniformArray3(this.n * 2, c.r, c.g, c.b),\n color2: uniformArray3(this.n * 2, c.r, c.g, c.b)\n })\n Object.assign(arcData, {\n color: uniformArray3(this.arcLength, c.r, c.g, c.b),\n color2: uniformArray3(this.arcLength, c.r, c.g, c.b)\n })\n Object.assign(sectorData, {\n color: uniformArray3(this.sectorLength, c.r, c.g, c.b)\n })\n }\n\n // if (what.sectorOpacity) {\n // this.sectorBuffer.opacity = what.sectorOpacity\n // }\n\n this.vectorBuffer.setAttributes(vectorData)\n this.arcBuffer.setAttributes(arcData)\n this.sectorBuffer.setAttributes(sectorData)\n }\n\n setParameters (params: Partial) {\n var rebuild = false\n var what = {}\n\n super.setParameters(params, what, rebuild)\n\n if (params && (\n params.vectorVisible !== undefined ||\n params.arcVisible !== undefined ||\n params.sectorVisible !== undefined)) {\n this.setVisibility(this.visible)\n }\n\n if (params && params.lineOpacity) {\n this.vectorBuffer.setParameters({ opacity: params.lineOpacity })\n this.arcBuffer.setParameters({ opacity: params.lineOpacity })\n }\n\n if (params && params.opacity !== undefined) {\n this.vectorBuffer.setParameters({ opacity: this.lineOpacity })\n this.arcBuffer.setParameters({ opacity: this.lineOpacity })\n }\n\n if (params && params.linewidth) {\n this.vectorBuffer.setParameters({ linewidth: params.linewidth })\n this.arcBuffer.setParameters({ linewidth: params.linewidth })\n }\n\n return this\n }\n\n setVisibility (value: boolean, noRenderRequest?: boolean) {\n super.setVisibility(value, true)\n\n if (this.vectorBuffer) {\n this.vectorBuffer.setVisibility(this.vectorVisible && this.visible)\n }\n\n if (this.arcBuffer) {\n this.arcBuffer.setVisibility(this.arcVisible && this.visible)\n }\n\n if (this.sectorBuffer) {\n this.sectorBuffer.setVisibility(this.sectorVisible && this.visible)\n }\n\n if (!noRenderRequest) this.viewer.requestRender()\n\n return this\n }\n}\n\n/**\n * Ensure mid point does not coincide with first or second\n * @param {Float32Array} position 9*nAngle array of coordinates\n * @return {Float32Array} Filtered position array, may be shorter\n */\nfunction validatePositions (position: Float32Array) {\n const include = []\n const n = position.length / 9\n for (let i = 0; i < n; i++) {\n // Check that first point not same as second and that second not same as third\n let okay = true\n for (let j = i; j < i + 3; j += 3) {\n if (position[j] === position[j + 3] &&\n position[j + 1] === position[j + 4] &&\n position[j + 2] === position[j + 5]) {\n okay = false\n }\n }\n if (okay) include.push(i)\n }\n const outPosition = new Float32Array(include.length * 9)\n let outIdx = 0\n include.forEach(function (i) {\n copyArray(position, outPosition, i * 9, outIdx * 9, 9)\n outIdx++\n })\n return outPosition\n}\n\nfunction atomTriplePositions (sview: StructureView, atomTriple: (number|string)[][]) {\n return validatePositions(parseNestedAtoms(sview, atomTriple))\n}\n\n/**\n * Converts triple positions into data required to build various buffers.\n */\nfunction getAngleData (position: Float32Array, params: Partial = {}) {\n const angleStep = defaults(params.angleStep, Math.PI / 90)\n const n = position.length / 9\n const angles = new Float32Array(n)\n const labelPosition = new Float32Array(n * 3)\n const labelText = new Array(n)\n\n const vectorPosition1 = new Float32Array(n * 6) // Two lines per angle\n const vectorPosition2 = new Float32Array(n * 6)\n\n const arcPositionTmp1 = new Array(n) // Start points for arc lines\n const arcPositionTmp2 = new Array(n) // End points for arc lines\n const sectorPositionTmp = new Array(n) // Triangle points\n\n let totalSegments = 0\n\n // Re-used vectors etc\n const p1 = v3new() // Positions of points for each angel\n const p2 = v3new()\n const p3 = v3new()\n const v21 = v3new() // Vectors\n const v23 = v3new()\n const cross = v3new() // Cross product v21xv23\n const cross2 = v3new() // In-plane cross product v21 x (v21 x v23)\n const labelTmp = v3new()\n const arcPoint = v3new()\n\n for (var i = 0; i < n; i++) {\n let p = 9 * i\n v3fromArray(p1, position, p)\n v3fromArray(p2, position, p + 3)\n v3fromArray(p3, position, p + 6)\n\n let v = 6 * i\n v3toArray(p1, vectorPosition1, v)\n v3toArray(p2, vectorPosition2, v)\n v3toArray(p2, vectorPosition1, v + 3)\n v3toArray(p3, vectorPosition2, v + 3)\n\n v3sub(v21, p1, p2)\n v3sub(v23, p3, p2)\n\n v3normalize(v21, v21) // validatePositions ensures valid\n v3normalize(v23, v23)\n\n v3cross(cross, v21, v23)\n const crossLength = v3length(cross)\n const dot = v3dot(v21, v23)\n\n const angle = angles[i] = Math.atan2(crossLength, dot)\n labelText[i] = (RAD2DEG * angle).toFixed(1) + String.fromCharCode(0x00B0)\n\n if (v3length(cross) === 0.0) {\n // Angle exactly 0/180, pick an arbitrary direction\n cross[ 0 ] = 1.0\n cross[ 1 ] = 0.0\n cross[ 2 ] = 0.0\n }\n v3cross(cross2, cross, v21)\n v3normalize(cross2, cross2)\n\n calcArcPoint(labelTmp, p2, v21, cross2, angle / 2.0)\n // TODO: Scale label position?\n v3toArray(labelTmp, labelPosition, 3 * i)\n\n // Build the arc and sector\n\n const nSegments = Math.ceil(angle / angleStep)\n const sectorVertices = new Float32Array(nSegments * 9)\n sectorPositionTmp[ i ] = sectorVertices\n const arcVertices1 = new Float32Array(nSegments * 3)\n const arcVertices2 = new Float32Array(nSegments * 3)\n arcPositionTmp1[ i ] = arcVertices1\n arcPositionTmp2[ i ] = arcVertices2\n\n v3add(arcPoint, p2, v21) // Our initial arc point\n\n const appendArcSection = function (a: number, j: number) {\n const si = j * 9\n const ai = j * 3\n v3toArray(p2, sectorVertices, si)\n v3toArray(arcPoint, sectorVertices, si + 3)\n v3toArray(arcPoint, arcVertices1, ai)\n\n calcArcPoint(arcPoint, p2, v21, cross2, a)\n\n v3toArray(arcPoint, sectorVertices, si + 6)\n v3toArray(arcPoint, arcVertices2, ai)\n }\n\n let j = 0\n for (let a = angleStep; a < angle; a += angleStep) {\n appendArcSection(a, j)\n j++\n }\n appendArcSection(angle, j)\n totalSegments += nSegments\n }\n\n // Flatten nested arrays of arc/segment points\n const arcSize = totalSegments * 3\n const sectorSize = totalSegments * 9\n const arcPosition1 = new Float32Array(arcSize)\n const arcPosition2 = new Float32Array(arcSize)\n const sectorPosition = new Float32Array(sectorSize)\n\n let sectorOffset = 0\n let arcOffset = 0\n for (let i = 0; i < n; i++) {\n const ap1 = arcPositionTmp1[ i ]\n const ap2 = arcPositionTmp2[ i ]\n copyArray(ap1, arcPosition1, 0, arcOffset, ap1.length)\n copyArray(ap2, arcPosition2, 0, arcOffset, ap2.length)\n arcOffset += ap1.length // === ap2.length\n\n const sp = sectorPositionTmp[ i ]\n copyArray(sp, sectorPosition, 0, sectorOffset, sp.length)\n sectorOffset += sp.length\n }\n\n return {\n labelPosition,\n labelText,\n vectorPosition1,\n vectorPosition2,\n arcPosition1,\n arcPosition2,\n sectorPosition\n }\n}\n\nRepresentationRegistry.add('angle', AngleRepresentation)\n\nexport default AngleRepresentation\n","/**\n * @file Cylinder Geometry Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4, Vector3, CylinderGeometry } from 'three'\n\nimport { defaults } from '../utils'\nimport { calculateCenterArray, serialBlockArray } from '../math/array-utils'\nimport GeometryBuffer from './geometry-buffer'\nimport { CylinderBufferData } from './cylinder-buffer'\nimport { BufferDefaultParameters, BufferParameters } from './buffer'\n\nconst scale = new Vector3()\nconst eye = new Vector3()\nconst target = new Vector3()\nconst up = new Vector3(0, 1, 0)\n\nexport const CylinderGeometryBufferDefaultParameters = Object.assign({\n radialSegments: 1,\n openEnded: true\n}, BufferDefaultParameters)\nexport type CylinderGeometryBufferParameters = BufferParameters & {radialSegments: number, openEnded: boolean}\n\nfunction getData (data: CylinderBufferData, params: Partial = {}) {\n const geo = getGeo(params)\n\n const n = data.position1.length\n\n const geoLength = (geo.attributes as any).position.array.length / 3\n const count = n / 3\n const primitiveId = new Float32Array(count * 2 * geoLength)\n serialBlockArray(count, geoLength, 0, primitiveId)\n serialBlockArray(count, geoLength, count * geoLength, primitiveId)\n\n const position = new Float32Array(n * 2)\n const color = new Float32Array(n * 2)\n\n return {\n position, color, primitiveId, picking: data.picking\n }\n}\n\nfunction getGeo (params: Partial = {}) {\n const radialSegments = defaults(params.radialSegments, 10)\n const openEnded = defaults(params.openEnded, true)\n const matrix = new Matrix4().makeRotationX(Math.PI / 2)\n\n const geo = new CylinderGeometry(\n 1, // radiusTop,\n 1, // radiusBottom,\n 1, // height,\n radialSegments, // radialSegments,\n 1, // heightSegments,\n openEnded // openEnded\n )\n geo.applyMatrix4(matrix)\n\n return geo\n}\n\n/**\n * Cylinder geometry buffer.\n *\n * @example\n * var cylinderGeometryBuffer = new CylinderGeometryBuffer({\n * position1: new Float32Array([ 0, 0, 0 ]),\n * position2: new Float32Array([ 1, 1, 1 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * color2: new Float32Array([ 0, 1, 0 ]),\n * radius: new Float32Array([ 1 ])\n * });\n */\nclass CylinderGeometryBuffer extends GeometryBuffer {\n updateNormals = true\n\n get defaultParameters() { return CylinderGeometryBufferDefaultParameters }\n parameters: CylinderGeometryBufferParameters\n\n __center: Float32Array\n _position: Float32Array\n _color: Float32Array\n _from: Float32Array\n _to: Float32Array\n _radius: Float32Array\n\n /**\n * @param {Object} data - buffer data\n * @param {Float32Array} data.position1 - from positions\n * @param {Float32Array} data.position2 - to positions\n * @param {Float32Array} data.color - from colors\n * @param {Float32Array} data.color2 - to colors\n * @param {Float32Array} data.radius - radii\n * @param {Picker} [data.picking] - picking ids\n * @param {BufferParameters} [params] - parameters object\n */\n constructor (data: CylinderBufferData, params: Partial = {}) {\n super(getData(data, params), params, getGeo(params))\n\n const n = data.position1.length\n const m = data.radius.length\n\n this.__center = new Float32Array(n)\n this._position = new Float32Array(n * 2)\n this._color = new Float32Array(n * 2)\n this._from = new Float32Array(n * 2)\n this._to = new Float32Array(n * 2)\n this._radius = new Float32Array(m * 2)\n\n this.setAttributes(data, true)\n }\n\n applyPositionTransform (matrix: Matrix4, i: number, i3: number) {\n eye.fromArray(this._from as any, i3)\n target.fromArray(this._to as any, i3)\n matrix.lookAt(eye, target, up)\n\n const r = this._radius[ i ]\n scale.set(r, r, eye.distanceTo(target))\n matrix.scale(scale)\n }\n\n setAttributes (data: Partial = {}, initNormals?: boolean) {\n const meshData: Partial = {}\n\n if (data.position1 && data.position2) {\n calculateCenterArray(\n data.position1, data.position2, this.__center\n )\n calculateCenterArray(\n data.position1, this.__center, this._position\n )\n calculateCenterArray(\n this.__center, data.position2, this._position, data.position1.length\n )\n this._from.set(data.position1)\n this._from.set(this.__center, data.position1.length)\n this._to.set(this.__center)\n this._to.set(data.position2, this.__center.length)\n meshData.position = this._position\n }\n\n if (data.color && data.color2) {\n this._color.set(data.color)\n this._color.set(data.color2, data.color.length)\n meshData.color = this._color\n }\n\n if (data.radius) {\n this._radius.set(data.radius)\n this._radius.set(data.radius, data.radius.length)\n meshData.radius = this._radius\n }\n\n super.setAttributes(meshData, initNormals)\n }\n}\n\nexport default CylinderGeometryBuffer\n","/**\n * @file Mapped Aligned Box Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { BufferParameters, BufferData } from './buffer'\nimport MappedBuffer from './mapped-buffer'\n\n// +Y /\n// 0**********2\n// * | / **\n// * |/ * *\n// -----------3---- +X\n// * /| * *\n// * / | * *\n// 1/**|******4\n// / | * *\n// / | ** \n// +Z | 5 \nconst mapping = new Float32Array([\n -1.0, 1.0, -1.0,\n -1.0, -1.0, -1.0,\n 1.0, 1.0, -1.0,\n 1.0, 1.0, 1.0,\n 1.0, -1.0, -1.0,\n 1.0, -1.0, 1.0\n])\n\nconst mappingIndices = new Uint16Array([\n 0, 1, 2,\n 1, 4, 2,\n 2, 4, 3,\n 4, 5, 3\n])\n\n/**\n * Mapped Aligned box buffer. Draws boxes where one side is always screen-space aligned.\n * Used to render cylinder imposters.\n * @interface\n */\nclass MappedAlignedBoxBuffer extends MappedBuffer {\n constructor(data: BufferData, params: Partial = {}) {\n super('v3', data, params)\n }\n get mapping () { return mapping }\n get mappingIndices () { return mappingIndices }\n get mappingIndicesSize () { return 12 }\n get mappingSize () { return 6 }\n get mappingItemSize () { return 3 }\n}\n\nexport default MappedAlignedBoxBuffer\n","/**\n * @file Cylinder Impostor Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Vector3 required for declaration only\nimport { Matrix4, Vector3 } from 'three'\n\nimport '../shader/CylinderImpostor.vert'\nimport '../shader/CylinderImpostor.frag'\n\nimport MappedAlignedBoxBuffer from './mappedalignedbox-buffer'\nimport { BufferDefaultParameters, BufferParameters, BufferParameterTypes, BufferTypes } from './buffer'\nimport { CylinderBufferData } from './cylinder-buffer'\n\nexport const CylinderImpostorBufferDefaultParameters = Object.assign({\n openEnded: false\n}, BufferDefaultParameters)\nexport type CylinderImpostorBufferParameters = BufferParameters & { openEnded: boolean }\n\nconst CylinderImpostorBufferParameterTypes = Object.assign({\n openEnded: { updateShader: true }\n}, BufferParameterTypes)\n\n/**\n * Cylinder impostor buffer.\n *\n * @example\n * var cylinderimpostorBuffer = new CylinderImpostorBuffer({\n * position1: new Float32Array([ 0, 0, 0 ]),\n * position2: new Float32Array([ 1, 1, 1 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * color2: new Float32Array([ 0, 1, 0 ]),\n * radius: new Float32Array([ 1 ])\n * });\n */\nclass CylinderImpostorBuffer extends MappedAlignedBoxBuffer {\n parameterTypes = CylinderImpostorBufferParameterTypes\n get defaultParameters() { return CylinderImpostorBufferDefaultParameters }\n parameters: CylinderImpostorBufferParameters\n\n isImpostor = true\n vertexShader = 'CylinderImpostor.vert'\n fragmentShader = 'CylinderImpostor.frag'\n\n /**\n * make cylinder impostor buffer\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position1 - from positions\n * @param {Float32Array} data.position2 - to positions\n * @param {Float32Array} data.color - from colors\n * @param {Float32Array} data.color2 - to colors\n * @param {Float32Array} data.radius - radii\n * @param {Picker} data.picking - picking ids\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: CylinderBufferData, params: Partial = {}) {\n super(data, params)\n\n this.addUniforms({\n 'modelViewMatrixInverse': { value: new Matrix4() },\n 'ortho': { value: 0.0 }\n })\n\n this.addAttributes({\n 'position1': { type: 'v3', value: null },\n 'position2': { type: 'v3', value: null },\n 'color2': { type: 'c', value: null },\n 'radius': { type: 'f', value: null }\n })\n\n this.setAttributes(data)\n this.makeMapping()\n }\n\n getDefines (type?: BufferTypes) {\n const defines = MappedAlignedBoxBuffer.prototype.getDefines.call(this, type)\n\n if (!this.parameters.openEnded) {\n defines.CAP = 1\n }\n\n return defines\n }\n}\n\nexport default CylinderImpostorBuffer\n","/**\n * @file Cylinder Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import required for declaration only\nimport { Vector3, Matrix4 } from 'three'\nimport { BufferRegistry, ExtensionFragDepth } from '../globals'\nimport CylinderGeometryBuffer, { CylinderGeometryBufferDefaultParameters, CylinderGeometryBufferParameters } from './cylindergeometry-buffer'\nimport CylinderImpostorBuffer, { CylinderImpostorBufferDefaultParameters, CylinderImpostorBufferParameters } from './cylinderimpostor-buffer'\nimport { BufferData } from './buffer'\n\nexport interface CylinderBufferData extends BufferData {\n position1: Float32Array\n position2: Float32Array\n color2: Float32Array\n radius: Float32Array\n}\n\nexport const CylinderBufferDefaultParameters = Object.assign({\n disableImpostor: false\n}, CylinderGeometryBufferDefaultParameters, CylinderImpostorBufferDefaultParameters)\nexport type CylinderBufferParameters = (CylinderGeometryBufferParameters & {disableImpostor: boolean}) | (CylinderImpostorBufferParameters & {disableImpostor: boolean})\n\nclass CylinderBufferImpl {\n constructor (data: CylinderBufferData, params: Partial = {}) {\n if (!data.color2 && data.color) data.color2 = data.color\n if (!ExtensionFragDepth || (params && params.disableImpostor)) {\n return new CylinderGeometryBuffer(data, params)\n } else {\n return new CylinderImpostorBuffer(data, params)\n }\n }\n}\n\n/**\n * Cylinder buffer. Depending on the value {@link ExtensionFragDepth} and\n * `params.disableImpostor` the constructor returns either a\n * {@link CylinderGeometryBuffer} or a {@link CylinderImpostorBuffer}\n * @implements {Buffer}\n *\n * @example\n * var cylinderBuffer = new CylinderBuffer({\n * position1: new Float32Array([ 0, 0, 0 ]),\n * position2: new Float32Array([ 1, 1, 1 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * color2: new Float32Array([ 0, 1, 0 ]),\n * radius: new Float32Array([ 1 ])\n * });\n */\n//@ts-expect-error Incompatible constructor signatures\nconst CylinderBuffer: {\n new(data: CylinderBufferData, params: Partial): CylinderGeometryBuffer | CylinderImpostorBuffer;\n} = CylinderBufferImpl;\n\ntype CylinderBuffer = CylinderGeometryBuffer | CylinderImpostorBuffer;\n\nBufferRegistry.add('cylinder', CylinderBuffer)\n\nexport default CylinderBuffer\n","/**\n * @file Axes Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { Color, Vector3 } from 'three'\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport { AxesPicker } from '../utils/picker'\nimport { uniformArray, uniformArray3 } from '../math/array-utils'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport SphereBuffer, { SphereBufferData, SphereBufferParameters } from '../buffer/sphere-buffer'\nimport CylinderBuffer, { CylinderBufferData } from '../buffer/cylinder-buffer'\nimport StructureView from '../structure/structure-view';\nimport Viewer from '../viewer/viewer';\nimport { Structure } from '../ngl';\nimport { AtomDataFields } from '../structure/structure-data';\nimport SphereGeometryBuffer from '../buffer/spheregeometry-buffer';\nimport CylinderGeometryBuffer from '../buffer/cylindergeometry-buffer';\nimport PrincipalAxes from '../math/principal-axes';\n\nexport interface AxesRepresentationParameters extends StructureRepresentationParameters {\n showAxes: boolean\n showBox: boolean\n}\n\n/**\n * Axes representation. Show principal axes and/or a box aligned with them\n * that fits the structure or selection.\n *\n * __Name:__ _axes_\n *\n * @example\n * stage.loadFile( \"rcsb://3pqr\", {\n * assembly: \"BU1\"\n * } ).then( function( o ){\n * o.addRepresentation( \"cartoon\" );\n * o.addRepresentation( \"axes\", {\n * sele: \"RET\", showAxes: false, showBox: true, radius: 0.2\n * } );\n * o.addRepresentation( \"ball+stick\", { sele: \"RET\" } );\n * o.addRepresentation( \"axes\", {\n * sele: \":B and backbone\", showAxes: false, showBox: true, radius: 0.2\n * } );\n * stage.autoView();\n * var pa = o.structure.getPrincipalAxes();\n * stage.animationControls.rotate( pa.getRotationQuaternion(), 1500 );\n * } );\n */\nclass AxesRepresentation extends StructureRepresentation {\n \n protected showAxes: boolean\n protected showBox: boolean\n protected sphereBuffer: SphereBuffer\n protected cylinderBuffer: CylinderBuffer\n /**\n * @param {Structure} structure - the structure object\n * @param {Viewer} viewer - the viewer object\n * @param {StructureRepresentationParameters} params - parameters object\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'axes'\n\n this.parameters = Object.assign({\n\n radiusSize: {\n type: 'number', precision: 3, max: 10.0, min: 0.001\n },\n sphereDetail: true,\n radialSegments: true,\n disableImpostor: true,\n showAxes: {\n type: 'boolean', rebuild: true\n },\n showBox: {\n type: 'boolean', rebuild: true\n }\n\n }, this.parameters, {\n assembly: null\n })\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n p.radiusSize = defaults(p.radiusSize, 0.5)\n p.colorValue = defaults(p.colorValue, 'lightgreen')\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n this.showAxes = defaults(p.showAxes, true)\n this.showBox = defaults(p.showBox, false)\n\n super.init(p)\n }\n\n getPrincipalAxes (): PrincipalAxes {\n let selection\n const assembly = this.getAssembly()\n\n if (assembly) {\n selection = assembly.partList[ 0 ].getSelection()\n }\n\n return this.structureView.getPrincipalAxes(selection)\n }\n\n getAxesData (sview: StructureView) {\n const pa = this.getPrincipalAxes()\n const c = new Color(this.colorValue)\n\n let vn = 0\n let en = 0\n\n if (this.showAxes) {\n vn += 6\n en += 3\n }\n\n if (this.showBox) {\n vn += 8\n en += 12\n }\n\n const vertexPosition = new Float32Array(3 * vn)\n const vertexColor = uniformArray3(vn, c.r, c.g, c.b)\n const vertexRadius = uniformArray(vn, this.radiusSize)\n\n const edgePosition1 = new Float32Array(3 * en)\n const edgePosition2 = new Float32Array(3 * en)\n const edgeColor = uniformArray3(en, c.r, c.g, c.b)\n const edgeRadius = uniformArray(en, this.radiusSize)\n\n let offset = 0\n\n if (this.showAxes) {\n const addAxis = function (v1: Vector3, v2: Vector3) {\n v1.toArray(vertexPosition as any, offset * 2)\n v2.toArray(vertexPosition as any, offset * 2 + 3)\n v1.toArray(edgePosition1 as any, offset)\n v2.toArray(edgePosition2 as any, offset)\n offset += 3\n }\n\n addAxis(pa.begA, pa.endA)\n addAxis(pa.begB, pa.endB)\n addAxis(pa.begC, pa.endC)\n }\n\n if (this.showBox) {\n const v = new Vector3()\n const { d1a, d2a, d3a, d1b, d2b, d3b } = pa.getProjectedScaleForAtoms(sview)\n\n // console.log(d1a, d2a, d3a, d1b, d2b, d3b)\n\n let offset2 = offset * 2\n const addCorner = function (d1: number, d2: number, d3: number) {\n v.copy(pa.center)\n .addScaledVector(pa.normVecA, d1)\n .addScaledVector(pa.normVecB, d2)\n .addScaledVector(pa.normVecC, d3)\n v.toArray(vertexPosition as any, offset2)\n offset2 += 3\n }\n addCorner(d1a, d2a, d3a)\n addCorner(d1a, d2a, d3b)\n addCorner(d1a, d2b, d3b)\n addCorner(d1a, d2b, d3a)\n addCorner(d1b, d2b, d3b)\n addCorner(d1b, d2b, d3a)\n addCorner(d1b, d2a, d3a)\n addCorner(d1b, d2a, d3b)\n\n let edgeOffset = offset\n const addEdge = function (a: number, b: number) {\n v.fromArray(vertexPosition as any, offset * 2 + a * 3)\n .toArray(edgePosition1 as any, edgeOffset)\n v.fromArray(vertexPosition as any, offset * 2 + b * 3)\n .toArray(edgePosition2 as any, edgeOffset)\n edgeOffset += 3\n }\n addEdge(0, 1)\n addEdge(0, 3)\n addEdge(0, 6)\n addEdge(1, 2)\n addEdge(1, 7)\n addEdge(2, 3)\n addEdge(2, 4)\n addEdge(3, 5)\n addEdge(4, 5)\n addEdge(4, 7)\n addEdge(5, 6)\n addEdge(6, 7)\n }\n\n const picker = new AxesPicker(pa)\n\n return {\n vertex: {\n position: vertexPosition,\n color: vertexColor,\n radius: vertexRadius,\n picking: picker\n },\n edge: {\n position1: edgePosition1,\n position2: edgePosition2,\n color: edgeColor,\n color2: edgeColor,\n radius: edgeRadius,\n picking: picker\n }\n }\n }\n\n create () {\n const axesData = this.getAxesData(this.structureView)\n\n this.sphereBuffer = new SphereBuffer(\n axesData.vertex as SphereBufferData,\n this.getBufferParams({\n sphereDetail: this.sphereDetail,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n }) as SphereBufferParameters\n )\n\n this.cylinderBuffer = new CylinderBuffer(\n axesData.edge as CylinderBufferData,\n this.getBufferParams({\n openEnded: true,\n radialSegments: this.radialSegments,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n })\n )\n\n this.dataList.push({\n sview: this.structureView,\n bufferList: [ this.sphereBuffer as SphereGeometryBuffer, this.cylinderBuffer as CylinderGeometryBuffer]\n })\n }\n\n createData (sview: StructureView): undefined {\n return\n }\n\n updateData (what: AtomDataFields, data: StructureRepresentationData) {\n const axesData = this.getAxesData(data.sview as StructureView)\n const sphereData = {}\n const cylinderData = {}\n\n if (!what || what.position) {\n Object.assign(sphereData, {\n position: axesData.vertex.position\n })\n Object.assign(cylinderData, {\n position1: axesData.edge.position1,\n position2: axesData.edge.position2\n })\n }\n\n if (!what || what.color) {\n Object.assign(sphereData, {\n color: axesData.vertex.color as Float32Array\n })\n Object.assign(cylinderData, {\n color: axesData.edge.color as Float32Array,\n color2: axesData.edge.color as Float32Array\n })\n }\n\n if (!what || what.radius) {\n Object.assign(sphereData, {\n radius: axesData.vertex.radius as Float32Array\n })\n Object.assign(cylinderData, {\n radius: axesData.edge.radius as Float32Array\n })\n }\n\n (this.sphereBuffer as SphereGeometryBuffer).setAttributes(sphereData);\n (this.cylinderBuffer as CylinderGeometryBuffer).setAttributes(cylinderData)\n }\n}\n\nRepresentationRegistry.add('axes', AxesRepresentation)\n\nexport default AxesRepresentation\n","/**\n * @file Ball And Stick Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport { ExtensionFragDepth, RepresentationRegistry } from '../globals'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport SphereBuffer, { SphereBufferData, SphereBufferParameters } from '../buffer/sphere-buffer'\nimport CylinderBuffer, { CylinderBufferData } from '../buffer/cylinder-buffer'\nimport WideLineBuffer from '../buffer/wideline-buffer'\nimport Viewer from '../viewer/viewer';\n// @ts-ignore: unused import Volume required for declaration only\nimport { Structure, Volume } from '../ngl';\nimport AtomProxy from '../proxy/atom-proxy';\nimport { AtomDataParams, BondDataParams, BondDataFields, AtomDataFields, BondData, AtomData } from '../structure/structure-data';\nimport StructureView from '../structure/structure-view';\nimport CylinderGeometryBuffer from '../buffer/cylindergeometry-buffer';\nimport SphereGeometryBuffer from '../buffer/spheregeometry-buffer';\n// @ts-ignore: unused import Surface required for declaration only\nimport Surface from '../surface/surface';\n\nexport interface BallAndStickRepresentationParameters extends StructureRepresentationParameters {\n sphereDetail: number\n radialSegments: number\n openEnded: boolean\n disableImpostor: boolean\n aspectRatio: number\n lineOnly: boolean\n lineWidth: number\n cylinderOnly: boolean\n multipleBond: 'off' | 'symmetric' | 'offset'\n bondSpacing: number\n bondScale: number\n linewidth: number\n}\n\n/**\n * Ball And Stick representation parameter object. Extends {@link RepresentationParameters} and\n * {@link StructureRepresentationParameters}.\n *\n * @typedef {Object} BallAndStickRepresentationParameters - ball and stick representation parameters\n *\n * @property {Integer} sphereDetail - sphere quality (icosahedron subdivisions)\n * @property {Integer} radialSegments - cylinder quality (number of segments)\n * @property {Boolean} openEnded - capped or not\n * @property {Boolean} disableImpostor - disable use of raycasted impostors for rendering\n * @property {Float} aspectRatio - size difference between atom and bond radii\n * @property {Boolean} lineOnly - render only bonds, and only as lines\n * @property {Integer} linewidth - width of lines\n * @property {Boolean} cylinderOnly - render only bonds (no atoms)\n * @property {String} multipleBond - one off \"off\", \"symmetric\", \"offset\"\n * @property {Float} bondSpacing - spacing for multiple bond rendering\n * @property {Float} bondScale - scale/radius for multiple bond rendering\n */\n\n/**\n * Ball And Stick representation. Show atoms as spheres and bonds as cylinders.\n *\n * __Name:__ _ball+stick_\n *\n * @example\n * stage.loadFile( \"rcsb://1crn\" ).then( function( o ){\n * o.addRepresentation( \"ball+stick\" );\n * o.autoView();\n * } );\n */\nclass BallAndStickRepresentation extends StructureRepresentation {\n protected sphereDetail: number\n protected radialSegments: number\n protected openEnded: boolean\n protected disableImpostor: boolean\n protected aspectRatio: number\n protected lineOnly: boolean\n protected lineWidth: number\n protected cylinderOnly: boolean\n protected multipleBond: 'off' | 'symmetric' | 'offset'\n protected bondSpacing: number\n protected bondScale: number\n protected linewidth: number\n\n protected lineBuffer: WideLineBuffer\n /**\n * Create Ball And Stick representation object\n * @param {Structure} structure - the structure to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {BallAndStickRepresentationParameters} params - ball and stick representation parameters\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'ball+stick'\n\n this.parameters = Object.assign({\n\n sphereDetail: true,\n radialSegments: true,\n openEnded: true,\n disableImpostor: true,\n aspectRatio: {\n type: 'number', precision: 1, max: 10.0, min: 1.0\n },\n lineOnly: {\n type: 'boolean', rebuild: true\n },\n cylinderOnly: {\n type: 'boolean', rebuild: true\n },\n multipleBond: {\n type: 'select',\n rebuild: true,\n options: {\n 'off': 'off',\n 'symmetric': 'symmetric',\n 'offset': 'offset'\n }\n },\n bondScale: {\n type: 'number', precision: 2, max: 1.0, min: 0.01\n },\n bondSpacing: {\n type: 'number', precision: 2, max: 2.0, min: 0.5\n },\n linewidth: {\n type: 'integer', max: 50, min: 1, buffer: true\n }\n\n }, this.parameters)\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n p.radiusType = defaults(p.radiusType, 'size')\n p.radiusSize = defaults(p.radiusSize, 0.15)\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n this.aspectRatio = defaults(p.aspectRatio, 2.0)\n this.lineOnly = defaults(p.lineOnly, false)\n this.cylinderOnly = defaults(p.cylinderOnly, false)\n this.multipleBond = defaults(p.multipleBond, 'off')\n this.bondSpacing = defaults(p.bondSpacing, 1.0)\n this.bondScale = defaults(p.bondScale, 0.4)\n this.linewidth = defaults(p.linewidth, 2)\n\n super.init(p)\n }\n\n getAtomRadius (atom: AtomProxy) {\n return this.aspectRatio * super.getAtomRadius(atom)\n }\n\n getAtomParams (what?: AtomDataFields, params?: Partial) {\n var p = super.getAtomParams(what, params)\n p.radiusParams.scale *= this.aspectRatio\n\n return p\n }\n\n getAtomData (sview: StructureView, what?: AtomDataFields, params?: Partial): AtomData {\n return sview.getAtomData(this.getAtomParams(what, params))\n }\n\n getBondParams (what?: BondDataFields, params?: Partial) {\n params = Object.assign({\n multipleBond: this.multipleBond,\n bondSpacing: this.bondSpacing,\n bondScale: this.bondScale\n }, params)\n\n return super.getBondParams(what, params)\n }\n\n getBondData (sview: StructureView, what?: BondDataFields, params?: Partial): BondData {\n return sview.getBondData(this.getBondParams(what, params))\n }\n\n createData (sview: StructureView) {\n const bufferList: any[] = []\n\n if (this.lineOnly) {\n this.lineBuffer = new WideLineBuffer(\n this.getBondData(sview, { position: true, color: true, picking: true }),\n this.getBufferParams({ linewidth: this.linewidth })\n )\n\n bufferList.push(this.lineBuffer)\n } else {\n const cylinderBuffer = new CylinderBuffer(\n (this.getBondData(sview) as CylinderBufferData),\n this.getBufferParams({\n openEnded: this.openEnded,\n radialSegments: this.radialSegments,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n })\n )\n\n bufferList.push(cylinderBuffer as CylinderGeometryBuffer)\n\n if (!this.cylinderOnly) {\n const sphereBuffer = new SphereBuffer(\n (this.getAtomData(sview) as SphereBufferData),\n (this.getBufferParams({\n sphereDetail: this.sphereDetail,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n }) as SphereBufferParameters)\n )\n\n bufferList.push(sphereBuffer as SphereGeometryBuffer)\n }\n }\n\n return {\n bufferList: bufferList\n }\n }\n\n updateData (what: BondDataFields | AtomDataFields, data: StructureRepresentationData) {\n if (this.multipleBond !== 'off' && what && what.radius) {\n what.position = true\n }\n\n const bondData = this.getBondData(data.sview as StructureView, what)\n\n if (this.lineOnly) {\n const lineData:Partial = {}\n\n if (!what || what.position) {\n Object.assign(lineData, {\n position1: bondData.position1,\n position2: bondData.position2\n })\n }\n\n if (!what || what.color) {\n Object.assign(lineData, {\n color: bondData.color,\n color2: bondData.color2\n })\n }\n\n data.bufferList[ 0 ].setAttributes(lineData)\n } else {\n var cylinderData: Partial = {}\n\n if (!what || what.position) {\n Object.assign(cylinderData, {\n position1: bondData.position1,\n position2: bondData.position2\n })\n }\n\n if (!what || what.color) {\n Object.assign(cylinderData, {\n color: bondData.color,\n color2: bondData.color2\n })\n }\n\n if (!what || what.radius) {\n Object.assign(cylinderData, {\n radius: bondData.radius\n })\n }\n\n data.bufferList[ 0 ].setAttributes(cylinderData)\n\n if (!this.cylinderOnly) {\n var atomData = this.getAtomData(data.sview as StructureView, what)\n\n var sphereData: Partial = {}\n\n if (!what || what.position) {\n Object.assign(sphereData, {\n position: atomData.position\n })\n }\n\n if (!what || what.color) {\n Object.assign(sphereData, {\n color: atomData.color\n })\n }\n\n if (!what || what.radius) {\n Object.assign(sphereData, {\n radius: atomData.radius\n })\n }\n\n data.bufferList[ 1 ].setAttributes(sphereData)\n }\n }\n }\n\n setParameters (params: Partial = {}) {\n let rebuild = false\n const what: AtomDataFields = {}\n\n if (params.aspectRatio || params.bondSpacing || params.bondScale) {\n Object.assign(what, {radius: true})\n if (!ExtensionFragDepth || this.disableImpostor) {\n rebuild = true\n }\n }\n\n super.setParameters(params, what, rebuild)\n\n return this\n }\n}\n\nRepresentationRegistry.add('ball+stick', BallAndStickRepresentation)\n\nexport default BallAndStickRepresentation\n","/**\n * @file Backbone Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport BallAndStickRepresentation, { BallAndStickRepresentationParameters } from './ballandstick-representation'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport AtomProxy from '../proxy/atom-proxy';\nimport StructureView from '../structure/structure-view';\nimport { AtomDataFields, AtomDataParams, BondDataFields, BondDataParams, BondData, AtomData } from '../structure/structure-data';\n\n/**\n * Backbone representation. Show cylinders (or lines) connecting .CA (protein)\n * or .C4'/.C3' (RNA/DNA) of polymers.\n *\n * __Name:__ _backbone_\n *\n * @example\n * stage.loadFile( \"rcsb://1sfi\" ).then( function( o ){\n * o.addRepresentation( \"backbone\" );\n * o.autoView();\n * } );\n */\nclass BackboneRepresentation extends BallAndStickRepresentation {\n /**\n * @param {Structure} structure - the structure object\n * @param {Viewer} viewer - the viewer object\n * @param {BallAndStickRepresentationParameters} params - parameters object\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'backbone'\n\n this.parameters = Object.assign({\n\n }, this.parameters, {\n\n multipleBond: null,\n bondSpacing: null\n\n })\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n p.aspectRatio = defaults(p.aspectRatio, 1.0)\n p.radiusSize = defaults(p.radiusSize, 0.25)\n\n super.init(p)\n }\n\n getAtomRadius (atom: AtomProxy) {\n return atom.isTrace() ? super.getAtomRadius(atom) : 0\n }\n\n getAtomData (sview: StructureView, what?: AtomDataFields, params?: Partial): AtomData {\n return sview.getBackboneAtomData(this.getAtomParams(what, params))\n }\n\n getBondData (sview: StructureView, what?: BondDataFields, params?: Partial): BondData {\n return sview.getBackboneBondData(this.getBondParams(what, params))\n }\n}\n\nRepresentationRegistry.add('backbone', BackboneRepresentation)\n\nexport default BackboneRepresentation\n","/**\n * @file Base Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport BallAndStickRepresentation, { BallAndStickRepresentationParameters } from './ballandstick-representation'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport StructureView from '../structure/structure-view';\nimport { AtomDataFields, AtomDataParams, BondDataFields, BondDataParams, BondData, AtomData } from '../structure/structure-data';\n\n/**\n * Base representation. Show cylinders for RNA/DNA ladders.\n *\n * __Name:__ _base_\n *\n * @example\n * stage.loadFile( \"rcsb://1d66\" ).then( function( o ){\n * o.addRepresentation( \"cartoon\", { sele: \"nucleic\" } );\n * o.addRepresentation( \"base\", { color: \"resname\" } );\n * o.autoView( \"nucleic\" );\n * } );\n */\nclass BaseRepresentation extends BallAndStickRepresentation {\n /**\n * @param {Structure} structure - the structure object\n * @param {Viewer} viewer - the viewer object\n * @param {BallAndStickRepresentationParameters} params - parameters object\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'base'\n\n this.parameters = Object.assign({\n\n }, this.parameters, {\n\n multipleBond: null,\n bondSpacing: null\n\n })\n }\n\n init (params: Partial) {\n let p = params || {}\n p.aspectRatio = defaults(p.aspectRatio, 1.0)\n p.radiusSize = defaults(p.radiusSize, 0.3)\n\n super.init(p)\n }\n\n getAtomData (sview: StructureView, what?: AtomDataFields, params?: AtomDataParams): AtomData {\n return sview.getRungAtomData(this.getAtomParams(what, params))\n }\n\n getBondData (sview: StructureView, what?: BondDataFields, params?: BondDataParams): BondData {\n let p = this.getBondParams(what, params)\n Object.assign(p.colorParams, {rung: true})\n\n return sview.getRungBondData(p)\n }\n}\n\nRepresentationRegistry.add('base', BaseRepresentation)\n\nexport default BaseRepresentation\n","/**\n * @file Spline\n * @author Alexander Rose \n * @private\n */\n\nimport { Vector3 } from 'three'\n\nimport { ColormakerRegistry } from '../globals'\nimport { AtomPicker } from '../utils/picker'\nimport RadiusFactory, { RadiusParams } from '../utils/radius-factory'\nimport { copyArray } from '../math/array-utils'\nimport { spline } from '../math/math-utils'\nimport Polymer from '../proxy/polymer';\nimport AtomProxy from '../proxy/atom-proxy';\nimport { ColormakerParameters } from '../color/colormaker';\nimport { NumberArray } from '../types';\n\nexport class Interpolator {\n \n m: number\n tension: number\n dt: number\n delta: number\n vec1: Vector3\n vec2: Vector3\n vDir: Vector3 \n vTan: Vector3\n vNorm: Vector3\n vBin: Vector3\n m2: number\n\n constructor (m: number, tension: number) {\n this.m = m\n this.tension = tension\n this.dt = 1.0 / this.m\n this.delta = 0.0001\n\n this.vec1 = new Vector3()\n this.vec2 = new Vector3()\n\n this.vDir = new Vector3()\n this.vTan = new Vector3()\n this.vNorm = new Vector3()\n this.vBin = new Vector3()\n \n this.m2 = Math.ceil(this.m / 2)\n }\n\n private interpolateToArr (v0: Vector3, v1: Vector3, v2: Vector3, v3: Vector3, t: number, arr: Float32Array, offset: number) {\n arr[ offset + 0 ] = spline(v0.x, v1.x, v2.x, v3.x, t, this.tension)\n arr[ offset + 1 ] = spline(v0.y, v1.y, v2.y, v3.y, t, this.tension)\n arr[ offset + 2 ] = spline(v0.z, v1.z, v2.z, v3.z, t, this.tension)\n }\n\n private interpolateToVec (v0: Vector3, v1: Vector3, v2: Vector3, v3: Vector3, t: number, vec: Vector3) {\n vec.x = spline(v0.x, v1.x, v2.x, v3.x, t, this.tension)\n vec.y = spline(v0.y, v1.y, v2.y, v3.y, t, this.tension)\n vec.z = spline(v0.z, v1.z, v2.z, v3.z, t, this.tension)\n }\n\n private interpolatePosition (v0: Vector3, v1: Vector3, v2: Vector3, v3: Vector3, pos: Float32Array, offset: number) {\n for (var j = 0; j < this.m; ++j) {\n var l = offset + j * 3\n var d = this.dt * j\n this.interpolateToArr(v0, v1, v2, v3, d, pos, l)\n }\n }\n\n private interpolateTangent (v0: Vector3, v1: Vector3, v2: Vector3, v3: Vector3, tan: Float32Array, offset: number) {\n for (var j = 0; j < this.m; ++j) {\n var d = this.dt * j\n var d1 = d - this.delta\n var d2 = d + this.delta\n var l = offset + j * 3\n // capping as a precaution\n if (d1 < 0) d1 = 0\n if (d2 > 1) d2 = 1\n //\n this.interpolateToVec(v0, v1, v2, v3, d1, this.vec1)\n this.interpolateToVec(v0, v1, v2, v3, d2, this.vec2)\n //\n this.vec2.sub(this.vec1).normalize()\n this.vec2.toArray(tan as any, l)\n }\n }\n\n private vectorSubdivide (interpolationFn: (v0: Vector3, v1: Vector3, v2: Vector3, v3: Vector3, array: Float32Array, offset: number) => void,\n iterator: AtomIterator, array: Float32Array, offset: number, isCyclic: boolean) {\n let v0: Vector3\n let v1 = iterator.next()\n let v2 = iterator.next()\n let v3 = iterator.next()\n //\n const n = iterator.size\n const n1 = n - 1\n let k = offset || 0\n for (let i = 0; i < n1; ++i) {\n v0 = v1\n v1 = v2\n v2 = v3\n v3 = iterator.next()\n interpolationFn.apply(this, [v0, v1, v2, v3, array, k])\n k += 3 * this.m\n }\n if (isCyclic) {\n v0 = iterator.get(n - 2)\n v1 = iterator.get(n - 1)\n v2 = iterator.get(0)\n v3 = iterator.get(1)\n interpolationFn.apply(this, [v0, v1, v2, v3, array, k])\n k += 3 * this.m\n }\n }\n\n //\n\n public getPosition (iterator: AtomIterator, array: Float32Array, offset: number, isCyclic: boolean) {\n iterator.reset()\n this.vectorSubdivide(this.interpolatePosition, iterator, array, offset, isCyclic)\n var n1 = iterator.size - 1\n var k = n1 * this.m * 3\n if (isCyclic) k += this.m * 3\n var v = iterator.get(isCyclic ? 0 : n1)\n array[ k ] = v.x\n array[ k + 1 ] = v.y\n array[ k + 2 ] = v.z\n }\n\n public getTangent (iterator: AtomIterator, array: Float32Array, offset: number, isCyclic: boolean) {\n iterator.reset()\n this.vectorSubdivide(this.interpolateTangent, iterator, array, offset, isCyclic)\n const n1 = iterator.size - 1\n let k = n1 * this.m * 3\n if (isCyclic) k += this.m * 3\n copyArray(array, array, k - 3, k, 3)\n }\n\n private interpolateNormalDir (u0: Vector3, u1: Vector3, u2: Vector3, u3: Vector3,\n v0: Vector3, v1: Vector3, v2: Vector3, v3: Vector3,\n tan: Float32Array, norm: Float32Array, bin: Float32Array,\n offset: number, shift: boolean) {\n for (let j = 0; j < this.m; ++j) {\n let l = offset + j * 3\n if (shift) l += this.m2 * 3\n const d = this.dt * j\n this.interpolateToVec(u0, u1, u2, u3, d, this.vec1)\n this.interpolateToVec(v0, v1, v2, v3, d, this.vec2)\n this.vDir.subVectors(this.vec2, this.vec1).normalize()\n this.vTan.fromArray(tan as any, l)\n this.vBin.crossVectors(this.vDir, this.vTan).normalize()\n this.vBin.toArray(bin as any, l)\n this.vNorm.crossVectors(this.vTan, this.vBin).normalize()\n this.vNorm.toArray(norm as any, l)\n }\n }\n\n private interpolateNormal (vDir: Vector3, tan: Float32Array, norm: Float32Array, bin: Float32Array, offset: number) {\n for (var j = 0; j < this.m; ++j) {\n var l = offset + j * 3\n vDir.copy(this.vNorm)\n this.vTan.fromArray(tan as any, l)\n this.vBin.crossVectors(vDir, this.vTan).normalize()\n this.vBin.toArray(bin as any, l)\n this.vNorm.crossVectors(this.vTan, this.vBin).normalize()\n this.vNorm.toArray(norm as any, l)\n }\n }\n\n public getNormal (size: number, tan: Float32Array, norm: Float32Array, bin: Float32Array, offset: number, isCyclic: boolean) {\n this.vNorm.set(0, 0, 1)\n const n = size\n const n1 = n - 1\n let k = offset || 0\n for (var i = 0; i < n1; ++i) {\n this.interpolateNormal(this.vDir, tan, norm, bin, k)\n k += 3 * this.m\n }\n if (isCyclic) {\n this.interpolateNormal(this.vDir, tan, norm, bin, k)\n k += 3 * this.m\n }\n this.vBin.toArray(bin as any, k)\n this.vNorm.toArray(norm as any, k)\n }\n\n public getNormalDir (iterDir1: AtomIterator, iterDir2: AtomIterator, tan: Float32Array, norm: Float32Array, bin: Float32Array, offset: number, isCyclic: boolean, shift: boolean) {\n iterDir1.reset()\n iterDir2.reset()\n //\n const vSub1 = new Vector3()\n const vSub2 = new Vector3()\n const vSub3 = new Vector3()\n const vSub4 = new Vector3()\n //\n const d1v1 = new Vector3()\n const d1v2 = new Vector3().copy(iterDir1.next())\n const d1v3 = new Vector3().copy(iterDir1.next())\n const d1v4 = new Vector3().copy(iterDir1.next())\n const d2v1 = new Vector3()\n const d2v2 = new Vector3().copy(iterDir2.next())\n const d2v3 = new Vector3().copy(iterDir2.next())\n const d2v4 = new Vector3().copy(iterDir2.next())\n //\n this.vNorm.set(0, 0, 1)\n let n = iterDir1.size\n let n1 = n - 1\n let k = offset || 0\n for (var i = 0; i < n1; ++i) {\n d1v1.copy(d1v2)\n d1v2.copy(d1v3)\n d1v3.copy(d1v4)\n d1v4.copy(iterDir1.next())\n d2v1.copy(d2v2)\n d2v2.copy(d2v3)\n d2v3.copy(d2v4)\n d2v4.copy(iterDir2.next())\n //\n if (i === 0) {\n vSub1.subVectors(d2v1, d1v1)\n vSub2.subVectors(d2v2, d1v2)\n if (vSub1.dot(vSub2) < 0) {\n vSub2.multiplyScalar(-1)\n d2v2.addVectors(d1v2, vSub2)\n }\n vSub3.subVectors(d2v3, d1v3)\n if (vSub2.dot(vSub3) < 0) {\n vSub3.multiplyScalar(-1)\n d2v3.addVectors(d1v3, vSub3)\n }\n } else {\n vSub3.copy(vSub4)\n }\n vSub4.subVectors(d2v4, d1v4)\n if (vSub3.dot(vSub4) < 0) {\n vSub4.multiplyScalar(-1)\n d2v4.addVectors(d1v4, vSub4)\n }\n this.interpolateNormalDir(\n d1v1, d1v2, d1v3, d1v4,\n d2v1, d2v2, d2v3, d2v4,\n tan, norm, bin, k, shift\n )\n k += 3 * this.m\n }\n if (isCyclic) {\n d1v1.copy(iterDir1.get(n - 2))\n d1v2.copy(iterDir1.get(n - 1))\n d1v3.copy(iterDir1.get(0))\n d1v4.copy(iterDir1.get(1))\n d2v1.copy(iterDir2.get(n - 2))\n d2v2.copy(iterDir2.get(n - 1))\n d2v3.copy(iterDir2.get(0))\n d2v4.copy(iterDir2.get(1))\n //\n vSub3.copy(vSub4)\n vSub4.subVectors(d2v4, d1v4)\n if (vSub3.dot(vSub4) < 0) {\n vSub4.multiplyScalar(-1)\n d2v4.addVectors(d1v4, vSub4)\n }\n this.interpolateNormalDir(\n d1v1, d1v2, d1v3, d1v4,\n d2v1, d2v2, d2v3, d2v4,\n tan, norm, bin, k, shift\n )\n k += 3 * this.m\n }\n if (shift) {\n // FIXME shift requires data from one this.more preceeding residue\n this.vBin.fromArray(bin as any, this.m2 * 3)\n this.vNorm.fromArray(norm as any, this.m2 * 3)\n for (var j = 0; j < this.m2; ++j) {\n this.vBin.toArray(bin as any, j * 3)\n this.vNorm.toArray(norm as any, j * 3)\n }\n } else {\n this.vBin.toArray(bin as any, k)\n this.vNorm.toArray(norm as any, k)\n }\n }\n\n //\n\n private interpolateColor (item1: AtomProxy, item2: AtomProxy, colFn: (...arg: any[]) => void, col: any, offset: number) {\n var j, l\n for (j = 0; j < this.m2; ++j) {\n l = offset + j * 3\n colFn.apply(this, [item1, col, l]) // itemColorToArray\n }\n for (j = this.m2; j < this.m; ++j) {\n l = offset + j * 3\n colFn.apply(this, [item2, col, l]) // itemColorToArray\n }\n }\n\n public getColor (iterator: AtomIterator, colFn: (...arg: any[]) => void, col: any, offset: number, isCyclic: boolean) {\n iterator.reset()\n iterator.next() // first element not needed\n let i0: AtomProxy\n let i1 = iterator.next()\n //\n var n = iterator.size\n var n1 = n - 1\n var k = offset || 0\n for (var i = 0; i < n1; ++i) {\n i0 = i1\n i1 = iterator.next()\n this.interpolateColor(i0, i1, colFn, col, k)\n k += 3 * this.m\n }\n if (isCyclic) {\n i0 = iterator.get(n - 1)\n i1 = iterator.get(0)\n this.interpolateColor(i0, i1, colFn, col, k)\n k += 3 * this.m\n }\n //\n col[ k ] = col[ k - 3 ]\n col[ k + 1 ] = col[ k - 2 ]\n col[ k + 2 ] = col[ k - 1 ]\n }\n\n //\n\n private interpolatePicking (item1: AtomProxy, item2: AtomProxy, pickFn: (item: AtomProxy) => number, pick: Float32Array, offset: number) {\n var j\n for (j = 0; j < this.m2; ++j) {\n pick[ offset + j ] = pickFn.apply(this, [item1])\n }\n for (j = this.m2; j < this.m; ++j) {\n pick[ offset + j ] = pickFn.apply(this, [item2])\n }\n }\n\n public getPicking (iterator: AtomIterator, pickFn: (item: AtomProxy) => number, pick: Float32Array, offset: number, isCyclic: boolean) {\n iterator.reset()\n iterator.next() // first element not needed\n let i0: AtomProxy\n let i1 = iterator.next()\n //\n const n = iterator.size\n const n1 = n - 1\n let k = offset || 0\n for (var i = 0; i < n1; ++i) {\n i0 = i1\n i1 = iterator.next()\n this.interpolatePicking(i0, i1, pickFn, pick, k)\n k += this.m\n }\n if (isCyclic) {\n i0 = iterator.get(n - 1)\n i1 = iterator.get(0)\n this.interpolatePicking(i0, i1, pickFn, pick, k)\n k += this.m\n }\n //\n pick[ k ] = pick[ k - 1 ]\n }\n\n //\n\n private interpolateSize (item1: AtomProxy, item2: AtomProxy, sizeFn: (item: AtomProxy) => number, size: Float32Array, offset: number) {\n const s1: number = sizeFn.apply(this, [item1])\n const s2: number = sizeFn.apply(this, [item2])\n for (let j = 0; j < this.m; ++j) {\n // linear interpolation\n let t = j / this.m\n size[ offset + j ] = (1 - t) * s1 + t * s2\n }\n }\n\n public getSize (iterator: AtomIterator, sizeFn: (item: AtomProxy) => number, size: Float32Array, offset: number, isCyclic: boolean) {\n iterator.reset()\n iterator.next() // first element not needed\n let i0: AtomProxy\n let i1: AtomProxy = iterator.next()\n //\n const n = iterator.size\n const n1 = n - 1\n let k = offset || 0\n for (var i = 0; i < n1; ++i) {\n i0 = i1\n i1 = iterator.next()\n this.interpolateSize(i0, i1, sizeFn, size, k)\n k += this.m\n }\n if (isCyclic) {\n i0 = iterator.get(n - 1)\n i1 = iterator.get(0)\n this.interpolateSize(i0, i1, sizeFn, size, k)\n k += this.m\n }\n //\n size[ k ] = size[ k - 1 ]\n }\n}\n\nexport interface SplineParameters {\n directional?: boolean\n positionIterator?: boolean\n subdiv?: number\n smoothSheet?: boolean\n tension?: number\n}\nexport interface AtomIterator {\n size: number,\n next: () => AtomProxy | Vector3,\n get: (idx: number) => AtomProxy | Vector3,\n reset: () => void\n}\nclass Spline {\n\n polymer: Polymer\n size: number\n directional: boolean\n positionIterator: any\n subdiv: number\n smoothSheet: boolean\n tension: number\n interpolator: Interpolator\n\n constructor (polymer: Polymer, params?: SplineParameters) {\n this.polymer = polymer\n this.size = polymer.residueCount\n\n var p = params || {}\n this.directional = p.directional || false\n this.positionIterator = p.positionIterator || false\n this.subdiv = p.subdiv || 1\n this.smoothSheet = p.smoothSheet || false\n\n if (!p.tension) {\n this.tension = this.polymer.isNucleic() ? 0.5 : 0.9\n } else {\n this.tension = p.tension\n }\n\n this.interpolator = new Interpolator(this.subdiv, this.tension)\n }\n\n getAtomIterator (type: string, smooth?: boolean): AtomIterator {\n const polymer = this.polymer\n const structure = polymer.structure\n const n = polymer.residueCount\n\n let i = 0\n let j = -1\n\n const cache = [\n structure.getAtomProxy(),\n structure.getAtomProxy(),\n structure.getAtomProxy(),\n structure.getAtomProxy()\n ]\n\n const cache2 = [\n new Vector3(),\n new Vector3(),\n new Vector3(),\n new Vector3()\n ]\n\n function next () {\n var atomProxy = get(j)\n j += 1\n return atomProxy\n }\n\n var apPrev = structure.getAtomProxy()\n var apNext = structure.getAtomProxy()\n\n function get (idx: number) {\n var atomProxy = cache[ i % 4 ]\n atomProxy.index = polymer.getAtomIndexByType(idx, type) as number\n if (smooth && idx > 0 && idx < n && atomProxy.sstruc === 'e') {\n var vec = cache2[ i % 4 ]\n apPrev.index = polymer.getAtomIndexByType(idx + 1, type) as number\n apNext.index = polymer.getAtomIndexByType(idx - 1, type) as number\n vec.addVectors(apPrev as any, apNext as any)\n .add(atomProxy as any).add(atomProxy as any)\n .multiplyScalar(0.25)\n i += 1\n return vec\n }\n i += 1\n return atomProxy\n }\n\n function reset () {\n i = 0\n j = -1\n }\n\n return {\n size: n,\n next: next,\n get: get,\n reset: reset\n }\n }\n\n getSubdividedColor (params: {scheme: string, [k: string]: any } & ColormakerParameters) {\n var m = this.subdiv\n var polymer = this.polymer\n var n = polymer.residueCount\n var n1 = n - 1\n var nCol = n1 * m * 3 + 3\n if (polymer.isCyclic) nCol += m * 3\n\n var col = new Float32Array(nCol)\n var iterator = this.getAtomIterator('trace')\n\n var p = params || {}\n p.structure = polymer.structure\n\n var colormaker = ColormakerRegistry.getScheme(p)\n\n function colFn (item: AtomProxy, array: NumberArray, offset: number) {\n colormaker.atomColorToArray(item, array, offset)\n }\n\n this.interpolator.getColor(\n iterator, colFn, col, 0, polymer.isCyclic\n )\n\n return {\n 'color': col\n }\n }\n \n getSubdividedPicking () {\n var m = this.subdiv\n var polymer = this.polymer\n var n = polymer.residueCount\n var n1 = n - 1\n var nCol = n1 * m + 1\n if (polymer.isCyclic) nCol += m\n\n var structure = polymer.structure\n var iterator = this.getAtomIterator('trace')\n var pick = new Float32Array(nCol)\n\n function pickFn (item: AtomProxy) {\n return item.index\n }\n\n this.interpolator.getPicking(\n iterator, pickFn, pick, 0, polymer.isCyclic\n )\n\n return {\n 'picking': new AtomPicker(pick, structure)\n }\n }\n\n getSubdividedPosition () {\n var pos = this.getPosition()\n\n return {\n 'position': pos\n }\n }\n \n getSubdividedOrientation () {\n const tan = this.getTangent()\n const normals = this.getNormals(tan)\n\n return {\n 'tangent': tan,\n 'normal': normals.normal,\n 'binormal': normals.binormal\n }\n }\n\n getSubdividedSize (params: RadiusParams) {\n var m = this.subdiv\n var polymer = this.polymer\n var n = polymer.residueCount\n var n1 = n - 1\n var nSize = n1 * m + 1\n if (polymer.isCyclic) nSize += m\n\n var size = new Float32Array(nSize)\n var iterator = this.getAtomIterator('trace')\n\n var radiusFactory = new RadiusFactory(params)\n\n function sizeFn (item: AtomProxy) {\n return radiusFactory.atomRadius(item)\n }\n\n this.interpolator.getSize(\n iterator, sizeFn, size, 0, polymer.isCyclic\n )\n\n return {\n 'size': size\n }\n }\n\n getPosition () {\n const m = this.subdiv\n const polymer = this.polymer\n const n = polymer.residueCount\n const n1 = n - 1\n let nPos = n1 * m * 3 + 3\n if (polymer.isCyclic) nPos += m * 3\n\n const pos = new Float32Array(nPos)\n const iterator = this.positionIterator || this.getAtomIterator('trace', this.smoothSheet)\n\n this.interpolator.getPosition(iterator, pos, 0, polymer.isCyclic)\n\n return pos\n }\n\n getTangent () {\n const m = this.subdiv\n const polymer = this.polymer\n const n = this.size\n const n1 = n - 1\n let nTan = n1 * m * 3 + 3\n if (polymer.isCyclic) nTan += m * 3\n\n const tan = new Float32Array(nTan)\n const iterator = this.positionIterator || this.getAtomIterator('trace', this.smoothSheet)\n\n this.interpolator.getTangent(iterator, tan, 0, polymer.isCyclic)\n\n return tan\n }\n\n getNormals (tan: Float32Array) {\n const m = this.subdiv\n const polymer = this.polymer\n const isProtein = polymer.isProtein()\n const n = this.size\n const n1 = n - 1\n let nNorm = n1 * m * 3 + 3\n if (polymer.isCyclic) nNorm += m * 3\n\n const norm = new Float32Array(nNorm)\n const bin = new Float32Array(nNorm)\n\n if (this.directional && !this.polymer.isCg()) {\n const iterDir1 = this.getAtomIterator('direction1')\n const iterDir2 = this.getAtomIterator('direction2')\n this.interpolator.getNormalDir(\n iterDir1, iterDir2, tan, norm, bin, 0, polymer.isCyclic, isProtein\n )\n } else {\n this.interpolator.getNormal(\n n, tan, norm, bin, 0, polymer.isCyclic\n )\n }\n\n return {\n 'normal': norm,\n 'binormal': bin\n }\n }\n\n}\n\nexport default Spline\n","/**\n * @file Tube Mesh Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Matrix4 required for declaration only\nimport { Vector3, Matrix4 } from 'three'\n\nimport { defaults, getUintArray } from '../utils'\nimport { serialArray } from '../math/array-utils'\nimport MeshBuffer from './mesh-buffer'\nimport { BufferDefaultParameters, BufferData, BufferParameters } from './buffer'\nimport {Log} from \"../globals\";\n\nconst vTangent = new Vector3()\nconst vMeshNormal = new Vector3()\n\nexport interface TubeMeshBufferData extends BufferData {\n binormal: Float32Array\n tangent: Float32Array\n size: Float32Array\n}\n\nexport const TubeMeshBufferDefaultParameters = Object.assign({\n radialSegments: 4,\n capped: false,\n aspectRatio: 1.0\n}, BufferDefaultParameters)\nexport type TubeMeshBufferParameters = BufferParameters & {\n radialSegments: number,\n capped: boolean,\n aspectRatio: number\n}\n\nfunction getData (data: TubeMeshBufferData, params: Partial = {}) {\n const radialSegments = defaults(params.radialSegments, 4)\n const capped = defaults(params.capped, false)\n\n const capVertices = capped ? radialSegments : 0\n const capTriangles = capped ? radialSegments - 2 : 0\n\n const n = data.position!.length / 3\n const n1 = n - 1\n const x = n * radialSegments * 3 + 2 * capVertices * 3\n const xi = n1 * 2 * radialSegments * 3 + 2 * capTriangles * 3\n\n return {\n position: new Float32Array(x),\n color: new Float32Array(x),\n index: getUintArray(xi, x / 3),\n normal: new Float32Array(x),\n picking: data.picking\n }\n}\n\n/**\n * Tube mesh buffer. Draws a tube.\n */\nclass TubeMeshBuffer extends MeshBuffer {\n get defaultParameters() { return TubeMeshBufferDefaultParameters }\n parameters: TubeMeshBufferParameters\n\n capVertices: number\n capTriangles: number\n size2: number\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.normal - normals\n * @param {Float32Array} data.binormal - binormals\n * @param {Float32Array} data.tangent - tangents\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} data.size - sizes\n * @param {Picker} data.picking - picking ids\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: TubeMeshBufferData, params: Partial = {}) {\n super(getData(data, params), params)\n\n this.capVertices = this.parameters.capped ? this.parameters.radialSegments : 0\n this.capTriangles = this.parameters.capped ? this.parameters.radialSegments - 2 : 0\n\n this.size2 = data.position!.length / 3\n data.primitiveId = serialArray(this.size2)\n\n this.setAttributes(data)\n this.makeIndex()\n }\n\n setAttributes (data: Partial = {}) {\n const aspectRatio = this.parameters.aspectRatio\n\n const n = this.size2\n const n1 = n - 1\n const radialSegments = this.parameters.radialSegments\n\n const attributes = this.geometry.attributes as any\n\n let position, normal, binormal, tangent, color, size, primitiveId\n let meshPosition, meshColor, meshNormal, meshPrimitiveId\n\n if (data.position) {\n position = data.position\n normal = data.normal\n binormal = data.binormal\n tangent = data.tangent\n size = data.size\n\n meshPosition = attributes.position.array\n meshNormal = attributes.normal.array\n\n attributes.position.needsUpdate = true\n attributes.normal.needsUpdate = true\n }\n\n if (data.color) {\n color = data.color\n meshColor = attributes.color.array\n attributes.color.needsUpdate = true\n }\n\n if (data.primitiveId) {\n primitiveId = data.primitiveId\n meshPrimitiveId = attributes.primitiveId.array\n attributes.primitiveId.needsUpdate = true\n }\n\n let k, l\n let radius = 0\n\n let normX = 0\n let normY = 0\n let normZ = 0\n let biX = 0\n let biY = 0\n let biZ = 0\n let posX = 0\n let posY = 0\n let posZ = 0\n\n const cxArr = []\n const cyArr = []\n const cx1Arr = []\n const cy1Arr = []\n const cx2Arr = []\n const cy2Arr = []\n\n if (position) {\n for (let j = 0; j < radialSegments; ++j) {\n const v = (j / radialSegments) * 2 * Math.PI\n\n cxArr[ j ] = aspectRatio * Math.cos(v)\n cyArr[ j ] = Math.sin(v)\n\n cx1Arr[ j ] = aspectRatio * Math.cos(v - 0.01)\n cy1Arr[ j ] = Math.sin(v - 0.01)\n cx2Arr[ j ] = aspectRatio * Math.cos(v + 0.01)\n cy2Arr[ j ] = Math.sin(v + 0.01)\n }\n }\n\n for (let i = 0; i < n; ++i) {\n k = i * 3\n l = k * radialSegments\n\n if (position && tangent && normal && binormal && size) {\n vTangent.set(\n tangent[ k ], tangent[ k + 1 ], tangent[ k + 2 ]\n )\n\n normX = normal[ k ]\n normY = normal[ k + 1 ]\n normZ = normal[ k + 2 ]\n\n biX = binormal[ k ]\n biY = binormal[ k + 1 ]\n biZ = binormal[ k + 2 ]\n\n posX = position[ k ]\n posY = position[ k + 1 ]\n posZ = position[ k + 2 ]\n\n radius = size[ i ]\n }\n\n for (let j = 0; j < radialSegments; ++j) {\n const s = l + j * 3\n\n if (position) {\n const cx = -radius * cxArr[ j ] // TODO: Hack: Negating it so it faces outside.\n const cy = radius * cyArr[ j ]\n\n const cx1 = -radius * cx1Arr[ j ]\n const cy1 = radius * cy1Arr[ j ]\n const cx2 = -radius * cx2Arr[ j ]\n const cy2 = radius * cy2Arr[ j ]\n\n meshPosition[ s ] = posX + cx * normX + cy * biX\n meshPosition[ s + 1 ] = posY + cx * normY + cy * biY\n meshPosition[ s + 2 ] = posZ + cx * normZ + cy * biZ\n\n // TODO half of these are symmetric\n vMeshNormal.set(\n // ellipse tangent approximated as vector from/to adjacent points\n (cx2 * normX + cy2 * biX) - (cx1 * normX + cy1 * biX),\n (cx2 * normY + cy2 * biY) - (cx1 * normY + cy1 * biY),\n (cx2 * normZ + cy2 * biZ) - (cx1 * normZ + cy1 * biZ)\n ).cross(vTangent)\n\n meshNormal[ s ] = vMeshNormal.x\n meshNormal[ s + 1 ] = vMeshNormal.y\n meshNormal[ s + 2 ] = vMeshNormal.z\n }\n\n if (color) {\n meshColor[ s ] = color[ k ]\n meshColor[ s + 1 ] = color[ k + 1 ]\n meshColor[ s + 2 ] = color[ k + 2 ]\n }\n\n if (primitiveId) {\n meshPrimitiveId[ i * radialSegments + j ] = primitiveId[ i ]\n }\n }\n }\n\n // front cap\n\n k = 0\n l = n * 3 * radialSegments\n\n for (let j = 0; j < radialSegments; ++j) {\n const s = k + j * 3\n const t = l + j * 3\n\n if (position && tangent) {\n meshPosition[ t ] = meshPosition[ s ]\n meshPosition[ t + 1 ] = meshPosition[ s + 1 ]\n meshPosition[ t + 2 ] = meshPosition[ s + 2 ]\n\n meshNormal[ t ] = tangent[ k ]\n meshNormal[ t + 1 ] = tangent[ k + 1 ]\n meshNormal[ t + 2 ] = tangent[ k + 2 ]\n }\n\n if (color) {\n meshColor[ t ] = meshColor[ s ]\n meshColor[ t + 1 ] = meshColor[ s + 1 ]\n meshColor[ t + 2 ] = meshColor[ s + 2 ]\n }\n\n if (primitiveId) {\n meshPrimitiveId[ n * radialSegments + j ] = meshPrimitiveId[ 0 + j ]\n }\n }\n\n // back cap\n\n k = (n - 1) * 3 * radialSegments\n l = (n + 1) * 3 * radialSegments\n\n for (let j = 0; j < radialSegments; ++j) {\n const s = k + j * 3\n const t = l + j * 3\n\n if (position && tangent) {\n meshPosition[ t ] = meshPosition[ s ]\n meshPosition[ t + 1 ] = meshPosition[ s + 1 ]\n meshPosition[ t + 2 ] = meshPosition[ s + 2 ]\n\n meshNormal[ t ] = tangent[ n1 * 3 ]\n meshNormal[ t + 1 ] = tangent[ n1 * 3 + 1 ]\n meshNormal[ t + 2 ] = tangent[ n1 * 3 + 2 ]\n }\n\n if (color) {\n meshColor[ t ] = meshColor[ s ]\n meshColor[ t + 1 ] = meshColor[ s + 1 ]\n meshColor[ t + 2 ] = meshColor[ s + 2 ]\n }\n\n if (primitiveId) {\n meshPrimitiveId[ (n + 1) * radialSegments + j ] = meshPrimitiveId[ (n - 1) * radialSegments + j ]\n }\n }\n }\n\n makeIndex () {\n const index = this.geometry.getIndex()\n if (!index) { Log.error('Index is null'); return; }\n const meshIndex = index.array as Uint32Array|Uint16Array\n\n const n = this.size2\n const n1 = n - 1\n const capTriangles = this.capTriangles\n const radialSegments = this.parameters.radialSegments\n const radialSegments1 = this.parameters.radialSegments + 1\n\n let k, l\n\n for (let i = 0; i < n1; ++i) {\n const k = i * radialSegments * 3 * 2\n\n const irs = i * radialSegments\n const irs1 = (i + 1) * radialSegments\n\n for (let j = 0; j < radialSegments; ++j) {\n l = k + j * 3 * 2\n\n // meshIndex[ l + 0 ] = irs + ( ( j + 0 ) % radialSegments );\n meshIndex[ l ] = irs + j\n meshIndex[ l + 1 ] = irs + ((j + 1) % radialSegments)\n // meshIndex[ l + 2 ] = irs1 + ( ( j + 0 ) % radialSegments );\n meshIndex[ l + 2 ] = irs1 + j\n\n // meshIndex[ l + 3 ] = irs1 + ( ( j + 0 ) % radialSegments );\n meshIndex[ l + 3 ] = irs1 + j\n meshIndex[ l + 4 ] = irs + ((j + 1) % radialSegments)\n meshIndex[ l + 5 ] = irs1 + ((j + 1) % radialSegments)\n }\n }\n\n // capping\n\n const strip = [ 0 ]\n\n for (let j = 1; j < radialSegments1 / 2; ++j) {\n strip.push(j)\n if (radialSegments - j !== j) {\n strip.push(radialSegments - j)\n }\n }\n\n // front cap\n\n l = n1 * radialSegments * 3 * 2\n k = n * radialSegments\n\n for (let j = 0; j < strip.length - 2; ++j) {\n if (j % 2 === 0) {\n meshIndex[ l + j * 3 + 0 ] = k + strip[ j + 0 ]\n meshIndex[ l + j * 3 + 1 ] = k + strip[ j + 1 ]\n meshIndex[ l + j * 3 + 2 ] = k + strip[ j + 2 ]\n } else {\n meshIndex[ l + j * 3 + 0 ] = k + strip[ j + 2 ]\n meshIndex[ l + j * 3 + 1 ] = k + strip[ j + 1 ]\n meshIndex[ l + j * 3 + 2 ] = k + strip[ j + 0 ]\n }\n }\n\n // back cap\n\n l = n1 * radialSegments * 3 * 2 + 3 * capTriangles\n k = n * radialSegments + radialSegments\n\n for (let j = 0; j < strip.length - 2; ++j) {\n if (j % 2 === 0) {\n meshIndex[ l + j * 3 + 0 ] = k + strip[ j + 0 ]\n meshIndex[ l + j * 3 + 1 ] = k + strip[ j + 1 ]\n meshIndex[ l + j * 3 + 2 ] = k + strip[ j + 2 ]\n } else {\n meshIndex[ l + j * 3 + 0 ] = k + strip[ j + 2 ]\n meshIndex[ l + j * 3 + 1 ] = k + strip[ j + 1 ]\n meshIndex[ l + j * 3 + 2 ] = k + strip[ j + 0 ]\n }\n }\n }\n}\n\nexport default TubeMeshBuffer\n","/**\n * @file Cartoon Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport { Debug, Log, RepresentationRegistry } from '../globals'\nimport Spline from '../geometry/spline'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport TubeMeshBuffer from '../buffer/tubemesh-buffer'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport Polymer from '../proxy/polymer';\nimport AtomProxy from '../proxy/atom-proxy';\nimport StructureView from '../structure/structure-view';\nimport Buffer from '../buffer/buffer';\n\nexport interface CartoonRepresentationParameters extends StructureRepresentationParameters {\n aspectRatio: number\n subdiv: number\n radialSegments: number\n tension: number\n capped: boolean\n smoothSheet: boolean\n}\n\n/**\n * Cartoon representation. Show a thick ribbon that\n * smoothly connecting backbone atoms in polymers.\n *\n * __Name:__ _cartoon_\n *\n * @example\n * stage.loadFile( \"rcsb://1crn\" ).then( function( o ){\n * o.addRepresentation( \"cartoon\" );\n * o.autoView();\n * } );\n */\nclass CartoonRepresentation extends StructureRepresentation {\n protected aspectRatio: number\n protected tension: number\n protected capped: boolean\n protected smoothSheet: boolean\n protected subdiv: number\n \n /**\n * Create Cartoon representation object\n * @param {Structure} structure - the structure to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {StructureRepresentationParameters} params - representation parameters\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'cartoon'\n\n this.parameters = Object.assign({\n\n aspectRatio: {\n type: 'number', precision: 1, max: 10.0, min: 1.0, rebuild: true\n },\n subdiv: {\n type: 'integer', max: 50, min: 1, rebuild: true\n },\n radialSegments: {\n type: 'integer', max: 50, min: 1, rebuild: true\n },\n tension: {\n type: 'number', precision: 1, max: 1.0, min: 0.1\n },\n capped: {\n type: 'boolean', rebuild: true\n },\n smoothSheet: {\n type: 'boolean', rebuild: true\n }\n\n }, this.parameters)\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n p.colorScheme = defaults(p.colorScheme, 'chainname')\n p.colorScale = defaults(p.colorScale, 'RdYlBu')\n p.radiusType = defaults(p.radiusType, 'sstruc')\n p.radiusScale = defaults(p.radiusScale, 0.7)\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n this.aspectRatio = defaults(p.aspectRatio, 5.0)\n this.tension = defaults(p.tension, NaN)\n this.capped = defaults(p.capped, true)\n this.smoothSheet = defaults(p.smoothSheet, false)\n\n if (p.quality === 'low') {\n this.subdiv = 3\n this.radialSegments = 6\n } else if (p.quality === 'medium') {\n this.subdiv = 6\n } else if (p.quality === 'high') {\n this.subdiv = 12\n } else {\n this.subdiv = defaults(p.subdiv, 6)\n }\n\n super.init(p)\n }\n\n getSplineParams (params?: Partial) {\n return Object.assign({\n subdiv: this.subdiv,\n tension: this.tension,\n directional: this.aspectRatio !== 1.0,\n smoothSheet: this.smoothSheet\n }, params)\n }\n\n getSpline (polymer: Polymer): Spline {\n return new Spline(polymer, this.getSplineParams())\n }\n\n getAspectRatio (polymer: Polymer): number {\n return polymer.isCg() ? 1.0 : this.aspectRatio\n }\n\n getAtomRadius (atom: AtomProxy): number {\n return atom.isTrace() ? super.getAtomRadius(atom) : 0\n }\n\n createData (sview: StructureView) {\n let bufferList: Buffer[] = []\n let polymerList: Polymer[] = []\n\n this.structure.eachPolymer(polymer => {\n if (polymer.residueCount < 4) return\n polymerList.push(polymer)\n\n const spline = this.getSpline(polymer)\n const aspectRatio = this.getAspectRatio(polymer)\n\n const subPos = spline.getSubdividedPosition()\n const subOri = spline.getSubdividedOrientation()\n const subCol = spline.getSubdividedColor(this.getColorParams())\n const subPick = spline.getSubdividedPicking()\n const subSize = spline.getSubdividedSize(this.getRadiusParams())\n\n bufferList.push(\n new TubeMeshBuffer(\n Object.assign({}, subPos, subOri, subCol, subPick, subSize),\n this.getBufferParams({\n radialSegments: this.radialSegments,\n aspectRatio: aspectRatio,\n capped: this.capped\n })\n )\n )\n }, sview.getSelection())\n\n return {\n bufferList: bufferList,\n polymerList: polymerList\n }\n }\n\n updateData (what: any, data: StructureRepresentationData) {\n if (Debug) Log.time(this.type + ' repr update')\n\n what = what || {}\n\n for (var i = 0, il = data.polymerList!.length; i < il; ++i) {\n var bufferData: {[key: string]: any} = {}\n var polymer = data.polymerList![ i ]\n var spline = this.getSpline(polymer)\n var aspectRatio = this.getAspectRatio(polymer)\n\n Object.assign(data.bufferList[ i ], {aspectRatio: aspectRatio})\n\n if (what.position || what.radius) {\n var subPos = spline.getSubdividedPosition()\n var subOri = spline.getSubdividedOrientation()\n var subSize = spline.getSubdividedSize(this.getRadiusParams(aspectRatio))\n\n bufferData.position = subPos.position\n bufferData.normal = subOri.normal\n bufferData.binormal = subOri.binormal\n bufferData.tangent = subOri.tangent\n bufferData.size = subSize.size\n }\n\n if (what.color) {\n var subCol = spline.getSubdividedColor(this.getColorParams())\n bufferData.color = subCol.color\n }\n\n if (what.picking) {\n var subPick = spline.getSubdividedPicking()\n bufferData.picking = subPick.picking\n }\n\n data.bufferList[ i ].setAttributes(bufferData)\n }\n\n if (Debug) Log.timeEnd(this.type + ' repr update')\n }\n\n setParameters (params: Partial) {\n const rebuild = false\n var what: {[k: string]: any} = {}\n\n if (params && params.aspectRatio) {\n what.radius = true\n }\n\n if (params && params.tension) {\n what.position = true\n }\n\n super.setParameters(params, what, rebuild)\n\n return this\n }\n}\n\nRepresentationRegistry.add('cartoon', CartoonRepresentation)\n\nexport default CartoonRepresentation\n","/**\n * @file Contact Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport { RepresentationRegistry } from '../globals'\nimport StructureRepresentation, { StructureRepresentationParameters } from './structure-representation'\nimport { calculateContacts, getContactData, getLabelData } from '../chemistry/interactions/contact'\nimport CylinderBuffer from '../buffer/cylinder-buffer'\nimport TextBuffer from '../buffer/text-buffer'\nimport { getFixedCountDashData } from '../geometry/dash'\nimport Viewer from '../viewer/viewer';\nimport { Structure } from '../ngl';\nimport StructureView from '../structure/structure-view';\nimport CylinderGeometryBuffer from '../buffer/cylindergeometry-buffer';\nimport CylinderImpostorBuffer from '../buffer/cylinderimpostor-buffer';\n// @ts-ignore: unused import ContactPicker required for declaration only\nimport { ContactPicker } from '../utils/picker';\n\nexport interface ContactRepresentationParameters extends StructureRepresentationParameters {\n hydrogenBond: boolean\n weakHydrogenBond: boolean\n waterHydrogenBond: boolean\n backboneHydrogenBond: boolean\n hydrophobic: boolean\n halogenBond: boolean\n ionicInteraction: boolean\n metalCoordination: boolean\n cationPi: boolean\n piStacking: boolean\n filterSele: string|[string, string]\n maxHydrophobicDist: number\n maxHbondDist: number\n maxHbondSulfurDist: number\n maxHbondAccAngle: number\n maxHbondDonAngle: number\n maxHbondAccPlaneAngle: number\n maxHbondDonPlaneAngle: number\n maxPiStackingDist: number\n maxPiStackingOffset: number\n maxPiStackingAngle: number\n maxCationPiDist: number\n maxCationPiOffset: number\n maxIonicDist: number\n maxHalogenBondDist: number\n maxHalogenBondAngle: number\n maxMetalDist: number\n refineSaltBridges: boolean\n masterModelIndex: number\n lineOfSightDistFactor: number\n}\n\n/**\n * Contact representation.\n */\nclass ContactRepresentation extends StructureRepresentation {\n protected hydrogenBond: boolean\n protected weakHydrogenBond: boolean\n protected waterHydrogenBond: boolean\n protected backboneHydrogenBond: boolean\n protected hydrophobic: boolean\n protected halogenBond: boolean\n protected ionicInteraction: boolean\n protected metalCoordination: boolean\n protected cationPi: boolean\n protected piStacking: boolean\n protected filterSele: string|[string, string]\n protected maxHydrophobicDist: number\n protected maxHbondDist: number\n protected maxHbondSulfurDist: number\n protected maxHbondAccAngle: number\n protected maxHbondDonAngle: number\n protected maxHbondAccPlaneAngle: number\n protected maxHbondDonPlaneAngle: number\n protected maxPiStackingDist: number\n protected maxPiStackingOffset: number\n protected maxPiStackingAngle: number\n protected maxCationPiDist: number\n protected maxCationPiOffset: number\n protected maxIonicDist: number\n protected maxHalogenBondDist: number\n protected maxHalogenBondAngle: number\n protected maxMetalDist: number\n protected refineSaltBridges: boolean\n protected masterModelIndex: number\n protected lineOfSightDistFactor: number\n\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'contact'\n\n this.parameters = Object.assign({\n hydrogenBond: {\n type: 'boolean', rebuild: true\n },\n weakHydrogenBond: {\n type: 'boolean', rebuild: true\n },\n waterHydrogenBond: {\n type: 'boolean', rebuild: true\n },\n backboneHydrogenBond: {\n type: 'boolean', rebuild: true\n },\n hydrophobic: {\n type: 'boolean', rebuild: true\n },\n halogenBond: {\n type: 'boolean', rebuild: true\n },\n ionicInteraction: {\n type: 'boolean', rebuild: true\n },\n metalCoordination: {\n type: 'boolean', rebuild: true\n },\n cationPi: {\n type: 'boolean', rebuild: true\n },\n piStacking: {\n type: 'boolean', rebuild: true\n },\n\n filterSele: {\n type: 'text', rebuild: true\n },\n\n labelVisible: {\n type: 'boolean', rebuild: true\n },\n\n labelFixedSize: {\n type: 'boolean', buffer: 'fixedSize'\n },\n\n labelSize: {\n type: 'number', precision: 3, max: 10.0, min: 0.001, rebuild: true\n },\n\n labelUnit: {\n type: 'select',\n rebuild: true,\n options: { '': '', angstrom: 'angstrom', nm: 'nm' }\n },\n\n maxHydrophobicDist: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n maxHbondDist: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n maxHbondSulfurDist: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n maxHbondAccAngle: {\n type: 'integer', max: 180, min: 0, rebuild: true\n },\n maxHbondDonAngle: {\n type: 'integer', max: 180, min: 0, rebuild: true\n },\n maxHbondAccPlaneAngle: {\n type: 'integer', max: 90, min: 0, rebuild: true\n },\n maxHbondDonPlaneAngle: {\n type: 'integer', max: 90, min: 0, rebuild: true\n },\n maxPiStackingDist: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n maxPiStackingOffset: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n maxPiStackingAngle: {\n type: 'integer', max: 180, min: 0, rebuild: true\n },\n maxCationPiDist: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n maxCationPiOffset: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n maxIonicDist: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n maxHalogenBondDist: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n maxHalogenBondAngle: {\n type: 'integer', max: 180, min: 0, rebuild: true\n },\n maxMetalDist: {\n type: 'number', precision: 1, max: 10, min: 0.1, rebuild: true\n },\n refineSaltBridges: {\n type: 'boolean', rebuild: true\n },\n masterModelIndex: {\n type: 'integer', max: 1000, min: -1, rebuild: true\n },\n lineOfSightDistFactor: {\n type: 'number', precision: 1, max: 10, min: 0.0, rebuild: true\n },\n\n radialSegments: true,\n disableImpostor: true\n }, this.parameters)\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n p.radiusSize = defaults(p.radiusSize, 0.05)\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n this.hydrogenBond = defaults(p.hydrogenBond, true)\n this.weakHydrogenBond = defaults(p.weakHydrogenBond, false)\n this.waterHydrogenBond = defaults(p.waterHydrogenBond, false)\n this.backboneHydrogenBond = defaults(p.backboneHydrogenBond, false)\n this.hydrophobic = defaults(p.hydrophobic, false)\n this.halogenBond = defaults(p.halogenBond, true)\n this.ionicInteraction = defaults(p.ionicInteraction, true)\n this.metalCoordination = defaults(p.metalCoordination, true)\n this.cationPi = defaults(p.cationPi, true)\n this.piStacking = defaults(p.piStacking, true)\n\n this.filterSele = defaults(p.filterSele, '')\n this.labelVisible = defaults(p.labelVisible, false)\n this.labelFixedSize = defaults(p.labelFixedSize, false)\n this.labelSize = defaults(p.labelSize, 2.0)\n this.labelUnit = defaults(p.labelUnit, '')\n\n this.maxHydrophobicDist = defaults(p.maxHydrophobicDist, 4.0)\n this.maxHbondDist = defaults(p.maxHbondDist, 3.5)\n this.maxHbondSulfurDist = defaults(p.maxHbondSulfurDist, 4.1)\n this.maxHbondAccAngle = defaults(p.maxHbondAccAngle, 45)\n this.maxHbondDonAngle = defaults(p.maxHbondDonAngle, 45)\n this.maxHbondAccPlaneAngle = defaults(p.maxHbondAccPlaneAngle, 90)\n this.maxHbondDonPlaneAngle = defaults(p.maxHbondDonPlaneAngle, 30)\n this.maxPiStackingDist = defaults(p.maxPiStackingDist, 5.5)\n this.maxPiStackingOffset = defaults(p.maxPiStackingOffset, 2.0)\n this.maxPiStackingAngle = defaults(p.maxPiStackingAngle, 30)\n this.maxCationPiDist = defaults(p.maxCationPiDist, 6.0)\n this.maxCationPiOffset = defaults(p.maxCationPiOffset, 2.0)\n this.maxIonicDist = defaults(p.maxIonicDist, 5.0)\n this.maxHalogenBondDist = defaults(p.maxHalogenBondDist, 3.5)\n this.maxHalogenBondAngle = defaults(p.maxHalogenBondAngle, 30)\n this.maxMetalDist = defaults(p.maxMetalDist, 3.0)\n this.refineSaltBridges = defaults(p.refineSaltBridges, true)\n this.masterModelIndex = defaults(p.masterModelIndex, -1)\n this.lineOfSightDistFactor = defaults(p.lineOfSightDistFactor, 1.0)\n\n super.init(p)\n }\n\n getAtomRadius () {\n return 0\n }\n\n getContactData (sview: StructureView) {\n const params = {\n maxHydrophobicDist: this.maxHydrophobicDist,\n maxHbondDist: this.maxHbondDist,\n maxHbondSulfurDist: this.maxHbondSulfurDist,\n maxHbondAccAngle: this.maxHbondAccAngle,\n maxHbondDonAngle: this.maxHbondDonAngle,\n maxHbondAccPlaneAngle: this.maxHbondAccPlaneAngle,\n maxHbondDonPlaneAngle: this.maxHbondDonPlaneAngle,\n maxPiStackingDist: this.maxPiStackingDist,\n maxPiStackingOffset: this.maxPiStackingOffset,\n maxPiStackingAngle: this.maxPiStackingAngle,\n maxCationPiDist: this.maxCationPiDist,\n maxCationPiOffset: this.maxCationPiOffset,\n maxIonicDist: this.maxIonicDist,\n maxHalogenBondDist: this.maxHalogenBondDist,\n maxHalogenBondAngle: this.maxHalogenBondAngle,\n maxMetalDist: this.maxMetalDist,\n refineSaltBridges: this.refineSaltBridges,\n masterModelIndex: this.masterModelIndex,\n lineOfSightDistFactor: this.lineOfSightDistFactor\n }\n\n const dataParams = {\n hydrogenBond: this.hydrogenBond,\n weakHydrogenBond: this.weakHydrogenBond,\n waterHydrogenBond: this.waterHydrogenBond,\n backboneHydrogenBond: this.backboneHydrogenBond,\n hydrophobic: this.hydrophobic,\n halogenBond: this.halogenBond,\n ionicInteraction: this.ionicInteraction,\n metalCoordination: this.metalCoordination,\n cationPi: this.cationPi,\n piStacking: this.piStacking,\n radius: this.radiusSize * this.radiusScale,\n filterSele: this.filterSele\n }\n\n const contacts = calculateContacts(sview, params)\n return getContactData(contacts, sview, dataParams)\n }\n\n createData (sview: StructureView) {\n const contactData = this.getContactData(sview)\n\n const bufferList = [\n new CylinderBuffer(\n getFixedCountDashData(contactData),\n this.getBufferParams({\n sphereDetail: 1,\n dullInterior: true,\n disableImpostor: this.disableImpostor\n })\n ) as (CylinderGeometryBuffer | CylinderImpostorBuffer | TextBuffer)\n ]\n\n if (this.labelVisible) {\n const labelParams = {\n size: this.labelSize,\n unit: this.labelUnit\n }\n bufferList.push(new TextBuffer(\n getLabelData(contactData, labelParams),\n this.getBufferParams({fixedSize: this.labelFixedSize})\n ))\n }\n\n return { bufferList }\n }\n}\n\nRepresentationRegistry.add('contact', ContactRepresentation)\n\nexport default ContactRepresentation\n","/**\n * @file Dihedral Representation\n * @author Fred Ludlow \n * @private\n */\nimport { Color } from 'three'\n\nimport { RepresentationRegistry } from '../globals'\nimport MeasurementRepresentation, { calcArcPoint, parseNestedAtoms, MeasurementRepresentationParameters, LabelDataField } from './measurement-representation'\nimport { defaults } from '../utils'\n\nimport MeshBuffer from '../buffer/mesh-buffer'\nimport TextBuffer, { TextBufferData } from '../buffer/text-buffer'\nimport WideLineBuffer from '../buffer/wideline-buffer'\n\nimport { copyArray, uniformArray, uniformArray3 } from '../math/array-utils'\nimport { v3add, v3angle, v3cross, v3dot, v3multiplyScalar, v3fromArray, v3length,\n v3negate, v3new, v3normalize, v3sub, v3toArray } from '../math/vector-utils'\nimport { RAD2DEG } from '../math/math-constants'\nimport { getFixedLengthWrappedDashData } from '../geometry/dash'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport StructureView from '../structure/structure-view';\nimport { CylinderBufferData } from '../buffer/cylinder-buffer';\nimport { BufferData } from '../buffer/buffer';\nimport { StructureRepresentationData } from './structure-representation';\n\n/**\n * @typedef {Object} DihedralRepresentationParameters - dihedral representation parameters\n * @mixes RepresentationParameters\n * @mixes StructureRepresentationParameters\n * @mixes MeasurementRepresentationParameters\n *\n * @property {String} atomQuad - list of quadruplets of selection strings\n * or atom indices\n * @property {Boolean} extendLine - Extend lines in planes\n * @property {Number} lineOpacity - Opacity for the line part of the representation\n * @property {Boolean} lineVisible - Display the line part of the representation\n * @property {Number} linewidth - width for line part of representation\n * @property {Boolean} planeVisible - Display the two planes corresponding to dihedral\n * @property {Boolean} sectorVisible - Display the filled arc for each angle\n */\n\nexport interface DihedralRepresentationParameters extends MeasurementRepresentationParameters {\n atomQuad: (number|string)[][]\n extendLine: boolean\n lineOpacity: number\n lineVisible: boolean\n linewidth: number\n planeVisible: boolean\n sectorVisible: boolean\n}\n\n/**\n * Dihedral representation object\n *\n * Reperesentation consists of three parts, visibility can be set for each\n * label - text label indicating dihedral angle\n * line - line indicating four positions that define the dihedral\n * sector - filled arc section\n *\n * @param {Structure} structure - the structure to measure angles in\n * @param {Viewer} viewer - a viewer object\n * @param {AngleRepresentationParameters} params - angle representation parameters\n */\nclass DihedralRepresentation extends MeasurementRepresentation {\n protected atomQuad: (number|string)[][]\n protected extendLine: boolean\n protected lineOpacity: number\n protected lineVisible: boolean\n protected linewidth: number\n protected planeVisible: boolean\n protected sectorVisible: boolean\n\n protected lineLength: number\n protected planeLength: number\n protected sectorLength: number\n\n protected lineBuffer: WideLineBuffer\n protected planeBuffer: MeshBuffer\n protected sectorBuffer: MeshBuffer\n\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'dihedral'\n\n this.parameters = Object.assign({\n atomQuad: {\n type: 'hidden', rebuild: true\n },\n extendLine: {\n type: 'boolean', rebuild: true, default: true\n },\n lineVisible: {\n type: 'boolean', default: true\n },\n planeVisible: {\n type: 'boolean', default: true\n },\n sectorVisible: {\n type: 'boolean', default: true\n }\n }, this.parameters)\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n p.side = defaults(p.side, 'double')\n p.opacity = defaults(p.opacity, 0.5)\n\n this.atomQuad = defaults(p.atomQuad, [])\n this.extendLine = defaults(p.extendLine, true)\n this.lineVisible = defaults(p.lineVisible, true)\n this.planeVisible = defaults(p.planeVisible, true)\n this.sectorVisible = defaults(p.sectorVisible, true)\n\n super.init(p)\n }\n\n createData (sview: StructureView) {\n if (!sview.atomCount || !this.atomQuad.length) return\n\n const atomPosition = parseNestedAtoms(sview, this.atomQuad)\n const dihedralData = getDihedralData(\n atomPosition, {\n extendLine: this.extendLine\n }\n )\n\n const n = this.n = dihedralData.labelText.length\n const labelColor = new Color(this.labelColor)\n\n this.textBuffer = new TextBuffer({\n position: dihedralData.labelPosition,\n size: uniformArray(n, this.labelSize),\n color: uniformArray3(n, labelColor.r, labelColor.g, labelColor.b),\n text: dihedralData.labelText\n } as TextBufferData, this.getLabelBufferParams())\n\n const c = new Color(this.colorValue)\n this.lineLength = dihedralData.linePosition1.length / 3\n const lineColor = uniformArray3(this.lineLength, c.r, c.g, c.b)\n\n this.lineBuffer = new WideLineBuffer(\n getFixedLengthWrappedDashData({\n position1: dihedralData.linePosition1,\n position2: dihedralData.linePosition2,\n color: lineColor,\n color2: lineColor\n } as CylinderBufferData) ,\n this.getBufferParams({\n linewidth: this.linewidth,\n visible: this.lineVisible,\n opacity: this.lineOpacity\n })\n )\n\n this.planeLength = dihedralData.planePosition.length / 3\n this.planeBuffer = new MeshBuffer({\n position: dihedralData.planePosition,\n color: uniformArray3(this.planeLength, c.r, c.g, c.b)\n } as BufferData, this.getBufferParams({\n visible: this.planeVisible\n }))\n\n this.sectorLength = dihedralData.sectorPosition.length / 3\n this.sectorBuffer = new MeshBuffer({\n position: dihedralData.sectorPosition,\n color: uniformArray3(this.sectorLength, c.r, c.g, c.b)\n } as BufferData, this.getBufferParams({\n visible: this.sectorVisible\n }))\n\n return {\n bufferList: [\n this.textBuffer,\n this.lineBuffer,\n this.planeBuffer,\n this.sectorBuffer\n ]\n }\n }\n\n updateData (what: LabelDataField & {color?: boolean}, data: StructureRepresentationData) {\n super.updateData(what, data)\n const lineData = {}\n const planeData = {}\n const sectorData = {}\n\n if (what.color) {\n const c = new Color(this.colorValue)\n Object.assign(lineData, {\n color: uniformArray3(this.lineLength, c.r, c.g, c.b),\n color2: uniformArray3(this.lineLength, c.r, c.g, c.b)\n })\n Object.assign(planeData, {\n color: uniformArray3(this.planeLength, c.r, c.g, c.b)\n })\n Object.assign(sectorData, {\n color: uniformArray3(this.sectorLength, c.r, c.g, c.b)\n })\n }\n\n this.lineBuffer.setAttributes(lineData)\n this.planeBuffer.setAttributes(planeData)\n this.sectorBuffer.setAttributes(sectorData)\n }\n\n setParameters (params: Partial) {\n var rebuild = false\n var what = {}\n\n super.setParameters(params, what, rebuild)\n\n if (params && (\n params.lineVisible !== undefined ||\n params.sectorVisible !== undefined ||\n params.planeVisible !== undefined)) {\n this.setVisibility(this.visible)\n }\n\n if (params && params.lineOpacity) {\n this.lineBuffer.setParameters({ opacity: params.lineOpacity })\n }\n\n if (params && params.opacity !== undefined) {\n this.lineBuffer.setParameters({ opacity: this.lineOpacity })\n }\n\n if (params && params.linewidth) {\n this.lineBuffer.setParameters({ linewidth: params.linewidth })\n }\n\n return this\n }\n\n setVisibility (value: boolean, noRenderRequest?: boolean) {\n super.setVisibility(value, true)\n\n if (this.lineBuffer) {\n this.lineBuffer.setVisibility(this.lineVisible && this.visible)\n }\n\n if (this.planeBuffer) {\n this.planeBuffer.setVisibility(this.planeVisible && this.visible)\n }\n\n if (this.sectorBuffer) {\n this.sectorBuffer.setVisibility(this.sectorVisible && this.visible)\n }\n\n if (!noRenderRequest) this.viewer.requestRender()\n\n return this\n }\n}\n\n/**\n * Build the data required to create {Buffer} objects, given positions\n * @param {Float32Array} atomPosition 3*4*nDihedral array of coordinates\n * @return {Object} Arrays for building buffers\n */\nfunction getDihedralData (position: Float32Array, params: Partial = {}) {\n const angleStep = defaults(params.angleStep, Math.PI / 90)\n const nPos = position.length\n const n = position.length / 12\n const angles = new Float32Array(n)\n const labelPosition = new Float32Array(n * 3)\n const labelText = new Array(n)\n\n // Temporary arrays as don't know output length yet\n const lineTmp1 = new Array(n)\n const lineTmp2 = new Array(n)\n const sectorTmp = new Array(n)\n const planeTmp = new Array(n)\n\n // Eventual sizes of output arrays\n let totalLines = 0\n let totalSegments = 0\n let totalPlanes = 0\n\n const p1 = v3new()\n const p2 = v3new()\n const p3 = v3new()\n const p4 = v3new()\n\n const v21 = v3new()\n const v23 = v3new()\n const v34 = v3new()\n\n const tmp = v3new()\n const mid = v3new()\n const inPlane1 = v3new()\n const inPlane2 = v3new()\n const start = v3new()\n const end = v3new()\n\n const cross = v3new()\n const arcPoint = v3new()\n\n let i = 0 // Actual output index (after skipping inappropriate)\n\n for (var p = 0; p < nPos; p += 12) {\n // Set Positions\n v3fromArray(p1, position, p)\n v3fromArray(p2, position, p + 3)\n v3fromArray(p3, position, p + 6)\n v3fromArray(p4, position, p + 9)\n\n // Vectors between points\n v3sub(v21, p1, p2)\n v3sub(v23, p3, p2)\n if (v3length(v23) === 0.0) {\n continue // Can't define axis\n }\n\n v3sub(v34, p4, p3)\n\n v3multiplyScalar(tmp, v23, 0.5)\n v3add(mid, p2, tmp)\n\n v3normalize(v21, v21)\n v3normalize(v23, v23)\n v3normalize(v34, v34)\n\n // Which side of plane are p1, p4 (are we measuring something that\n // looks more like an improper? e.g. C, CA, CB, N)\n v3sub(tmp, p1, mid)\n const improperStart = v3dot(tmp, v23) > 0.0\n v3sub(tmp, p4, mid)\n const improperEnd = v3dot(tmp, v23) < 0.0\n\n // Calculate vectors perp to v23 (lying in plane (1,2,3) and (2,3,4))\n v3multiplyScalar(tmp, v23, v3dot(v23, v21))\n v3sub(inPlane1, v21, tmp)\n\n v3multiplyScalar(tmp, v23, v3dot(v23, v34))\n v3sub(inPlane2, v34, tmp)\n\n if (v3length(inPlane1) === 0.0 || v3length(inPlane2) === 0.0) {\n continue // Indeterminate angle\n }\n\n v3normalize(inPlane1, inPlane1)\n v3normalize(inPlane2, inPlane2)\n\n const angle = angles[ i ] = v3angle(inPlane1, inPlane2)\n labelText[ i ] = (RAD2DEG * angle).toFixed(1) + String.fromCharCode(0x00B0)\n\n v3cross(cross, inPlane1, v23)\n v3normalize(cross, cross)\n if (v3dot(cross, inPlane2) < 0.0) {\n v3negate(cross, cross) // Ensure cp faces correct way\n }\n\n calcArcPoint(tmp, mid, inPlane1, cross, angle / 2.0)\n v3toArray(tmp, labelPosition, 3 * i)\n\n const nSegments = Math.ceil(angle / angleStep)\n // For extended display mode, 4 straight lines plus arc/segment edge\n // For non-extended, 2 straight lines plus segment edge\n const nLines = nSegments + ((params.extendLine) ? 4 : 2)\n\n // Don't draw planes if not extending lines\n const nPlanes = params.extendLine ? 36 : 0\n\n const line1 = new Float32Array(nLines * 3)\n const line2 = new Float32Array(nLines * 3)\n const sector = new Float32Array(nSegments * 9)\n // 2 planes, 2 triangles each per dihedral (2*2*9)\n const plane = new Float32Array(nPlanes)\n\n lineTmp1[ i ] = line1\n lineTmp2[ i ] = line2\n sectorTmp[ i ] = sector\n planeTmp[ i ] = plane\n\n // Start points for lines/planes, only required\n // if extending lines\n if (params.extendLine) {\n if (improperStart) { // We'll start on the v3->1 line (tmp)\n v3sub(tmp, p1, p3)\n v3normalize(tmp, tmp)\n v3multiplyScalar(start, tmp, 1.0 / v3dot(inPlane1, tmp))\n v3add(start, start, p3)\n } else { // start on the 2->1 line\n v3multiplyScalar(start, v21, 1.0 / v3dot(inPlane1, v21))\n v3add(start, start, p2)\n }\n\n if (improperEnd) { // Finish on 2->4 line\n v3sub(tmp, p4, p2)\n v3normalize(tmp, tmp)\n v3multiplyScalar(end, tmp, 1.0 / v3dot(inPlane2, tmp))\n v3add(end, end, p2)\n } else { // end on the 3->4 line\n v3multiplyScalar(end, v34, 1.0 / v3dot(inPlane2, v34))\n v3add(end, end, p3)\n }\n }\n\n v3add(arcPoint, mid, inPlane1)\n\n // index into line1, line2\n let li = 0\n // If extending lines, there's a bit of stuff to do here\n // figuring out start and end positions\n if (params.extendLine) {\n v3toArray(p1, line1, li)\n v3toArray(start, line2, li)\n li += 3\n v3toArray(start, line1, li)\n v3toArray(arcPoint, line2, li)\n li += 3\n\n // Construct plane at start, if not extening lines\n // this is skipped\n v3toArray(start, plane, 0)\n v3toArray(arcPoint, plane, 3)\n v3toArray(improperStart ? p3 : p2, plane, 6)\n v3toArray(improperStart ? p3 : p2, plane, 9)\n v3toArray(arcPoint, plane, 12)\n v3toArray(mid, plane, 15)\n } else {\n // Not extending lines\n v3toArray(mid, line1, li)\n v3toArray(arcPoint, line2, li)\n li += 3\n }\n\n const appendArcSection = function (a: number, j: number) {\n const si = j * 9\n\n v3toArray(mid, sector, si)\n v3toArray(arcPoint, sector, si + 3)\n v3toArray(arcPoint, line1, li)\n\n calcArcPoint(arcPoint, mid, inPlane1, cross, a)\n\n v3toArray(arcPoint, sector, si + 6)\n v3toArray(arcPoint, line2, li)\n li += 3\n }\n\n let j = 0\n for (let a = angleStep; a < angle; a += angleStep) {\n appendArcSection(a, j++)\n }\n appendArcSection(angle, j++)\n\n if (params.extendLine) {\n v3toArray(arcPoint, line1, (nLines - 2) * 3)\n v3toArray(end, line2, (nLines - 2) * 3)\n v3toArray(end, line1, (nLines - 1) * 3)\n v3toArray(p4, line2, (nLines - 1) * 3)\n\n // Construct plane at end\n v3toArray(end, plane, 18)\n v3toArray(arcPoint, plane, 21)\n v3toArray(improperEnd ? p2 : p3, plane, 24)\n v3toArray(improperEnd ? p2 : p3, plane, 27)\n v3toArray(arcPoint, plane, 30)\n v3toArray(mid, plane, 33)\n } else {\n v3toArray(arcPoint, line1, li)\n v3toArray(mid, line2, li)\n li += 3\n }\n\n totalLines += nLines * 3\n totalSegments += nSegments * 9\n totalPlanes += nPlanes\n i += 1\n }\n\n const nSuccess = i\n\n const linePosition1 = new Float32Array(totalLines)\n const linePosition2 = new Float32Array(totalLines)\n const sectorPosition = new Float32Array(totalSegments)\n const planePosition = new Float32Array(totalPlanes)\n\n let lineOffset = 0\n let sectorOffset = 0\n let planeOffset = 0\n\n for (let i = 0; i < nSuccess; i++) {\n const lp1 = lineTmp1[ i ]\n const lp2 = lineTmp2[ i ]\n const sp = sectorTmp[ i ]\n const pp = planeTmp[ i ]\n\n copyArray(lp1, linePosition1, 0, lineOffset, lp1.length)\n copyArray(lp2, linePosition2, 0, lineOffset, lp2.length)\n copyArray(sp, sectorPosition, 0, sectorOffset, sp.length)\n copyArray(pp, planePosition, 0, planeOffset, pp.length)\n\n lineOffset += lp1.length\n sectorOffset += sp.length\n planeOffset += pp.length\n }\n\n return {\n labelPosition: labelPosition.subarray(0, nSuccess * 3),\n labelText: labelText.slice(0, nSuccess),\n linePosition1,\n linePosition2,\n planePosition,\n sectorPosition\n }\n}\n\nRepresentationRegistry.add('dihedral', DihedralRepresentation)\n\nexport default DihedralRepresentation\n","/**\n * @file Dihedral Histogram Representation\n * @author Rudolfs Petrovs \n * @private\n */\nimport { Color } from 'three'\n\nimport { calcArcPoint, parseNestedAtoms } from './measurement-representation'\nimport StructureRepresentation, { StructureRepresentationParameters } from './structure-representation'\n\nimport { RepresentationRegistry } from '../globals'\nimport { Structure } from '../ngl'\nimport { defaults } from '../utils'\n\nimport { BufferData } from '../buffer/buffer'\nimport MeshBuffer from '../buffer/mesh-buffer'\nimport WideLineBuffer, { WideLineBufferData } from '../buffer/wideline-buffer'\n\nimport { copyArray, uniformArray3, arraySum } from '../math/array-utils'\nimport {\n v3add, v3cross, v3dot, v3multiplyScalar, v3fromArray,\n v3negate, v3new, v3normalize, v3sub, v3toArray, v3length\n} from '../math/vector-utils'\n\nimport StructureView from '../structure/structure-view'\n\nimport Viewer from '../viewer/viewer'\n\n\nconst pointLength = 3 // One Point Length (number of coordinates of one point in 3D)\nconst pointsInTriangle = 3\n\ntype ColorDefinition = Color | string | number | undefined\n\ninterface HistogramColorParameters {\n histogramBinBorderColor: ColorDefinition\n adjacentBondArrowColor: ColorDefinition\n distantBondArrowColor: ColorDefinition\n frontHistogramColor: ColorDefinition\n backHistogramColor: ColorDefinition\n opaqueMiddleDiscColor: ColorDefinition\n}\n\ninterface HistogramInputData extends Partial {\n atomQuad: (number | string)[]\n histogram360: number[]\n}\n\ninterface HistogramData extends HistogramInputData {\n atomPositions: Float32Array\n histogram360Scaled: number[]\n}\n\ninterface WideLineData {\n startPoints: Float32Array\n endPoints: Float32Array\n startColors: Float32Array\n endColors: Float32Array\n}\n\ninterface MeshData {\n triangles: Float32Array\n triangleColors: Float32Array\n}\n\nfunction createUpdatedObject(o: Object, updateSource: Object) {\n function hasKey(obj: O, key: keyof any): key is keyof O {\n return key in obj\n }\n\n const result = { ...o } // Shallow copy\n for (const key in result) {\n if (hasKey(result, key) && hasKey(updateSource, key)) {\n result[key] = defaults(updateSource[key], result[key])\n }\n }\n return result\n}\n\nfunction createColorArray(color: ColorDefinition, arrayLength: number) {\n const colorValue = new Color(color)\n const targetArray = new Float32Array(arrayLength * 3)\n uniformArray3(arrayLength, colorValue.r, colorValue.g, colorValue.b, targetArray)\n return targetArray\n}\n\n/**\n * @typedef {Object} DihedralHistogramRepresentationParameters - dihedral representation parameters\n * @mixes RepresentationParameters\n * @mixes StructureRepresentationParameters\n *\n * @property {HistogramInputData[]} histogramsData\n * List of HistogramInputData objects, which properties specifies each particular\n * histogram, and can contain particular histogram-specific parameters.\n * Obligatory properties are:\n * atomQuad - Quadruplet of selection strings or atom indices\n * histogram360 - List of values, representing histogram from 0 to 360 degrees.\n * @property {Boolean} histogramBinBorderVisible - Display the lines that separate circular histogram bins\n * @property {Boolean} scaleBinToSectorArea - Should sector-based histogram bins'\n * area be proportional to the bins' value\n */\n\nexport interface DihedralHistogramRepresentationParameters extends StructureRepresentationParameters {\n histogramsData: HistogramInputData[]\n\n histogramBinBorderVisible: boolean\n scaleBinToSectorArea: boolean\n}\n\n/**\n * Dihedral Histogram representation object\n *\n * Reperesentation consists of several parts:\n * opaqueMiddleDisc - opaque disc in the middle of the dihedral between front and back histograms\n * frontHistogram - circular histogram from the adjacent bond viewpoint\n * backHistogram - circular histogram from the distant bond viewpoint\n * histogramBinBorder - lines, which separate histogram bins\n * bondArrows - lines, which show the actual angle on the histogram disc\n *\n * @param {Structure} structure - the structure to measure angles in\n * @param {Viewer} viewer - a viewer object\n * @param {DihedralHistogramRepresentationParameters} params - Dihedral histogram representation parameters\n */\nclass DihedralHistogramRepresentation extends StructureRepresentation {\n protected histogramsData: HistogramData[]\n\n protected histogramBinBorderVisible: boolean\n protected histogramBinBorderWidth: number\n protected histogramBinBorderColor: ColorDefinition\n protected histogramBinBorderOpacity: number\n\n protected bondArrowVisible: boolean\n protected bondArrowWidth: number\n protected bondArrowOpacity: number\n\n protected adjacentBondArrowColor: ColorDefinition\n protected distantBondArrowColor: ColorDefinition\n\n protected histogramOpacity: number\n protected frontHistogramColor: ColorDefinition\n protected backHistogramColor: ColorDefinition\n\n protected opaqueMiddleDiscVisible: boolean\n protected opaqueMiddleDiscColor: ColorDefinition\n protected opaqueMiddleDiscOpacity: number\n\n protected scaleBinToSectorArea: boolean\n\n constructor(structure: Structure, viewer: Viewer, params: DihedralHistogramRepresentationParameters) {\n super(structure, viewer, params)\n\n this.type = 'dihedral-histogram'\n\n this.parameters = Object.assign({\n histogramsData: {\n type: 'hidden', rebuild: true\n },\n histogramBinBorderVisible: {\n type: 'boolean', default: true\n },\n scaleBinToSectorArea: {\n type: 'boolean',\n rebuild: true,\n default: false\n }\n }, this.parameters)\n\n this.init(params)\n }\n\n init(params: Partial) {\n const p = params || {}\n\n const defaultColorData = {\n histogramBinBorderColor: 'grey',\n adjacentBondArrowColor: 'black',\n distantBondArrowColor: 'magenta',\n frontHistogramColor: 'green',\n backHistogramColor: 'blue',\n opaqueMiddleDiscColor: 'white'\n }\n\n const colorData = createUpdatedObject(defaultColorData, p)\n Object.assign(this, colorData)\n\n const defaultParameters = {\n histogramsData: [],\n histogramOpacity: 1.0,\n\n opaqueMiddleDiscVisible: true,\n opaqueMiddleDiscOpacity: 1.0,\n\n histogramBinBorderVisible: true,\n histogramBinBorderWidth: 1,\n histogramBinBorderOpacity: 0.5,\n\n bondArrowVisible: true,\n bondArrowWidth: 2,\n bondArrowOpacity: 1.0,\n\n scaleBinToSectorArea: false,\n }\n const parameters = createUpdatedObject(defaultParameters, p)\n Object.assign(this, parameters)\n\n this.histogramsData.forEach(x => {\n const specificColorData = createUpdatedObject(colorData, x)\n Object.assign(x, specificColorData)\n })\n\n p.side = defaults(p.side, 'double')\n p.opacity = defaults(p.opacity, 0.5)\n p.radiusType = defaults(p.radiusType, 'size')\n p.radiusSize = defaults(p.radiusSize, 0.15)\n\n super.init(p)\n }\n\n getHistogramBinBorderBufferParameters() {\n return this.getBufferParams({\n linewidth: this.histogramBinBorderWidth,\n visible: this.histogramBinBorderVisible,\n opacity: this.histogramBinBorderOpacity,\n })\n }\n\n getBondArrowsBufferParameters() {\n return this.getBufferParams({\n linewidth: this.bondArrowWidth,\n visible: this.bondArrowVisible,\n opacity: this.bondArrowOpacity,\n })\n }\n\n getOpaqueMiddleDiscBufferParameters() {\n return this.getBufferParams({\n visible: this.opaqueMiddleDiscVisible,\n opacity: this.opaqueMiddleDiscOpacity\n })\n }\n\n getHistogramBufferParameters() {\n return this.getBufferParams({\n visible: true,\n opacity: this.histogramOpacity,\n side: \"double\"\n })\n }\n\n createData(sview: StructureView) {\n if (!sview.atomCount || !this.histogramsData.length) return\n this.histogramsData.forEach(x => x.atomPositions = parseNestedAtoms(sview, [x.atomQuad]))\n const scaleData = this.scaleBinToSectorArea ? function (y: number) { return Math.sqrt(y) } : function (y: number) { return y }\n this.histogramsData.forEach(x => x.histogram360Scaled = x.histogram360.map(scaleData))\n function Float32Concat(arrays: Float32Array[]) {\n const lengths = arrays.map(x => x.length)\n const result = new Float32Array(arraySum(lengths))\n let accumulatedOffset = 0\n for (let i = 0; i < arrays.length; i++) {\n result.set(arrays[i], accumulatedOffset)\n accumulatedOffset += arrays[i].length\n }\n return result\n }\n\n function createWideLineBuffer(linesList: WideLineData[], params: {}) {\n return new WideLineBuffer(\n {\n position1: Float32Concat(linesList.map(x => x.startPoints)),\n position2: Float32Concat(linesList.map(x => x.endPoints)),\n color: Float32Concat(linesList.map(x => x.startColors)),\n color2: Float32Concat(linesList.map(x => x.endColors)),\n } as WideLineBufferData,\n params)\n }\n\n function createMeshBuffer(mesh: MeshData[], params: {}) {\n return new MeshBuffer(\n {\n position: Float32Concat(mesh.map(x => x.triangles)),\n color: Float32Concat(mesh.map(x => x.triangleColors))\n } as BufferData,\n params)\n }\n\n const dihedralDataArray = []\n\n for (let i = 0; i < this.histogramsData.length; i++) {\n let dihedralData = undefined\n let currentHistogramData = this.histogramsData[i]\n let currentHistogram360 = currentHistogramData.histogram360\n if (currentHistogram360.length >= 3) {\n dihedralData = calculateDihedralHistogram(currentHistogramData)\n }\n if (typeof dihedralData === \"undefined\") continue\n dihedralDataArray.push(dihedralData)\n }\n\n this.frontHistogramBinBordersBuffer = createWideLineBuffer(\n dihedralDataArray.map(x => x.frontHistogramBinBorders),\n this.getHistogramBinBorderBufferParameters()\n )\n\n this.backHistogramBinBordersBuffer = createWideLineBuffer(\n dihedralDataArray.map(x => x.backHistogramBinBorders),\n this.getHistogramBinBorderBufferParameters()\n )\n\n this.adjacentBondArrowsBuffer = createWideLineBuffer(\n dihedralDataArray.map(x => x.adjacentBondArrows),\n this.getBondArrowsBufferParameters()\n )\n\n this.distantBondArrowsBuffer = createWideLineBuffer(\n dihedralDataArray.map(x => x.distantBondArrows),\n this.getBondArrowsBufferParameters()\n )\n\n this.opaqueMiddleDiscBuffer = createMeshBuffer(\n dihedralDataArray.map(x => x.opaqueMiddleDisc),\n this.getOpaqueMiddleDiscBufferParameters()\n )\n\n this.frontHistogramBuffer = createMeshBuffer(\n dihedralDataArray.map(x => x.frontHistogram),\n this.getHistogramBufferParameters()\n )\n\n this.backHistogramBuffer = createMeshBuffer(\n dihedralDataArray.map(x => x.backHistogram),\n this.getHistogramBufferParameters()\n )\n\n return {\n bufferList: [].concat(\n this.frontHistogramBinBordersBuffer,\n this.backHistogramBinBordersBuffer,\n this.adjacentBondArrowsBuffer,\n this.distantBondArrowsBuffer,\n this.opaqueMiddleDiscBuffer,\n this.frontHistogramBuffer,\n this.backHistogramBuffer\n )\n }\n }\n\n setParameters(params: Partial) {\n const rebuild = false\n const what = {}\n super.setParameters(params, what, rebuild)\n\n if (params && (params.histogramBinBorderVisible !== undefined)) {\n this.setVisibility(this.visible)\n }\n return this\n }\n\n setVisibility(value: boolean, noRenderRequest?: boolean) {\n super.setVisibility(value, true)\n if (this.frontHistogramBinBordersBuffer) {\n this.frontHistogramBinBordersBuffer.setVisibility(this.histogramBinBorderVisible)\n }\n if (this.backHistogramBinBordersBuffer) {\n this.backHistogramBinBordersBuffer.setVisibility(this.histogramBinBorderVisible)\n }\n if (!noRenderRequest) this.viewer.requestRender()\n return this\n }\n}\n\n/**\n * Calculates the data required to create {Buffer} objects for one histogram, given positions\n * @param Float32Array positionOfDihedralAtoms 3*4 array of coordinates\n * @param NumberArray histogram array of coordinates\n * @return Arrays for building buffers\n */\nfunction calculateDihedralHistogram(histogramData: HistogramData) {\n const positionOfDihedralAtoms = histogramData.atomPositions\n const histogram = histogramData.histogram360Scaled;\n const totalSectorTrianglesInOpaqueMiddleDisc = histogram.length <= 180 ? 360 : histogram.length * 2\n const frontAndBack = 2\n\n const opaqueMiddleDisc = {\n triangles: new Float32Array(totalSectorTrianglesInOpaqueMiddleDisc * pointsInTriangle * pointLength),\n triangleColors: createColorArray(histogramData.opaqueMiddleDiscColor, totalSectorTrianglesInOpaqueMiddleDisc * pointsInTriangle)\n }\n\n const frontHistogram = {\n triangles: new Float32Array(histogram.length * pointsInTriangle * pointLength),\n triangleColors: createColorArray(histogramData.frontHistogramColor, histogram.length * pointsInTriangle)\n }\n\n const backHistogram = {\n triangles: new Float32Array(histogram.length * pointsInTriangle * pointLength),\n triangleColors: createColorArray(histogramData.backHistogramColor, histogram.length * pointsInTriangle)\n }\n\n const frontHistogramBinBorders = {\n startPoints: new Float32Array(histogram.length * pointLength),\n endPoints: new Float32Array(histogram.length * pointLength),\n startColors: createColorArray(histogramData.histogramBinBorderColor, histogram.length),\n endColors: createColorArray(histogramData.histogramBinBorderColor, histogram.length)\n }\n\n const backHistogramBinBorders = {\n startPoints: new Float32Array(histogram.length * pointLength),\n endPoints: new Float32Array(histogram.length * pointLength),\n startColors: createColorArray(histogramData.histogramBinBorderColor, histogram.length),\n endColors: createColorArray(histogramData.histogramBinBorderColor, histogram.length)\n }\n\n const adjacentBondArrows = {\n startPoints: new Float32Array(frontAndBack * pointLength),\n endPoints: new Float32Array(frontAndBack * pointLength),\n startColors: createColorArray(histogramData.adjacentBondArrowColor, histogram.length),\n endColors: createColorArray(histogramData.adjacentBondArrowColor, histogram.length)\n }\n const distantBondArrows = {\n startPoints: new Float32Array(frontAndBack * pointLength),\n endPoints: new Float32Array(frontAndBack * pointLength),\n startColors: createColorArray(histogramData.distantBondArrowColor, histogram.length),\n endColors: createColorArray(histogramData.distantBondArrowColor, histogram.length)\n }\n\n const p1 = v3new()\n const p2 = v3new()\n const p3 = v3new()\n const p4 = v3new()\n\n const v21 = v3new()\n const v23 = v3new()\n const v32 = v3new()\n const v34 = v3new()\n\n const mid = v3new()\n const inPlane1 = v3new()\n const inPlane2 = v3new()\n\n const cross1 = v3new()\n const cross2 = v3new()\n\n const arcPoint = v3new()\n const tmp = v3new()\n const tmp2 = v3new()\n\n // Set Atom Coordinates\n const dihedralAtomVectors = [p1, p2, p3, p4]\n\n for (let i = 0; i < dihedralAtomVectors.length; i++) {\n v3fromArray(dihedralAtomVectors[i], positionOfDihedralAtoms, i * pointLength)\n }\n\n // Vectors between points\n v3sub(v21, p1, p2)\n v3sub(v23, p3, p2)\n v3sub(v34, p4, p3)\n if (v3length(v23) === 0.0) {\n return // Can't define axis\n }\n\n v3multiplyScalar(tmp, v23, 0.5)\n v3add(mid, p2, tmp)\n\n v3normalize(v21, v21)\n v3normalize(v23, v23)\n v3normalize(v34, v34)\n\n v3negate(v32, v23)\n // Calculate vectors perp to v23 (lying in plane (1,2,3) and (2,3,4))\n v3multiplyScalar(tmp, v32, v3dot(v32, v21))\n v3sub(inPlane1, v21, tmp)\n\n v3multiplyScalar(tmp, v23, v3dot(v23, v34))\n v3sub(inPlane2, v34, tmp)\n\n if (v3length(inPlane1) === 0.0 || v3length(inPlane2) === 0.0) {\n return // Indeterminate angle\n }\n\n v3normalize(inPlane1, inPlane1)\n v3normalize(inPlane2, inPlane2)\n\n // Can use acos as normalized and non-zero\n const absAngle = Math.acos(v3dot(inPlane1, inPlane2))\n\n v3cross(cross1, v32, inPlane1)\n v3cross(cross2, v23, inPlane2)\n v3normalize(cross1, cross1)\n v3normalize(cross2, cross2)\n\n let angle = absAngle\n if (v3dot(cross1, inPlane2) < 0.0) {\n angle = -absAngle\n }\n\n v3add(arcPoint, mid, inPlane1)\n\n // Calculate necessary constants\n const maxHist = Math.max.apply(null, histogram)\n const histBinAngleStep = (Math.PI * 2) / histogram.length\n\n function setHistogramBinCoordinates(out: Float32Array, ind: number, zeroDegreeVector: Float32Array, crossVector: Float32Array, histBinAngleStep: number) {\n const startOffset = ind * pointsInTriangle * pointLength\n v3toArray(mid, out, startOffset)\n const scalingFactor = Number(histogram[ind]) / maxHist\n v3multiplyScalar(tmp, zeroDegreeVector, scalingFactor)\n v3multiplyScalar(tmp2, crossVector, scalingFactor)\n calcArcPoint(arcPoint, mid, tmp, tmp2, ind * histBinAngleStep)\n v3toArray(arcPoint, out, startOffset + 1 * pointLength)\n calcArcPoint(arcPoint, mid, tmp, tmp2, (ind + 1) * histBinAngleStep)\n v3toArray(arcPoint, out, startOffset + 2 * pointLength)\n }\n\n function setOneSideHistogram(discHistogram: MeshData, binBorders: { startPoints: Float32Array, endPoints: Float32Array }, ind: number, zeroDegreeVector: Float32Array, crossVector: Float32Array) {\n // Set Bond Arrows\n\n copyArray(mid, adjacentBondArrows.startPoints, 0, ind * pointLength, mid.length)\n calcArcPoint(tmp, mid, zeroDegreeVector, crossVector, 0 + histBinAngleStep * 0)\n copyArray(tmp, adjacentBondArrows.endPoints, 0, ind * pointLength, mid.length)\n\n copyArray(mid, distantBondArrows.startPoints, 0, ind * pointLength, mid.length)\n calcArcPoint(tmp, mid, zeroDegreeVector, crossVector, angle)\n copyArray(tmp, distantBondArrows.endPoints, 0, ind * pointLength, mid.length)\n\n // Set Histogram Bin Borders\n\n for (let i = 0; i < histogram.length; i++) {\n copyArray(mid, binBorders.startPoints, 0, i * 3, mid.length)\n calcArcPoint(tmp, mid, zeroDegreeVector, crossVector, 0 + histBinAngleStep * i)\n copyArray(tmp, binBorders.endPoints, 0, i * 3, tmp.length)\n }\n\n // Set Histogram Bins\n\n for (let sectionIndex = 0; sectionIndex < histogram.length; sectionIndex++) {\n setHistogramBinCoordinates(discHistogram.triangles, sectionIndex, zeroDegreeVector, crossVector, histBinAngleStep)\n }\n }\n\n // Opaque disc\n const opaqueCircleSectorAngleStep = Math.PI * 2 / totalSectorTrianglesInOpaqueMiddleDisc\n\n for (let sectionIndex = 0; sectionIndex < totalSectorTrianglesInOpaqueMiddleDisc; sectionIndex++) {\n const startOffset = sectionIndex * pointsInTriangle * pointLength\n v3toArray(mid, opaqueMiddleDisc.triangles, startOffset)\n calcArcPoint(arcPoint, mid, inPlane1, cross1, sectionIndex * opaqueCircleSectorAngleStep)\n v3toArray(arcPoint, opaqueMiddleDisc.triangles, startOffset + 1 * pointLength)\n calcArcPoint(arcPoint, mid, inPlane1, cross1, (sectionIndex + 1) * opaqueCircleSectorAngleStep)\n v3toArray(arcPoint, opaqueMiddleDisc.triangles, startOffset + 2 * pointLength)\n }\n\n // Front Histogram\n const distanceToOpaqueDisc = 0.01\n v3multiplyScalar(tmp, v23, -distanceToOpaqueDisc) // Get a vector to move \"mid\" just a bit from opaque disc\n v3add(mid, mid, tmp)\n setOneSideHistogram(frontHistogram, frontHistogramBinBorders, 0, inPlane1, cross1)\n\n // Back Histogram\n v3multiplyScalar(tmp, v23, 2 * distanceToOpaqueDisc) // Get a vector to move \"mid\" back and plus just a bit from opaque disc the other way\n v3add(mid, mid, tmp)\n setOneSideHistogram(backHistogram, backHistogramBinBorders, 1, inPlane2, cross2)\n\n return {\n opaqueMiddleDisc,\n frontHistogram,\n backHistogram,\n frontHistogramBinBorders,\n backHistogramBinBorders,\n adjacentBondArrows,\n distantBondArrows\n }\n}\n\nRepresentationRegistry.add('dihedral-histogram', DihedralHistogramRepresentation)\n\nexport default DihedralHistogramRepresentation\n","/**\n * @file Distance Representation\n * @author Alexander Rose \n * @author Fred Ludlow \n * @private\n */\n\nimport { Color } from 'three'\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport { DistancePicker } from '../utils/picker'\nimport { uniformArray, uniformArray3 } from '../math/array-utils'\nimport BitArray from '../utils/bitarray'\nimport MeasurementRepresentation, { MeasurementRepresentationParameters } from './measurement-representation'\nimport Selection from '../selection/selection'\nimport BondStore from '../store/bond-store'\nimport TextBuffer, { TextBufferData, TextBufferParameters } from '../buffer/text-buffer'\nimport WideLineBuffer from '../buffer/wideline-buffer'\nimport CylinderBuffer, { CylinderBufferData } from '../buffer/cylinder-buffer'\nimport { getFixedLengthDashData } from '../geometry/dash'\nimport Viewer from '../viewer/viewer';\nimport { Structure } from '../ngl';\nimport StructureView from '../structure/structure-view';\nimport { BondDataFields, BondDataParams, BondData } from '../structure/structure-data';\nimport { StructureRepresentationData } from './structure-representation';\nimport CylinderGeometryBuffer from '../buffer/cylindergeometry-buffer';\n\n/**\n * Distance representation parameter object.\n * @typedef {Object} DistanceRepresentationParameters - distance representation parameters\n * @mixes RepresentationParameters\n * @mixes StructureRepresentationParameters\n * @mixes MeasurementRepresentationParameters\n *\n * @property {String} labelUnit - distance unit (e.g. \"angstrom\" or \"nm\"). If set, a distance\n * symbol is appended to the label (i.e. 'nm' or '\\u00C5'). In case of 'nm', the\n * distance value is computed in nanometers instead of Angstroms.\n * @property {Array[]} atomPair - list of pairs of selection strings (see {@link Selection})\n * or pairs of atom indices. Using atom indices is much more\n * efficient when the representation is updated often, e.g. by\n * changing the selection or the atom positions, as there\n * are no selection strings to be evaluated.\n */\nexport interface DistanceRepresentationParameters extends MeasurementRepresentationParameters {\n labelUnit: string\n atomPair: AtomPair\n useCylinder: boolean\n}\nexport type AtomPair = (number|string)[][]\n/**\n * Distance representation\n */\nclass DistanceRepresentation extends MeasurementRepresentation {\n protected labelUnit: string\n protected atomPair: AtomPair\n protected useCylinder: boolean\n protected distanceBuffer: WideLineBuffer|CylinderGeometryBuffer\n /**\n * Create Distance representation object\n * @example\n * stage.loadFile( \"rcsb://1crn\" ).then( function( o ){\n * o.addRepresentation( \"cartoon\" );\n * // either give selections (uses first selected atom) ...\n * var atomPair = [ [ \"1.CA\", \"4.CA\" ], [ \"7.CA\", \"13.CA\" ] ];\n * // or atom indices\n * var atomPair = [ [ 8, 28 ], [ 173, 121 ] ];\n * o.addRepresentation( \"distance\", { atomPair: atomPair } );\n * stage.autoView();\n * } );\n * @param {Structure} structure - the structure to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {DistanceRepresentationParameters} params - distance representation parameters\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'distance'\n\n this.parameters = Object.assign({\n radialSegments: true,\n openEnded: true,\n disableImpostor: true,\n labelUnit: {\n type: 'select',\n rebuild: true,\n options: { '': '', angstrom: 'angstrom', nm: 'nm' }\n },\n useCylinder: {\n type: 'boolean', rebuild: true\n },\n atomPair: {\n type: 'hidden', rebuild: true\n }\n }, this.parameters)\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n p.linewidth = defaults(p.linewidth, 5.0)\n p.radiusType = defaults(p.radiusType, 'size')\n p.radiusSize = defaults(p.radiusSize, 0.2)\n\n this.labelUnit = defaults(p.labelUnit, '')\n this.useCylinder = defaults(p.useCylinder, false)\n this.atomPair = defaults(p.atomPair, [])\n\n super.init(p)\n }\n\n getDistanceData (sview: StructureView, atomPair: AtomPair) {\n let n = atomPair.length\n const text = new Array(n)\n let position = new Float32Array(n * 3)\n const sele1 = new Selection()\n const sele2 = new Selection()\n\n const bondStore = new BondStore()\n\n const ap1 = sview.getAtomProxy()\n const ap2 = sview.getAtomProxy()\n\n let j = 0 // Skipped pairs\n const selected = sview.getAtomSet()\n\n atomPair.forEach((pair, i) => {\n let v1 = pair[ 0 ]\n let v2 = pair[ 1 ]\n\n if (typeof(v1) === 'number' && Number.isInteger(v1) && typeof(v2) === 'number' && Number.isInteger(v2)) {\n if (selected.get(v1) && selected.get(v2)) {\n ap1.index = v1\n ap2.index = v2\n } else {\n j += 1\n return\n }\n } else {\n sele1.setString(v1 as string)\n sele2.setString(v2 as string)\n\n var atomIndices1 = sview.getAtomIndices(sele1)\n var atomIndices2 = sview.getAtomIndices(sele2)\n\n if (atomIndices1!.length && atomIndices2!.length) {\n ap1.index = atomIndices1![ 0 ]\n ap2.index = atomIndices2![ 0 ]\n } else {\n j += 1\n return\n }\n }\n\n bondStore.addBond(ap1, ap2, 1)\n\n i -= j\n var d = ap1.distanceTo(ap2)\n switch (this.labelUnit) {\n case 'angstrom':\n text[ i ] = d.toFixed(2) + ' ' + String.fromCharCode(0x212B)\n break\n case 'nm':\n text[ i ] = (d / 10).toFixed(2) + ' nm'\n break\n default:\n text[ i ] = d.toFixed(2)\n break\n }\n\n var i3 = i * 3\n position[ i3 + 0 ] = (ap1.x + ap2.x) / 2\n position[ i3 + 1 ] = (ap1.y + ap2.y) / 2\n position[ i3 + 2 ] = (ap1.z + ap2.z) / 2\n })\n\n if (j > 0) {\n n -= j\n position = position.subarray(0, n * 3)\n }\n\n var bondSet = new BitArray(bondStore.count, true)\n\n return {\n text: text,\n position: position,\n bondSet: bondSet,\n bondStore: bondStore\n }\n }\n\n getBondData (sview: StructureView, what: BondDataFields, params: BondDataParams): BondData {\n const bondData = sview.getBondData(this.getBondParams(what, params))\n if (bondData.picking) {\n bondData.picking = new DistancePicker(\n bondData.picking.array,\n bondData.picking.structure,\n params.bondStore!\n ) as any\n }\n return bondData\n }\n\n createData (sview: StructureView) {\n if (!sview.atomCount || !this.atomPair.length) return\n\n const n = this.atomPair.length\n const c = new Color(this.labelColor)\n const distanceData = this.getDistanceData(sview, this.atomPair)\n\n this.textBuffer = new TextBuffer({\n position: distanceData.position,\n size: uniformArray(n, this.labelSize),\n color: uniformArray3(n, c.r, c.g, c.b),\n text: distanceData.text\n } as TextBufferData, this.getLabelBufferParams() as TextBufferParameters)\n\n const bondParams = {\n bondSet: distanceData.bondSet,\n bondStore: distanceData.bondStore\n }\n\n const bondData = this.getBondData(\n sview,\n { position: true, color: true, picking: true, radius: this.useCylinder },\n bondParams\n )\n\n if (this.useCylinder) {\n this.distanceBuffer = new CylinderBuffer(\n bondData as CylinderBufferData,\n this.getBufferParams({\n openEnded: this.openEnded,\n radialSegments: this.radialSegments,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n }) \n ) as CylinderGeometryBuffer\n } else {\n this.distanceBuffer = new WideLineBuffer(\n getFixedLengthDashData(bondData as CylinderBufferData),\n this.getBufferParams({\n linewidth: this.linewidth,\n visible: this.lineVisible,\n opacity: this.lineOpacity\n })\n )\n }\n\n return {\n bondSet: distanceData.bondSet,\n bondStore: distanceData.bondStore,\n position: distanceData.position,\n bufferList: [ this.textBuffer, this.distanceBuffer ]\n }\n }\n\n updateData (what: BondDataFields, data: StructureRepresentationData) {\n super.updateData(what, data)\n\n const bondParams = {\n bondSet: data.bondSet,\n bondStore: data.bondStore\n }\n\n const bondData = this.getBondData(data.sview as StructureView, what, bondParams)\n const distanceData = {}\n\n if (!what || what.color) {\n Object.assign( distanceData, {\n color: bondData.color,\n color2: bondData.color2\n })\n }\n\n if (!what || what.radius) {\n Object.assign( distanceData, {radius: bondData.radius})\n }\n\n (this.distanceBuffer as CylinderGeometryBuffer).setAttributes(distanceData)\n }\n\n setParameters (params: Partial) {\n let rebuild = false\n const what = {}\n\n super.setParameters(params, what, rebuild)\n\n if (!this.useCylinder) {\n if (params && params.lineOpacity) {\n (this.distanceBuffer as WideLineBuffer).setParameters({ opacity: params.lineOpacity })\n }\n if (params && params.opacity !== undefined) {\n (this.distanceBuffer as WideLineBuffer).setParameters({ opacity: this.lineOpacity })\n }\n if (params && params.linewidth) {\n (this.distanceBuffer as WideLineBuffer).setParameters({ linewidth: params.linewidth })\n }\n }\n\n return this\n }\n}\n\nRepresentationRegistry.add('distance', DistanceRepresentation)\n\nexport default DistanceRepresentation\n","/**\n * @file Vector Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Vector3, Matrix4 required for declaration only\nimport { Color, Matrix4, Vector3 } from 'three'\n\nimport '../shader/Line.vert'\nimport '../shader/Line.frag'\n\nimport { uniformArray3 } from '../math/array-utils'\nimport Buffer, { BufferDefaultParameters, BufferData, BufferParameters } from './buffer'\nimport { GenericColor } from '../types'\n\nfunction getSize(data: BufferData){\n const n = data.position!.length / 3\n return n * 2 * 3\n}\n\nexport interface VectorBufferData extends BufferData {\n vector: Float32Array\n}\n\nexport const VectorBufferDefaultParameters = Object.assign({\n scale: 1,\n color: 'grey'\n}, BufferDefaultParameters)\nexport type VectorBufferParameters = BufferParameters & { scale: number, color: GenericColor }\n\n/**\n * Vector buffer. Draws vectors as lines.\n */\nclass VectorBuffer extends Buffer {\n get defaultParameters() { return VectorBufferDefaultParameters }\n parameters: VectorBufferParameters\n\n isLine = true\n vertexShader = 'Line.vert'\n fragmentShader = 'Line.frag'\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.vector - vectors\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: VectorBufferData, params: Partial = {}) {\n super({\n position: new Float32Array(getSize(data)),\n color: new Float32Array(getSize(data))\n }, params)\n\n const color = new Color(this.parameters.color)\n const attributes = this.geometry.attributes as any // TODO\n uniformArray3(getSize(data) / 3, color.r, color.g, color.b, attributes.color.array)\n\n this.setAttributes(data)\n }\n\n setAttributes (data: Partial = {}) {\n const attributes = this.geometry.attributes as any // TODO\n\n let position, vector\n let aPosition\n\n if (data.position && data.vector) {\n position = data.position\n vector = data.vector\n aPosition = attributes.position.array\n attributes.position.needsUpdate = true\n }\n\n const n = this.size / 2\n const scale = this.parameters.scale\n\n if (position && vector) {\n for (let v = 0; v < n; v++) {\n const i = v * 2 * 3\n const j = v * 3\n\n aPosition[ i + 0 ] = position[ j + 0 ]\n aPosition[ i + 1 ] = position[ j + 1 ]\n aPosition[ i + 2 ] = position[ j + 2 ]\n aPosition[ i + 3 ] = position[ j + 0 ] + vector[ j + 0 ] * scale\n aPosition[ i + 4 ] = position[ j + 1 ] + vector[ j + 1 ] * scale\n aPosition[ i + 5 ] = position[ j + 2 ] + vector[ j + 2 ] * scale\n }\n }\n }\n}\n\nexport default VectorBuffer\n","/**\n * @file Helixorient Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { Debug, Log, RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport Helixorient from '../geometry/helixorient'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport SphereBuffer, { SphereBufferParameters } from '../buffer/sphere-buffer'\nimport VectorBuffer from '../buffer/vector-buffer'\nimport Viewer from '../viewer/viewer';\nimport { Structure } from '../ngl';\nimport StructureView from '../structure/structure-view';\nimport Polymer from '../proxy/polymer';\nimport { AtomDataFields } from '../structure/structure-data';\nimport SphereGeometryBuffer from '../buffer/spheregeometry-buffer';\nimport SphereImpostorBuffer from '../buffer/sphereimpostor-buffer';\nimport { BufferData } from '../buffer/buffer';\n\n/**\n * Helixorient Representation\n */\nclass HelixorientRepresentation extends StructureRepresentation {\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'helixorient'\n\n this.parameters = Object.assign({\n sphereDetail: true,\n disableImpostor: true\n }, this.parameters)\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n p.colorScheme = defaults(p.colorScheme, 'sstruc')\n p.radiusType = defaults(p.radiusType, 'size')\n p.radiusSize = defaults(p.radiusSize, 0.15)\n p.radiusScale = defaults(p.radiusScale, 1.0)\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n super.init(p)\n }\n\n createData (sview: StructureView) {\n const bufferList: (SphereBuffer|VectorBuffer)[] = []\n const polymerList: Polymer[] = []\n\n this.structure.eachPolymer(polymer => {\n if (polymer.residueCount < 4) return\n polymerList.push(polymer)\n\n const helixorient = new Helixorient(polymer)\n const position = helixorient.getPosition()\n const color = helixorient.getColor(this.getColorParams())\n const size = helixorient.getSize(this.getRadiusParams())\n const picking = helixorient.getPicking()\n\n bufferList.push(\n new SphereBuffer(\n {\n position: position.center,\n color: color.color,\n radius: size.size,\n picking: picking.picking\n },\n this.getBufferParams({\n sphereDetail: this.sphereDetail,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n }) as SphereBufferParameters\n ),\n new VectorBuffer(\n {\n position: position.center,\n vector: position.axis\n },\n this.getBufferParams({\n color: 'skyblue',\n scale: 1\n })\n ),\n new VectorBuffer(\n {\n position: position.center,\n vector: position.resdir\n },\n this.getBufferParams({\n color: 'lightgreen',\n scale: 1\n })\n )\n )\n }, sview.getSelection())\n\n return {\n bufferList: bufferList as (SphereGeometryBuffer|SphereImpostorBuffer|VectorBuffer)[],\n polymerList: polymerList\n }\n }\n\n updateData (what: AtomDataFields, data: StructureRepresentationData) {\n if (Debug) Log.time(this.type + ' repr update')\n\n what = what || {}\n\n for (let i = 0, il = data.polymerList!.length; i < il; ++i) {\n const j = i * 3\n\n const bufferData: Partial = {}\n const polymer = data.polymerList![ i ]\n const helixorient = new Helixorient(polymer)\n\n if (what.position) {\n const position = helixorient.getPosition()\n\n Object.assign(bufferData, {position: position.center})\n\n data.bufferList[ j + 1 ].setAttributes({\n 'position': position.center,\n 'vector': position.axis\n })\n data.bufferList[ j + 2 ].setAttributes({\n 'position': position.center,\n 'vector': position.resdir\n })\n }\n\n data.bufferList[ j ].setAttributes(bufferData)\n }\n\n if (Debug) Log.timeEnd(this.type + ' repr update')\n }\n}\n\nRepresentationRegistry.add('helixorient', HelixorientRepresentation)\n\nexport default HelixorientRepresentation\n","/**\n * @file Licorice Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport BallAndStickRepresentation, { BallAndStickRepresentationParameters } from './ballandstick-representation'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\n\n/**\n * Licorice representation object ({@link BallAndStickRepresentation} with `aspectRatio` fixed at 1.0)\n */\nclass LicoriceRepresentation extends BallAndStickRepresentation {\n /**\n * Create Licorice representation object\n * @param {Structure} structure - the structure to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {BallAndStickRepresentationParameters} params - ball and stick representation parameters\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'licorice'\n\n this.parameters = Object.assign(\n {}, this.parameters, { aspectRatio: null }\n )\n }\n\n init (params: Partial) {\n var p = params || {}\n p.aspectRatio = 1.0\n\n super.init(p)\n }\n}\n\nRepresentationRegistry.add('licorice', LicoriceRepresentation)\n\nexport default LicoriceRepresentation\n","/**\n * @file Mapped Box Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { BufferParameters, BufferData } from './buffer'\nimport MappedBuffer from './mapped-buffer'\n\nconst mapping = new Float32Array([\n -1.0, -1.0, -1.0,\n 1.0, -1.0, -1.0,\n 1.0, -1.0, 1.0,\n -1.0, -1.0, 1.0,\n -1.0, 1.0, -1.0,\n 1.0, 1.0, -1.0,\n 1.0, 1.0, 1.0,\n -1.0, 1.0, 1.0\n])\n\nconst mappingIndices = new Uint16Array([\n 0, 1, 2,\n 0, 2, 3,\n 1, 5, 6,\n 1, 6, 2,\n 4, 6, 5,\n 4, 7, 6,\n 0, 7, 4,\n 0, 3, 7,\n 0, 5, 1,\n 0, 4, 5,\n 3, 2, 6,\n 3, 6, 7\n])\n\n/**\n * Mapped Box buffer. Draws boxes. Used to render general imposters.\n * @interface\n */\nclass MappedBoxBuffer extends MappedBuffer {\n constructor(data: BufferData, params: Partial = {}) {\n super('v3', data, params)\n }\n get mapping () { return mapping }\n get mappingIndices () { return mappingIndices }\n get mappingIndicesSize () { return 36 }\n get mappingSize () { return 8 }\n get mappingItemSize () { return 3 }\n}\n\nexport default MappedBoxBuffer\n","/**\n * @file Hyperball Stick Impostor Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import Vector3 required for declaration only\nimport { Matrix4, Vector3 } from 'three'\n\nimport '../shader/HyperballStickImpostor.vert'\nimport '../shader/HyperballStickImpostor.frag'\n\nimport MappedBoxBuffer from './mappedbox-buffer'\nimport { BufferDefaultParameters, BufferParameterTypes, BufferData, BufferParameters } from './buffer'\n\nexport interface HyperballStickImpostorBufferData extends BufferData {\n position1: Float32Array\n position2: Float32Array\n color2: Float32Array\n radius: Float32Array\n radius2: Float32Array\n}\n\nexport const HyperballStickImpostorBufferDefaultParameters = Object.assign({\n shrink: 0.14\n}, BufferDefaultParameters)\nexport type HyperballStickImpostorBufferParameters = BufferParameters & { shrink: number }\n\nconst HyperballStickImpostorBufferParameterTypes = Object.assign({\n shrink: { uniform: true }\n}, BufferParameterTypes)\n\n/**\n * Hyperball stick impostor buffer.\n *\n * @example\n * var hyperballStickImpostorBuffer = new HyperballStickImpostorBuffer({\n * position1: new Float32Array([ 0, 0, 0 ]),\n * position2: new Float32Array([ 2, 2, 2 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * color2: new Float32Array([ 0, 1, 0 ]),\n * radius: new Float32Array([ 1 ]),\n * radius2: new Float32Array([ 2 ])\n * });\n */\nclass HyperballStickImpostorBuffer extends MappedBoxBuffer {\n parameterTypes = HyperballStickImpostorBufferParameterTypes\n get defaultParameters() { return HyperballStickImpostorBufferDefaultParameters }\n parameters: HyperballStickImpostorBufferParameters\n\n isImpostor = true\n vertexShader = 'HyperballStickImpostor.vert'\n fragmentShader = 'HyperballStickImpostor.frag'\n\n constructor (data: HyperballStickImpostorBufferData, params: Partial = {}) {\n super(data, params)\n\n this.addUniforms({\n 'modelViewProjectionMatrix': { value: new Matrix4() },\n 'modelViewProjectionMatrixInverse': { value: new Matrix4() },\n 'modelViewMatrixInverseTranspose': { value: new Matrix4() },\n 'shrink': { value: this.parameters.shrink }\n })\n\n this.addAttributes({\n 'position1': { type: 'v3', value: null },\n 'position2': { type: 'v3', value: null },\n 'color2': { type: 'c', value: null },\n 'radius': { type: 'f', value: null },\n 'radius2': { type: 'f', value: null }\n })\n\n this.setAttributes(data)\n this.makeMapping()\n }\n}\n\nexport default HyperballStickImpostorBuffer\n","/**\n * @file Hyperball Stick Buffer\n * @author Alexander Rose \n * @private\n */\n\n// @ts-ignore: unused import required for declaration only\nimport { Vector3, Matrix4 } from 'three'\nimport { ExtensionFragDepth } from '../globals'\nimport { calculateMinArray } from '../math/array-utils'\nimport CylinderGeometryBuffer, { CylinderGeometryBufferDefaultParameters, CylinderGeometryBufferParameters } from './cylindergeometry-buffer'\nimport HyperballStickImpostorBuffer, { HyperballStickImpostorBufferDefaultParameters, HyperballStickImpostorBufferParameters } from './hyperballstickimpostor-buffer'\nimport { BufferData } from './buffer'\n\nexport interface HyperballStickBufferData extends BufferData {\n position1: Float32Array\n position2: Float32Array\n color2: Float32Array\n radius: Float32Array\n radius2: Float32Array\n}\n\nexport const HyperballStickBufferDefaultParameters = Object.assign({\n disableImpostor: false\n}, CylinderGeometryBufferDefaultParameters, HyperballStickImpostorBufferDefaultParameters)\nexport type HyperballStickBufferParameters = HyperballStickImpostorBufferParameters & CylinderGeometryBufferParameters & { disableImpostor: boolean }\n\nclass HyperballStickBufferImpl {\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position1 - from positions\n * @param {Float32Array} data.position2 - to positions\n * @param {Float32Array} data.color - from colors\n * @param {Float32Array} data.color2 - to colors\n * @param {Float32Array} data.radius - from radii\n * @param {Float32Array} data.radius2 - to radii\n * @param {Float32Array} data.picking - picking ids\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: HyperballStickBufferData, params: Partial = {}) {\n if (!ExtensionFragDepth || (params && params.disableImpostor)) {\n data.radius = calculateMinArray(data.radius, data.radius2)\n return new CylinderGeometryBuffer(data, params)\n } else {\n return new HyperballStickImpostorBuffer(data, params)\n }\n }\n}\n\n/**\n * Hyperball stick buffer. Depending on the value {@link ExtensionFragDepth} and\n * `params.disableImpostor` the constructor returns either a\n * {@link CylinderGeometryBuffer} or a {@link HyperballStickImpostorBuffer}\n * @implements {Buffer}\n *\n * @example\n * var hyperballStickBuffer = new HyperballStickBuffer({\n * position1: new Float32Array([ 0, 0, 0 ]),\n * position2: new Float32Array([ 2, 2, 2 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * color2: new Float32Array([ 0, 1, 0 ]),\n * radius: new Float32Array([ 1 ]),\n * radius2: new Float32Array([ 2 ])\n * });\n */\n//@ts-expect-error Incompatible constructor signatures\nconst HyperballStickBuffer: {\n new(data: HyperballStickBufferData, params: Partial): CylinderGeometryBuffer | HyperballStickImpostorBuffer;\n} = HyperballStickBufferImpl;\n\ntype HyperballStickBuffer = CylinderGeometryBuffer | HyperballStickImpostorBuffer;\n\nexport default HyperballStickBuffer\n","/**\n * @file Hyperball Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport { calculateCenterArray } from '../math/array-utils'\nimport LicoriceRepresentation from './licorice-representation'\nimport SphereBuffer, { SphereBufferData, SphereBufferParameters } from '../buffer/sphere-buffer'\nimport HyperballStickBuffer, { HyperballStickBufferData } from '../buffer/hyperballstick-buffer'\nimport { BallAndStickRepresentationParameters } from './ballandstick-representation';\n// @ts-ignore: unused import Volume required for declaration only\nimport { Structure, Volume } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport { BondDataParams, BondDataFields, AtomDataFields } from '../structure/structure-data';\nimport StructureView from '../structure/structure-view';\nimport { StructureRepresentationData } from './structure-representation';\nimport SphereGeometryBuffer from '../buffer/spheregeometry-buffer';\n// @ts-ignore: unused import Surface required for declaration only\nimport Surface from '../surface/surface';\n\nexport interface HyperballRepresentationParameters extends BallAndStickRepresentationParameters {\n shrink: number\n}\n\n/**\n * Hyperball Representation\n */\nclass HyperballRepresentation extends LicoriceRepresentation {\n protected shrink: number\n protected __center: Float32Array\n \n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'hyperball'\n\n this.parameters = Object.assign({\n\n shrink: {\n type: 'number', precision: 3, max: 1.0, min: 0.001, buffer: true\n }\n\n }, this.parameters, {\n\n multipleBond: null,\n bondSpacing: null\n\n })\n }\n\n init (params: Partial) {\n var p = params || {}\n p.radiusScale = defaults(p.radiusScale, 0.2)\n p.radiusType = defaults(p.radiusType, 'vdw')\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n this.shrink = defaults(p.shrink, 0.12)\n\n super.init(p)\n }\n\n getBondParams (what?: BondDataFields, params?: BondDataParams) {\n if (!what || what.radius) {\n params = Object.assign({ radius2: true }, params)\n }\n\n return super.getBondParams(what, params)\n }\n\n createData (sview: StructureView) {\n var sphereBuffer = new SphereBuffer(\n (sview.getAtomData(this.getAtomParams()) as SphereBufferData),\n this.getBufferParams({\n sphereDetail: this.sphereDetail,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n }) as SphereBufferParameters\n ) as SphereGeometryBuffer\n\n this.__center = new Float32Array(sview.bondCount * 3)\n\n var stickBuffer = new HyperballStickBuffer(\n sview.getBondData(this.getBondParams()) as HyperballStickBufferData,\n this.getBufferParams({\n shrink: this.shrink,\n radialSegments: this.radialSegments,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n })\n )\n\n return {\n bufferList: [ sphereBuffer, stickBuffer ]\n }\n }\n\n updateData (what: AtomDataFields, data: StructureRepresentationData) {\n var atomData = data.sview!.getAtomData(this.getAtomParams())\n var bondData = data.sview!.getBondData(this.getBondParams())\n var sphereData = {}\n var stickData = {}\n\n if (!what || what.position) {\n Object.assign(sphereData, {position: atomData.position})\n var from = bondData.position1\n var to = bondData.position2\n Object.assign(stickData, {\n position: calculateCenterArray(from!, to!, this.__center),\n position1: from,\n position2: to\n })\n }\n\n if (!what || what.color) {\n Object.assign(sphereData, {color: atomData.color})\n Object.assign(stickData, {\n color: bondData.color,\n color2: bondData.color2\n })\n }\n\n if (!what || what.radius) {\n Object.assign(sphereData, {radius: atomData.radius})\n Object.assign(stickData, {\n radius: bondData.radius,\n radius2: bondData.radius2\n })\n }\n\n data.bufferList[ 0 ].setAttributes(sphereData)\n data.bufferList[ 1 ].setAttributes(stickData)\n }\n}\n\nRepresentationRegistry.add('hyperball', HyperballRepresentation)\n\nexport default HyperballRepresentation\n","/**\n * @file Label Factory\n * @author Alexander Rose \n * @private\n */\n\nimport { AA1 } from '../structure/structure-constants'\nimport AtomProxy from '../proxy/atom-proxy'\nimport { sprintf } from 'sprintf-js'\n\nexport const LabelFactoryTypes = {\n '': '',\n 'atomname': 'atom name',\n 'atomindex': 'atom index',\n 'occupancy': 'occupancy',\n 'bfactor': 'b-factor',\n 'serial': 'serial',\n 'element': 'element',\n 'atom': 'atom name + index',\n 'resname': 'residue name',\n 'resno': 'residue no',\n 'res': 'one letter code + no',\n 'residue': '[residue name] + no + inscode',\n 'text': 'text',\n 'format': 'format',\n 'qualified': 'qualified name'\n}\nexport type LabelType = keyof typeof LabelFactoryTypes\n\nclass LabelFactory {\n\n static types = LabelFactoryTypes\n errorLogged: boolean = false\n\n constructor(readonly type: LabelType, readonly text: { [k: number]: string } = {},\n readonly format: string = '') {}\n\n atomLabel (a: AtomProxy) {\n const type = this.type\n\n let l\n\n switch (type) {\n case 'atomname':\n l = a.atomname\n break\n\n case 'atomindex':\n l = `${a.index}`\n break\n\n case 'occupancy':\n l = a.occupancy.toFixed(2)\n break\n\n case 'bfactor':\n l = a.bfactor.toFixed(2)\n break\n\n case 'serial':\n l = `${a.serial}`\n break\n\n case 'element':\n l = a.element\n break\n\n case 'atom':\n l = `${a.atomname}|${a.index}`\n break\n\n case 'resname':\n l = a.resname\n break\n\n case 'resno':\n l = `${a.resno}`\n break\n\n case 'res':\n l = `${(AA1[ a.resname.toUpperCase() ] || a.resname)}${a.resno}`\n break\n\n case 'residue':\n const aa1 = AA1[ a.resname.toUpperCase() ]\n if (aa1 && !a.inscode) {\n l = `${aa1}${a.resno}`\n } else {\n l = `[${a.resname}]${a.resno}${a.inscode}`\n }\n break\n\n case 'text':\n l = this.text[ a.index ]\n break\n\n case 'format':\n try {\n l = sprintf(this.format, a)\n } catch (e) {\n if (!this.errorLogged) {\n this.errorLogged = true\n console.log(e.message)\n }\n }\n break\n\n // case \"qualified\":\n default:\n l = a.qualifiedName()\n break\n }\n\n return l === undefined ? '' : l\n }\n}\n\nexport default LabelFactory\n","/**\n * @file Label Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry, ColormakerRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport LabelFactory, { LabelType } from '../utils/label-factory'\nimport RadiusFactory from '../utils/radius-factory'\nimport StructureRepresentation, { StructureRepresentationData } from './structure-representation'\nimport TextBuffer, { TextBufferData } from '../buffer/text-buffer'\nimport { RepresentationParameters } from './representation';\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport StructureView from '../structure/structure-view';\nimport { GenericColor } from '../types'\n\nexport interface TextDataField {\n position?: boolean\n color?: boolean\n radius?: boolean\n text?: boolean\n}\n\n/**\n * Label representation parameter object. Extends {@link RepresentationParameters} and\n * {@link StructureRepresentationParameters}.\n *\n * @typedef {Object} LabelRepresentationParameters - label representation parameters\n *\n * @property {Integer} clipNear - position of camera near/front clipping plane\n * in percent of scene bounding box\n * @property {Float} opacity - translucency: 1 is fully opaque, 0 is fully transparent\n * @property {String} labelType - type of the label, one of:\n * \"atomname\", \"atomindex\", \"occupancy\", \"bfactor\",\n * \"serial\", \"element\", \"atom\", \"resname\", \"resno\",\n * \"res\", \"text\", \"qualified\". When set to \"text\", the\n * `labelText` list is used.\n * @property {String[]} labelText - list of label strings, must set `labelType` to \"text\"\n * to take effect\n * @property {String} labelFormat - sprintf-js format string, any attribute of\n * {@link AtomProxy} can be used\n * @property {String} labelGrouping - grouping of the label, one of:\n * \"atom\", \"residue\".\n * @property {String} fontFamily - font family, one of: \"sans-serif\", \"monospace\", \"serif\"\n * @property {String} fontStyle - font style, \"normal\" or \"italic\"\n * @property {String} fontWeight - font weight, \"normal\" or \"bold\"\n * @property {Float} xOffset - offset in x-direction\n * @property {Float} yOffset - offset in y-direction\n * @property {Float} zOffset - offset in z-direction (i.e. in camera direction)\n * @property {String} attachment - attachment of the label, one of:\n * \"bottom-left\", \"bottom-center\", \"bottom-right\",\n * \"middle-left\", \"middle-center\", \"middle-right\",\n * \"top-left\", \"top-center\", \"top-right\"\n * @property {Boolean} showBorder - show border/outline\n * @property {Color} borderColor - color of the border/outline\n * @property {Float} borderWidth - width of the border/outline\n * @property {Boolean} showBackground - show background rectangle\n * @property {Color} backgroundColor - color of the background\n * @property {Float} backgroundMargin - width of the background\n * @property {Float} backgroundOpacity - opacity of the background\n * @property {Boolean} fixedSize - show text with a fixed pixel size\n */\nexport interface LabelRepresentationParameters extends RepresentationParameters {\n labelType: LabelType\n labelText: string[]\n labelFormat: string\n labelGrouping: 'atom'|'residue'\n fontFamily: 'sans-serif'|'monospace'|'serif'\n fontStyle: 'normal'|'italic'\n fontWeight: 'normal'|'bold'\n xOffset: number\n yOffset: number\n zOffset: number\n attachment: 'bottom-left'|'bottom-center'|'bottom-right'|'middle-left'|'middle-center'|'middle-right'|'top-left'|'top-center'|'top-right'\n showBorder: boolean\n borderColor: GenericColor\n borderWidth: number\n showBackground: boolean\n backgroundColor: GenericColor\n backgroundMargin: number\n backgroundOpacity: number\n fixedSize: boolean\n}\n/**\n * Label representation\n */\nclass LabelRepresentation extends StructureRepresentation {\n\n protected labelType: LabelType\n protected labelText: string[]\n protected labelFormat: string\n protected labelGrouping: 'atom'|'residue'\n protected fontFamily: 'sans-serif'|'monospace'|'serif'\n protected fontStyle: 'normal'|'italic'\n protected fontWeight: 'normal'|'bold'\n protected xOffset: number\n protected yOffset: number\n protected zOffset: number\n protected attachment: 'bottom-left'|'bottom-center'|'bottom-right'|'middle-left'|'middle-center'|'middle-right'|'top-left'|'top-center'|'top-right'\n protected showBorder: boolean\n protected borderColor: GenericColor\n protected borderWidth: number\n protected showBackground: boolean\n protected backgroundColor: GenericColor\n protected backgroundMargin: number\n protected backgroundOpacity: number\n protected fixedSize: boolean\n\n /**\n * Create Label representation object\n * @param {Structure} structure - the structure to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {LabelRepresentationParameters} params - label representation parameters\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'label'\n\n this.parameters = Object.assign({\n\n labelType: {\n type: 'select', options: LabelFactory.types, rebuild: true\n },\n labelText: {\n type: 'hidden', rebuild: true\n },\n labelFormat: {\n type: 'text', rebuild: true\n },\n labelGrouping: {\n type: 'select',\n options: {\n 'atom': 'atom',\n 'residue': 'residue'\n },\n rebuild: true\n },\n fontFamily: {\n type: 'select',\n options: {\n 'sans-serif': 'sans-serif',\n 'monospace': 'monospace',\n 'serif': 'serif'\n },\n buffer: true\n },\n fontStyle: {\n type: 'select',\n options: {\n 'normal': 'normal',\n 'italic': 'italic'\n },\n buffer: true\n },\n fontWeight: {\n type: 'select',\n options: {\n 'normal': 'normal',\n 'bold': 'bold'\n },\n buffer: true\n },\n xOffset: {\n type: 'number', precision: 1, max: 20, min: -20, buffer: true\n },\n yOffset: {\n type: 'number', precision: 1, max: 20, min: -20, buffer: true\n },\n zOffset: {\n type: 'number', precision: 1, max: 20, min: -20, buffer: true\n },\n attachment: {\n type: 'select',\n options: {\n 'bottom-left': 'bottom-left',\n 'bottom-center': 'bottom-center',\n 'bottom-right': 'bottom-right',\n 'middle-left': 'middle-left',\n 'middle-center': 'middle-center',\n 'middle-right': 'middle-right',\n 'top-left': 'top-left',\n 'top-center': 'top-center',\n 'top-right': 'top-right'\n },\n rebuild: true\n },\n showBorder: {\n type: 'boolean', buffer: true\n },\n borderColor: {\n type: 'color', buffer: true\n },\n borderWidth: {\n type: 'number', precision: 2, max: 0.3, min: 0, buffer: true\n },\n showBackground: {\n type: 'boolean', rebuild: true\n },\n backgroundColor: {\n type: 'color', buffer: true\n },\n backgroundMargin: {\n type: 'number', precision: 2, max: 2, min: 0, rebuild: true\n },\n backgroundOpacity: {\n type: 'range', step: 0.01, max: 1, min: 0, buffer: true\n },\n fixedSize: {\n type: 'boolean', buffer: true\n }\n\n }, this.parameters, {\n\n side: null,\n flatShaded: null,\n wireframe: null,\n linewidth: null,\n\n roughness: null,\n metalness: null,\n diffuse: null\n\n })\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n\n this.labelType = defaults(p.labelType, 'res')\n this.labelText = defaults(p.labelText, {})\n this.labelFormat = defaults(p.labelFormat, '')\n this.labelGrouping = defaults(p.labelGrouping, 'atom')\n this.fontFamily = defaults(p.fontFamily, 'sans-serif')\n this.fontStyle = defaults(p.fontStyle, 'normal')\n this.fontWeight = defaults(p.fontWeight, 'bold')\n this.xOffset = defaults(p.xOffset, 0.0)\n this.yOffset = defaults(p.yOffset, 0.0)\n this.zOffset = defaults(p.zOffset, 0.5)\n this.attachment = defaults(p.attachment, 'bottom-left')\n this.showBorder = defaults(p.showBorder, false)\n this.borderColor = defaults(p.borderColor, 'lightgrey')\n this.borderWidth = defaults(p.borderWidth, 0.15)\n this.showBackground = defaults(p.showBackground, false)\n this.backgroundColor = defaults(p.backgroundColor, 'lightgrey')\n this.backgroundMargin = defaults(p.backgroundMargin, 0.5)\n this.backgroundOpacity = defaults(p.backgroundOpacity, 1.0)\n this.fixedSize = defaults(p.fixedSize, false)\n\n super.init(p)\n }\n\n getTextData (sview: StructureView, what?: TextDataField) {\n const p = this.getAtomParams(what)\n const labelFactory = new LabelFactory(this.labelType, this.labelText, this.labelFormat)\n let position: Float32Array, size: Float32Array, color: Float32Array, text: string[],\n positionN: number[], sizeN: number[], colorN: number[]\n if (this.labelGrouping === 'atom') {\n const atomData = sview.getAtomData(p)\n position = atomData.position as Float32Array\n size = atomData.radius as Float32Array\n color = atomData.color as Float32Array\n if (!what || what.text) {\n text = []\n sview.eachAtom(ap => text.push(labelFactory.atomLabel(ap)))\n }\n } else if (this.labelGrouping === 'residue') {\n if (!what || what.position) positionN = []\n if (!what || what.color) colorN = []\n if (!what || what.radius) sizeN = []\n if (!what || what.text) text = []\n if (p.colorParams) p.colorParams.structure = sview.getStructure()\n const colormaker = ColormakerRegistry.getScheme(p.colorParams)\n const radiusFactory = new RadiusFactory(p.radiusParams)\n const ap1 = sview.getAtomProxy()\n\n let i = 0\n sview.eachResidue(rp => {\n const i3 = i * 3\n if (rp.isProtein() || rp.isNucleic()) {\n ap1.index = rp.traceAtomIndex\n if (!what || what.position) {\n ap1.positionToArray(positionN, i3)\n }\n } else {\n ap1.index = rp.atomOffset\n if (!what || what.position) {\n rp.positionToArray(positionN, i3)\n }\n }\n if (!what || what.color) {\n colormaker.atomColorToArray(ap1, colorN, i3)\n }\n if (!what || what.radius) {\n sizeN[ i ] = radiusFactory.atomRadius(ap1)\n }\n if (!what || what.text) {\n text.push(labelFactory.atomLabel(ap1))\n }\n ++i\n })\n\n if (!what || what.position) position = new Float32Array(positionN!)\n if (!what || what.color) color = new Float32Array(colorN!)\n if (!what || what.radius) size = new Float32Array(sizeN!)\n }\n\n return { position: position!, size: size!, color: color!, text: text! }\n }\n\n createData (sview: StructureView) {\n const what: TextDataField = { position: true, color: true, radius: true, text: true }\n\n const textBuffer = new TextBuffer(\n this.getTextData(sview, what) as TextBufferData,\n this.getBufferParams({\n fontFamily: this.fontFamily,\n fontStyle: this.fontStyle,\n fontWeight: this.fontWeight,\n xOffset: this.xOffset,\n yOffset: this.yOffset,\n zOffset: this.zOffset,\n attachment: this.attachment,\n showBorder: this.showBorder,\n borderColor: this.borderColor,\n borderWidth: this.borderWidth,\n showBackground: this.showBackground,\n backgroundColor: this.backgroundColor,\n backgroundMargin: this.backgroundMargin,\n backgroundOpacity: this.backgroundOpacity,\n fixedSize: this.fixedSize\n })\n )\n\n return { bufferList: [ textBuffer ] }\n }\n\n updateData (what: TextDataField, data: StructureRepresentationData) {\n data.bufferList[ 0 ].setAttributes(this.getTextData(data.sview as StructureView, what))\n }\n\n getAtomRadius () {\n return 0\n }\n}\n\nRepresentationRegistry.add('label', LabelRepresentation)\n\nexport default LabelRepresentation\n","/**\n * @file Line Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport { RepresentationRegistry } from '../globals'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport WideLineBuffer from '../buffer/wideline-buffer'\nimport { AtomPicker } from '../utils/picker'\n// @ts-ignore: unused import Volume required for declaration only\nimport { Structure, Volume } from '../ngl';\nimport StructureView from '../structure/structure-view';\nimport Viewer from '../viewer/viewer';\nimport AtomProxy from '../proxy/atom-proxy';\n// @ts-ignore: unused import Surface required for declaration only\nimport Surface from '../surface/surface';\n// @ts-ignore: unused import BondDataFields, BondDataParams required for declaration only\nimport { BondDataFields, BondDataParams } from '../structure/structure-data';\n\n/**\n * Determine which atoms in a Structure[View] form no bonds to any other atoms\n * in that Structure.\n *\n * This differs from setting the selection to \"nonbonded\" as it finds atoms\n * that have no bonds within the current selection.\n * @param {Structure} structure - The Structure or StructureView object\n * @return {AtomSet} AtomSet of lone atoms\n */\nfunction getLoneAtomSet (structure: Structure | StructureView) {\n const atomSet = structure.getAtomSet()\n const bondSet = structure.getBondSet()\n const bp = structure.getBondProxy()\n bondSet.forEach(function (idx) {\n bp.index = idx\n atomSet.clear(bp.atomIndex1)\n atomSet.clear(bp.atomIndex2)\n })\n return atomSet\n}\n\nexport interface LineRepresentationParameters extends StructureRepresentationParameters {\n multipleBond: 'off' | 'symmetric' | 'offset'\n bondSpacing: number\n linewidth: number\n lines: boolean\n crosses: 'off' | 'all' | 'lone'\n crossSize: number\n}\n\nexport interface CrossData {\n position1?: Float32Array\n position2?: Float32Array\n color?: Float32Array\n color2?: Float32Array\n picking?: AtomPicker\n}\n\n/**\n * Line representation\n */\nclass LineRepresentation extends StructureRepresentation {\n protected multipleBond: 'off' | 'symmetric' | 'offset'\n protected bondSpacing: number\n protected linewidth: number\n protected lines: boolean\n protected crosses: 'off' | 'all' | 'lone'\n protected crossSize: number\n /**\n * Create Line representation object\n * @param {Structure} structure - the structure to be represented\n * @param {Viewer} viewer - a viewer object\n * @param {RepresentationParameters} params - representation parameters, plus the properties listed below\n * @property {String} multipleBond - one off \"off\", \"symmetric\", \"offset\"\n * @param {Float} params.bondSpacing - spacing for multiple bond rendering\n * @param {Integer} params.linewidth - width of lines\n * @param {Boolean} params.lines - render bonds as lines\n * @param {String} params.crosses - render atoms as crosses: \"off\", \"all\" or \"lone\" (default)\n * @param {Float} params.crossSize - size of cross\n * @param {null} params.flatShaded - not available\n * @param {null} params.side - not available\n * @param {null} params.wireframe - not available\n * @param {null} params.roughness - not available\n * @param {null} params.metalness - not available\n * @param {null} params.diffuse - not available\n */\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'line'\n\n this.parameters = Object.assign({\n\n multipleBond: {\n type: 'select',\n rebuild: true,\n options: {\n 'off': 'off',\n 'symmetric': 'symmetric',\n 'offset': 'offset'\n }\n },\n bondSpacing: {\n type: 'number', precision: 2, max: 2.0, min: 0.5\n },\n linewidth: {\n type: 'integer', max: 50, min: 1, buffer: true\n },\n lines: {\n type: 'boolean', rebuild: true\n },\n crosses: {\n type: 'select',\n rebuild: true,\n options: {\n 'off': 'off',\n 'lone': 'lone',\n 'all': 'all'\n }\n },\n crossSize: {\n type: 'number', precision: 2, max: 2.0, min: 0.1\n }\n\n }, this.parameters, {\n\n flatShaded: null,\n side: null,\n wireframe: null,\n\n roughness: null,\n metalness: null\n\n })\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n\n this.multipleBond = defaults(p.multipleBond, 'off')\n this.bondSpacing = defaults(p.bondSpacing, 1.0)\n this.linewidth = defaults(p.linewidth, 2)\n this.lines = defaults(p.lines, true)\n this.crosses = defaults(p.crosses, 'lone')\n this.crossSize = defaults(p.crossSize, 0.4)\n\n super.init(p)\n }\n\n getAtomRadius (atom:AtomProxy) {\n return 0.1\n }\n\n getBondParams (what: any, params?: Partial) {\n params = Object.assign({\n multipleBond: this.multipleBond,\n bondSpacing: this.bondSpacing,\n radiusParams: { 'type': 'size', 'size': 0.1, 'scale': 1 }\n }, params)\n\n return super.getBondParams(what, params)\n }\n\n _crossData (what: any, sview: StructureView) {\n if (what) {\n if (!what.position && !what.color) return\n }\n\n const p = {}\n if (this.crosses === 'lone') {\n Object.assign(p, {atomSet : getLoneAtomSet(sview)})\n }\n\n const atomData = sview.getAtomData(this.getAtomParams(what, p))\n const crossData: CrossData = {}\n const position = atomData.position\n const color = atomData.color\n const picking = atomData.picking\n\n const size = (position! || color).length\n const attrSize = size * 3\n\n let cPosition1 = new Float32Array(0)\n let cPosition2 = new Float32Array(0)\n let cColor = new Float32Array(0)\n let cColor2 = new Float32Array(0)\n let cOffset: number = 0\n\n let pickingArray = new Float32Array(0)\n\n if (!what || what.position) {\n cPosition1 = crossData.position1 = new Float32Array(attrSize)\n cPosition2 = crossData.position2 = new Float32Array(attrSize)\n cOffset = this.crossSize / 2\n }\n if (!what || what.color) {\n cColor = crossData.color = new Float32Array(attrSize)\n cColor2 = crossData.color2 = new Float32Array(attrSize)\n }\n if (!what || what.picking) {\n pickingArray = new Float32Array(atomData.picking!.array!.length * 3) // Needs padding??\n }\n\n for (let v = 0; v < size; v++) {\n const j = v * 3\n const i = j * 3\n\n if (!what || what.position) {\n const x = position![ j ]\n const y = position![ j + 1 ]\n const z = position![ j + 2 ]\n\n cPosition1[ i ] = x - cOffset!\n cPosition1[ i + 1 ] = y\n cPosition1[ i + 2 ] = z\n cPosition2[ i ] = x + cOffset\n cPosition2[ i + 1 ] = y\n cPosition2[ i + 2 ] = z\n\n cPosition1[ i + 3 ] = x\n cPosition1[ i + 4 ] = y - cOffset\n cPosition1[ i + 5 ] = z\n cPosition2[ i + 3 ] = x\n cPosition2[ i + 4 ] = y + cOffset\n cPosition2[ i + 5 ] = z\n\n cPosition1[ i + 6 ] = x\n cPosition1[ i + 7 ] = y\n cPosition1[ i + 8 ] = z - cOffset\n cPosition2[ i + 6 ] = x\n cPosition2[ i + 7 ] = y\n cPosition2[ i + 8 ] = z + cOffset\n }\n\n if (!what || what.color) {\n const cimax = i + 9\n for (let ci = i; ci < cimax; ci += 3) {\n cColor[ ci ] = cColor2[ ci ] = color![ j ]\n cColor[ ci + 1 ] = cColor2[ ci + 1 ] = color![ j + 1 ]\n cColor[ ci + 2 ] = cColor2[ ci + 2 ] = color![ j + 2 ]\n }\n }\n\n if (!what || what.picking) {\n pickingArray[ j ] =\n pickingArray[ j + 1 ] =\n pickingArray[ j + 2 ] = picking!.array![ v ]\n }\n }\n\n if (!what || what.picking) {\n crossData.picking = new AtomPicker(\n pickingArray, picking!.structure\n )\n }\n\n return crossData\n }\n\n createData (sview: StructureView) {\n const what = { position: true, color: true, picking: true }\n\n const bufferList = []\n\n if (this.lines) {\n const bondData = sview.getBondData(this.getBondParams(what))\n\n const lineBuffer = new WideLineBuffer(\n bondData, this.getBufferParams({ linewidth: this.linewidth })\n )\n\n bufferList.push(lineBuffer)\n }\n\n if (this.crosses !== 'off') {\n const crossBuffer = new WideLineBuffer(\n (this._crossData(what, sview) as CrossData),\n this.getBufferParams({linewidth: this.linewidth})\n )\n bufferList.push(crossBuffer)\n }\n\n return {\n bufferList: bufferList\n }\n }\n\n updateData (what: any, data: StructureRepresentationData) {\n let bufferIdx = 0\n\n if (this.lines) {\n const bondData = data.sview!.getBondData(this.getBondParams(what))\n const lineAttributes = {}\n\n if (!what || what.position) {\n Object.assign(lineAttributes, {\n position1: bondData.position1,\n position2: bondData.position2\n })\n }\n\n if (!what || what.color) {\n Object.assign(lineAttributes, {\n color: bondData.color,\n color2: bondData.color2\n })\n }\n\n data.bufferList[ bufferIdx++ ].setAttributes(lineAttributes)\n }\n\n if (this.crosses !== 'off') {\n const crossData = this._crossData(what, (data.sview as StructureView))\n const crossAttributes = {}\n\n if (!what || what.position) {\n Object.assign(crossAttributes, {\n position1: crossData!.position1,\n position2: crossData!.position2\n })\n }\n if (!what || what.color) {\n Object.assign(crossAttributes, {\n color: crossData!.color,\n color2: crossData!.color2\n })\n }\n\n data.bufferList[ bufferIdx++ ].setAttributes(crossAttributes)\n }\n }\n\n setParameters (params: Partial) {\n var rebuild = false\n var what = {}\n\n if (params && (params.bondSpacing || params.crossSize)) {\n Object.assign(what, { position: true })\n }\n\n super.setParameters(params, what, rebuild)\n\n return this\n }\n}\n\nRepresentationRegistry.add('line', LineRepresentation)\n\nexport default LineRepresentation\n","import { NumberArray, TypedArray } from \"../types\";\n\n/**\n * @file Grid\n * @author Alexander Rose \n * @private\n */\nexport interface iGrid {\n data: TypedArray\n index: (x: number, y: number, z: number) => number\n set: (x: number, y: number, z: number, ...arg: number[]) => void\n toArray: (x: number, y: number, z: number, array?: NumberArray, offset?: number) => void\n fromArray: (x: number, y: number, z: number, array: NumberArray, offset?: number) => void\n copy: (grid: iGrid) => void\n // clone: () => iGrid\n}\n\nfunction makeGrid (length: number, width: number, height: number, DataCtor: any, elemSize: number) : iGrid {\n DataCtor = DataCtor || Int32Array\n elemSize = elemSize || 1\n\n const data = new DataCtor(length * width * height * elemSize)\n\n function index (x: number, y: number, z: number) {\n return ((((x * width) + y) * height) + z) * elemSize\n }\n\n function set (x: number, y: number, z: number, ...args: number[]) {\n const i = index(x, y, z)\n\n for (let j = 0; j < elemSize; ++j) {\n data[ i + j ] = args[ j ]\n }\n }\n\n function toArray (x: number, y: number, z: number, array: NumberArray = [], offset: number = 0) {\n const i = index(x, y, z)\n\n for (let j = 0; j < elemSize; ++j) {\n array[ offset + j ] = data[ i + j ]\n }\n }\n\n function fromArray(x: number, y: number, z: number, array: NumberArray, offset: number = 0) {\n const i = index(x, y, z)\n\n for (let j = 0; j < elemSize; ++j) {\n data[ i + j ] = array[ offset + j ]\n }\n }\n\n function copy(grid: iGrid) {\n data.set(grid.data)\n }\n\n // function clone() {\n // return makeGrid(\n // length, width, height, DataCtor, elemSize\n // ).copy(this)\n // }\n return { data, index, set, toArray, fromArray, copy }\n}\n\nexport { makeGrid }","/**\n * @file EDT Surface\n * @author Alexander Rose \n * @private\n */\n\nimport { VolumeSurface } from './volume'\nimport { iGrid, makeGrid } from '../geometry/grid'\nimport { computeBoundingBox } from '../math/vector-utils'\nimport { getRadiusDict, getSurfaceGrid } from './surface-utils'\nimport { TypedArray } from '../types';\n\ninterface EDTSurface {\n getVolume: (type: string, probeRadius: number, scaleFactor: number, cutoff: number, setAtomID: boolean) => {\n data: TypedArray\n nx: number\n ny: number\n nz: number\n atomindex: TypedArray\n }\n getSurface: (type: string, probeRadius: number, scaleFactor: number, cutoff: number, setAtomID: boolean, smooth: number, contour: boolean) => any\n}\n\nfunction EDTSurface (this: EDTSurface, coordList: Float32Array, radiusList: Float32Array, indexList: Uint16Array|Uint32Array) {\n // based on D. Xu, Y. Zhang (2009) Generating Triangulated Macromolecular\n // Surfaces by Euclidean Distance Transform. PLoS ONE 4(12): e8140.\n //\n // Permission to use, copy, modify, and distribute this program for\n // any purpose, with or without fee, is hereby granted, provided that\n // the notices on the head, the reference information, and this\n // copyright notice appear in all copies or substantial portions of\n // the Software. It is provided \"as is\" without express or implied\n // warranty.\n //\n // ported to JavaScript by biochem_fan (http://webglmol.sourceforge.jp/)\n // refactored by dkoes (https://github.com/dkoes)\n //\n // adapted to NGL by Alexander Rose\n\n var radiusDict = getRadiusDict(radiusList as any)\n var bbox = computeBoundingBox(coordList)\n if (coordList.length === 0) {\n bbox[ 0 ].set([ 0, 0, 0 ])\n bbox[ 1 ].set([ 0, 0, 0 ])\n }\n var min = bbox[ 0 ]\n var max = bbox[ 1 ]\n\n var probeRadius: number, scaleFactor: number, cutoff: number\n var pLength: number, pWidth: number, pHeight: number\n var matrix: Float32Array, ptran: Float32Array\n var depty: {[k: string]: TypedArray}, widxz: {[k: string]: number}\n var cutRadius: number\n var setAtomID: boolean\n var vpBits: TypedArray, vpDistance: TypedArray, vpAtomID: TypedArray\n\n function init (btype: boolean, _probeRadius: number, _scaleFactor: number, _cutoff: number, _setAtomID: boolean) {\n probeRadius = _probeRadius || 1.4\n scaleFactor = _scaleFactor || 2.0\n setAtomID = _setAtomID || true\n\n var maxRadius = 0\n for (var radius in radiusDict) {\n maxRadius = Math.max(maxRadius, radius as any)\n }\n\n var grid = getSurfaceGrid(\n min, max, maxRadius, scaleFactor, btype ? probeRadius : 0\n )\n\n pLength = grid.dim[0]\n pWidth = grid.dim[1]\n pHeight = grid.dim[2]\n\n matrix = grid.matrix\n ptran = grid.tran\n scaleFactor = grid.scaleFactor\n\n // boundingatom caches\n depty = {}\n widxz = {}\n boundingatom(btype)\n\n cutRadius = probeRadius * scaleFactor\n\n if (_cutoff) {\n cutoff = _cutoff\n } else {\n // cutoff = Math.max( 0.1, -1.2 + scaleFactor * probeRadius );\n cutoff = probeRadius / scaleFactor\n }\n\n vpBits = new Uint8Array(pLength * pWidth * pHeight)\n if (btype) {\n vpDistance = new Float64Array(pLength * pWidth * pHeight)\n }\n if (setAtomID) {\n vpAtomID = new Int32Array(pLength * pWidth * pHeight)\n }\n }\n\n // constants for vpBits bitmasks\n var INOUT = 1\n var ISDONE = 2\n var ISBOUND = 4\n\n var nb = [\n new Int32Array([ 1, 0, 0 ]), new Int32Array([ -1, 0, 0 ]),\n new Int32Array([ 0, 1, 0 ]), new Int32Array([ 0, -1, 0 ]),\n new Int32Array([ 0, 0, 1 ]), new Int32Array([ 0, 0, -1 ]),\n new Int32Array([ 1, 1, 0 ]), new Int32Array([ 1, -1, 0 ]),\n new Int32Array([ -1, 1, 0 ]), new Int32Array([ -1, -1, 0 ]),\n new Int32Array([ 1, 0, 1 ]), new Int32Array([ 1, 0, -1 ]),\n new Int32Array([ -1, 0, 1 ]), new Int32Array([ -1, 0, -1 ]),\n new Int32Array([ 0, 1, 1 ]), new Int32Array([ 0, 1, -1 ]),\n new Int32Array([ 0, -1, 1 ]), new Int32Array([ 0, -1, -1 ]),\n new Int32Array([ 1, 1, 1 ]), new Int32Array([ 1, 1, -1 ]),\n new Int32Array([ 1, -1, 1 ]), new Int32Array([ -1, 1, 1 ]),\n new Int32Array([ 1, -1, -1 ]), new Int32Array([ -1, -1, 1 ]),\n new Int32Array([ -1, 1, -1 ]), new Int32Array([ -1, -1, -1 ])\n ]\n\n //\n\n this.getVolume = function (type: string, probeRadius: number, scaleFactor: number, cutoff: number, setAtomID: boolean) {\n console.time('EDTSurface.getVolume')\n\n var btype = type !== 'vws'\n\n init(btype, probeRadius, scaleFactor, cutoff, setAtomID)\n\n fillvoxels(btype)\n buildboundary()\n\n if (type === 'ms' || type === 'ses') {\n fastdistancemap()\n }\n\n if (type === 'ses') {\n boundingatom(false)\n fillvoxelswaals()\n }\n\n marchingcubeinit(type)\n\n // set atomindex in the volume data\n for (var i = 0, il = vpAtomID.length; i < il; ++i) {\n vpAtomID[ i ] = indexList[ vpAtomID[ i ] ]\n }\n\n console.timeEnd('EDTSurface.getVolume')\n\n return {\n data: vpBits,\n nx: pHeight,\n ny: pWidth,\n nz: pLength,\n atomindex: vpAtomID\n }\n }\n\n this.getSurface = function (type: string, probeRadius: number, scaleFactor: number, cutoff: number, setAtomID: boolean, smooth: number, contour: boolean) {\n var vd = this.getVolume(\n type, probeRadius, scaleFactor, cutoff, setAtomID\n )\n\n var volsurf = new (VolumeSurface as any)(\n vd.data, vd.nx, vd.ny, vd.nz, vd.atomindex\n ) as VolumeSurface\n\n return (volsurf!.getSurface as any)(1, smooth, undefined, matrix, contour)\n }\n\n function boundingatom (btype: boolean) {\n var r\n var j\n var k\n var txz\n var tdept\n var sradius\n var tradius\n var widxzR\n var deptyName\n var indx\n\n for (var name in radiusDict) {\n r = parseFloat(name)\n\n if (depty[ name ]) continue\n\n if (!btype) {\n tradius = r * scaleFactor + 0.5\n } else {\n tradius = (r + probeRadius) * scaleFactor + 0.5\n }\n\n sradius = tradius * tradius\n widxzR = Math.floor(tradius) + 1\n deptyName = new Int32Array(widxzR * widxzR)\n indx = 0\n\n for (j = 0; j < widxzR; ++j) {\n for (k = 0; k < widxzR; ++k) {\n txz = j * j + k * k\n\n if (txz > sradius) {\n deptyName[ indx ] = -1\n } else {\n tdept = Math.sqrt(sradius - txz)\n deptyName[ indx ] = Math.floor(tdept)\n }\n\n ++indx\n }\n }\n\n widxz[ name ] = widxzR\n depty[ name ] = deptyName\n }\n }\n\n function fillatom (idx: number) {\n var ci = idx * 3\n var ri = idx\n\n var cx, cy, cz, ox, oy, oz, mi, mj, mk, i, j, k, si, sj, sk\n var ii, jj, kk\n\n cx = Math.floor(0.5 + scaleFactor * (coordList[ ci ] + ptran[0]))\n cy = Math.floor(0.5 + scaleFactor * (coordList[ ci + 1 ] + ptran[1]))\n cz = Math.floor(0.5 + scaleFactor * (coordList[ ci + 2 ] + ptran[2]))\n\n var at = radiusList[ ri ]\n var deptyAt = depty[ at ]\n var nind = 0\n var pWH = pWidth * pHeight\n var n = widxz[ at ]\n\n var deptyAtNind\n\n for (i = 0; i < n; ++i) {\n for (j = 0; j < n; ++j) {\n deptyAtNind = deptyAt[ nind ]\n\n if (deptyAtNind !== -1) {\n for (ii = -1; ii < 2; ++ii) {\n for (jj = -1; jj < 2; ++jj) {\n for (kk = -1; kk < 2; ++kk) {\n if (ii !== 0 && jj !== 0 && kk !== 0) {\n mi = ii * i\n mk = kk * j\n\n for (k = 0; k <= deptyAtNind; ++k) {\n mj = k * jj\n si = cx + mi\n sj = cy + mj\n sk = cz + mk\n\n if (si < 0 || sj < 0 || sk < 0 ||\n si >= pLength || sj >= pWidth || sk >= pHeight\n ) {\n continue\n }\n\n var index = si * pWH + sj * pHeight + sk\n\n if (!setAtomID) {\n vpBits[ index ] |= INOUT\n } else {\n if (!(vpBits[ index ] & INOUT)) {\n vpBits[ index ] |= INOUT\n vpAtomID[ index ] = idx\n } else if (vpBits[ index ] & INOUT) {\n var ci2 = vpAtomID[ index ]\n\n if (ci2 !== ci) {\n ox = cx + mi - Math.floor(0.5 + scaleFactor * (coordList[ci2] + ptran[0]))\n oy = cy + mj - Math.floor(0.5 + scaleFactor * (coordList[ci2 + 1] + ptran[1]))\n oz = cz + mk - Math.floor(0.5 + scaleFactor * (coordList[ci2 + 2] + ptran[2]))\n\n if (mi * mi + mj * mj + mk * mk < ox * ox + oy * oy + oz * oz) {\n vpAtomID[ index ] = idx\n }\n }\n }\n }\n } // k\n } // if\n } // kk\n } // jj\n } // ii\n } // if\n\n nind++\n } // j\n } // i\n }\n\n function fillvoxels (btype: boolean) {\n console.time('EDTSurface fillvoxels')\n\n var i, il\n\n for (i = 0, il = vpBits.length; i < il; ++i) {\n vpBits[ i ] = 0\n if (btype) vpDistance[ i ] = -1.0\n if (setAtomID) vpAtomID[ i ] = -1\n }\n\n for (i = 0, il = coordList.length / 3; i < il; ++i) {\n fillatom(i)\n }\n\n for (i = 0, il = vpBits.length; i < il; ++i) {\n if (vpBits[ i ] & INOUT) {\n vpBits[ i ] |= ISDONE\n }\n }\n\n console.timeEnd('EDTSurface fillvoxels')\n }\n\n function fillAtomWaals (idx: number) {\n var ci = idx * 3\n var ri = idx\n\n var cx\n var cy\n var cz\n var ox\n var oy\n var oz\n var nind = 0\n\n var mi\n var mj\n var mk\n var si\n var sj\n var sk\n var i\n var j\n var k\n var ii\n var jj\n var kk\n var n\n\n cx = Math.floor(0.5 + scaleFactor * (coordList[ ci ] + ptran[0]))\n cy = Math.floor(0.5 + scaleFactor * (coordList[ ci + 1 ] + ptran[1]))\n cz = Math.floor(0.5 + scaleFactor * (coordList[ ci + 2 ] + ptran[2]))\n\n var at = radiusList[ ri ]\n var pWH = pWidth * pHeight\n\n for (i = 0, n = widxz[at]; i < n; ++i) {\n for (j = 0; j < n; ++j) {\n if (depty[ at ][ nind ] !== -1) {\n for (ii = -1; ii < 2; ++ii) {\n for (jj = -1; jj < 2; ++jj) {\n for (kk = -1; kk < 2; ++kk) {\n if (ii !== 0 && jj !== 0 && kk !== 0) {\n mi = ii * i\n mk = kk * j\n\n for (k = 0; k <= depty[ at ][ nind ]; ++k) {\n mj = k * jj\n si = cx + mi\n sj = cy + mj\n sk = cz + mk\n\n if (si < 0 || sj < 0 || sk < 0 ||\n si >= pLength || sj >= pWidth || sk >= pHeight\n ) {\n continue\n }\n\n var index = si * pWH + sj * pHeight + sk\n\n if (!(vpBits[ index ] & ISDONE)) {\n vpBits[ index ] |= ISDONE\n if (setAtomID) vpAtomID[ index ] = idx\n } else if (setAtomID) {\n var ci2 = vpAtomID[ index ]\n\n ox = Math.floor(0.5 + scaleFactor * (coordList[ ci2 ] + ptran[0]))\n oy = Math.floor(0.5 + scaleFactor * (coordList[ ci2 + 1 ] + ptran[1]))\n oz = Math.floor(0.5 + scaleFactor * (coordList[ ci2 + 2 ] + ptran[2]))\n\n if (mi * mi + mj * mj + mk * mk < ox * ox + oy * oy + oz * oz) {\n vpAtomID[ index ] = idx\n }\n }\n } // k\n } // if\n } // kk\n } // jj\n } // ii\n } // if\n\n nind++\n } // j\n } // i\n }\n\n function fillvoxelswaals () {\n var i, il\n\n for (i = 0, il = vpBits.length; i < il; ++i) {\n vpBits[ i ] &= ~ISDONE // not isdone\n }\n\n for (i = 0, il = coordList.length / 3; i < il; ++i) {\n fillAtomWaals(i)\n }\n }\n\n function buildboundary () {\n var i, j, k\n var pWH = pWidth * pHeight\n\n for (i = 0; i < pLength; ++i) {\n for (j = 0; j < pHeight; ++j) {\n for (k = 0; k < pWidth; ++k) {\n var index = i * pWH + k * pHeight + j\n\n if (vpBits[ index ] & INOUT) {\n // var flagbound = false;\n var ii = 0\n\n // while( !flagbound && ii < 26 ){\n while (ii < 26) {\n var ti = i + nb[ ii ][ 0 ]\n var tj = j + nb[ ii ][ 2 ]\n var tk = k + nb[ ii ][ 1 ]\n\n if (ti > -1 && ti < pLength &&\n tk > -1 && tk < pWidth &&\n tj > -1 && tj < pHeight &&\n !(vpBits[ ti * pWH + tk * pHeight + tj ] & INOUT)\n ) {\n vpBits[ index ] |= ISBOUND\n // flagbound = true;\n break\n } else {\n ii++\n }\n }\n }\n } // k\n } // j\n } // i\n }\n\n function fastdistancemap () {\n console.time('EDTSurface fastdistancemap')\n\n var i, j, k, n\n\n var boundPoint = makeGrid(\n pLength, pWidth, pHeight, Uint16Array, 3\n )\n var pWH = pWidth * pHeight\n var cutRSq = cutRadius * cutRadius\n\n var totalsurfacevox = 0\n // var totalinnervox = 0;\n\n var index\n\n for (i = 0; i < pLength; ++i) {\n for (j = 0; j < pWidth; ++j) {\n for (k = 0; k < pHeight; ++k) {\n index = i * pWH + j * pHeight + k\n\n vpBits[ index ] &= ~ISDONE\n\n if (vpBits[ index ] & INOUT) {\n if (vpBits[ index ] & ISBOUND) {\n boundPoint.set(\n i, j, k,\n i, j, k\n )\n\n vpDistance[ index ] = 0\n vpBits[ index ] |= ISDONE\n\n totalsurfacevox += 1\n }/* else{\n totalinnervox += 1;\n } */\n }\n }\n }\n }\n\n var inarray = new Int32Array(3 * totalsurfacevox)\n var positin = 0\n var outarray = new Int32Array(3 * totalsurfacevox)\n var positout = 0\n\n for (i = 0; i < pLength; ++i) {\n for (j = 0; j < pWidth; ++j) {\n for (k = 0; k < pHeight; ++k) {\n index = i * pWH + j * pHeight + k\n\n if (vpBits[ index ] & ISBOUND) {\n inarray[ positin ] = i\n inarray[ positin + 1 ] = j\n inarray[ positin + 2 ] = k\n positin += 3\n\n vpBits[ index ] &= ~ISBOUND\n }\n }\n }\n }\n\n do {\n positout = fastoneshell(inarray, boundPoint, positin, outarray)\n positin = 0\n\n for (i = 0, n = positout; i < n; i += 3) {\n index = pWH * outarray[ i ] + pHeight * outarray[ i + 1 ] + outarray[ i + 2 ]\n vpBits[ index ] &= ~ISBOUND\n\n if (vpDistance[ index ] <= 1.0404 * cutRSq) {\n // if( vpDistance[ index ] <= 1.02 * cutRadius ){\n\n inarray[ positin ] = outarray[ i ]\n inarray[ positin + 1 ] = outarray[ i + 1 ]\n inarray[ positin + 2 ] = outarray[ i + 2 ]\n positin += 3\n }\n }\n } while (positin > 0)\n\n // var cutsf = Math.max( 0, scaleFactor - 0.5 );\n // cutoff = cutRadius - 0.5 / ( 0.1 + cutsf );\n var cutoffSq = cutoff * cutoff\n\n var index2\n var bp = new Uint16Array(3)\n\n for (i = 0; i < pLength; ++i) {\n for (j = 0; j < pWidth; ++j) {\n for (k = 0; k < pHeight; ++k) {\n index = i * pWH + j * pHeight + k\n vpBits[ index ] &= ~ISBOUND\n\n // ses solid\n\n if (vpBits[ index ] & INOUT) {\n if (!(vpBits[ index ] & ISDONE) ||\n ((vpBits[ index ] & ISDONE) && vpDistance[ index ] >= cutoffSq)\n ) {\n vpBits[ index ] |= ISBOUND\n\n if (setAtomID && (vpBits[ index ] & ISDONE)) {\n boundPoint.toArray(i, j, k, bp)\n index2 = bp[ 0 ] * pWH + bp[ 1 ] * pHeight + bp[ 2 ]\n\n vpAtomID[ index ] = vpAtomID[ index2 ]\n }\n }\n }\n }\n }\n }\n\n console.timeEnd('EDTSurface fastdistancemap')\n }\n\n function fastoneshell (inarray: Int32Array, boundPoint: iGrid, positin: number, outarray: Int32Array) {\n // *allocout,voxel2\n // ***boundPoint, int*\n // outnum, int *elimi)\n var tx, ty, tz\n var dx, dy, dz\n var i, j, n\n var square\n var index\n var nbj\n var bp = new Uint16Array(3)\n var positout = 0\n\n if (positin === 0) {\n return positout\n }\n\n var tnvix = -1\n var tnviy = -1\n var tnviz = -1\n\n var pWH = pWidth * pHeight\n\n for (i = 0, n = positin; i < n; i += 3) {\n tx = inarray[ i ]\n ty = inarray[ i + 1 ]\n tz = inarray[ i + 2 ]\n boundPoint.toArray(tx, ty, tz, bp)\n\n for (j = 0; j < 6; ++j) {\n nbj = nb[ j ]\n tnvix = tx + nbj[ 0 ]\n tnviy = ty + nbj[ 1 ]\n tnviz = tz + nbj[ 2 ]\n\n if (tnvix < pLength && tnvix > -1 &&\n tnviy < pWidth && tnviy > -1 &&\n tnviz < pHeight && tnviz > -1\n ) {\n index = tnvix * pWH + pHeight * tnviy + tnviz\n\n if ((vpBits[ index ] & INOUT) && !(vpBits[ index ] & ISDONE)) {\n boundPoint.fromArray(tnvix, tnviy, tnviz, bp)\n dx = tnvix - bp[ 0 ]\n dy = tnviy - bp[ 1 ]\n dz = tnviz - bp[ 2 ]\n square = dx * dx + dy * dy + dz * dz\n // square = Math.sqrt( square );\n\n vpDistance[ index ] = square\n vpBits[ index ] |= ISDONE\n vpBits[ index ] |= ISBOUND\n\n outarray[ positout ] = tnvix\n outarray[ positout + 1 ] = tnviy\n outarray[ positout + 2 ] = tnviz\n positout += 3\n } else if ((vpBits[ index ] & INOUT) && (vpBits[ index ] & ISDONE)) {\n dx = tnvix - bp[ 0 ]\n dy = tnviy - bp[ 1 ]\n dz = tnviz - bp[ 2 ]\n square = dx * dx + dy * dy + dz * dz\n // square = Math.sqrt( square );\n\n if (square < vpDistance[ index ]) {\n boundPoint.fromArray(tnvix, tnviy, tnviz, bp)\n vpDistance[ index ] = square\n\n if (!(vpBits[ index ] & ISBOUND)) {\n vpBits[ index ] |= ISBOUND\n\n outarray[ positout ] = tnvix\n outarray[ positout + 1 ] = tnviy\n outarray[ positout + 2 ] = tnviz\n positout += 3\n }\n }\n }\n }\n }\n }\n\n for (i = 0, n = positin; i < n; i += 3) {\n tx = inarray[ i ]\n ty = inarray[ i + 1 ]\n tz = inarray[ i + 2 ]\n boundPoint.toArray(tx, ty, tz, bp)\n\n for (j = 6; j < 18; j++) {\n nbj = nb[ j ]\n tnvix = tx + nbj[ 0 ]\n tnviy = ty + nbj[ 1 ]\n tnviz = tz + nbj[ 2 ]\n\n if (tnvix < pLength && tnvix > -1 &&\n tnviy < pWidth && tnviy > -1 &&\n tnviz < pHeight && tnviz > -1\n ) {\n index = tnvix * pWH + pHeight * tnviy + tnviz\n\n if ((vpBits[index] & INOUT) && !(vpBits[index] & ISDONE)) {\n boundPoint.fromArray(tnvix, tnviy, tnviz, bp)\n dx = tnvix - bp[ 0 ]\n dy = tnviy - bp[ 1 ]\n dz = tnviz - bp[ 2 ]\n square = dx * dx + dy * dy + dz * dz\n // square = Math.sqrt( square );\n\n vpDistance[index] = square\n vpBits[index] |= ISDONE\n vpBits[index] |= ISBOUND\n\n outarray[ positout ] = tnvix\n outarray[ positout + 1 ] = tnviy\n outarray[ positout + 2 ] = tnviz\n positout += 3\n } else if ((vpBits[index] & INOUT) && (vpBits[index] & ISDONE)) {\n dx = tnvix - bp[ 0 ]\n dy = tnviy - bp[ 1 ]\n dz = tnviz - bp[ 2 ]\n square = dx * dx + dy * dy + dz * dz\n // square = Math.sqrt( square );\n\n if (square < vpDistance[index]) {\n boundPoint.fromArray(tnvix, tnviy, tnviz, bp)\n vpDistance[index] = square\n\n if (!(vpBits[index] & ISBOUND)) {\n vpBits[index] |= ISBOUND\n\n outarray[ positout ] = tnvix\n outarray[ positout + 1 ] = tnviy\n outarray[ positout + 2 ] = tnviz\n positout += 3\n }\n }\n }\n }\n }\n }\n\n for (i = 0, n = positin; i < n; i += 3) {\n tx = inarray[ i ]\n ty = inarray[ i + 1 ]\n tz = inarray[ i + 2 ]\n boundPoint.toArray(tx, ty, tz, bp)\n\n for (j = 18; j < 26; j++) {\n nbj = nb[ j ]\n tnvix = tx + nbj[ 0 ]\n tnviy = ty + nbj[ 1 ]\n tnviz = tz + nbj[ 2 ]\n\n if (tnvix < pLength && tnvix > -1 &&\n tnviy < pWidth && tnviy > -1 &&\n tnviz < pHeight && tnviz > -1\n ) {\n index = tnvix * pWH + pHeight * tnviy + tnviz\n\n if ((vpBits[index] & INOUT) && !(vpBits[index] & ISDONE)) {\n boundPoint.fromArray(tnvix, tnviy, tnviz, bp)\n dx = tnvix - bp[ 0 ]\n dy = tnviy - bp[ 1 ]\n dz = tnviz - bp[ 2 ]\n square = dx * dx + dy * dy + dz * dz\n // square = Math.sqrt( square );\n\n vpDistance[index] = square\n vpBits[index] |= ISDONE\n vpBits[index] |= ISBOUND\n\n outarray[ positout ] = tnvix\n outarray[ positout + 1 ] = tnviy\n outarray[ positout + 2 ] = tnviz\n positout += 3\n } else if ((vpBits[index] & INOUT) && (vpBits[index] & ISDONE)) {\n dx = tnvix - bp[ 0 ]\n dy = tnviy - bp[ 1 ]\n dz = tnviz - bp[ 2 ]\n square = dx * dx + dy * dy + dz * dz\n // square = Math.sqrt( square );\n\n if (square < vpDistance[index]) {\n boundPoint.fromArray(tnvix, tnviy, tnviz, bp)\n vpDistance[index] = square\n\n if (!(vpBits[index] & ISBOUND)) {\n vpBits[index] |= ISBOUND\n\n outarray[ positout ] = tnvix\n outarray[ positout + 1 ] = tnviy\n outarray[ positout + 2 ] = tnviz\n positout += 3\n }\n }\n }\n }\n }\n }\n\n return positout\n }\n\n function marchingcubeinit (stype: string) {\n var i\n var n = vpBits.length\n\n if (stype === 'vws') {\n for (i = 0; i < n; ++i) {\n vpBits[ i ] &= ~ISBOUND\n vpBits[ i ] = (vpBits[ i ] & ISDONE) ? 1 : 0\n }\n } else if (stype === 'ms') { // ses without vdw => ms\n for (i = 0; i < n; ++i) {\n vpBits[ i ] &= ~ISDONE\n if (vpBits[ i ] & ISBOUND) {\n vpBits[ i ] |= ISDONE\n }\n vpBits[ i ] &= ~ISBOUND\n vpBits[ i ] = (vpBits[ i ] & ISDONE) ? 1 : 0\n }\n } else if (stype === 'ses') {\n for (i = 0; i < n; ++i) {\n if ((vpBits[ i ] & ISBOUND) && (vpBits[ i ] & ISDONE)) {\n vpBits[ i ] &= ~ISBOUND\n } else if ((vpBits[ i ] & ISBOUND) && !(vpBits[ i ] & ISDONE)) {\n vpBits[ i ] |= ISDONE\n }\n vpBits[ i ] = (vpBits[ i ] & ISDONE) ? 1 : 0\n }\n } else if (stype === 'sas') {\n for (i = 0; i < n; ++i) {\n vpBits[ i ] &= ~ISBOUND\n vpBits[ i ] = (vpBits[ i ] & ISDONE) ? 1 : 0\n }\n }\n }\n}\nObject.assign(EDTSurface, {__deps: [\n getSurfaceGrid, getRadiusDict, VolumeSurface, computeBoundingBox, makeGrid\n]})\n\nexport default EDTSurface\n","/**\n * @file AV Surface\n * @author Fred Ludlow \n * @private\n */\n\nimport { getSurfaceGrid } from './surface-utils'\nimport { VolumeSurface } from './volume'\nimport { uniformArray } from '../math/array-utils'\nimport {\n computeBoundingBox, v3multiplyScalar, v3cross, v3normalize\n} from '../math/vector-utils'\nimport { defaults } from '../utils'\nimport { NumberArray } from '../types';\n\n\n/**\n * Modifed from SpatialHash\n *\n * Main differences are:\n * - Optimized grid size to ensure we only ever need to look +/-1 cell\n * - Aware of atomic radii and will only output atoms within rAtom + rExtra\n * (see withinRadii method)\n *\n * (Uses rounding rather than bitshifting as consequence of arbitrary grid size)\n * @class\n * @param {Float32Array} atomsX - x coordinates\n * @param {Float32Array} atomsY - y coordinates\n * @param {Float32Array} atomsZ - z coordinates\n * @param {Float32Array} atomsR - atom radii\n * @param {Float32Array} min - xyz min coordinates\n * @param {Float32Array} max - xyz max coordinates\n * @param {Float} maxDistance - max distance\n */\nexport interface iAVHash {\n neighbourListLength: number\n withinRadii: (x: number, y: number, z: number, rExtra: number, out: Int32Array) => void\n}\n\n\nfunction makeAVHash (atomsX: Float32Array, atomsY: Float32Array, atomsZ: Float32Array, atomsR: Float32Array, min: Float32Array, max: Float32Array, maxDistance: number): iAVHash {\n maxDistance = Math.max(0.1, maxDistance) // Avoid maxDistance of zero, see #802\n var nAtoms = atomsX.length\n\n var minX = min[ 0 ]\n var minY = min[ 1 ]\n var minZ = min[ 2 ]\n\n var maxX = max[ 0 ]\n var maxY = max[ 1 ]\n var maxZ = max[ 2 ]\n\n function hashFunc (w: number, minW: number) {\n return Math.floor((w - minW) / maxDistance)\n }\n\n var iDim = hashFunc(maxX, minX) + 1\n var jDim = hashFunc(maxY, minY) + 1\n var kDim = hashFunc(maxZ, minZ) + 1\n\n var nCells = iDim * jDim * kDim\n\n var jkDim = jDim * kDim\n\n /* Get cellID for cartesian x,y,z */\n var cellID = function (x: number, y: number, z: number) {\n return (((hashFunc(x, minX) * jDim) + hashFunc(y, minY)) * kDim) + hashFunc(z, minZ)\n }\n\n /* Initial building, could probably be optimized further */\n var preHash = [] // preHash[ cellID ] = [ atomId1, atomId2 ];\n\n for (var i = 0; i < nAtoms; i++) {\n var cid = cellID(atomsX[ i ], atomsY[ i ], atomsZ[ i ])\n\n if (preHash[ cid ] === undefined) {\n preHash[ cid ] = [ i ]\n } else {\n preHash[ cid ].push(i)\n }\n }\n\n var cellOffsets = new Uint32Array(nCells)\n var cellLengths = new Uint16Array(nCells)\n var data = new Uint32Array(nAtoms)\n\n var offset = 0\n var maxCellLength = 0\n\n for (i = 0; i < nCells; i++) {\n var start = cellOffsets[ i ] = offset\n\n var subArray = preHash[ i ]\n\n if (subArray !== undefined) {\n for (var j = 0; j < subArray.length; j++) {\n data[ offset ] = subArray[ j ]\n offset++\n }\n }\n\n var cellLength = offset - start\n cellLengths[ i ] = cellLength\n\n if (cellLength > maxCellLength) { maxCellLength = cellLength }\n }\n\n // Maximum number of neighbours we could ever produce (27 adjacent cells of equal population)\n const neighbourListLength = (27 * maxCellLength) + 1\n\n /**\n * Populate the supplied out array with atom indices that are within rAtom + rExtra\n * of x,y,z\n *\n * -1 in out array indicates the end of the list\n *\n * @param {Float} x - x coordinate\n * @param {Float} y - y coordinate\n * @param {Float} z - z coordinate\n * @param {Float} rExtra - additional radius\n * @param {Float32Array} out - pre-allocated output array\n * @return {undefined}\n */\n const withinRadii = function (x: number, y: number, z: number, rExtra: number, out: Int32Array) {\n var outIdx = 0\n\n var nearI = hashFunc(x, minX)\n var nearJ = hashFunc(y, minY)\n var nearK = hashFunc(z, minZ)\n\n var loI = Math.max(0, nearI - 1)\n var loJ = Math.max(0, nearJ - 1)\n var loK = Math.max(0, nearK - 1)\n\n var hiI = Math.min(iDim, nearI + 2)\n var hiJ = Math.min(jDim, nearJ + 2)\n var hiK = Math.min(kDim, nearK + 2)\n\n for (var i = loI; i < hiI; ++i) {\n var iOffset = i * jkDim\n\n for (var j = loJ; j < hiJ; ++j) {\n var jOffset = j * kDim\n\n for (var k = loK; k < hiK; ++k) {\n var cid = iOffset + jOffset + k\n\n var cellStart = cellOffsets[ cid ]\n var cellEnd = cellStart + cellLengths[ cid ]\n\n for (var dataIndex = cellStart; dataIndex < cellEnd; dataIndex++) {\n var atomIndex = data[ dataIndex ]\n var dx = atomsX[ atomIndex ] - x\n var dy = atomsY[ atomIndex ] - y\n var dz = atomsZ[ atomIndex ] - z\n var rSum = atomsR[ atomIndex ] + rExtra\n\n if ((dx * dx + dy * dy + dz * dz) <= (rSum * rSum)) {\n out[ outIdx++ ] = data[ dataIndex ]\n }\n }\n }\n }\n }\n // Add terminator\n out[ outIdx ] = -1\n }\n return {\n neighbourListLength: neighbourListLength,\n withinRadii: withinRadii\n }\n}\n\ninterface AVSurface {\n getSurface: (type: string, probeRadius: number, scaleFactor: number, cutoff: number, setAtomID: boolean, smooth: number, contour: boolean) => any\n}\nfunction AVSurface (this: AVSurface, coordList: Float32Array, radiusList: Float32Array, indexList: Uint16Array|Uint32Array) {\n // Field generation method adapted from AstexViewer (Mike Hartshorn)\n // by Fred Ludlow.\n // Other parts based heavily on NGL (Alexander Rose) EDT Surface class\n //\n // Should work as a drop-in alternative to EDTSurface (though some of\n // the EDT paramters are not relevant in this method).\n\n const nAtoms = radiusList.length\n\n const x = new Float32Array(nAtoms)\n const y = new Float32Array(nAtoms)\n const z = new Float32Array(nAtoms)\n\n for (let i = 0; i < nAtoms; i++) {\n const ci = 3 * i\n x[ i ] = coordList[ ci ]\n y[ i ] = coordList[ ci + 1 ]\n z[ i ] = coordList[ ci + 2 ]\n }\n\n let bbox = computeBoundingBox(coordList)\n if (coordList.length === 0) {\n bbox[ 0 ].set([ 0, 0, 0 ])\n bbox[ 1 ].set([ 0, 0, 0 ])\n }\n const min = bbox[0]\n const max = bbox[1]\n\n let r: Float32Array, r2: Float32Array // Atom positions, expanded radii (squared)\n let maxRadius: number\n\n // Parameters\n let probeRadius: number, scaleFactor: number, setAtomID: boolean, probePositions: number\n\n // Cache last value for obscured test\n let lastClip = -1\n\n // Grid params\n let dim: Float32Array, matrix: Float32Array, grid: NumberArray, atomIndex: Int32Array\n\n // grid indices -> xyz coords\n let gridx: Float32Array, gridy: Float32Array, gridz: Float32Array\n\n // Lookup tables:\n let sinTable: Float32Array, cosTable: Float32Array\n\n // Spatial Hash\n let hash: iAVHash\n\n // Neighbour array to be filled by hash\n let neighbours: Int32Array\n\n // Vectors for Torus Projection\n const atob = new Float32Array([ 0.0, 0.0, 0.0 ])\n const mid = new Float32Array([ 0.0, 0.0, 0.0 ])\n const n1 = new Float32Array([ 0.0, 0.0, 0.0 ])\n const n2 = new Float32Array([ 0.0, 0.0, 0.0 ])\n\n let ngTorus: number\n\n function init (_probeRadius?: number, _scaleFactor?: number, _setAtomID?: boolean, _probePositions?: number) {\n probeRadius = defaults(_probeRadius, 1.4)\n scaleFactor = defaults(_scaleFactor, 2.0)\n setAtomID = defaults(_setAtomID, true)\n probePositions = defaults(_probePositions, 30)\n\n r = new Float32Array(nAtoms)\n r2 = new Float32Array(nAtoms)\n\n for (let i = 0; i < r.length; ++i) {\n var rExt = radiusList[ i ] + probeRadius\n r[ i ] = rExt\n r2[ i ] = rExt * rExt\n }\n\n maxRadius = 0\n for (let j = 0; j < r.length; ++j) {\n if (r[ j ] > maxRadius) maxRadius = r[ j ]\n }\n\n initializeGrid()\n initializeAngleTables()\n initializeHash()\n\n lastClip = -1\n }\n\n function fillGridDim (a: Float32Array, start: number, step: number) {\n for (let i = 0; i < a.length; i++) {\n a[i] = start + (step * i)\n }\n }\n\n function initializeGrid () {\n const surfGrid = getSurfaceGrid(\n min, max, maxRadius, scaleFactor, 0.0\n )\n\n scaleFactor = surfGrid.scaleFactor\n dim = surfGrid.dim\n matrix = surfGrid.matrix\n\n ngTorus = Math.max(5, 2 + Math.floor(probeRadius * scaleFactor))\n\n grid = uniformArray(dim[0] * dim[1] * dim[2], -1001.0)\n\n atomIndex = new Int32Array(grid.length)\n\n gridx = new Float32Array(dim[0])\n gridy = new Float32Array(dim[1])\n gridz = new Float32Array(dim[2])\n\n fillGridDim(gridx, min[0], 1 / scaleFactor)\n fillGridDim(gridy, min[1], 1 / scaleFactor)\n fillGridDim(gridz, min[2], 1 / scaleFactor)\n }\n\n function initializeAngleTables () {\n var theta = 0.0\n var step = 2 * Math.PI / probePositions\n\n cosTable = new Float32Array(probePositions)\n sinTable = new Float32Array(probePositions)\n for (var i = 0; i < probePositions; i++) {\n cosTable[ i ] = Math.cos(theta)\n sinTable[ i ] = Math.sin(theta)\n theta += step\n }\n }\n\n function initializeHash () {\n hash = makeAVHash(x, y, z, r, min, max, 2.01 * maxRadius)\n neighbours = new Int32Array(hash.neighbourListLength)\n }\n\n function obscured (x: number, y: number, z: number, a: number, b: number) {\n // Is the point at x,y,z obscured by any of the atoms\n // specifeid by indices in neighbours. Ignore indices\n // a and b (these are the relevant atoms in projectPoints/Torii)\n\n // Cache the last clipped atom (as very often the same one in\n // subsequent calls)\n let ai: number\n\n if (lastClip !== -1) {\n ai = lastClip\n if (ai !== a && ai !== b && singleAtomObscures(ai, x, y, z)) {\n return ai\n } else {\n lastClip = -1\n }\n }\n\n var ni = 0\n ai = neighbours[ ni ]\n while (ai >= 0) {\n if (ai !== a && ai !== b && singleAtomObscures(ai, x, y, z)) {\n lastClip = ai\n return ai\n }\n ai = neighbours[ ++ni ]\n }\n\n lastClip = -1\n\n return -1\n }\n\n function singleAtomObscures (ai: number, x: number, y: number, z: number) {\n var ci = 3 * ai\n var ra2 = r2[ ai ]\n var dx = coordList[ ci ] - x\n var dy = coordList[ ci + 1 ] - y\n var dz = coordList[ ci + 2 ] - z\n var d2 = dx * dx + dy * dy + dz * dz\n\n return d2 < ra2\n }\n\n function projectPoints () {\n // For each atom:\n // Iterate over a subsection of the grid, for each point:\n // If current value < 0.0, unvisited, set positive\n //\n // In any case: Project this point onto surface of the atomic sphere\n // If this projected point is not obscured by any other atom\n // Calcualte delta distance and set grid value to minimum of\n // itself and delta\n\n // Should we alias frequently accessed closure variables??\n // Assume JS engine capable of optimizing this\n // anyway...\n\n for (var i = 0; i < nAtoms; i++) {\n var ax = x[ i ]\n var ay = y[ i ]\n var az = z[ i ]\n var ar = r[ i ]\n var ar2 = r2[ i ]\n\n hash.withinRadii(ax, ay, az, ar, neighbours)\n\n // Number of grid points, round this up...\n var ng = Math.ceil(ar * scaleFactor)\n\n // Center of the atom, mapped to grid points (take floor)\n var iax = Math.floor(scaleFactor * (ax - min[ 0 ]))\n var iay = Math.floor(scaleFactor * (ay - min[ 1 ]))\n var iaz = Math.floor(scaleFactor * (az - min[ 2 ]))\n\n // Extents of grid to consider for this atom\n var minx = Math.max(0, iax - ng)\n var miny = Math.max(0, iay - ng)\n var minz = Math.max(0, iaz - ng)\n\n // Add two to these points:\n // - iax are floor'd values so this ensures coverage\n // - these are loop limits (exclusive)\n var maxx = Math.min(dim[ 0 ], iax + ng + 2)\n var maxy = Math.min(dim[ 1 ], iay + ng + 2)\n var maxz = Math.min(dim[ 2 ], iaz + ng + 2)\n\n for (var ix = minx; ix < maxx; ix++) {\n var dx = gridx[ ix ] - ax\n var xoffset = dim[ 1 ] * dim[ 2 ] * ix\n\n for (var iy = miny; iy < maxy; iy++) {\n var dy = gridy[ iy ] - ay\n var dxy2 = dx * dx + dy * dy\n var xyoffset = xoffset + dim[ 2 ] * iy\n\n for (var iz = minz; iz < maxz; iz++) {\n var dz = gridz[ iz ] - az\n var d2 = dxy2 + dz * dz\n\n if (d2 < ar2) {\n var idx = iz + xyoffset\n\n if (grid[idx] < 0.0) {\n // Unvisited, make positive\n grid[ idx ] = -grid[ idx ]\n }\n // Project on to the surface of the sphere\n // sp is the projected point ( dx, dy, dz ) * ( ra / d )\n var d = Math.sqrt(d2)\n var ap = ar / d\n var spx = dx * ap\n var spy = dy * ap\n var spz = dz * ap\n\n spx += ax\n spy += ay\n spz += az\n\n if (obscured(spx, spy, spz, i, -1) === -1) {\n var dd = ar - d\n if (dd < grid[ idx ]) {\n grid[ idx ] = dd\n if (setAtomID) atomIndex[ idx ] = i\n }\n }\n }\n }\n }\n }\n }\n }\n\n function projectTorii () {\n for (var i = 0; i < nAtoms; i++) {\n hash.withinRadii(x[ i ], y[ i ], z[ i ], r[ i ], neighbours)\n var ia = 0\n var ni = neighbours[ ia ]\n while (ni >= 0) {\n if (i < ni) {\n projectTorus(i, ni)\n }\n ni = neighbours[ ++ia ]\n }\n }\n }\n\n function projectTorus (a: number, b: number) {\n var r1 = r[ a ]\n var r2 = r[ b ]\n var dx = atob[ 0 ] = x[ b ] - x[ a ]\n var dy = atob[ 1 ] = y[ b ] - y[ a ]\n var dz = atob[ 2 ] = z[ b ] - z[ a ]\n var d2 = dx * dx + dy * dy + dz * dz\n\n // This check now redundant as already done in AVHash.withinRadii\n // if( d2 > (( r1 + r2 ) * ( r1 + r2 )) ){ return; }\n\n var d = Math.sqrt(d2)\n\n // Find angle between a->b vector and the circle\n // of their intersection by cosine rule\n var cosA = (r1 * r1 + d * d - r2 * r2) / (2.0 * r1 * d)\n\n // distance along a->b at intersection\n var dmp = r1 * cosA\n\n v3normalize(atob, atob)\n\n // Create normal to line\n normalToLine(n1 as any, atob)\n v3normalize(n1, n1)\n\n // Cross together for second normal vector\n v3cross(n2, atob, n1)\n v3normalize(n2, n2)\n\n // r is radius of circle of intersection\n var rInt = Math.sqrt(r1 * r1 - dmp * dmp)\n\n v3multiplyScalar(n1, n1, rInt)\n v3multiplyScalar(n2, n2, rInt)\n v3multiplyScalar(atob, atob, dmp)\n\n mid[ 0 ] = atob[ 0 ] + x[ a ]\n mid[ 1 ] = atob[ 1 ] + y[ a ]\n mid[ 2 ] = atob[ 2 ] + z[ a ]\n\n lastClip = -1\n\n var ng = ngTorus\n\n for (var i = 0; i < probePositions; i++) {\n var cost = cosTable[ i ]\n var sint = sinTable[ i ]\n\n var px = mid[ 0 ] + cost * n1[ 0 ] + sint * n2[ 0 ]\n var py = mid[ 1 ] + cost * n1[ 1 ] + sint * n2[ 1 ]\n var pz = mid[ 2 ] + cost * n1[ 2 ] + sint * n2[ 2 ]\n\n if (obscured(px, py, pz, a, b) === -1) {\n // As above, iterate over our grid...\n // px, py, pz in grid coords\n var iax = Math.floor(scaleFactor * (px - min[ 0 ]))\n var iay = Math.floor(scaleFactor * (py - min[ 1 ]))\n var iaz = Math.floor(scaleFactor * (pz - min[ 2 ]))\n\n var minx = Math.max(0, iax - ng)\n var miny = Math.max(0, iay - ng)\n var minz = Math.max(0, iaz - ng)\n\n var maxx = Math.min(dim[ 0 ], iax + ng + 2)\n var maxy = Math.min(dim[ 1 ], iay + ng + 2)\n var maxz = Math.min(dim[ 2 ], iaz + ng + 2)\n\n for (var ix = minx; ix < maxx; ix++) {\n dx = px - gridx[ ix ]\n var xoffset = dim[ 1 ] * dim[ 2 ] * ix\n\n for (var iy = miny; iy < maxy; iy++) {\n dy = py - gridy[ iy ]\n var dxy2 = dx * dx + dy * dy\n var xyoffset = xoffset + dim[ 2 ] * iy\n\n for (var iz = minz; iz < maxz; iz++) {\n dz = pz - gridz[ iz ]\n d2 = dxy2 + dz * dz\n var idx = iz + xyoffset\n var current = grid[ idx ]\n\n if (current > 0.0 && d2 < (current * current)) {\n grid[ idx ] = Math.sqrt(d2)\n if (setAtomID) {\n // Is this grid point closer to a or b?\n // Take dot product of atob and gridpoint->p (dx, dy, dz)\n const dp = dx * atob[ 0 ] + dy * atob [ 1 ] + dz * atob[ 2 ]\n atomIndex[ idx ] = dp < 0.0 ? b : a\n }\n }\n }\n }\n }\n }\n }\n }\n\n function normalToLine (out: Int32Array, p: Float32Array) {\n out[ 0 ] = out[ 1 ] = out[ 2 ] = 1.0\n if (p[ 0 ] !== 0) {\n out[ 0 ] = (p[ 1 ] + p[ 2 ]) / -p[ 0 ]\n } else if (p[ 1 ] !== 0) {\n out[ 1 ] = (p[ 0 ] + p[ 2 ]) / -p[ 1 ]\n } else if (p[ 2 ] !== 0) {\n out[ 2 ] = (p[ 0 ] + p[ 1 ]) / -p[ 2 ]\n }\n return out\n }\n\n function fixNegatives () {\n for (var i = 0; i < grid.length; i++) {\n if (grid[ i ] < 0) grid[ i ] = 0\n }\n }\n\n function fixAtomIDs () {\n for (var i = 0; i < atomIndex.length; i++) {\n atomIndex[ i ] = indexList[ atomIndex[ i ] ]\n }\n }\n\n function getVolume (probeRadius: number, scaleFactor: number, setAtomID: boolean) {\n // Basic steps are:\n // 1) Initialize\n // 2) Project points\n // 3) Project torii\n\n console.time('AVSurface.getVolume')\n\n console.time('AVSurface.init')\n init(probeRadius, scaleFactor, setAtomID)\n console.timeEnd('AVSurface.init')\n\n console.time('AVSurface.projectPoints')\n projectPoints()\n console.timeEnd('AVSurface.projectPoints')\n\n console.time('AVSurface.projectTorii')\n projectTorii()\n console.timeEnd('AVSurface.projectTorii')\n fixNegatives()\n fixAtomIDs()\n\n console.timeEnd('AVSurface.getVolume')\n }\n\n this.getSurface = function (type: string, probeRadius: number, scaleFactor: number, cutoff: number, setAtomID: boolean, smooth: number, contour: boolean) {\n // type and cutoff left in for compatibility with EDTSurface.getSurface\n // function signature\n\n getVolume(probeRadius, scaleFactor, setAtomID)\n\n var volsurf = new (VolumeSurface as any)(\n grid, dim[ 2 ], dim[ 1 ], dim[ 0 ], atomIndex\n ) as VolumeSurface\n\n return volsurf.getSurface!(probeRadius, false, undefined, matrix, contour)\n }\n}\nObject.assign(AVSurface, {__deps: [\n getSurfaceGrid, VolumeSurface, uniformArray, computeBoundingBox,\n v3multiplyScalar, v3cross, v3normalize,\n makeAVHash,\n defaults\n]})\n\nexport { AVSurface, makeAVHash }\n","/**\n * @file Molecular Surface\n * @author Alexander Rose \n * @private\n */\n\nimport { WorkerRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport Worker from '../worker/worker'\nimport EDTSurface from './edt-surface'\nimport { AVSurface } from './av-surface'\nimport Surface, { SurfaceData } from './surface'\nimport { Structure } from '../ngl';\nimport { AtomData, RadiusParams } from '../structure/structure-data';\n\nWorkerRegistry.add('molsurf', function func (e: any, callback: (data: any, buffers: any[])=> void) {\n const a = e.data.args\n const p = e.data.params\n if (a && p) {\n const SurfClass = (p.type === 'av') ? AVSurface : EDTSurface\n const surf = new (SurfClass as any)(a.coordList, a.radiusList, a.indexList) as AVSurface|EDTSurface\n const sd = surf.getSurface(\n p.type, p.probeRadius, p.scaleFactor, p.cutoff, true, p.smooth, p.contour\n ) as SurfaceData\n const transferList = [ sd.position.buffer, sd.index!.buffer ]\n if (sd.normal) transferList.push(sd.normal.buffer)\n if (sd.atomindex) transferList.push(sd.atomindex.buffer)\n const data = {\n sd: sd,\n p: p\n }\n callback(data, transferList)\n }\n}, [ EDTSurface, AVSurface ])\n\n/**\n * Molecular surface parameter object.\n * @typedef {Object} MolecularSurfaceParameters - stage parameters\n * @property {String} type - \"av\" or \"edt\"\n * @property {Number} probeRadius - probe radius\n * @property {Number} scaleFactor - higher for better quality\n * @property {Integer} smooth - number of smoothing cycles to apply\n * @property {String} name - name for created surface\n */\nexport interface MolecularSurfaceParameters {\n type: 'av'|'edt'\n probeRadius: number\n scaleFactor: number\n smooth: number\n name: string\n cutoff: number\n contour: boolean,\n radiusParams: RadiusParams\n}\n/**\n * Create Molecular surfaces\n */\nclass MolecularSurface {\n structure: Structure\n worker: Worker|undefined\n\n constructor (structure: Structure) {\n this.structure = structure\n }\n\n _getAtomData (params: Partial): AtomData {\n return this.structure.getAtomData({\n what: { position: true, radius: true, index: true },\n radiusParams: defaults(params.radiusParams, {\n type: 'vdw', scale: 1.0\n })\n })\n }\n\n _makeSurface (sd: SurfaceData, p: Partial) {\n var surface = new Surface(p.name!, '', sd)\n\n surface.info.type = p.type\n surface.info.probeRadius = p.probeRadius\n surface.info.scaleFactor = p.scaleFactor\n surface.info.smooth = p.smooth\n surface.info.cutoff = p.cutoff\n\n return surface\n }\n\n /**\n * Get molecular surface\n * @param {MolecularSurfaceParameters} params - parameters for surface creation\n * @return {Surface} the surface\n */\n getSurface (params: Partial) {\n const p = params || {}\n\n const atomData = this._getAtomData(params)\n const coordList = atomData.position\n const radiusList = atomData.radius\n const indexList = atomData.index\n\n const SurfClass = (p.type === 'av') ? AVSurface : EDTSurface\n const surf = new (SurfClass as any)(coordList, radiusList, indexList) as AVSurface|EDTSurface\n const sd = surf.getSurface(\n p.type!, p.probeRadius!, p.scaleFactor!, p.cutoff!, true, p.smooth!, p.contour!\n )\n\n return this._makeSurface(sd, p)\n }\n\n /**\n * Get molecular surface asynchronous\n * @param {MolecularSurfaceParameters} params - parameters for surface creation\n * @param {function(surface: Surface)} callback - function to be called after surface is created\n * @return {undefined}\n */\n getSurfaceWorker (params: MolecularSurfaceParameters, callback: (s: Surface) => void) {\n const p = Object.assign({}, params)\n\n if (window.hasOwnProperty('Worker')) {\n if (this.worker === undefined) {\n this.worker = new Worker('molsurf')\n }\n\n const atomData = this._getAtomData(params)\n const coordList = atomData.position\n const radiusList = atomData.radius\n const indexList = atomData.index\n\n const msg = {\n args: {\n coordList: coordList,\n radiusList: radiusList,\n indexList: indexList\n },\n params: p\n }\n\n const transferList = [\n coordList!.buffer, radiusList!.buffer, indexList!.buffer\n ]\n\n this.worker.post(msg, transferList,\n\n (e: any) => {\n callback(this._makeSurface(e.data.sd, p))\n },\n\n (e: string) => {\n console.warn(\n 'MolecularSurface.getSurfaceWorker error - trying without worker', e\n )\n this.worker!.terminate()\n this.worker = undefined\n const surface = this.getSurface(p)\n callback(surface)\n }\n\n )\n } else {\n const surface = this.getSurface(p)\n callback(surface)\n }\n }\n\n /**\n * Cleanup\n * @return {undefined}\n */\n dispose () {\n if (this.worker) this.worker.terminate()\n }\n}\n\nexport default MolecularSurface\n","/**\n * @file Molecular Surface Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport MolecularSurface, { MolecularSurfaceParameters } from '../surface/molecular-surface'\nimport SurfaceBuffer from '../buffer/surface-buffer'\nimport ContourBuffer from '../buffer/contour-buffer'\nimport DoubleSidedBuffer from '../buffer/doublesided-buffer'\nimport Selection from '../selection/selection'\nimport Viewer from '../viewer/viewer';\n// @ts-ignore: unused import Volume required for declaration only\nimport { Structure, Vector3, Volume } from '../ngl';\nimport StructureView from '../structure/structure-view';\nimport { SurfaceDataFields } from './surface-representation';\nimport Surface, {SurfaceData} from '../surface/surface';\n\nexport interface MolecularSurfaceRepresentationParameters extends StructureRepresentationParameters {\n surfaceType: 'vws'|'sas'|'ms'|'ses'|'av'\n probeRadius: number\n smooth: number\n scaleFactor: number\n cutoff: number\n contour: boolean\n background: boolean\n opaqueBack: boolean\n filterSele: string\n colorVolume: any\n useWorker: boolean\n}\n\nexport interface MolecularSurfaceInfo {\n molsurf?: MolecularSurface\n sele?: string\n surface?: Surface\n}\n\n/**\n * Molecular Surface Representation\n */\nclass MolecularSurfaceRepresentation extends StructureRepresentation {\n protected surfaceType: 'vws'|'sas'|'ms'|'ses'|'av'\n protected probeRadius: number\n protected smooth: number\n protected scaleFactor: number\n protected cutoff: number\n protected contour: boolean\n protected background: boolean\n protected opaqueBack: boolean\n protected filterSele: string\n protected colorVolume: any\n protected useWorker: boolean\n\n protected __infoList: MolecularSurfaceInfo[]\n protected __forceNewMolsurf: boolean\n protected __sele: string\n protected __surfaceParams: string\n\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'surface'\n\n this.parameters = Object.assign({\n\n surfaceType: {\n type: 'select',\n rebuild: true,\n options: {\n 'vws': 'vws',\n 'sas': 'sas',\n 'ms': 'ms',\n 'ses': 'ses',\n 'av': 'av'\n }\n },\n probeRadius: {\n type: 'number',\n precision: 1,\n max: 20,\n min: 0,\n rebuild: true\n },\n smooth: {\n type: 'integer',\n precision: 1,\n max: 10,\n min: 0,\n rebuild: true\n },\n scaleFactor: {\n type: 'number',\n precision: 1,\n max: 5,\n min: 0,\n rebuild: true\n },\n cutoff: {\n type: 'number',\n precision: 2,\n max: 50,\n min: 0,\n rebuild: true\n },\n contour: {\n type: 'boolean', rebuild: true\n },\n background: {\n type: 'boolean', rebuild: true // FIXME\n },\n opaqueBack: {\n type: 'boolean', buffer: true\n },\n filterSele: {\n type: 'text', rebuild: true\n },\n colorVolume: {\n type: 'hidden'\n },\n useWorker: {\n type: 'boolean', rebuild: true\n }\n\n }, this.parameters, {\n\n radius: null,\n scale: null\n\n })\n\n this.__infoList = []\n\n // TODO find a more direct way\n this.structure.signals.refreshed.add(() => {\n this.__forceNewMolsurf = true\n })\n\n this.toBePrepared = true\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n p.colorScheme = defaults(p.colorScheme, 'uniform')\n p.colorValue = defaults(p.colorValue, 0xDDDDDD)\n p.disablePicking = defaults(p.disablePicking, true)\n\n this.surfaceType = defaults(p.surfaceType, 'ms')\n this.probeRadius = defaults(p.probeRadius, 1.4)\n this.smooth = defaults(p.smooth, 2)\n this.scaleFactor = defaults(p.scaleFactor, 2.0)\n this.cutoff = defaults(p.cutoff, 0.0)\n this.contour = defaults(p.contour, false)\n this.background = defaults(p.background, false)\n this.opaqueBack = defaults(p.opaqueBack, true)\n this.filterSele = defaults(p.filterSele, '')\n this.colorVolume = defaults(p.colorVolume, undefined)\n this.useWorker = defaults(p.useWorker, true)\n\n super.init(params)\n }\n\n prepareData (sview: StructureView, i: number, callback: (i: number) => void) {\n let info: MolecularSurfaceInfo = this.__infoList[ i ]\n if (!info) {\n info = {}\n this.__infoList[ i ] = info\n }\n\n if (!info.molsurf || info.sele !== sview.selection.string) {\n if (this.filterSele) {\n const sviewFilter = sview.structure.getView(new Selection(this.filterSele))\n const bbSize = sviewFilter.boundingBox.getSize(new Vector3())\n const maxDim = Math.max(bbSize.x, bbSize.y, bbSize.z)\n const asWithin = sview.getAtomSetWithinPoint(sviewFilter.center, (maxDim / 2) + 6.0)\n sview = sview.getView(\n new Selection(sview.getAtomSetWithinSelection(asWithin, 3).toSeleString())\n )\n if (sview.atomCount === 0) {\n callback(i)\n return\n }\n }\n\n info.sele = sview.selection.string\n info.molsurf = new MolecularSurface(sview)\n\n const p = this.getSurfaceParams()\n const onSurfaceFinish = (surface: Surface) => {\n info.surface = surface\n callback(i)\n }\n\n if (this.useWorker) {\n info.molsurf.getSurfaceWorker(p as MolecularSurfaceParameters, onSurfaceFinish)\n } else {\n onSurfaceFinish(info.molsurf.getSurface(p as {name: string, type: 'av'|'edt' } & MolecularSurfaceRepresentationParameters))\n }\n } else {\n callback(i)\n }\n }\n\n prepare (callback: () => void) {\n if (this.__forceNewMolsurf || this.__sele !== this.selection.string ||\n this.__surfaceParams !== JSON.stringify(this.getSurfaceParams())) {\n this.__infoList.forEach((info: MolecularSurfaceInfo) => {\n if (info && info.molsurf) {\n info.molsurf.dispose()\n }\n })\n this.__infoList.length = 0\n }\n\n if (this.structureView.atomCount === 0) {\n callback()\n return\n }\n\n const after = () => {\n this.__sele = this.selection.string\n this.__surfaceParams = JSON.stringify(this.getSurfaceParams())\n this.__forceNewMolsurf = false\n callback()\n }\n\n const name = this.assembly === 'default' ? this.defaultAssembly : this.assembly\n const assembly = this.structure.biomolDict[ name ]\n\n if (assembly) {\n assembly.partList.forEach((part, i) => {\n const sview = part.getView(this.structureView)\n this.prepareData(sview as StructureView, i, (_i) => {\n if (_i === assembly.partList.length - 1) after()\n })\n })\n } else {\n this.prepareData(this.structureView, 0, after)\n }\n }\n\n createData (sview: StructureView, i: number) {\n const info = this.__infoList[ i ]\n const surface = info.surface\n\n if (!surface) {\n // Surface creation bailed (no surface generated for this sview)\n return\n }\n\n const surfaceData = {\n position: surface!.getPosition(),\n color: surface!.getColor(this.getColorParams()),\n index: surface!.getFilteredIndex(this.filterSele, sview)\n }\n\n const bufferList = []\n\n if (surface.contour) {\n const contourBuffer = new ContourBuffer(\n surfaceData,\n this.getBufferParams({\n wireframe: false\n })\n )\n\n bufferList.push(contourBuffer)\n } else {\n Object.assign(surfaceData, {\n normal: surface.getNormal(),\n picking: surface.getPicking(sview.getStructure())\n })\n\n const surfaceBuffer = new SurfaceBuffer(\n surfaceData,\n this.getBufferParams({\n background: this.background,\n opaqueBack: this.opaqueBack,\n dullInterior: false\n })\n )\n\n if (this.getBufferParams().side == 'double') {\n const doubleSidedBuffer = new DoubleSidedBuffer(surfaceBuffer)\n bufferList.push(doubleSidedBuffer)\n }\n else {\n bufferList.push(surfaceBuffer)\n }\n }\n\n return { bufferList, info } as StructureRepresentationData\n }\n\n updateData (what: SurfaceDataFields, data: StructureRepresentationData) {\n const surfaceData: Partial = {}\n\n if (what.position || what.radius) {\n this.__forceNewMolsurf = true\n this.build()\n return\n }\n\n if (what.color) {\n surfaceData.color = data.info.surface.getColor(this.getColorParams())\n }\n\n if (what.index) {\n surfaceData.index = data.info.surface.getFilteredIndex(this.filterSele, data.sview)\n }\n\n data.bufferList[ 0 ].setAttributes(surfaceData)\n }\n\n setParameters (params: Partial, what: Partial = {}, rebuild?: boolean) {\n if (params && params.filterSele) {\n what.index = true\n }\n\n if (params && params.colorVolume !== undefined) {\n what.color = true\n }\n\n // forbid setting wireframe to true when contour is true\n if (params && params.wireframe && (\n params.contour || (params.contour === undefined && this.contour)\n )\n ) {\n params.wireframe = false\n }\n\n super.setParameters(params, what, rebuild)\n\n return this\n }\n\n getSurfaceParams (params: Partial = {}) {\n const p = Object.assign({\n type: this.surfaceType as string,\n probeRadius: this.probeRadius as number,\n scaleFactor: this.scaleFactor as number,\n smooth: this.smooth && !this.contour,\n cutoff: this.cutoff as number,\n contour: this.contour as boolean,\n useWorker: this.useWorker as boolean,\n radiusParams: this.getRadiusParams()\n }, params)\n\n return p\n }\n\n getColorParams () {\n const p = super.getColorParams()\n\n p.volume = this.colorVolume\n\n return p\n }\n\n getAtomRadius () {\n return 0\n }\n\n clear () {\n super.clear()\n }\n\n dispose () {\n this.__infoList.forEach((info: MolecularSurfaceInfo) => {\n if (info && info.molsurf) {\n info.molsurf.dispose()\n }\n })\n this.__infoList.length = 0\n\n super.dispose()\n }\n}\n\nRepresentationRegistry.add('surface', MolecularSurfaceRepresentation)\n\nexport default MolecularSurfaceRepresentation\n","/**\n * @file Point Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport PointBuffer from '../buffer/point-buffer'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport StructureView from '../structure/structure-view';\nimport { AtomDataFields } from '../structure/structure-data';\n\nexport interface PointRepresentationParameters extends StructureRepresentationParameters {\n pointSize: number\n sizeAttenuation: boolean\n sortParticles: boolean\n useTexture: boolean\n alphaTest: number\n forceTransparent: boolean\n edgeBleach: number\n}\n\n/**\n * Point Representation\n */\nclass PointRepresentation extends StructureRepresentation {\n protected pointSize: number\n protected sizeAttenuation: boolean\n protected sortParticles: boolean\n protected useTexture: boolean\n protected alphaTest: number\n protected forceTransparent: boolean\n protected edgeBleach: number\n\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'point'\n\n this.parameters = Object.assign({\n\n pointSize: {\n type: 'number', precision: 1, max: 100, min: 0, buffer: true\n },\n sizeAttenuation: {\n type: 'boolean', buffer: true\n },\n sortParticles: {\n type: 'boolean', rebuild: true\n },\n useTexture: {\n type: 'boolean', buffer: true\n },\n alphaTest: {\n type: 'range', step: 0.001, max: 1, min: 0, buffer: true\n },\n forceTransparent: {\n type: 'boolean', buffer: true\n },\n edgeBleach: {\n type: 'range', step: 0.001, max: 1, min: 0, buffer: true\n }\n\n }, this.parameters, {\n\n flatShaded: null,\n wireframe: null,\n linewidth: null,\n side: null,\n\n roughness: null,\n metalness: null\n\n })\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n\n this.pointSize = defaults(p.pointSize, 1)\n this.sizeAttenuation = defaults(p.sizeAttenuation, true)\n this.sortParticles = defaults(p.sortParticles, false)\n this.useTexture = defaults(p.useTexture, false)\n this.alphaTest = defaults(p.alphaTest, 0.5)\n this.forceTransparent = defaults(p.forceTransparent, false)\n this.edgeBleach = defaults(p.edgeBleach, 0.0)\n\n super.init(p)\n }\n\n createData (sview: StructureView) {\n var what = { position: true, color: true, picking: true }\n var atomData = sview.getAtomData(this.getAtomParams(what))\n\n var pointBuffer = new PointBuffer(\n atomData,\n this.getBufferParams({\n pointSize: this.pointSize,\n sizeAttenuation: this.sizeAttenuation,\n sortParticles: this.sortParticles,\n useTexture: this.useTexture,\n alphaTest: this.alphaTest,\n forceTransparent: this.forceTransparent,\n edgeBleach: this.edgeBleach\n })\n )\n\n return {\n bufferList: [ pointBuffer ]\n }\n }\n\n updateData (what: AtomDataFields, data: StructureRepresentationData) {\n var atomData = data.sview!.getAtomData(this.getAtomParams(what))\n var pointData = {}\n\n if (!what || what.position) {\n Object.assign(pointData, {position: atomData.position})\n }\n\n if (!what || what.color) {\n Object.assign(pointData, {color: atomData.color})\n }\n\n data.bufferList[ 0 ].setAttributes(pointData)\n }\n\n getAtomRadius () {\n return 0.1\n }\n}\n\nRepresentationRegistry.add('point', PointRepresentation)\n\nexport default PointRepresentation\n","/**\n * @file Ribbon Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport '../shader/Ribbon.vert'\n\nimport { getUintArray } from '../utils'\nimport { serialArray } from '../math/array-utils'\nimport MeshBuffer from './mesh-buffer'\nimport { BufferParameters, BufferData } from './buffer'\nimport {Log} from \"../globals\";\n\nconst quadIndices = new Uint16Array([\n 0, 1, 2,\n 1, 3, 2\n])\n\nexport interface RibbonBufferData extends BufferData {\n normal: Float32Array\n dir: Float32Array\n size: Float32Array\n}\n\nfunction getSize(data: RibbonBufferData){\n const n = (data.position!.length / 3) - 1\n const n4 = n * 4\n const x = n4 * 3\n return x\n}\n\n/**\n * Ribbon buffer. Draws a thin ribbon.\n */\nclass RibbonBuffer extends MeshBuffer {\n vertexShader = 'Ribbon.vert'\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.normal - normals\n * @param {Float32Array} data.dir - binormals\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} data.size - sizes\n * @param {Picker} data.picking - picking ids\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: RibbonBufferData, params: Partial = {}) {\n super({\n position: new Float32Array(getSize(data)),\n color: new Float32Array(getSize(data)),\n index: getUintArray(getSize(data), getSize(data) / 3),\n normal: new Float32Array(getSize(data)),\n picking: data.picking\n }, params)\n\n const n = (data.position!.length / 3) - 1\n const n4 = n * 4\n const x = n4 * 3\n\n this.addAttributes({\n 'dir': { type: 'v3', value: new Float32Array(x) }\n })\n this.addAttributes({\n 'size': { type: 'f', value: new Float32Array(n4) }\n })\n\n data.primitiveId = serialArray(n)\n this.setAttributes(data)\n\n this.makeIndex()\n }\n\n setAttributes (data: Partial = {}) {\n const n4 = this.size\n const n = n4 / 4\n\n const attributes = this.geometry.attributes as any // TODO\n\n let position, normal, size, dir, color, primitiveId\n let aPosition, aNormal, aSize, aDir, aColor, aPrimitiveId\n\n if (data.position) {\n position = data.position\n aPosition = attributes.position.array\n attributes.position.needsUpdate = true\n }\n\n if (data.normal) {\n normal = data.normal\n aNormal = attributes.normal.array\n attributes.normal.needsUpdate = true\n }\n\n if (data.size) {\n size = data.size\n aSize = attributes.size.array\n attributes.size.needsUpdate = true\n }\n\n if (data.dir) {\n dir = data.dir\n aDir = attributes.dir.array\n attributes.dir.needsUpdate = true\n }\n\n if (data.color) {\n color = data.color\n aColor = attributes.color.array\n attributes.color.needsUpdate = true\n }\n\n if (data.primitiveId) {\n primitiveId = data.primitiveId\n aPrimitiveId = attributes.primitiveId.array\n attributes.primitiveId.needsUpdate = true\n }\n\n let v, i, k, p, l, v3\n let currSize\n let prevSize = size ? size[ 0 ] : null\n\n for (v = 0; v < n; ++v) {\n v3 = v * 3\n k = v * 3 * 4\n l = v * 4\n\n if (position) {\n aPosition[ k ] = aPosition[ k + 3 ] = position[ v3 ]\n aPosition[ k + 1 ] = aPosition[ k + 4 ] = position[ v3 + 1 ]\n aPosition[ k + 2 ] = aPosition[ k + 5 ] = position[ v3 + 2 ]\n\n aPosition[ k + 6 ] = aPosition[ k + 9 ] = position[ v3 + 3 ]\n aPosition[ k + 7 ] = aPosition[ k + 10 ] = position[ v3 + 4 ]\n aPosition[ k + 8 ] = aPosition[ k + 11 ] = position[ v3 + 5 ]\n }\n\n if (normal) {\n aNormal[ k ] = aNormal[ k + 3 ] = -normal[ v3 ]\n aNormal[ k + 1 ] = aNormal[ k + 4 ] = -normal[ v3 + 1 ]\n aNormal[ k + 2 ] = aNormal[ k + 5 ] = -normal[ v3 + 2 ]\n\n aNormal[ k + 6 ] = aNormal[ k + 9 ] = -normal[ v3 + 3 ]\n aNormal[ k + 7 ] = aNormal[ k + 10 ] = -normal[ v3 + 4 ]\n aNormal[ k + 8 ] = aNormal[ k + 11 ] = -normal[ v3 + 5 ]\n }\n\n for (i = 0; i < 4; ++i) {\n p = k + 3 * i\n\n if (color) {\n aColor[ p ] = color[ v3 ]\n aColor[ p + 1 ] = color[ v3 + 1 ]\n aColor[ p + 2 ] = color[ v3 + 2 ]\n }\n\n if (primitiveId) {\n aPrimitiveId[ l + i ] = primitiveId[ v ]\n }\n }\n\n if (size) {\n currSize = size[ v ]\n\n if (prevSize !== size[ v ]) {\n aSize[ l ] = prevSize\n aSize[ l + 1 ] = prevSize\n aSize[ l + 2 ] = currSize\n aSize[ l + 3 ] = currSize\n } else {\n aSize[ l ] = currSize\n aSize[ l + 1 ] = currSize\n aSize[ l + 2 ] = currSize\n aSize[ l + 3 ] = currSize\n }\n\n prevSize = currSize\n }\n\n if (dir) {\n aDir[ k ] = dir[ v3 ]\n aDir[ k + 1 ] = dir[ v3 + 1 ]\n aDir[ k + 2 ] = dir[ v3 + 2 ]\n\n aDir[ k + 3 ] = -dir[ v3 ]\n aDir[ k + 4 ] = -dir[ v3 + 1 ]\n aDir[ k + 5 ] = -dir[ v3 + 2 ]\n\n aDir[ k + 6 ] = dir[ v3 + 3 ]\n aDir[ k + 7 ] = dir[ v3 + 4 ]\n aDir[ k + 8 ] = dir[ v3 + 5 ]\n\n aDir[ k + 9 ] = -dir[ v3 + 3 ]\n aDir[ k + 10 ] = -dir[ v3 + 4 ]\n aDir[ k + 11 ] = -dir[ v3 + 5 ]\n }\n }\n }\n\n makeIndex () {\n const index = this.geometry.getIndex()\n if (!index) { Log.error('Index is null'); return; }\n const meshIndex = index.array as Uint32Array|Uint16Array\n const n = meshIndex.length / 4 / 3\n\n for (let v = 0; v < n; ++v) {\n const ix = v * 6\n const it = v * 4\n\n meshIndex.set(quadIndices, ix)\n for (let s = 0; s < 6; ++s) {\n meshIndex[ ix + s ] += it\n }\n }\n }\n}\n\nexport default RibbonBuffer\n","/**\n * @file Ribbon Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport Spline, { SplineParameters } from '../geometry/spline'\nimport StructureRepresentation, { StructureRepresentationParameters } from './structure-representation'\nimport RibbonBuffer from '../buffer/ribbon-buffer'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport AtomProxy from '../proxy/atom-proxy';\nimport StructureView from '../structure/structure-view';\nimport Polymer from '../proxy/polymer';\n\nexport interface RibbonRepresentationParameters extends StructureRepresentationParameters {\n subdiv: number\n tension: number\n smoothSheet: boolean\n}\n\n/**\n * Ribbon Representation\n */\nclass RibbonRepresentation extends StructureRepresentation {\n protected subdiv: number\n protected tension: number\n protected smoothSheet: boolean\n \n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'ribbon'\n\n this.parameters = Object.assign({\n\n subdiv: {\n type: 'integer', max: 50, min: 1, rebuild: true\n },\n tension: {\n type: 'number', precision: 1, max: 1.0, min: 0.1\n },\n smoothSheet: {\n type: 'boolean', rebuild: true\n }\n\n }, this.parameters, {\n\n side: null,\n wireframe: null,\n linewidth: null\n\n })\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n p.colorScheme = defaults(p.colorScheme, 'chainname')\n p.colorScale = defaults(p.colorScale, 'RdYlBu')\n p.radiusType = defaults(p.radiusType, 'sstruc')\n p.radiusScale = defaults(p.radiusScale, 4.0)\n\n if (p.quality === 'low') {\n this.subdiv = 3\n } else if (p.quality === 'medium') {\n this.subdiv = 6\n } else if (p.quality === 'high') {\n this.subdiv = 12\n } else {\n this.subdiv = defaults(p.subdiv, 6)\n }\n\n this.tension = defaults(p.tension, NaN)\n this.smoothSheet = defaults(p.smoothSheet, false)\n\n super.init(p)\n }\n\n getSplineParams (params?: Partial) {\n return Object.assign({\n subdiv: this.subdiv,\n tension: this.tension,\n directional: true,\n smoothSheet: this.smoothSheet\n }, params)\n }\n\n getAtomRadius (atom: AtomProxy) {\n return atom.isTrace() ? super.getAtomRadius(atom) : 0\n }\n\n createData (sview: StructureView) {\n var bufferList: RibbonBuffer[] = []\n var polymerList: Polymer[] = []\n\n this.structure.eachPolymer(polymer => {\n if (polymer.residueCount < 4) return\n polymerList.push(polymer)\n\n var spline = new Spline(polymer, this.getSplineParams())\n var subPos = spline.getSubdividedPosition()\n var subOri = spline.getSubdividedOrientation()\n var subCol = spline.getSubdividedColor(this.getColorParams())\n var subPick = spline.getSubdividedPicking()\n var subSize = spline.getSubdividedSize(this.getRadiusParams())\n\n bufferList.push(\n new RibbonBuffer(\n ({\n position: subPos.position,\n normal: subOri.binormal,\n dir: subOri.normal,\n color: subCol.color,\n size: subSize.size,\n picking: subPick.picking\n }),\n this.getBufferParams()\n )\n )\n }, sview.getSelection())\n\n return {\n bufferList: bufferList,\n polymerList: polymerList\n }\n }\n\n updateData (what: {position?: boolean, radius?: boolean, scale?: boolean, color?: boolean}, data: {polymerList: Polymer[], bufferList: RibbonBuffer[]}) {\n what = what || {}\n\n var i = 0\n var n = data.polymerList.length\n\n for (i = 0; i < n; ++i) {\n var bufferData = {}\n var spline = new Spline(data.polymerList[ i ], this.getSplineParams())\n\n if (what.position) {\n var subPos = spline.getSubdividedPosition()\n var subOri = spline.getSubdividedOrientation()\n Object.assign(bufferData, {\n position: subPos.position,\n normal: subOri.binormal,\n dir: subOri.normal\n })\n }\n\n if (what.radius || what.scale) {\n var subSize = spline.getSubdividedSize(this.getRadiusParams())\n Object.assign(bufferData, {size: subSize.size})\n }\n\n if (what.color) {\n var subCol = spline.getSubdividedColor(this.getColorParams())\n Object.assign(bufferData, {color: subCol.color})\n }\n\n data.bufferList[ i ].setAttributes(bufferData)\n }\n }\n\n setParameters (params: Partial) {\n var rebuild = false\n var what = {}\n\n if (params && params.tension) {\n Object.assign(what, {position: true})\n }\n\n super.setParameters(params, what, rebuild)\n\n return this\n }\n}\n\nRepresentationRegistry.add('ribbon', RibbonRepresentation)\n\nexport default RibbonRepresentation\n","/**\n * @file Rocket Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport { AtomPicker } from '../utils/picker'\nimport StructureRepresentation, { StructureRepresentationParameters } from './structure-representation'\nimport Helixbundle, { Axis } from '../geometry/helixbundle'\nimport CylinderBuffer from '../buffer/cylinder-buffer'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport StructureView from '../structure/structure-view';\nimport CylinderGeometryBuffer from '../buffer/cylindergeometry-buffer';\nimport CylinderImpostorBuffer from '../buffer/cylinderimpostor-buffer';\n\nexport interface RocketRepresentationParameters extends StructureRepresentationParameters {\n localAngle: number\n centerDist: number\n ssBorder: boolean\n radialSegments: number\n openEnded: boolean\n disableImpostor: boolean\n}\n\nexport interface AxisData {\n begin: Float32Array\n end: Float32Array\n size: Float32Array\n color: Float32Array\n picking: AtomPicker\n}\n\n/**\n * Rocket Representation\n */\nclass RocketRepresentation extends StructureRepresentation {\n\n protected localAngle: number\n protected centerDist: number\n protected ssBorder: boolean\n protected radialSegments: number\n protected openEnded: boolean\n protected disableImpostor: boolean\n // protected helixbundleList: Helixbundle[]\n\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'rocket'\n\n this.parameters = Object.assign({\n\n localAngle: {\n type: 'integer', max: 180, min: 0, rebuild: true\n },\n centerDist: {\n type: 'number', precision: 1, max: 10, min: 0, rebuild: true\n },\n ssBorder: {\n type: 'boolean', rebuild: true\n },\n radialSegments: true,\n openEnded: true,\n disableImpostor: true\n\n }, this.parameters)\n\n // this.helixbundleList = []\n\n this.init(params)\n }\n\n init (params: Partial) {\n let p = params || {}\n p.colorScheme = defaults(p.colorScheme, 'sstruc')\n p.radiusSize = defaults(p.radiusSize, 1.5)\n p.radiusScale = defaults(p.radiusScale, 1.0)\n p.openEnded = defaults(p.openEnded, false)\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n this.localAngle = defaults(p.localAngle, 30)\n this.centerDist = defaults(p.centerDist, 2.5)\n this.ssBorder = defaults(p.ssBorder, false)\n\n super.init(p)\n }\n\n createData (sview: StructureView) {\n let length = 0\n const axisList:Axis[] = []\n const helixbundleList:Helixbundle[] = []\n\n this.structure.eachPolymer(polymer => {\n if (polymer.residueCount < 4 || polymer.isNucleic()) return\n\n const helixbundle = new Helixbundle(polymer)\n const axis = helixbundle.getAxis(\n this.localAngle, this.centerDist, this.ssBorder,\n this.getColorParams(), this.getRadiusParams()\n )\n\n length += axis.size.length\n axisList.push(axis)\n helixbundleList.push(helixbundle)\n }, sview.getSelection())\n\n const axisData = {\n begin: new Float32Array(length * 3),\n end: new Float32Array(length * 3),\n size: new Float32Array(length),\n color: new Float32Array(length * 3),\n picking: {}\n }\n\n let picking = new Float32Array(length)\n\n let offset = 0\n\n axisList.forEach(function (axis) {\n axisData.begin.set(axis.begin, offset * 3)\n axisData.end.set(axis.end, offset * 3)\n axisData.size.set(axis.size, offset)\n axisData.color.set(axis.color, offset * 3)\n picking.set(axis.picking.array!, offset)\n offset += axis.size.length\n })\n\n if (length) {\n axisData.picking = new AtomPicker(\n picking, sview.getStructure()\n )\n }\n\n const cylinderBuffer = new CylinderBuffer(\n {\n position1: axisData.begin,\n position2: axisData.end,\n color: axisData.color,\n color2: axisData.color,\n radius: axisData.size,\n picking: axisData.picking\n },\n this.getBufferParams({\n openEnded: this.openEnded,\n radialSegments: this.radialSegments,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n })\n )\n\n return {\n bufferList: [ cylinderBuffer as CylinderGeometryBuffer|CylinderImpostorBuffer ],\n axisList: axisList,\n helixbundleList: helixbundleList,\n axisData: axisData\n }\n }\n\n \n updateData (what: any, data: {bufferList: CylinderBuffer[], helixbundleList: Helixbundle[], axisList: Axis[], axisData: AxisData}) {\n what = what || {}\n\n if (what.position) {\n this.build()\n return\n }\n\n var cylinderData = {}\n\n if (what.color || what.radius) {\n var offset = 0\n\n data.helixbundleList.forEach((helixbundle) => {\n var axis = helixbundle.getAxis(\n this.localAngle, this.centerDist, this.ssBorder,\n this.getColorParams(), this.getRadiusParams()\n )\n if (what.color) {\n data.axisData.color.set(axis.color, offset * 3)\n }\n if (what.radius || what.scale) {\n data.axisData.size.set(axis.size, offset)\n }\n offset += axis.size.length\n })\n\n if (what.color) {\n Object.assign(cylinderData, {\n color: data.axisData.color,\n color2: data.axisData.color\n })\n }\n\n if (what.radius || what.scale) {\n Object.assign(cylinderData, {\n radius: data.axisData.size\n })\n }\n }\n\n (data.bufferList[ 0 ] as CylinderGeometryBuffer).setAttributes(cylinderData)\n }\n}\n\nRepresentationRegistry.add('rocket', RocketRepresentation)\n\nexport default RocketRepresentation\n","/**\n * @file Rope Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport CartoonRepresentation, { CartoonRepresentationParameters } from './cartoon-representation'\nimport Helixorient from '../geometry/helixorient'\nimport Spline from '../geometry/spline'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport Polymer from '../proxy/polymer';\n\n/**\n * Rope Representation\n */\nclass RopeRepresentation extends CartoonRepresentation {\n protected smooth: number\n \n constructor (structure: Structure, viewer: Viewer, params: Partial&{smooth: number}) {\n super(structure, viewer, params)\n\n this.type = 'rope'\n\n this.parameters = Object.assign({\n\n smooth: {\n type: 'integer', max: 15, min: 0, rebuild: true\n }\n\n }, this.parameters, {\n aspectRatio: null,\n smoothSheet: null\n })\n }\n\n init (params: Partial) {\n var p = params || {}\n p.aspectRatio = 1.0\n p.tension = defaults(p.tension, 0.5)\n p.radiusScale = defaults(p.radiusScale, 5.0)\n p.smoothSheet = false\n\n this.smooth = defaults(p.smooth, 2)\n\n super.init(p)\n }\n\n getSpline (polymer: Polymer) {\n var helixorient = new Helixorient(polymer)\n\n return new Spline(polymer, this.getSplineParams({\n directional: false,\n positionIterator: helixorient.getCenterIterator(this.smooth)\n }))\n }\n}\n\nRepresentationRegistry.add('rope', RopeRepresentation)\n\nexport default RopeRepresentation\n","/**\n * @file Spacefill Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { defaults } from '../utils'\nimport { RepresentationRegistry } from '../globals'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport SphereBuffer, { SphereBufferData, SphereBufferParameters } from '../buffer/sphere-buffer'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport StructureView from '../structure/structure-view';\nimport SphereGeometryBuffer from '../buffer/spheregeometry-buffer';\nimport { AtomDataFields } from '../structure/structure-data';\nimport SphereImpostorBuffer from '../buffer/sphereimpostor-buffer';\n\n/**\n * Spacefill Representation\n */\nclass SpacefillRepresentation extends StructureRepresentation {\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'spacefill'\n\n this.parameters = Object.assign({\n sphereDetail: true,\n disableImpostor: true\n }, this.parameters)\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n super.init(p)\n }\n\n createData (sview: StructureView) {\n var sphereBuffer = new SphereBuffer(\n (sview.getAtomData(this.getAtomParams()) as SphereBufferData),\n (this.getBufferParams({\n sphereDetail: this.sphereDetail,\n dullInterior: true,\n disableImpostor: this.disableImpostor\n }) as SphereBufferParameters)\n )\n\n return {\n bufferList: [ sphereBuffer as SphereGeometryBuffer|SphereImpostorBuffer ]\n }\n }\n\n updateData (what: AtomDataFields, data: StructureRepresentationData) {\n var atomData = data.sview!.getAtomData(this.getAtomParams(what))\n var sphereData: Partial = {}\n\n if (!what || what.position) {\n Object.assign(sphereData, {position: atomData.position})\n }\n\n if (!what || what.color) {\n Object.assign(sphereData, {color: atomData.color})\n }\n\n if (!what || what.radius) {\n Object.assign(sphereData, {radius: atomData.radius})\n }\n\n data.bufferList[ 0 ].setAttributes(sphereData)\n }\n}\n\nRepresentationRegistry.add('spacefill', SpacefillRepresentation)\n\nexport default SpacefillRepresentation\n","/**\n * @file Trace Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport '../shader/Line.vert'\nimport '../shader/Line.frag'\n\nimport { Log } from '../globals'\nimport Buffer, { BufferParameters, BufferData } from './buffer'\n\nfunction getSize(data: BufferData){\n const n = data.position!.length / 3\n const n1 = n - 1\n return n1 * 3 * 2\n}\n\n/**\n * Trace buffer. Draws a series of lines.\n */\nclass TraceBuffer extends Buffer {\n isLine = true\n vertexShader = 'Line.vert'\n fragmentShader = 'Line.frag'\n\n /**\n * @param {Object} data - attribute object\n * @param {Float32Array} data.position - positions\n * @param {Float32Array} data.color - colors\n * @param {BufferParameters} params - parameter object\n */\n constructor (data: BufferData, params: Partial = {}) {\n super({\n position: new Float32Array(getSize(data)),\n color: new Float32Array(getSize(data))\n }, params)\n\n this.setAttributes(data)\n }\n\n setAttributes (data: Partial) {\n let position, color\n let linePosition, lineColor\n\n const attributes = this.geometry.attributes as any // TODO\n\n if (data.position) {\n position = data.position\n linePosition = attributes.position.array\n attributes.position.needsUpdate = true\n }\n\n if (data.color) {\n color = data.color\n lineColor = attributes.color.array\n attributes.color.needsUpdate = true\n }\n\n if (!position && !color) {\n Log.warn('TraceBuffer.prototype.setAttributes no data')\n return\n }\n\n let v, v2\n const n = this.size\n const n1 = n - 1\n\n for (let i = 0; i < n1; ++i) {\n v = 3 * i\n v2 = 3 * i * 2\n\n if (position) {\n linePosition[ v2 ] = position[ v ]\n linePosition[ v2 + 1 ] = position[ v + 1 ]\n linePosition[ v2 + 2 ] = position[ v + 2 ]\n\n linePosition[ v2 + 3 ] = position[ v + 3 ]\n linePosition[ v2 + 4 ] = position[ v + 4 ]\n linePosition[ v2 + 5 ] = position[ v + 5 ]\n }\n\n if (color) {\n lineColor[ v2 ] = color[ v ]\n lineColor[ v2 + 1 ] = color[ v + 1 ]\n lineColor[ v2 + 2 ] = color[ v + 2 ]\n\n lineColor[ v2 + 3 ] = color[ v + 3 ]\n lineColor[ v2 + 4 ] = color[ v + 4 ]\n lineColor[ v2 + 5 ] = color[ v + 5 ]\n }\n }\n }\n}\n\nexport default TraceBuffer\n","/**\n * @file Trace Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport Spline from '../geometry/spline'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport TraceBuffer from '../buffer/trace-buffer'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport AtomProxy from '../proxy/atom-proxy';\nimport StructureView from '../structure/structure-view';\nimport Polymer from '../proxy/polymer';\n\nexport interface TraceRepresentationParameters extends StructureRepresentationParameters {\n subdiv: number\n tension: number\n smoothSheet: boolean\n}\n/**\n * Trace Representation\n */\nclass TraceRepresentation extends StructureRepresentation {\n protected subdiv: number\n protected tension: number\n protected smoothSheet: boolean\n \n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'trace'\n\n this.parameters = Object.assign({\n\n subdiv: {\n type: 'integer', max: 50, min: 1, rebuild: true\n },\n tension: {\n type: 'number', precision: 1, max: 1.0, min: 0.1\n },\n smoothSheet: {\n type: 'boolean', rebuild: true\n }\n\n }, this.parameters, {\n\n flatShaded: null,\n side: null,\n wireframe: null\n\n })\n\n this.init(params)\n }\n\n init (params: Partial) {\n var p = params || {}\n p.colorScheme = defaults(p.colorScheme, 'chainname')\n p.colorScale = defaults(p.colorScale, 'RdYlBu')\n\n if (p.quality === 'low') {\n this.subdiv = 3\n } else if (p.quality === 'medium') {\n this.subdiv = 6\n } else if (p.quality === 'high') {\n this.subdiv = 12\n } else {\n this.subdiv = defaults(p.subdiv, 6)\n }\n\n this.tension = defaults(p.tension, NaN)\n this.smoothSheet = defaults(p.smoothSheet, false)\n\n super.init(p)\n }\n\n getSplineParams (params?: {[k:string]: any}) {\n return Object.assign({\n subdiv: this.subdiv,\n tension: this.tension,\n directional: false,\n smoothSheet: this.smoothSheet\n }, params)\n }\n\n getAtomRadius (atom: AtomProxy) {\n return atom.isTrace() ? 0.1 : 0\n }\n\n createData (sview: StructureView) {\n var bufferList: TraceBuffer[] = []\n var polymerList: Polymer[] = []\n\n this.structure.eachPolymer(polymer => {\n if (polymer.residueCount < 4) return\n polymerList.push(polymer)\n\n var spline = new Spline(polymer, this.getSplineParams())\n var subPos = spline.getSubdividedPosition()\n var subCol = spline.getSubdividedColor(this.getColorParams())\n\n bufferList.push(\n new TraceBuffer(\n Object.assign({}, subPos, subCol),\n this.getBufferParams()\n )\n )\n }, sview.getSelection())\n\n return {\n bufferList: bufferList,\n polymerList: polymerList\n }\n }\n\n updateData (what: any, data: StructureRepresentationData) {\n what = what || {}\n\n var i = 0\n var n = data.polymerList!.length\n\n for (i = 0; i < n; ++i) {\n var bufferData = {}\n var spline = new Spline(data.polymerList![ i ], this.getSplineParams())\n\n if (what.position) {\n var subPos = spline.getSubdividedPosition()\n Object.assign(bufferData, { position: subPos.position })\n }\n\n if (what.color) {\n var subCol = spline.getSubdividedColor(this.getColorParams())\n Object.assign(bufferData, { color: subCol.color })\n }\n\n data.bufferList[ i ].setAttributes(bufferData)\n }\n }\n\n setParameters (params: Partial) {\n var rebuild = false\n var what = {}\n\n if (params && params.tension) {\n Object.assign(what, {position: true})\n }\n\n super.setParameters(params, what, rebuild)\n\n return this\n }\n}\n\nRepresentationRegistry.add('trace', TraceRepresentation)\n\nexport default TraceRepresentation\n","/**\n * @file Tube Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport CartoonRepresentation, {CartoonRepresentationParameters} from './cartoon-representation'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\n\n/**\n * Tube Representation\n */\nclass TubeRepresentation extends CartoonRepresentation {\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'tube'\n\n this.parameters = Object.assign(\n {}, this.parameters, { aspectRatio: null }\n )\n }\n\n init (params: Partial) {\n var p = params || {}\n p.aspectRatio = 1.0\n p.radiusScale = defaults(p.radiusScale, 2.0)\n\n if (p.quality === 'low') {\n this.radialSegments = 5\n }\n\n super.init(p)\n }\n\n getSplineParams (/* params */) {\n return super.getSplineParams({\n directional: false\n })\n }\n}\n\nRepresentationRegistry.add('tube', TubeRepresentation)\n\nexport default TubeRepresentation\n","/**\n * @file Unitcell Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport StructureRepresentation, { StructureRepresentationParameters, StructureRepresentationData } from './structure-representation'\nimport SphereBuffer, { SphereBufferData, SphereBufferParameters } from '../buffer/sphere-buffer'\nimport CylinderBuffer, { CylinderBufferData } from '../buffer/cylinder-buffer'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport { AtomDataFields } from '../structure/structure-data';\nimport StructureView from '../structure/structure-view';\nimport SphereGeometryBuffer from '../buffer/spheregeometry-buffer';\nimport CylinderGeometryBuffer from '../buffer/cylindergeometry-buffer';\n// @ts-ignore: unused import UnitcellPicker required for declaration only\nimport { UnitcellPicker } from '../utils/picker';\n\nexport interface UnitcellRepresentationParameters extends StructureRepresentationParameters {\n radiusSize: number\n sphereDetail: number\n radialSegments: number\n disableImpostor: boolean\n}\n\n/**\n * Unitcell Representation\n */\nclass UnitcellRepresentation extends StructureRepresentation {\n sphereBuffer: SphereBuffer\n cylinderBuffer: CylinderBuffer\n\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'unitcell'\n\n this.parameters = Object.assign({\n\n radiusSize: {\n type: 'number', precision: 3, max: 10.0, min: 0.001\n },\n sphereDetail: true,\n radialSegments: true,\n disableImpostor: true\n\n }, this.parameters, {\n assembly: null\n })\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n\n let defaultRadius = 0.5\n if (this.structure.unitcell) {\n defaultRadius = Math.cbrt(this.structure.unitcell.volume) / 200\n }\n\n p.radiusSize = defaults(p.radiusSize, defaultRadius)\n p.colorValue = defaults(p.colorValue, 'orange')\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n super.init(p)\n }\n\n getUnitcellData (structure: Structure) {\n return structure.unitcell!.getData(structure)\n }\n\n create () {\n const structure = this.structureView.getStructure()\n if (!structure.unitcell) return\n const unitcellData = this.getUnitcellData(structure)\n\n this.sphereBuffer = new SphereBuffer(\n unitcellData.vertex as SphereBufferData,\n this.getBufferParams({\n sphereDetail: this.sphereDetail,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n }) as SphereBufferParameters\n )\n\n this.cylinderBuffer = new CylinderBuffer(\n unitcellData.edge as CylinderBufferData,\n this.getBufferParams({\n openEnded: true,\n radialSegments: this.radialSegments,\n disableImpostor: this.disableImpostor,\n dullInterior: true\n })\n )\n\n this.dataList.push({\n sview: this.structureView,\n bufferList: [ this.sphereBuffer as SphereGeometryBuffer, this.cylinderBuffer as CylinderGeometryBuffer ]\n })\n }\n\n createData (sview: StructureView): undefined {\n return\n }\n\n updateData (what: AtomDataFields, data: StructureRepresentationData) {\n const structure = data.sview!.getStructure()\n if (!structure.unitcell) return\n const unitcellData = this.getUnitcellData(structure)\n const sphereData: Partial = {}\n const cylinderData: Partial = {}\n\n if (!what || what.position) {\n Object.assign(sphereData, {position: unitcellData.vertex.position})\n Object.assign(cylinderData, {\n position1: unitcellData.edge.position1,\n position2: unitcellData.edge.position2\n })\n }\n\n if (!what || what.color) {\n Object.assign(sphereData, {color: unitcellData.vertex.color})\n Object.assign(cylinderData, {\n color: unitcellData.edge.color,\n color2: unitcellData.edge.color2\n })\n }\n\n if (!what || what.radius) {\n Object.assign(sphereData, {radius: unitcellData.vertex.radius})\n Object.assign(cylinderData, {radius: unitcellData.edge.radius})\n }\n\n (this.sphereBuffer as SphereGeometryBuffer).setAttributes(sphereData);\n (this.cylinderBuffer as CylinderGeometryBuffer).setAttributes(cylinderData)\n }\n}\n\nRepresentationRegistry.add('unitcell', UnitcellRepresentation)\n\nexport default UnitcellRepresentation\n","/**\n * @file Validation Representation\n * @author Alexander Rose \n * @private\n */\n\nimport { RepresentationRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport StructureRepresentation, { StructureRepresentationParameters } from './structure-representation'\nimport CylinderBuffer from '../buffer/cylinder-buffer'\nimport { Structure } from '../ngl';\nimport Viewer from '../viewer/viewer';\nimport StructureView from '../structure/structure-view';\nimport CylinderGeometryBuffer from '../buffer/cylindergeometry-buffer';\nimport CylinderImpostorBuffer from '../buffer/cylinderimpostor-buffer';\n\n/**\n * Validation representation\n */\nclass ValidationRepresentation extends StructureRepresentation {\n constructor (structure: Structure, viewer: Viewer, params: Partial) {\n super(structure, viewer, params)\n\n this.type = 'validation'\n\n this.parameters = Object.assign({\n\n }, this.parameters, {\n radiusType: null,\n radiusSize: null,\n radiusScale: null\n })\n\n this.init(params)\n }\n\n init (params: Partial) {\n const p = params || {}\n p.colorValue = defaults(p.colorValue, '#f0027f')\n p.useInteriorColor = defaults(p.useInteriorColor, true)\n\n super.init(p)\n }\n\n createData (sview: StructureView) {\n if (!sview.validation) return\n\n const clashData = sview.validation.getClashData({\n structure: sview,\n color: this.colorValue\n })\n\n const cylinderBuffer = new CylinderBuffer(\n clashData, this.getBufferParams({ openEnded: false })\n )\n\n return {\n bufferList: [ cylinderBuffer as CylinderGeometryBuffer|CylinderImpostorBuffer ]\n }\n }\n}\n\nRepresentationRegistry.add('validation', ValidationRepresentation)\n\nexport default ValidationRepresentation\n","/**\n * @file Cone Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4, Vector3, ConeGeometry } from 'three'\n\nimport { BufferRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport { calculateCenterArray } from '../math/array-utils'\nimport GeometryBuffer from './geometry-buffer'\nimport { BufferData, BufferDefaultParameters } from './buffer'\n\nconst scale = new Vector3()\nconst eye = new Vector3()\nconst target = new Vector3()\nconst up = new Vector3(0, 1, 0)\n\nfunction getGeo (params: Partial = {}) {\n const geo = new ConeGeometry(\n 1, // radius\n 1, // height\n defaults(params.radialSegments, 60), // radialSegments\n 1, // heightSegments\n defaults(params.openEnded, false) // openEnded\n )\n geo.applyMatrix4(new Matrix4().makeRotationX(-Math.PI / 2))\n\n return geo\n}\n\nexport interface ConeBufferData extends BufferData {\n position1: Float32Array\n position2: Float32Array\n radius: Float32Array\n}\n\nexport const ConeBufferDefaultParameters = Object.assign({\n radialSegments: 60,\n openEnded: false\n}, BufferDefaultParameters)\nexport type ConeBufferParameters = typeof ConeBufferDefaultParameters\n\n\n/**\n * Cone geometry buffer.\n *\n * @example\n * var coneBuffer = new ConeBuffer({\n * position1: new Float32Array([ 0, 0, 0 ]),\n * position2: new Float32Array([ 1, 1, 1 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * color2: new Float32Array([ 0, 1, 0 ]),\n * radius: new Float32Array([ 1 ])\n * });\n */\nclass ConeBuffer extends GeometryBuffer {\n updateNormals = true\n\n get defaultParameters() { return ConeBufferDefaultParameters }\n parameters: ConeBufferParameters\n\n _position: Float32Array\n _position1: Float32Array\n _position2: Float32Array\n _radius: Float32Array\n\n /**\n * @param {Object} data - buffer data\n * @param {Float32Array} data.position1 - from positions\n * @param {Float32Array} data.position2 - to positions\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} data.radius - radii\n * @param {Picker} [data.picking] - picking ids\n * @param {BufferParameters} [params] - parameters object\n */\n constructor (data: ConeBufferData, params: Partial = {}) {\n super({\n position: new Float32Array(data.position1.length),\n color: data.color,\n picking: data.picking\n }, params, getGeo(params))\n\n this._position = new Float32Array(data.position1.length)\n\n this.setAttributes(data, true)\n }\n\n applyPositionTransform (matrix: Matrix4, i: number, i3: number) {\n eye.fromArray(this._position1 as any, i3)\n target.fromArray(this._position2 as any, i3)\n matrix.lookAt(eye, target, up)\n\n const r = this._radius[ i ]\n scale.set(r, r, eye.distanceTo(target))\n matrix.scale(scale)\n }\n\n setAttributes (data: Partial = {}, initNormals?: boolean) {\n if (data.position1 && data.position2) {\n calculateCenterArray(data.position1, data.position2, this._position)\n this._position1 = data.position1\n this._position2 = data.position2\n data.position = this._position\n }\n if (data.radius) this._radius = data.radius\n\n super.setAttributes(data, initNormals)\n }\n}\n\nBufferRegistry.add('cone', ConeBuffer)\n\nexport default ConeBuffer\n","/**\n * @file Geometry Group\n * @author Alexander Rose \n * @private\n */\n\nimport { Box3, BufferGeometry } from 'three'\n\nclass GeometryGroup {\n geometryList: BufferGeometry[]\n boundingBox: Box3\n\n constructor (geometryList: BufferGeometry[] = []) {\n this.geometryList = geometryList\n }\n\n computeBoundingBox () {\n if (!this.boundingBox) {\n this.boundingBox = new Box3()\n } else {\n this.boundingBox.empty()\n }\n\n this.geometryList.forEach(geo => {\n if (!geo.boundingBox) geo.computeBoundingBox()\n this.boundingBox.union(geo.boundingBox as Box3)\n })\n }\n}\n\nexport default GeometryGroup\n","/**\n * @file Arrow Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { Matrix4, Vector3, Group } from 'three'\n\nimport { BufferRegistry } from '../globals'\nimport { createParams, defaults } from '../utils'\nimport { Picker } from '../utils/picker'\nimport Buffer from './buffer'\nimport CylinderBuffer, { CylinderBufferData } from './cylinder-buffer'\nimport CylinderGeometryBuffer from './cylindergeometry-buffer'\nimport ConeBuffer, { ConeBufferData } from './cone-buffer'\nimport GeometryGroup from '../viewer/geometry-group'\nimport { BufferData, BufferDefaultParameters } from './buffer'\n\nexport interface ArrowBufferData extends BufferData {\n position1: Float32Array\n position2: Float32Array\n radius: Float32Array\n}\n\nexport const ArrowBufferDefaultParameters = Object.assign({\n aspectRatio: 1.5,\n radialSegments: 50,\n openEnded: false,\n disableImpostor: false\n}, BufferDefaultParameters)\nexport type ArrowBufferParameters = typeof ArrowBufferDefaultParameters\n\n/**\n * Arrow buffer. Draws arrows made from a cylinder and a cone.\n * @implements {Buffer}\n *\n * @example\n * var arrowBuffer = new ArrowBuffer({\n * position1: new Float32Array([ 0, 0, 0 ]),\n * position2: new Float32Array([ 10, 1, 1 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * radius: new Float32Array([ 1 ])\n * });\n */\nclass ArrowBuffer {\n parameters: ArrowBufferParameters\n get defaultParameters() { return ArrowBufferDefaultParameters }\n\n cylinderBuffer: CylinderGeometryBuffer\n coneBuffer: ConeBuffer\n\n splitPosition: Float32Array\n cylinderRadius: Float32Array\n\n geometry: GeometryGroup\n picking?: Picker\n\n group = new Group()\n wireframeGroup = new Group()\n pickingGroup = new Group()\n\n visible = true\n\n /**\n * @param {Object} data - buffer data\n * @param {Float32Array} data.position1 - from positions\n * @param {Float32Array} data.position2 - to positions\n * @param {Float32Array} data.color - colors\n * @param {Float32Array} data.radius - radii\n * @param {Picker} [data.picking] - picking ids\n * @param {BufferParameters} [params] - parameters object\n */\n constructor (data: ArrowBufferData, params: Partial = {}) {\n this.parameters = createParams(params, this.defaultParameters)\n\n this.splitPosition = new Float32Array(data.position1.length)\n this.cylinderRadius = new Float32Array(data.radius.length)\n\n const attr = this.makeAttributes(data)\n const bufferParams = {\n radialSegments: this.parameters.radialSegments,\n openEnded: this.parameters.openEnded,\n disableImpostor: this.parameters.disableImpostor\n }\n\n this.cylinderBuffer = new CylinderBuffer(\n attr.cylinder as CylinderBufferData, bufferParams\n ) as CylinderGeometryBuffer\n this.coneBuffer = new ConeBuffer(\n attr.cone as ConeBufferData, bufferParams\n )\n\n this.geometry = new GeometryGroup([\n this.cylinderBuffer.geometry,\n this.coneBuffer.geometry\n ])\n\n // requires Group objects to be present\n this.matrix = defaults(params.matrix, new Matrix4())\n\n this.picking = data.picking\n }\n\n set matrix (m) {\n Buffer.prototype.setMatrix.call(this, m)\n }\n get matrix () {\n return this.group.matrix.clone()\n }\n\n get pickable () {\n return !!this.picking\n }\n\n makeAttributes (data: Partial = {}) {\n const splitPosition = this.splitPosition\n const cylinderRadius = this.cylinderRadius\n\n const aspectRatio = this.parameters.aspectRatio\n\n let i, il\n const cylinder: Partial = {}\n const cone: Partial = {}\n\n if (data.radius) {\n for (i = 0, il = cylinderRadius.length; i < il; ++i) {\n cylinderRadius[ i ] = data.radius[ i ] / aspectRatio\n }\n cylinder.radius = cylinderRadius\n cone.radius = data.radius\n }\n\n if (data.position1 && data.position2) {\n const vFrom = new Vector3()\n const vTo = new Vector3()\n const vDir = new Vector3()\n const vSplit = new Vector3()\n for (i = 0, il = splitPosition.length; i < il; i += 3) {\n vFrom.fromArray(data.position1 as any, i)\n vTo.fromArray(data.position2 as any, i)\n vDir.subVectors(vFrom, vTo)\n const fullLength = vDir.length()\n const coneLength = cylinderRadius[ i / 3 ] * aspectRatio * 2\n const length = Math.min(fullLength, coneLength)\n vDir.setLength(length)\n vSplit.copy(vTo).add(vDir)\n vSplit.toArray(splitPosition as any, i)\n }\n cylinder.position1 = data.position1\n cylinder.position2 = splitPosition\n cone.position1 = splitPosition\n cone.position2 = data.position2\n }\n\n if (data.color) {\n cylinder.color = data.color\n cylinder.color2 = data.color\n cone.color = data.color\n }\n\n return {\n cylinder: cylinder,\n cone: cone\n }\n }\n\n getMesh () {\n return new Group().add(\n this.cylinderBuffer.getMesh(),\n this.coneBuffer.getMesh()\n )\n }\n\n getWireframeMesh () {\n return new Group().add(\n this.cylinderBuffer.getWireframeMesh(),\n this.coneBuffer.getWireframeMesh()\n )\n }\n\n getPickingMesh () {\n return new Group().add(\n this.cylinderBuffer.getPickingMesh(),\n this.coneBuffer.getPickingMesh()\n )\n }\n\n setAttributes (data: Partial = {}) {\n const attr = this.makeAttributes(data)\n\n this.cylinderBuffer.setAttributes(attr.cylinder)\n this.coneBuffer.setAttributes(attr.cone)\n }\n\n /**\n * Set buffer parameters\n * @param {BufferParameters} params - buffer parameters object\n * @return {undefined}\n */\n setParameters (params: Partial = {}) {\n params = Object.assign({}, params)\n\n if (params && params.matrix !== undefined) {\n this.matrix = params.matrix\n }\n delete params.matrix\n\n if (params && params.wireframe !== undefined) {\n this.parameters.wireframe = params.wireframe\n this.setVisibility(this.visible)\n }\n\n this.cylinderBuffer.setParameters(params)\n this.coneBuffer.setParameters(params)\n }\n\n setVisibility (value: boolean) {\n Buffer.prototype.setVisibility.call(this, value)\n }\n\n dispose () {\n this.cylinderBuffer.dispose()\n this.coneBuffer.dispose()\n }\n}\n\nBufferRegistry.add('arrow', ArrowBuffer)\n\nexport default ArrowBuffer\n","/**\n * @file Box Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { BoxGeometry, Vector3, Matrix4 } from 'three'\n\nimport { BufferRegistry } from '../globals'\nimport GeometryBuffer from './geometry-buffer'\nimport { BufferData, BufferParameters } from './buffer'\n\nconst scale = new Vector3()\nconst target = new Vector3()\nconst up = new Vector3()\nconst eye = new Vector3(0, 0, 0)\n\nexport interface BoxBufferData extends BufferData {\n heightAxis: Float32Array\n depthAxis: Float32Array\n size: Float32Array\n}\n\n/**\n * Box buffer. Draws boxes.\n *\n * @example\n * var boxBuffer = new BoxBuffer({\n * position: new Float32Array([ 0, 3, 0, -2, 0, 0 ]),\n * color: new Float32Array([ 1, 0, 1, 0, 1, 0 ]),\n * size: new Float32Array([ 2, 1.5 ]),\n * heightAxis: new Float32Array([ 0, 1, 1, 0, 2, 0 ]),\n * depthAxis: new Float32Array([ 1, 0, 1, 0, 0, 2 ])\n * })\n */\nclass BoxBuffer extends GeometryBuffer {\n updateNormals = true\n\n _heightAxis: Float32Array\n _depthAxis: Float32Array\n _size: Float32Array\n\n constructor (data: BoxBufferData, params: Partial = {}) {\n super(data, params, new BoxGeometry(1, 1, 1))\n\n this.setAttributes(data, true)\n }\n\n applyPositionTransform (matrix: Matrix4, i: number, i3: number) {\n target.fromArray(this._heightAxis as any, i3)\n up.fromArray(this._depthAxis as any, i3)\n matrix.lookAt(eye, target, up)\n\n scale.set(this._size[ i ], up.length(), target.length())\n matrix.scale(scale)\n }\n\n setAttributes (data: Partial = {}, initNormals?: boolean) {\n if (data.size) this._size = data.size\n if (data.heightAxis) this._heightAxis = data.heightAxis\n if (data.depthAxis) this._depthAxis = data.depthAxis\n\n super.setAttributes(data, initNormals)\n }\n}\n\nBufferRegistry.add('box', BoxBuffer)\n\nexport default BoxBuffer\n","/**\n * @file Ellipsoid Geometry Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { IcosahedronGeometry, Vector3, Matrix4 } from 'three'\n\nimport { BufferRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport GeometryBuffer from './geometry-buffer'\nimport { BufferData, BufferDefaultParameters } from './buffer'\n\nconst scale = new Vector3()\nconst target = new Vector3()\nconst up = new Vector3()\nconst eye = new Vector3(0, 0, 0)\n\nexport interface EllipsoidBufferData extends BufferData {\n majorAxis: Float32Array\n minorAxis: Float32Array\n radius: Float32Array\n}\n\nexport const EllipsoidBufferDefaultParameters = Object.assign({\n sphereDetail: 2,\n}, BufferDefaultParameters)\nexport type EllipsoidBufferParameters = typeof EllipsoidBufferDefaultParameters\n\n/**\n * Ellipsoid buffer. Draws ellipsoids.\n *\n * @example\n * var ellipsoidBuffer = new EllipsoidBuffer({\n * position: new Float32Array([ 0, 0, 0 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * radius: new Float32Array([ 1 ]),\n * majorAxis: new Float32Array([ 1, 1, 0 ]),\n * minorAxis: new Float32Array([ 0.5, 0, 0.5 ]),\n * });\n */\nclass EllipsoidBuffer extends GeometryBuffer {\n updateNormals = true\n\n get defaultParameters() { return EllipsoidBufferDefaultParameters }\n parameters: EllipsoidBufferParameters\n\n _majorAxis: Float32Array\n _minorAxis: Float32Array\n _radius: Float32Array\n\n constructor (data: EllipsoidBufferData, params: Partial = {}) {\n super(data, params, new IcosahedronGeometry(1, defaults(params.sphereDetail, 2)))\n\n this.setAttributes(data, true)\n }\n\n applyPositionTransform (matrix: Matrix4, i: number, i3: number) {\n target.fromArray(this._majorAxis as any, i3)\n up.fromArray(this._minorAxis as any, i3)\n matrix.lookAt(eye, target, up)\n\n scale.set(this._radius[ i ], up.length(), target.length())\n matrix.scale(scale)\n }\n\n setAttributes (data: Partial = {}, initNormals?: boolean) {\n if (data.radius) this._radius = data.radius\n if (data.majorAxis) this._majorAxis = data.majorAxis\n if (data.minorAxis) this._minorAxis = data.minorAxis\n\n super.setAttributes(data, initNormals)\n }\n}\n\nBufferRegistry.add('ellipsoid', EllipsoidBuffer)\n\nexport default EllipsoidBuffer\n","/**\n * @file Octahedron Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { OctahedronGeometry, Vector3, Matrix4 } from 'three'\nimport { BufferRegistry } from '../globals'\nimport GeometryBuffer from './geometry-buffer'\nimport { BufferData, BufferParameters } from './buffer'\n\nconst scale = new Vector3()\nconst target = new Vector3()\nconst up = new Vector3()\nconst eye = new Vector3(0, 0, 0)\n\nexport interface OctahedronBufferData extends BufferData {\n heightAxis: Float32Array\n depthAxis: Float32Array\n size: Float32Array\n}\n\n/**\n * Octahedron buffer. Draws octahedrons.\n *\n * @example\n * var octahedronBuffer = new OctahedronBuffer({\n * position: new Float32Array([ 0, 3, 0, -2, 0, 0 ]),\n * color: new Float32Array([ 1, 0, 1, 0, 1, 0 ]),\n * size: new Float32Array([ 2, 1.5 ]),\n * heightAxis: new Float32Array([ 0, 1, 1, 0, 2, 0 ]),\n * depthAxis: new Float32Array([ 1, 0, 1, 0, 0, 2 ])\n * })\n */\nclass OctahedronBuffer extends GeometryBuffer {\n updateNormals = true\n\n _heightAxis: Float32Array\n _depthAxis: Float32Array\n _size: Float32Array\n\n constructor (data: OctahedronBufferData, params: Partial = {}) {\n super(data, params, new OctahedronGeometry(1, 0))\n\n this.setAttributes(data, true)\n }\n\n applyPositionTransform (matrix: Matrix4, i: number, i3: number) {\n target.fromArray(this._heightAxis as any, i3)\n up.fromArray(this._depthAxis as any, i3)\n matrix.lookAt(eye, target, up)\n\n scale.set(this._size[ i ], up.length(), target.length())\n matrix.scale(scale)\n }\n\n setAttributes (data: Partial = {}, initNormals?: boolean) {\n if (data.size) this._size = data.size\n if (data.heightAxis) this._heightAxis = data.heightAxis\n if (data.depthAxis) this._depthAxis = data.depthAxis\n\n super.setAttributes(data, initNormals)\n }\n}\n\nBufferRegistry.add('octahedron', OctahedronBuffer)\n\nexport default OctahedronBuffer\n","/**\n * @file Tetrahedron Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { TetrahedronGeometry, Vector3, Matrix4 } from 'three'\nimport { BufferRegistry } from '../globals'\nimport GeometryBuffer from './geometry-buffer'\nimport { BufferData, BufferParameters } from './buffer'\n\nconst scale = new Vector3()\nconst target = new Vector3()\nconst up = new Vector3()\nconst eye = new Vector3(0, 0, 0)\n\nexport interface TetrahedronBufferData extends BufferData {\n heightAxis: Float32Array\n depthAxis: Float32Array\n size: Float32Array\n}\n\n/**\n * Tetrahedron buffer. Draws tetrahedrons.\n *\n * @example\n * var tetrahedronBuffer = new TetrahedronBuffer({\n * position: new Float32Array([ 0, 3, 0, -2, 0, 0 ]),\n * color: new Float32Array([ 1, 0, 1, 0, 1, 0 ]),\n * size: new Float32Array([ 2, 1.5 ]),\n * heightAxis: new Float32Array([ 0, 1, 1, 0, 2, 0 ]),\n * depthAxis: new Float32Array([ 1, 0, 1, 0, 0, 2 ])\n * })\n */\nclass TetrahedronBuffer extends GeometryBuffer {\n updateNormals = true\n\n _heightAxis: Float32Array\n _depthAxis: Float32Array\n _size: Float32Array\n\n constructor (data: TetrahedronBufferData, params: Partial = {}) {\n super(data, params, new TetrahedronGeometry(1, 0))\n\n this.setAttributes(data, true)\n }\n\n applyPositionTransform (matrix: Matrix4, i: number, i3: number) {\n target.fromArray(this._heightAxis as any, i3)\n up.fromArray(this._depthAxis as any, i3)\n matrix.lookAt(eye, target, up)\n\n scale.set(this._size[ i ], up.length(), target.length())\n matrix.scale(scale)\n }\n\n setAttributes (data: Partial = {}, initNormals?: boolean) {\n if (data.size) this._size = data.size\n if (data.heightAxis) this._heightAxis = data.heightAxis\n if (data.depthAxis) this._depthAxis = data.depthAxis\n\n super.setAttributes(data, initNormals)\n }\n}\n\nBufferRegistry.add('tetrahedron', TetrahedronBuffer)\n\nexport default TetrahedronBuffer\n","/**\n * @file Tetrahedron Geometry Buffer\n * @author Alexander Rose \n * @private\n */\n\nimport { TorusGeometry, Vector3, Matrix4 } from 'three'\n\nimport { BufferRegistry } from '../globals'\nimport { defaults } from '../utils'\nimport GeometryBuffer from './geometry-buffer'\nimport { BufferDefaultParameters, BufferData } from './buffer'\n\nconst scale = new Vector3()\nconst target = new Vector3()\nconst up = new Vector3()\nconst eye = new Vector3(0, 0, 0)\n\nexport interface TorusBufferData extends BufferData {\n majorAxis: Float32Array\n minorAxis: Float32Array\n radius: Float32Array\n}\n\nexport const TorusBufferDefaultParameters = Object.assign({\n radiusRatio: 0.2,\n radialSegments: 16,\n tubularSegments: 32\n}, BufferDefaultParameters)\nexport type TorusBufferParameters = typeof TorusBufferDefaultParameters\n\n/**\n * Torus geometry buffer. Draws torii.\n *\n * @example\n * var torusBuffer = new TorusBuffer({\n * position: new Float32Array([ 0, 0, 0 ]),\n * color: new Float32Array([ 1, 0, 0 ]),\n * radius: new Float32Array([ 1 ]),\n * majorAxis: new Float32Array([ 1, 1, 0 ]),\n * minorAxis: new Float32Array([ 0.5, 0, 0.5 ]),\n * });\n */\nclass TorusBuffer extends GeometryBuffer {\n updateNormals = true\n\n get defaultParameters() { return TorusBufferDefaultParameters }\n parameters: TorusBufferParameters\n\n _majorAxis: Float32Array\n _minorAxis: Float32Array\n _radius: Float32Array\n\n constructor (data: TorusBufferData, params: Partial = {}) {\n super(data, params, new TorusGeometry(\n 1,\n defaults(params.radiusRatio, 0.2),\n defaults(params.radialSegments, 16),\n defaults(params.tubularSegments, 32)\n ))\n\n this.setAttributes(data, true)\n }\n\n applyPositionTransform (matrix: Matrix4, i: number, i3: number) {\n target.fromArray(this._majorAxis as any, i3)\n up.fromArray(this._minorAxis as any, i3)\n matrix.lookAt(eye, target, up)\n\n const r = this._radius[ i ]\n scale.set(r, r, r)\n matrix.scale(scale)\n }\n\n setAttributes (data: Partial = {}, initNormals?: boolean) {\n if (data.radius) this._radius = data.radius\n if (data.majorAxis) this._majorAxis = data.majorAxis\n if (data.minorAxis) this._minorAxis = data.minorAxis\n\n super.setAttributes(data, initNormals)\n }\n}\n\nBufferRegistry.add('torus', TorusBuffer)\n\nexport default TorusBuffer\n","/**\n * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n */\nexport function getArrayBounds(rowCount, params) {\n const start = params && typeof params.start !== 'undefined' ? Math.max(Math.min(params.start, rowCount - 1), 0) : 0;\n const end = params && typeof params.end !== 'undefined' ? Math.min(params.end, rowCount) : rowCount;\n return { start, end };\n}\nexport function createArray(rowCount, params) {\n const c = params && typeof params.array !== 'undefined' ? params.array : Array;\n const { start, end } = getArrayBounds(rowCount, params);\n return { array: new c(end - start), start, end };\n}\nexport function fillArrayValues(value, target, start) {\n for (let i = 0, _e = target.length; i < _e; i++)\n target[i] = value(start + i);\n return target;\n}\nexport function createAndFillArray(rowCount, value, params) {\n const { array, start } = createArray(rowCount, params);\n return fillArrayValues(value, array, start);\n}\nexport function isTypedArray(data) {\n return !!data.buffer && typeof data.byteLength === 'number' && typeof data.BYTES_PER_ELEMENT === 'number';\n}\nexport function typedArrayWindow(data, params) {\n const { constructor, buffer, length, byteOffset, BYTES_PER_ELEMENT } = data;\n const { start, end } = getArrayBounds(length, params);\n if (start === 0 && end === length)\n return data;\n return new constructor(buffer, byteOffset + BYTES_PER_ELEMENT * start, Math.min(length, end - start));\n}\n","/**\n * Copyright (c) 2017-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n * @author Alexander Rose \n */\n/*\n * This code has been modified from https://github.com/toji/gl-matrix/,\n * copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n */\nexport const EPSILON = 0.000001;\nexport function equalEps(a, b, eps) {\n return Math.abs(a - b) <= eps;\n}\n","/**\n * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author Alexander Rose \n */\nexport function normalize(value, min, max) {\n return (value - min) / (max - min);\n}\nexport function clamp(value, min, max) {\n return Math.max(min, Math.min(max, value));\n}\nexport function pclamp(value) {\n return clamp(value, 0, 100);\n}\nexport function saturate(value) {\n return clamp(value, 0, 1);\n}\nexport function damp(value, dampingFactor) {\n const dampedValue = value * dampingFactor;\n return Math.abs(dampedValue) < 0.1 ? 0 : dampedValue;\n}\nexport function lerp(start, stop, alpha) {\n return start + (stop - start) * alpha;\n}\n/** Catmul-Rom spline */\nexport function spline(p0, p1, p2, p3, t, tension) {\n const v0 = (p2 - p0) * tension;\n const v1 = (p3 - p1) * tension;\n const t2 = t * t;\n const t3 = t * t2;\n return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;\n}\nexport function quadraticBezier(p0, p1, p2, t) {\n const k = 1 - t;\n return (k * k * p0) + (2 * k * t * p1) + (t * t * p2);\n}\nexport function smoothstep(min, max, x) {\n x = saturate(normalize(x, min, max));\n return x * x * (3 - 2 * x);\n}\nexport function smootherstep(min, max, x) {\n x = saturate(normalize(x, min, max));\n return x * x * x * (x * (x * 6 - 15) + 10);\n}\nexport function smootheststep(min, max, x) {\n x = saturate(normalize(x, min, max));\n return -20 * Math.pow(x, 7) + 70 * Math.pow(x, 6) - 84 * Math.pow(x, 5) + 35 * Math.pow(x, 4);\n}\nexport function almostIdentity(value, start, stop) {\n if (value > start)\n return value;\n const a = 2 * stop - start;\n const b = 2 * start - 3 * stop;\n const t = value / start;\n return (a * t + b) * t * t + stop;\n}\n","/**\n * Copyright (c) 2017-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n * @author Alexander Rose \n */\n/*\n * This code has been modified from https://github.com/toji/gl-matrix/,\n * copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n */\nimport { Mat4 } from './mat4';\nimport { spline as _spline, quadraticBezier as _quadraticBezier, clamp as _clamp } from '../../interpolate';\nimport { EPSILON } from './common';\nconst _isFinite = isFinite;\nfunction Vec3() {\n return Vec3.zero();\n}\n(function (Vec3) {\n function zero() {\n const out = [0.1, 0.0, 0.0]; // ensure backing array of type double\n out[0] = 0;\n return out;\n }\n Vec3.zero = zero;\n function clone(a) {\n const out = zero();\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n return out;\n }\n Vec3.clone = clone;\n function isFinite(a) {\n return _isFinite(a[0]) && _isFinite(a[1]) && _isFinite(a[2]);\n }\n Vec3.isFinite = isFinite;\n function hasNaN(a) {\n return isNaN(a[0]) || isNaN(a[1]) || isNaN(a[2]);\n }\n Vec3.hasNaN = hasNaN;\n function setNaN(out) {\n out[0] = NaN;\n out[1] = NaN;\n out[2] = NaN;\n return out;\n }\n Vec3.setNaN = setNaN;\n function fromObj(v) {\n return create(v.x, v.y, v.z);\n }\n Vec3.fromObj = fromObj;\n function toObj(v) {\n return { x: v[0], y: v[1], z: v[2] };\n }\n Vec3.toObj = toObj;\n function fromArray(v, array, offset) {\n v[0] = array[offset + 0];\n v[1] = array[offset + 1];\n v[2] = array[offset + 2];\n return v;\n }\n Vec3.fromArray = fromArray;\n function toArray(v, out, offset) {\n out[offset + 0] = v[0];\n out[offset + 1] = v[1];\n out[offset + 2] = v[2];\n return out;\n }\n Vec3.toArray = toArray;\n function create(x, y, z) {\n const out = zero();\n out[0] = x;\n out[1] = y;\n out[2] = z;\n return out;\n }\n Vec3.create = create;\n function ofArray(array) {\n const out = zero();\n out[0] = array[0];\n out[1] = array[1];\n out[2] = array[2];\n return out;\n }\n Vec3.ofArray = ofArray;\n function set(out, x, y, z) {\n out[0] = x;\n out[1] = y;\n out[2] = z;\n return out;\n }\n Vec3.set = set;\n function copy(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n return out;\n }\n Vec3.copy = copy;\n function add(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n return out;\n }\n Vec3.add = add;\n function sub(out, a, b) {\n out[0] = a[0] - b[0];\n out[1] = a[1] - b[1];\n out[2] = a[2] - b[2];\n return out;\n }\n Vec3.sub = sub;\n function mul(out, a, b) {\n out[0] = a[0] * b[0];\n out[1] = a[1] * b[1];\n out[2] = a[2] * b[2];\n return out;\n }\n Vec3.mul = mul;\n function div(out, a, b) {\n out[0] = a[0] / b[0];\n out[1] = a[1] / b[1];\n out[2] = a[2] / b[2];\n return out;\n }\n Vec3.div = div;\n function scale(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n out[2] = a[2] * b;\n return out;\n }\n Vec3.scale = scale;\n /** Scales b, then adds a and b together */\n function scaleAndAdd(out, a, b, scale) {\n out[0] = a[0] + (b[0] * scale);\n out[1] = a[1] + (b[1] * scale);\n out[2] = a[2] + (b[2] * scale);\n return out;\n }\n Vec3.scaleAndAdd = scaleAndAdd;\n /** Scales b, then subtracts b from a */\n function scaleAndSub(out, a, b, scale) {\n out[0] = a[0] - (b[0] * scale);\n out[1] = a[1] - (b[1] * scale);\n out[2] = a[2] - (b[2] * scale);\n return out;\n }\n Vec3.scaleAndSub = scaleAndSub;\n function addScalar(out, a, b) {\n out[0] = a[0] + b;\n out[1] = a[1] + b;\n out[2] = a[2] + b;\n return out;\n }\n Vec3.addScalar = addScalar;\n function subScalar(out, a, b) {\n out[0] = a[0] - b;\n out[1] = a[1] - b;\n out[2] = a[2] - b;\n return out;\n }\n Vec3.subScalar = subScalar;\n /**\n * Math.round the components of a Vec3\n */\n function round(out, a) {\n out[0] = Math.round(a[0]);\n out[1] = Math.round(a[1]);\n out[2] = Math.round(a[2]);\n return out;\n }\n Vec3.round = round;\n /**\n * Math.ceil the components of a Vec3\n */\n function ceil(out, a) {\n out[0] = Math.ceil(a[0]);\n out[1] = Math.ceil(a[1]);\n out[2] = Math.ceil(a[2]);\n return out;\n }\n Vec3.ceil = ceil;\n /**\n * Math.floor the components of a Vec3\n */\n function floor(out, a) {\n out[0] = Math.floor(a[0]);\n out[1] = Math.floor(a[1]);\n out[2] = Math.floor(a[2]);\n return out;\n }\n Vec3.floor = floor;\n /**\n * Math.trunc the components of a Vec3\n */\n function trunc(out, a) {\n out[0] = Math.trunc(a[0]);\n out[1] = Math.trunc(a[1]);\n out[2] = Math.trunc(a[2]);\n return out;\n }\n Vec3.trunc = trunc;\n /**\n * Math.abs the components of a Vec3\n */\n function abs(out, a) {\n out[0] = Math.abs(a[0]);\n out[1] = Math.abs(a[1]);\n out[2] = Math.abs(a[2]);\n return out;\n }\n Vec3.abs = abs;\n /**\n * Returns the minimum of two Vec3's\n */\n function min(out, a, b) {\n out[0] = Math.min(a[0], b[0]);\n out[1] = Math.min(a[1], b[1]);\n out[2] = Math.min(a[2], b[2]);\n return out;\n }\n Vec3.min = min;\n /**\n * Returns the maximum of two Vec3's\n */\n function max(out, a, b) {\n out[0] = Math.max(a[0], b[0]);\n out[1] = Math.max(a[1], b[1]);\n out[2] = Math.max(a[2], b[2]);\n return out;\n }\n Vec3.max = max;\n /**\n * Assumes min < max, componentwise\n */\n function clamp(out, a, min, max) {\n out[0] = Math.max(min[0], Math.min(max[0], a[0]));\n out[1] = Math.max(min[1], Math.min(max[1], a[1]));\n out[2] = Math.max(min[2], Math.min(max[2], a[2]));\n return out;\n }\n Vec3.clamp = clamp;\n function distance(a, b) {\n const x = b[0] - a[0], y = b[1] - a[1], z = b[2] - a[2];\n return Math.sqrt(x * x + y * y + z * z);\n }\n Vec3.distance = distance;\n function squaredDistance(a, b) {\n const x = b[0] - a[0], y = b[1] - a[1], z = b[2] - a[2];\n return x * x + y * y + z * z;\n }\n Vec3.squaredDistance = squaredDistance;\n function magnitude(a) {\n const x = a[0], y = a[1], z = a[2];\n return Math.sqrt(x * x + y * y + z * z);\n }\n Vec3.magnitude = magnitude;\n function squaredMagnitude(a) {\n const x = a[0], y = a[1], z = a[2];\n return x * x + y * y + z * z;\n }\n Vec3.squaredMagnitude = squaredMagnitude;\n function setMagnitude(out, a, l) {\n return scale(out, normalize(out, a), l);\n }\n Vec3.setMagnitude = setMagnitude;\n /**\n * Negates the components of a vec3\n */\n function negate(out, a) {\n out[0] = -a[0];\n out[1] = -a[1];\n out[2] = -a[2];\n return out;\n }\n Vec3.negate = negate;\n /**\n * Returns the inverse of the components of a Vec3\n */\n function inverse(out, a) {\n out[0] = 1.0 / a[0];\n out[1] = 1.0 / a[1];\n out[2] = 1.0 / a[2];\n return out;\n }\n Vec3.inverse = inverse;\n function normalize(out, a) {\n const x = a[0], y = a[1], z = a[2];\n let len = x * x + y * y + z * z;\n if (len > 0) {\n len = 1 / Math.sqrt(len);\n out[0] = a[0] * len;\n out[1] = a[1] * len;\n out[2] = a[2] * len;\n }\n return out;\n }\n Vec3.normalize = normalize;\n function dot(a, b) {\n return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];\n }\n Vec3.dot = dot;\n function cross(out, a, b) {\n const ax = a[0], ay = a[1], az = a[2], bx = b[0], by = b[1], bz = b[2];\n out[0] = ay * bz - az * by;\n out[1] = az * bx - ax * bz;\n out[2] = ax * by - ay * bx;\n return out;\n }\n Vec3.cross = cross;\n /**\n * Performs a linear interpolation between two Vec3's\n */\n function lerp(out, a, b, t) {\n const ax = a[0], ay = a[1], az = a[2];\n out[0] = ax + t * (b[0] - ax);\n out[1] = ay + t * (b[1] - ay);\n out[2] = az + t * (b[2] - az);\n return out;\n }\n Vec3.lerp = lerp;\n const slerpRelVec = zero();\n function slerp(out, a, b, t) {\n const d = _clamp(dot(a, b), -1, 1);\n const theta = Math.acos(d) * t;\n scaleAndAdd(slerpRelVec, b, a, -d);\n normalize(slerpRelVec, slerpRelVec);\n return add(out, scale(out, a, Math.cos(theta)), scale(slerpRelVec, slerpRelVec, Math.sin(theta)));\n }\n Vec3.slerp = slerp;\n /**\n * Performs a hermite interpolation with two control points\n */\n function hermite(out, a, b, c, d, t) {\n const factorTimes2 = t * t;\n const factor1 = factorTimes2 * (2 * t - 3) + 1;\n const factor2 = factorTimes2 * (t - 2) + t;\n const factor3 = factorTimes2 * (t - 1);\n const factor4 = factorTimes2 * (3 - 2 * t);\n out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;\n out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;\n out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;\n return out;\n }\n Vec3.hermite = hermite;\n /**\n * Performs a bezier interpolation with two control points\n */\n function bezier(out, a, b, c, d, t) {\n const inverseFactor = 1 - t;\n const inverseFactorTimesTwo = inverseFactor * inverseFactor;\n const factorTimes2 = t * t;\n const factor1 = inverseFactorTimesTwo * inverseFactor;\n const factor2 = 3 * t * inverseFactorTimesTwo;\n const factor3 = 3 * factorTimes2 * inverseFactor;\n const factor4 = factorTimes2 * t;\n out[0] = a[0] * factor1 + b[0] * factor2 + c[0] * factor3 + d[0] * factor4;\n out[1] = a[1] * factor1 + b[1] * factor2 + c[1] * factor3 + d[1] * factor4;\n out[2] = a[2] * factor1 + b[2] * factor2 + c[2] * factor3 + d[2] * factor4;\n return out;\n }\n Vec3.bezier = bezier;\n function quadraticBezier(out, a, b, c, t) {\n out[0] = _quadraticBezier(a[0], b[0], c[0], t);\n out[1] = _quadraticBezier(a[1], b[1], c[1], t);\n out[2] = _quadraticBezier(a[2], b[2], c[2], t);\n return out;\n }\n Vec3.quadraticBezier = quadraticBezier;\n /**\n * Performs a spline interpolation with two control points and a tension parameter\n */\n function spline(out, a, b, c, d, t, tension) {\n out[0] = _spline(a[0], b[0], c[0], d[0], t, tension);\n out[1] = _spline(a[1], b[1], c[1], d[1], t, tension);\n out[2] = _spline(a[2], b[2], c[2], d[2], t, tension);\n return out;\n }\n Vec3.spline = spline;\n /**\n * Generates a random vector with the given scale\n */\n function random(out, scale) {\n const r = Math.random() * 2.0 * Math.PI;\n const z = (Math.random() * 2.0) - 1.0;\n const zScale = Math.sqrt(1.0 - z * z) * scale;\n out[0] = Math.cos(r) * zScale;\n out[1] = Math.sin(r) * zScale;\n out[2] = z * scale;\n return out;\n }\n Vec3.random = random;\n /**\n * Transforms the Vec3 with a Mat4. 4th vector component is implicitly '1'\n */\n function transformMat4(out, a, m) {\n const x = a[0], y = a[1], z = a[2], w = 1 / ((m[3] * x + m[7] * y + m[11] * z + m[15]) || 1.0);\n out[0] = (m[0] * x + m[4] * y + m[8] * z + m[12]) * w;\n out[1] = (m[1] * x + m[5] * y + m[9] * z + m[13]) * w;\n out[2] = (m[2] * x + m[6] * y + m[10] * z + m[14]) * w;\n return out;\n }\n Vec3.transformMat4 = transformMat4;\n function transformDirection(out, a, m) {\n const x = a[0], y = a[1], z = a[2];\n out[0] = m[0] * x + m[4] * y + m[8] * z;\n out[1] = m[1] * x + m[5] * y + m[9] * z;\n out[2] = m[2] * x + m[6] * y + m[10] * z;\n return normalize(out, out);\n }\n Vec3.transformDirection = transformDirection;\n /**\n * Like `transformMat4` but with offsets into arrays\n */\n function transformMat4Offset(out, a, m, outO, aO, oM) {\n const x = a[0 + aO], y = a[1 + aO], z = a[2 + aO], w = 1 / ((m[3 + oM] * x + m[7 + oM] * y + m[11 + oM] * z + m[15 + oM]) || 1.0);\n out[0 + outO] = (m[0 + oM] * x + m[4 + oM] * y + m[8 + oM] * z + m[12 + oM]) * w;\n out[1 + outO] = (m[1 + oM] * x + m[5 + oM] * y + m[9 + oM] * z + m[13 + oM]) * w;\n out[2 + outO] = (m[2 + oM] * x + m[6 + oM] * y + m[10 + oM] * z + m[14 + oM]) * w;\n return out;\n }\n Vec3.transformMat4Offset = transformMat4Offset;\n /**\n * Transforms the direction vector with a Mat4. 4th vector component is implicitly '0'\n * This means the translation components of the matrix are ignored.\n * Assumes that m is already the transpose of the inverse matrix suitable for normal transformation.\n */\n function transformDirectionOffset(out, a, m, outO, aO, oM) {\n const x = a[0 + aO], y = a[1 + aO], z = a[2 + aO];\n out[0 + outO] = m[0 + oM] * x + m[4 + oM] * y + m[8 + oM] * z;\n out[1 + outO] = m[1 + oM] * x + m[5 + oM] * y + m[9 + oM] * z;\n out[2 + outO] = m[2 + oM] * x + m[6 + oM] * y + m[10 + oM] * z;\n // Normalize the output vector to handle non-uniform scaling\n const len = Math.hypot(out[0 + outO], out[1 + outO], out[2 + outO]);\n if (len > 0) {\n out[0 + outO] /= len;\n out[1 + outO] /= len;\n out[2 + outO] /= len;\n }\n return out;\n }\n Vec3.transformDirectionOffset = transformDirectionOffset;\n /**\n * Transforms the Vec3 with a Mat3.\n */\n function transformMat3(out, a, m) {\n const x = a[0], y = a[1], z = a[2];\n out[0] = x * m[0] + y * m[3] + z * m[6];\n out[1] = x * m[1] + y * m[4] + z * m[7];\n out[2] = x * m[2] + y * m[5] + z * m[8];\n return out;\n }\n Vec3.transformMat3 = transformMat3;\n /** Transforms the Vec3 with a quat */\n function transformQuat(out, a, q) {\n // benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations\n const x = a[0], y = a[1], z = a[2];\n const qx = q[0], qy = q[1], qz = q[2], qw = q[3];\n // calculate quat * vec\n const ix = qw * x + qy * z - qz * y;\n const iy = qw * y + qz * x - qx * z;\n const iz = qw * z + qx * y - qy * x;\n const iw = -qx * x - qy * y - qz * z;\n // calculate result * inverse quat\n out[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;\n out[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;\n out[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;\n return out;\n }\n Vec3.transformQuat = transformQuat;\n /** Computes the angle between 2 vectors, reports in radians. */\n function angle(a, b) {\n const denominator = Math.sqrt(squaredMagnitude(a) * squaredMagnitude(b));\n if (denominator === 0)\n return Math.PI / 2;\n const theta = dot(a, b) / denominator;\n return Math.acos(_clamp(theta, -1, 1)); // clamp to avoid numerical problems\n }\n Vec3.angle = angle;\n const tmp_dh_ab = zero();\n const tmp_dh_cb = zero();\n const tmp_dh_bc = zero();\n const tmp_dh_dc = zero();\n const tmp_dh_abc = zero();\n const tmp_dh_bcd = zero();\n const tmp_dh_cross = zero();\n /**\n * Computes the dihedral angles of 4 points, reports in radians.\n */\n function dihedralAngle(a, b, c, d) {\n sub(tmp_dh_ab, a, b);\n sub(tmp_dh_cb, c, b);\n sub(tmp_dh_bc, b, c);\n sub(tmp_dh_dc, d, c);\n cross(tmp_dh_abc, tmp_dh_ab, tmp_dh_cb);\n cross(tmp_dh_bcd, tmp_dh_bc, tmp_dh_dc);\n const _angle = angle(tmp_dh_abc, tmp_dh_bcd);\n cross(tmp_dh_cross, tmp_dh_abc, tmp_dh_bcd);\n return dot(tmp_dh_cb, tmp_dh_cross) > 0 ? _angle : -_angle;\n }\n Vec3.dihedralAngle = dihedralAngle;\n /**\n * @param inclination in radians [0, PI]\n * @param azimuth in radians [0, 2 * PI]\n * @param radius [0, +Inf]\n */\n function directionFromSpherical(out, inclination, azimuth, radius) {\n return Vec3.set(out, radius * Math.cos(azimuth) * Math.sin(inclination), radius * Math.sin(azimuth) * Math.sin(inclination), radius * Math.cos(inclination));\n }\n Vec3.directionFromSpherical = directionFromSpherical;\n /**\n * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)\n */\n function exactEquals(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2];\n }\n Vec3.exactEquals = exactEquals;\n /**\n * Returns whether or not the vectors have approximately the same elements in the same position.\n */\n function equals(a, b) {\n const a0 = a[0], a1 = a[1], a2 = a[2];\n const b0 = b[0], b1 = b[1], b2 = b[2];\n return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&\n Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) &&\n Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)));\n }\n Vec3.equals = equals;\n const rotTemp = zero();\n function makeRotation(mat, a, b) {\n const by = angle(a, b);\n if (Math.abs(by) < 0.0001)\n return Mat4.setIdentity(mat);\n if (Math.abs(by - Math.PI) < EPSILON) {\n // here, axis can be [0,0,0] but the rotation is a simple flip\n return Mat4.fromScaling(mat, Vec3.negUnit);\n }\n const axis = cross(rotTemp, a, b);\n return Mat4.fromRotation(mat, by, axis);\n }\n Vec3.makeRotation = makeRotation;\n function isZero(v) {\n return v[0] === 0 && v[1] === 0 && v[2] === 0;\n }\n Vec3.isZero = isZero;\n /** Project `point` onto `vector` starting from `origin` */\n function projectPointOnVector(out, point, vector, origin) {\n sub(out, point, origin);\n const scalar = dot(vector, out) / squaredMagnitude(vector);\n return add(out, scale(out, vector, scalar), origin);\n }\n Vec3.projectPointOnVector = projectPointOnVector;\n const tmpProjectPlane = zero();\n /** Project `point` onto `plane` defined by `normal` starting from `origin` */\n function projectPointOnPlane(out, point, normal, origin) {\n normalize(tmpProjectPlane, normal);\n sub(out, point, origin);\n return sub(out, point, scale(tmpProjectPlane, tmpProjectPlane, dot(out, tmpProjectPlane)));\n }\n Vec3.projectPointOnPlane = projectPointOnPlane;\n function projectOnVector(out, p, vector) {\n const scalar = dot(vector, p) / squaredMagnitude(vector);\n return scale(out, vector, scalar);\n }\n Vec3.projectOnVector = projectOnVector;\n const tmpProject = zero();\n function projectOnPlane(out, p, normal) {\n projectOnVector(tmpProject, p, normal);\n return sub(out, p, tmpProject);\n }\n Vec3.projectOnPlane = projectOnPlane;\n /** Get a vector that is similar to `b` but orthogonal to `a` */\n function orthogonalize(out, a, b) {\n return normalize(out, cross(out, cross(out, a, b), a));\n }\n Vec3.orthogonalize = orthogonalize;\n /**\n * Get a vector like `a` that point into the same general direction as `b`,\n * i.e. where the dot product is > 0\n */\n function matchDirection(out, a, b) {\n if (dot(a, b) > 0)\n copy(out, a);\n else\n negate(out, copy(out, a));\n return out;\n }\n Vec3.matchDirection = matchDirection;\n const triangleNormalTmpAB = zero();\n const triangleNormalTmpAC = zero();\n /** Calculate normal for the triangle defined by `a`, `b` and `c` */\n function triangleNormal(out, a, b, c) {\n sub(triangleNormalTmpAB, b, a);\n sub(triangleNormalTmpAC, c, a);\n return normalize(out, cross(out, triangleNormalTmpAB, triangleNormalTmpAC));\n }\n Vec3.triangleNormal = triangleNormal;\n function toString(a, precision) {\n return `[${a[0].toPrecision(precision)} ${a[1].toPrecision(precision)} ${a[2].toPrecision(precision)}]`;\n }\n Vec3.toString = toString;\n Vec3.origin = create(0, 0, 0);\n Vec3.unit = create(1, 1, 1);\n Vec3.negUnit = create(-1, -1, -1);\n Vec3.unitX = create(1, 0, 0);\n Vec3.unitY = create(0, 1, 0);\n Vec3.unitZ = create(0, 0, 1);\n Vec3.negUnitX = create(-1, 0, 0);\n Vec3.negUnitY = create(0, -1, 0);\n Vec3.negUnitZ = create(0, 0, -1);\n})(Vec3 || (Vec3 = {}));\nexport { Vec3 };\n","/**\n * Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author Alexander Rose \n */\nexport const halfPI = Math.PI / 2;\nexport const PiDiv180 = Math.PI / 180;\nexport function degToRad(deg) {\n return deg * PiDiv180; // deg * Math.PI / 180\n}\nexport function radToDeg(rad) {\n return rad / PiDiv180; // rad * 180 / Math.PI\n}\nexport function isPowerOfTwo(x) {\n return (x !== 0) && (x & (x - 1)) === 0;\n}\n/** return the value that has the largest absolute value */\nexport function absMax(...values) {\n let max = 0;\n let absMax = 0;\n for (let i = 0, il = values.length; i < il; ++i) {\n const value = values[i];\n const abs = Math.abs(value);\n if (abs > absMax) {\n max = value;\n absMax = abs;\n }\n }\n return max;\n}\n/** Length of an arc with angle in radians */\nexport function arcLength(angle, radius) {\n return angle * radius;\n}\n/** Create an outward spiral of given `radius` on a 2d grid */\nexport function spiral2d(radius) {\n let x = 0;\n let y = 0;\n const delta = [0, -1];\n const size = radius * 2 + 1;\n const halfSize = size / 2;\n const out = [];\n for (let i = Math.pow(size, 2); i > 0; --i) {\n if ((-halfSize < x && x <= halfSize) && (-halfSize < y && y <= halfSize)) {\n out.push([x, y]);\n }\n if (x === y || (x < 0 && x === -y) || (x > 0 && x === 1 - y)) {\n [delta[0], delta[1]] = [-delta[1], delta[0]]; // change direction\n }\n x += delta[0];\n y += delta[1];\n }\n return out;\n}\n","/**\n * Copyright (c) 2017-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n * @author Alexander Rose \n */\n/*\n * This code has been modified from https://github.com/toji/gl-matrix/,\n * copyright (c) 2015, Brandon Jones, Colin MacKenzie IV.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n */\nimport { EPSILON, equalEps } from './common';\nimport { Vec3 } from './vec3';\nimport { degToRad } from '../../misc';\nfunction Mat4() {\n return Mat4.zero();\n}\n/**\n * Stores a 4x4 matrix in a column major (j * 4 + i indexing) format.\n */\n(function (Mat4) {\n function zero() {\n // force double backing array by 0.1.\n const ret = [0.1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n ret[0] = 0.0;\n return ret;\n }\n Mat4.zero = zero;\n function identity() {\n const out = zero();\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = 1;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n }\n Mat4.identity = identity;\n function setIdentity(mat) {\n mat[0] = 1;\n mat[1] = 0;\n mat[2] = 0;\n mat[3] = 0;\n mat[4] = 0;\n mat[5] = 1;\n mat[6] = 0;\n mat[7] = 0;\n mat[8] = 0;\n mat[9] = 0;\n mat[10] = 1;\n mat[11] = 0;\n mat[12] = 0;\n mat[13] = 0;\n mat[14] = 0;\n mat[15] = 1;\n return mat;\n }\n Mat4.setIdentity = setIdentity;\n function setZero(mat) {\n for (let i = 0; i < 16; i++)\n mat[i] = 0;\n return mat;\n }\n Mat4.setZero = setZero;\n function ofRows(rows) {\n const out = zero();\n for (let i = 0; i < 4; i++) {\n const r = rows[i];\n for (let j = 0; j < 4; j++) {\n out[4 * j + i] = r[j];\n }\n }\n return out;\n }\n Mat4.ofRows = ofRows;\n const _id = identity();\n function isIdentity(m, eps) {\n return areEqual(m, _id, typeof eps === 'undefined' ? EPSILON : eps);\n }\n Mat4.isIdentity = isIdentity;\n function hasNaN(m) {\n for (let i = 0; i < 16; i++)\n if (isNaN(m[i]))\n return true;\n return false;\n }\n Mat4.hasNaN = hasNaN;\n function areEqual(a, b, eps) {\n for (let i = 0; i < 16; i++) {\n if (Math.abs(a[i] - b[i]) > eps)\n return false;\n }\n return true;\n }\n Mat4.areEqual = areEqual;\n function setValue(a, i, j, value) {\n a[4 * j + i] = value;\n }\n Mat4.setValue = setValue;\n function getValue(a, i, j) {\n return a[4 * j + i];\n }\n Mat4.getValue = getValue;\n function toArray(a, out, offset) {\n out[offset + 0] = a[0];\n out[offset + 1] = a[1];\n out[offset + 2] = a[2];\n out[offset + 3] = a[3];\n out[offset + 4] = a[4];\n out[offset + 5] = a[5];\n out[offset + 6] = a[6];\n out[offset + 7] = a[7];\n out[offset + 8] = a[8];\n out[offset + 9] = a[9];\n out[offset + 10] = a[10];\n out[offset + 11] = a[11];\n out[offset + 12] = a[12];\n out[offset + 13] = a[13];\n out[offset + 14] = a[14];\n out[offset + 15] = a[15];\n return out;\n }\n Mat4.toArray = toArray;\n function fromArray(a, array, offset) {\n a[0] = array[offset + 0];\n a[1] = array[offset + 1];\n a[2] = array[offset + 2];\n a[3] = array[offset + 3];\n a[4] = array[offset + 4];\n a[5] = array[offset + 5];\n a[6] = array[offset + 6];\n a[7] = array[offset + 7];\n a[8] = array[offset + 8];\n a[9] = array[offset + 9];\n a[10] = array[offset + 10];\n a[11] = array[offset + 11];\n a[12] = array[offset + 12];\n a[13] = array[offset + 13];\n a[14] = array[offset + 14];\n a[15] = array[offset + 15];\n return a;\n }\n Mat4.fromArray = fromArray;\n function fromBasis(a, x, y, z) {\n setZero(a);\n setValue(a, 0, 0, x[0]);\n setValue(a, 1, 0, x[1]);\n setValue(a, 2, 0, x[2]);\n setValue(a, 0, 1, y[0]);\n setValue(a, 1, 1, y[1]);\n setValue(a, 2, 1, y[2]);\n setValue(a, 0, 2, z[0]);\n setValue(a, 1, 2, z[1]);\n setValue(a, 2, 2, z[2]);\n setValue(a, 3, 3, 1);\n return a;\n }\n Mat4.fromBasis = fromBasis;\n function copy(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[8] = a[8];\n out[9] = a[9];\n out[10] = a[10];\n out[11] = a[11];\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n return out;\n }\n Mat4.copy = copy;\n function clone(a) {\n return copy(zero(), a);\n }\n Mat4.clone = clone;\n /**\n * Returns the translation vector component of a transformation matrix.\n */\n function getTranslation(out, mat) {\n out[0] = mat[12];\n out[1] = mat[13];\n out[2] = mat[14];\n return out;\n }\n Mat4.getTranslation = getTranslation;\n /**\n * Returns the scaling factor component of a transformation matrix.\n */\n function getScaling(out, mat) {\n const m11 = mat[0];\n const m12 = mat[1];\n const m13 = mat[2];\n const m21 = mat[4];\n const m22 = mat[5];\n const m23 = mat[6];\n const m31 = mat[8];\n const m32 = mat[9];\n const m33 = mat[10];\n out[0] = Math.sqrt(m11 * m11 + m12 * m12 + m13 * m13);\n out[1] = Math.sqrt(m21 * m21 + m22 * m22 + m23 * m23);\n out[2] = Math.sqrt(m31 * m31 + m32 * m32 + m33 * m33);\n return out;\n }\n Mat4.getScaling = getScaling;\n /**\n * Returns a quaternion representing the rotational component of a transformation matrix.\n */\n function getRotation(out, mat) {\n // Algorithm taken from http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm\n const trace = mat[0] + mat[5] + mat[10];\n let S = 0;\n if (trace > 0) {\n S = Math.sqrt(trace + 1.0) * 2;\n out[3] = 0.25 * S;\n out[0] = (mat[6] - mat[9]) / S;\n out[1] = (mat[8] - mat[2]) / S;\n out[2] = (mat[1] - mat[4]) / S;\n }\n else if ((mat[0] > mat[5]) && (mat[0] > mat[10])) {\n S = Math.sqrt(1.0 + mat[0] - mat[5] - mat[10]) * 2;\n out[3] = (mat[6] - mat[9]) / S;\n out[0] = 0.25 * S;\n out[1] = (mat[1] + mat[4]) / S;\n out[2] = (mat[8] + mat[2]) / S;\n }\n else if (mat[5] > mat[10]) {\n S = Math.sqrt(1.0 + mat[5] - mat[0] - mat[10]) * 2;\n out[3] = (mat[8] - mat[2]) / S;\n out[0] = (mat[1] + mat[4]) / S;\n out[1] = 0.25 * S;\n out[2] = (mat[6] + mat[9]) / S;\n }\n else {\n S = Math.sqrt(1.0 + mat[10] - mat[0] - mat[5]) * 2;\n out[3] = (mat[1] - mat[4]) / S;\n out[0] = (mat[8] + mat[2]) / S;\n out[1] = (mat[6] + mat[9]) / S;\n out[2] = 0.25 * S;\n }\n return out;\n }\n Mat4.getRotation = getRotation;\n function extractRotation(out, mat) {\n const scaleX = 1 / Math.sqrt(mat[0] * mat[0] + mat[1] * mat[1] + mat[2] * mat[2]);\n const scaleY = 1 / Math.sqrt(mat[4] * mat[4] + mat[5] * mat[5] + mat[6] * mat[6]);\n const scaleZ = 1 / Math.sqrt(mat[8] * mat[8] + mat[9] * mat[9] + mat[10] * mat[10]);\n out[0] = mat[0] * scaleX;\n out[1] = mat[1] * scaleX;\n out[2] = mat[2] * scaleX;\n out[3] = 0;\n out[4] = mat[4] * scaleY;\n out[5] = mat[5] * scaleY;\n out[6] = mat[6] * scaleY;\n out[7] = 0;\n out[8] = mat[8] * scaleZ;\n out[9] = mat[9] * scaleZ;\n out[10] = mat[10] * scaleZ;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n }\n Mat4.extractRotation = extractRotation;\n function transpose(out, a) {\n // If we are transposing ourselves we can skip a few steps but have to cache some values\n if (out === a) {\n const a01 = a[1], a02 = a[2], a03 = a[3];\n const a12 = a[6], a13 = a[7];\n const a23 = a[11];\n out[1] = a[4];\n out[2] = a[8];\n out[3] = a[12];\n out[4] = a01;\n out[6] = a[9];\n out[7] = a[13];\n out[8] = a02;\n out[9] = a12;\n out[11] = a[14];\n out[12] = a03;\n out[13] = a13;\n out[14] = a23;\n }\n else {\n out[0] = a[0];\n out[1] = a[4];\n out[2] = a[8];\n out[3] = a[12];\n out[4] = a[1];\n out[5] = a[5];\n out[6] = a[9];\n out[7] = a[13];\n out[8] = a[2];\n out[9] = a[6];\n out[10] = a[10];\n out[11] = a[14];\n out[12] = a[3];\n out[13] = a[7];\n out[14] = a[11];\n out[15] = a[15];\n }\n return out;\n }\n Mat4.transpose = transpose;\n function tryInvert(out, a) {\n const a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], b00 = a00 * a11 - a01 * a10, b01 = a00 * a12 - a02 * a10, b02 = a00 * a13 - a03 * a10, b03 = a01 * a12 - a02 * a11, b04 = a01 * a13 - a03 * a11, b05 = a02 * a13 - a03 * a12, b06 = a20 * a31 - a21 * a30, b07 = a20 * a32 - a22 * a30, b08 = a20 * a33 - a23 * a30, b09 = a21 * a32 - a22 * a31, b10 = a21 * a33 - a23 * a31, b11 = a22 * a33 - a23 * a32;\n // Calculate the determinant\n let det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n if (!det) {\n return false;\n }\n det = 1.0 / det;\n out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;\n out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;\n out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;\n out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;\n out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;\n out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;\n out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;\n out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;\n out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;\n out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;\n out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;\n out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;\n out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;\n out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;\n out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;\n out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;\n return true;\n }\n Mat4.tryInvert = tryInvert;\n function invert(out, a) {\n if (!tryInvert(out, a)) {\n console.warn('non-invertible matrix.', a);\n }\n return out;\n }\n Mat4.invert = invert;\n function mul(out, a, b) {\n const a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];\n // Cache only the current line of the second matrix\n let b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];\n out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[4];\n b1 = b[5];\n b2 = b[6];\n b3 = b[7];\n out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[8];\n b1 = b[9];\n b2 = b[10];\n b3 = b[11];\n out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[12];\n b1 = b[13];\n b2 = b[14];\n b3 = b[15];\n out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n return out;\n }\n Mat4.mul = mul;\n /**\n * Like `mul` but with offsets into arrays\n */\n function mulOffset(out, a, b, oOut, oA, oB) {\n const a00 = a[0 + oA], a01 = a[1 + oA], a02 = a[2 + oA], a03 = a[3 + oA], a10 = a[4 + oA], a11 = a[5 + oA], a12 = a[6 + oA], a13 = a[7 + oA], a20 = a[8 + oA], a21 = a[9 + oA], a22 = a[10 + oA], a23 = a[11 + oA], a30 = a[12 + oA], a31 = a[13 + oA], a32 = a[14 + oA], a33 = a[15 + oA];\n // Cache only the current line of the second matrix\n let b0 = b[0 + oB], b1 = b[1 + oB], b2 = b[2 + oB], b3 = b[3 + oB];\n out[0 + oOut] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[1 + oOut] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[2 + oOut] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[3 + oOut] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[4 + oB];\n b1 = b[5 + oB];\n b2 = b[6 + oB];\n b3 = b[7 + oB];\n out[4 + oOut] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[5 + oOut] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[6 + oOut] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[7 + oOut] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[8 + oB];\n b1 = b[9 + oB];\n b2 = b[10 + oB];\n b3 = b[11 + oB];\n out[8 + oOut] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[9 + oOut] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[10 + oOut] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[11 + oOut] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n b0 = b[12 + oB];\n b1 = b[13 + oB];\n b2 = b[14 + oB];\n b3 = b[15 + oB];\n out[12 + oOut] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;\n out[13 + oOut] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;\n out[14 + oOut] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;\n out[15 + oOut] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;\n return out;\n }\n Mat4.mulOffset = mulOffset;\n function mul3(out, a, b, c) {\n return mul(out, mul(out, a, b), c);\n }\n Mat4.mul3 = mul3;\n /** Translate a Mat4 by the given Vec3 */\n function translate(out, a, v) {\n const x = v[0], y = v[1], z = v[2];\n let a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23;\n if (a === out) {\n out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];\n out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];\n out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];\n out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];\n }\n else {\n a00 = a[0];\n a01 = a[1];\n a02 = a[2];\n a03 = a[3];\n a10 = a[4];\n a11 = a[5];\n a12 = a[6];\n a13 = a[7];\n a20 = a[8];\n a21 = a[9];\n a22 = a[10];\n a23 = a[11];\n out[0] = a00;\n out[1] = a01;\n out[2] = a02;\n out[3] = a03;\n out[4] = a10;\n out[5] = a11;\n out[6] = a12;\n out[7] = a13;\n out[8] = a20;\n out[9] = a21;\n out[10] = a22;\n out[11] = a23;\n out[12] = a00 * x + a10 * y + a20 * z + a[12];\n out[13] = a01 * x + a11 * y + a21 * z + a[13];\n out[14] = a02 * x + a12 * y + a22 * z + a[14];\n out[15] = a03 * x + a13 * y + a23 * z + a[15];\n }\n return out;\n }\n Mat4.translate = translate;\n function fromTranslation(out, v) {\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = 1;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = 1;\n out[11] = 0;\n out[12] = v[0];\n out[13] = v[1];\n out[14] = v[2];\n out[15] = 1;\n return out;\n }\n Mat4.fromTranslation = fromTranslation;\n function setTranslation(out, v) {\n out[12] = v[0];\n out[13] = v[1];\n out[14] = v[2];\n return out;\n }\n Mat4.setTranslation = setTranslation;\n /**\n * Sets the specified quaternion with values corresponding to the given\n * axes. Each axis is a vec3 and is expected to be unit length and\n * perpendicular to all other specified axes.\n */\n function setAxes(out, view, right, up) {\n out[0] = right[0];\n out[4] = right[1];\n out[8] = right[2];\n out[1] = up[0];\n out[5] = up[1];\n out[9] = up[2];\n out[2] = view[0];\n out[6] = view[1];\n out[10] = view[2];\n return out;\n }\n Mat4.setAxes = setAxes;\n function rotate(out, a, rad, axis) {\n let x = axis[0], y = axis[1], z = axis[2];\n let len = Math.sqrt(x * x + y * y + z * z);\n if (Math.abs(len) < EPSILON) {\n return identity();\n }\n len = 1 / len;\n x *= len;\n y *= len;\n z *= len;\n const s = Math.sin(rad);\n const c = Math.cos(rad);\n const t = 1 - c;\n const a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3];\n const a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7];\n const a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11];\n // Construct the elements of the rotation matrix\n const b00 = x * x * t + c, b01 = y * x * t + z * s, b02 = z * x * t - y * s;\n const b10 = x * y * t - z * s, b11 = y * y * t + c, b12 = z * y * t + x * s;\n const b20 = x * z * t + y * s, b21 = y * z * t - x * s, b22 = z * z * t + c;\n // Perform rotation-specific matrix multiplication\n out[0] = a00 * b00 + a10 * b01 + a20 * b02;\n out[1] = a01 * b00 + a11 * b01 + a21 * b02;\n out[2] = a02 * b00 + a12 * b01 + a22 * b02;\n out[3] = a03 * b00 + a13 * b01 + a23 * b02;\n out[4] = a00 * b10 + a10 * b11 + a20 * b12;\n out[5] = a01 * b10 + a11 * b11 + a21 * b12;\n out[6] = a02 * b10 + a12 * b11 + a22 * b12;\n out[7] = a03 * b10 + a13 * b11 + a23 * b12;\n out[8] = a00 * b20 + a10 * b21 + a20 * b22;\n out[9] = a01 * b20 + a11 * b21 + a21 * b22;\n out[10] = a02 * b20 + a12 * b21 + a22 * b22;\n out[11] = a03 * b20 + a13 * b21 + a23 * b22;\n if (a !== out) { // If the source and destination differ, copy the unchanged last row\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n }\n return out;\n }\n Mat4.rotate = rotate;\n function fromRotation(out, rad, axis) {\n let x = axis[0], y = axis[1], z = axis[2];\n let len = Math.sqrt(x * x + y * y + z * z);\n if (Math.abs(len) < EPSILON) {\n return setIdentity(out);\n }\n len = 1 / len;\n x *= len;\n y *= len;\n z *= len;\n const s = Math.sin(rad);\n const c = Math.cos(rad);\n const t = 1 - c;\n // Perform rotation-specific matrix multiplication\n out[0] = x * x * t + c;\n out[1] = y * x * t + z * s;\n out[2] = z * x * t - y * s;\n out[3] = 0;\n out[4] = x * y * t - z * s;\n out[5] = y * y * t + c;\n out[6] = z * y * t + x * s;\n out[7] = 0;\n out[8] = x * z * t + y * s;\n out[9] = y * z * t - x * s;\n out[10] = z * z * t + c;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n }\n Mat4.fromRotation = fromRotation;\n function scale(out, a, v) {\n const x = v[0], y = v[1], z = v[2];\n out[0] = a[0] * x;\n out[1] = a[1] * x;\n out[2] = a[2] * x;\n out[3] = a[3] * x;\n out[4] = a[4] * y;\n out[5] = a[5] * y;\n out[6] = a[6] * y;\n out[7] = a[7] * y;\n out[8] = a[8] * z;\n out[9] = a[9] * z;\n out[10] = a[10] * z;\n out[11] = a[11] * z;\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n return out;\n }\n Mat4.scale = scale;\n function scaleUniformly(out, a, scale) {\n out[0] = a[0] * scale;\n out[1] = a[1] * scale;\n out[2] = a[2] * scale;\n out[3] = a[3] * scale;\n out[4] = a[4] * scale;\n out[5] = a[5] * scale;\n out[6] = a[6] * scale;\n out[7] = a[7] * scale;\n out[8] = a[8] * scale;\n out[9] = a[9] * scale;\n out[10] = a[10] * scale;\n out[11] = a[11] * scale;\n out[12] = a[12];\n out[13] = a[13];\n out[14] = a[14];\n out[15] = a[15];\n return out;\n }\n Mat4.scaleUniformly = scaleUniformly;\n function fromScaling(out, v) {\n out[0] = v[0];\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = v[1];\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = v[2];\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n }\n Mat4.fromScaling = fromScaling;\n function fromUniformScaling(out, scale) {\n out[0] = scale;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = scale;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = scale;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n }\n Mat4.fromUniformScaling = fromUniformScaling;\n /**\n * Copies the mat3 into upper-left 3x3 values.\n */\n function fromMat3(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[4] = a[3];\n out[5] = a[4];\n out[6] = a[5];\n out[8] = a[6];\n out[9] = a[7];\n out[10] = a[8];\n return out;\n }\n Mat4.fromMat3 = fromMat3;\n function compose(out, position, quaternion, scale) {\n const [x, y, z, w] = quaternion;\n const x2 = x + x, y2 = y + y, z2 = z + z;\n const xx = x * x2, xy = x * y2, xz = x * z2;\n const yy = y * y2, yz = y * z2, zz = z * z2;\n const wx = w * x2, wy = w * y2, wz = w * z2;\n const [sx, sy, sz] = scale;\n out[0] = (1 - (yy + zz)) * sx;\n out[1] = (xy + wz) * sx;\n out[2] = (xz - wy) * sx;\n out[3] = 0;\n out[4] = (xy - wz) * sy;\n out[5] = (1 - (xx + zz)) * sy;\n out[6] = (yz + wx) * sy;\n out[7] = 0;\n out[8] = (xz + wy) * sz;\n out[9] = (yz - wx) * sz;\n out[10] = (1 - (xx + yy)) * sz;\n out[11] = 0;\n out[12] = position[0];\n out[13] = position[1];\n out[14] = position[2];\n out[15] = 1;\n return out;\n }\n Mat4.compose = compose;\n const _v3 = [0, 0, 0];\n const _m4 = zero();\n function decompose(m, position, quaternion, scale) {\n let sx = Vec3.magnitude(Vec3.set(_v3, m[0], m[1], m[2]));\n const sy = Vec3.magnitude(Vec3.set(_v3, m[4], m[5], m[6]));\n const sz = Vec3.magnitude(Vec3.set(_v3, m[8], m[9], m[10]));\n // if determine is negative, we need to invert one scale\n const det = determinant(m);\n if (det < 0)\n sx = -sx;\n position[0] = m[12];\n position[1] = m[13];\n position[2] = m[14];\n // scale the rotation part\n copy(_m4, m);\n const invSX = 1 / sx;\n const invSY = 1 / sy;\n const invSZ = 1 / sz;\n _m4[0] *= invSX;\n _m4[1] *= invSX;\n _m4[2] *= invSX;\n _m4[4] *= invSY;\n _m4[5] *= invSY;\n _m4[6] *= invSY;\n _m4[8] *= invSZ;\n _m4[9] *= invSZ;\n _m4[10] *= invSZ;\n getRotation(quaternion, _m4);\n scale[0] = sx;\n scale[1] = sy;\n scale[2] = sz;\n return m;\n }\n Mat4.decompose = decompose;\n function makeTable(m) {\n let ret = '';\n for (let i = 0; i < 4; i++) {\n for (let j = 0; j < 4; j++) {\n ret += m[4 * j + i].toString();\n if (j < 3)\n ret += ' ';\n }\n if (i < 3)\n ret += '\\n';\n }\n return ret;\n }\n Mat4.makeTable = makeTable;\n function determinant(a) {\n const a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15], b00 = a00 * a11 - a01 * a10, b01 = a00 * a12 - a02 * a10, b02 = a00 * a13 - a03 * a10, b03 = a01 * a12 - a02 * a11, b04 = a01 * a13 - a03 * a11, b05 = a02 * a13 - a03 * a12, b06 = a20 * a31 - a21 * a30, b07 = a20 * a32 - a22 * a30, b08 = a20 * a33 - a23 * a30, b09 = a21 * a32 - a22 * a31, b10 = a21 * a33 - a23 * a31, b11 = a22 * a33 - a23 * a32;\n // Calculate the determinant\n return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;\n }\n Mat4.determinant = determinant;\n /**\n * Check if the matrix has the form\n * [ Rotation Translation ]\n * [ 0 1 ]\n *\n * Allows for improper rotations\n */\n function isRotationAndTranslation(a, eps) {\n return _isRotationAndTranslation(a, typeof eps !== 'undefined' ? eps : EPSILON);\n }\n Mat4.isRotationAndTranslation = isRotationAndTranslation;\n function _isRotationAndTranslation(a, eps) {\n const a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3], a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7], a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11], a33 = a[15];\n if (!equalEps(a33, 1, eps) || !equalEps(a03, 0, eps) || !equalEps(a13, 0, eps) || !equalEps(a23, 0, eps)) {\n return false;\n }\n // use `abs` to allow for improper rotations\n const det3x3 = Math.abs(a00 * (a11 * a22 - a12 * a21) - a01 * (a10 * a22 - a12 * a20) + a02 * (a10 * a21 - a11 * a20));\n if (!equalEps(det3x3, 1, eps)) {\n return false;\n }\n return true;\n }\n /**\n * Check if the matrix has only translation and uniform scaling\n * [ S 0 0 X ]\n * [ 0 S 0 Y ]\n * [ 0 0 S Z ]\n * [ 0 0 0 1 ]\n */\n function isTranslationAndUniformScaling(a, eps) {\n return _isTranslationAndUniformScaling(a, typeof eps !== 'undefined' ? eps : EPSILON);\n }\n Mat4.isTranslationAndUniformScaling = isTranslationAndUniformScaling;\n function _isTranslationAndUniformScaling(a, eps) {\n const a00 = a[0];\n return (\n // 0 base scaling\n equalEps(a[1], 0, eps) &&\n equalEps(a[2], 0, eps) &&\n equalEps(a[3], 0, eps) &&\n equalEps(a[4], 0, eps) &&\n equalEps(a[5], a00, eps) &&\n equalEps(a[6], 0, eps) &&\n equalEps(a[7], 0, eps) &&\n equalEps(a[8], 0, eps) &&\n equalEps(a[9], 0, eps) &&\n equalEps(a[10], a00, eps) &&\n equalEps(a[11], 0, eps) &&\n // 12, 13, 14 translation can be anything\n equalEps(a[15], 1, eps));\n }\n function fromQuat(out, q) {\n const x = q[0], y = q[1], z = q[2], w = q[3];\n const x2 = x + x;\n const y2 = y + y;\n const z2 = z + z;\n const xx = x * x2;\n const yx = y * x2;\n const yy = y * y2;\n const zx = z * x2;\n const zy = z * y2;\n const zz = z * z2;\n const wx = w * x2;\n const wy = w * y2;\n const wz = w * z2;\n out[0] = 1 - yy - zz;\n out[1] = yx + wz;\n out[2] = zx - wy;\n out[3] = 0;\n out[4] = yx - wz;\n out[5] = 1 - xx - zz;\n out[6] = zy + wx;\n out[7] = 0;\n out[8] = zx + wy;\n out[9] = zy - wx;\n out[10] = 1 - xx - yy;\n out[11] = 0;\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n }\n Mat4.fromQuat = fromQuat;\n function fromEuler(out, euler, order) {\n const x = euler[0], y = euler[1], z = euler[2];\n const a = Math.cos(x), b = Math.sin(x);\n const c = Math.cos(y), d = Math.sin(y);\n const e = Math.cos(z), f = Math.sin(z);\n if (order === 'XYZ') {\n const ae = a * e, af = a * f, be = b * e, bf = b * f;\n out[0] = c * e;\n out[4] = -c * f;\n out[8] = d;\n out[1] = af + be * d;\n out[5] = ae - bf * d;\n out[9] = -b * c;\n out[2] = bf - ae * d;\n out[6] = be + af * d;\n out[10] = a * c;\n }\n else if (order === 'YXZ') {\n const ce = c * e, cf = c * f, de = d * e, df = d * f;\n out[0] = ce + df * b;\n out[4] = de * b - cf;\n out[8] = a * d;\n out[1] = a * f;\n out[5] = a * e;\n out[9] = -b;\n out[2] = cf * b - de;\n out[6] = df + ce * b;\n out[10] = a * c;\n }\n else if (order === 'ZXY') {\n const ce = c * e, cf = c * f, de = d * e, df = d * f;\n out[0] = ce - df * b;\n out[4] = -a * f;\n out[8] = de + cf * b;\n out[1] = cf + de * b;\n out[5] = a * e;\n out[9] = df - ce * b;\n out[2] = -a * d;\n out[6] = b;\n out[10] = a * c;\n }\n else if (order === 'ZYX') {\n const ae = a * e, af = a * f, be = b * e, bf = b * f;\n out[0] = c * e;\n out[4] = be * d - af;\n out[8] = ae * d + bf;\n out[1] = c * f;\n out[5] = bf * d + ae;\n out[9] = af * d - be;\n out[2] = -d;\n out[6] = b * c;\n out[10] = a * c;\n }\n else if (order === 'YZX') {\n const ac = a * c, ad = a * d, bc = b * c, bd = b * d;\n out[0] = c * e;\n out[4] = bd - ac * f;\n out[8] = bc * f + ad;\n out[1] = f;\n out[5] = a * e;\n out[9] = -b * e;\n out[2] = -d * e;\n out[6] = ad * f + bc;\n out[10] = ac - bd * f;\n }\n else if (order === 'XZY') {\n const ac = a * c, ad = a * d, bc = b * c, bd = b * d;\n out[0] = c * e;\n out[4] = -f;\n out[8] = d * e;\n out[1] = ac * f + bd;\n out[5] = a * e;\n out[9] = ad * f - bc;\n out[2] = bc * f - ad;\n out[6] = b * e;\n out[10] = bd * f + ac;\n }\n // bottom row\n out[3] = 0;\n out[7] = 0;\n out[11] = 0;\n // last column\n out[12] = 0;\n out[13] = 0;\n out[14] = 0;\n out[15] = 1;\n return out;\n }\n Mat4.fromEuler = fromEuler;\n /**\n * Generates a perspective projection (frustum) matrix with the given bounds\n */\n function perspective(out, left, right, top, bottom, near, far) {\n const x = 2 * near / (right - left);\n const y = 2 * near / (top - bottom);\n const a = (right + left) / (right - left);\n const b = (top + bottom) / (top - bottom);\n const c = -(far + near) / (far - near);\n const d = -2 * far * near / (far - near);\n out[0] = x;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = y;\n out[6] = 0;\n out[7] = 0;\n out[8] = a;\n out[9] = b;\n out[10] = c;\n out[11] = -1;\n out[12] = 0;\n out[13] = 0;\n out[14] = d;\n out[15] = 0;\n return out;\n }\n Mat4.perspective = perspective;\n /**\n * Generates a orthogonal projection matrix with the given bounds\n */\n function ortho(out, left, right, top, bottom, near, far) {\n const w = 1.0 / (right - left);\n const h = 1.0 / (top - bottom);\n const p = 1.0 / (far - near);\n const x = (right + left) * w;\n const y = (top + bottom) * h;\n const z = (far + near) * p;\n out[0] = 2 * w;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 0;\n out[5] = 2 * h;\n out[6] = 0;\n out[7] = 0;\n out[8] = 0;\n out[9] = 0;\n out[10] = -2 * p;\n out[11] = 0;\n out[12] = -x;\n out[13] = -y;\n out[14] = -z;\n out[15] = 1;\n return out;\n }\n Mat4.ortho = ortho;\n /**\n * Generates a look-at matrix with the given eye position, focal point, and up axis\n */\n function lookAt(out, eye, center, up) {\n let x0, x1, x2, y0, y1, y2, z0, z1, z2, len;\n const eyex = eye[0];\n const eyey = eye[1];\n const eyez = eye[2];\n const upx = up[0];\n const upy = up[1];\n const upz = up[2];\n const centerx = center[0];\n const centery = center[1];\n const centerz = center[2];\n if (Math.abs(eyex - centerx) < EPSILON &&\n Math.abs(eyey - centery) < EPSILON &&\n Math.abs(eyez - centerz) < EPSILON) {\n return setIdentity(out);\n }\n z0 = eyex - centerx;\n z1 = eyey - centery;\n z2 = eyez - centerz;\n len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);\n z0 *= len;\n z1 *= len;\n z2 *= len;\n x0 = upy * z2 - upz * z1;\n x1 = upz * z0 - upx * z2;\n x2 = upx * z1 - upy * z0;\n len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);\n if (!len) {\n x0 = 0;\n x1 = 0;\n x2 = 0;\n }\n else {\n len = 1 / len;\n x0 *= len;\n x1 *= len;\n x2 *= len;\n }\n y0 = z1 * x2 - z2 * x1;\n y1 = z2 * x0 - z0 * x2;\n y2 = z0 * x1 - z1 * x0;\n len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);\n if (!len) {\n y0 = 0;\n y1 = 0;\n y2 = 0;\n }\n else {\n len = 1 / len;\n y0 *= len;\n y1 *= len;\n y2 *= len;\n }\n out[0] = x0;\n out[1] = y0;\n out[2] = z0;\n out[3] = 0;\n out[4] = x1;\n out[5] = y1;\n out[6] = z1;\n out[7] = 0;\n out[8] = x2;\n out[9] = y2;\n out[10] = z2;\n out[11] = 0;\n out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez);\n out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez);\n out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez);\n out[15] = 1;\n return out;\n }\n Mat4.lookAt = lookAt;\n /**\n * Generates a matrix that makes something look at something else.\n */\n function targetTo(out, eye, target, up) {\n const eyex = eye[0], eyey = eye[1], eyez = eye[2], upx = up[0], upy = up[1], upz = up[2];\n let z0 = eyex - target[0], z1 = eyey - target[1], z2 = eyez - target[2];\n let len = z0 * z0 + z1 * z1 + z2 * z2;\n if (len > 0) {\n len = 1 / Math.sqrt(len);\n z0 *= len;\n z1 *= len;\n z2 *= len;\n }\n let x0 = upy * z2 - upz * z1, x1 = upz * z0 - upx * z2, x2 = upx * z1 - upy * z0;\n len = x0 * x0 + x1 * x1 + x2 * x2;\n if (len > 0) {\n len = 1 / Math.sqrt(len);\n x0 *= len;\n x1 *= len;\n x2 *= len;\n }\n out[0] = x0;\n out[1] = x1;\n out[2] = x2;\n out[3] = 0;\n out[4] = z1 * x2 - z2 * x1;\n out[5] = z2 * x0 - z0 * x2;\n out[6] = z0 * x1 - z1 * x0;\n out[7] = 0;\n out[8] = z0;\n out[9] = z1;\n out[10] = z2;\n out[11] = 0;\n out[12] = eyex;\n out[13] = eyey;\n out[14] = eyez;\n out[15] = 1;\n return out;\n }\n Mat4.targetTo = targetTo;\n /**\n * Perm is 0-indexed permutation\n */\n function fromPermutation(out, perm) {\n setZero(out);\n for (let i = 0; i < 4; i++) {\n const p = perm[i];\n setValue(out, i, p, 1);\n }\n return out;\n }\n Mat4.fromPermutation = fromPermutation;\n function getMaxScaleOnAxis(m) {\n const scaleXSq = m[0] * m[0] + m[1] * m[1] + m[2] * m[2];\n const scaleYSq = m[4] * m[4] + m[5] * m[5] + m[6] * m[6];\n const scaleZSq = m[8] * m[8] + m[9] * m[9] + m[10] * m[10];\n return Math.sqrt(Math.max(scaleXSq, scaleYSq, scaleZSq));\n }\n Mat4.getMaxScaleOnAxis = getMaxScaleOnAxis;\n const xAxis = [1, 0, 0];\n const yAxis = [0, 1, 0];\n const zAxis = [0, 0, 1];\n /** Rotation matrix for 90deg around x-axis */\n Mat4.rotX90 = fromRotation(zero(), degToRad(90), xAxis);\n /** Rotation matrix for 180deg around x-axis */\n Mat4.rotX180 = fromRotation(zero(), degToRad(180), xAxis);\n /** Rotation matrix for 90deg around y-axis */\n Mat4.rotY90 = fromRotation(zero(), degToRad(90), yAxis);\n /** Rotation matrix for 180deg around y-axis */\n Mat4.rotY180 = fromRotation(zero(), degToRad(180), yAxis);\n /** Rotation matrix for 270deg around y-axis */\n Mat4.rotY270 = fromRotation(zero(), degToRad(270), yAxis);\n /** Rotation matrix for 90deg around z-axis */\n Mat4.rotZ90 = fromRotation(zero(), degToRad(90), zAxis);\n /** Rotation matrix for 180deg around z-axis */\n Mat4.rotZ180 = fromRotation(zero(), degToRad(180), zAxis);\n /** Rotation matrix for 90deg around first x-axis and then y-axis */\n Mat4.rotXY90 = mul(zero(), Mat4.rotX90, Mat4.rotY90);\n /** Rotation matrix for 90deg around first z-axis and then y-axis */\n Mat4.rotZY90 = mul(zero(), Mat4.rotZ90, Mat4.rotY90);\n /** Rotation matrix for 90deg around first z-axis and then y-axis and then z-axis */\n Mat4.rotZYZ90 = mul(zero(), Mat4.rotZY90, Mat4.rotZ90);\n /** Rotation matrix for 90deg around first z-axis and then 180deg around x-axis */\n Mat4.rotZ90X180 = mul(zero(), Mat4.rotZ90, Mat4.rotX180);\n /** Rotation matrix for 90deg around first y-axis and then 180deg around z-axis */\n Mat4.rotY90Z180 = mul(zero(), Mat4.rotY90, Mat4.rotZ180);\n /** Identity matrix */\n Mat4.id = identity();\n})(Mat4 || (Mat4 = {}));\nexport { Mat4 };\n","/**\n * Copyright (c) 2017-2024 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n * @author Alexander Rose \n */\nimport { EPSILON } from './common';\nimport { Mat4 } from './mat4';\nimport { Vec3 } from './vec3';\nfunction Mat3() {\n return Mat3.zero();\n}\n(function (Mat3) {\n function zero() {\n // force double backing array by 0.1.\n const ret = [0.1, 0, 0, 0, 0, 0, 0, 0, 0];\n ret[0] = 0.0;\n return ret;\n }\n Mat3.zero = zero;\n function identity() {\n const out = zero();\n out[0] = 1;\n out[1] = 0;\n out[2] = 0;\n out[3] = 0;\n out[4] = 1;\n out[5] = 0;\n out[6] = 0;\n out[7] = 0;\n out[8] = 1;\n return out;\n }\n Mat3.identity = identity;\n function setIdentity(mat) {\n mat[0] = 1;\n mat[1] = 0;\n mat[2] = 0;\n mat[3] = 0;\n mat[4] = 1;\n mat[5] = 0;\n mat[6] = 0;\n mat[7] = 0;\n mat[8] = 1;\n return mat;\n }\n Mat3.setIdentity = setIdentity;\n function toArray(a, out, offset) {\n out[offset + 0] = a[0];\n out[offset + 1] = a[1];\n out[offset + 2] = a[2];\n out[offset + 3] = a[3];\n out[offset + 4] = a[4];\n out[offset + 5] = a[5];\n out[offset + 6] = a[6];\n out[offset + 7] = a[7];\n out[offset + 8] = a[8];\n return out;\n }\n Mat3.toArray = toArray;\n function fromArray(a, array, offset) {\n a[0] = array[offset + 0];\n a[1] = array[offset + 1];\n a[2] = array[offset + 2];\n a[3] = array[offset + 3];\n a[4] = array[offset + 4];\n a[5] = array[offset + 5];\n a[6] = array[offset + 6];\n a[7] = array[offset + 7];\n a[8] = array[offset + 8];\n return a;\n }\n Mat3.fromArray = fromArray;\n function fromColumns(out, left, middle, right) {\n out[0] = left[0];\n out[1] = left[1];\n out[2] = left[2];\n out[3] = middle[0];\n out[4] = middle[1];\n out[5] = middle[2];\n out[6] = right[0];\n out[7] = right[1];\n out[8] = right[2];\n return out;\n }\n Mat3.fromColumns = fromColumns;\n /**\n * Copies the upper-left 3x3 values into the given mat3.\n */\n function fromMat4(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[4];\n out[4] = a[5];\n out[5] = a[6];\n out[6] = a[8];\n out[7] = a[9];\n out[8] = a[10];\n return out;\n }\n Mat3.fromMat4 = fromMat4;\n const _m4 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n function fromEuler(out, euler, order) {\n Mat4.fromEuler(_m4, euler, order);\n return fromMat4(out, _m4);\n }\n Mat3.fromEuler = fromEuler;\n function create(a00, a01, a02, a10, a11, a12, a20, a21, a22) {\n const out = zero();\n out[0] = a00;\n out[1] = a01;\n out[2] = a02;\n out[3] = a10;\n out[4] = a11;\n out[5] = a12;\n out[6] = a20;\n out[7] = a21;\n out[8] = a22;\n return out;\n }\n Mat3.create = create;\n const _id = identity();\n function isIdentity(m, eps) {\n return areEqual(m, _id, typeof eps === 'undefined' ? EPSILON : eps);\n }\n Mat3.isIdentity = isIdentity;\n function hasNaN(m) {\n for (let i = 0; i < 9; i++)\n if (isNaN(m[i]))\n return true;\n return false;\n }\n Mat3.hasNaN = hasNaN;\n /**\n * Creates a new Mat3 initialized with values from an existing matrix\n */\n function clone(a) {\n return copy(zero(), a);\n }\n Mat3.clone = clone;\n function areEqual(a, b, eps) {\n for (let i = 0; i < 9; i++) {\n if (Math.abs(a[i] - b[i]) > eps)\n return false;\n }\n return true;\n }\n Mat3.areEqual = areEqual;\n function setValue(a, i, j, value) {\n a[3 * j + i] = value;\n }\n Mat3.setValue = setValue;\n function getValue(a, i, j) {\n return a[3 * j + i];\n }\n Mat3.getValue = getValue;\n /**\n * Copy the values from one Mat3 to another\n */\n function copy(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[6];\n out[7] = a[7];\n out[8] = a[8];\n return out;\n }\n Mat3.copy = copy;\n /**\n * Transpose the values of a Mat3\n */\n function transpose(out, a) {\n // If we are transposing ourselves we can skip a few steps but have to cache some values\n if (out === a) {\n const a01 = a[1], a02 = a[2], a12 = a[5];\n out[1] = a[3];\n out[2] = a[6];\n out[3] = a01;\n out[5] = a[7];\n out[6] = a02;\n out[7] = a12;\n }\n else {\n out[0] = a[0];\n out[1] = a[3];\n out[2] = a[6];\n out[3] = a[1];\n out[4] = a[4];\n out[5] = a[7];\n out[6] = a[2];\n out[7] = a[5];\n out[8] = a[8];\n }\n return out;\n }\n Mat3.transpose = transpose;\n /**\n * Inverts a Mat3\n */\n function invert(out, a) {\n const a00 = a[0], a01 = a[1], a02 = a[2];\n const a10 = a[3], a11 = a[4], a12 = a[5];\n const a20 = a[6], a21 = a[7], a22 = a[8];\n const b01 = a22 * a11 - a12 * a21;\n const b11 = -a22 * a10 + a12 * a20;\n const b21 = a21 * a10 - a11 * a20;\n // Calculate the determinant\n let det = a00 * b01 + a01 * b11 + a02 * b21;\n if (!det) {\n console.warn('non-invertible matrix.', a);\n return out;\n }\n det = 1.0 / det;\n out[0] = b01 * det;\n out[1] = (-a22 * a01 + a02 * a21) * det;\n out[2] = (a12 * a01 - a02 * a11) * det;\n out[3] = b11 * det;\n out[4] = (a22 * a00 - a02 * a20) * det;\n out[5] = (-a12 * a00 + a02 * a10) * det;\n out[6] = b21 * det;\n out[7] = (-a21 * a00 + a01 * a20) * det;\n out[8] = (a11 * a00 - a01 * a10) * det;\n return out;\n }\n Mat3.invert = invert;\n function symmtricFromUpper(out, a) {\n if (out === a) {\n out[3] = a[1];\n out[6] = a[2];\n out[7] = a[5];\n }\n else {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[1];\n out[4] = a[4];\n out[5] = a[5];\n out[6] = a[2];\n out[7] = a[5];\n out[8] = a[8];\n }\n return out;\n }\n Mat3.symmtricFromUpper = symmtricFromUpper;\n function symmtricFromLower(out, a) {\n if (out === a) {\n out[1] = a[3];\n out[2] = a[6];\n out[5] = a[7];\n }\n else {\n out[0] = a[0];\n out[1] = a[3];\n out[2] = a[6];\n out[3] = a[3];\n out[4] = a[4];\n out[5] = a[7];\n out[6] = a[6];\n out[7] = a[7];\n out[8] = a[8];\n }\n return out;\n }\n Mat3.symmtricFromLower = symmtricFromLower;\n function determinant(a) {\n const a00 = a[0], a01 = a[1], a02 = a[2];\n const a10 = a[3], a11 = a[4], a12 = a[5];\n const a20 = a[6], a21 = a[7], a22 = a[8];\n const b01 = a22 * a11 - a12 * a21;\n const b11 = -a22 * a10 + a12 * a20;\n const b21 = a21 * a10 - a11 * a20;\n // Calculate the determinant\n return a00 * b01 + a01 * b11 + a02 * b21;\n }\n Mat3.determinant = determinant;\n function trace(a) {\n return a[0] + a[4] + a[8];\n }\n Mat3.trace = trace;\n function sub(out, a, b) {\n out[0] = a[0] - b[0];\n out[1] = a[1] - b[1];\n out[2] = a[2] - b[2];\n out[3] = a[3] - b[3];\n out[4] = a[4] - b[4];\n out[5] = a[5] - b[5];\n out[6] = a[6] - b[6];\n out[7] = a[7] - b[7];\n out[8] = a[8] - b[8];\n return out;\n }\n Mat3.sub = sub;\n function add(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n out[3] = a[3] + b[3];\n out[4] = a[4] + b[4];\n out[5] = a[5] + b[5];\n out[6] = a[6] + b[6];\n out[7] = a[7] + b[7];\n out[8] = a[8] + b[8];\n return out;\n }\n Mat3.add = add;\n function mul(out, a, b) {\n const a00 = a[0], a01 = a[1], a02 = a[2], a10 = a[3], a11 = a[4], a12 = a[5], a20 = a[6], a21 = a[7], a22 = a[8];\n const b00 = b[0], b01 = b[1], b02 = b[2], b10 = b[3], b11 = b[4], b12 = b[5], b20 = b[6], b21 = b[7], b22 = b[8];\n out[0] = b00 * a00 + b01 * a10 + b02 * a20;\n out[1] = b00 * a01 + b01 * a11 + b02 * a21;\n out[2] = b00 * a02 + b01 * a12 + b02 * a22;\n out[3] = b10 * a00 + b11 * a10 + b12 * a20;\n out[4] = b10 * a01 + b11 * a11 + b12 * a21;\n out[5] = b10 * a02 + b11 * a12 + b12 * a22;\n out[6] = b20 * a00 + b21 * a10 + b22 * a20;\n out[7] = b20 * a01 + b21 * a11 + b22 * a21;\n out[8] = b20 * a02 + b21 * a12 + b22 * a22;\n return out;\n }\n Mat3.mul = mul;\n function subScalar(out, a, s) {\n out[0] = a[0] - s;\n out[1] = a[1] - s;\n out[2] = a[2] - s;\n out[3] = a[3] - s;\n out[4] = a[4] - s;\n out[5] = a[5] - s;\n out[6] = a[6] - s;\n out[7] = a[7] - s;\n out[8] = a[8] - s;\n return out;\n }\n Mat3.subScalar = subScalar;\n function addScalar(out, a, s) {\n out[0] = a[0] + s;\n out[1] = a[1] + s;\n out[2] = a[2] + s;\n out[3] = a[3] + s;\n out[4] = a[4] + s;\n out[5] = a[5] + s;\n out[6] = a[6] + s;\n out[7] = a[7] + s;\n out[8] = a[8] + s;\n return out;\n }\n Mat3.addScalar = addScalar;\n function mulScalar(out, a, s) {\n out[0] = a[0] * s;\n out[1] = a[1] * s;\n out[2] = a[2] * s;\n out[3] = a[3] * s;\n out[4] = a[4] * s;\n out[5] = a[5] * s;\n out[6] = a[6] * s;\n out[7] = a[7] * s;\n out[8] = a[8] * s;\n return out;\n }\n Mat3.mulScalar = mulScalar;\n const piThird = Math.PI / 3;\n const tmpB = zero();\n /**\n * Given a real symmetric 3x3 matrix A, compute the eigenvalues\n *\n * From https://en.wikipedia.org/wiki/Eigenvalue_algorithm#3.C3.973_matrices\n */\n function symmetricEigenvalues(out, a) {\n const p1 = a[1] * a[1] + a[2] * a[2] + a[5] * a[5];\n if (p1 === 0) {\n out[0] = a[0];\n out[1] = a[4];\n out[2] = a[8];\n }\n else {\n const q = trace(a) / 3;\n const a1 = a[0] - q;\n const a2 = a[4] - q;\n const a3 = a[8] - q;\n const p2 = a1 * a1 + a2 * a2 + a3 * a3 + 2 * p1;\n const p = Math.sqrt(p2 / 6);\n mulScalar(tmpB, Mat3.Identity, q);\n sub(tmpB, a, tmpB);\n mulScalar(tmpB, tmpB, (1 / p));\n const r = determinant(tmpB) / 2;\n // In exact arithmetic for a symmetric matrix -1 <= r <= 1\n // but computation error can leave it slightly outside this range.\n const phi = r <= -1 ? piThird : r >= 1 ?\n 0 : Math.acos(r) / 3;\n // the eigenvalues satisfy eig3 <= eig2 <= eig1\n out[0] = q + 2 * p * Math.cos(phi);\n out[2] = q + 2 * p * Math.cos(phi + (2 * piThird));\n out[1] = 3 * q - out[0] - out[2]; // since trace(A) = eig1 + eig2 + eig3\n }\n return out;\n }\n Mat3.symmetricEigenvalues = symmetricEigenvalues;\n const tmpR0 = [0.1, 0.0, 0.0];\n const tmpR1 = [0.1, 0.0, 0.0];\n const tmpR2 = [0.1, 0.0, 0.0];\n const tmpR0xR1 = [0.1, 0.0, 0.0];\n const tmpR0xR2 = [0.1, 0.0, 0.0];\n const tmpR1xR2 = [0.1, 0.0, 0.0];\n /**\n * Calculates the eigenvector for the given eigenvalue `e` of matrix `a`\n */\n function eigenvector(out, a, e) {\n Vec3.set(tmpR0, a[0] - e, a[1], a[2]);\n Vec3.set(tmpR1, a[1], a[4] - e, a[5]);\n Vec3.set(tmpR2, a[2], a[5], a[8] - e);\n Vec3.cross(tmpR0xR1, tmpR0, tmpR1);\n Vec3.cross(tmpR0xR2, tmpR0, tmpR2);\n Vec3.cross(tmpR1xR2, tmpR1, tmpR2);\n const d0 = Vec3.dot(tmpR0xR1, tmpR0xR1);\n const d1 = Vec3.dot(tmpR0xR2, tmpR0xR2);\n const d2 = Vec3.dot(tmpR1xR2, tmpR1xR2);\n let dmax = d0;\n let imax = 0;\n if (d1 > dmax) {\n dmax = d1;\n imax = 1;\n }\n if (d2 > dmax)\n imax = 2;\n if (imax === 0) {\n Vec3.scale(out, tmpR0xR1, 1 / Math.sqrt(d0));\n }\n else if (imax === 1) {\n Vec3.scale(out, tmpR0xR2, 1 / Math.sqrt(d1));\n }\n else {\n Vec3.scale(out, tmpR1xR2, 1 / Math.sqrt(d2));\n }\n return out;\n }\n Mat3.eigenvector = eigenvector;\n /**\n * Get matrix to transform directions, e.g. normals\n */\n function directionTransform(out, t) {\n fromMat4(out, t);\n invert(out, out);\n transpose(out, out);\n return out;\n }\n Mat3.directionTransform = directionTransform;\n Mat3.Identity = identity();\n /** Return the Frobenius inner product of two matrices (= dot product of the flattened matrices).\n * Can be used as a measure of similarity between two rotation matrices. */\n function innerProduct(a, b) {\n return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]\n + a[3] * b[3] + a[4] * b[4] + a[5] * b[5]\n + a[6] * b[6] + a[7] * b[7] + a[8] * b[8];\n }\n Mat3.innerProduct = innerProduct;\n})(Mat3 || (Mat3 = {}));\nexport { Mat3 };\n","/**\n * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author Alexander Rose \n */\nfunction Vec2() {\n return Vec2.zero();\n}\n(function (Vec2) {\n function zero() {\n // force double backing array by 0.1.\n const ret = [0.1, 0];\n ret[0] = 0.0;\n return ret;\n }\n Vec2.zero = zero;\n function clone(a) {\n const out = zero();\n out[0] = a[0];\n out[1] = a[1];\n return out;\n }\n Vec2.clone = clone;\n function create(x, y) {\n const out = zero();\n out[0] = x;\n out[1] = y;\n return out;\n }\n Vec2.create = create;\n function hasNaN(a) {\n return isNaN(a[0]) || isNaN(a[1]);\n }\n Vec2.hasNaN = hasNaN;\n function toArray(a, out, offset) {\n out[offset + 0] = a[0];\n out[offset + 1] = a[1];\n return out;\n }\n Vec2.toArray = toArray;\n function fromArray(a, array, offset) {\n a[0] = array[offset + 0];\n a[1] = array[offset + 1];\n return a;\n }\n Vec2.fromArray = fromArray;\n function copy(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n return out;\n }\n Vec2.copy = copy;\n function set(out, x, y) {\n out[0] = x;\n out[1] = y;\n return out;\n }\n Vec2.set = set;\n function add(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n return out;\n }\n Vec2.add = add;\n function sub(out, a, b) {\n out[0] = a[0] - b[0];\n out[1] = a[1] - b[1];\n return out;\n }\n Vec2.sub = sub;\n function mul(out, a, b) {\n out[0] = a[0] * b[0];\n out[1] = a[1] * b[1];\n return out;\n }\n Vec2.mul = mul;\n function div(out, a, b) {\n out[0] = a[0] / b[0];\n out[1] = a[1] / b[1];\n return out;\n }\n Vec2.div = div;\n function scale(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n return out;\n }\n Vec2.scale = scale;\n /**\n * Math.round the components of a Vec2\n */\n function round(out, a) {\n out[0] = Math.round(a[0]);\n out[1] = Math.round(a[1]);\n return out;\n }\n Vec2.round = round;\n /**\n * Math.ceil the components of a Vec2\n */\n function ceil(out, a) {\n out[0] = Math.ceil(a[0]);\n out[1] = Math.ceil(a[1]);\n return out;\n }\n Vec2.ceil = ceil;\n /**\n * Math.floor the components of a Vec2\n */\n function floor(out, a) {\n out[0] = Math.floor(a[0]);\n out[1] = Math.floor(a[1]);\n return out;\n }\n Vec2.floor = floor;\n function distance(a, b) {\n const x = b[0] - a[0], y = b[1] - a[1];\n return Math.sqrt(x * x + y * y);\n }\n Vec2.distance = distance;\n function squaredDistance(a, b) {\n const x = b[0] - a[0], y = b[1] - a[1];\n return x * x + y * y;\n }\n Vec2.squaredDistance = squaredDistance;\n function magnitude(a) {\n const x = a[0], y = a[1];\n return Math.sqrt(x * x + y * y);\n }\n Vec2.magnitude = magnitude;\n function squaredMagnitude(a) {\n const x = a[0], y = a[1];\n return x * x + y * y;\n }\n Vec2.squaredMagnitude = squaredMagnitude;\n /**\n * Returns the inverse of the components of a Vec2\n */\n function inverse(out, a) {\n out[0] = 1.0 / a[0];\n out[1] = 1.0 / a[1];\n return out;\n }\n Vec2.inverse = inverse;\n function areEqual(a, b) {\n return a[0] === b[0] && a[1] === b[1];\n }\n Vec2.areEqual = areEqual;\n function toString(a, precision) {\n return `[${a[0].toPrecision(precision)} ${a[1].toPrecision(precision)}}]`;\n }\n Vec2.toString = toString;\n})(Vec2 || (Vec2 = {}));\nexport { Vec2 };\n","/**\n * Copyright (c) 2017-2018 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n * @author Alexander Rose \n */\nimport { EPSILON } from './common';\nfunction Vec4() {\n return Vec4.zero();\n}\n(function (Vec4) {\n function zero() {\n // force double backing array by 0.1.\n const ret = [0.1, 0, 0, 0];\n ret[0] = 0.0;\n return ret;\n }\n Vec4.zero = zero;\n function clone(a) {\n const out = zero();\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n return out;\n }\n Vec4.clone = clone;\n function create(x, y, z, w) {\n const out = zero();\n out[0] = x;\n out[1] = y;\n out[2] = z;\n out[3] = w;\n return out;\n }\n Vec4.create = create;\n function fromSphere(out, sphere) {\n out[0] = sphere.center[0];\n out[1] = sphere.center[1];\n out[2] = sphere.center[2];\n out[3] = sphere.radius;\n return out;\n }\n Vec4.fromSphere = fromSphere;\n function ofSphere(sphere) {\n return fromSphere(zero(), sphere);\n }\n Vec4.ofSphere = ofSphere;\n function hasNaN(a) {\n return isNaN(a[0]) || isNaN(a[1]) || isNaN(a[2]) || isNaN(a[3]);\n }\n Vec4.hasNaN = hasNaN;\n function toArray(a, out, offset) {\n out[offset + 0] = a[0];\n out[offset + 1] = a[1];\n out[offset + 2] = a[2];\n out[offset + 3] = a[3];\n return out;\n }\n Vec4.toArray = toArray;\n function fromArray(a, array, offset) {\n a[0] = array[offset + 0];\n a[1] = array[offset + 1];\n a[2] = array[offset + 2];\n a[3] = array[offset + 3];\n return a;\n }\n Vec4.fromArray = fromArray;\n function toVec3Array(a, out, offset) {\n out[offset + 0] = a[0];\n out[offset + 1] = a[1];\n out[offset + 2] = a[2];\n }\n Vec4.toVec3Array = toVec3Array;\n function fromVec3Array(a, array, offset) {\n a[0] = array[offset + 0];\n a[1] = array[offset + 1];\n a[2] = array[offset + 2];\n a[3] = 0;\n return a;\n }\n Vec4.fromVec3Array = fromVec3Array;\n function copy(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n return out;\n }\n Vec4.copy = copy;\n function set(out, x, y, z, w) {\n out[0] = x;\n out[1] = y;\n out[2] = z;\n out[3] = w;\n return out;\n }\n Vec4.set = set;\n function add(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n out[3] = a[3] + b[3];\n return out;\n }\n Vec4.add = add;\n function distance(a, b) {\n const x = b[0] - a[0], y = b[1] - a[1], z = b[2] - a[2], w = b[3] - a[3];\n return Math.sqrt(x * x + y * y + z * z + w * w);\n }\n Vec4.distance = distance;\n function scale(out, a, b) {\n out[0] = a[0] * b;\n out[1] = a[1] * b;\n out[2] = a[2] * b;\n out[4] = a[4] * b;\n return out;\n }\n Vec4.scale = scale;\n /**\n * Math.round the components of a Vec4\n */\n function round(out, a) {\n out[0] = Math.round(a[0]);\n out[1] = Math.round(a[1]);\n out[2] = Math.round(a[2]);\n out[3] = Math.round(a[3]);\n return out;\n }\n Vec4.round = round;\n /**\n * Math.ceil the components of a Vec4\n */\n function ceil(out, a) {\n out[0] = Math.ceil(a[0]);\n out[1] = Math.ceil(a[1]);\n out[2] = Math.ceil(a[2]);\n out[3] = Math.ceil(a[3]);\n return out;\n }\n Vec4.ceil = ceil;\n /**\n * Math.floor the components of a Vec3\n */\n function floor(out, a) {\n out[0] = Math.floor(a[0]);\n out[1] = Math.floor(a[1]);\n out[2] = Math.floor(a[2]);\n out[3] = Math.floor(a[3]);\n return out;\n }\n Vec4.floor = floor;\n function squaredDistance(a, b) {\n const x = b[0] - a[0], y = b[1] - a[1], z = b[2] - a[2], w = b[3] - a[3];\n return x * x + y * y + z * z + w * w;\n }\n Vec4.squaredDistance = squaredDistance;\n function norm(a) {\n const x = a[0], y = a[1], z = a[2], w = a[3];\n return Math.sqrt(x * x + y * y + z * z + w * w);\n }\n Vec4.norm = norm;\n function squaredNorm(a) {\n const x = a[0], y = a[1], z = a[2], w = a[3];\n return x * x + y * y + z * z + w * w;\n }\n Vec4.squaredNorm = squaredNorm;\n function transformMat4(out, a, m) {\n const x = a[0], y = a[1], z = a[2], w = a[3];\n out[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;\n out[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;\n out[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;\n out[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;\n return out;\n }\n Vec4.transformMat4 = transformMat4;\n function dot(a, b) {\n return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];\n }\n Vec4.dot = dot;\n /**\n * Returns the inverse of the components of a Vec4\n */\n function inverse(out, a) {\n out[0] = 1.0 / a[0];\n out[1] = 1.0 / a[1];\n out[2] = 1.0 / a[2];\n out[3] = 1.0 / a[3];\n return out;\n }\n Vec4.inverse = inverse;\n /**\n * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===)\n */\n function exactEquals(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];\n }\n Vec4.exactEquals = exactEquals;\n /**\n * Returns whether or not the vectors have approximately the same elements in the same position.\n */\n function equals(a, b) {\n const a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];\n const b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];\n return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&\n Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) &&\n Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) &&\n Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)));\n }\n Vec4.equals = equals;\n function toString(a, precision) {\n return `[${a[0].toPrecision(precision)} ${a[1].toPrecision(precision)} ${a[2].toPrecision(precision)} ${a[3].toPrecision(precision)}]`;\n }\n Vec4.toString = toString;\n})(Vec4 || (Vec4 = {}));\nexport { Vec4 };\n","/**\n * Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author Alexander Rose \n * @author David Sehnal \n */\nexport function ObjectKeys(o) {\n return Object.keys(o);\n}\n;\nexport function assertUnreachable(x) {\n throw new Error('unreachable');\n}\nexport function isPromiseLike(x) {\n return typeof (x === null || x === void 0 ? void 0 : x.then) === 'function';\n}\n","/**\n * Copyright (c) 2017-2023 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n * @author Alexander Rose \n */\nimport { Vec3 } from './vec3';\nimport { EPSILON } from './common';\nimport { assertUnreachable } from '../../../mol-util/type-helpers';\nfunction Quat() {\n return Quat.zero();\n}\n(function (Quat) {\n function zero() {\n // force double backing array by 0.1.\n const ret = [0.1, 0, 0, 0];\n ret[0] = 0.0;\n return ret;\n }\n Quat.zero = zero;\n function identity() {\n const out = zero();\n out[3] = 1;\n return out;\n }\n Quat.identity = identity;\n function setIdentity(out) {\n out[0] = 0;\n out[1] = 0;\n out[2] = 0;\n out[3] = 1;\n }\n Quat.setIdentity = setIdentity;\n function hasNaN(q) {\n return isNaN(q[0]) || isNaN(q[1]) || isNaN(q[2]) || isNaN(q[3]);\n }\n Quat.hasNaN = hasNaN;\n function create(x, y, z, w) {\n const out = identity();\n out[0] = x;\n out[1] = y;\n out[2] = z;\n out[3] = w;\n return out;\n }\n Quat.create = create;\n function setAxisAngle(out, axis, rad) {\n rad = rad * 0.5;\n const s = Math.sin(rad);\n out[0] = s * axis[0];\n out[1] = s * axis[1];\n out[2] = s * axis[2];\n out[3] = Math.cos(rad);\n return out;\n }\n Quat.setAxisAngle = setAxisAngle;\n /**\n * Gets the rotation axis and angle for a given\n * quaternion. If a quaternion is created with\n * setAxisAngle, this method will return the same\n * values as providied in the original parameter list\n * OR functionally equivalent values.\n * Example: The quaternion formed by axis [0, 0, 1] and\n * angle -90 is the same as the quaternion formed by\n * [0, 0, 1] and 270. This method favors the latter.\n */\n function getAxisAngle(out_axis, q) {\n const rad = Math.acos(q[3]) * 2.0;\n const s = Math.sin(rad / 2.0);\n if (s !== 0.0) {\n out_axis[0] = q[0] / s;\n out_axis[1] = q[1] / s;\n out_axis[2] = q[2] / s;\n }\n else {\n // If s is zero, return any axis (no rotation - axis does not matter)\n out_axis[0] = 1;\n out_axis[1] = 0;\n out_axis[2] = 0;\n }\n return rad;\n }\n Quat.getAxisAngle = getAxisAngle;\n function multiply(out, a, b) {\n const ax = a[0], ay = a[1], az = a[2], aw = a[3];\n const bx = b[0], by = b[1], bz = b[2], bw = b[3];\n out[0] = ax * bw + aw * bx + ay * bz - az * by;\n out[1] = ay * bw + aw * by + az * bx - ax * bz;\n out[2] = az * bw + aw * bz + ax * by - ay * bx;\n out[3] = aw * bw - ax * bx - ay * by - az * bz;\n return out;\n }\n Quat.multiply = multiply;\n function rotateX(out, a, rad) {\n rad *= 0.5;\n const ax = a[0], ay = a[1], az = a[2], aw = a[3];\n const bx = Math.sin(rad), bw = Math.cos(rad);\n out[0] = ax * bw + aw * bx;\n out[1] = ay * bw + az * bx;\n out[2] = az * bw - ay * bx;\n out[3] = aw * bw - ax * bx;\n return out;\n }\n Quat.rotateX = rotateX;\n function rotateY(out, a, rad) {\n rad *= 0.5;\n const ax = a[0], ay = a[1], az = a[2], aw = a[3];\n const by = Math.sin(rad), bw = Math.cos(rad);\n out[0] = ax * bw - az * by;\n out[1] = ay * bw + aw * by;\n out[2] = az * bw + ax * by;\n out[3] = aw * bw - ay * by;\n return out;\n }\n Quat.rotateY = rotateY;\n function rotateZ(out, a, rad) {\n rad *= 0.5;\n const ax = a[0], ay = a[1], az = a[2], aw = a[3];\n const bz = Math.sin(rad), bw = Math.cos(rad);\n out[0] = ax * bw + ay * bz;\n out[1] = ay * bw - ax * bz;\n out[2] = az * bw + aw * bz;\n out[3] = aw * bw - az * bz;\n return out;\n }\n Quat.rotateZ = rotateZ;\n /**\n * Calculates the W component of a quat from the X, Y, and Z components.\n * Assumes that quaternion is 1 unit in length.\n * Any existing W component will be ignored.\n */\n function calculateW(out, a) {\n const x = a[0], y = a[1], z = a[2];\n out[0] = x;\n out[1] = y;\n out[2] = z;\n out[3] = Math.sqrt(Math.abs(1.0 - x * x - y * y - z * z));\n return out;\n }\n Quat.calculateW = calculateW;\n /**\n * Performs a spherical linear interpolation between two quat\n */\n function slerp(out, a, b, t) {\n // benchmarks:\n // http://jsperf.com/quaternion-slerp-implementations\n const ax = a[0], ay = a[1], az = a[2], aw = a[3];\n let bx = b[0], by = b[1], bz = b[2], bw = b[3];\n let omega, cosom, sinom, scale0, scale1;\n // calc cosine\n cosom = ax * bx + ay * by + az * bz + aw * bw;\n // adjust signs (if necessary)\n if (cosom < 0.0) {\n cosom = -cosom;\n bx = -bx;\n by = -by;\n bz = -bz;\n bw = -bw;\n }\n // calculate coefficients\n if ((1.0 - cosom) > 0.000001) {\n // standard case (slerp)\n omega = Math.acos(cosom);\n sinom = Math.sin(omega);\n scale0 = Math.sin((1.0 - t) * omega) / sinom;\n scale1 = Math.sin(t * omega) / sinom;\n }\n else {\n // \"from\" and \"to\" quaternions are very close\n // ... so we can do a linear interpolation\n scale0 = 1.0 - t;\n scale1 = t;\n }\n // calculate final values\n out[0] = scale0 * ax + scale1 * bx;\n out[1] = scale0 * ay + scale1 * by;\n out[2] = scale0 * az + scale1 * bz;\n out[3] = scale0 * aw + scale1 * bw;\n return out;\n }\n Quat.slerp = slerp;\n function invert(out, a) {\n const a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];\n const dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3;\n const invDot = dot ? 1.0 / dot : 0;\n // TODO: Would be faster to return [0,0,0,0] immediately if dot == 0\n out[0] = -a0 * invDot;\n out[1] = -a1 * invDot;\n out[2] = -a2 * invDot;\n out[3] = a3 * invDot;\n return out;\n }\n Quat.invert = invert;\n /**\n * Calculates the conjugate of a quat\n * If the quaternion is normalized, this function is faster than quat.inverse and produces the same result.\n */\n function conjugate(out, a) {\n out[0] = -a[0];\n out[1] = -a[1];\n out[2] = -a[2];\n out[3] = a[3];\n return out;\n }\n Quat.conjugate = conjugate;\n function dot(a, b) {\n return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];\n }\n Quat.dot = dot;\n /**\n * Creates a quaternion from the given 3x3 rotation matrix.\n *\n * NOTE: The resultant quaternion is not normalized, so you should be sure\n * to renormalize the quaternion yourself where necessary.\n */\n function fromMat3(out, m) {\n // Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes\n // article \"Quaternion Calculus and Fast Animation\".\n const fTrace = m[0] + m[4] + m[8];\n let fRoot;\n if (fTrace > 0.0) {\n // |w| > 1/2, may as well choose w > 1/2\n fRoot = Math.sqrt(fTrace + 1.0); // 2w\n out[3] = 0.5 * fRoot;\n fRoot = 0.5 / fRoot; // 1/(4w)\n out[0] = (m[5] - m[7]) * fRoot;\n out[1] = (m[6] - m[2]) * fRoot;\n out[2] = (m[1] - m[3]) * fRoot;\n }\n else {\n // |w| <= 1/2\n let i = 0;\n if (m[4] > m[0])\n i = 1;\n if (m[8] > m[i * 3 + i])\n i = 2;\n const j = (i + 1) % 3;\n const k = (i + 2) % 3;\n fRoot = Math.sqrt(m[i * 3 + i] - m[j * 3 + j] - m[k * 3 + k] + 1.0);\n out[i] = 0.5 * fRoot;\n fRoot = 0.5 / fRoot;\n out[3] = (m[j * 3 + k] - m[k * 3 + j]) * fRoot;\n out[j] = (m[j * 3 + i] + m[i * 3 + j]) * fRoot;\n out[k] = (m[k * 3 + i] + m[i * 3 + k]) * fRoot;\n }\n return out;\n }\n Quat.fromMat3 = fromMat3;\n function fromEuler(out, euler, order) {\n const [x, y, z] = euler;\n // http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m\n const c1 = Math.cos(x / 2);\n const c2 = Math.cos(y / 2);\n const c3 = Math.cos(z / 2);\n const s1 = Math.sin(x / 2);\n const s2 = Math.sin(y / 2);\n const s3 = Math.sin(z / 2);\n switch (order) {\n case 'XYZ':\n out[0] = s1 * c2 * c3 + c1 * s2 * s3;\n out[1] = c1 * s2 * c3 - s1 * c2 * s3;\n out[2] = c1 * c2 * s3 + s1 * s2 * c3;\n out[3] = c1 * c2 * c3 - s1 * s2 * s3;\n break;\n case 'YXZ':\n out[0] = s1 * c2 * c3 + c1 * s2 * s3;\n out[1] = c1 * s2 * c3 - s1 * c2 * s3;\n out[2] = c1 * c2 * s3 - s1 * s2 * c3;\n out[3] = c1 * c2 * c3 + s1 * s2 * s3;\n break;\n case 'ZXY':\n out[0] = s1 * c2 * c3 - c1 * s2 * s3;\n out[1] = c1 * s2 * c3 + s1 * c2 * s3;\n out[2] = c1 * c2 * s3 + s1 * s2 * c3;\n out[3] = c1 * c2 * c3 - s1 * s2 * s3;\n break;\n case 'ZYX':\n out[0] = s1 * c2 * c3 - c1 * s2 * s3;\n out[1] = c1 * s2 * c3 + s1 * c2 * s3;\n out[2] = c1 * c2 * s3 - s1 * s2 * c3;\n out[3] = c1 * c2 * c3 + s1 * s2 * s3;\n break;\n case 'YZX':\n out[0] = s1 * c2 * c3 + c1 * s2 * s3;\n out[1] = c1 * s2 * c3 + s1 * c2 * s3;\n out[2] = c1 * c2 * s3 - s1 * s2 * c3;\n out[3] = c1 * c2 * c3 - s1 * s2 * s3;\n break;\n case 'XZY':\n out[0] = s1 * c2 * c3 - c1 * s2 * s3;\n out[1] = c1 * s2 * c3 - s1 * c2 * s3;\n out[2] = c1 * c2 * s3 + s1 * s2 * c3;\n out[3] = c1 * c2 * c3 + s1 * s2 * s3;\n break;\n default:\n assertUnreachable(order);\n }\n return out;\n }\n Quat.fromEuler = fromEuler;\n const fromUnitVec3Temp = [0, 0, 0];\n /** Quaternion from two normalized unit vectors. */\n function fromUnitVec3(out, a, b) {\n // assumes a and b are normalized\n let r = Vec3.dot(a, b) + 1;\n if (r < EPSILON) {\n // If u and v are exactly opposite, rotate 180 degrees\n // around an arbitrary orthogonal axis. Axis normalisation\n // can happen later, when we normalise the quaternion.\n r = 0;\n if (Math.abs(a[0]) > Math.abs(a[2])) {\n Vec3.set(fromUnitVec3Temp, -a[1], a[0], 0);\n }\n else {\n Vec3.set(fromUnitVec3Temp, 0, -a[2], a[1]);\n }\n }\n else {\n // Otherwise, build quaternion the standard way.\n Vec3.cross(fromUnitVec3Temp, a, b);\n }\n out[0] = fromUnitVec3Temp[0];\n out[1] = fromUnitVec3Temp[1];\n out[2] = fromUnitVec3Temp[2];\n out[3] = r;\n normalize(out, out);\n return out;\n }\n Quat.fromUnitVec3 = fromUnitVec3;\n function clone(a) {\n const out = zero();\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n return out;\n }\n Quat.clone = clone;\n function toArray(a, out, offset) {\n out[offset + 0] = a[0];\n out[offset + 1] = a[1];\n out[offset + 2] = a[2];\n out[offset + 3] = a[3];\n return out;\n }\n Quat.toArray = toArray;\n function fromArray(a, array, offset) {\n a[0] = array[offset + 0];\n a[1] = array[offset + 1];\n a[2] = array[offset + 2];\n a[3] = array[offset + 3];\n return a;\n }\n Quat.fromArray = fromArray;\n function copy(out, a) {\n out[0] = a[0];\n out[1] = a[1];\n out[2] = a[2];\n out[3] = a[3];\n return out;\n }\n Quat.copy = copy;\n function set(out, x, y, z, w) {\n out[0] = x;\n out[1] = y;\n out[2] = z;\n out[3] = w;\n return out;\n }\n Quat.set = set;\n /**\n * Returns whether or not the quaternions have exactly the same elements in the same position (when compared with ===)\n */\n function exactEquals(a, b) {\n return a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3];\n }\n Quat.exactEquals = exactEquals;\n /**\n * Returns whether or not the quaternions have approximately the same elements in the same position.\n */\n function equals(a, b) {\n const a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];\n const b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];\n return (Math.abs(a0 - b0) <= EPSILON * Math.max(1.0, Math.abs(a0), Math.abs(b0)) &&\n Math.abs(a1 - b1) <= EPSILON * Math.max(1.0, Math.abs(a1), Math.abs(b1)) &&\n Math.abs(a2 - b2) <= EPSILON * Math.max(1.0, Math.abs(a2), Math.abs(b2)) &&\n Math.abs(a3 - b3) <= EPSILON * Math.max(1.0, Math.abs(a3), Math.abs(b3)));\n }\n Quat.equals = equals;\n function add(out, a, b) {\n out[0] = a[0] + b[0];\n out[1] = a[1] + b[1];\n out[2] = a[2] + b[2];\n out[3] = a[3] + b[3];\n return out;\n }\n Quat.add = add;\n function normalize(out, a) {\n const x = a[0];\n const y = a[1];\n const z = a[2];\n const w = a[3];\n let len = x * x + y * y + z * z + w * w;\n if (len > 0) {\n len = 1 / Math.sqrt(len);\n out[0] = x * len;\n out[1] = y * len;\n out[2] = z * len;\n out[3] = w * len;\n }\n return out;\n }\n Quat.normalize = normalize;\n /**\n * Sets a quaternion to represent the shortest rotation from one\n * vector to another.\n *\n * Both vectors are assumed to be unit length.\n */\n const rotTmpVec3 = [0, 0, 0];\n const rotTmpVec3UnitX = [1, 0, 0];\n const rotTmpVec3UnitY = [0, 1, 0];\n function rotationTo(out, a, b) {\n const dot = Vec3.dot(a, b);\n if (dot < -0.999999) {\n Vec3.cross(rotTmpVec3, rotTmpVec3UnitX, a);\n if (Vec3.magnitude(rotTmpVec3) < 0.000001)\n Vec3.cross(rotTmpVec3, rotTmpVec3UnitY, a);\n Vec3.normalize(rotTmpVec3, rotTmpVec3);\n setAxisAngle(out, rotTmpVec3, Math.PI);\n return out;\n }\n else if (dot > 0.999999) {\n out[0] = 0;\n out[1] = 0;\n out[2] = 0;\n out[3] = 1;\n return out;\n }\n else {\n Vec3.cross(rotTmpVec3, a, b);\n out[0] = rotTmpVec3[0];\n out[1] = rotTmpVec3[1];\n out[2] = rotTmpVec3[2];\n out[3] = 1 + dot;\n return normalize(out, out);\n }\n }\n Quat.rotationTo = rotationTo;\n /**\n * Performs a spherical linear interpolation with two control points\n */\n const sqlerpTemp1 = zero();\n const sqlerpTemp2 = zero();\n function sqlerp(out, a, b, c, d, t) {\n slerp(sqlerpTemp1, a, d, t);\n slerp(sqlerpTemp2, b, c, t);\n slerp(out, sqlerpTemp1, sqlerpTemp2, 2 * t * (1 - t));\n return out;\n }\n Quat.sqlerp = sqlerp;\n /**\n * Sets the specified quaternion with values corresponding to the given\n * axes. Each axis is a vec3 and is expected to be unit length and\n * perpendicular to all other specified axes.\n */\n const axesTmpMat = [0, 0, 0, 0, 0, 0, 0, 0, 0];\n function setAxes(out, view, right, up) {\n axesTmpMat[0] = right[0];\n axesTmpMat[3] = right[1];\n axesTmpMat[6] = right[2];\n axesTmpMat[1] = up[0];\n axesTmpMat[4] = up[1];\n axesTmpMat[7] = up[2];\n axesTmpMat[2] = -view[0];\n axesTmpMat[5] = -view[1];\n axesTmpMat[8] = -view[2];\n return normalize(out, fromMat3(out, axesTmpMat));\n }\n Quat.setAxes = setAxes;\n function toString(a, precision) {\n return `[${a[0].toPrecision(precision)} ${a[1].toPrecision(precision)} ${a[2].toPrecision(precision)} ${a[3].toPrecision(precision)}]`;\n }\n Quat.toString = toString;\n Quat.Identity = identity();\n})(Quat || (Quat = {}));\nexport { Quat };\n","import { Mat3 } from './3d/mat3';\n/**\n * Copyright (c) 2017-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n * @author Alexander Rose \n */\nimport { Mat4 } from './3d/mat4';\nexport var Tensor;\n(function (Tensor) {\n function Layout(dimensions, axisOrderSlowToFast, ctor) {\n // need to reverse the axis order for better access.\n const axisOrderFastToSlow = [];\n for (let i = 0; i < axisOrderSlowToFast.length; i++)\n axisOrderFastToSlow[i] = axisOrderSlowToFast[axisOrderSlowToFast.length - i - 1];\n const accessDimensions = [1];\n for (let i = 1; i < dimensions.length; i++)\n accessDimensions[i] = dimensions[axisOrderFastToSlow[i - 1]];\n return { dimensions, axisOrderFastToSlow, axisOrderSlowToFast, accessDimensions, defaultCtor: ctor || Float64Array };\n }\n function create(space, data) { return { space, data }; }\n Tensor.create = create;\n function Space(dimensions, axisOrderSlowToFast, ctor) {\n const layout = Layout(dimensions, axisOrderSlowToFast, ctor);\n const { get, set, add, dataOffset, getCoords } = accessors(layout);\n return { rank: dimensions.length, dimensions, axisOrderSlowToFast, create: creator(layout), get, set, add, dataOffset, getCoords };\n }\n Tensor.Space = Space;\n function Data1(values) { return values; }\n Tensor.Data1 = Data1;\n function Vector(d, ctor) { return Space([d], [0], ctor); }\n Tensor.Vector = Vector;\n function ColumnMajorMatrix(rows, cols, ctor) { return Space([rows, cols], [1, 0], ctor); }\n Tensor.ColumnMajorMatrix = ColumnMajorMatrix;\n function RowMajorMatrix(rows, cols, ctor) { return Space([rows, cols], [0, 1], ctor); }\n Tensor.RowMajorMatrix = RowMajorMatrix;\n function toMat4(out, space, data) {\n if (space.rank !== 2)\n throw new Error('Invalid tensor rank');\n const d0 = Math.min(4, space.dimensions[0]), d1 = Math.min(4, space.dimensions[1]);\n for (let i = 0; i < d0; i++) {\n for (let j = 0; j < d1; j++)\n Mat4.setValue(out, i, j, space.get(data, i, j));\n }\n return out;\n }\n Tensor.toMat4 = toMat4;\n function toMat3(out, space, data) {\n if (space.rank !== 2)\n throw new Error('Invalid tensor rank');\n const d0 = Math.min(3, space.dimensions[0]), d1 = Math.min(3, space.dimensions[1]);\n for (let i = 0; i < d0; i++) {\n for (let j = 0; j < d1; j++)\n Mat3.setValue(out, i, j, space.get(data, i, j));\n }\n return out;\n }\n Tensor.toMat3 = toMat3;\n function toVec3(out, space, data) {\n if (space.rank !== 1)\n throw new Error('Invalid tensor rank');\n const d0 = Math.min(3, space.dimensions[0]);\n for (let i = 0; i < d0; i++)\n out[i] = data[i];\n return out;\n }\n Tensor.toVec3 = toVec3;\n function toVec4(out, space, data) {\n if (space.rank !== 1)\n throw new Error('Invalid tensor rank');\n const d0 = Math.min(4, space.dimensions[0]);\n for (let i = 0; i < d0; i++)\n out[i] = data[i];\n return out;\n }\n Tensor.toVec4 = toVec4;\n function areEqualExact(a, b) {\n const len = a.length;\n if (len !== b.length)\n return false;\n for (let i = 0; i < len; i++)\n if (a[i] !== b[i])\n return false;\n return true;\n }\n Tensor.areEqualExact = areEqualExact;\n function accessors(layout) {\n const { dimensions, axisOrderFastToSlow: ao } = layout;\n switch (dimensions.length) {\n case 1: return {\n get: (t, d) => t[d],\n set: (t, d, x) => t[d] = x,\n add: (t, d, x) => t[d] += x,\n dataOffset: (d) => d,\n getCoords: (o, c) => {\n c[0] = o;\n return c;\n }\n };\n case 2: {\n // column major\n if (ao[0] === 0 && ao[1] === 1) {\n const rows = dimensions[0];\n return {\n get: (t, i, j) => t[j * rows + i],\n set: (t, i, j, x) => t[j * rows + i] = x,\n add: (t, i, j, x) => t[j * rows + i] += x,\n dataOffset: (i, j) => j * rows + i,\n getCoords: (o, c) => {\n c[0] = o % rows;\n c[1] = Math.floor(o / rows);\n return c;\n }\n };\n }\n if (ao[0] === 1 && ao[1] === 0) {\n const cols = dimensions[1];\n return {\n get: (t, i, j) => t[i * cols + j],\n set: (t, i, j, x) => t[i * cols + j] = x,\n add: (t, i, j, x) => t[i * cols + j] += x,\n dataOffset: (i, j) => i * cols + j,\n getCoords: (o, c) => {\n c[0] = Math.floor(o / cols);\n c[1] = o % cols;\n return c;\n }\n };\n }\n throw new Error('bad axis order');\n }\n case 3: {\n if (ao[0] === 0 && ao[1] === 1 && ao[2] === 2) { // 012 ijk\n const u = dimensions[0], v = dimensions[1], uv = u * v;\n return {\n get: (t, i, j, k) => t[i + j * u + k * uv],\n set: (t, i, j, k, x) => t[i + j * u + k * uv] = x,\n add: (t, i, j, k, x) => t[i + j * u + k * uv] += x,\n dataOffset: (i, j, k) => i + j * u + k * uv,\n getCoords: (o, c) => {\n const p = Math.floor(o / u);\n c[0] = o % u;\n c[1] = p % v;\n c[2] = Math.floor(p / v);\n return c;\n }\n };\n }\n if (ao[0] === 0 && ao[1] === 2 && ao[2] === 1) { // 021 ikj\n const u = dimensions[0], v = dimensions[2], uv = u * v;\n return {\n get: (t, i, j, k) => t[i + k * u + j * uv],\n set: (t, i, j, k, x) => t[i + k * u + j * uv] = x,\n add: (t, i, j, k, x) => t[i + k * u + j * uv] += x,\n dataOffset: (i, j, k) => i + k * u + j * uv,\n getCoords: (o, c) => {\n const p = Math.floor(o / u);\n c[0] = o % u;\n c[1] = Math.floor(p / v);\n c[2] = p % v;\n return c;\n }\n };\n }\n if (ao[0] === 1 && ao[1] === 0 && ao[2] === 2) { // 102 jik\n const u = dimensions[1], v = dimensions[0], uv = u * v;\n return {\n get: (t, i, j, k) => t[j + i * u + k * uv],\n set: (t, i, j, k, x) => t[j + i * u + k * uv] = x,\n add: (t, i, j, k, x) => t[j + i * u + k * uv] += x,\n dataOffset: (i, j, k) => j + i * u + k * uv,\n getCoords: (o, c) => {\n const p = Math.floor(o / u);\n c[0] = p % v;\n c[1] = o % u;\n c[2] = Math.floor(p / v);\n return c;\n }\n };\n }\n if (ao[0] === 1 && ao[1] === 2 && ao[2] === 0) { // 120 jki\n const u = dimensions[1], v = dimensions[2], uv = u * v;\n return {\n get: (t, i, j, k) => t[j + k * u + i * uv],\n set: (t, i, j, k, x) => t[j + k * u + i * uv] = x,\n add: (t, i, j, k, x) => t[j + k * u + i * uv] += x,\n dataOffset: (i, j, k) => j + k * u + i * uv,\n getCoords: (o, c) => {\n const p = Math.floor(o / u);\n c[0] = Math.floor(p / v);\n c[1] = o % u;\n c[2] = p % v;\n return c;\n }\n };\n }\n if (ao[0] === 2 && ao[1] === 0 && ao[2] === 1) { // 201 kij\n const u = dimensions[2], v = dimensions[0], uv = u * v;\n return {\n get: (t, i, j, k) => t[k + i * u + j * uv],\n set: (t, i, j, k, x) => t[k + i * u + j * uv] = x,\n add: (t, i, j, k, x) => t[k + i * u + j * uv] += x,\n dataOffset: (i, j, k) => k + i * u + j * uv,\n getCoords: (o, c) => {\n const p = Math.floor(o / u);\n c[0] = p % v;\n c[1] = Math.floor(p / v);\n c[2] = o % u;\n return c;\n }\n };\n }\n if (ao[0] === 2 && ao[1] === 1 && ao[2] === 0) { // 210 kji\n const u = dimensions[2], v = dimensions[1], uv = u * v;\n return {\n get: (t, i, j, k) => t[k + j * u + i * uv],\n set: (t, i, j, k, x) => t[k + j * u + i * uv] = x,\n add: (t, i, j, k, x) => t[k + j * u + i * uv] += x,\n dataOffset: (i, j, k) => k + j * u + i * uv,\n getCoords: (o, c) => {\n const p = Math.floor(o / u);\n c[0] = Math.floor(p / v);\n c[1] = p % v;\n c[2] = o % u;\n return c;\n }\n };\n }\n throw new Error('bad axis order');\n }\n default: return {\n get: (t, ...c) => t[dataOffset(layout, c)],\n set: (t, ...c) => t[dataOffset(layout, c)] = c[c.length - 1],\n add: (t, ...c) => t[dataOffset(layout, c)] += c[c.length - 1],\n dataOffset: (...c) => dataOffset(layout, c),\n getCoords: (o, c) => getCoords(layout, o, c),\n };\n }\n }\n function creator(layout) {\n const { dimensions: ds } = layout;\n let size = 1;\n for (let i = 0, _i = ds.length; i < _i; i++)\n size *= ds[i];\n return ctor => new (ctor || layout.defaultCtor)(size);\n }\n function dataOffset(layout, coord) {\n const { accessDimensions: acc, axisOrderFastToSlow: ao } = layout;\n const d = acc.length - 1;\n let o = acc[d] * coord[ao[d]];\n for (let i = d - 1; i >= 0; i--) {\n o = (o + coord[ao[i]]) * acc[i];\n }\n return o;\n }\n function getCoords(layout, o, coords) {\n const { dimensions: dim, axisOrderFastToSlow: ao } = layout;\n const d = dim.length;\n let c = o;\n for (let i = 0; i < d; i++) {\n const d = dim[ao[i]];\n coords[ao[i]] = c % d;\n c = Math.floor(c / d);\n }\n coords[ao[d + 1]] = c;\n return coords;\n }\n // Convers \"slow to fast\" axis order to \"fast to slow\" and vice versa.\n function invertAxisOrder(v) {\n const ret = [];\n for (let i = 0; i < v.length; i++) {\n ret[i] = v[v.length - i - 1];\n }\n return ret;\n }\n Tensor.invertAxisOrder = invertAxisOrder;\n function reorder(xs, indices) {\n const ret = [];\n for (let i = 0; i < xs.length; i++)\n ret[i] = xs[indices[i]];\n return ret;\n }\n function convertToCanonicalAxisIndicesFastToSlow(order) {\n const indices = new Int32Array(order.length);\n for (let i = 0; i < order.length; i++)\n indices[order[i]] = i;\n return (xs) => reorder(xs, indices);\n }\n Tensor.convertToCanonicalAxisIndicesFastToSlow = convertToCanonicalAxisIndicesFastToSlow;\n function convertToCanonicalAxisIndicesSlowToFast(order) {\n const indices = new Int32Array(order.length);\n for (let i = 0; i < order.length; i++)\n indices[order[order.length - i - 1]] = i;\n return (xs) => reorder(xs, indices);\n }\n Tensor.convertToCanonicalAxisIndicesSlowToFast = convertToCanonicalAxisIndicesSlowToFast;\n})(Tensor || (Tensor = {}));\n","/**\n * Copyright (c) 2017-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n * @author Alexander Rose \n */\nimport * as ColumnHelpers from './column-helpers';\nimport { Tensor as Tensors } from '../../mol-math/linear-algebra';\nimport { parseInt as fastParseInt, parseFloat as fastParseFloat } from '../../mol-io/reader/common/text/number-parser';\nvar Column;\n(function (Column) {\n let Schema;\n (function (Schema) {\n // T also serves as a default value for undefined columns\n Schema.str = { '@type': 'str', T: '', valueType: 'str' };\n Schema.ustr = { '@type': 'str', T: '', valueType: 'str', transform: 'uppercase' };\n Schema.lstr = { '@type': 'str', T: '', valueType: 'str', transform: 'lowercase' };\n Schema.int = { '@type': 'int', T: 0, valueType: 'int' };\n Schema.coord = { '@type': 'coord', T: 0, valueType: 'float' };\n Schema.float = { '@type': 'float', T: 0, valueType: 'float' };\n function Str(options) { var _a; return { '@type': 'str', T: (_a = options === null || options === void 0 ? void 0 : options.defaultValue) !== null && _a !== void 0 ? _a : '', transform: options === null || options === void 0 ? void 0 : options.transform, valueType: 'str' }; }\n Schema.Str = Str;\n ;\n function Int(defaultValue = 0) { return { '@type': 'int', T: defaultValue, valueType: 'int' }; }\n Schema.Int = Int;\n ;\n function Float(defaultValue = 0) { return { '@type': 'float', T: defaultValue, valueType: 'float' }; }\n Schema.Float = Float;\n ;\n function Tensor(space, baseType = Schema.float) { return { '@type': 'tensor', T: space.create(), space, valueType: 'tensor', baseType }; }\n Schema.Tensor = Tensor;\n function Vector(dim, baseType = Schema.float) { return Tensor(Tensors.Vector(dim, baseType['@type'] === 'int' ? Int32Array : Float64Array), baseType); }\n Schema.Vector = Vector;\n function Matrix(rows, cols, baseType = Schema.float) { return Tensor(Tensors.ColumnMajorMatrix(rows, cols, baseType['@type'] === 'int' ? Int32Array : Float64Array), baseType); }\n Schema.Matrix = Matrix;\n function Aliased(t) {\n return t;\n }\n Schema.Aliased = Aliased;\n function List(separator, itemParse, defaultValue = []) {\n return { '@type': 'list', T: defaultValue, separator, itemParse, valueType: 'list' };\n }\n Schema.List = List;\n })(Schema = Column.Schema || (Column.Schema = {}));\n function is(v) {\n return !!v && !!v.schema && !!v.value;\n }\n Column.is = is;\n Column.ValueKind = {\n /** Defined value (= 0) */\n Present: 0 /* ValueKinds.Present */,\n /** Expressed in CIF as `.` (= 1) */\n NotPresent: 1 /* ValueKinds.NotPresent */,\n /** Expressed in CIF as `?` (= 2) */\n Unknown: 2 /* ValueKinds.Unknown */\n };\n function Undefined(rowCount, schema) {\n return constColumn(schema['T'], rowCount, schema, 1 /* ValueKinds.NotPresent */);\n }\n Column.Undefined = Undefined;\n function ofConst(v, rowCount, type) {\n return constColumn(v, rowCount, type, 0 /* ValueKinds.Present */);\n }\n Column.ofConst = ofConst;\n function ofLambda(spec) {\n return lambdaColumn(spec);\n }\n Column.ofLambda = ofLambda;\n /** values [min, max] (i.e. include both values) */\n function range(min, max) {\n return ofLambda({\n value: i => i + min,\n rowCount: Math.max(max - min + 1, 0),\n schema: Schema.int\n });\n }\n Column.range = range;\n function ofArray(spec) {\n return arrayColumn(spec);\n }\n Column.ofArray = ofArray;\n function ofIntArray(array) {\n return arrayColumn({ array, schema: Schema.int });\n }\n Column.ofIntArray = ofIntArray;\n function ofFloatArray(array) {\n return arrayColumn({ array, schema: Schema.float });\n }\n Column.ofFloatArray = ofFloatArray;\n function ofStringArray(array) {\n return arrayColumn({ array, schema: Schema.str });\n }\n Column.ofStringArray = ofStringArray;\n function ofStringAliasArray(array) {\n return arrayColumn({ array, schema: Schema.Aliased(Schema.str) });\n }\n Column.ofStringAliasArray = ofStringAliasArray;\n function ofStringListArray(array, separator = ',') {\n return arrayColumn({ array, schema: Schema.List(separator, x => x) });\n }\n Column.ofStringListArray = ofStringListArray;\n function ofIntTokens(tokens) {\n const { count, data, indices } = tokens;\n return lambdaColumn({\n value: (row) => fastParseInt(data, indices[2 * row], indices[2 * row + 1]) || 0,\n rowCount: count,\n schema: Schema.int,\n });\n }\n Column.ofIntTokens = ofIntTokens;\n function ofFloatTokens(tokens) {\n const { count, data, indices } = tokens;\n return lambdaColumn({\n value: (row) => fastParseFloat(data, indices[2 * row], indices[2 * row + 1]) || 0,\n rowCount: count,\n schema: Schema.float,\n });\n }\n Column.ofFloatTokens = ofFloatTokens;\n function ofStringTokens(tokens) {\n const { count, data, indices } = tokens;\n return lambdaColumn({\n value: (row) => {\n const ret = data.substring(indices[2 * row], indices[2 * row + 1]);\n if (ret === '.' || ret === '?')\n return '';\n return ret;\n },\n rowCount: count,\n schema: Schema.str,\n });\n }\n Column.ofStringTokens = ofStringTokens;\n function window(column, start, end) {\n return windowColumn(column, start, end);\n }\n Column.window = window;\n function view(column, indices, checkIndentity = true) {\n return columnView(column, indices, checkIndentity);\n }\n Column.view = view;\n /** A map of the 1st occurence of each value. */\n function createFirstIndexMap(column) {\n return createFirstIndexMapOfColumn(column);\n }\n Column.createFirstIndexMap = createFirstIndexMap;\n function createIndexer(column) {\n return createIndexerOfColumn(column);\n }\n Column.createIndexer = createIndexer;\n function mapToArray(column, f, ctor) {\n return mapToArrayImpl(column, f, ctor || Array);\n }\n Column.mapToArray = mapToArray;\n function areEqual(a, b) {\n return areColumnsEqual(a, b);\n }\n Column.areEqual = areEqual;\n function indicesOf(c, test) {\n return columnIndicesOf(c, test);\n }\n Column.indicesOf = indicesOf;\n /** Makes the column backed by an array. Useful for columns that are accessed often. */\n function asArrayColumn(c, array) {\n if (c.__array)\n return c;\n if (!c.isDefined)\n return Undefined(c.rowCount, c.schema);\n return arrayColumn({ array: c.toArray({ array }), schema: c.schema, valueKind: c.valueKind });\n }\n Column.asArrayColumn = asArrayColumn;\n function copyToArray(c, array, offset = 0) {\n if (!c.isDefined)\n return;\n const cArray = c.__array;\n if (cArray) {\n for (let i = 0, _i = cArray.length; i < _i; i++)\n array[offset + i] = cArray[i];\n }\n else {\n for (let i = 0, _i = c.rowCount; i < _i; i++)\n array[offset + i] = c.value(i);\n }\n }\n Column.copyToArray = copyToArray;\n function isIdentity(c) {\n for (let i = 0, _i = c.rowCount; i < _i; i++) {\n if (i !== c.value(i))\n return false;\n }\n return true;\n }\n Column.isIdentity = isIdentity;\n})(Column || (Column = {}));\nexport { Column };\nfunction createFirstIndexMapOfColumn(c) {\n const map = new Map();\n for (let i = 0, _i = c.rowCount; i < _i; i++) {\n const v = c.value(i);\n if (!map.has(v))\n map.set(c.value(i), i);\n }\n return map;\n}\nfunction createIndexerOfColumn(c) {\n const map = new Map();\n for (let i = 0, _i = c.rowCount; i < _i; i++) {\n const v = c.value(i);\n if (!map.has(v))\n map.set(c.value(i), i);\n }\n return v => map.has(v) ? map.get(v) : -1;\n}\nfunction constColumn(v, rowCount, schema, valueKind) {\n const value = row => v;\n return {\n schema: schema,\n __array: void 0,\n isDefined: valueKind === 0 /* Column.ValueKinds.Present */,\n rowCount,\n value,\n valueKind: row => valueKind,\n toArray: params => {\n const { array } = ColumnHelpers.createArray(rowCount, params);\n for (let i = 0, _i = array.length; i < _i; i++)\n array[i] = v;\n return array;\n },\n areValuesEqual: (rowA, rowB) => true\n };\n}\nfunction lambdaColumn({ value, valueKind, areValuesEqual, rowCount, schema }) {\n return {\n schema: schema,\n __array: void 0,\n isDefined: true,\n rowCount,\n value,\n valueKind: valueKind ? valueKind : row => 0 /* Column.ValueKinds.Present */,\n toArray: params => {\n const { array, start } = ColumnHelpers.createArray(rowCount, params);\n for (let i = 0, _i = array.length; i < _i; i++)\n array[i] = value(i + start);\n return array;\n },\n areValuesEqual: areValuesEqual ? areValuesEqual : (rowA, rowB) => value(rowA) === value(rowB)\n };\n}\nfunction arrayColumn({ array, schema, valueKind }) {\n const rowCount = array.length;\n const defaultValue = schema.T;\n const value = schema.valueType === 'str'\n ? schema.transform === 'lowercase'\n ? row => { const v = array[row]; return typeof v === 'string' ? v.toLowerCase() : `${v !== null && v !== void 0 ? v : defaultValue}`.toLowerCase(); }\n : schema.transform === 'uppercase'\n ? row => { const v = array[row]; return typeof v === 'string' ? v.toUpperCase() : `${v !== null && v !== void 0 ? v : defaultValue}`.toUpperCase(); }\n : row => { const v = array[row]; return typeof v === 'string' ? v : `${v !== null && v !== void 0 ? v : defaultValue}`; }\n : row => array[row];\n const isTyped = ColumnHelpers.isTypedArray(array);\n return {\n schema: schema,\n __array: array,\n isDefined: true,\n rowCount,\n value,\n valueKind: valueKind ? valueKind : row => 0 /* Column.ValueKinds.Present */,\n toArray: schema.valueType === 'str'\n ? schema.transform === 'lowercase'\n ? params => {\n const { start, end } = ColumnHelpers.getArrayBounds(rowCount, params);\n const ret = new (params && typeof params.array !== 'undefined' ? params.array : array.constructor)(end - start);\n for (let i = 0, _i = end - start; i < _i; i++) {\n const v = array[start + i];\n ret[i] = typeof v === 'string' ? v.toLowerCase() : `${v !== null && v !== void 0 ? v : defaultValue}`.toLowerCase();\n }\n return ret;\n }\n : schema.transform === 'uppercase'\n ? params => {\n const { start, end } = ColumnHelpers.getArrayBounds(rowCount, params);\n const ret = new (params && typeof params.array !== 'undefined' ? params.array : array.constructor)(end - start);\n for (let i = 0, _i = end - start; i < _i; i++) {\n const v = array[start + i];\n ret[i] = typeof v === 'string' ? v.toUpperCase() : `${v !== null && v !== void 0 ? v : defaultValue}`.toUpperCase();\n }\n return ret;\n }\n : params => {\n const { start, end } = ColumnHelpers.getArrayBounds(rowCount, params);\n const ret = new (params && typeof params.array !== 'undefined' ? params.array : array.constructor)(end - start);\n for (let i = 0, _i = end - start; i < _i; i++) {\n const v = array[start + i];\n ret[i] = typeof v === 'string' ? v : `${v !== null && v !== void 0 ? v : defaultValue}`;\n }\n return ret;\n }\n : isTyped\n ? params => ColumnHelpers.typedArrayWindow(array, params)\n : params => {\n const { start, end } = ColumnHelpers.getArrayBounds(rowCount, params);\n if (start === 0 && end === array.length)\n return array;\n const ret = new (params && typeof params.array !== 'undefined' ? params.array : array.constructor)(end - start);\n for (let i = 0, _i = end - start; i < _i; i++)\n ret[i] = array[start + i];\n return ret;\n },\n areValuesEqual: (rowA, rowB) => array[rowA] === array[rowB]\n };\n}\nfunction windowColumn(column, start, end) {\n if (!column.isDefined)\n return Column.Undefined(end - start, column.schema);\n if (start === 0 && end === column.rowCount)\n return column;\n if (!!column.__array && ColumnHelpers.isTypedArray(column.__array))\n return windowTyped(column, start, end);\n return windowFull(column, start, end);\n}\nfunction windowTyped(c, start, end) {\n const array = ColumnHelpers.typedArrayWindow(c.__array, { start, end });\n const vk = c.valueKind;\n return arrayColumn({ array, schema: c.schema, valueKind: row => vk(start + row) });\n}\nfunction windowFull(c, start, end) {\n const v = c.value, vk = c.valueKind, ave = c.areValuesEqual;\n const value = start === 0 ? v : row => v(row + start);\n const rowCount = end - start;\n return {\n schema: c.schema,\n __array: void 0,\n isDefined: c.isDefined,\n rowCount,\n value,\n valueKind: start === 0 ? vk : row => vk(row + start),\n toArray: params => {\n const { array } = ColumnHelpers.createArray(rowCount, params);\n for (let i = 0, _i = array.length; i < _i; i++)\n array[i] = v(i + start);\n return array;\n },\n areValuesEqual: start === 0 ? ave : (rowA, rowB) => ave(rowA + start, rowB + start)\n };\n}\nfunction isIdentity(map, rowCount) {\n if (map.length !== rowCount)\n return false;\n for (let i = 0, _i = map.length; i < _i; i++) {\n if (map[i] !== i)\n return false;\n }\n return true;\n}\nfunction columnView(c, map, checkIdentity) {\n if (c.rowCount === 0)\n return c;\n if (checkIdentity && isIdentity(map, c.rowCount))\n return c;\n if (!!c.__array && typeof c.value(0) === typeof c.__array[0])\n return arrayView(c, map);\n return viewFull(c, map);\n}\nfunction arrayView(c, map) {\n const array = c.__array;\n const ret = new array.constructor(map.length);\n for (let i = 0, _i = map.length; i < _i; i++)\n ret[i] = array[map[i]];\n const vk = c.valueKind;\n return arrayColumn({ array: ret, schema: c.schema, valueKind: row => vk(map[row]) });\n}\nfunction viewFull(c, map) {\n const v = c.value, vk = c.valueKind, ave = c.areValuesEqual;\n const value = row => v(map[row]);\n const rowCount = map.length;\n return {\n schema: c.schema,\n __array: void 0,\n isDefined: c.isDefined,\n rowCount,\n value,\n valueKind: row => vk(map[row]),\n toArray: params => {\n const { array } = ColumnHelpers.createArray(rowCount, params);\n for (let i = 0, _i = array.length; i < _i; i++)\n array[i] = v(map[i]);\n return array;\n },\n areValuesEqual: (rowA, rowB) => ave(map[rowA], map[rowB])\n };\n}\nfunction mapToArrayImpl(c, f, ctor) {\n const ret = new ctor(c.rowCount);\n for (let i = 0, _i = c.rowCount; i < _i; i++)\n ret[i] = f(c.value(i));\n return ret;\n}\nfunction areColumnsEqual(a, b) {\n if (a === b)\n return true;\n if (a.rowCount !== b.rowCount || a.isDefined !== b.isDefined || a.schema.valueType !== b.schema.valueType)\n return false;\n if (!!a.__array && !!b.__array)\n return areArraysEqual(a, b);\n return areValuesEqual(a, b);\n}\nfunction areArraysEqual(a, b) {\n const xs = a.__array, ys = b.__array;\n for (let i = 0, _i = a.rowCount; i < _i; i++) {\n if (xs[i] !== ys[i])\n return false;\n }\n return true;\n}\nfunction areValuesEqual(a, b) {\n const va = a.value, vb = b.value;\n for (let i = 0, _i = a.rowCount; i < _i; i++) {\n if (va(i) !== vb(i))\n return false;\n }\n return true;\n}\nfunction columnIndicesOf(c, test) {\n const ret = [], v = c.value;\n for (let i = 0, _i = c.rowCount; i < _i; i++) {\n if (test(v(i)))\n ret[ret.length] = i;\n }\n return ret;\n}\n","/**\n * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n */\nvar BitFlags;\n(function (BitFlags) {\n function create(flags) { return flags; }\n BitFlags.create = create;\n function has(flags, flag) { return (flags & flag) !== 0; }\n BitFlags.has = has;\n /** toCheck must be non-zero */\n function hasAll(flags, toCheck) { return !!toCheck && (flags & toCheck) === toCheck; }\n BitFlags.hasAll = hasAll;\n})(BitFlags || (BitFlags = {}));\nexport { BitFlags };\n","/**\n * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * Adapted from CIFTools.js (https://github.com/dsehnal/CIFTools.js)\n *\n * @author David Sehnal \n */\nvar StringBuilder;\n(function (StringBuilder) {\n function create(chunkCapacity = 512) {\n return {\n current: [],\n offset: 0,\n capacity: chunkCapacity,\n chunks: []\n };\n }\n StringBuilder.create = create;\n function getString(builder) {\n if (!builder.chunks.length) {\n if (builder.current.length === builder.offset)\n return builder.current.join('');\n return builder.current.splice(0, builder.offset).join('');\n }\n if (builder.offset > 0) {\n builder.chunks[builder.chunks.length] = builder.current.length === builder.offset\n ? builder.current.join('')\n : builder.current.slice(0, builder.offset).join('');\n }\n return builder.chunks.join('');\n }\n StringBuilder.getString = getString;\n function getSize(builder) {\n let size = 0;\n for (const c of builder.chunks)\n size += c.length;\n for (let i = 0; i < builder.offset; i++)\n size += builder.current[i].length;\n return size;\n }\n StringBuilder.getSize = getSize;\n function getChunks(builder) {\n if (builder.offset > 0) {\n if (builder.current.length === builder.offset)\n builder.chunks[builder.chunks.length] = builder.current.join('');\n else\n builder.chunks[builder.chunks.length] = builder.current.slice(0, builder.offset).join('');\n builder.offset = 0;\n }\n return builder.chunks;\n }\n StringBuilder.getChunks = getChunks;\n const __paddingSpaces = [];\n (function () {\n let s = '';\n for (let i = 0; i < 512 /* PaddingSpaces.Count */; i++) {\n __paddingSpaces[i] = s;\n s = s + ' ';\n }\n })();\n function newline(builder) {\n writeSafe(builder, '\\n');\n }\n StringBuilder.newline = newline;\n function whitespace(builder, len) {\n if (len > 0)\n writeSafe(builder, __paddingSpaces[len]);\n }\n StringBuilder.whitespace = whitespace;\n function whitespace1(builder) {\n writeSafe(builder, ' ');\n }\n StringBuilder.whitespace1 = whitespace1;\n function write(builder, val) {\n if (!val)\n return;\n if (builder.offset === builder.capacity) {\n builder.chunks[builder.chunks.length] = builder.current.join('');\n builder.offset = 0;\n }\n builder.current[builder.offset++] = val;\n }\n StringBuilder.write = write;\n /** Write without check. */\n function writeSafe(builder, val) {\n if (builder.offset === builder.capacity) {\n builder.chunks[builder.chunks.length] = builder.current.join('');\n builder.offset = 0;\n }\n builder.current[builder.offset++] = val;\n }\n StringBuilder.writeSafe = writeSafe;\n function writePadLeft(builder, val, totalWidth) {\n if (!val) {\n whitespace(builder, totalWidth);\n return;\n }\n const padding = totalWidth - val.length;\n whitespace(builder, padding);\n writeSafe(builder, val);\n }\n StringBuilder.writePadLeft = writePadLeft;\n function writePadRight(builder, val, totalWidth) {\n if (!val) {\n whitespace(builder, totalWidth);\n return;\n }\n const padding = totalWidth - val.length;\n writeSafe(builder, val);\n whitespace(builder, padding);\n }\n StringBuilder.writePadRight = writePadRight;\n function writeInteger(builder, val) {\n writeSafe(builder, '' + val);\n }\n StringBuilder.writeInteger = writeInteger;\n function writeIntegerAndSpace(builder, val) {\n writeSafe(builder, '' + val + ' ');\n }\n StringBuilder.writeIntegerAndSpace = writeIntegerAndSpace;\n function writeIntegerPadLeft(builder, val, totalWidth) {\n const s = '' + val;\n const padding = totalWidth - s.length;\n whitespace(builder, padding);\n writeSafe(builder, s);\n }\n StringBuilder.writeIntegerPadLeft = writeIntegerPadLeft;\n function writeIntegerPadRight(builder, val, totalWidth) {\n const s = '' + val;\n const padding = totalWidth - s.length;\n writeSafe(builder, s);\n whitespace(builder, padding);\n }\n StringBuilder.writeIntegerPadRight = writeIntegerPadRight;\n /**\n * @example writeFloat(123.2123, 100) -- 2 decim\n */\n function writeFloat(builder, val, precisionMultiplier) {\n writeSafe(builder, '' + Math.round(precisionMultiplier * val) / precisionMultiplier);\n }\n StringBuilder.writeFloat = writeFloat;\n function writeFloatPadLeft(builder, val, precisionMultiplier, totalWidth) {\n const s = '' + Math.round(precisionMultiplier * val) / precisionMultiplier;\n const padding = totalWidth - s.length;\n whitespace(builder, padding);\n writeSafe(builder, s);\n }\n StringBuilder.writeFloatPadLeft = writeFloatPadLeft;\n function writeFloatPadRight(builder, val, precisionMultiplier, totalWidth) {\n const s = '' + Math.round(precisionMultiplier * val) / precisionMultiplier;\n const padding = totalWidth - s.length;\n writeSafe(builder, s);\n whitespace(builder, padding);\n }\n StringBuilder.writeFloatPadRight = writeFloatPadRight;\n})(StringBuilder || (StringBuilder = {}));\nexport { StringBuilder };\n","/**\n * Copyright (c) 2017-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n * @author Alexander Rose \n *\n * based in part on https://github.com/dsehnal/CIFTools.js\n */\n/**\n * Efficient integer and float parsers.\n *\n * For the purposes of parsing numbers from the mmCIF data representations,\n * up to 4 times faster than JS parseInt/parseFloat.\n */\nexport function parseIntSkipLeadingWhitespace(str, start, end) {\n while (start < end && str.charCodeAt(start) === 32)\n start++;\n return parseInt(str, start, end);\n}\nexport function parseInt(str, start, end) {\n let _start = start, ret = 0, neg = 1;\n if (str.charCodeAt(_start) === 45 /* - */) {\n neg = -1;\n ++_start;\n }\n else if (str.charCodeAt(_start) === 43 /* + */) {\n ++_start;\n }\n for (; _start < end; _start++) {\n const c = str.charCodeAt(_start) - 48;\n if (c > 9 || c < 0)\n return (neg * ret) | 0;\n else\n ret = (10 * ret + c) | 0;\n }\n return neg * ret;\n}\nfunction parseScientific(main, str, start, end) {\n // handle + in '1e+1' separately.\n if (str.charCodeAt(start) === 43 /* + */)\n start++;\n return main * Math.pow(10.0, parseInt(str, start, end));\n}\nexport function parseFloatSkipLeadingWhitespace(str, start, end) {\n while (start < end && str.charCodeAt(start) === 32)\n start++;\n return parseFloat(str, start, end);\n}\nexport function parseFloat(str, start, end) {\n let _start = start, neg = 1.0, ret = 0.0, point = 0.0, div = 1.0;\n if (str.charCodeAt(_start) === 45 /* - */) {\n neg = -1;\n ++_start;\n }\n else if (str.charCodeAt(_start) === 43 /* + */) {\n ++_start;\n }\n while (_start < end) {\n let c = str.charCodeAt(_start) - 48;\n if (c >= 0 && c < 10) {\n ret = ret * 10 + c;\n ++_start;\n }\n else if (c === -2) { // .\n ++_start;\n while (_start < end) {\n c = str.charCodeAt(_start) - 48;\n if (c >= 0 && c < 10) {\n point = 10.0 * point + c;\n div = 10.0 * div;\n ++_start;\n }\n else if (c === 53 || c === 21) { // 'e'/'E'\n return parseScientific(neg * (ret + point / div), str, _start + 1, end);\n }\n else {\n return neg * (ret + point / div);\n }\n }\n return neg * (ret + point / div);\n }\n else if (c === 53 || c === 21) { // 'e'/'E'\n return parseScientific(neg * ret, str, _start + 1, end);\n }\n else {\n break;\n }\n }\n return neg * ret;\n}\nexport const NumberType = {\n Int: 0 /* NumberTypes.Int */,\n Float: 1 /* NumberTypes.Float */,\n Scientific: 2 /* NumberTypes.Scientific */,\n NaN: 3 /* NumberTypes.NaN */\n};\nfunction isInt(str, start, end) {\n if (str.charCodeAt(start) === 45 /* - */) {\n start++;\n }\n for (; start < end; start++) {\n const c = str.charCodeAt(start) - 48;\n if (c > 9 || c < 0)\n return false;\n }\n return true;\n}\n// TODO: check for \"scientific integers?\"\nfunction getNumberTypeScientific(str, start, end) {\n // handle + in '1e+1' separately.\n if (str.charCodeAt(start) === 43 /* + */)\n start++;\n return isInt(str, start, end) ? 2 /* NumberTypes.Scientific */ : 3 /* NumberTypes.NaN */;\n}\n/** The whole range must match, otherwise returns NaN */\nexport function getNumberType(str) {\n let start = 0;\n const end = str.length;\n if (str.charCodeAt(start) === 45) { // -\n ++start;\n }\n // string is . or -.\n if (str.charCodeAt(start) === 46 && end - start === 1) {\n return 3 /* NumberTypes.NaN */;\n }\n while (start < end) {\n let c = str.charCodeAt(start) - 48;\n if (c >= 0 && c < 10) {\n ++start;\n }\n else if (c === -2) { // .\n ++start;\n let hasDigit = false;\n while (start < end) {\n c = str.charCodeAt(start) - 48;\n if (c >= 0 && c < 10) {\n hasDigit = true;\n ++start;\n }\n else if (c === 53 || c === 21) { // 'e'/'E'\n return getNumberTypeScientific(str, start + 1, end);\n }\n else {\n return 3 /* NumberTypes.NaN */;\n }\n }\n return hasDigit ? 1 /* NumberTypes.Float */ : 0 /* NumberTypes.Int */;\n }\n else if (c === 53 || c === 21) { // 'e'/'E'\n if (start === 0 || start === 1 && str.charCodeAt(0) === 45) {\n return 3 /* NumberTypes.NaN */; // string starts with e/E or -e/-E\n }\n return getNumberTypeScientific(str, start + 1, end);\n }\n else {\n break;\n }\n }\n return start === end ? 0 /* NumberTypes.Int */ : 3 /* NumberTypes.NaN */;\n}\n","/**\n * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n */\nexport function arrayLess(arr, i, j) {\n return arr[i] - arr[j];\n}\nexport function arraySwap(arr, i, j) {\n const temp = arr[i];\n arr[i] = arr[j];\n arr[j] = temp;\n}\nfunction medianPivotIndex(data, cmp, l, r) {\n const m = (l + r) >> 1;\n if (cmp(data, l, r) > 0)\n return cmp(data, l, m) > 0 ? cmp(data, m, r) > 0 ? m : r : l;\n else\n return cmp(data, r, m) > 0 ? cmp(data, m, l) > 0 ? m : l : r;\n}\nfunction partition(ctx, l, r) {\n const { cmp, swap, data, parts } = ctx;\n let equals = l + 1, tail = r;\n // move the median to the 1st spot\n swap(data, l, medianPivotIndex(data, cmp, l, r));\n while (cmp(data, tail, l) > 0) {\n --tail;\n }\n for (let i = l + 1; i <= tail; i++) {\n const c = cmp(data, i, l);\n if (c > 0) {\n swap(data, i, tail);\n --tail;\n while (cmp(data, tail, l) > 0) {\n --tail;\n }\n i--;\n }\n else if (c === 0) {\n swap(data, i, equals);\n equals++;\n }\n }\n // move the medians to the correct spots\n for (let i = l; i < equals; i++) {\n swap(data, i, l + tail - i);\n }\n parts[0] = tail - equals + l + 1;\n parts[1] = tail;\n}\nfunction insertionSort({ data, cmp, swap }, start, end) {\n for (let i = start + 1; i <= end; i++) {\n let j = i - 1;\n while (j >= start && cmp(data, j, j + 1) > 0) {\n swap(data, j, j + 1);\n j = j - 1;\n }\n }\n}\nfunction quickSort(ctx, low, high) {\n const { parts } = ctx;\n while (low < high) {\n if (high - low < 16) {\n insertionSort(ctx, low, high);\n return;\n }\n partition(ctx, low, high);\n const li = parts[0], ri = parts[1];\n if (li - low < high - ri) {\n quickSort(ctx, low, li - 1);\n low = ri + 1;\n }\n else {\n quickSort(ctx, ri + 1, high);\n high = li - 1;\n }\n }\n}\nfunction partitionArrayAsc(data, parts, l, r) {\n let equals = l + 1, tail = r;\n // move the median to the 1st spot\n arraySwap(data, l, medianPivotIndex(data, arrayLess, l, r));\n const pivot = data[l];\n while (data[tail] > pivot) {\n --tail;\n }\n for (let i = l + 1; i <= tail; i++) {\n const v = data[i];\n if (v > pivot) {\n arraySwap(data, i, tail);\n --tail;\n while (data[tail] > pivot) {\n --tail;\n }\n i--;\n }\n else if (v === pivot) {\n arraySwap(data, i, equals);\n ++equals;\n }\n }\n // move all medians to the correct spots\n for (let i = l; i < equals; i++) {\n arraySwap(data, i, l + tail - i);\n }\n parts[0] = tail - equals + l + 1;\n parts[1] = tail;\n}\nfunction insertionSortArrayAsc(data, start, end) {\n for (let i = start + 1; i <= end; i++) {\n const key = data[i];\n let j = i - 1;\n while (j >= start && data[j] > key) {\n data[j + 1] = data[j];\n j = j - 1;\n }\n data[j + 1] = key;\n }\n}\nfunction quickSortArrayAsc(data, parts, low, high) {\n while (low < high) {\n if (high - low < 16) {\n insertionSortArrayAsc(data, low, high);\n return;\n }\n partitionArrayAsc(data, parts, low, high);\n const li = parts[0], ri = parts[1];\n if (li - low < high - ri) {\n quickSortArrayAsc(data, parts, low, li - 1);\n low = ri + 1;\n }\n else {\n quickSortArrayAsc(data, parts, ri + 1, high);\n high = li - 1;\n }\n }\n}\nexport function sortArray(data, cmp = arrayLess) {\n return sortArrayRange(data, 0, data.length, cmp);\n}\nexport function sortArrayRange(data, start, end, cmp = arrayLess) {\n if (cmp === arrayLess)\n quickSortArrayAsc(data, [0, 0], start, end - 1);\n else\n quickSort({ data, cmp, swap: arraySwap, parts: [0, 0] }, start, end - 1);\n return data;\n}\nexport function sort(data, start, end, cmp, swap) {\n const ctx = { data, cmp, swap, parts: [0, 0] };\n quickSort(ctx, start, end - 1);\n return data;\n}\n","/**\n * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n */\nconst now = (function () {\n if (typeof window !== 'undefined' && window.performance) {\n const perf = window.performance;\n return () => perf.now();\n }\n else if (typeof process !== 'undefined' && process.hrtime !== 'undefined' && typeof process.hrtime === 'function') {\n return () => {\n const t = process.hrtime();\n return t[0] * 1000 + t[1] / 1000000;\n };\n }\n else if (Date.now) {\n return () => Date.now();\n }\n else {\n return () => +new Date();\n }\n}());\nfunction formatTimespan(t, includeMsZeroes = true) {\n if (isNaN(t))\n return 'n/a';\n const h = Math.floor(t / (60 * 60 * 1000)), m = Math.floor(t / (60 * 1000) % 60), s = Math.floor(t / 1000 % 60);\n let ms = Math.floor(t % 1000).toString();\n while (ms.length < 3)\n ms = '0' + ms;\n while (!includeMsZeroes && ms.length > 1 && ms[ms.length - 1] === '0')\n ms = ms.substr(0, ms.length - 1);\n if (h > 0)\n return `${h}h${m}m${s}.${ms}s`;\n if (m > 0)\n return `${m}m${s}.${ms}s`;\n if (s > 0)\n return `${s}.${ms}s`;\n return `${t.toFixed(0)}ms`;\n}\nexport { now, formatTimespan };\n","/**\n * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n */\nimport { now } from '../mol-util/now';\nvar UUID;\n(function (UUID) {\n const _btoa = typeof btoa !== 'undefined' ? btoa : (s) => Buffer.from(s).toString('base64');\n const chars = [];\n /** Creates a 22 characters 'base64' encoded UUID */\n function create22() {\n let d = (+new Date()) + now();\n for (let i = 0; i < 16; i++) {\n chars[i] = String.fromCharCode((d + Math.random() * 0xff) % 0xff | 0);\n d = Math.floor(d / 0xff);\n }\n return _btoa(chars.join('')).replace(/\\+/g, '-').replace(/\\//g, '_').substr(0, 22);\n }\n UUID.create22 = create22;\n function createv4() {\n let d = (+new Date()) + now();\n const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n const r = (d + Math.random() * 16) % 16 | 0;\n d = Math.floor(d / 16);\n return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);\n });\n return uuid;\n }\n UUID.createv4 = createv4;\n function is(x) {\n return typeof x === 'string';\n }\n UUID.is = is;\n})(UUID || (UUID = {}));\nexport { UUID };\n","/**\n * Copyright (c) 2017 Mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n */\n// TODO check if the removal of FastSet and the removal of the context object for forEach\n// have any performance implications\nfunction _ascSort(a, b) {\n return a - b;\n}\nexport function sortAsc(array) {\n Array.prototype.sort.call(array, _ascSort);\n return array;\n}\nvar Mask;\n(function (Mask) {\n class EmptyMask {\n has(i) { return false; }\n forEach(f, ctx) { return ctx; }\n constructor() {\n this.size = 0;\n }\n }\n class SingletonMask {\n has(i) { return i === this.idx; }\n forEach(f, ctx) { f(this.idx, ctx); return ctx; }\n constructor(idx) {\n this.idx = idx;\n this.size = 1;\n }\n }\n class BitMask {\n has(i) { return i < this.length && !!this.mask[i]; }\n _forEach(f, ctx) {\n for (let i = 0; i < this.length; i++) {\n if (this.mask[i])\n f(i, ctx);\n }\n }\n forEach(f, ctx) {\n this._forEach(f, ctx);\n return ctx;\n }\n constructor(mask, size) {\n this.mask = mask;\n this.size = size;\n this.length = mask.length;\n }\n }\n class AllMask {\n has(i) { return true; }\n _forEach(f, ctx) {\n for (let i = 0; i < this.size; i++) {\n f(i, ctx);\n }\n }\n forEach(f, ctx) {\n this._forEach(f, ctx);\n return ctx;\n }\n constructor(size) {\n this.size = size;\n }\n }\n class SetMask {\n has(i) { return this.set.has(i); }\n _forEach(f, ctx) {\n for (const idx of this.flatten()) {\n f(idx, ctx);\n }\n }\n flatten() {\n if (this._flat)\n return this._flat;\n const indices = new Int32Array(this.size);\n let offset = 0;\n this.set.forEach(i => indices[offset++] = i);\n sortAsc(indices);\n this._flat = indices;\n return this._flat;\n }\n forEach(f, ctx) {\n this._forEach(f, ctx);\n return ctx;\n }\n constructor(set) {\n this.set = set;\n this._flat = void 0;\n this.size = set.size;\n }\n }\n function always(size) { return new AllMask(size); }\n Mask.always = always;\n Mask.never = new EmptyMask();\n function ofSet(set) {\n return new SetMask(set);\n }\n Mask.ofSet = ofSet;\n function singleton(i) {\n return new SingletonMask(i);\n }\n Mask.singleton = singleton;\n function ofUniqueIndices(indices) {\n const len = indices.length;\n if (len === 0)\n return new EmptyMask();\n if (len === 1)\n return new SingletonMask(indices[0]);\n let max = 0;\n for (const i of indices) {\n if (i > max)\n max = i;\n }\n if (len === max)\n return new AllMask(len);\n const f = len / max;\n if (f < 1 / 12) {\n const set = new Set();\n for (const i of indices)\n set.add(i);\n return new SetMask(set);\n }\n const mask = new Int8Array(max + 1);\n for (const i of indices) {\n mask[i] = 1;\n }\n return new BitMask(mask, indices.length);\n }\n Mask.ofUniqueIndices = ofUniqueIndices;\n function ofMask(mask, size) {\n return new BitMask(mask, size);\n }\n Mask.ofMask = ofMask;\n function hasAny(mask, xs) {\n for (const x of xs) {\n if (mask.has(x))\n return true;\n }\n return false;\n }\n Mask.hasAny = hasAny;\n function complement(mask, against) {\n let count = 0;\n let max = 0;\n against.forEach(i => {\n if (!mask.has(i)) {\n count++;\n if (i > max)\n max = i;\n }\n });\n if (count / max < 1 / 12) {\n // set based\n const set = new Set();\n against.forEach(i => {\n if (!mask.has(i)) {\n set.add(i);\n }\n });\n return ofSet(set);\n }\n else {\n // mask based\n const target = new Uint8Array(max + 1);\n against.forEach(i => {\n if (!mask.has(i)) {\n target[i] = 1;\n }\n });\n return ofMask(target, count);\n }\n }\n Mask.complement = complement;\n})(Mask || (Mask = {}));\nexport { Mask };\n","/**\n * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n * @author Alexander Rose \n */\nimport { idFactory } from './id-factory';\nvar ValueRef;\n(function (ValueRef) {\n function create(ref) { return { ref }; }\n ValueRef.create = create;\n function set(ref, value) { ref.ref = value; return ref; }\n ValueRef.set = set;\n})(ValueRef || (ValueRef = {}));\nconst getNextId = idFactory(0, 0x7FFFFFFF);\nvar ValueBox;\n(function (ValueBox) {\n function create(value, metadata) {\n return { id: getNextId(), version: 0, value, metadata: metadata };\n }\n ValueBox.create = create;\n /** The box.metadata is carried over from the old box */\n function withValue(box, value) {\n return { id: box.id, version: box.version + 1, value, metadata: box.metadata };\n }\n ValueBox.withValue = withValue;\n})(ValueBox || (ValueBox = {}));\nvar ValueCell;\n(function (ValueCell) {\n function create(value, metadata) {\n return ValueRef.create(ValueBox.create(value, metadata));\n }\n ValueCell.create = create;\n /** The box.metadata is carried over from the old box */\n function update(cell, value) {\n return ValueRef.set(cell, ValueBox.withValue(cell.ref, value));\n }\n ValueCell.update = update;\n function set(cell, box) {\n return ValueRef.set(cell, box);\n }\n ValueCell.set = set;\n /** Updates the cell if the value is has changed, comparing by reference */\n function updateIfChanged(cell, value) {\n return cell.ref.value !== value ? update(cell, value) : cell;\n }\n ValueCell.updateIfChanged = updateIfChanged;\n})(ValueCell || (ValueCell = {}));\nexport { ValueRef, ValueBox, ValueCell };\n","/**\n * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author Alexander Rose \n */\n/** Builds id function returning ids within [firstId, maxId) */\nexport function idFactory(firstId = 0, maxId = Number.MAX_SAFE_INTEGER) {\n let _nextId = firstId;\n return () => {\n const ret = _nextId;\n _nextId = (_nextId + 1) % maxId;\n return ret;\n };\n}\n","/**\n * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n */\nimport { Column } from './column';\nimport { sortArray } from '../util/sort';\nimport { StringBuilder } from '../../mol-util';\n/** An immutable table */\nvar Table;\n(function (Table) {\n function is(t) {\n return t && typeof t._rowCount === 'number' && !!t._columns && !!t._schema;\n }\n Table.is = is;\n function pickColumns(schema, table, guard = {}) {\n const ret = Object.create(null);\n const keys = Object.keys(schema);\n ret._rowCount = table._rowCount;\n ret._columns = keys;\n ret._schema = schema;\n for (const k of keys) {\n if (!!table[k])\n ret[k] = table[k];\n else if (!!guard[k])\n ret[k] = guard[k];\n else\n throw Error(`Cannot find column '${k}'.`);\n }\n return ret;\n }\n Table.pickColumns = pickColumns;\n function ofColumns(schema, columns) {\n const _columns = Object.keys(columns);\n const _rowCount = columns[_columns[0]].rowCount;\n return { _rowCount, _columns, _schema: schema, ...columns };\n }\n Table.ofColumns = ofColumns;\n function ofPartialColumns(schema, partialColumns, rowCount) {\n const ret = Object.create(null);\n const columns = Object.keys(schema);\n ret._rowCount = rowCount;\n ret._columns = columns;\n ret._schema = schema;\n for (const k of columns) {\n if (k in partialColumns)\n ret[k] = partialColumns[k];\n else\n ret[k] = Column.Undefined(rowCount, schema[k]);\n }\n return ret;\n }\n Table.ofPartialColumns = ofPartialColumns;\n function ofUndefinedColumns(schema, rowCount) {\n const ret = Object.create(null);\n const columns = Object.keys(schema);\n ret._rowCount = rowCount;\n ret._columns = columns;\n ret._schema = schema;\n for (const k of columns) {\n ret[k] = Column.Undefined(rowCount, schema[k]);\n }\n return ret;\n }\n Table.ofUndefinedColumns = ofUndefinedColumns;\n function ofRows(schema, rows) {\n const ret = Object.create(null);\n const rowCount = rows.length;\n const columns = Object.keys(schema);\n ret._rowCount = rowCount;\n ret._columns = columns;\n ret._schema = schema;\n for (const k of columns) {\n ret[k] = Column.ofLambda({\n rowCount,\n schema: schema[k],\n value: r => rows[r][k],\n valueKind: r => typeof rows[r][k] === 'undefined' ? 1 /* Column.ValueKinds.NotPresent */ : 0 /* Column.ValueKinds.Present */\n });\n }\n return ret;\n }\n Table.ofRows = ofRows;\n function ofArrays(schema, arrays) {\n var _a;\n const ret = Object.create(null);\n const columns = Object.keys(schema);\n ret._rowCount = 0;\n ret._columns = columns;\n ret._schema = schema;\n for (const k of columns) {\n if (typeof arrays[k] !== 'undefined') {\n ret[k] = Column.ofArray({ array: arrays[k], schema: schema[k] });\n ret._rowCount = (_a = arrays[k]) === null || _a === void 0 ? void 0 : _a.length;\n }\n else {\n ret[k] = Column.Undefined(ret._rowCount, schema[k]);\n }\n }\n return ret;\n }\n Table.ofArrays = ofArrays;\n function view(table, schema, view) {\n const ret = Object.create(null);\n const columns = Object.keys(schema);\n ret._rowCount = view.length;\n ret._columns = columns;\n ret._schema = schema;\n for (const k of columns) {\n ret[k] = Column.view(table[k], view);\n }\n return ret;\n }\n Table.view = view;\n function pick(table, schema, test) {\n const _view = [];\n for (let i = 0, il = table._rowCount; i < il; ++i) {\n if (test(i))\n _view.push(i);\n }\n return view(table, schema, _view);\n }\n Table.pick = pick;\n function window(table, schema, start, end) {\n if (start === 0 && end === table._rowCount)\n return table;\n const ret = Object.create(null);\n const columns = Object.keys(schema);\n ret._rowCount = end - start;\n ret._columns = columns;\n ret._schema = schema;\n for (const k of columns) {\n ret[k] = Column.window(table[k], start, end);\n }\n return ret;\n }\n Table.window = window;\n function concat(tables, schema) {\n const ret = Object.create(null);\n const columns = Object.keys(schema);\n ret._rowCount = 0;\n for (const table of tables) {\n ret._rowCount += table._rowCount;\n }\n const arrays = {};\n for (const column of columns) {\n arrays[column] = new Array(ret._rowCount);\n }\n ret._columns = columns;\n ret._schema = schema;\n let offset = 0;\n for (const table of tables) {\n for (const k of columns) {\n Column.copyToArray(table[k], arrays[k], offset);\n }\n offset += table._rowCount;\n }\n for (const k of columns) {\n ret[k] = Column.ofArray({ array: arrays[k], schema: schema[k] });\n }\n return ret;\n }\n Table.concat = concat;\n function columnToArray(table, name, array) {\n table[name] = Column.asArrayColumn(table[name], array);\n }\n Table.columnToArray = columnToArray;\n /** Sort and return a new table */\n function sort(table, cmp) {\n const indices = new Int32Array(table._rowCount);\n for (let i = 0, _i = indices.length; i < _i; i++)\n indices[i] = i;\n sortArray(indices, (_, i, j) => cmp(i, j));\n let isIdentity = true;\n for (let i = 0, _i = indices.length; i < _i; i++) {\n if (indices[i] !== i) {\n isIdentity = false;\n break;\n }\n }\n if (isIdentity)\n return table;\n const ret = Object.create(null);\n ret._rowCount = table._rowCount;\n ret._columns = table._columns;\n ret._schema = table._schema;\n for (const c of table._columns) {\n ret[c] = Column.view(table[c], indices, false);\n }\n return ret;\n }\n Table.sort = sort;\n function areEqual(a, b) {\n if (a._rowCount !== b._rowCount)\n return false;\n if (a._columns.length !== b._columns.length)\n return false;\n for (const c of a._columns) {\n if (!b[c])\n return false;\n }\n for (const c of a._columns) {\n if (!Column.areEqual(a[c], b[c]))\n return false;\n }\n return true;\n }\n Table.areEqual = areEqual;\n /** Allocate a new object with the given row values. */\n function getRow(table, index) {\n const row = Object.create(null);\n const { _columns: cols } = table;\n for (let i = 0; i < cols.length; i++) {\n const c = cols[i];\n row[c] = table[c].value(index);\n }\n return row;\n }\n Table.getRow = getRow;\n /** Pick the first row for which `test` evaluates to true */\n function pickRow(table, test) {\n for (let i = 0, il = table._rowCount; i < il; ++i) {\n if (test(i))\n return getRow(table, i);\n }\n }\n Table.pickRow = pickRow;\n function getRows(table) {\n const ret = [];\n const { _rowCount: c } = table;\n for (let i = 0; i < c; i++) {\n ret[i] = getRow(table, i);\n }\n return ret;\n }\n Table.getRows = getRows;\n function toArrays(table) {\n const arrays = {};\n const { _columns } = table;\n for (let i = 0; i < _columns.length; i++) {\n const c = _columns[i];\n arrays[c] = table[c].toArray();\n }\n return arrays;\n }\n Table.toArrays = toArrays;\n function formatToString(table) {\n const sb = StringBuilder.create();\n const { _columns: cols, _rowCount } = table;\n let headerLength = 1;\n StringBuilder.write(sb, '|');\n for (let i = 0; i < cols.length; i++) {\n StringBuilder.write(sb, cols[i]);\n StringBuilder.write(sb, '|');\n headerLength += cols[i].length + 1;\n }\n StringBuilder.newline(sb);\n StringBuilder.write(sb, new Array(headerLength + 1).join('-'));\n StringBuilder.newline(sb);\n for (let r = 0; r < _rowCount; r++) {\n StringBuilder.write(sb, '|');\n for (let i = 0; i < cols.length; i++) {\n const c = table[cols[i]];\n if (c.valueKind(r) === 0 /* Column.ValueKinds.Present */) {\n StringBuilder.write(sb, c.value(r));\n StringBuilder.write(sb, '|');\n }\n else {\n StringBuilder.write(sb, '.|');\n }\n }\n StringBuilder.newline(sb);\n }\n return StringBuilder.getString(sb);\n }\n Table.formatToString = formatToString;\n})(Table || (Table = {}));\nexport { Table };\n","/**\n * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n */\nimport { Table } from './table';\nvar Database;\n(function (Database) {\n function ofTables(name, schema, tables) {\n const keys = Object.keys(tables);\n const ret = Object.create(null);\n const tableNames = [];\n ret._name = name;\n ret._tableNames = tableNames;\n ret._schema = schema;\n for (const k of keys) {\n if (!Table.is(tables[k]))\n continue;\n ret[k] = tables[k];\n tableNames[tableNames.length] = k;\n }\n return ret;\n }\n Database.ofTables = ofTables;\n function getTablesAsRows(database) {\n const ret = {};\n for (const k of database._tableNames) {\n ret[k] = Table.getRows(database[k]);\n }\n return ret;\n }\n Database.getTablesAsRows = getTablesAsRows;\n})(Database || (Database = {}));\nexport { Database };\n","/**\n * Copyright (c) 2017-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n * @author Alexander Rose \n */\nimport { Column, ColumnHelpers } from '../../../mol-data/db';\nimport { getNumberType, parseInt as fastParseInt, parseFloat as fastParseFloat } from '../common/text/number-parser';\nimport { areValuesEqualProvider } from '../common/text/column/token';\nexport function CifFile(blocks, name) {\n return { name, blocks: blocks };\n}\nexport function CifBlock(categoryNames, categories, header, saveFrames = []) {\n return {\n categoryNames, header, categories, saveFrames,\n getField(name) {\n const [category, field] = name.split('.');\n return categories[category].getField(field || '');\n }\n };\n}\nexport function CifSaveFrame(categoryNames, categories, header) {\n return { categoryNames, header, categories };\n}\nexport function CifCategory(name, rowCount, fieldNames, fields) {\n return { rowCount, name, fieldNames: [...fieldNames], getField(name) { return fields[name]; } };\n}\n(function (CifCategory) {\n function empty(name) {\n return { rowCount: 0, name, fieldNames: [], getField(name) { return void 0; } };\n }\n CifCategory.empty = empty;\n ;\n function ofFields(name, fields) {\n const fieldNames = Object.keys(fields);\n return {\n rowCount: fieldNames.length > 0 ? fields[fieldNames[0]].rowCount : 0,\n name,\n fieldNames,\n getField(name) { return fields[name]; }\n };\n }\n CifCategory.ofFields = ofFields;\n function ofTable(name, table) {\n const fields = {};\n for (const name of table._columns) {\n fields[name] = CifField.ofColumn(table[name]);\n }\n return ofFields(name, fields);\n }\n CifCategory.ofTable = ofTable;\n})(CifCategory || (CifCategory = {}));\nexport var CifField;\n(function (CifField) {\n function ofString(value) {\n return ofStrings([value]);\n }\n CifField.ofString = ofString;\n function ofStrings(values) {\n const rowCount = values.length;\n const str = row => { const ret = values[row]; if (!ret || ret === '.' || ret === '?')\n return ''; return ret; };\n const int = row => { const v = values[row]; return fastParseInt(v, 0, v.length) || 0; };\n const float = row => { const v = values[row]; return fastParseFloat(v, 0, v.length) || 0; };\n const valueKind = row => {\n const v = values[row], l = v.length;\n if (l > 1)\n return 0 /* Column.ValueKinds.Present */;\n if (l === 0)\n return 1 /* Column.ValueKinds.NotPresent */;\n const c = v.charCodeAt(0);\n if (c === 46 /* . */)\n return 1 /* Column.ValueKinds.NotPresent */;\n if (c === 63 /* ? */)\n return 2 /* Column.ValueKinds.Unknown */;\n return 0 /* Column.ValueKinds.Present */;\n };\n return {\n __array: void 0,\n binaryEncoding: void 0,\n isDefined: true,\n rowCount,\n str,\n int,\n float,\n valueKind,\n areValuesEqual: (rowA, rowB) => values[rowA] === values[rowB],\n toStringArray: params => params ? ColumnHelpers.createAndFillArray(rowCount, str, params) : values,\n toIntArray: params => ColumnHelpers.createAndFillArray(rowCount, int, params),\n toFloatArray: params => ColumnHelpers.createAndFillArray(rowCount, float, params)\n };\n }\n CifField.ofStrings = ofStrings;\n function ofNumbers(values) {\n const rowCount = values.length;\n const str = row => { return '' + values[row]; };\n const float = row => values[row];\n const valueKind = row => 0 /* Column.ValueKinds.Present */;\n const toFloatArray = (params) => {\n if (!params || params.array && values instanceof params.array) {\n return values;\n }\n else {\n return ColumnHelpers.createAndFillArray(rowCount, float, params);\n }\n };\n return {\n __array: void 0,\n binaryEncoding: void 0,\n isDefined: true,\n rowCount,\n str,\n int: float,\n float,\n valueKind,\n areValuesEqual: (rowA, rowB) => values[rowA] === values[rowB],\n toStringArray: params => ColumnHelpers.createAndFillArray(rowCount, str, params),\n toIntArray: toFloatArray,\n toFloatArray\n };\n }\n CifField.ofNumbers = ofNumbers;\n function ofTokens(tokens) {\n const { data, indices, count: rowCount } = tokens;\n const str = row => {\n const ret = data.substring(indices[2 * row], indices[2 * row + 1]);\n if (ret === '.' || ret === '?')\n return '';\n return ret;\n };\n const int = row => {\n return fastParseInt(data, indices[2 * row], indices[2 * row + 1]) || 0;\n };\n const float = row => {\n return fastParseFloat(data, indices[2 * row], indices[2 * row + 1]) || 0;\n };\n const valueKind = row => {\n const s = indices[2 * row], l = indices[2 * row + 1] - s;\n if (l > 1)\n return 0 /* Column.ValueKinds.Present */;\n if (l === 0)\n return 1 /* Column.ValueKinds.NotPresent */;\n const v = data.charCodeAt(s);\n if (v === 46 /* . */)\n return 1 /* Column.ValueKinds.NotPresent */;\n if (v === 63 /* ? */)\n return 2 /* Column.ValueKinds.Unknown */;\n return 0 /* Column.ValueKinds.Present */;\n };\n return {\n __array: void 0,\n binaryEncoding: void 0,\n isDefined: true,\n rowCount,\n str,\n int,\n float,\n valueKind,\n areValuesEqual: areValuesEqualProvider(tokens),\n toStringArray: params => ColumnHelpers.createAndFillArray(rowCount, str, params),\n toIntArray: params => ColumnHelpers.createAndFillArray(rowCount, int, params),\n toFloatArray: params => ColumnHelpers.createAndFillArray(rowCount, float, params)\n };\n }\n CifField.ofTokens = ofTokens;\n function ofColumn(column) {\n const { rowCount, valueKind, areValuesEqual, isDefined } = column;\n let str;\n let int;\n let float;\n switch (column.schema.valueType) {\n case 'float':\n case 'int':\n str = row => { return '' + column.value(row); };\n int = column.value;\n float = column.value;\n break;\n case 'str':\n str = column.value;\n int = row => { const v = column.value(row); return fastParseInt(v, 0, v.length) || 0; };\n float = row => { const v = column.value(row); return fastParseFloat(v, 0, v.length) || 0; };\n break;\n case 'list':\n const { separator } = column.schema;\n str = row => column.value(row).join(separator);\n int = row => NaN;\n float = row => NaN;\n break;\n default:\n throw new Error(`unsupported valueType '${column.schema.valueType}'`);\n }\n return {\n __array: void 0,\n binaryEncoding: void 0,\n isDefined,\n rowCount,\n str,\n int,\n float,\n valueKind,\n areValuesEqual,\n toStringArray: params => ColumnHelpers.createAndFillArray(rowCount, str, params),\n toIntArray: params => ColumnHelpers.createAndFillArray(rowCount, int, params),\n toFloatArray: params => ColumnHelpers.createAndFillArray(rowCount, float, params)\n };\n }\n CifField.ofColumn = ofColumn;\n function ofUndefined(rowCount, schema) {\n return ofColumn(Column.Undefined(rowCount, schema));\n }\n CifField.ofUndefined = ofUndefined;\n})(CifField || (CifField = {}));\nexport function tensorFieldNameGetter(field, rank, zeroIndexed, namingVariant) {\n const offset = zeroIndexed ? 0 : 1;\n switch (rank) {\n case 1:\n return namingVariant === 'brackets'\n ? (i) => `${field}[${i + offset}]`\n : (i) => `${field}_${i + offset}`;\n case 2:\n return namingVariant === 'brackets'\n ? (i, j) => `${field}[${i + offset}][${j + offset}]`\n : (i, j) => `${field}_${i + offset}${j + offset}`;\n case 3:\n return namingVariant === 'brackets'\n ? (i, j, k) => `${field}[${i + offset}][${j + offset}][${k + offset}]`\n : (i, j, k) => `${field}_${i + offset}${j + offset}${k + offset}`;\n default:\n throw new Error('Tensors with rank > 3 or rank 0 are currently not supported.');\n }\n}\nexport function getTensor(category, space, row, getName) {\n const ret = space.create();\n if (space.rank === 1) {\n const rows = space.dimensions[0];\n for (let i = 0; i < rows; i++) {\n const f = category.getField(getName(i));\n space.set(ret, i, !!f ? f.float(row) : 0.0);\n }\n }\n else if (space.rank === 2) {\n const rows = space.dimensions[0], cols = space.dimensions[1];\n for (let i = 0; i < rows; i++) {\n for (let j = 0; j < cols; j++) {\n const f = category.getField(getName(i, j));\n space.set(ret, i, j, !!f ? f.float(row) : 0.0);\n }\n }\n }\n else if (space.rank === 3) {\n const d0 = space.dimensions[0], d1 = space.dimensions[1], d2 = space.dimensions[2];\n for (let i = 0; i < d0; i++) {\n for (let j = 0; j < d1; j++) {\n for (let k = 0; k < d2; k++) {\n const f = category.getField(getName(i, j, k));\n space.set(ret, i, j, k, !!f ? f.float(row) : 0.0);\n }\n }\n }\n }\n else {\n throw new Error('Tensors with rank > 3 or rank 0 are currently not supported.');\n }\n return ret;\n}\nexport function getCifFieldType(field) {\n let floatCount = 0, hasStringOrScientific = false, undefinedCount = 0;\n for (let i = 0, _i = field.rowCount; i < _i; i++) {\n const k = field.valueKind(i);\n if (k !== 0 /* Column.ValueKinds.Present */) {\n undefinedCount++;\n continue;\n }\n const type = getNumberType(field.str(i));\n if (type === 0 /* NumberTypes.Int */)\n continue;\n else if (type === 1 /* NumberTypes.Float */)\n floatCount++;\n else {\n hasStringOrScientific = true;\n break;\n }\n }\n // numbers in scientific notation and plain text are not distinguishable\n if (hasStringOrScientific || undefinedCount === field.rowCount)\n return Column.Schema.str;\n if (floatCount > 0)\n return Column.Schema.float;\n return Column.Schema.int;\n}\n","/**\n * Copyright (c) 2017-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n * @author Alexander Rose \n */\nimport { ColumnHelpers } from '../../../../../mol-data/db';\nimport { parseInt as fastParseInt, parseFloat as fastParseFloat } from '../number-parser';\nexport function TokenColumnProvider(tokens) {\n return function (type) {\n return TokenColumn(tokens, type);\n };\n}\nexport function TokenColumn(tokens, schema) {\n const { data, indices, count: rowCount } = tokens;\n const { valueType: type } = schema;\n const value = type === 'str'\n ? row => data.substring(indices[2 * row], indices[2 * row + 1])\n : type === 'int'\n ? row => fastParseInt(data, indices[2 * row], indices[2 * row + 1]) || 0\n : row => fastParseFloat(data, indices[2 * row], indices[2 * row + 1]) || 0;\n return {\n schema: schema,\n __array: void 0,\n isDefined: true,\n rowCount,\n value,\n valueKind: row => 0 /* Column.ValueKinds.Present */,\n toArray: params => ColumnHelpers.createAndFillArray(rowCount, value, params),\n areValuesEqual: areValuesEqualProvider(tokens)\n };\n}\nexport function areValuesEqualProvider(tokens) {\n const { data, indices } = tokens;\n return function (rowA, rowB) {\n const aS = indices[2 * rowA], bS = indices[2 * rowB];\n const len = indices[2 * rowA + 1] - aS;\n if (len !== indices[2 * rowB + 1] - bS)\n return false;\n for (let i = 0; i < len; i++) {\n if (data.charCodeAt(i + aS) !== data.charCodeAt(i + bS)) {\n return false;\n }\n }\n return true;\n };\n}\nexport function areTokensEmpty(tokens) {\n const { count, indices } = tokens;\n for (let i = 0; i < count; ++i) {\n if (indices[2 * i] !== indices[2 * i + 1])\n return false;\n }\n return true;\n}\n","/**\n * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.\n *\n * @author David Sehnal \n */\nfunction createImmediateActions() {\n const thisGlobal = (function () {\n const _window = typeof window !== 'undefined' && window;\n const _self = typeof self !== 'undefined' && typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope && self;\n const _global = typeof global !== 'undefined' && global;\n return _window || _global || _self;\n })();\n const tasksByHandle = {};\n const doc = typeof document !== 'undefined' ? document : void 0;\n let nextHandle = 1; // Spec says greater than zero\n let registerImmediate;\n function setImmediate(callback, ...args) {\n // Callback can either be a function or a string\n if (typeof callback !== 'function') {\n callback = new Function('' + callback);\n }\n // Store and register the task\n const task = { callback: callback, args: args };\n tasksByHandle[nextHandle] = task;\n registerImmediate(nextHandle);\n return nextHandle++;\n }\n function clearImmediate(handle) {\n delete tasksByHandle[handle];\n }\n function run(task) {\n const callback = task.callback;\n const args = task.args;\n switch (args.length) {\n case 0:\n callback();\n break;\n case 1:\n callback(args[0]);\n break;\n case 2:\n callback(args[0], args[1]);\n break;\n case 3:\n callback(args[0], args[1], args[2]);\n break;\n default:\n callback.apply(undefined, args);\n break;\n }\n }\n function runIfPresent(handle) {\n const task = tasksByHandle[handle];\n clearImmediate(handle);\n run(task);\n }\n function installNextTickImplementation() {\n registerImmediate = function (handle) {\n process.nextTick(function () { runIfPresent(handle); });\n };\n }\n function canUsePostMessage() {\n if (thisGlobal && thisGlobal.postMessage && !thisGlobal.importScripts) {\n let postMessageIsAsynchronous = true;\n const oldOnMessage = thisGlobal.onmessage;\n thisGlobal.onmessage = function () {\n postMessageIsAsynchronous = false;\n };\n thisGlobal.postMessage('', '*');\n thisGlobal.onmessage = oldOnMessage;\n return postMessageIsAsynchronous;\n }\n }\n function installPostMessageImplementation() {\n // Installs an event handler on `global` for the `message` event: see\n // * https://developer.mozilla.org/en/DOM/window.postMessage\n // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages\n const messagePrefix = 'setImmediate$' + Math.random() + '$';\n const onGlobalMessage = function (event) {\n if (event.source === thisGlobal &&\n typeof event.data === 'string' &&\n event.data.indexOf(messagePrefix) === 0) {\n runIfPresent(+event.data.slice(messagePrefix.length));\n }\n };\n if (window.addEventListener) {\n window.addEventListener('message', onGlobalMessage, false);\n }\n else {\n window.attachEvent('onmessage', onGlobalMessage);\n }\n registerImmediate = function (handle) {\n window.postMessage(messagePrefix + handle, '*');\n };\n }\n function installMessageChannelImplementation() {\n const channel = new MessageChannel();\n channel.port1.onmessage = function (event) {\n const handle = event.data;\n runIfPresent(handle);\n };\n registerImmediate = function (handle) {\n channel.port2.postMessage(handle);\n };\n }\n function installReadyStateChangeImplementation() {\n const html = doc.documentElement;\n registerImmediate = function (handle) {\n // Create a