diff --git a/CHANGELOG.md b/CHANGELOG.md
index 27ef4b28..67e8eba7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,6 @@
## Change Log
+[icn3d-3.29.0](https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d-3.29.0.zip) was release on December 13, 2023. Added the feature to load electron density maps from ccp4 or MTZ files either locally or via URLs.
+
[icn3d-3.28.4](https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d-3.28.4.zip) was release on November 7, 2023. Enabled to show DelPhi potential for multiple structures.
[icn3d-3.28.3](https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d-3.28.3.zip) was release on October 5, 2023. Fixed the async/await issue for electron density maps and EM density maps.
@@ -307,7 +309,7 @@
[icn3d-2.15.0](https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d-2.15.0.zip) was release on April 21, 2020. Enabled to show the same structure "Side by Side" in two views in the "View" menu. Each view has the same orientation, but can have independent 3D display. Enabled to add multiple sequence alignments as tracks when clicking "Add Track" in the "Sequences & Annotations" window. Added "Hide Selection" in the "View" menu. Improved selection on "H-Bonds & Interactions". Improved the UI for "Realign Selection" in the "File" menu. The gallery shows COVID-19-related structures at the top.
-[icn3d-2.14.0](https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d-2.14.0.zip) was release on April 15, 2020. Added the features to load Electron Density data in the menu "File > Open File > Electron Density (DSN6)", resize the 3D window, realign two structures in the menu "File > Realign", color residues with custom colors in the menu "Color > Residue > Custom", and add custom colors when aligning a sequence to a structure.
+[icn3d-2.14.0](https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d-2.14.0.zip) was release on April 15, 2020. Added the features to load Electron Density data in the menu "File > Open File > Electron Density", resize the 3D window, realign two structures in the menu "File > Realign", color residues with custom colors in the menu "Color > Residue > Custom", and add custom colors when aligning a sequence to a structure.
[icn3d-2.13.1](https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d-2.13.1.zip) was release on March 26, 2020. Showed membranes for transmembrane proteins in VAST+ alignment.
diff --git a/README.md b/README.md
index a499f103..330d7e2a 100644
--- a/README.md
+++ b/README.md
@@ -66,7 +66,7 @@
* Contact Map for any Selected Residues:
You can click the menu "Analysis > Contact Map" to show the interactive [contact map](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?rnMbe26tNsAjJLGK9) for any selected residues. You can export the map in PNG or SVG.
-* More features are listed at [www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d.html](https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d.html): [binding site](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?JR5B), [interaction interface](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?CuXYgGLCukDeUKnJ6), [3D printing](https://www.ncbi.nlm.nih.gov/Structure/icn3d/?mmdbid=1tup&command=export+stl+stabilizer+file), [transmembrane proteins](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?TuSd), [surface](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?aYAjP4S3NbrBJX3x6), [EM map](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?L4C4WYE85tYRiFeK7), [electron density map](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?QpqNZ3k65ToYFvUB6), 1D sequences and 2D interactions, [align two structures](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?PfsQFtZRTgFAW2LG6), [align multiple chains](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?ijnf), [align a protein sequence to a structure](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?Mmm82craCwGMAxru9), [realign](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?UccFrXLDNeVB7Jk16), [custom tracks](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?pUzP), [force-directed graph for interactions](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?rshvjTFXpAFu8GDa9), [solvent accessible surface area](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?xKSyfd1umbKstGh29), etc.
+* More features are listed at [www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d.html](https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d.html): [binding site](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?JR5B), [interaction interface](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?CuXYgGLCukDeUKnJ6), [3D printing](https://www.ncbi.nlm.nih.gov/Structure/icn3d/?mmdbid=1tup&command=export+stl+stabilizer+file), [transmembrane proteins](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?TuSd), [surface](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?aYAjP4S3NbrBJX3x6), [EM map](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?L4C4WYE85tYRiFeK7), [electron density map from MTZ, CCP4, or DSN6](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?QpqNZ3k65ToYFvUB6), 1D sequences and 2D interactions, [align two structures](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?PfsQFtZRTgFAW2LG6), [align multiple chains](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?ijnf), [align a protein sequence to a structure](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?Mmm82craCwGMAxru9), [realign](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?UccFrXLDNeVB7Jk16), [custom tracks](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?pUzP), [force-directed graph for interactions](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?rshvjTFXpAFu8GDa9), [solvent accessible surface area](https://structure.ncbi.nlm.nih.gov/icn3d/share.html?xKSyfd1umbKstGh29), etc.
## Embed iCn3D with iframe or JavaScript libraries
@@ -123,6 +123,7 @@ iCn3D also accepts the following file types: PDB, mmCIF, Mol2, SDF, XYZ, and iCn
* **[Orientations of Proteins in Membranes (OPM)](https://opm.phar.umich.edu/)**: The membrane data of transmembrane proteins are from OPM.
* **[Membranome](https://membranome.org)**: For AlphaFold Structures, the membrane data of single-spanning transmembrane proteins are from Membranome.
* **[Post-Translational Modification (PTM)](https://www.ebi.ac.uk/proteins/api/doc/#/features)**: The PTM data are from UniProt.
+* **[UglyMol](https://github.com/uglymol/uglymol.github.io)**: The electron density maps from CCP4 map or MTZ format are based on UglyMol.
## Building
diff --git a/build/icn3d.js b/build/icn3d.js
index 91f1142d..57c77c79 100644
--- a/build/icn3d.js
+++ b/build/icn3d.js
@@ -8195,6 +8195,8 @@ var icn3d = (function (exports) {
let sigma2fofc = parseFloat($("#" + me.pre + "sigma2fofc" ).val());
let type = '2fofc';
await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma2fofc);
+ //ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma2fofc);
+
//ic.setOptionCls.setOption('map', '2fofc');
thisClass.setLogCmd('set map 2fofc sigma ' + sigma2fofc, true);
});
@@ -9457,6 +9459,8 @@ var icn3d = (function (exports) {
html += this.getLink('mn1_dsn6url', 'URL(CORS) ' + me.htmlCls.wifiStr, undefined, 3);
html += "";
+ html += "
';
htmlTmp += '
';
@@ -46808,13 +46929,22 @@ var icn3d = (function (exports) {
if(i < il - 1) refpdbnameList += ", ";
}
- let scoreList = '';
+ let scoreList = '', seqidList = '', nresAlignList = '';
for(let i = 0, il = domainidArray.length; i < il; ++i) {
- scoreList += domainid2score[domainidArray[i]];
- if(i < il - 1) scoreList += ", ";
+ let itemArray = domainid2score[domainidArray[i]].split('_');
+
+ scoreList += itemArray[0];
+ seqidList += itemArray[1];
+ nresAlignList += itemArray[2];
+
+ if(i < il - 1) {
+ scoreList += ", ";
+ seqidList += ", ";
+ nresAlignList += ", ";
+ }
}
- return {'refpdbnameList': refpdbnameList, 'scoreList': scoreList};
+ return {'refpdbnameList': refpdbnameList, 'scoreList': scoreList, 'seqidList': seqidList, 'nresAlignList': nresAlignList};
}
async parseAlignData(dataArray, domainidpairArray, bRound1) { let ic = this.icn3d, me = ic.icn3dui;
@@ -46909,28 +47039,15 @@ var icn3d = (function (exports) {
if(!bRound1) {
console.log("domainid: " + domainid);
-
- if(!ic.domainid2score.hasOwnProperty(domainid) || queryData[0].score >= ic.domainid2score[domainid]) {
- ic.domainid2score[domainid] = queryData[0].score;
-
- ic.domainid2refpdbname[domainid] = refpdbname;
- domainid2segs[domainid] = queryData[0].segs;
- ic.domainid2ig2kabat[domainid] = queryData[0].ig2kabat;
- ic.domainid2ig2imgt[domainid] = queryData[0].ig2imgt;
- }
}
- else {
- //let mixScore = 10 / queryData[0].super_rmsd + queryData[0].num_seg / 5;
- let mixScore = queryData[0].score;
- if(!ic.domainid2score.hasOwnProperty(domainid) || mixScore > ic.domainid2score[domainid]) {
- ic.domainid2score[domainid] = mixScore;
-
- ic.domainid2refpdbname[domainid] = refpdbname;
- domainid2segs[domainid] = queryData[0].segs;
- ic.domainid2ig2kabat[domainid] = queryData[0].ig2kabat;
- ic.domainid2ig2imgt[domainid] = queryData[0].ig2imgt;
- }
+ if(!ic.domainid2score.hasOwnProperty(domainid) || queryData[0].score >= ic.domainid2score[domainid].split('_')[0]) {
+ ic.domainid2score[domainid] = queryData[0].score + '_' + queryData[0].frac_identical + '_' + queryData[0].num_res ;
+
+ ic.domainid2refpdbname[domainid] = refpdbname;
+ domainid2segs[domainid] = queryData[0].segs;
+ ic.domainid2ig2kabat[domainid] = queryData[0].ig2kabat;
+ ic.domainid2ig2imgt[domainid] = queryData[0].ig2imgt;
}
}
@@ -47001,7 +47118,7 @@ var icn3d = (function (exports) {
// end of round 2
return;
}
-
+
// combine domainid into chainid
let processedChainid = {};
for(let domainid in ic.domainid2refpdbname) {
@@ -47049,8 +47166,10 @@ var icn3d = (function (exports) {
let result = this.getTemplateList(chainid);
let refpdbnameList = result.refpdbnameList;
let scoreList = result.scoreList;
+ let seqidList = result.seqidList;
+ let nresAlignList = result.nresAlignList;
- let message = "The reference PDBs for chain " + chainid + " are " + refpdbnameList + ". The TM-scores are " + scoreList + ".";
+ let message = "The reference PDB(s) for chain " + chainid + " is(are) " + refpdbnameList + ". The TM-score(s) is(are) " + scoreList + ". The sequence identitie(s) is(are) " + seqidList + ". The number of aligned residue(s) is(are) " + nresAlignList + ".";
if(!me.bNode) {
console.log(message);
me.htmlCls.clickMenuCls.setLogCmd(message, true);
@@ -48686,7 +48805,7 @@ var icn3d = (function (exports) {
if(ic.bD3 === undefined) {
//let url = "https://d3js.org/d3.v4.min.js";
- let url = "https://www.ncbi.nlm.nih.gov/Structure/icn3d/script/d3v4-force-all.min.js";
+ let url = "./script/d3v4-force-all.min.js";
await me.getAjaxPromise(url, 'script');
ic.bD3 = true;
@@ -49961,7 +50080,7 @@ var icn3d = (function (exports) {
for(let j = 0, jl = mmdbTmp.molecules.length; j < jl; ++j) {
let molecule = mmdbTmp.molecules[j];
let molid = molecule.moleculeId;
- let chainName = molecule.chain.trim();
+ let chainName = molecule.chain.trim().replace(/_/g, ''); // change "A_1" to "A1"
if(chainNameHash[chainName] === undefined) {
chainNameHash[chainName] = 1;
}
@@ -51255,10 +51374,10 @@ var icn3d = (function (exports) {
// https://edmaps.rcsb.org/maps/1kq2_fofc.dsn6
let url = "https://edmaps.rcsb.org/maps/" + pdbid.toLowerCase() + "_" + type + ".dsn6";
- await this.dsn6ParserBase(url, type, sigma);
+ await this.dsn6ParserBase(url, type, sigma, 'url', true);
}
- async dsn6ParserBase(url, type, sigma) { let ic = this.icn3d, me = ic.icn3dui;
+ async dsn6ParserBase(url, type, sigma, location, bInputSigma) { let ic = this.icn3d, me = ic.icn3dui;
let thisClass = this;
//https://stackoverflow.com/questions/33902299/using-jquery-ajax-to-download-a-binary-file
@@ -51272,7 +51391,7 @@ var icn3d = (function (exports) {
}
else {
let arrayBuffer = await me.getXMLHttpRqstPromise(url, 'GET', 'arraybuffer', 'rcsbEdmaps');
- thisClass.loadDsn6Data(arrayBuffer, type, sigma);
+ sigma = thisClass.loadDsn6Data(arrayBuffer, type, sigma, location, bInputSigma);
if(type == '2fofc') {
ic.bAjax2fofc = true;
@@ -51283,9 +51402,11 @@ var icn3d = (function (exports) {
ic.setOptionCls.setOption('map', type);
}
+
+ return sigma;
}
- loadDsn6Data(dsn6data, type, sigma) { let ic = this.icn3d; ic.icn3dui;
+ loadDsn6Data(dsn6data, type, sigma, location, bInputSigma) { let ic = this.icn3d; ic.icn3dui;
// DSN6 http://www.uoxray.uoregon.edu/tnt/manual/node104.html
// BRIX http://svn.cgl.ucsf.edu/svn/chimera/trunk/libs/VolumeData/dsn6/brix-1.html
@@ -51334,9 +51455,9 @@ var icn3d = (function (exports) {
}
}
- header.zStart = intView[ 2 ];
header.xStart = intView[ 0 ]; // NXSTART
header.yStart = intView[ 1 ];
+ header.zStart = intView[ 2 ];
header.xExtent = intView[ 3 ]; // NX
header.yExtent = intView[ 4 ];
@@ -51372,6 +51493,7 @@ var icn3d = (function (exports) {
let zBlocks = Math.ceil(header.zExtent / 8);
// loop over blocks
+ let maxValue = -999;
for(let zz = 0; zz < zBlocks; ++zz) {
for(let yy = 0; yy < yBlocks; ++yy) {
for(let xx = 0; xx < xBlocks; ++xx) {
@@ -51387,6 +51509,7 @@ var icn3d = (function (exports) {
if(x < header.xExtent && y < header.yExtent && z < header.zExtent) {
let idx =((((x * header.yExtent) + y) * header.zExtent) + z);
data[ idx ] =(byteView[ offset ] - summand) / divisor;
+ if(data[ idx ] > maxValue) maxValue = data[ idx ];
++offset;
} else {
offset += 8 - i;
@@ -51399,6 +51522,10 @@ var icn3d = (function (exports) {
}
}
+ if(!bInputSigma) {
+ sigma = this.setSigma(maxValue, location, type, sigma);
+ }
+
if(type == '2fofc') {
ic.mapData.header2 = header;
ic.mapData.data2 = data;
@@ -51413,6 +51540,32 @@ var icn3d = (function (exports) {
ic.mapData.type = type;
ic.mapData.sigma = sigma;
}
+
+ return sigma;
+ }
+
+ setSigma(maxValue, location, type, sigma) { let ic = this.icn3d, me = ic.icn3dui;
+ let inputId;
+ if(location == 'file') {
+ inputId = 'dsn6sigma' + type;
+ }
+ else if(location == 'url') {
+ inputId = 'dsn6sigmaurl' + type;
+ }
+
+ let factor = (type == '2fofc') ? 0.5 : 0.3;
+
+ if(inputId) {
+ if(!($("#" + me.pre + inputId).val())) {
+ sigma = (factor * maxValue).toFixed(2);
+ $("#" + me.pre + inputId).val(sigma);
+ }
+ else {
+ sigma = $("#" + me.pre + inputId).val();
+ }
+ }
+
+ return sigma;
}
getMatrix(header) { let ic = this.icn3d; ic.icn3dui;
@@ -51473,7 +51626,7 @@ var icn3d = (function (exports) {
return matrix;
}
- loadDsn6File(type, bCcp4) {var ic = this.icn3d, me = ic.icn3dui;
+ loadDsn6File(type) {var ic = this.icn3d, me = ic.icn3dui;
let thisClass = this;
let file = $("#" + ic.pre + "dsn6file" + type)[0].files[0];
@@ -51486,12 +51639,8 @@ var icn3d = (function (exports) {
let reader = new FileReader();
reader.onload = function(e) { let ic = thisClass.icn3d;
let arrayBuffer = e.target.result; // or = reader.result;
- if(bCcp4) {
- ic.densityCifParserCls.parseChannels(arrayBuffer, type, sigma);
- }
- else {
- thisClass.loadDsn6Data(arrayBuffer, type, sigma);
- }
+
+ sigma = thisClass.loadDsn6Data(arrayBuffer, type, sigma, 'file');
if(type == '2fofc') {
ic.bAjax2fofc = true;
@@ -51500,21 +51649,1006 @@ var icn3d = (function (exports) {
ic.bAjaxfofc = true;
}
ic.setOptionCls.setOption('map', type);
- me.htmlCls.clickMenuCls.setLogCmd('load map file ' + $("#" + ic.pre + "dsn6file" + type).val(), false);
+ me.htmlCls.clickMenuCls.setLogCmd('load map file ' + $("#" + ic.pre + "dsn6file" + type).val() + ' with sigma ' + sigma, false);
};
reader.readAsArrayBuffer(file);
}
}
loadDsn6FileUrl(type) {var ic = this.icn3d, me = ic.icn3dui;
+ let url = $("#" + ic.pre + "dsn6fileurl" + type).val();
+ let sigma = $("#" + ic.pre + "dsn6sigmaurl" + type).val();
+ if(!url) {
+ alert("Please input the file URL before clicking 'Load'");
+ }
+ else {
+ sigma = this.dsn6ParserBase(url, type, sigma, 'url');
+ me.htmlCls.clickMenuCls.setLogCmd('set map ' + type + ' sigma ' + sigma + ' file dsn6 | ' + encodeURIComponent(url), true);
+ }
+ }
+
+ }
+
+ /**
+ * @file Ccp4 Parser
+ * @author Marcin Wojdyr
+ * @private
+ * Modified by Jiyao Wang / https://github.com/ncbi/icn3d
+ */
+
+ class Ccp4Parser {
+ constructor(icn3d) {
+ this.icn3d = icn3d;
+ }
+
+ async ccp4ParserBase(url, type, sigma, location) { let ic = this.icn3d, me = ic.icn3dui;
+ let thisClass = this;
+
+ //https://stackoverflow.com/questions/33902299/using-jquery-ajax-to-download-a-binary-file
+ // if(type == '2fofc' && ic.bAjax2fofcccp4) {
+ // ic.mapData.sigma2 = sigma;
+ // ic.setOptionCls.setOption('map', type);
+ // }
+ // else if(type == 'fofc' && ic.bAjaxfofcccp4) {
+ // ic.mapData.sigma = sigma;
+ // ic.setOptionCls.setOption('map', type);
+ // }
+ // else {
+ let arrayBuffer = await me.getXMLHttpRqstPromise(url, 'GET', 'arraybuffer', '');
+ let bInputSigma = true;
+ sigma = thisClass.load_map_from_buffer(arrayBuffer, type, sigma, location, bInputSigma);
+
+ // if(type == '2fofc') {
+ // ic.bAjax2fofcccp4 = true;
+ // }
+ // else if(type == 'fofc') {
+ // ic.bAjaxfofcccp4 = true;
+ // }
+
+ ic.setOptionCls.setOption('map', type);
+
+ return sigma;
+ // }
+ }
+
+ // modified from_ccp4() at https://github.com/uglymol/uglymol.github.io/blob/master/src/elmap.js
+ load_map_from_buffer(buf, type, sigma, location, bInputSigma) { let ic = this.icn3d; ic.icn3dui;
+ if (buf.byteLength < 1024) throw Error('File shorter than 1024 bytes.');
+
+ //console.log('buf type: ' + Object.prototype.toString.call(buf));
+ // for now we assume both file and host are little endian
+ const iview = new Int32Array(buf, 0, 256);
+ // word 53 - character string 'MAP ' to identify file type
+ if (iview[52] !== 0x2050414d) throw Error('not a CCP4 map');
+
+ // map has 3 dimensions referred to as columns (fastest changing), rows
+ // and sections (c-r-s)
+ const n_crs = [iview[0], iview[1], iview[2]]; // 108, 108, 108
+ const mode = iview[3]; //2
+ let nb;
+ if (mode === 2) nb = 4;
+ else if (mode === 0) nb = 1;
+ else throw Error('Only Mode 2 and Mode 0 of CCP4 map is supported.');
+
+ const start = [iview[4], iview[5], iview[6]]; // 0,0,0
+ const n_grid = [iview[7], iview[8], iview[9]]; // 108,108,108
+ const nsymbt = iview[23]; // size of extended header in bytes
+ // nsymbt = 1920
+
+ if (1024 + nsymbt + nb*n_crs[0]*n_crs[1]*n_crs[2] !== buf.byteLength) {
+ throw Error('ccp4 file too short or too long');
+ }
+
+ const fview = new Float32Array(buf, 0, buf.byteLength / 4);
+ const grid = new GridArray(n_grid);
+ const unit_cell = new UnitCell(fview[10], fview[11], fview[12], fview[13], fview[14], fview[15]); // 79.1, 79.1, 79.1, 90, 90, 90
+
+ // MAPC, MAPR, MAPS - axis corresp to cols, rows, sections (1,2,3 for X,Y,Z)
+ const map_crs = [iview[16], iview[17], iview[18]]; // 2,1,3
+ const ax = map_crs.indexOf(1);
+ const ay = map_crs.indexOf(2);
+ const az = map_crs.indexOf(3);
+
+ const min = fview[19]; // -0.49
+ const max = fview[20]; // 0.94
+ //const sg_number = iview[22];
+ //const lskflg = iview[24];
+
+ if (nsymbt % 4 !== 0) {
+ throw Error('CCP4 map with NSYMBT not divisible by 4 is not supported.');
+ }
+ let data_view;
+ if (mode === 2) data_view = fview;
+ else /* mode === 0 */ data_view = new Int8Array(buf);
+ let idx = (1024 + nsymbt) / nb | 0; //736
+
+ // We assume that if DMEAN and RMS from the header are not clearly wrong
+ // they are what the user wants. Because the map can cover a small part
+ // of the asu and its rmsd may be different than the total rmsd.
+ // let stats = { mean: 0.0, rms: 1.0 };
+ // stats.mean = fview[21]; //0
+ // stats.rms = fview[54]; //0.15
+ // if (stats.mean < min || stats.mean > max || stats.rms <= 0) {
+ // stats = this.calculate_stddev(data_view, idx);
+ // }
+
+ let b1 = 1;
+ let b0 = 0;
+ // if the file was converted by mapmode2to0 - scale the data
+ if (mode === 0 && iview[39] === -128 && iview[40] === 127) { //39:0, 40:0
+ // scaling f(x)=b1*x+b0 such that f(-128)=min and f(127)=max
+ b1 = (max - min) / 255.0;
+ b0 = 0.5 * (min + max + b1);
+ }
+
+ const end = [start[0] + n_crs[0], start[1] + n_crs[1], start[2] + n_crs[2]];
+ let it = [0, 0, 0];
+ let maxValue = -999;
+ for (it[2] = start[2]; it[2] < end[2]; it[2]++) { // sections
+ for (it[1] = start[1]; it[1] < end[1]; it[1]++) { // rows
+ for (it[0] = start[0]; it[0] < end[0]; it[0]++) { // cols
+ let value = b1 * data_view[idx] + b0;
+ grid.set_grid_value(it[ax], it[ay], it[az], value);
+
+ if(value > maxValue) maxValue = value;
+ idx++;
+ }
+ }
+ }
+
+ /*
+ if (expand_symmetry && nsymbt > 0) {
+ const u8view = new Uint8Array(buf);
+ for (let i = 0; i+80 <= nsymbt; i += 80) {
+ let j;
+ let symop = '';
+ for (j = 0; j < 80; ++j) {
+ symop += String.fromCharCode(u8view[1024 + i + j]);
+ }
+ if (/^\s*x\s*,\s*y\s*,\s*z\s*$/i.test(symop)) continue; // skip x,y,z
+ //console.log('sym ops', symop.trim());
+ let mat = this.parse_symop(symop);
+ // Note: we apply here symops to grid points instead of coordinates.
+ // In the cases we came across it is equivalent, but in general not.
+ for (j = 0; j < 3; ++j) {
+ mat[j][3] = Math.round(mat[j][3] * n_grid[j]) | 0;
+ }
+ idx = (1024 + nsymbt) / nb | 0;
+ let xyz = [0, 0, 0];
+ for (it[2] = start[2]; it[2] < end[2]; it[2]++) { // sections
+ for (it[1] = start[1]; it[1] < end[1]; it[1]++) { // rows
+ for (it[0] = start[0]; it[0] < end[0]; it[0]++) { // cols
+ for (j = 0; j < 3; ++j) {
+ xyz[j] = it[ax] * mat[j][0] + it[ay] * mat[j][1] +
+ it[az] * mat[j][2] + mat[j][3];
+ }
+ let value = b1 * data_view[idx] + b0;
+ grid.set_grid_value(xyz[0], xyz[1], xyz[2], value);
+
+ if(value > maxValue) maxValue = value;
+ idx++;
+ }
+ }
+ }
+ }
+ }
+ */
+
+ if(!bInputSigma) {
+ sigma = ic.dsn6ParserCls.setSigma(maxValue, location, type, sigma);
+ }
+
+ if(type == '2fofc') {
+ ic.mapData.ccp4 = 1;
+ ic.mapData.grid2 = grid;
+ ic.mapData.unit_cell2 = unit_cell;
+ ic.mapData.type2 = type;
+ ic.mapData.sigma2 = sigma;
+ }
+ else {
+ ic.mapData.ccp4 = 1;
+ ic.mapData.grid = grid;
+ ic.mapData.unit_cell = unit_cell;
+ ic.mapData.type = type;
+ ic.mapData.sigma = sigma;
+ }
+
+ return sigma;
+ }
+
+ load_maps_from_mtz_buffer(mtz, type, sigma, location, bInputSigma) { let ic = this.icn3d; ic.icn3dui;
+ let is_diff = (type == 'fofc'); // diff: fofc, non-diff: 2fofc
+ let dataArray = mtz.calculate_map(is_diff);
+
+ let mc = mtz.cell;
+ const unit_cell = new UnitCell(mc.a, mc.b, mc.c, mc.alpha, mc.beta, mc.gamma);
+
+ let maxValue = -999;
+ for(let i = 0, il = dataArray.length; i < il; ++i) {
+ if(dataArray[i] > maxValue) maxValue = dataArray[i];
+ }
+
+ if(!bInputSigma) {
+ sigma = ic.dsn6ParserCls.setSigma(maxValue, location, type, sigma);
+ }
+
+ const grid = new GridArray([mtz.nx, mtz.ny, mtz.nz]);
+ grid.values.set(dataArray);
+
+ if(type == '2fofc') {
+ ic.mapData.ccp4 = 1;
+ ic.mapData.grid2 = grid;
+ ic.mapData.unit_cell2 = unit_cell;
+ ic.mapData.type2 = type;
+ ic.mapData.sigma2 = sigma;
+ }
+ else {
+ ic.mapData.ccp4 = 1;
+ ic.mapData.grid = grid;
+ ic.mapData.unit_cell = unit_cell;
+ ic.mapData.type = type;
+ ic.mapData.sigma = sigma;
+ }
+
+ mtz.delete();
+
+ return sigma;
+ }
+
+ // calculate_stddev(a, offset) {
+ // let sum = 0;
+ // let sq_sum = 0;
+ // const alen = a.length;
+ // for (let i = offset; i < alen; i++) {
+ // sum += a[i];
+ // sq_sum += a[i] * a[i];
+ // }
+ // const mean = sum / (alen - offset);
+ // const variance = sq_sum / (alen - offset) - mean * mean;
+ // return {mean: mean, rms: Math.sqrt(variance)};
+ // }
+
+ parse_symop(symop) {
+ const ops = symop.toLowerCase().replace(/\s+/g, '').split(',');
+ if (ops.length !== 3) throw Error('Unexpected symop: ' + symop);
+ let mat = [];
+ for (let i = 0; i < 3; i++) {
+ const terms = ops[i].split(/(?=[+-])/);
+ let row = [0, 0, 0, 0];
+ for (let j = 0; j < terms.length; j++) {
+ const term = terms[j];
+ const sign = (term[0] === '-' ? -1 : 1);
+ let m = terms[j].match(/^[+-]?([xyz])$/);
+ if (m) {
+ const pos = {x: 0, y: 1, z: 2}[m[1]];
+ row[pos] = sign;
+ } else {
+ m = terms[j].match(/^[+-]?(\d)\/(\d)$/);
+ if (!m) throw Error('What is ' + terms[j] + ' in ' + symop);
+ row[3] = sign * Number(m[1]) / Number(m[2]);
+ }
+ }
+ mat.push(row);
+ }
+ return mat;
+ }
+
+ loadCcp4File(type) {let ic = this.icn3d, me = ic.icn3dui;
+ let thisClass = this;
+
+ let file = $("#" + ic.pre + "dsn6file" + type)[0].files[0];
+ let sigma = $("#" + ic.pre + "dsn6sigma" + type).val();
+ if(!file) {
+ alert("Please select a file before clicking 'Load'");
+ }
+ else {
+ me.utilsCls.checkFileAPI();
+ let reader = new FileReader();
+ reader.onload = function(e) { let ic = thisClass.icn3d;
+ let arrayBuffer = e.target.result; // or = reader.result;
+ sigma = thisClass.load_map_from_buffer(arrayBuffer, type, sigma, 'file');
+
+ // if(type == '2fofc') {
+ // ic.bAjax2fofcCcp4 = true;
+ // }
+ // else if(type == 'fofc') {
+ // ic.bAjaxfofcCcp4 = true;
+ // }
+ ic.setOptionCls.setOption('map', type);
+ me.htmlCls.clickMenuCls.setLogCmd('load map file ' + $("#" + ic.pre + "dsn6file" + type).val() + ' with sigma ' + sigma, false);
+ };
+ reader.readAsArrayBuffer(file);
+ }
+ }
+
+ async loadCcp4FileUrl(type) { let ic = this.icn3d, me = ic.icn3dui;
let url = $("#" + ic.pre + "dsn6fileurl" + type).val();
let sigma = $("#" + ic.pre + "dsn6sigmaurl" + type).val();
if(!url) {
alert("Please input the file URL before clicking 'Load'");
}
else {
- this.dsn6ParserBase(url, type, sigma);
- me.htmlCls.clickMenuCls.setLogCmd('set map ' + type + ' sigma ' + sigma + ' | ' + encodeURIComponent(url), true);
+ sigma = await this.ccp4ParserBase(url, type, sigma, 'file');
+
+ me.htmlCls.clickMenuCls.setLogCmd('set map ' + type + ' sigma ' + sigma + ' file ccp4 | ' + encodeURIComponent(url), true);
+ }
+ }
+
+ // Extract a block of density for calculating an isosurface using the
+ // separate marching cubes implementation.
+ extract_block(grid, unit_cell, radius, center, typeDetail) { let ic = this.icn3d; ic.icn3dui;
+ // let grid = this.grid;
+ // let unit_cell = this.unit_cell;
+ if (grid == null || unit_cell == null) { return; }
+ let fc = unit_cell.fractionalize(center);
+
+ let r = [radius / unit_cell.parameters[0],
+ radius / unit_cell.parameters[1],
+ radius / unit_cell.parameters[2]];
+ let grid_min = grid.frac2grid([fc[0] - r[0], fc[1] - r[1], fc[2] - r[2]]);
+ let grid_max = grid.frac2grid([fc[0] + r[0], fc[1] + r[1], fc[2] + r[2]]);
+
+ let size = [grid_max[0] - grid_min[0] + 1,
+ grid_max[1] - grid_min[1] + 1,
+ grid_max[2] - grid_min[2] + 1];
+ let points = [];
+ let values = [];
+ let threshold = 1;
+ let bAtoms = ic.hAtoms && Object.keys(ic.hAtoms).length > 0;
+ for (let i = grid_min[0]; i <= grid_max[0]; i++) {
+ for (let j = grid_min[1]; j <= grid_max[1]; j++) {
+ for (let k = grid_min[2]; k <= grid_max[2]; k++) {
+ let frac = grid.grid2frac(i, j, k);
+ let orth = unit_cell.orthogonalize(frac);
+ points.push(orth);
+
+ // get overlap between map and atoms
+ let positoin = new THREE.Vector3(orth[0], orth[1], orth[2]);
+ let atomsNear = ic.rayCls.getAtomsFromPosition(positoin, threshold, ic.hAtoms);
+
+ let map_value = (atomsNear || !bAtoms) ? grid.get_grid_value(i, j, k) : 0;
+
+ if(typeDetail == 'fofc_pos' && map_value < 0) map_value = 0;
+ if(typeDetail == 'fofc_neg') map_value = (map_value > 0) ? 0 : -map_value;
+
+ values.push(map_value);
+ }
+ }
+ }
+
+ return {size: size, values: values, points: points};
+ // this.block.set(points, values, size);
+ };
+
+ marchingCubes(dims, values, points, isolevel, method) { let ic = this.icn3d; ic.icn3dui;
+ const edgeTable = new Int32Array([
+ 0x0 , 0x0 , 0x202, 0x302, 0x406, 0x406, 0x604, 0x704,
+ 0x804, 0x805, 0xa06, 0xa06, 0xc0a, 0xd03, 0xe08, 0xf00,
+ 0x90 , 0x98 , 0x292, 0x292, 0x496, 0x49e, 0x694, 0x694,
+ 0x894, 0x894, 0xa96, 0xa96, 0xc9a, 0xc92, 0xe91, 0xe90,
+ 0x230, 0x230, 0x33 , 0x13a, 0x636, 0x636, 0x434, 0x43c,
+ 0xa34, 0xa35, 0x837, 0x936, 0xe3a, 0xf32, 0xc31, 0xd30,
+ 0x2a0, 0x2a8, 0xa3 , 0xaa , 0x6a6, 0x6af, 0x5a4, 0x4ac,
+ 0xaa4, 0xaa4, 0x9a6, 0x8a6, 0xfaa, 0xea3, 0xca1, 0xca0,
+ 0x460, 0x460, 0x662, 0x762, 0x66 , 0x66 , 0x265, 0x364,
+ 0xc64, 0xc65, 0xe66, 0xe66, 0x86a, 0x863, 0xa69, 0xa60,
+ 0x4f0, 0x4f8, 0x6f2, 0x6f2, 0xf6 , 0xfe , 0x2f5, 0x2fc,
+ 0xcf4, 0xcf4, 0xef6, 0xef6, 0x8fa, 0x8f3, 0xaf9, 0xaf0,
+ 0x650, 0x650, 0x453, 0x552, 0x256, 0x256, 0x54 , 0x154,
+ 0xe54, 0xf54, 0xc57, 0xd56, 0xa5a, 0xb52, 0x859, 0x950,
+ 0x7c0, 0x6c1, 0x5c2, 0x4c2, 0x3c6, 0x2ce, 0xc5 , 0xc4 ,
+ 0xfc4, 0xec5, 0xdc6, 0xcc6, 0xbca, 0xac2, 0x8c1, 0x8c0,
+ 0x8c0, 0x8c0, 0xac2, 0xbc2, 0xcc6, 0xcc6, 0xec4, 0xfcc,
+ 0xc4 , 0xc5 , 0x2c6, 0x3c6, 0x4c2, 0x5c2, 0x6c1, 0x7c0,
+ 0x950, 0x859, 0xb52, 0xa5a, 0xd56, 0xc57, 0xe54, 0xe5c,
+ 0x154, 0x54 , 0x25e, 0x256, 0x552, 0x453, 0x658, 0x650,
+ 0xaf0, 0xaf0, 0x8f3, 0x8fa, 0xef6, 0xef6, 0xcf4, 0xcfc,
+ 0x2f4, 0x3f5, 0xff , 0x1f6, 0x6f2, 0x6f3, 0x4f9, 0x5f0,
+ 0xa60, 0xa69, 0x863, 0x86a, 0xe66, 0xe67, 0xd65, 0xc6c,
+ 0x364, 0x265, 0x166, 0x66 , 0x76a, 0x663, 0x460, 0x460,
+ 0xca0, 0xca0, 0xea2, 0xfa2, 0x8a6, 0x8a6, 0xaa4, 0xba4,
+ 0x4ac, 0x5a4, 0x6ae, 0x7a6, 0xaa , 0xa3 , 0x2a8, 0x2a0,
+ 0xd30, 0xc31, 0xf32, 0xe3a, 0x936, 0x837, 0xb35, 0xa34,
+ 0x43c, 0x434, 0x73e, 0x636, 0x13a, 0x33 , 0x339, 0x230,
+ 0xe90, 0xe90, 0xc92, 0xc9a, 0xa96, 0xa96, 0x894, 0x89c,
+ 0x694, 0x695, 0x49f, 0x496, 0x292, 0x392, 0x98 , 0x90 ,
+ 0xf00, 0xe08, 0xd03, 0xc0a, 0xa06, 0xa0e, 0x805, 0x804,
+ 0x704, 0x604, 0x506, 0x406, 0x302, 0x202, 0x0 , 0x0]);
+
+ const segTable = [
+ [],
+ [],
+ [1, 9],
+ [1, 8, 1, 9],
+ [2, 10, 10, 1],
+ [2, 10, 10, 1],
+ [9, 2, 2, 10, 10, 9],
+ [2, 8, 2, 10, 10, 8, 10, 9],
+ [11, 2],
+ [0, 11, 11, 2],
+ [1, 9, 11, 2],
+ [1, 11, 11, 2, 1, 9, 9, 11],
+ [3, 10, 10, 1, 11, 10],
+ [0, 10, 10, 1, 8, 10, 11, 10],
+ [3, 9, 11, 9, 11, 10, 10, 9],
+ [8, 10, 10, 9, 11, 10],
+ [4, 7],
+ [4, 3, 4, 7],
+ [1, 9, 4, 7],
+ [4, 1, 1, 9, 4, 7, 7, 1],
+ [2, 10, 10, 1, 4, 7],
+ [3, 4, 4, 7, 2, 10, 10, 1],
+ [9, 2, 2, 10, 10, 9, 4, 7],
+ [2, 10, 10, 9, 9, 2, 9, 7, 7, 2, 4, 7],
+ [4, 7, 11, 2],
+ [11, 4, 4, 7, 11, 2, 2, 4],
+ [1, 9, 4, 7, 11, 2],
+ [4, 7, 11, 4, 11, 9, 11, 2, 2, 9, 1, 9],
+ [3, 10, 10, 1, 11, 10, 4, 7],
+ [1, 11, 11, 10, 10, 1, 1, 4, 4, 11, 4, 7],
+ [4, 7, 0, 11, 11, 9, 11, 10, 10, 9],
+ [4, 7, 11, 4, 11, 9, 11, 10, 10, 9],
+ [9, 5, 5, 4],
+ [9, 5, 5, 4],
+ [0, 5, 5, 4, 1, 5],
+ [8, 5, 5, 4, 3, 5, 1, 5],
+ [2, 10, 10, 1, 9, 5, 5, 4],
+ [2, 10, 10, 1, 9, 5, 5, 4],
+ [5, 2, 2, 10, 10, 5, 5, 4, 4, 2],
+ [2, 10, 10, 5, 5, 2, 5, 3, 5, 4, 4, 3],
+ [9, 5, 5, 4, 11, 2],
+ [0, 11, 11, 2, 9, 5, 5, 4],
+ [0, 5, 5, 4, 1, 5, 11, 2],
+ [1, 5, 5, 2, 5, 8, 8, 2, 11, 2, 5, 4],
+ [10, 3, 11, 10, 10, 1, 9, 5, 5, 4],
+ [9, 5, 5, 4, 8, 1, 8, 10, 10, 1, 11, 10],
+ [5, 4, 0, 5, 0, 11, 11, 5, 11, 10, 10, 5],
+ [5, 4, 8, 5, 8, 10, 10, 5, 11, 10],
+ [9, 7, 5, 7, 9, 5],
+ [9, 3, 9, 5, 5, 3, 5, 7],
+ [0, 7, 1, 7, 1, 5, 5, 7],
+ [1, 5, 5, 3, 5, 7],
+ [9, 7, 9, 5, 5, 7, 10, 1, 2, 10],
+ [10, 1, 2, 10, 9, 5, 5, 0, 5, 3, 5, 7],
+ [2, 8, 2, 5, 5, 8, 5, 7, 10, 5, 2, 10],
+ [2, 10, 10, 5, 5, 2, 5, 3, 5, 7],
+ [7, 9, 9, 5, 5, 7, 11, 2],
+ [9, 5, 5, 7, 7, 9, 7, 2, 2, 9, 11, 2],
+ [11, 2, 1, 8, 1, 7, 1, 5, 5, 7],
+ [11, 2, 1, 11, 1, 7, 1, 5, 5, 7],
+ [9, 5, 5, 8, 5, 7, 10, 1, 3, 10, 11, 10],
+ [5, 7, 7, 0, 0, 5, 9, 5, 11, 0, 0, 10, 10, 1, 11, 10],
+ [11, 10, 10, 0, 0, 11, 10, 5, 5, 0, 0, 7, 5, 7],
+ [11, 10, 10, 5, 5, 11, 5, 7],
+ [10, 6, 6, 5, 5, 10],
+ [5, 10, 10, 6, 6, 5],
+ [1, 9, 5, 10, 10, 6, 6, 5],
+ [1, 8, 1, 9, 5, 10, 10, 6, 6, 5],
+ [1, 6, 6, 5, 5, 1, 2, 6],
+ [1, 6, 6, 5, 5, 1, 2, 6],
+ [9, 6, 6, 5, 5, 9, 0, 6, 2, 6],
+ [5, 9, 8, 5, 8, 2, 2, 5, 2, 6, 6, 5],
+ [11, 2, 10, 6, 6, 5, 5, 10],
+ [11, 0, 11, 2, 10, 6, 6, 5, 5, 10],
+ [1, 9, 11, 2, 5, 10, 10, 6, 6, 5],
+ [5, 10, 10, 6, 6, 5, 1, 9, 9, 2, 9, 11, 11, 2],
+ [6, 3, 11, 6, 6, 5, 5, 3, 5, 1],
+ [11, 0, 11, 5, 5, 0, 5, 1, 11, 6, 6, 5],
+ [11, 6, 6, 3, 6, 0, 6, 5, 5, 0, 5, 9],
+ [6, 5, 5, 9, 9, 6, 9, 11, 11, 6],
+ [5, 10, 10, 6, 6, 5, 4, 7],
+ [4, 3, 4, 7, 6, 5, 5, 10, 10, 6],
+ [1, 9, 5, 10, 10, 6, 6, 5, 4, 7],
+ [10, 6, 6, 5, 5, 10, 1, 9, 9, 7, 7, 1, 4, 7],
+ [6, 1, 2, 6, 6, 5, 5, 1, 4, 7],
+ [2, 5, 5, 1, 2, 6, 6, 5, 4, 3, 4, 7],
+ [4, 7, 0, 5, 5, 9, 0, 6, 6, 5, 2, 6],
+ [3, 9, 9, 7, 4, 7, 2, 9, 5, 9, 9, 6, 6, 5, 2, 6],
+ [11, 2, 4, 7, 10, 6, 6, 5, 5, 10],
+ [5, 10, 10, 6, 6, 5, 4, 7, 7, 2, 2, 4, 11, 2],
+ [1, 9, 4, 7, 11, 2, 5, 10, 10, 6, 6, 5],
+ [9, 2, 1, 9, 9, 11, 11, 2, 4, 11, 4, 7, 5, 10, 10, 6, 6, 5],
+ [4, 7, 11, 5, 5, 3, 5, 1, 11, 6, 6, 5],
+ [5, 1, 1, 11, 11, 5, 11, 6, 6, 5, 0, 11, 11, 4, 4, 7],
+ [0, 5, 5, 9, 0, 6, 6, 5, 3, 6, 11, 6, 4, 7],
+ [6, 5, 5, 9, 9, 6, 9, 11, 11, 6, 4, 7, 7, 9],
+ [10, 4, 9, 10, 6, 4, 10, 6],
+ [4, 10, 10, 6, 6, 4, 9, 10],
+ [10, 0, 1, 10, 10, 6, 6, 0, 6, 4],
+ [1, 8, 1, 6, 6, 8, 6, 4, 1, 10, 10, 6],
+ [1, 4, 9, 1, 2, 4, 2, 6, 6, 4],
+ [2, 9, 9, 1, 2, 4, 2, 6, 6, 4],
+ [2, 4, 2, 6, 6, 4],
+ [2, 8, 2, 4, 2, 6, 6, 4],
+ [10, 4, 9, 10, 10, 6, 6, 4, 11, 2],
+ [8, 2, 11, 2, 9, 10, 10, 4, 10, 6, 6, 4],
+ [11, 2, 1, 6, 6, 0, 6, 4, 1, 10, 10, 6],
+ [6, 4, 4, 1, 1, 6, 1, 10, 10, 6, 8, 1, 1, 11, 11, 2],
+ [9, 6, 6, 4, 9, 3, 3, 6, 9, 1, 11, 6],
+ [11, 1, 1, 8, 11, 6, 6, 1, 9, 1, 1, 4, 6, 4],
+ [11, 6, 6, 3, 6, 0, 6, 4],
+ [6, 4, 8, 6, 11, 6],
+ [7, 10, 10, 6, 6, 7, 8, 10, 9, 10],
+ [0, 7, 0, 10, 10, 7, 9, 10, 6, 7, 10, 6],
+ [10, 6, 6, 7, 7, 10, 1, 10, 7, 1, 8, 1],
+ [10, 6, 6, 7, 7, 10, 7, 1, 1, 10],
+ [2, 6, 6, 1, 6, 8, 8, 1, 9, 1, 6, 7],
+ [2, 6, 6, 9, 9, 2, 9, 1, 6, 7, 7, 9, 9, 3],
+ [0, 7, 0, 6, 6, 7, 2, 6],
+ [2, 7, 6, 7, 2, 6],
+ [11, 2, 10, 6, 6, 8, 8, 10, 9, 10, 6, 7],
+ [0, 7, 7, 2, 11, 2, 9, 7, 6, 7, 7, 10, 10, 6, 9, 10],
+ [1, 8, 1, 7, 1, 10, 10, 7, 6, 7, 10, 6, 11, 2],
+ [11, 2, 1, 11, 1, 7, 10, 6, 6, 1, 1, 10, 6, 7],
+ [9, 6, 6, 8, 6, 7, 9, 1, 1, 6, 11, 6, 6, 3],
+ [9, 1, 11, 6, 6, 7],
+ [0, 7, 0, 6, 6, 7, 11, 0, 11, 6],
+ [11, 6, 6, 7],
+ [7, 6, 6, 11],
+ [7, 6, 6, 11],
+ [1, 9, 7, 6, 6, 11],
+ [8, 1, 1, 9, 7, 6, 6, 11],
+ [10, 1, 2, 10, 6, 11, 7, 6],
+ [2, 10, 10, 1, 6, 11, 7, 6],
+ [2, 9, 2, 10, 10, 9, 6, 11, 7, 6],
+ [6, 11, 7, 6, 2, 10, 10, 3, 10, 8, 10, 9],
+ [7, 2, 6, 2, 7, 6],
+ [7, 0, 7, 6, 6, 0, 6, 2],
+ [2, 7, 7, 6, 6, 2, 1, 9],
+ [1, 6, 6, 2, 1, 8, 8, 6, 1, 9, 7, 6],
+ [10, 7, 7, 6, 6, 10, 10, 1, 1, 7],
+ [10, 7, 7, 6, 6, 10, 1, 7, 10, 1, 1, 8],
+ [7, 0, 7, 10, 10, 0, 10, 9, 6, 10, 7, 6],
+ [7, 6, 6, 10, 10, 7, 10, 8, 10, 9],
+ [6, 8, 4, 6, 6, 11],
+ [3, 6, 6, 11, 0, 6, 4, 6],
+ [8, 6, 6, 11, 4, 6, 1, 9],
+ [4, 6, 6, 9, 6, 3, 3, 9, 1, 9, 6, 11],
+ [6, 8, 4, 6, 6, 11, 2, 10, 10, 1],
+ [2, 10, 10, 1, 0, 11, 0, 6, 6, 11, 4, 6],
+ [4, 11, 4, 6, 6, 11, 2, 9, 2, 10, 10, 9],
+ [10, 9, 9, 3, 3, 10, 2, 10, 4, 3, 3, 6, 6, 11, 4, 6],
+ [8, 2, 4, 2, 4, 6, 6, 2],
+ [4, 2, 4, 6, 6, 2],
+ [1, 9, 3, 4, 4, 2, 4, 6, 6, 2],
+ [1, 9, 4, 1, 4, 2, 4, 6, 6, 2],
+ [8, 1, 8, 6, 6, 1, 4, 6, 6, 10, 10, 1],
+ [10, 1, 0, 10, 0, 6, 6, 10, 4, 6],
+ [4, 6, 6, 3, 3, 4, 6, 10, 10, 3, 3, 9, 10, 9],
+ [10, 9, 4, 10, 6, 10, 4, 6],
+ [9, 5, 5, 4, 7, 6, 6, 11],
+ [9, 5, 5, 4, 7, 6, 6, 11],
+ [5, 0, 1, 5, 5, 4, 7, 6, 6, 11],
+ [7, 6, 6, 11, 3, 4, 3, 5, 5, 4, 1, 5],
+ [9, 5, 5, 4, 10, 1, 2, 10, 7, 6, 6, 11],
+ [6, 11, 7, 6, 2, 10, 10, 1, 9, 5, 5, 4],
+ [7, 6, 6, 11, 5, 4, 4, 10, 10, 5, 4, 2, 2, 10],
+ [3, 4, 3, 5, 5, 4, 2, 5, 10, 5, 2, 10, 7, 6, 6, 11],
+ [7, 2, 7, 6, 6, 2, 5, 4, 9, 5],
+ [9, 5, 5, 4, 8, 6, 6, 0, 6, 2, 7, 6],
+ [3, 6, 6, 2, 7, 6, 1, 5, 5, 0, 5, 4],
+ [6, 2, 2, 8, 8, 6, 7, 6, 1, 8, 8, 5, 5, 4, 1, 5],
+ [9, 5, 5, 4, 10, 1, 1, 6, 6, 10, 1, 7, 7, 6],
+ [1, 6, 6, 10, 10, 1, 1, 7, 7, 6, 0, 7, 9, 5, 5, 4],
+ [0, 10, 10, 4, 10, 5, 5, 4, 3, 10, 6, 10, 10, 7, 7, 6],
+ [7, 6, 6, 10, 10, 7, 10, 8, 5, 4, 4, 10, 10, 5],
+ [6, 9, 9, 5, 5, 6, 6, 11, 11, 9],
+ [3, 6, 6, 11, 0, 6, 0, 5, 5, 6, 9, 5],
+ [0, 11, 0, 5, 5, 11, 1, 5, 5, 6, 6, 11],
+ [6, 11, 3, 6, 3, 5, 5, 6, 1, 5],
+ [2, 10, 10, 1, 9, 5, 5, 11, 11, 9, 5, 6, 6, 11],
+ [0, 11, 0, 6, 6, 11, 9, 6, 5, 6, 9, 5, 2, 10, 10, 1],
+ [8, 5, 5, 11, 5, 6, 6, 11, 0, 5, 10, 5, 5, 2, 2, 10],
+ [6, 11, 3, 6, 3, 5, 5, 6, 2, 10, 10, 3, 10, 5],
+ [5, 8, 9, 5, 5, 2, 2, 8, 5, 6, 6, 2],
+ [9, 5, 5, 6, 6, 9, 6, 0, 6, 2],
+ [1, 5, 5, 8, 8, 1, 5, 6, 6, 8, 8, 2, 6, 2],
+ [1, 5, 5, 6, 6, 1, 6, 2],
+ [3, 6, 6, 1, 6, 10, 10, 1, 8, 6, 5, 6, 6, 9, 9, 5],
+ [10, 1, 0, 10, 0, 6, 6, 10, 9, 5, 5, 0, 5, 6],
+ [5, 6, 6, 10, 10, 5],
+ [10, 5, 5, 6, 6, 10],
+ [11, 5, 5, 10, 10, 11, 7, 5],
+ [11, 5, 5, 10, 10, 11, 7, 5],
+ [5, 11, 7, 5, 5, 10, 10, 11, 1, 9],
+ [10, 7, 7, 5, 5, 10, 10, 11, 8, 1, 1, 9],
+ [11, 1, 2, 11, 7, 1, 7, 5, 5, 1],
+ [2, 7, 7, 1, 7, 5, 5, 1, 2, 11],
+ [9, 7, 7, 5, 5, 9, 9, 2, 2, 7, 2, 11],
+ [7, 5, 5, 2, 2, 7, 2, 11, 5, 9, 9, 2, 2, 8],
+ [2, 5, 5, 10, 10, 2, 3, 5, 7, 5],
+ [8, 2, 8, 5, 5, 2, 7, 5, 10, 2, 5, 10],
+ [1, 9, 5, 10, 10, 3, 3, 5, 7, 5, 10, 2],
+ [8, 2, 2, 9, 1, 9, 7, 2, 10, 2, 2, 5, 5, 10, 7, 5],
+ [3, 5, 5, 1, 7, 5],
+ [7, 0, 7, 1, 7, 5, 5, 1],
+ [3, 9, 3, 5, 5, 9, 7, 5],
+ [7, 9, 5, 9, 7, 5],
+ [5, 8, 4, 5, 5, 10, 10, 8, 10, 11],
+ [5, 0, 4, 5, 5, 11, 11, 0, 5, 10, 10, 11],
+ [1, 9, 4, 10, 10, 8, 10, 11, 4, 5, 5, 10],
+ [10, 11, 11, 4, 4, 10, 4, 5, 5, 10, 3, 4, 4, 1, 1, 9],
+ [2, 5, 5, 1, 2, 8, 8, 5, 2, 11, 4, 5],
+ [4, 11, 11, 0, 4, 5, 5, 11, 2, 11, 11, 1, 5, 1],
+ [2, 5, 5, 0, 5, 9, 2, 11, 11, 5, 4, 5, 5, 8],
+ [4, 5, 5, 9, 2, 11],
+ [2, 5, 5, 10, 10, 2, 3, 5, 3, 4, 4, 5],
+ [5, 10, 10, 2, 2, 5, 2, 4, 4, 5],
+ [3, 10, 10, 2, 3, 5, 5, 10, 8, 5, 4, 5, 1, 9],
+ [5, 10, 10, 2, 2, 5, 2, 4, 4, 5, 1, 9, 9, 2],
+ [4, 5, 5, 8, 5, 3, 5, 1],
+ [4, 5, 5, 0, 5, 1],
+ [4, 5, 5, 8, 5, 3, 0, 5, 5, 9],
+ [4, 5, 5, 9],
+ [4, 11, 7, 4, 9, 11, 9, 10, 10, 11],
+ [9, 7, 7, 4, 9, 11, 9, 10, 10, 11],
+ [1, 10, 10, 11, 11, 1, 11, 4, 4, 1, 7, 4],
+ [1, 4, 4, 3, 1, 10, 10, 4, 7, 4, 4, 11, 10, 11],
+ [4, 11, 7, 4, 9, 11, 9, 2, 2, 11, 9, 1],
+ [9, 7, 7, 4, 9, 11, 9, 1, 1, 11, 2, 11],
+ [7, 4, 4, 11, 4, 2, 2, 11],
+ [7, 4, 4, 11, 4, 2, 2, 11, 3, 4],
+ [2, 9, 9, 10, 10, 2, 2, 7, 7, 9, 7, 4],
+ [9, 10, 10, 7, 7, 9, 7, 4, 10, 2, 2, 7, 7, 0],
+ [7, 10, 10, 3, 10, 2, 7, 4, 4, 10, 1, 10, 10, 0],
+ [1, 10, 10, 2, 7, 4],
+ [9, 1, 1, 4, 1, 7, 7, 4],
+ [9, 1, 1, 4, 1, 7, 7, 4, 8, 1],
+ [3, 4, 7, 4],
+ [7, 4],
+ [9, 10, 10, 8, 10, 11],
+ [9, 3, 9, 11, 9, 10, 10, 11],
+ [1, 10, 10, 0, 10, 8, 10, 11],
+ [1, 10, 10, 3, 10, 11],
+ [2, 11, 11, 1, 11, 9, 9, 1],
+ [9, 3, 9, 11, 2, 9, 9, 1, 2, 11],
+ [2, 11, 11, 0],
+ [2, 11],
+ [8, 2, 8, 10, 10, 2, 9, 10],
+ [9, 10, 10, 2, 2, 9],
+ [8, 2, 8, 10, 10, 2, 1, 8, 1, 10],
+ [1, 10, 10, 2],
+ [8, 1, 9, 1],
+ [9, 1],
+ [],
+ []];
+
+ const snap = (method === 'snapped MC');
+ // const seg_table = (method === 'squarish' ? segTable2 : segTable);
+ const seg_table = segTable;
+
+ let vlist = new Array(12);
+ const vert_offsets = this.calculateVertOffsets(dims);
+
+ const edgeIndex = [[0,1], [1,2], [2,3], [3,0], [4,5], [5,6],
+ [6,7], [7,4], [0,4], [1,5], [2,6], [3,7]];
+
+ let vertex_values = new Float32Array(8);
+ let p0 = [0, 0, 0]; // unused initial value - to make Flow happy
+ let vertex_points = [p0, p0, p0, p0, p0, p0, p0, p0];
+ const size_x = dims[0];
+ const size_y = dims[1];
+ const size_z = dims[2];
+ if (values == null || points == null) return;
+ let vertices = [];
+ let segments = [];
+ let vertex_count = 0;
+ for (let x = 0; x < size_x - 1; x++) {
+ for (let y = 0; y < size_y - 1; y++) {
+ for (let z = 0; z < size_z - 1; z++) {
+ const offset0 = z + size_z * (y + size_y * x);
+ let cubeindex = 0;
+ let i;
+ let j;
+ for (i = 0; i < 8; ++i) {
+ j = offset0 + vert_offsets[i];
+ cubeindex |= (values[j] < isolevel) ? 1 << i : 0;
+ }
+ if (cubeindex === 0 || cubeindex === 255) continue;
+ for (i = 0; i < 8; ++i) {
+ j = offset0 + vert_offsets[i];
+ vertex_values[i] = values[j];
+ vertex_points[i] = points[j];
+ }
+
+ // 12 bit number, indicates which edges are crossed by the isosurface
+ const edge_mask = edgeTable[cubeindex];
+
+ // check which edges are crossed, and estimate the point location
+ // using a weighted average of scalar values at edge endpoints.
+ for (i = 0; i < 12; ++i) {
+ if ((edge_mask & (1 << i)) !== 0) {
+ const e = edgeIndex[i];
+ let mu = (isolevel - vertex_values[e[0]]) /
+ (vertex_values[e[1]] - vertex_values[e[0]]);
+ if (snap === true) {
+ if (mu > 0.85) mu = 1;
+ else if (mu < 0.15) mu = 0;
+ }
+ const p1 = vertex_points[e[0]];
+ const p2 = vertex_points[e[1]];
+ // The number of added vertices could be roughly halved
+ // if we avoided duplicates between neighbouring cells.
+ // Using a map for lookups is too slow, perhaps a big
+ // array would do?
+ vertices.push(p1[0] + (p2[0] - p1[0]) * mu,
+ p1[1] + (p2[1] - p1[1]) * mu,
+ p1[2] + (p2[2] - p1[2]) * mu);
+ vlist[i] = vertex_count++;
+ }
+ }
+ const t = seg_table[cubeindex];
+ for (i = 0; i < t.length; i++) {
+ segments.push(vlist[t[i]]);
+ }
+ }
+ }
+ }
+
+ return { vertices: vertices, segments: segments };
+ }
+
+ // return offsets relative to vertex [0,0,0]
+ calculateVertOffsets(dims) { let ic = this.icn3d; ic.icn3dui;
+ let vert_offsets = [];
+ const cubeVerts = [[0,0,0], [1,0,0], [1,1,0], [0,1,0],
+ [0,0,1], [1,0,1], [1,1,1], [0,1,1]];
+
+ for (let i = 0; i < 8; ++i) {
+ const v = cubeVerts[i];
+ vert_offsets.push(v[0] + dims[2] * (v[1] + dims[1] * v[2]));
+ }
+ return vert_offsets;
+ }
+
+ makeChickenWire(data, typeDetail) { let ic = this.icn3d, me = ic.icn3dui;
+ let geom = new THREE.BufferGeometry();
+ let position = new Float32Array(data.vertices);
+ geom.setAttribute('position', new THREE.BufferAttribute(position, 3));
+
+ // Although almost all browsers support OES_element_index_uint nowadays,
+ // use Uint32 indexes only when needed.
+ let arr = (data.vertices.length < 3*65536 ? new Uint16Array(data.segments) : new Uint32Array(data.segments));
+
+ geom.setIndex(new THREE.BufferAttribute(arr, 1));
+
+ let colorFor2fofc = me.parasCls.thr('#00FFFF');
+ let colorForfofcPos = me.parasCls.thr('#00FF00');
+ let colorForfofcNeg = me.parasCls.thr('#ff0000');
+
+ let color = (typeDetail == '2fofc') ? colorFor2fofc : ((typeDetail == 'fofc_pos') ? colorForfofcPos : colorForfofcNeg);
+ let material = new THREE.LineBasicMaterial({ linewidth: 1, color: color });
+ //return new THREE.LineSegments(geom, material);
+
+ let mesh = new THREE.LineSegments(geom, material);
+ ic.mdl.add(mesh);
+
+ ic.prevMaps.push(mesh);
+ }
+ }
+
+
+ class UnitCell {
+ /*::
+ parameters: number[]
+ orth: number[]
+ frac: number[]
+ */
+ // eslint-disable-next-line max-params
+ constructor(a /*:number*/, b /*:number*/, c /*:number*/,
+ alpha /*:number*/, beta /*:number*/, gamma /*:number*/) {
+ if (a <= 0 || b <= 0 || c <= 0 || alpha <= 0 || beta <= 0 || gamma <= 0) {
+ throw Error('Zero or negative unit cell parameter(s).');
+ }
+ this.parameters = [a, b, c, alpha, beta, gamma];
+ const deg2rad = Math.PI / 180.0;
+ const cos_alpha = Math.cos(deg2rad * alpha);
+ const cos_beta = Math.cos(deg2rad * beta);
+ const cos_gamma = Math.cos(deg2rad * gamma);
+ const sin_alpha = Math.sin(deg2rad * alpha);
+ const sin_beta = Math.sin(deg2rad * beta);
+ const sin_gamma = Math.sin(deg2rad * gamma);
+ if (sin_alpha === 0 || sin_beta === 0 || sin_gamma === 0) {
+ throw Error('Impossible angle - N*180deg.');
+ }
+ const cos_alpha_star_sin_beta = (cos_beta * cos_gamma - cos_alpha) /
+ sin_gamma;
+ const cos_alpha_star = cos_alpha_star_sin_beta / sin_beta;
+ const s1rca2 = Math.sqrt(1.0 - cos_alpha_star * cos_alpha_star);
+ // The orthogonalization matrix we use is described in ITfC B p.262:
+ // "An alternative mode of orthogonalization, used by the Protein
+ // Data Bank and most programs, is to align the a1 axis of the unit
+ // cell with the Cartesian X_1 axis, and to align the a*_3 axis with the
+ // Cartesian X_3 axis."
+ //
+ // Zeros in the matrices below are kept to make matrix multiplication
+ // faster: they make extract_block() 2x (!) faster on V8 4.5.103,
+ // no difference on FF 50.
+ /* eslint-disable no-multi-spaces, comma-spacing */
+ this.orth = [a, b * cos_gamma, c * cos_beta,
+ 0.0, b * sin_gamma, -c * cos_alpha_star_sin_beta,
+ 0.0, 0.0 , c * sin_beta * s1rca2];
+ // based on xtal.js which is based on cctbx.uctbx
+ this.frac = [
+ 1.0 / a,
+ -cos_gamma / (sin_gamma * a),
+ -(cos_gamma * cos_alpha_star_sin_beta + cos_beta * sin_gamma) /
+ (sin_beta * s1rca2 * sin_gamma * a),
+ 0.0,
+ 1.0 / (sin_gamma * b),
+ cos_alpha_star / (s1rca2 * sin_gamma * b),
+ 0.0,
+ 0.0,
+ 1.0 / (sin_beta * s1rca2 * c),
+ ];
+ }
+
+ // This function is only used with matrices frac and orth, which have 3 zeros.
+ // We skip these elements, but it doesn't affect performance (on FF50 and V8).
+ multiply(xyz, mat) {
+ /* eslint-disable indent */
+ return [mat[0] * xyz[0] + mat[1] * xyz[1] + mat[2] * xyz[2],
+ /*mat[3] * xyz[0]*/+ mat[4] * xyz[1] + mat[5] * xyz[2],
+ /*mat[6] * xyz[0] + mat[7] * xyz[1]*/+ mat[8] * xyz[2]];
+ }
+
+ fractionalize(xyz /*:[number,number,number]*/) {
+ return this.multiply(xyz, this.frac);
+ }
+
+ orthogonalize(xyz /*:[number,number,number]*/) {
+ return this.multiply(xyz, this.orth);
+ }
+ }
+
+
+ class GridArray {
+ /*::
+ dim: number[]
+ values: Float32Array
+ */
+ constructor(dim /*:number[]*/) {
+ this.dim = dim; // dimensions of the grid for the entire unit cell
+ this.values = new Float32Array(dim[0] * dim[1] * dim[2]);
+ }
+
+ modulo(a, b) {
+ const reminder = a % b;
+ return reminder >= 0 ? reminder : reminder + b;
+ }
+
+ grid2index(i/*:number*/, j/*:number*/, k/*:number*/) {
+ i = this.modulo(i, this.dim[0]);
+ j = this.modulo(j, this.dim[1]);
+ k = this.modulo(k, this.dim[2]);
+ return this.dim[2] * (this.dim[1] * i + j) + k;
+ }
+
+ grid2index_unchecked(i/*:number*/, j/*:number*/, k/*:number*/) {
+ return this.dim[2] * (this.dim[1] * i + j) + k;
+ }
+
+ grid2frac(i/*:number*/, j/*:number*/, k/*:number*/) {
+ return [i / this.dim[0], j / this.dim[1], k / this.dim[2]];
+ }
+
+ // return grid coordinates (rounded down) for the given fractional coordinates
+ frac2grid(xyz/*:number[]*/) {
+ // at one point "| 0" here made extract_block() 40% faster on V8 3.14,
+ // but I don't see any effect now
+ return [Math.floor(xyz[0] * this.dim[0]) | 0,
+ Math.floor(xyz[1] * this.dim[1]) | 0,
+ Math.floor(xyz[2] * this.dim[2]) | 0];
+ }
+
+ set_grid_value(i/*:number*/, j/*:number*/, k/*:number*/, value/*:number*/) {
+ const idx = this.grid2index(i, j, k);
+ this.values[idx] = value;
+ }
+
+ get_grid_value(i/*:number*/, j/*:number*/, k/*:number*/) {
+ const idx = this.grid2index(i, j, k);
+ return this.values[idx];
+ }
+ }
+
+ /**
+ * @file Mtz Parser
+ * @author Marcin Wojdyr
+ * @private
+ * Modified by Jiyao Wang / https://github.com/ncbi/icn3d
+ */
+
+ class MtzParser {
+ constructor(icn3d) {
+ this.icn3d = icn3d;
+ }
+
+ async mtzParserBase(url, type, sigma, location, bInputSigma) { let ic = this.icn3d, me = ic.icn3dui;
+ let thisClass = this;
+
+ //https://stackoverflow.com/questions/33902299/using-jquery-ajax-to-download-a-binary-file
+ // if(type == '2fofc' && ic.bAjax2fofcccp4) {
+ // ic.mapData.sigma2 = sigma;
+ // ic.setOptionCls.setOption('map', type);
+ // }
+ // else if(type == 'fofc' && ic.bAjaxfofcccp4) {
+ // ic.mapData.sigma = sigma;
+ // ic.setOptionCls.setOption('map', type);
+ // }
+ // else {
+ let arrayBuffer = await me.getXMLHttpRqstPromise(url, 'GET', 'arraybuffer', '');
+ sigma = await thisClass.loadMtzFileBase(arrayBuffer, type, sigma, location, bInputSigma, url);
+
+ // if(type == '2fofc') {
+ // ic.bAjax2fofcccp4 = true;
+ // }
+ // else if(type == 'fofc') {
+ // ic.bAjaxfofcccp4 = true;
+ // }
+
+ ic.setOptionCls.setOption('map', type);
+
+ return sigma;
+ // }
+ }
+
+ loadMtzFile(type) {var ic = this.icn3d, me = ic.icn3dui;
+ let thisClass = this;
+
+ let file = $("#" + ic.pre + "dsn6file" + type)[0].files[0];
+ let sigma = $("#" + ic.pre + "dsn6sigma" + type).val();
+ if(!file) {
+ alert("Please select a file before clicking 'Load'");
+ }
+ else {
+ me.utilsCls.checkFileAPI();
+ let reader = new FileReader();
+ reader.onload = async function(e) { let ic = thisClass.icn3d;
+ sigma = await thisClass.loadMtzFileBase(e.target.result, type, sigma, 'file');
+ me.htmlCls.clickMenuCls.setLogCmd('load map file ' + $("#" + ic.pre + "dsn6file" + type).val() + ' with sigma ' + sigma, false);
+ };
+ reader.readAsArrayBuffer(file);
+ }
+ }
+
+ async loadMtzFileBase(data, type, sigma, location, bInputSigma, url) {var ic = this.icn3d, me = ic.icn3dui;
+ if(ic.bMtz === undefined) {
+ let url = "./script/mtz.js";
+ await me.getAjaxPromise(url, 'script');
+
+ ic.bMtz = true;
+ }
+
+ GemmiMtz().then(function(Gemmi) {
+ let mtz = Gemmi.readMtz(data);
+
+ sigma = ic.ccp4ParserCls.load_maps_from_mtz_buffer(mtz, type, sigma, location, bInputSigma);
+
+ // if(type == '2fofc') {
+ // ic.bAjax2fofcCcp4 = true;
+ // }
+ // else if(type == 'fofc') {
+ // ic.bAjaxfofcCcp4 = true;
+ // }
+ ic.setOptionCls.setOption('map', type);
+ if(url) me.htmlCls.clickMenuCls.setLogCmd('set map ' + type + ' sigma ' + sigma + ' file mtz | ' + encodeURIComponent(url), true);
+
+ return sigma;
+ });
+ }
+
+ async loadMtzFileUrl(type) {var ic = this.icn3d; ic.icn3dui;
+ let url = $("#" + ic.pre + "dsn6fileurl" + type).val();
+ let sigma = $("#" + ic.pre + "dsn6sigmaurl" + type).val();
+ if(!url) {
+ alert("Please input the file URL before clicking 'Load'");
+ }
+ else {
+ sigma = await this.mtzParserBase(url, type, sigma, 'url');
+
+ console.log("### sigma " + sigma);
+ //me.htmlCls.clickMenuCls.setLogCmd('set map ' + type + ' sigma ' + sigma + ' file mtz | ' + encodeURIComponent(url), true);
}
}
@@ -54348,6 +55482,9 @@ var icn3d = (function (exports) {
ic.mapData.header2 = header;
ic.mapData.data2 = density.data;
+ for(let i = 0; i < density.data.length; ++i) {
+ density.data[i];
+ }
let origin = density.box.origin;
let dimensions = density.box.dimensions;
@@ -54382,6 +55519,7 @@ var icn3d = (function (exports) {
origin = density.box.origin;
dimensions = density.box.dimensions;
basis = density.spacegroup.basis;
+
scale = new THREE.Matrix4().makeScale(
dimensions[0] / (sampleCount[0] ),
dimensions[1] / (sampleCount[1] ),
@@ -56010,7 +57148,10 @@ var icn3d = (function (exports) {
if(bAppend) {
if(ic.bSetChainsAdvancedMenu) ic.definedSetsCls.showSets();
- if(ic.bAnnoShown) await ic.showAnnoCls.showAnnotations();
+ if(ic.bAnnoShown) {
+ await ic.showAnnoCls.showAnnotations();
+ ic.annotationCls.resetAnnoTabAll();
+ }
}
// Realign by sequence alignment with the residues in "segment", i.e., transmembrane helix
@@ -57340,12 +58481,12 @@ var icn3d = (function (exports) {
if(i > 0) {
let index1 = alignIndex;
-
+
for(let j = prevIndex1 + 1, jl = start1; j < jl; ++j) {
- if(posChain1[j]) continue;
+ //if(posChain1[j]) continue;
posChain1[j] = 1;
- if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid1][j] === undefined) break;
+ //if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid1][j] === undefined) break;
//let resi = this.getResiAferAlign(chainid1, bRealign, j + 1);
let resi = this.getResiAferAlign(chainid1, bRealign, j);
@@ -57356,18 +58497,19 @@ var icn3d = (function (exports) {
color = me.htmlCls.GREY8;
classname = 'icn3d-nalign';
-
+
ic.nalignHash1[chainid1 + '_' + resi] = 1;
this.setSeqPerResi(chainid1, chainid1, chainid2, resi, resn, false, color, undefined, classname, true, false, index1);
++index1;
}
let index2 = alignIndex;
+
for(let j = prevIndex2 + 1, jl = start2; j < jl; ++j) {
- if(posChain2[j]) continue;
+ //if(posChain2[j]) continue;
posChain2[j] = 1;
- if(ic.chainsSeq[chainid2] === undefined || ic.chainsSeq[chainid2] === undefined) break;
+ //if(ic.chainsSeq[chainid2] === undefined || ic.chainsSeq[chainid2] === undefined) break;
//let resi = this.getResiAferAlign(chainid2, bRealign, j + 1);
let resi = this.getResiAferAlign(chainid2, bRealign, j);
@@ -57413,7 +58555,7 @@ var icn3d = (function (exports) {
}
for(let j = 0; j <= end1 - start1; ++j) {
- if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid2] === undefined) break;
+ ///if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid2] === undefined) break;
let resi1, resi2, resn1, resn2;
/*
@@ -57443,15 +58585,17 @@ var icn3d = (function (exports) {
if(resn1 == '?' || resn2 == '?') continue;
}
else {
- if(ic.chainsSeq[chainid1][j + start1] === undefined || ic.chainsSeq[chainid2][j + start2] === undefined) continue;
+ ///if(ic.chainsSeq[chainid1][j + start1] === undefined || ic.chainsSeq[chainid2][j + start2] === undefined) continue;
// resi1 = ic.chainsSeq[chainid1][j + start1].resi;
// resi2 = ic.chainsSeq[chainid2][j + start2].resi;
// resn1 = ic.chainsSeq[chainid1][j + start1].name.toUpperCase();
// resn2 = ic.chainsSeq[chainid2][j + start2].name.toUpperCase();
- resi1 = this.getResiAferAlign(chainid1, bRealign, j + start1 + 1);
- resi2 = this.getResiAferAlign(chainid2, bRealign, j + start2 + 1);
+ // resi1 = this.getResiAferAlign(chainid1, bRealign, j + start1 + 1);
+ // resi2 = this.getResiAferAlign(chainid2, bRealign, j + start2 + 1);
+ resi1 = this.getResiAferAlign(chainid1, bRealign, j + start1);
+ resi2 = this.getResiAferAlign(chainid2, bRealign, j + start2);
resn1 = this.getResnFromResi(chainid1, resi1).toUpperCase();
resn2 = this.getResnFromResi(chainid2, resi2).toUpperCase();
}
@@ -62507,7 +63651,8 @@ var icn3d = (function (exports) {
let strArray = ic.commands[i].split("|||");
let command = strArray[0].trim();
- if(ic.inputid) ic.bNotLoadStructure = true;
+ // sometimes URL has an ID input, then load a structure in commands
+ //if(ic.inputid) ic.bNotLoadStructure = true;
if(command.indexOf('load') !== -1) {
if(end === 0 && start === end) {
@@ -62543,18 +63688,7 @@ var icn3d = (function (exports) {
}
}
else if(command.indexOf('set map') == 0 && command.indexOf('set map wireframe') == -1) {
- //set map 2fofc sigma 1.5
- let urlArray = strArray[0].trim().split(' | ');
-
- let str = urlArray[0].substr(8);
- let paraArray = str.split(" ");
-
- if(paraArray.length == 3 && paraArray[1] == 'sigma') {
- paraArray[2];
- paraArray[0];
-
- await thisClass.applyCommandMap(strArray[0].trim());
- }
+ await thisClass.applyCommandMap(strArray[0].trim());
}
else if(command.indexOf('set emmap') == 0 && command.indexOf('set emmap wireframe') == -1) {
//set emmap percentage 70
@@ -63054,17 +64188,34 @@ var icn3d = (function (exports) {
// ic.deferredMap = $.Deferred(function() { let ic = thisClass.icn3d;
//"set map 2fofc sigma 1.5"
// or "set map 2fofc sigma 1.5 | [url]"
+
+ // added more para later
+ //"set map 2fofc sigma 1.5 file dsn6"
+ // or "set map 2fofc sigma 1.5 file dsn6 | [url]"
let urlArray = command.split(" | ");
let str = urlArray[0].substr(8);
let paraArray = str.split(" ");
- if(paraArray.length == 3 && paraArray[1] == 'sigma') {
+ //if(paraArray.length == 3 && paraArray[1] == 'sigma') {
+ if(paraArray[1] == 'sigma') {
let sigma = paraArray[2];
let type = paraArray[0];
+ let fileType = 'dsn6';
+ if(paraArray.length == 5) fileType = paraArray[4];
+
if(urlArray.length == 2) {
- await ic.dsn6ParserCls.dsn6ParserBase(urlArray[1], type, sigma);
+ let bInputSigma = true;
+ if(fileType == 'dsn6') {
+ await ic.dsn6ParserCls.dsn6ParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
+ }
+ else if(fileType == 'ccp4') {
+ await ic.ccp4ParserCls.ccp4ParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
+ }
+ else if(fileType == 'mtz') {
+ await ic.mtzParserCls.mtzParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
+ }
}
else {
await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma);
@@ -72008,7 +73159,7 @@ var icn3d = (function (exports) {
}
// from iview (http://istar.cse.cuhk.edu.hk/iview/)
- getAtomsFromPosition(point, threshold) { let ic = this.icn3d, me = ic.icn3dui;
+ getAtomsFromPosition(point, threshold, atoms) { let ic = this.icn3d, me = ic.icn3dui;
let i;
if(threshold === undefined || threshold === null) {
@@ -72016,7 +73167,8 @@ var icn3d = (function (exports) {
}
//for (i in ic.atoms) {
- for (i in ic.dAtoms) {
+ let atomHash = (atoms) ? atoms : ic.dAtoms;
+ for (i in atomHash) {
let atom = ic.atoms[i];
if(ic.ions.hasOwnProperty(i) && ic.opts['ions'] === 'sphere') {
@@ -73588,6 +74740,8 @@ var icn3d = (function (exports) {
this.alignParserCls = new AlignParser(this);
this.chainalignParserCls = new ChainalignParser(this);
this.dsn6ParserCls = new Dsn6Parser(this);
+ this.ccp4ParserCls = new Ccp4Parser(this);
+ this.mtzParserCls = new MtzParser(this);
this.mmcifParserCls = new MmcifParser(this);
this.mmdbParserCls = new MmdbParser(this);
this.mmtfParserCls = new MmtfParser(this);
@@ -73850,7 +75004,7 @@ var icn3d = (function (exports) {
//even when multiple iCn3D viewers are shown together.
this.pre = this.cfg.divid + "_";
- this.REVISION = '3.28.4';
+ this.REVISION = '3.29.0';
// In nodejs, iCn3D defines "window = {navigator: {}}"
this.bNode = (Object.keys(window).length < 2) ? true : false;
diff --git a/build/icn3d.min.js b/build/icn3d.min.js
index d2c65baa..b5d61ea9 100644
--- a/build/icn3d.min.js
+++ b/build/icn3d.min.js
@@ -1,5 +1,5 @@
var $NGL_shaderTextHash={};$NGL_shaderTextHash["SphereImpostor.frag"]=["#define STANDARD","#define IMPOSTOR","","uniform vec3 diffuse;","uniform vec3 emissive;","uniform float roughness;","uniform float metalness;","uniform float opacity;","uniform float nearClip;","uniform mat4 projectionMatrix;","uniform float ortho;","","varying float vRadius;","varying float vRadiusSq;","varying vec3 vPoint;","varying vec3 vPointViewPosition;","","#ifdef PICKING"," uniform float objectId;"," varying vec3 vPickingColor;","#else"," #include common"," #include color_pars_fragment"," #include fog_pars_fragment"," #include bsdfs"," #include lights_pars_begin"," #include lights_physical_pars_fragment","#endif","","bool flag2 = false;","bool interior = false;","vec3 cameraPos;","vec3 cameraNormal;","","// Calculate depth based on the given camera position.","float calcDepth( in vec3 cameraPos ){"," vec2 clipZW = cameraPos.z * projectionMatrix[2].zw + projectionMatrix[3].zw;"," return 0.5 + 0.5 * clipZW.x / clipZW.y;","}","","float calcClip( vec3 cameraPos ){"," return dot( vec4( cameraPos, 1.0 ), vec4( 0.0, 0.0, 1.0, nearClip - 0.5 ) );","}","","bool Impostor( out vec3 cameraPos, out vec3 cameraNormal ){",""," vec3 cameraSpherePos = -vPointViewPosition;"," cameraSpherePos.z += vRadius;",""," vec3 rayOrigin = mix( vec3( 0.0, 0.0, 0.0 ), vPoint, ortho );"," vec3 rayDirection = mix( normalize( vPoint ), vec3( 0.0, 0.0, 1.0 ), ortho );"," vec3 cameraSphereDir = mix( cameraSpherePos, rayOrigin - cameraSpherePos, ortho );",""," float B = dot( rayDirection, cameraSphereDir );"," float det = B * B + vRadiusSq - dot( cameraSphereDir, cameraSphereDir );",""," if( det < 0.0 ){"," discard;"," return false;"," }"," float sqrtDet = sqrt( det );"," float posT = mix( B + sqrtDet, B + sqrtDet, ortho );"," float negT = mix( B - sqrtDet, sqrtDet - B, ortho );",""," cameraPos = rayDirection * negT + rayOrigin;",""," #ifdef NEAR_CLIP","if( calcDepth( cameraPos ) <= 0.0 ){"," cameraPos = rayDirection * posT + rayOrigin;"," interior = true;"," return false;","}else if( calcClip( cameraPos ) > 0.0 ){"," cameraPos = rayDirection * posT + rayOrigin;"," interior = true;"," flag2 = true;"," return false;","}else{"," cameraNormal = normalize( cameraPos - cameraSpherePos );","}"," #else","if( calcDepth( cameraPos ) <= 0.0 ){"," cameraPos = rayDirection * posT + rayOrigin;"," interior = true;"," return false;","}else{"," cameraNormal = normalize( cameraPos - cameraSpherePos );","}"," #endif",""," cameraNormal = normalize( cameraPos - cameraSpherePos );"," cameraNormal *= float(!interior) * 2.0 - 1.0;"," return !interior;","","}","","void main(void){",""," bool flag = Impostor( cameraPos, cameraNormal );",""," #ifdef NEAR_CLIP"," if( calcClip( cameraPos ) > 0.0 )"," discard;"," #endif",""," // FIXME not compatible with custom clipping plane"," //Set the depth based on the new cameraPos."," gl_FragDepthEXT = calcDepth( cameraPos );"," if( !flag ){",""," // clamp to near clipping plane and add a tiny value to"," // make spheres with a greater radius occlude smaller ones"," #ifdef NEAR_CLIP","if( flag2 ){"," gl_FragDepthEXT = max( 0.0, calcDepth( vec3( - ( nearClip - 0.5 ) ) ) + ( 0.0000001 / vRadius ) );","}else if( gl_FragDepthEXT >= 0.0 ){"," gl_FragDepthEXT = 0.0 + ( 0.0000001 / vRadius );","}"," #else","if( gl_FragDepthEXT >= 0.0 ){"," gl_FragDepthEXT = 0.0 + ( 0.0000001 / vRadius );","}"," #endif",""," }",""," // bugfix (mac only?)"," if (gl_FragDepthEXT < 0.0)"," discard;"," if (gl_FragDepthEXT > 1.0)"," discard;",""," #ifdef PICKING",""," gl_FragColor = vec4( vPickingColor, objectId );",""," #else",""," vec3 vNormal = cameraNormal;"," vec3 vViewPosition = -cameraPos;",""," vec4 diffuseColor = vec4( diffuse, opacity );"," ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );"," vec3 totalEmissiveLight = emissive;",""," #include color_fragment"," #include roughnessmap_fragment"," #include metalnessmap_fragment",""," // don't use include normal_fragment"," vec3 normal = normalize( vNormal );",""," #include lights_physical_fragment"," //include lights_template"," #include lights_fragment_begin"," #include lights_fragment_end",""," vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveLight;",""," gl_FragColor = vec4( outgoingLight, diffuseColor.a );"," //gl_FragColor = vec4( reflectedLight.directSpecular, diffuseColor.a );",""," #include premultiplied_alpha_fragment"," #include tonemapping_fragment"," #include encodings_fragment"," //include fog_fragment"," #ifdef USE_FOG"," #ifdef USE_LOGDEPTHBUF_EXT"," float depth = gl_FragDepthEXT / gl_FragCoord.w;"," #else"," float depth = gl_FragCoord.z / gl_FragCoord.w;"," #endif"," #ifdef FOG_EXP2"," float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );"," #else"," float fogFactor = smoothstep( fogNear, fogFar, depth );"," #endif"," gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );"," #endif",""," #endif","","}"].join("\n"),$NGL_shaderTextHash["SphereImpostor.vert"]=["uniform mat4 projectionMatrixInverse;","uniform float nearClip;","","varying float vRadius;","varying float vRadiusSq;","varying vec3 vPoint;","varying vec3 vPointViewPosition;","varying float fogDepth;","varying float fogNear;","varying float fogFar;","","attribute vec2 mapping;","//attribute vec3 position;","attribute float radius;","","#ifdef PICKING"," #include unpack_clr"," attribute float primitiveId;"," varying vec3 vPickingColor;","#else"," #include color_pars_vertex","#endif","","//include matrix_scale","float matrixScale( in mat4 m ){"," vec4 r = m[ 0 ];"," return sqrt( r[ 0 ] * r[ 0 ] + r[ 1 ] * r[ 1 ] + r[ 2 ] * r[ 2 ] );","}","","const mat4 D = mat4("," 1.0, 0.0, 0.0, 0.0,"," 0.0, 1.0, 0.0, 0.0,"," 0.0, 0.0, 1.0, 0.0,"," 0.0, 0.0, 0.0, -1.0",");","","mat4 transposeTmp( in mat4 inMatrix ) {"," vec4 i0 = inMatrix[0];"," vec4 i1 = inMatrix[1];"," vec4 i2 = inMatrix[2];"," vec4 i3 = inMatrix[3];",""," mat4 outMatrix = mat4("," vec4(i0.x, i1.x, i2.x, i3.x),"," vec4(i0.y, i1.y, i2.y, i3.y),"," vec4(i0.z, i1.z, i2.z, i3.z),"," vec4(i0.w, i1.w, i2.w, i3.w)"," );"," return outMatrix;","}","","//------------------------------------------------------------------------------","// Compute point size and center using the technique described in:","// 'GPU-Based Ray-Casting of Quadratic Surfaces'","// by Christian Sigg, Tim Weyrich, Mario Botsch, Markus Gross.","//","// Code based on","/*=========================================================================",""," Program: Visualization Toolkit"," Module: Quadrics_fs.glsl and Quadrics_vs.glsl",""," Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen"," All rights reserved."," See Copyright.txt or http://www.kitware.com/Copyright.htm for details.",""," This software is distributed WITHOUT ANY WARRANTY; without even"," the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR"," PURPOSE. See the above copyright notice for more information.",""," =========================================================================*/","","// .NAME Quadrics_fs.glsl and Quadrics_vs.glsl","// .SECTION Thanks","// ","//","// This file is part of the PointSprites plugin developed and contributed by","//","// Copyright (c) CSCS - Swiss National Supercomputing Centre","// EDF - Electricite de France","//","// John Biddiscombe, Ugo Varetto (CSCS)","// Stephane Ploix (EDF)","//","// ","//","// Contributions by Alexander Rose","// - ported to WebGL","// - adapted to work with quads","void ComputePointSizeAndPositionInClipCoordSphere(){",""," vec2 xbc;"," vec2 ybc;",""," mat4 T = mat4("," radius, 0.0, 0.0, 0.0,"," 0.0, radius, 0.0, 0.0,"," 0.0, 0.0, radius, 0.0,"," position.x, position.y, position.z, 1.0"," );",""," mat4 R = transposeTmp( projectionMatrix * modelViewMatrix * T );"," float A = dot( R[ 3 ], D * R[ 3 ] );"," float B = -2.0 * dot( R[ 0 ], D * R[ 3 ] );"," float C = dot( R[ 0 ], D * R[ 0 ] );"," xbc[ 0 ] = ( -B - sqrt( B * B - 4.0 * A * C ) ) / ( 2.0 * A );"," xbc[ 1 ] = ( -B + sqrt( B * B - 4.0 * A * C ) ) / ( 2.0 * A );"," float sx = abs( xbc[ 0 ] - xbc[ 1 ] ) * 0.5;",""," A = dot( R[ 3 ], D * R[ 3 ] );"," B = -2.0 * dot( R[ 1 ], D * R[ 3 ] );"," C = dot( R[ 1 ], D * R[ 1 ] );"," ybc[ 0 ] = ( -B - sqrt( B * B - 4.0 * A * C ) ) / ( 2.0 * A );"," ybc[ 1 ] = ( -B + sqrt( B * B - 4.0 * A * C ) ) / ( 2.0 * A );"," float sy = abs( ybc[ 0 ] - ybc[ 1 ] ) * 0.5;",""," gl_Position.xy = vec2( 0.5 * ( xbc.x + xbc.y ), 0.5 * ( ybc.x + ybc.y ) );"," gl_Position.xy -= mapping * vec2( sx, sy );"," gl_Position.xy *= gl_Position.w;","","}","","void main(void){",""," #ifdef PICKING"," vPickingColor = unpackColor( primitiveId );"," #else"," #include color_vertex"," #endif",""," vRadius = radius * matrixScale( modelViewMatrix );",""," vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );"," // avoid clipping, added again in fragment shader"," mvPosition.z -= vRadius;",""," gl_Position = projectionMatrix * vec4( mvPosition.xyz, 1.0 );"," ComputePointSizeAndPositionInClipCoordSphere();","",""," vRadiusSq = vRadius * vRadius;"," vec4 vPoint4 = projectionMatrixInverse * gl_Position;"," vPoint = vPoint4.xyz / vPoint4.w;"," vPointViewPosition = -mvPosition.xyz / mvPosition.w;","","}"].join("\n"),$NGL_shaderTextHash["CylinderImpostor.frag"]=["#define STANDARD","#define IMPOSTOR","","// Open-Source PyMOL is Copyright (C) Schrodinger, LLC.","//","// All Rights Reserved","//","// Permission to use, copy, modify, distribute, and distribute modified","// versions of this software and its built-in documentation for any","// purpose and without fee is hereby granted, provided that the above","// copyright notice appears in all copies and that both the copyright","// notice and this permission notice appear in supporting documentation,","// and that the name of Schrodinger, LLC not be used in advertising or","// publicity pertaining to distribution of the software without specific,","// written prior permission.","//","// SCHRODINGER, LLC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,","// INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN","// NO EVENT SHALL SCHRODINGER, LLC BE LIABLE FOR ANY SPECIAL, INDIRECT OR","// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS","// OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE","// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE","// USE OR PERFORMANCE OF THIS SOFTWARE.","","// Contributions by Alexander Rose","// - ported to WebGL","// - dual color","// - pk color","// - custom clipping","// - three.js lighting","","uniform vec3 diffuse;","uniform vec3 emissive;","uniform float roughness;","uniform float metalness;","uniform float opacity;","uniform float nearClip;","uniform mat4 projectionMatrix;","uniform float ortho;","","varying vec3 axis;","varying vec4 base_radius;","varying vec4 end_b;","varying vec3 U;","varying vec3 V;","varying vec4 w;","","#ifdef PICKING"," uniform float objectId;"," varying vec3 vPickingColor;","#else"," varying vec3 vColor1;"," varying vec3 vColor2;"," #include common"," #include fog_pars_fragment"," #include bsdfs"," #include lights_pars_begin"," #include lights_physical_pars_fragment","#endif","","bool interior = false;","","float distSq3( vec3 v3a, vec3 v3b ){"," return ("," ( v3a.x - v3b.x ) * ( v3a.x - v3b.x ) +"," ( v3a.y - v3b.y ) * ( v3a.y - v3b.y ) +"," ( v3a.z - v3b.z ) * ( v3a.z - v3b.z )"," );","}","","// Calculate depth based on the given camera position.","float calcDepth( in vec3 cameraPos ){"," vec2 clipZW = cameraPos.z * projectionMatrix[2].zw + projectionMatrix[3].zw;"," return 0.5 + 0.5 * clipZW.x / clipZW.y;","}","","float calcClip( vec3 cameraPos ){"," return dot( vec4( cameraPos, 1.0 ), vec4( 0.0, 0.0, 1.0, nearClip - 0.5 ) );","}","","void main(){",""," vec3 point = w.xyz / w.w;",""," // unpacking"," vec3 base = base_radius.xyz;"," float vRadius = base_radius.w;"," vec3 end = end_b.xyz;"," float b = end_b.w;",""," vec3 end_cyl = end;"," vec3 surface_point = point;",""," vec3 ray_target = surface_point;"," vec3 ray_origin = vec3(0.0);"," vec3 ray_direction = mix(normalize(ray_origin - ray_target), vec3(0.0, 0.0, 1.0), ortho);"," mat3 basis = mat3( U, V, axis );",""," vec3 diff = ray_target - 0.5 * (base + end_cyl);"," vec3 P = diff * basis;",""," // angle (cos) between cylinder cylinder_axis and ray direction"," float dz = dot( axis, ray_direction );",""," float radius2 = vRadius*vRadius;",""," // calculate distance to the cylinder from ray origin"," vec3 D = vec3(dot(U, ray_direction),"," dot(V, ray_direction),"," dz);"," float a0 = P.x*P.x + P.y*P.y - radius2;"," float a1 = P.x*D.x + P.y*D.y;"," float a2 = D.x*D.x + D.y*D.y;",""," // calculate a dicriminant of the above quadratic equation"," float d = a1*a1 - a0*a2;"," if (d < 0.0)"," // outside of the cylinder"," discard;",""," float dist = (-a1 + sqrt(d)) / a2;",""," // point of intersection on cylinder surface"," vec3 new_point = ray_target + dist * ray_direction;",""," vec3 tmp_point = new_point - base;"," vec3 _normal = normalize( tmp_point - axis * dot(tmp_point, axis) );",""," ray_origin = mix( ray_origin, surface_point, ortho );",""," // test caps"," float front_cap_test = dot( tmp_point, axis );"," float end_cap_test = dot((new_point - end_cyl), axis);",""," // to calculate caps, simply check the angle between"," // the point of intersection - cylinder end vector"," // and a cap plane normal (which is the cylinder cylinder_axis)"," // if the angle < 0, the point is outside of cylinder"," // test front cap",""," #ifndef CAP"," vec3 new_point2 = ray_target + ( (-a1 - sqrt(d)) / a2 ) * ray_direction;"," vec3 tmp_point2 = new_point2 - base;"," #endif",""," // flat"," if (front_cap_test < 0.0)"," {"," // ray-plane intersection"," float dNV = dot(-axis, ray_direction);"," if (dNV < 0.0)"," discard;"," float near = dot(-axis, (base)) / dNV;"," vec3 front_point = ray_direction * near + ray_origin;"," // within the cap radius?"," if (dot(front_point - base, front_point-base) > radius2)"," discard;",""," #ifdef CAP"," new_point = front_point;"," _normal = axis;"," #else"," new_point = ray_target + ( (-a1 - sqrt(d)) / a2 ) * ray_direction;"," dNV = dot(-axis, ray_direction);"," near = dot(axis, end_cyl) / dNV;"," new_point2 = ray_direction * near + ray_origin;"," if (dot(new_point2 - end_cyl, new_point2-base) < radius2)"," discard;"," interior = true;"," #endif"," }",""," // test end cap","",""," // flat"," if( end_cap_test > 0.0 )"," {"," // ray-plane intersection"," float dNV = dot(axis, ray_direction);"," if (dNV < 0.0)"," discard;"," float near = dot(axis, end_cyl) / dNV;"," vec3 end_point = ray_direction * near + ray_origin;"," // within the cap radius?"," if( dot(end_point - end_cyl, end_point-base) > radius2 )"," discard;",""," #ifdef CAP"," new_point = end_point;"," _normal = axis;"," #else"," new_point = ray_target + ( (-a1 - sqrt(d)) / a2 ) * ray_direction;"," dNV = dot(-axis, ray_direction);"," near = dot(-axis, (base)) / dNV;"," new_point2 = ray_direction * near + ray_origin;"," if (dot(new_point2 - base, new_point2-base) < radius2)"," discard;"," interior = true;"," #endif"," }",""," gl_FragDepthEXT = calcDepth( new_point );",""," #ifdef NEAR_CLIP"," if( calcClip( new_point ) > 0.0 ){"," dist = (-a1 - sqrt(d)) / a2;"," new_point = ray_target + dist * ray_direction;"," if( calcClip( new_point ) > 0.0 )"," discard;"," interior = true;"," gl_FragDepthEXT = calcDepth( new_point );"," if( gl_FragDepthEXT >= 0.0 ){"," gl_FragDepthEXT = max( 0.0, calcDepth( vec3( - ( nearClip - 0.5 ) ) ) + ( 0.0000001 / vRadius ) );"," }"," }else if( gl_FragDepthEXT <= 0.0 ){"," dist = (-a1 - sqrt(d)) / a2;"," new_point = ray_target + dist * ray_direction;"," interior = true;"," gl_FragDepthEXT = calcDepth( new_point );"," if( gl_FragDepthEXT >= 0.0 ){"," gl_FragDepthEXT = 0.0 + ( 0.0000001 / vRadius );"," }"," }"," #else"," if( gl_FragDepthEXT <= 0.0 ){"," dist = (-a1 - sqrt(d)) / a2;"," new_point = ray_target + dist * ray_direction;"," interior = true;"," gl_FragDepthEXT = calcDepth( new_point );"," if( gl_FragDepthEXT >= 0.0 ){"," gl_FragDepthEXT = 0.0 + ( 0.0000001 / vRadius );"," }"," }"," #endif",""," // this is a workaround necessary for Mac"," // otherwise the modified fragment won't clip properly"," if (gl_FragDepthEXT < 0.0)"," discard;"," if (gl_FragDepthEXT > 1.0)"," discard;",""," #ifdef PICKING",""," gl_FragColor = vec4( vPickingColor, objectId );",""," #else",""," vec3 vViewPosition = -new_point;"," vec3 vNormal = _normal;"," vec3 vColor;",""," if( distSq3( new_point, end_cyl ) < distSq3( new_point, base ) ){"," if( b < 0.0 ){"," vColor = vColor1;"," }else{"," vColor = vColor2;"," }"," }else{"," if( b > 0.0 ){"," vColor = vColor1;"," }else{"," vColor = vColor2;"," }"," }",""," vec4 diffuseColor = vec4( diffuse, opacity );"," ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );"," vec3 totalEmissiveLight = emissive;",""," #include color_fragment"," //ifdef USE_COLOR"," //diffuseColor.r *= vColor[0];"," //diffuseColor.g *= vColor[1];"," //diffuseColor.b *= vColor[2];"," //endif"," #include roughnessmap_fragment"," #include metalnessmap_fragment",""," // don't use include normal_fragment"," vec3 normal = normalize( vNormal );",""," #include lights_physical_fragment"," //include lights_template"," #include lights_fragment_begin"," #include lights_fragment_end",""," vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveLight;",""," gl_FragColor = vec4( outgoingLight, diffuseColor.a );"," //gl_FragColor = vec4( reflectedLight.directSpecular, diffuseColor.a );",""," #include premultiplied_alpha_fragment"," #include tonemapping_fragment"," #include encodings_fragment"," //include fog_fragment"," #ifdef USE_FOG"," #ifdef USE_LOGDEPTHBUF_EXT"," float depth = gl_FragDepthEXT / gl_FragCoord.w;"," #else"," float depth = gl_FragCoord.z / gl_FragCoord.w;"," #endif"," #ifdef FOG_EXP2"," float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );"," #else"," float fogFactor = smoothstep( fogNear, fogFar, depth );"," #endif"," gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );"," #endif",""," #endif","","}"].join("\n"),$NGL_shaderTextHash["CylinderImpostor.vert"]=["// Open-Source PyMOL is Copyright (C) Schrodinger, LLC.","//","// All Rights Reserved","//","// Permission to use, copy, modify, distribute, and distribute modified","// versions of this software and its built-in documentation for any","// purpose and without fee is hereby granted, provided that the above","// copyright notice appears in all copies and that both the copyright","// notice and this permission notice appear in supporting documentation,","// and that the name of Schrodinger, LLC not be used in advertising or","// publicity pertaining to distribution of the software without specific,","// written prior permission.","//","// SCHRODINGER, LLC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,","// INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN","// NO EVENT SHALL SCHRODINGER, LLC BE LIABLE FOR ANY SPECIAL, INDIRECT OR","// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS","// OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE","// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE","// USE OR PERFORMANCE OF THIS SOFTWARE.","","// Contributions by Alexander Rose","// - ported to WebGL","// - dual color","// - pk color","// - shift","","attribute vec3 mapping;","attribute vec3 position1;","attribute vec3 position2;","attribute float radius;","","varying vec3 axis;","varying vec4 base_radius;","varying vec4 end_b;","varying vec3 U;","varying vec3 V;","varying vec4 w;","varying float fogDepth;","varying float fogNear;","varying float fogFar;","","#ifdef PICKING"," #include unpack_clr"," attribute float primitiveId;"," varying vec3 vPickingColor;","#else"," //attribute vec3 color;"," attribute vec3 color2;"," varying vec3 vColor1;"," varying vec3 vColor2;","#endif","","uniform mat4 modelViewMatrixInverse;","uniform float ortho;","","//include matrix_scale","float matrixScale( in mat4 m ){"," vec4 r = m[ 0 ];"," return sqrt( r[ 0 ] * r[ 0 ] + r[ 1 ] * r[ 1 ] + r[ 2 ] * r[ 2 ] );","}","","void main(){",""," #ifdef PICKING"," vPickingColor = unpackColor( primitiveId );"," #else"," vColor1 = color;"," vColor2 = color2;"," #endif",""," // vRadius = radius;"," base_radius.w = radius * matrixScale( modelViewMatrix );",""," //vec3 center = position;"," vec3 center = ( position2 + position1 ) / 2.0;"," vec3 dir = normalize( position2 - position1 );"," float ext = length( position2 - position1 ) / 2.0;",""," // using cameraPosition fails on some machines, not sure why"," // vec3 cam_dir = normalize( cameraPosition - mix( center, vec3( 0.0 ), ortho ) );"," vec3 cam_dir;"," if( ortho == 0.0 ){"," cam_dir = ( modelViewMatrixInverse * vec4( 0, 0, 0, 1 ) ).xyz - center;"," }else{"," cam_dir = ( modelViewMatrixInverse * vec4( 0, 0, 1, 0 ) ).xyz;"," }"," cam_dir = normalize( cam_dir );",""," vec3 ldir;",""," float b = dot( cam_dir, dir );"," end_b.w = b;"," // direction vector looks away, so flip"," if( b < 0.0 )"," ldir = -ext * dir;"," // direction vector already looks in my direction"," else"," ldir = ext * dir;",""," vec3 left = normalize( cross( cam_dir, ldir ) );"," left = radius * left;"," vec3 up = radius * normalize( cross( left, ldir ) );",""," // transform to modelview coordinates"," axis = normalize( normalMatrix * ldir );"," U = normalize( normalMatrix * up );"," V = normalize( normalMatrix * left );",""," vec4 base4 = modelViewMatrix * vec4( center - ldir, 1.0 );"," base_radius.xyz = base4.xyz / base4.w;",""," vec4 top_position = modelViewMatrix * vec4( center + ldir, 1.0 );"," vec4 end4 = top_position;"," end_b.xyz = end4.xyz / end4.w;",""," w = modelViewMatrix * vec4("," center + mapping.x*ldir + mapping.y*left + mapping.z*up, 1.0"," );",""," gl_Position = projectionMatrix * w;",""," // avoid clipping (1.0 seems to induce flickering with some drivers)"," gl_Position.z = 0.99;","","}"].join("\n"),$NGL_shaderTextHash["SphereInstancing.frag"]=$NGL_shaderTextHash["SphereImpostor.frag"],$NGL_shaderTextHash["SphereInstancing.vert"]=["uniform mat4 projectionMatrixInverse;","uniform float nearClip;","","varying float vRadius;","varying float vRadiusSq;","varying vec3 vPoint;","varying vec3 vPointViewPosition;","varying float fogDepth;","varying float fogNear;","varying float fogFar;","","attribute vec2 mapping;","//attribute vec3 position;","attribute float radius;","attribute vec4 matrix1;","attribute vec4 matrix2;","attribute vec4 matrix3;","attribute vec4 matrix4;","","#ifdef PICKING"," #include unpack_clr"," attribute float primitiveId;"," varying vec3 vPickingColor;","#else"," #include color_pars_vertex","#endif","","//include matrix_scale","float matrixScale( in mat4 m ){"," vec4 r = m[ 0 ];"," return sqrt( r[ 0 ] * r[ 0 ] + r[ 1 ] * r[ 1 ] + r[ 2 ] * r[ 2 ] );","}","","const mat4 D = mat4("," 1.0, 0.0, 0.0, 0.0,"," 0.0, 1.0, 0.0, 0.0,"," 0.0, 0.0, 1.0, 0.0,"," 0.0, 0.0, 0.0, -1.0",");","","mat4 transposeTmp( in mat4 inMatrix ) {"," vec4 i0 = inMatrix[0];"," vec4 i1 = inMatrix[1];"," vec4 i2 = inMatrix[2];"," vec4 i3 = inMatrix[3];",""," mat4 outMatrix = mat4("," vec4(i0.x, i1.x, i2.x, i3.x),"," vec4(i0.y, i1.y, i2.y, i3.y),"," vec4(i0.z, i1.z, i2.z, i3.z),"," vec4(i0.w, i1.w, i2.w, i3.w)"," );"," return outMatrix;","}","","//------------------------------------------------------------------------------","// Compute point size and center using the technique described in:","// 'GPU-Based Ray-Casting of Quadratic Surfaces'","// by Christian Sigg, Tim Weyrich, Mario Botsch, Markus Gross.","//","// Code based on","/*=========================================================================",""," Program: Visualization Toolkit"," Module: Quadrics_fs.glsl and Quadrics_vs.glsl",""," Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen"," All rights reserved."," See Copyright.txt or http://www.kitware.com/Copyright.htm for details.",""," This software is distributed WITHOUT ANY WARRANTY; without even"," the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR"," PURPOSE. See the above copyright notice for more information.",""," =========================================================================*/","","// .NAME Quadrics_fs.glsl and Quadrics_vs.glsl","// .SECTION Thanks","// ","//","// This file is part of the PointSprites plugin developed and contributed by","//","// Copyright (c) CSCS - Swiss National Supercomputing Centre","// EDF - Electricite de France","//","// John Biddiscombe, Ugo Varetto (CSCS)","// Stephane Ploix (EDF)","//","// ","//","// Contributions by Alexander Rose","// - ported to WebGL","// - adapted to work with quads","void ComputePointSizeAndPositionInClipCoordSphere(vec4 updatePosition){",""," vec2 xbc;"," vec2 ybc;",""," mat4 T = mat4("," radius, 0.0, 0.0, 0.0,"," 0.0, radius, 0.0, 0.0,"," 0.0, 0.0, radius, 0.0,"," updatePosition.x, updatePosition.y, updatePosition.z, 1.0"," );",""," mat4 R = transposeTmp( projectionMatrix * modelViewMatrix * T );"," float A = dot( R[ 3 ], D * R[ 3 ] );"," float B = -2.0 * dot( R[ 0 ], D * R[ 3 ] );"," float C = dot( R[ 0 ], D * R[ 0 ] );"," xbc[ 0 ] = ( -B - sqrt( B * B - 4.0 * A * C ) ) / ( 2.0 * A );"," xbc[ 1 ] = ( -B + sqrt( B * B - 4.0 * A * C ) ) / ( 2.0 * A );"," float sx = abs( xbc[ 0 ] - xbc[ 1 ] ) * 0.5;",""," A = dot( R[ 3 ], D * R[ 3 ] );"," B = -2.0 * dot( R[ 1 ], D * R[ 3 ] );"," C = dot( R[ 1 ], D * R[ 1 ] );"," ybc[ 0 ] = ( -B - sqrt( B * B - 4.0 * A * C ) ) / ( 2.0 * A );"," ybc[ 1 ] = ( -B + sqrt( B * B - 4.0 * A * C ) ) / ( 2.0 * A );"," float sy = abs( ybc[ 0 ] - ybc[ 1 ] ) * 0.5;",""," gl_Position.xy = vec2( 0.5 * ( xbc.x + xbc.y ), 0.5 * ( ybc.x + ybc.y ) );"," gl_Position.xy -= mapping * vec2( sx, sy );"," gl_Position.xy *= gl_Position.w;","","}",""," mat4 computeMat(vec4 v1, vec4 v2, vec4 v3, vec4 v4) {"," return mat4("," v1.x, v1.y, v1.z, v1.w,"," v2.x, v2.y, v2.z, v2.w,"," v3.x, v3.y, v3.z, v3.w,"," v4.x, v4.y, v4.z, v4.w"," );"," }","","void main(void){",""," #ifdef PICKING"," vPickingColor = unpackColor( primitiveId );"," #else"," #include color_vertex"," #endif",""," vRadius = radius * matrixScale( modelViewMatrix );",""," mat4 matrix = computeMat(matrix1, matrix2, matrix3, matrix4);"," vec4 updatePosition = matrix * vec4(position, 1.0);","","// vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );"," vec4 mvPosition = modelViewMatrix * vec4( updatePosition.xyz, 1.0 );"," // avoid clipping, added again in fragment shader"," mvPosition.z -= vRadius;","","// gl_Position = projectionMatrix * vec4( mvPosition.xyz, 1.0 );"," gl_Position = projectionMatrix * vec4( mvPosition.xyz, 1.0 );"," ComputePointSizeAndPositionInClipCoordSphere(updatePosition);","",""," vRadiusSq = vRadius * vRadius;"," vec4 vPoint4 = projectionMatrixInverse * gl_Position;"," vPoint = vPoint4.xyz / vPoint4.w;"," vPointViewPosition = -mvPosition.xyz / mvPosition.w;","","}"].join("\n"),$NGL_shaderTextHash["CylinderInstancing.frag"]=$NGL_shaderTextHash["CylinderImpostor.frag"],$NGL_shaderTextHash["CylinderInstancing.vert"]=["// Open-Source PyMOL is Copyright (C) Schrodinger, LLC.","//","// All Rights Reserved","//","// Permission to use, copy, modify, distribute, and distribute modified","// versions of this software and its built-in documentation for any","// purpose and without fee is hereby granted, provided that the above","// copyright notice appears in all copies and that both the copyright","// notice and this permission notice appear in supporting documentation,","// and that the name of Schrodinger, LLC not be used in advertising or","// publicity pertaining to distribution of the software without specific,","// written prior permission.","//","// SCHRODINGER, LLC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,","// INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN","// NO EVENT SHALL SCHRODINGER, LLC BE LIABLE FOR ANY SPECIAL, INDIRECT OR","// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS","// OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE","// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE","// USE OR PERFORMANCE OF THIS SOFTWARE.","","// Contributions by Alexander Rose","// - ported to WebGL","// - dual color","// - pk color","// - shift","","attribute vec3 mapping;","attribute vec3 position1;","attribute vec3 position2;","attribute float radius;","attribute vec4 matrix1;","attribute vec4 matrix2;","attribute vec4 matrix3;","attribute vec4 matrix4;","","varying vec3 axis;","varying vec4 base_radius;","varying vec4 end_b;","varying vec3 U;","varying vec3 V;","varying vec4 w;","varying float fogDepth;","varying float fogNear;","varying float fogFar;","","#ifdef PICKING"," #include unpack_clr"," attribute float primitiveId;"," varying vec3 vPickingColor;","#else"," //attribute vec3 color;"," attribute vec3 color2;"," varying vec3 vColor1;"," varying vec3 vColor2;","#endif","","uniform mat4 modelViewMatrixInverse;","uniform float ortho;","","//include matrix_scale","float matrixScale( in mat4 m ){"," vec4 r = m[ 0 ];"," return sqrt( r[ 0 ] * r[ 0 ] + r[ 1 ] * r[ 1 ] + r[ 2 ] * r[ 2 ] );","}",""," mat4 computeMat(vec4 v1, vec4 v2, vec4 v3, vec4 v4) {"," return mat4("," v1.x, v1.y, v1.z, v1.w,"," v2.x, v2.y, v2.z, v2.w,"," v3.x, v3.y, v3.z, v3.w,"," v4.x, v4.y, v4.z, v4.w"," );"," }","","void main(){",""," #ifdef PICKING"," vPickingColor = unpackColor( primitiveId );"," #else"," vColor1 = color;"," vColor2 = color2;"," #endif",""," // vRadius = radius;"," base_radius.w = radius * matrixScale( modelViewMatrix );",""," //vec3 center = ( position2 + position1 ) / 2.0;",""," mat4 matrix = computeMat(matrix1, matrix2, matrix3, matrix4);"," vec4 updatePosition1 = matrix * vec4(position1, 1.0);"," vec4 updatePosition2 = matrix * vec4(position2, 1.0);"," vec3 center = ( updatePosition2.xyz + updatePosition1.xyz ) / 2.0;",""," //vec3 dir = normalize( position2 - position1 );"," vec3 dir = normalize( updatePosition2.xyz - updatePosition1.xyz );"," float ext = length( position2 - position1 ) / 2.0;",""," // using cameraPosition fails on some machines, not sure why"," // vec3 cam_dir = normalize( cameraPosition - mix( center, vec3( 0.0 ), ortho ) );"," vec3 cam_dir;"," if( ortho == 0.0 ){"," cam_dir = ( modelViewMatrixInverse * vec4( 0, 0, 0, 1 ) ).xyz - center;"," }else{"," cam_dir = ( modelViewMatrixInverse * vec4( 0, 0, 1, 0 ) ).xyz;"," }"," cam_dir = normalize( cam_dir );",""," vec3 ldir;",""," float b = dot( cam_dir, dir );"," end_b.w = b;"," // direction vector looks away, so flip"," if( b < 0.0 )"," ldir = -ext * dir;"," // direction vector already looks in my direction"," else"," ldir = ext * dir;",""," vec3 left = normalize( cross( cam_dir, ldir ) );"," left = radius * left;"," vec3 up = radius * normalize( cross( left, ldir ) );",""," // transform to modelview coordinates"," axis = normalize( normalMatrix * ldir );"," U = normalize( normalMatrix * up );"," V = normalize( normalMatrix * left );",""," vec4 base4 = modelViewMatrix * vec4( center - ldir, 1.0 );"," base_radius.xyz = base4.xyz / base4.w;",""," vec4 top_position = modelViewMatrix * vec4( center + ldir, 1.0 );"," vec4 end4 = top_position;"," end_b.xyz = end4.xyz / end4.w;",""," w = modelViewMatrix * vec4("," center + mapping.x*ldir + mapping.y*left + mapping.z*up, 1.0"," );",""," gl_Position = projectionMatrix * w;",""," // avoid clipping (1.0 seems to induce flickering with some drivers)"," gl_Position.z = 0.99;","","}"].join("\n"),$NGL_shaderTextHash["Instancing.frag"]=["#define STANDARD","uniform vec3 diffuse;","uniform vec3 emissive;","uniform float roughness;","uniform float metalness;","uniform float opacity;","uniform float nearClip;","uniform float clipRadius;","uniform mat4 projectionMatrix;","uniform float ortho;","varying float bCylinder;","","#if defined( NEAR_CLIP ) || defined( RADIUS_CLIP ) || ( !defined( PICKING ) && !defined( NOLIGHT ) )"," varying vec3 vViewPosition;","#endif","","#if defined( RADIUS_CLIP )"," varying vec3 vClipCenter;","#endif","","#if defined( PICKING )"," uniform float objectId;"," varying vec3 vPickingColor;","#elif defined( NOLIGHT )"," varying vec3 vColor;","#else"," #ifndef FLAT_SHADED"," varying vec3 vNormal;"," #endif"," #include common"," #include color_pars_fragment"," #include fog_pars_fragment"," #include bsdfs"," #include lights_pars_begin"," #include lights_physical_pars_fragment","#endif","","void main(){"," #include nearclip_fragment"," #include radiusclip_fragment",""," #if defined( PICKING )",""," gl_FragColor = vec4( vPickingColor, objectId );",""," #elif defined( NOLIGHT )",""," gl_FragColor = vec4( vColor, opacity );",""," #else",""," vec4 diffuseColor = vec4( diffuse, opacity );"," ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );"," vec3 totalEmissiveLight = emissive;",""," #include color_fragment"," #include roughnessmap_fragment"," #include metalnessmap_fragment"," #include normal_flip"," #include normal_fragment_begin",""," //include dull_interior_fragment",""," #include lights_physical_fragment"," //include lights_template"," #include lights_fragment_begin"," #include lights_fragment_end",""," vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveLight;",""," #include interior_fragment",""," gl_FragColor = vec4( outgoingLight, diffuseColor.a );",""," #include premultiplied_alpha_fragment"," #include tonemapping_fragment"," #include encodings_fragment"," #include fog_fragment",""," #include opaque_back_fragment",""," #endif","","}"].join("\n"),$NGL_shaderTextHash["Instancing.vert"]=["#define STANDARD","","uniform mat4 projectionMatrixInverse;","uniform float nearClip;","uniform vec3 clipCenter;","attribute vec4 matrix1;","attribute vec4 matrix2;","attribute vec4 matrix3;","attribute vec4 matrix4;","attribute float cylinder;","varying float bCylinder;","","#if defined( NEAR_CLIP ) || defined( RADIUS_CLIP ) || ( !defined( PICKING ) && !defined( NOLIGHT ) )"," varying vec3 vViewPosition;","#endif","","#if defined( RADIUS_CLIP )"," varying vec3 vClipCenter;","#endif","","#if defined( PICKING )"," #include unpack_color"," attribute float primitiveId;"," varying vec3 vPickingColor;","#elif defined( NOLIGHT )"," varying vec3 vColor;","#else"," #include color_pars_vertex"," #ifndef FLAT_SHADED"," varying vec3 vNormal;"," #endif","#endif","","#include common",""," mat4 computeMat(vec4 v1, vec4 v2, vec4 v3, vec4 v4) {"," return mat4("," v1.x, v1.y, v1.z, v1.w,"," v2.x, v2.y, v2.z, v2.w,"," v3.x, v3.y, v3.z, v3.w,"," v4.x, v4.y, v4.z, v4.w"," );"," }","","void main(){"," bCylinder = cylinder;",""," mat4 matrix = computeMat(matrix1, matrix2, matrix3, matrix4);"," vec4 updatePosition = matrix * vec4(position, 1.0);",""," #if defined( PICKING )"," vPickingColor = unpackColor( primitiveId );"," #elif defined( NOLIGHT )"," vColor = color;"," #else"," #include color_vertex"," //include beginnormal_vertex"," //vec3 objectNormal = vec3( normal );"," vec3 objectNormal = vec3(matrix * vec4(normal,0.0));"," #include defaultnormal_vertex"," // Normal computed with derivatives when FLAT_SHADED"," #ifndef FLAT_SHADED"," vNormal = normalize( transformedNormal );"," #endif"," #endif",""," //include begin_vertex"," vec3 transformed = updatePosition.xyz;"," //include project_vertex"," vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );"," gl_Position = projectionMatrix * mvPosition;",""," #if defined( NEAR_CLIP ) || defined( RADIUS_CLIP ) || ( !defined( PICKING ) && !defined( NOLIGHT ) )"," vViewPosition = -mvPosition.xyz;"," #endif",""," #if defined( RADIUS_CLIP )"," vClipCenter = -( modelViewMatrix * vec4( clipCenter, 1.0 ) ).xyz;"," #endif",""," #include nearclip_vertex","","}"].join("\n"),THREE.RenderableObject=function(){"use strict";this.id=0,this.object=null,this.z=0},THREE.RenderableFace=function(){"use strict";this.id=0,this.v1=new THREE.RenderableVertex,this.v2=new THREE.RenderableVertex,this.v3=new THREE.RenderableVertex,this.normalModel=new THREE.Vector3,this.vertexNormalsModel=[new THREE.Vector3,new THREE.Vector3,new THREE.Vector3],this.vertexNormalsLength=0,this.color=new THREE.Color,this.material=null,this.uvs=[new THREE.Vector2,new THREE.Vector2,new THREE.Vector2],this.z=0},THREE.RenderableVertex=function(){"use strict";this.position=new THREE.Vector3,this.positionWorld=new THREE.Vector3,this.positionScreen=new THREE.Vector4,this.visible=!0},THREE.RenderableVertex.prototype.copy=function(e){"use strict";this.positionWorld.copy(e.positionWorld),this.positionScreen.copy(e.positionScreen)},THREE.RenderableLine=function(){"use strict";this.id=0,this.v1=new THREE.RenderableVertex,this.v2=new THREE.RenderableVertex,this.vertexColors=[new THREE.Color,new THREE.Color],this.material=null,this.z=0},THREE.RenderableSprite=function(){"use strict";this.id=0,this.object=null,this.x=0,this.y=0,this.z=0,this.rotation=0,this.scale=new THREE.Vector2,this.material=null},THREE.Projector=function(){"use strict";var e,t,i,o,n,r,a,s,c,d,l,u=[],p=0,f=[],v=0,h=[],m=0,g=[],y=0,E=[],_=0,b={objects:[],lights:[],elements:[]},w=(new THREE.Vector3,new THREE.Vector3,new THREE.Vector3,new THREE.Vector3),T=new THREE.Vector4,x=new THREE.Box3(new THREE.Vector3(-1,-1,-1),new THREE.Vector3(1,1,1)),C=new THREE.Box3,R=new Array(3),S=(new Array(4),new THREE.Matrix4),L=new THREE.Matrix4,A=(new THREE.Matrix4,new THREE.Matrix3,new THREE.Frustum);new THREE.Vector4,new THREE.Vector4;this.projectVector=function(e,t){console.warn("THREE.Projector: .projectVector() is now vector.project()."),e.project(t)},this.unprojectVector=function(e,t){console.warn("THREE.Projector: .unprojectVector() is now vector.unproject()."),e.unproject(t)},this.pkRay=function(e,t){console.error("THREE.Projector: .pkRay() is now raycaster.setFromCamera().")};var I=new function(){var e=[],t=[],c=null,d=null,u=new THREE.Matrix3,p=function(e){var t=e.position,i=e.positionWorld,o=e.positionScreen;i.copy(t).applyMatrix4(l),o.copy(i).applyMatrix4(L);var n=1/o.w;o.x*=n,o.y*=n,o.z*=n,e.visible=o.x>=-1&&o.x<=1&&o.y>=-1&&o.y<=1&&o.z>=-1&&o.z<=1},E=function(e,t,i){return!0===e.visible||!0===t.visible||!0===i.visible||(R[0]=e.positionScreen,R[1]=t.positionScreen,R[2]=i.positionScreen,x.isIntersectionBox(C.setFromPoints(R)))},_=function(e,t,i){return(i.positionScreen.x-e.positionScreen.x)*(t.positionScreen.y-e.positionScreen.y)-(i.positionScreen.y-e.positionScreen.y)*(t.positionScreen.x-e.positionScreen.x)<0};return{setObject:function(i){d=(c=i).material,u.getNormalMatrix(c.matrixWorld),e.length=0,t.length=0},projectVertex:p,checkTriangleVisibility:E,checkBackfaceCulling:_,pushVertex:function(e,t,n){(i=function(){if(o===v){var e=new THREE.RenderableVertex;return f.push(e),v++,o++,e}return f[o++]}()).position.set(e,t,n),p(i)},pushNormal:function(t,i,o){e.push(t,i,o)},pushUv:function(e,i){t.push(e,i)},pushLine:function(e,t){var i=f[e],o=f[t];(a=function(){if(s===y){var e=new THREE.RenderableLine;return g.push(e),y++,s++,e}return g[s++]}()).id=c.id,a.v1.copy(i),a.v2.copy(o),a.z=(i.positionScreen.z+o.positionScreen.z)/2,a.material=c.material,b.elements.push(a)},pushTriangle:function(i,o,a){var s=f[i],l=f[o],p=f[a];if(!1!==E(s,l,p)&&(d.side===THREE.DoubleSide||!0===_(s,l,p))){(n=function(){if(r===m){var e=new THREE.RenderableFace;return h.push(e),m++,r++,e}return h[r++]}()).id=c.id,n.v1.copy(s),n.v2.copy(l),n.v3.copy(p),n.z=(s.positionScreen.z+l.positionScreen.z+p.positionScreen.z)/3;for(var v=0;v<3;v++){var g=3*arguments[v],y=n.vertexNormalsModel[v];y.set(e[g],e[g+1],e[g+2]),y.applyMatrix3(u).normalize();var w=2*arguments[v];n.uvs[v].set(t[w],t[w+1])}n.vertexNormalsLength=3,n.material=c.material,b.elements.push(n)}}}};function O(){if(d===_){var e=new THREE.RenderableSprite;return E.push(e),_++,d++,e}return E[d++]}function N(e,t){return e.z!==t.z?t.z-e.z:e.id!==t.id?e.id-t.id:0}this.projectScene=function(i,n,a,f){r=0,s=0,d=0,b.elements.length=0,!0===i.autoUpdate&&i.updateMatrixWorld(),void 0===n.parent&&n.updateMatrixWorld(),S.copy(n.matrixWorldInverse.copy(n.matrixWorld).invert()),L.multiplyMatrices(n.projectionMatrix,S),A.setFromMatrix(L),t=0,b.objects.length=0,b.lights.length=0,i.traverseVisible(function(i){if(i instanceof THREE.Light)b.lights.push(i);else if(i instanceof THREE.Mesh||i instanceof THREE.Line||i instanceof THREE.Sprite){if(!1===i.material.visible)return;!1!==i.frustumCulled&&!0!==A.intersectsObject(i)||((e=function(){if(t===p){var e=new THREE.RenderableObject;return u.push(e),p++,t++,e}return u[t++]}()).id=i.id,e.object=i,w.setFromMatrixPosition(i.matrixWorld),w.applyProjection(L),e.z=w.z,b.objects.push(e))}}),!0===a&&b.objects.sort(N);for(var v=0,h=b.objects.length;v0)for(v=0;v=-1&&T.z<=1&&((c=O()).id=m.id,c.x=T.x*j,c.y=T.y*j,c.z=T.z,c.object=m,c.rotation=m.rotation,c.scale.x=m.scale.x*Math.abs(c.x-(T.x+n.projectionMatrix.elements[0])/(T.w+n.projectionMatrix.elements[12])),c.scale.y=m.scale.y*Math.abs(c.y-(T.y+n.projectionMatrix.elements[5])/(T.w+n.projectionMatrix.elements[13])),c.material=m.material,b.elements.push(c))}}return!0===f&&b.elements.sort(N),b}},THREE.TrackballControls=function(e,t,i){"use strict";var o=this;this.STATE={NONE:-1,ROTATE:0,ZOOM:1,PAN:2,TOUCH_ROTATE:3,TOUCH_ZOOM_PAN:4},this.object=e,this.domElement=void 0!==t?t:document,this.enabled=!0,this.screen={left:0,top:0,width:0,height:0},this.rotateSpeed=1,this.zoomSpeed=1.2,this.panSpeed=.3,this.noRotate=!1,this.noZoom=!1,this.noPan=!1,this.noRoll=!1,this.staticMoving=!1,this.dynamicDampingFactor=.2,this.minDistance=0,this.maxDistance=1/0,this.keys=[65,83,68],this.target=new THREE.Vector3;var n=new THREE.Vector3;this._state=this.STATE.NONE;var r=this.STATE.NONE,a=new THREE.Vector3;this._rotateStart=new THREE.Vector3,this._rotateEnd=new THREE.Vector3,this._zoomStart=new THREE.Vector2,this._zoomEnd=new THREE.Vector2;var s=0,c=0;this._panStart=new THREE.Vector2,this._panEnd=new THREE.Vector2,this.target0=this.target.clone(),this.position0=this.object.position.clone(),this.up0=this.object.up.clone();var d={type:"change"},l={type:"start"},u={type:"end"};this.handleResize=function(){if(this.domElement===document)this.screen.left=0,this.screen.top=0,this.screen.width=window.innerWidth,this.screen.height=window.innerHeight;else if(this.domElement){var e=this.domElement.getBoundingClientRect(),t=this.domElement.ownerDocument.documentElement;this.screen.left=e.left+window.pageXOffset-t.clientLeft,this.screen.top=e.top+window.pageYOffset-t.clientTop,this.screen.width=e.width,this.screen.height=e.height}},this.handleEvent=function(e){"function"==typeof this[e.type]&&this[e.type](e)};var p,f,v,h,m,g,y,E,_,b=(p=new THREE.Vector2,function(e,t){return p.set((e-o.screen.left)/o.screen.width,(t-o.screen.top)/o.screen.height),p}),w=(f=new THREE.Vector3,v=new THREE.Vector3,h=new THREE.Vector3,function(e,t){h.set((e-.5*o.screen.width-o.screen.left)/(.5*o.screen.width),(.5*o.screen.height+o.screen.top-t)/(.5*o.screen.height),0);var i=h.length();return o.noRoll?i1?h.normalize():h.z=Math.sqrt(1-i*i),a.copy(o.object.position).sub(o.target),f.copy(o.object.up).setLength(h.y),f.add(v.copy(o.object.up).cross(a).setLength(h.x)),f.add(a.setLength(h.z)),f});function T(e){!1===o.enabled||Object.keys(window).length<2||(window.removeEventListener("keydown",T),r=o._state,o._state===o.STATE.NONE&&(e.keyCode!==o.keys[o.STATE.ROTATE]||o.noRotate?e.keyCode!==o.keys[o.STATE.ZOOM]||o.noZoom?e.keyCode!==o.keys[o.STATE.PAN]||o.noPan||(o._state=o.STATE.PAN):o._state=o.STATE.ZOOM:o._state=o.STATE.ROTATE))}function x(e){!1===o.enabled||Object.keys(window).length<2||(e.stopPropagation(),o._state!==o.STATE.ROTATE||o.noRotate?o._state!==o.STATE.ZOOM||o.noZoom?o._state!==o.STATE.PAN||o.noPan||o._panEnd.copy(b(e.pageX,e.pageY)):o._zoomEnd.copy(b(e.pageX,e.pageY)):o._rotateEnd.copy(w(e.pageX,e.pageY)))}function C(e){!1===o.enabled||Object.keys(window).length<2||(e.stopPropagation(),o._state=o.STATE.NONE,document.removeEventListener("mousemove",x),document.removeEventListener("mouseup",C),o.dispatchEvent(u))}function R(e){if(!(!1===o.enabled||Object.keys(window).length<2)){e.stopPropagation();var t=0;e.wheelDelta?t=e.wheelDelta/40:e.detail&&(t=-e.detail/3),o._zoomStart.y=.005*t,o.dispatchEvent(l),o.dispatchEvent(u)}}this.rotateCamera=(m=new THREE.Vector3,g=new THREE.Quaternion,function(e,t){var n;void 0===e&&(n=Math.acos(o._rotateStart.dot(o._rotateEnd)/o._rotateStart.length()/o._rotateEnd.length())),(n||void 0!==e)&&(void 0===e?(m.crossVectors(o._rotateStart,o._rotateEnd).normalize(),n*=o.rotateSpeed,g.setFromAxisAngle(m,-n)):g.copy(e),void 0===i||void 0===i.quaternion||void 0!==t&&!0!==t||i.quaternion.multiplyQuaternions(g,i.quaternion),a.applyQuaternion(g),o.object.up.applyQuaternion(g),o._rotateEnd.applyQuaternion(g),o.staticMoving?o._rotateStart.copy(o._rotateEnd):(g.setFromAxisAngle(m,n*(o.dynamicDampingFactor-1)),o._rotateStart.applyQuaternion(g)))}),this.zoomCamera=function(e,t){var n;o._state===o.STATE.TOUCH_ZOOM_PAN?(void 0!==e?n=e:(n=s/c,s=c),a.multiplyScalar(n),void 0===i||void 0===i._zoomFactor||void 0!==t&&!0!==t||(i._zoomFactor*=n,i.fogCls.setFog())):(n=void 0!==e?e:1+(o._zoomEnd.y-o._zoomStart.y)*o.zoomSpeed,void 0===i||void 0===i._zoomFactor||void 0!==t&&!0!==t||(i._zoomFactor*=n,i.fogCls.setFog()),1!==n&&(a.multiplyScalar(n),o.staticMoving?o._zoomStart.copy(o._zoomEnd):o._zoomStart.y+=(o._zoomEnd.y-o._zoomStart.y)*this.dynamicDampingFactor))},this.panCamera=(y=new THREE.Vector2,E=new THREE.Vector3,_=new THREE.Vector3,function(e,t){void 0!==e?(y=e,void 0===i||void 0===i.mouseChange||void 0!==t&&!0!==t||i.mouseChange.add(e)):(y.copy(o._panEnd).sub(o._panStart),void 0===i||void 0===i.mouseChange||void 0!==t&&!0!==t||i.mouseChange.add(o._panEnd).sub(o._panStart)),y.lengthSq()&&(y.multiplyScalar(a.length()*o.panSpeed),_.copy(a).cross(o.object.up).setLength(y.x),_.add(E.copy(o.object.up).setLength(y.y)),o.object.position.add(_),o.target.add(_),o.staticMoving?o._panStart.copy(o._panEnd):o._panStart.add(y.subVectors(o._panEnd,o._panStart).multiplyScalar(o.dynamicDampingFactor)))}),this.checkDistances=function(){o.noZoom&&o.noPan||(a.lengthSq()>o.maxDistance*o.maxDistance&&o.object.position.addVectors(o.target,a.setLength(o.maxDistance)),a.lengthSq()1e-6&&(o.dispatchEvent(d),n.copy(o.object.position))},this.reset=function(){o._state=o.STATE.NONE,r=o.STATE.NONE,o.target.copy(o.target0),o.object.position.copy(o.position0),o.object.up.copy(o.up0),a.subVectors(o.object.position,o.target),o.object.lookAt(o.target),o.dispatchEvent(d),n.copy(o.object.position)},Object.keys(window).length>=2&&this.domElement&&(this.domElement.addEventListener("contextmn",function(e){},!1),this.domElement.addEventListener("mousedown",function(e){!1===o.enabled||Object.keys(window).length<2||(e.stopPropagation(),o._state===o.STATE.NONE&&(o._state=e.button),o._state!==o.STATE.ROTATE||o.noRotate?o._state!==o.STATE.ZOOM||o.noZoom?o._state!==o.STATE.PAN||o.noPan||(o._panStart.copy(b(e.pageX,e.pageY)),o._panEnd.copy(o._panStart)):(o._zoomStart.copy(b(e.pageX,e.pageY)),o._zoomEnd.copy(o._zoomStart)):(o._rotateStart.copy(w(e.pageX,e.pageY)),o._rotateEnd.copy(o._rotateStart)),document.addEventListener("mousemove",x,!1),document.addEventListener("mouseup",C,!1),o.dispatchEvent(l))},!1),this.domElement.addEventListener("mousewheel",R,!1),this.domElement.addEventListener("DOMMouseScroll",R,!1),this.domElement.addEventListener("touchstart",function(e){if(!(!1===o.enabled||Object.keys(window).length<2)){switch(e.touches.length){case 1:o._state=o.STATE.TOUCH_ROTATE,o._rotateStart.copy(w(e.touches[0].pageX,e.touches[0].pageY)),o._rotateEnd.copy(o._rotateStart);break;case 2:o._state=o.STATE.TOUCH_ZOOM_PAN;var t=e.touches[0].pageX-e.touches[1].pageX,i=e.touches[0].pageY-e.touches[1].pageY;c=s=Math.sqrt(t*t+i*i);var n=(e.touches[0].pageX+e.touches[1].pageX)/2,r=(e.touches[0].pageY+e.touches[1].pageY)/2;o._panStart.copy(b(n,r)),o._panEnd.copy(o._panStart);break;default:o._state=o.STATE.NONE}o.dispatchEvent(l)}},!1),this.domElement.addEventListener("touchend",function(e){if(!(!1===o.enabled||Object.keys(window).length<2)){switch(e.touches.length){case 1:o._rotateEnd.copy(w(e.touches[0].pageX,e.touches[0].pageY)),o._rotateStart.copy(o._rotateEnd);break;case 2:s=c=0;var t=(e.touches[0].pageX+e.touches[1].pageX)/2,i=(e.touches[0].pageY+e.touches[1].pageY)/2;o._panEnd.copy(b(t,i)),o._panStart.copy(o._panEnd)}o._state=o.STATE.NONE,o.dispatchEvent(u)}},!1),this.domElement.addEventListener("touchmove",function(e){if(!(!1===o.enabled||Object.keys(window).length<2))switch(e.stopPropagation(),e.touches.length){case 1:o._rotateEnd.copy(w(e.touches[0].pageX,e.touches[0].pageY));break;case 2:var t=e.touches[0].pageX-e.touches[1].pageX,i=e.touches[0].pageY-e.touches[1].pageY;c=Math.sqrt(t*t+i*i);var n=(e.touches[0].pageX+e.touches[1].pageX)/2,r=(e.touches[0].pageY+e.touches[1].pageY)/2;o._panEnd.copy(b(n,r));break;default:o._state=o.STATE.NONE}},!1),Object.keys(window).length>=2&&window.addEventListener("keydown",T,!1),Object.keys(window).length>=2&&window.addEventListener("keyup",function(e){!1===o.enabled||Object.keys(window).length<2||(o._state=r,window.addEventListener("keydown",T,!1))},!1)),this.handleResize(),this.update()},THREE.TrackballControls.prototype=Object.create(THREE.EventDispatcher.prototype),THREE.TrackballControls.prototype.constructor=THREE.TrackballControls,THREE.OrthographicTrackballControls=function(e,t,i){this.icn3d;var o=this,n={NONE:-1,ROTATE:0,ZOOM:1,PAN:2,TOUCH_ROTATE:3,TOUCH_ZOOM_PAN:4};this.object=e,this.domElement=void 0!==t?t:document,this.enabled=!0,this.screen={left:0,top:0,width:0,height:0},this.rotateSpeed=.5,this.zoomSpeed=1.2;this.zoomSpeed*=.01,this.panSpeed=.03,this.noRotate=!1,this.noZoom=!1,this.noPan=!1,this.noRoll=!1,this.staticMoving=!1,this.dynamicDampingFactor=.2,this.keys=[65,83,68],this.target=new THREE.Vector3;var r=new THREE.Vector3;this._state=n.NONE;var a=n.NONE,s=new THREE.Vector3;this._rotateStart=new THREE.Vector3,this._rotateEnd=new THREE.Vector3,this._zoomStart=new THREE.Vector2,this._zoomEnd=new THREE.Vector2;var c=1,d=0,l=0;this._panStart=new THREE.Vector2,this._panEnd=new THREE.Vector2,this.target0=this.target.clone(),this.position0=this.object.position.clone(),this.up0=this.object.up.clone(),this.left0=this.object.left,this.right0=this.object.right,this.top0=this.object.top,this.bottom0=this.object.bottom,this.center0=new THREE.Vector2((this.left0+this.right0)/2,(this.top0+this.bottom0)/2);var u={type:"change"},p={type:"start"},f={type:"end"};this.handleResize=function(){if(this.domElement===document)this.screen.left=0,this.screen.top=0,this.screen.width=window.innerWidth,this.screen.height=window.innerHeight;else if(this.domElement){var e=this.domElement.getBoundingClientRect(),t=this.domElement.ownerDocument.documentElement;this.screen.left=e.left+window.pageXOffset-t.clientLeft,this.screen.top=e.top+window.pageYOffset-t.clientTop,this.screen.width=e.width,this.screen.height=e.height}this.left0=this.object.left,this.right0=this.object.right,this.top0=this.object.top,this.bottom0=this.object.bottom,this.center0.set((this.left0+this.right0)/2,(this.top0+this.bottom0)/2)},this.handleEvent=function(e){"function"==typeof this[e.type]&&this[e.type](e)};var v,h,m,g,y,E,_,b,w,T=(v=new THREE.Vector2,function(e,t){return v.set((e-o.screen.left)/o.screen.width,(t-o.screen.top)/o.screen.height),v}),x=(h=new THREE.Vector3,m=new THREE.Vector3,g=new THREE.Vector3,function(e,t){g.set((e-.5*o.screen.width-o.screen.left)/(.5*o.screen.width),(.5*o.screen.height+o.screen.top-t)/(.5*o.screen.height),0);var i=g.length();return o.noRoll?i1?g.normalize():g.z=Math.sqrt(1-i*i),s.copy(o.object.position).sub(o.target),h.copy(o.object.up).setLength(g.y),h.add(m.copy(o.object.up).cross(s).setLength(g.x)),h.add(s.setLength(g.z)),h});function C(e){!1===o.enabled||Object.keys(window).length<2||(window.removeEventListener("keydown",C),a=o._state,o._state===n.NONE&&(e.keyCode!==o.keys[n.ROTATE]||o.noRotate?e.keyCode!==o.keys[n.ZOOM]||o.noZoom?e.keyCode!==o.keys[n.PAN]||o.noPan||(o._state=n.PAN):o._state=n.ZOOM:o._state=n.ROTATE))}function R(e){!1===o.enabled||Object.keys(window).length<2||(e.stopPropagation(),o._state!==n.ROTATE||o.noRotate?o._state!==n.ZOOM||o.noZoom?o._state!==n.PAN||o.noPan||o._panEnd.copy(T(e.pageX,e.pageY)):o._zoomEnd.copy(T(e.pageX,e.pageY)):o._rotateEnd.copy(x(e.pageX,e.pageY)))}function S(e){!1===o.enabled||Object.keys(window).length<2||(e.stopPropagation(),o._state=n.NONE,document.removeEventListener("mousemove",R),document.removeEventListener("mouseup",S),o.dispatchEvent(f))}function L(e){if(!(!1===o.enabled||Object.keys(window).length<2)){e.stopPropagation();var t=0;e.wheelDelta?t=e.wheelDelta/40:e.detail&&(t=-e.detail/3),o._zoomStart.y=.01*t,o.dispatchEvent(p),o.dispatchEvent(f)}}this.rotateCamera=(y=new THREE.Vector3,E=new THREE.Quaternion,function(e,t){var n;void 0===e&&(n=Math.acos(o._rotateStart.dot(o._rotateEnd)/o._rotateStart.length()/o._rotateEnd.length())),(n||void 0!==e)&&(void 0===e?(y.crossVectors(o._rotateStart,o._rotateEnd).normalize(),n*=o.rotateSpeed,E.setFromAxisAngle(y,-n)):E.copy(e),void 0===i||void 0===i.quaternion||void 0!==t&&!0!==t||i.quaternion.multiplyQuaternions(E,i.quaternion),s.applyQuaternion(E),o.object.up.applyQuaternion(E),o._rotateEnd.applyQuaternion(E),o.staticMoving?o._rotateStart.copy(o._rotateEnd):(E.setFromAxisAngle(y,n*(o.dynamicDampingFactor-1)),o._rotateStart.applyQuaternion(E)))}),this.zoomCamera=function(e,t){var r;o._state===n.TOUCH_ZOOM_PAN?void 0!==e?r=e:(r=d/l,d=l):r=void 0!==e?e:1+(o._zoomEnd.y-o._zoomStart.y)*o.zoomSpeed/.01,void 0===i||void 0===i._zoomFactor||void 0!==t&&!0!==t||(i._zoomFactor*=r),1!==r&&(c=r,o.object.left=c*o.left0+(1-c)*o.center0.x,o.object.right=c*o.right0+(1-c)*o.center0.x,o.object.top=c*o.top0+(1-c)*o.center0.y,o.object.bottom=c*o.bottom0+(1-c)*o.center0.y,o.staticMoving?o._zoomStart.copy(o._zoomEnd):o._zoomStart.y+=(o._zoomEnd.y-o._zoomStart.y)*this.dynamicDampingFactor)},this.panCamera=(_=new THREE.Vector2,b=new THREE.Vector3,w=new THREE.Vector3,function(e,t){void 0!==e?(_=e,void 0===i||void 0===i.mouseChange||void 0!==t&&!0!==t||i.mouseChange.add(e)):(_.copy(o._panEnd).sub(o._panStart),void 0===i||void 0===i.mouseChange||void 0!==t&&!0!==t||i.mouseChange.add(o._panEnd).sub(o._panStart)),_.lengthSq()&&(_.multiplyScalar(s.length()*o.panSpeed),w.copy(s).cross(o.object.up).setLength(_.x),w.add(b.copy(o.object.up).setLength(_.y)),o.object.position.add(w),o.target.add(w),o.staticMoving?o._panStart.copy(o._panEnd):o._panStart.add(_.subVectors(o._panEnd,o._panStart).multiplyScalar(o.dynamicDampingFactor)))}),this.update=function(e){s.subVectors(o.object.position,o.target),o.noRotate||(void 0!==e&&void 0!==e.quaternion?o.rotateCamera(e.quaternion,e.update):o.rotateCamera()),o.noZoom||(void 0!==e&&void 0!==e._zoomFactor?o.zoomCamera(e._zoomFactor,e.update):o.zoomCamera(),o.object.updateProjectionMatrix()),o.noPan||(void 0!==e&&void 0!==e.mouseChange?o.panCamera(e.mouseChange,e.update):o.panCamera()),o.object.position.addVectors(o.target,s),o.object.lookAt(o.target),r.distanceToSquared(o.object.position)>1e-6&&(o.dispatchEvent(u),r.copy(o.object.position))},this.reset=function(){o._state=n.NONE,a=n.NONE,o.target.copy(o.target0),o.object.position.copy(o.position0),o.object.up.copy(o.up0),s.subVectors(o.object.position,o.target),o.object.left=o.left0,o.object.right=o.right0,o.object.top=o.top0,o.object.bottom=o.bottom0,o.object.lookAt(o.target),o.dispatchEvent(u),r.copy(o.object.position)},Object.keys(window).length>=2&&this.domElement&&(this.domElement.addEventListener("contextmn",function(e){},!1),this.domElement.addEventListener("mousedown",function(e){!1===o.enabled||Object.keys(window).length<2||(e.stopPropagation(),o._state===n.NONE&&(o._state=e.button),o._state!==n.ROTATE||o.noRotate?o._state!==n.ZOOM||o.noZoom?o._state!==n.PAN||o.noPan||(o._panStart.copy(T(e.pageX,e.pageY)),o._panEnd.copy(o._panStart)):(o._zoomStart.copy(T(e.pageX,e.pageY)),o._zoomEnd.copy(o._zoomStart)):(o._rotateStart.copy(x(e.pageX,e.pageY)),o._rotateEnd.copy(o._rotateStart)),document.addEventListener("mousemove",R,!1),document.addEventListener("mouseup",S,!1),o.dispatchEvent(p))},!1),this.domElement.addEventListener("mousewheel",L,!1),this.domElement.addEventListener("DOMMouseScroll",L,!1),this.domElement.addEventListener("touchstart",function(e){if(!(!1===o.enabled||Object.keys(window).length<2)){switch(e.touches.length){case 1:o._state=n.TOUCH_ROTATE,o._rotateStart.copy(x(e.touches[0].pageX,e.touches[0].pageY)),o._rotateEnd.copy(o._rotateStart);break;case 2:o._state=n.TOUCH_ZOOM_PAN;var t=e.touches[0].pageX-e.touches[1].pageX,i=e.touches[0].pageY-e.touches[1].pageY;l=d=Math.sqrt(t*t+i*i);var r=(e.touches[0].pageX+e.touches[1].pageX)/2,a=(e.touches[0].pageY+e.touches[1].pageY)/2;o._panStart.copy(T(r,a)),o._panEnd.copy(o._panStart);break;default:o._state=n.NONE}o.dispatchEvent(p)}},!1),this.domElement.addEventListener("touchend",function(e){if(!(!1===o.enabled||Object.keys(window).length<2)){switch(e.touches.length){case 1:o._rotateEnd.copy(x(e.touches[0].pageX,e.touches[0].pageY)),o._rotateStart.copy(o._rotateEnd);break;case 2:d=l=0;var t=(e.touches[0].pageX+e.touches[1].pageX)/2,i=(e.touches[0].pageY+e.touches[1].pageY)/2;o._panEnd.copy(T(t,i)),o._panStart.copy(o._panEnd)}o._state=n.NONE,o.dispatchEvent(f)}},!1),this.domElement.addEventListener("touchmove",function(e){if(!(!1===o.enabled||Object.keys(window).length<2))switch(e.stopPropagation(),e.touches.length){case 1:o._rotateEnd.copy(x(e.touches[0].pageX,e.touches[0].pageY));break;case 2:var t=e.touches[0].pageX-e.touches[1].pageX,i=e.touches[0].pageY-e.touches[1].pageY;l=Math.sqrt(t*t+i*i);var r=(e.touches[0].pageX+e.touches[1].pageX)/2,a=(e.touches[0].pageY+e.touches[1].pageY)/2;o._panEnd.copy(T(r,a));break;default:o._state=n.NONE}},!1),window.addEventListener("keydown",C,!1),window.addEventListener("keyup",function(e){!1===o.enabled||Object.keys(window).length<2||(o._state=a,window.addEventListener("keydown",C,!1))},!1)),this.handleResize(),this.update()},THREE.OrthographicTrackballControls.prototype=Object.create(THREE.EventDispatcher.prototype),THREE.OrthographicTrackballControls.prototype.constructor=THREE.OrthographicTrackballControls;var MMTF={};function initIcn3dpyMMTF(e){function t(e,t,i){for(var o=(e.byteLength,0),n=i.length;n>o;o++){var r=i.charCodeAt(o);if(128>r)e.setUint8(t++,r>>>0&127|0);else if(2048>r)e.setUint8(t++,r>>>6&31|192),e.setUint8(t++,r>>>0&63|128);else if(65536>r)e.setUint8(t++,r>>>12&15|224),e.setUint8(t++,r>>>6&63|128),e.setUint8(t++,r>>>0&63|128);else{if(!(1114112>r))throw new Error("bad codepoint "+r);e.setUint8(t++,r>>>18&7|240),e.setUint8(t++,r>>>12&63|128),e.setUint8(t++,r>>>6&63|128),e.setUint8(t++,r>>>0&63|128)}}}function i(e){for(var t=0,i=0,o=e.length;o>i;i++){var n=e.charCodeAt(i);if(128>n)t+=1;else if(2048>n)t+=2;else if(65536>n)t+=3;else{if(!(1114112>n))throw new Error("bad codepoint "+n);t+=4}}return t}function o(e){var o=new ArrayBuffer(function e(t){var o=typeof t;if("string"===o){if(32>(n=i(t)))return 1+n;if(256>n)return 2+n;if(65536>n)return 3+n;if(4294967296>n)return 5+n}if(t instanceof Uint8Array){if(256>(n=t.byteLength))return 2+n;if(65536>n)return 3+n;if(4294967296>n)return 5+n}if("number"===o){if(Math.floor(t)!==t)return 9;if(t>=0){if(128>t)return 1;if(256>t)return 2;if(65536>t)return 3;if(4294967296>t)return 5;throw new Error("Number too big 0x"+t.toString(16))}if(t>=-32)return 1;if(t>=-128)return 2;if(t>=-32768)return 3;if(t>=-2147483648)return 5;throw new Error("Number too small -0x"+t.toString(16).substr(1))}if("boolean"===o||null===t)return 1;if("object"===o){var n,r=0;if(Array.isArray(t)){n=t.length;for(var a=0;n>a;a++)r+=e(t[a])}else{var s=Object.keys(t);for(n=s.length,a=0;n>a;a++){var c=s[a];r+=e(c)+e(t[c])}}if(16>n)return 1+r;if(65536>n)return 3+r;if(4294967296>n)return 5+r;throw new Error("Array or object too long 0x"+n.toString(16))}throw new Error("Unknown type "+o)}(e));return function e(o,n,r){var a=typeof o;if("string"===a){if(32>(s=i(o)))return n.setUint8(r,160|s),t(n,r+1,o),1+s;if(256>s)return n.setUint8(r,217),n.setUint8(r+1,s),t(n,r+2,o),2+s;if(65536>s)return n.setUint8(r,218),n.setUint16(r+1,s),t(n,r+3,o),3+s;if(4294967296>s)return n.setUint8(r,219),n.setUint32(r+1,s),t(n,r+5,o),5+s}if(o instanceof Uint8Array){var s=o.byteLength,c=new Uint8Array(n.buffer);if(256>s)return n.setUint8(r,196),n.setUint8(r+1,s),c.set(o,r+2),2+s;if(65536>s)return n.setUint8(r,197),n.setUint16(r+1,s),c.set(o,r+3),3+s;if(4294967296>s)return n.setUint8(r,198),n.setUint32(r+1,s),c.set(o,r+5),5+s}if("number"===a){if(!isFinite(o))throw new Error("Number not finite: "+o);if(Math.floor(o)!==o)return n.setUint8(r,203),n.setFloat64(r+1,o),9;if(o>=0){if(128>o)return n.setUint8(r,o),1;if(256>o)return n.setUint8(r,204),n.setUint8(r+1,o),2;if(65536>o)return n.setUint8(r,205),n.setUint16(r+1,o),3;if(4294967296>o)return n.setUint8(r,206),n.setUint32(r+1,o),5;throw new Error("Number too big 0x"+o.toString(16))}if(o>=-32)return n.setInt8(r,o),1;if(o>=-128)return n.setUint8(r,208),n.setInt8(r+1,o),2;if(o>=-32768)return n.setUint8(r,209),n.setInt16(r+1,o),3;if(o>=-2147483648)return n.setUint8(r,210),n.setInt32(r+1,o),5;throw new Error("Number too small -0x"+(-o).toString(16).substr(1))}if(null===o)return n.setUint8(r,192),1;if("boolean"===a)return n.setUint8(r,o?195:194),1;if("object"===a){var d=0,l=Array.isArray(o);if(l)s=o.length;else{var u=Object.keys(o);s=u.length}if(16>s?(n.setUint8(r,s|(l?144:128)),d=1):65536>s?(n.setUint8(r,l?220:222),n.setUint16(r+1,s),d=3):4294967296>s&&(n.setUint8(r,l?221:223),n.setUint32(r+1,s),d=5),l)for(var p=0;s>p;p++)d+=e(o[p],n,r+d);else for(p=0;s>p;p++){var f=u[p];d+=e(f,n,r+d),d+=e(o[f],n,r+d)}return d}throw new Error("Unknown type "+a)}(e,new DataView(o),0),new Uint8Array(o)}function n(e,t,i){return t?new e(t.buffer,t.byteOffset,t.byteLength/(i||1)):void 0}function r(e){return n(DataView,e)}function a(e){return n(Uint8Array,e)}function s(e){return n(Int8Array,e)}function c(e){return n(Int32Array,e,4)}function d(e,t){var i=e.length/2;t||(t=new Int16Array(i));for(var o=0,n=0;i>o;++o,n+=2)t[o]=e[n]<<8^e[n+1]<<0;return t}function l(e,t){var i=e.length/4;t||(t=new Int32Array(i));for(var o=0,n=0;i>o;++o,n+=4)t[o]=e[n]<<24^e[n+1]<<16^e[n+2]<<8^e[n+3]<<0;return t}function u(e,t){var i=e.length;t||(t=new Uint8Array(4*i));for(var o=r(t),n=0;i>n;++n)o.setInt32(4*n,e[n]);return a(t)}function p(e,t,i){var o=e.length,n=1/t;i||(i=new Float32Array(o));for(var r=0;o>r;++r)i[r]=e[r]*n;return i}function f(e,t,i){var o=e.length;i||(i=new Int32Array(o));for(var n=0;o>n;++n)i[n]=Math.round(e[n]*t);return i}function v(e,t){var i,o;if(!t){var n=0;for(i=0,o=e.length;o>i;i+=2)n+=e[i+1];t=new e.constructor(n)}var r=0;for(i=0,o=e.length;o>i;i+=2)for(var a=e[i],s=e[i+1],c=0;s>c;++c)t[r]=a,++r;return t}function h(e){if(0===e.length)return new Int32Array;var t,i,o=2;for(t=1,i=e.length;i>t;++t)e[t-1]!==e[t]&&(o+=2);var n=new Int32Array(o),r=0,a=1;for(t=1,i=e.length;i>t;++t)e[t-1]!==e[t]?(n[r]=e[t-1],n[r+1]=a,a=1,r+=2):++a;return n[r]=e[e.length-1],n[r+1]=a,n}function m(e,t){var i=e.length;t||(t=new e.constructor(i)),i&&(t[0]=e[0]);for(var o=1;i>o;++o)t[o]=e[o]+t[o-1];return t}function g(e,t){var i=e.length;t||(t=new e.constructor(i)),t[0]=e[0];for(var o=1;i>o;++o)t[o]=e[o]-e[o-1];return t}function y(e,t){var i,o,n=e instanceof Int8Array?127:32767,r=-n-1,a=e.length;if(!t){var s=0;for(i=0;a>i;++i)e[i]r&&++s;t=new Int32Array(s)}for(i=0,o=0;a>i;){for(var c=0;e[i]===n||e[i]===r;)c+=e[i],++i;c+=e[i],++i,t[o]=c,++o}return t}function E(e,t,i){return p(y(e,c(i)),t,i)}function _(e,t,i){var o,r,a,s=y(e,c(i));return o=s,r=t,a=n(Float32Array,s,4),p(m(o,c(a)),r,a)}function b(e,t,i){return function(e,t){var i,o=t?127:32767,n=-o-1,r=e.length,a=0;for(i=0;r>i;++i)0===(d=e[i])?++a:d>0?(a+=Math.ceil(d/o),d%o==0&&(a+=1)):(a+=Math.ceil(d/n),d%n==0&&(a+=1));var s=t?new Int8Array(a):new Int16Array(a),c=0;for(i=0;r>i;++i){var d;if((d=e[i])>=0)for(;d>=o;)s[c]=o,++c,d-=o;else for(;n>=d;)s[c]=n,++c,d-=n;s[c]=d,++c}return s}(g(f(e,t),o),i);var o}function w(e,t,i,o){var n=new ArrayBuffer(12+o.byteLength),r=new Uint8Array(n),a=new DataView(n);return a.setInt32(0,e),a.setInt32(4,t),i&&r.set(i,8),r.set(o,12),r}function T(e){return w(2,e.length,void 0,a(e))}function x(e){return w(4,e.length,void 0,u(e))}function C(e,t){return w(5,e.length/t,u([t]),a(e))}function R(e){return w(6,e.length,void 0,u(h(e)))}function S(e){return w(8,e.length,void 0,u(h(g(e))))}function L(e,t){return w(9,e.length,u([t]),u(h(f(e,t))))}function A(e,t){return w(10,e.length,u([t]),function(e,t){var i=e.length;t||(t=new Uint8Array(2*i));for(var o=r(t),n=0;i>n;++n)o.setInt16(2*n,e[n]);return a(t)}(b(e,t)))}function I(e){var t={};return D.forEach(function(i){void 0!==e[i]&&(t[i]=e[i])}),e.bondAtomList&&(t.bondAtomList=x(e.bondAtomList)),e.bondOrderList&&(t.bondOrderList=T(e.bondOrderList)),t.xCoordList=A(e.xCoordList,1e3),t.yCoordList=A(e.yCoordList,1e3),t.zCoordList=A(e.zCoordList,1e3),e.bFactorList&&(t.bFactorList=A(e.bFactorList,100)),e.atomIdList&&(t.atomIdList=S(e.atomIdList)),e.altLocList&&(t.altLocList=R(e.altLocList)),e.occupancyList&&(t.occupancyList=L(e.occupancyList,100)),t.groupIdList=S(e.groupIdList),t.groupTypeList=x(e.groupTypeList),e.secStructList&&(t.secStructList=T(e.secStructList)),e.insCodeList&&(t.insCodeList=R(e.insCodeList)),e.sequenceIndexList&&(t.sequenceIndexList=S(e.sequenceIndexList)),t.chainIdList=C(e.chainIdList,4),e.chainNameList&&(t.chainNameList=C(e.chainNameList,4)),t}function O(e){function t(e){for(var t={},i=0;e>i;i++){t[r()]=r()}return t}function i(t){var i=e.subarray(a,a+t);return a+=t,i}function o(t){var i=e.subarray(a,a+t);a+=t;if(t>65535){for(var o=[],n=0;ni;i++)t[i]=r();return t}function r(){var r,c,d=e[a];if(0==(128&d))return a++,d;if(128==(240&d))return a++,t(c=15&d);if(144==(240&d))return a++,n(c=15&d);if(160==(224&d))return a++,o(c=31&d);if(224==(224&d))return r=s.getInt8(a),a++,r;switch(d){case 192:return a++,null;case 194:return a++,!1;case 195:return a++,!0;case 196:return c=s.getUint8(a+1),a+=2,i(c);case 197:return c=s.getUint16(a+1),a+=3,i(c);case 198:return c=s.getUint32(a+1),a+=5,i(c);case 202:return r=s.getFloat32(a+1),a+=5,r;case 203:return r=s.getFloat64(a+1),a+=9,r;case 204:return r=e[a+1],a+=2,r;case 205:return r=s.getUint16(a+1),a+=3,r;case 206:return r=s.getUint32(a+1),a+=5,r;case 208:return r=s.getInt8(a+1),a+=2,r;case 209:return r=s.getInt16(a+1),a+=3,r;case 210:return r=s.getInt32(a+1),a+=5,r;case 217:return c=s.getUint8(a+1),a+=2,o(c);case 218:return c=s.getUint16(a+1),a+=3,o(c);case 219:return c=s.getUint32(a+1),a+=5,o(c);case 220:return c=s.getUint16(a+1),a+=3,n(c);case 221:return c=s.getUint32(a+1),a+=5,n(c);case 222:return c=s.getUint16(a+1),a+=3,t(c);case 223:return c=s.getUint32(a+1),a+=5,t(c)}throw new Error("Unknown type 0x"+d.toString(16))}var a=0,s=new DataView(e.buffer);return r()}function N(e,t,i,o){switch(e){case 1:return function(e,t){var i=e.length;t||(t=new Float32Array(i/4));for(var o=r(t),n=r(e),a=0,s=0,c=i/4;c>a;++a,s+=4)o.setFloat32(s,n.getFloat32(s),!0);return t}(t);case 2:return s(t);case 3:return d(t);case 4:return l(t);case 5:return a(t);case 6:return v(l(t),new Uint8Array(i));case 7:return v(l(t));case 8:return m(v(l(t)),h);case 9:return n=l(t),u=l(o)[0],p(v(n,c(f)),u,f);case 10:return _(d(t),l(o)[0]);case 11:return p(d(t),l(o)[0]);case 12:return E(d(t),l(o)[0]);case 13:return E(s(t),l(o)[0]);case 14:return y(d(t));case 15:return y(s(t))}var n,u,f,h}function P(e,t){var i=(t=t||{}).ignoreFields,o={};return j.forEach(function(t){var n,a,s,c,d,l=!!i&&-1!==i.indexOf(t),u=e[t];l||void 0===u||(u instanceof Uint8Array?o[t]=N.apply(null,(a=r(n=u),s=a.getInt32(0),c=a.getInt32(4),d=n.subarray(8,12),[s,n=n.subarray(12),c,d])):o[t]=u)}),o}function M(e){return String.fromCharCode.apply(null,e).replace(/\0/g,"")}function H(e,t){return e instanceof ArrayBuffer&&(e=new Uint8Array(e)),P(e instanceof Uint8Array?O(e):e,t)}function z(e,t,i,o){var n=new XMLHttpRequest;n.addEventListener("load",function(){try{var e=H(n.response);i(e)}catch(e){o(e)}},!0),n.addEventListener("error",o,!0),n.responseType="arraybuffer",n.open("GET",t+e.toUpperCase()),n.send()}var D=["mmtfVersion","mmtfProducer","unitCell","spaceGroup","structureId","title","depositionDate","releaseDate","experimentalMethods","resolution","rFree","rWork","bioAssemblyList","ncsOperatorList","entityList","groupList","numBonds","numAtoms","numGroups","numChains","numModels","groupsPerChain","chainsPerModel"],j=D.concat(["xCoordList","yCoordList","zCoordList","groupIdList","groupTypeList","chainIdList","bFactorList","atomIdList","altLocList","occupancyList","secStructList","insCodeList","sequenceIndexList","chainNameList","bondAtomList","bondOrderList"]),F="//mmtf.rcsb.org/v1.0/",V=F+"full/",U=F+"reduced/";return e.encode=function(e){return o(I(e))},e.decode=H,e.traverse=function(e,t,i){var o,n,r,a,s,c,d=(i=i||{}).firstModelOnly,l=t.onModel,u=t.onChain,p=t.onGroup,f=t.onAtom,v=t.onBond,h=0,m=0,g=0,y=0,E=0,_=-1,b=e.chainNameList,w=e.secStructList,T=e.insCodeList,x=e.sequenceIndexList,C=e.atomIdList,R=e.bFactorList,S=e.altLocList,L=e.occupancyList,A=e.bondAtomList,I=e.bondOrderList;for(o=0,n=e.chainsPerModel.length;n>o&&!(d&&h>0);++o){var O=e.chainsPerModel[h];for(l&&l({chainCount:O,modelIndex:h}),r=0;O>r;++r){var N=e.groupsPerChain[m];if(u){var P=M(e.chainIdList.subarray(4*m,4*m+4)),H=null;b&&(H=M(b.subarray(4*m,4*m+4))),u({groupCount:N,chainIndex:m,modelIndex:h,chainId:P,chainName:H})}for(a=0;N>a;++a){var z=e.groupList[e.groupTypeList[g]],D=z.atomNameList.length;if(p){var j=null;w&&(j=w[g]);var F=null;e.insCodeList&&(F=String.fromCharCode(T[g]));var V=null;x&&(V=x[g]),p({atomCount:D,groupIndex:g,chainIndex:m,modelIndex:h,groupId:e.groupIdList[g],groupType:e.groupTypeList[g],groupName:z.groupName,singleLetterCode:z.singleLetterCode,chemCompType:z.chemCompType,secStruct:j,insCode:F,sequenceIndex:V})}for(s=0;D>s;++s){if(f){var U=null;C&&(U=C[y]);var k=null;R&&(k=R[y]);var G=null;S&&(G=String.fromCharCode(S[y]));var B=null;L&&(B=L[y]),f({atomIndex:y,groupIndex:g,chainIndex:m,modelIndex:h,atomId:U,element:z.elementList[s],atomName:z.atomNameList[s],formalCharge:z.formalChargeList[s],xCoord:e.xCoordList[y],yCoord:e.yCoordList[y],zCoord:e.zCoordList[y],bFactor:k,altLoc:G,occupancy:B})}y+=1}if(v){var X=z.bondAtomList;for(s=0,c=z.bondOrderList.length;c>s;++s)v({atomIndex1:y-D+X[2*s],atomIndex2:y-D+X[2*s+1],bondOrder:z.bondOrderList[s]})}g+=1}m+=1}if(E=_+1,_=y-1,v&&A)for(s=0,c=A.length;c>s;s+=2){var q=A[s],W=A[s+1];(q>=E&&_>=q||W>=E&&_>=W)&&v({atomIndex1:q,atomIndex2:W,bondOrder:I?I[s/2]:null})}h+=1}},e.fetch=function(e,t,i){z(e,V,t,i)},e.fetchReduced=function(e,t,i){z(e,U,t,i)},e.version="v1.0.1",e.fetchUrl=V,e.fetchReducedUrl=U,e.encodeMsgpack=o,e.encodeMmtf=I,e.decodeMsgpack=O,e.decodeMmtf=P,e}MMTF=initIcn3dpyMMTF(MMTF),function(e,t,i){var o,n="__instance__",r="firstChild",a=setTimeout;function s(e){return void 0!==e}function c(e){return"object"==typeof e}function d(e){return Object.keys(e).length}function l(e,t,i){return ei?i:e}function u(e,t){return parseInt(e,t||10)}function p(e){return Math.round(e)}function f(e){var t,i,o,n,r,a,s,c,d=+e[0],l=+e[1],u=+e[2];switch(a=u*(1-l),s=u*(1-(r=6*d-(n=Math.floor(6*d)))*l),c=u*(1-(1-r)*l),n=n||0,s=s||0,c=c||0,n%6){case 0:t=u,i=c,o=a;break;case 1:t=s,i=u,o=a;break;case 2:t=a,i=u,o=c;break;case 3:t=a,i=s,o=u;break;case 4:t=c,i=a,o=u;break;case 5:t=u,i=a,o=s}return[p(255*t),p(255*i),p(255*o)]}function v(e){return m(f(e))}function h(e){var t,i=+e[0],o=+e[1],n=+e[2],r=Math.max(i,o,n),a=Math.min(i,o,n),s=r-a,c=0===r?0:s/r,d=r/255;switch(r){case a:t=0;break;case i:t=o-n+s*(o
';var H,z=_[r].children,D=N([0,1,1]),j=z[0],F=z[1],V=j[r],U=F[r],k=0,G=0,B=0,X=0,q=0,W=0,Y=0,Z=0,Q=v(D);function K(e,t){e&&"h"!==e||M("change:h",t),e&&"sv"!==e||M("change:sv",t),M("change",t)}function $(){return _.parentNode}function J(n,r){n||((u||r||p).appendChild(_),m.visible=!0),Y=O(_).w,Z=O(_).h;var a=O(F),s=O(U),c=O(j).h,d=a.w,h=a.h,g=O(V).h,y=s.w,E=s.h;if(n){function L(e){var t=e.target,o=t===i||A(t,i)===i;o?J():m.exit(),M(o?"enter":"exit",[m])}_.style.left=_.style.top="-9999px",!1!==o&&C(o,i,L),m.create=function(){return J(1),M("create",[m]),m},m.destroy=function(){return!1!==o&&R(o,i,L),m.exit(),P(!1),M("destroy",[m]),m}}else ee();function z(e){f(D);var t=f([D[0],1,1]);F.style.backgroundColor="rgb("+t.join(",")+")",P(D),I(e)}function q(e){var t,i,o,n,r,a;B&&(i=l(S(j,t=e).y,0,c),D[0]=(c-i)/c,V.style.top=i-g/2+"px",z(t),Q=v(D),k||(M("drag:h",[Q,m]),M("drag",[Q,m]),K("h",[Q,m]))),X&&(n=S(F,o=e),r=l(n.x,0,d),a=l(n.y,0,h),D[1]=1-(d-r)/d,D[2]=(h-a)/h,U.style.right=d-r-y/2+"px",U.style.top=a-E/2+"px",z(o),Q=v(D),G||(M("drag:sv",[Q,m]),M("drag",[Q,m]),K("sv",[Q,m]))),k=0,G=0}function W(e){var t=e.target,n=B?"h":"sv",r=[v(D),m],a=t===i||A(t,i)===i,s=t===_||A(t,_)===_;a||s?s&&(M("stop:"+n,r),M("stop",r),K(n,r)):$()&&!1!==o&&(m.exit(),M("exit",[m]),K(0,r)),B=0,X=0}function te(e){k=1,B=1,q(e),I(e),M("start:h",[Q,m]),M("start",[Q,m]),K("h",[Q,m])}function ie(e){G=1,X=1,q(e),I(e),M("start:sv",[Q,m]),M("start",[Q,m]),K("sv",[Q,m])}H=function(){D=N(D),z(),V.style.top=c-g/2-c*+D[0]+"px",U.style.right=d-y/2-d*+D[1]+"px",U.style.top=h-E/2-h*+D[2]+"px"},m.exit=function(i){return $()&&($().removeChild(_),m.visible=!1),R(b,j,te),R(b,F,ie),R(w,t,q),R(T,t,W),R(x,e,ee),m},H(),n||(C(b,j,te),C(b,F,ie),C(w,t,q),C(T,t,W),C(x,e,ee))}function ee(){return m.fit()}return J(1),a(function(){var e=[v(D),m];M("create",e),K(0,e)},0),m.fit=function(t){var o=O(e),n=O(h),r=o.w-n.w,a=o.h-h.clientHeight,d=L(e),u=L(i);if(q=u.l+d.l,W=u.t+d.t+O(i).h,c(t))s(t[0])&&(q=t[0]),s(t[1])&&(W=t[1]);else{var p=d.l,f=d.t,v=d.l+o.w-Y-r,g=d.t+o.h-Z-a;q=l(q,p,v)>>0,W=l(W,f,g)>>0}return _.style.left=q+"px",_.style.top=W+"px",M("fit",[m]),m},m.set=function(e){return s(e)?("string"==typeof e&&(e=g.parse(e)),P(e),H(),m):N()},m.get=function(e){return N(e)},m.target=i,m.picker=_,m.visible=!1,m.on=function(e,t,i){return s(e)?s(t)?(s(E[e])||(E[e]={}),s(i)||(i=d(E[e])),E[e][i]=t,m):E[e]:E},m.off=function(e,t){return s(e)?s(t)?(delete E[e][t],m):(E[e]={},m):(E={},m)},m.fire=M,m.hooks=E,m.enter=function(e){return J(0,e)},m}).version="1.3.9",o[n]={},o.each=function(e,t){return a(function(){var t,i=o[n];for(t in i)e(i[t],t,i)},0===t?0:t||1),o},o.parse=b,o._HSV2RGB=f,o._HSV2HEX=v,o._RGB2HSV=h,o._HEX2HSV=g,o._HEX2RGB=function(e){return[+(t=y(e))[0]/255,+t[1]/255,+t[2]/255];var t},o.HSV2RGB=function(e){return f(E(e))},o.HSV2HEX=function(e){return v(E(e))},o.RGB2HSV=function(e){return _(h(e))},o.RGB2HEX=m,o.HEX2HSV=function(e){return _(g(e))},o.HEX2RGB=y}(window,document);var saveAs=function(e){"use strict";if(!(void 0===e||"undefined"!=typeof navigator&&/MSIE [1-9]\./.test(navigator.userAgent))){var t=function(){return e.URL||e.webkitURL||e},i=e.document.createElementNS("http://www.w3.org/1999/xhtml","a"),o="download"in i,n=/constructor/i.test(e.HTMLElement)||e.safari,r=/CriOS\/[\d]+/.test(navigator.userAgent),a=e.setImmediate||e.setTimeout,s=function(e){a(function(){throw e},0)},c=function(e){setTimeout(function(){"string"==typeof e?t().revokeObjectURL(e):e.remove()},4e4)},d=function(e){return/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)?new Blob([String.fromCharCode(65279),e],{type:e.type}):e},l=function(l,u,p){p||(l=d(l));var f,v=this,h="application/octet-stream"===(l?l.type:void 0),m=function(){!function(e,t,i){for(var o=(t=[].concat(t)).length;o--;){var n=e["on"+t[o]];if("function"==typeof n)try{n.call(e,i||e)}catch(e){s(e)}}}(v,"writestart progress write writeend".split(" "))};if(v.readyState=v.INIT,o)return f||(f=t().createObjectURL(l)),void a(function(){var e,t;i.href=f,i.download=u,e=i,t=new MouseEvent("click"),e.dispatchEvent(t),m(),c(f),v.readyState=v.DONE},0);!function(){if((r||h&&n)&&e.FileReader){var i=new FileReader;return i.onloadend=function(){var t=r?i.result:i.result.replace(/^data:[^;]*;/,"data:attachment/file;");e.open(t,"_blank")||(e.location.href=t),t=void 0,v.readyState=v.DONE,m()},i.readAsDataURL(l),void(v.readyState=v.INIT)}f||(f=t().createObjectURL(l)),h?e.location.href=f:e.open(f,"_blank")||(e.location.href=f);v.readyState=v.DONE,m(),c(f)}()},u=l.prototype;return"undefined"!=typeof navigator&&navigator.msSaveOrOpenBlob?function(e,t,i){return t=t||e.name||"download",i||(e=d(e)),navigator.msSaveOrOpenBlob(e,t)}:(u.abort=function(){},u.readyState=u.INIT=0,u.WRITING=1,u.DONE=2,u.error=u.onwritestart=u.onprogress=u.onwrite=u.onabort=u.onerror=u.onwriteend=null,function(e,t,i){return new l(e,t||e.name||"download",i)})}}("undefined"!=typeof self&&self||"undefined"!=typeof window&&window||this);!function(e){"use strict";var t=e.HTMLCanvasElement&&e.HTMLCanvasElement.prototype,i=e.Blob&&function(){try{return Boolean(new Blob)}catch(e){return!1}}(),o=i&&e.Uint8Array&&function(){try{return 100===new Blob([new Uint8Array(100)]).size}catch(e){return!1}}(),n=e.BlobBuilder||e.WebKitBlobBuilder||e.MozBlobBuilder||e.MSBlobBuilder,r=/^data:((.*?)(;charset=.*?)?)(;base64)?,/,a=(i||n)&&e.atob&&e.ArrayBuffer&&e.Uint8Array&&function(e){var t,a,s,c,d,l,u,p,f;if(!(t=e.match(r)))throw new Error("invalid data URI");for(a=t[2]?t[1]:"text/plain"+(t[3]||";charset=US-ASCII"),s=!!t[4],c=e.slice(t[0].length),d=s?atob(c):decodeURIComponent(c),l=new ArrayBuffer(d.length),u=new Uint8Array(l),p=0;p
0||window.navigator.userAgent.match(/Trident.*rv\:11\./))}isMobile(){return this.icn3dui,/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(window.navigator.userAgent)}isMac(){return this.icn3dui,/Mac/i.test(window.navigator.userAgent)}isAndroid(){return this.icn3dui,/android/i.test(window.navigator.userAgent.toLowerCase())}isChrome(){return this.icn3dui,navigator.userAgent.includes("Chrome")&&navigator.vendor.includes("Google Inc")}isSessionStorageSupported(){return this.icn3dui,window.sessionStorage}isLocalStorageSupported(){return this.icn3dui,window.localStorage}hexToRgb(e,t){this.icn3dui;let s=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return s?{r:parseInt(s[1],16),g:parseInt(s[2],16),b:parseInt(s[3],16),a:t}:null}isCalphaPhosOnly(e){this.icn3dui;let t=!1,s=0,i=0;for(let t in e){if(!(s<100))break;{let s=e[t].name.trim();"CA"!==s&&"P"!==s&&"O3'"!==s&&"O3*"!==s&&++i}++s}return i<.5*s&&(t=!0),t}hasCovalentBond(e,t){let s=this.icn3dui,i=s.parasCls.covalentRadii[e.elem.toUpperCase()]+s.parasCls.covalentRadii[t.elem.toUpperCase()],n=e.coord.x-t.coord.x,l=e.coord.y-t.coord.y,r=e.coord.z-t.coord.z;return n*n+l*l+r*r<("N"==e.elem&&"H"==t.elem.substr(0,1)||"N"==t.elem&&"H"==e.elem.substr(0,1)?2.2:1.3)*i*i}residueName2Abbr(e){this.icn3dui;let t=e.indexOf(" ");switch(t>0&&(e=e.substr(0,t)),e){case" A":case" DA":case"DA":case"ALA":return"A";case" C":case" DC":case"DC":case"CYS":return"C";case" G":case" DG":case"DG":case"GLY":return"G";case" T":case" DT":case"DT":case"THR":return"T";case" U":case" DU":case"DU":case"SEC":return"U";case" I":case" DI":case"DI":case"ILE":return"I";case"ARG":return"R";case"ASN":return"N";case"ASP":return"D";case"GLU":return"E";case"GLN":return"Q";case"HIS":return"H";case"LEU":return"L";case"LYS":return"K";case"MET":return"M";case"PHE":return"F";case"PRO":return"P";case"SER":return"S";case"TRP":return"W";case"TYR":return"Y";case"VAL":return"V";case"HOH":case"WAT":return"O";default:return e.trim()}}residueAbbr2Name(e){if(this.icn3dui,(e=e.toUpperCase()).length>1)return e;switch(e){case"A":return"ALA";case"R":return"ARG";case"N":return"ASN";case"D":return"ASP";case"C":return"CYS";case"E":return"GLU";case"Q":return"GLN";case"G":return"GLY";case"H":return"HIS";case"I":return"ILE";case"L":return"LEU";case"K":return"LYS";case"M":return"MET";case"F":return"PHE";case"P":return"PRO";case"S":return"SER";case"T":return"THR";case"W":return"TRP";case"Y":return"TYR";case"V":return"VAL";case"O":return"HOH";default:return e.trim()}}getJSONFromArray(e){this.icn3dui;let t="";for(let s=0,i=e.length;sd?1:ah?1:cs&&(e.htmlCls.WIDTH=s),i&&e.htmlCls.HEIGHT>i&&(e.htmlCls.HEIGHT=i)}sumArray(e){let t=0;for(let s=0,i=e.length;sRed and blue membranes indicate extracellular and intracellular membranes, respectively.
"}getStructures(e){let t=this.icn3dui,s={};for(let i in e){s[t.icn3d.atoms[i].structure]=1}return s}getHlStructures(e){let t=this.icn3dui;return e||(e=t.icn3d.hAtoms),this.getStructures(e)}getDisplayedStructures(e){let t=this.icn3dui;return e||(e=t.icn3d.dAtoms),this.getStructures(e)}getDateDigitStr(){this.icn3dui;let e=new Date,t=(e.getMonth()+1).toString();e.getMonth()+1<10&&(t="0"+t);let s=e.getDate().toString();return e.getDate()<10&&(s="0"+s),e.getFullYear().toString()+t+s}}class i{constructor(e){this.icn3dui=e,this.glycanHash={GLC:{c:"1E90FF",s:"sphere"},BGC:{c:"1E90FF",s:"sphere"},NAG:{c:"1E90FF",s:"cube"},NDG:{c:"1E90FF",s:"cube"},GCS:{c:"1E90FF",s:"cube"},PA1:{c:"1E90FF",s:"cube"},GCU:{c:"1E90FF",s:"cone"},BDP:{c:"1E90FF",s:"cone"},G6D:{c:"1E90FF",s:"cone"},DDA:{c:"1E90FF",s:"cylinder"},B6D:{c:"1E90FF",s:"cylinder"},XXM:{c:"1E90FF",s:"cylinder"},MAN:{c:"00FF00",s:"sphere"},BMA:{c:"00FF00",s:"sphere"},BM3:{c:"00FF00",s:"cube"},"95Z":{c:"00FF00",s:"cube"},MAV:{c:"00FF00",s:"cone"},BEM:{c:"00FF00",s:"cone"},RAM:{c:"00FF00",s:"cone"},RM4:{c:"00FF00",s:"cone"},TYV:{c:"00FF00",s:"cylinder"},ARA:{c:"00FF00",s:"cylinder"},ARB:{c:"00FF00",s:"cylinder"},KDN:{c:"00FF00",s:"cylinder"},KDM:{c:"00FF00",s:"cylinder"},"6PZ":{c:"00FF00",s:"cylinder"},GMH:{c:"00FF00",s:"cylinder"},BDF:{c:"00FF00",s:"cylinder"},GAL:{c:"FFFF00",s:"sphere"},GLA:{c:"FFFF00",s:"sphere"},NGA:{c:"FFFF00",s:"cube"},A2G:{c:"FFFF00",s:"cube"},X6X:{c:"FFFF00",s:"cube"},"1GN":{c:"FFFF00",s:"cube"},ADA:{c:"FFFF00",s:"cone"},GTR:{c:"FFFF00",s:"cone"},LDY:{c:"FFFF00",s:"cylinder"},KDO:{c:"FFFF00",s:"cylinder"},T6T:{c:"FFFF00",s:"cylinder"},GUP:{c:"A52A2A",s:"sphere"},GL0:{c:"A52A2A",s:"sphere"},LGU:{c:"A52A2A",s:"cone"},ABE:{c:"A52A2A",s:"cylinder"},XYS:{c:"A52A2A",s:"cylinder"},XYP:{c:"A52A2A",s:"cylinder"},SOE:{c:"A52A2A",s:"cylinder"},PZU:{c:"FF69B4",s:"cylinder"},RIP:{c:"FF69B4",s:"cylinder"},"0MK":{c:"FF69B4",s:"cylinder"},ALL:{c:"8A2BE2",s:"sphere"},AFD:{c:"8A2BE2",s:"sphere"},NAA:{c:"8A2BE2",s:"cube"},SIA:{c:"8A2BE2",s:"cylinder"},SIB:{c:"8A2BE2",s:"cylinder"},AMU:{c:"8A2BE2",s:"cylinder"},X0X:{c:"1E90FF",s:"cone"},X1X:{c:"1E90FF",s:"cone"},NGC:{c:"1E90FF",s:"cylinder"},NGE:{c:"1E90FF",s:"cylinder"},"4N2":{c:"A0522D",s:"sphere"},HSQ:{c:"A0522D",s:"cube"},IDR:{c:"A0522D",s:"cone"},MUR:{c:"A0522D",s:"cylinder"},FUC:{c:"FF0000",s:"cone"},FUL:{c:"FF0000",s:"cone"}},this.nucleotidesArray=[" G"," A"," T"," C"," U"," DG"," DA"," DT"," DC"," DU","G","A","T","C","U","DG","DA","DT","DC","DU"],this.ionsArray=[" K"," NA"," MG"," AL"," CA"," TI"," MN"," FE"," NI"," CU"," ZN"," AG"," BA"," F"," CL"," BR"," I","K","NA","MG","AL","CA","TI","MN","FE","NI","CU","ZN","AG","BA","F","CL","BR","I"],this.cationsTrimArray=["K","NA","MG","AL","CA","TI","MN","FE","NI","CU","ZN","AG","BA"],this.anionsTrimArray=["F","CL","BR","I"],this.ionCharges={K:1,NA:1,MG:2,AL:3,CA:2,TI:3,MN:2,FE:3,NI:2,CU:2,ZN:2,AG:1,BA:2},this.vdwRadii={H:1.08,HE:1.34,LI:1.75,BE:2.05,B:1.47,C:1.49,N:1.41,O:1.4,F:1.39,NE:1.68,NA:1.84,MG:2.05,AL:2.11,SI:2.07,P:1.92,S:1.82,CL:1.83,AR:1.93,K:2.05,CA:2.21,SC:2.16,TI:1.87,V:1.79,CR:1.89,MN:1.97,FE:1.94,CO:1.92,NI:1.84,CU:1.86,ZN:2.1,GA:2.08,GE:2.15,AS:2.06,SE:1.93,BR:1.98,KR:2.12,RB:2.16,SR:2.24,Y:2.19,ZR:1.86,NB:2.07,MO:2.09,TC:2.09,RU:2.07,RH:1.95,PD:2.02,AG:2.03,CD:2.3,IN:2.36,SN:2.33,SB:2.25,TE:2.23,I:2.23,XE:2.21,CS:2.22,BA:2.51,LA:2.4,CE:2.35,PR:2.39,ND:2.29,PM:2.36,SM:2.29,EU:2.33,GD:2.37,TB:2.21,DY:2.29,HO:2.16,ER:2.35,TM:2.27,YB:2.42,LU:2.21,HF:2.12,TA:2.17,W:2.1,RE:2.17,OS:2.16,IR:2.02,PT:2.09,AU:2.17,HG:2.09,TL:2.35,PB:2.32,BI:2.43,PO:2.29,AT:2.36,RN:2.43,FR:2.56,RA:2.43,AC:2.6,TH:2.37,PA:2.43,U:2.4,NP:2.21,PU:2.56,AM:2.56,CM:2.56,BK:2.56,CF:2.56,ES:2.56,FM:2.56},this.covalentRadii={H:.31,HE:.28,LI:1.28,BE:.96,B:.84,C:.76,N:.71,O:.66,F:.57,NE:.58,NA:1.66,MG:1.41,AL:1.21,SI:1.11,P:1.07,S:1.05,CL:1.02,AR:1.06,K:2.03,CA:1.76,SC:1.7,TI:1.6,V:1.53,CR:1.39,MN:1.39,FE:1.32,CO:1.26,NI:1.24,CU:1.32,ZN:1.22,GA:1.22,GE:1.2,AS:1.19,SE:1.2,BR:1.2,KR:1.16,RB:2.2,SR:1.95,Y:1.9,ZR:1.75,NB:1.64,MO:1.54,TC:1.47,RU:1.46,RH:1.42,PD:1.39,AG:1.45,CD:1.44,IN:1.42,SN:1.39,SB:1.39,TE:1.38,I:1.39,XE:1.4,CS:2.44,BA:2.15,LA:2.07,CE:2.04,PR:2.03,ND:2.01,PM:1.99,SM:1.98,EU:1.98,GD:1.96,TB:1.94,DY:1.92,HO:1.92,ER:1.89,TM:1.9,YB:1.87,LU:1.87,HF:1.75,TA:1.7,W:1.62,RE:1.51,OS:1.44,IR:1.41,PT:1.36,AU:1.36,HG:1.32,TL:1.45,PB:1.46,BI:1.48,PO:1.4,AT:1.5,RN:1.5,FR:2.6,RA:2.21,AC:2.15,TH:2.06,PA:2,U:1.96,NP:1.9,PU:1.87,AM:1.8,CM:1.69},this.atomColors={H:this.thr(16777215),He:this.thr(16761035),HE:this.thr(16761035),Li:this.thr(11674146),LI:this.thr(11674146),B:this.thr(65280),C:this.thr(11184810),N:this.thr(255),O:this.thr(15728640),F:this.thr(14329120),Na:this.thr(255),NA:this.thr(255),Mg:this.thr(2263842),MG:this.thr(2263842),Al:this.thr(8421520),AL:this.thr(8421520),Si:this.thr(14329120),SI:this.thr(14329120),P:this.thr(16753920),S:this.thr(16762930),Cl:this.thr(65280),CL:this.thr(65280),Ca:this.thr(8421520),CA:this.thr(8421520),Ti:this.thr(8421520),TI:this.thr(8421520),Cr:this.thr(8421520),CR:this.thr(8421520),Mn:this.thr(8421520),MN:this.thr(8421520),Fe:this.thr(16753920),FE:this.thr(16753920),Ni:this.thr(10824234),NI:this.thr(10824234),Cu:this.thr(10824234),CU:this.thr(10824234),Zn:this.thr(10824234),ZN:this.thr(10824234),Br:this.thr(10824234),BR:this.thr(10824234),Ag:this.thr(8421520),AG:this.thr(8421520),I:this.thr(10494192),Ba:this.thr(16753920),BA:this.thr(16753920),Au:this.thr(14329120),AU:this.thr(14329120)},this.atomnames={H:"Hydrogen",HE:"Helium",LI:"Lithium",B:"Boron",C:"Carbon",N:"Nitrogen",O:"Oxygen",F:"Fluorine",NA:"Sodium",MG:"Magnesium",AL:"Aluminum",SI:"Silicon",P:"Phosphorus",S:"Sulfur",CL:"Chlorine",CA:"Calcium",TI:"Titanium",CR:"Chromium",MN:"Manganese",FE:"Iron",NI:"Nickel",CU:"Copper",ZN:"Zinc",BR:"Bromine",AG:"Silver",I:"Iodine",BA:"Barium",AU:"Gold"},this.defaultAtomColor=this.thr(13421772),this.stdChainColors=[this.thr(16711935),this.thr(255),this.thr(10053171),this.thr(65433),this.thr(16750848),this.thr(16737894),this.thr(3329330),this.thr(2003199),this.thr(16416882),this.thr(16753920),this.thr(52945),this.thr(16738740),this.thr(65280),this.thr(255),this.thr(16711680),this.thr(16776960),this.thr(65535),this.thr(16711935),this.thr(3978097),this.thr(4620980),this.thr(13458524),this.thr(16770229),this.thr(11529966),this.thr(15631086),this.thr(25600),this.thr(139),this.thr(9109504),this.thr(13468991),this.thr(35723),this.thr(9699539)],this.backgroundColors={black:this.thr(0),grey:this.thr(13421772),white:this.thr(16777215),transparent:this.thr(16777215)},this.residueColors={ALA:this.thr(13158600),ARG:this.thr(1334015),ASN:this.thr(56540),ASP:this.thr(15075850),CYS:this.thr(15132160),GLN:this.thr(56540),GLU:this.thr(15075850),GLY:this.thr(15461355),HIS:this.thr(8553170),ILE:this.thr(1016335),LEU:this.thr(1016335),LYS:this.thr(1334015),MET:this.thr(15132160),PHE:this.thr(3289770),PRO:this.thr(14456450),SER:this.thr(16422400),THR:this.thr(16422400),TRP:this.thr(11819700),TYR:this.thr(3289770),VAL:this.thr(1016335),ASX:this.thr(16738740),GLX:this.thr(16738740),G:this.thr(32768),A:this.thr(6324479),T:this.thr(16744448),C:this.thr(16711680),U:this.thr(16744448),DG:this.thr(32768),DA:this.thr(6324479),DT:this.thr(16744448),DC:this.thr(16711680),DU:this.thr(16744448)},this.residueArea={ALA:247,ARG:366,ASN:290,ASP:285,CYS:271,GLN:336,GLU:325,GLY:217,HIS:340,ILE:324,LEU:328,LYS:373,MET:346,PHE:366,PRO:285,SER:265,THR:288,TRP:414,TYR:387,VAL:293,ASX:290,GLX:336,G:520,A:507,T:515,C:467,U:482,DG:520,DA:507,DT:515,DC:467,DU:482},this.defaultResidueColor=this.thr(12492910),this.chargeColors={" G":this.thr(16711680)," A":this.thr(16711680)," T":this.thr(16711680)," C":this.thr(16711680)," U":this.thr(16711680)," DG":this.thr(16711680)," DA":this.thr(16711680)," DT":this.thr(16711680)," DC":this.thr(16711680)," DU":this.thr(16711680),G:this.thr(16711680),A:this.thr(16711680),T:this.thr(16711680),C:this.thr(16711680),U:this.thr(16711680),DG:this.thr(16711680),DA:this.thr(16711680),DT:this.thr(16711680),DC:this.thr(16711680),DU:this.thr(16711680),ARG:this.thr(255),LYS:this.thr(255),ASP:this.thr(16711680),GLU:this.thr(16711680),HIS:this.thr(8421631),GLY:this.thr(8947848),PRO:this.thr(8947848),ALA:this.thr(8947848),VAL:this.thr(8947848),LEU:this.thr(8947848),ILE:this.thr(8947848),PHE:this.thr(8947848),SER:this.thr(8947848),THR:this.thr(8947848),ASN:this.thr(8947848),GLN:this.thr(8947848),TYR:this.thr(8947848),MET:this.thr(8947848),CYS:this.thr(8947848),TRP:this.thr(8947848)},this.hydrophobicColors={" G":this.thr(16711680)," A":this.thr(16711680)," T":this.thr(16711680)," C":this.thr(16711680)," U":this.thr(16711680)," DG":this.thr(16711680)," DA":this.thr(16711680)," DT":this.thr(16711680)," DC":this.thr(16711680)," DU":this.thr(16711680),G:this.thr(16711680),A:this.thr(16711680),T:this.thr(16711680),C:this.thr(16711680),U:this.thr(16711680),DG:this.thr(16711680),DA:this.thr(16711680),DT:this.thr(16711680),DC:this.thr(16711680),DU:this.thr(16711680),ARG:this.thr(255),LYS:this.thr(255),ASP:this.thr(16711680),GLU:this.thr(16711680),HIS:this.thr(8421631),TRP:this.thr().setHSL(1/3,1,.5),PHE:this.thr().setHSL(1/3,1,.5909090909090908),LEU:this.thr().setHSL(1/3,1,.700956937799043),ILE:this.thr().setHSL(1/3,1,.7320574162679425),TYR:this.thr().setHSL(1/3,1,.5+.69/2.09),MET:this.thr().setHSL(1/3,1,.5+.71/2.09),VAL:this.thr().setHSL(1/3,1,.5+.815/2.09),CYS:this.thr().setHSL(1/3,1,.5+1.035/2.09),PRO:this.thr().setHSL(1/6,1,.9391304347826086),THR:this.thr().setHSL(1/6,1,.8913043478260869),SER:this.thr().setHSL(1/6,1,.8),ALA:this.thr().setHSL(1/6,1,.7826086956521738),GLN:this.thr().setHSL(1/6,1,.6652173913043478),ASN:this.thr().setHSL(1/6,1,.6304347826086956),GLY:this.thr().setHSL(1/6,1,.5)},this.normalizedHPColors={" G":this.thr(16777215)," A":this.thr(16777215)," T":this.thr(16777215)," C":this.thr(16777215)," U":this.thr(16777215)," DG":this.thr(16777215)," DA":this.thr(16777215)," DT":this.thr(16777215)," DC":this.thr(16777215)," DU":this.thr(16777215),G:this.thr(16777215),A:this.thr(16777215),T:this.thr(16777215),C:this.thr(16777215),U:this.thr(16777215),DG:this.thr(16777215),DA:this.thr(16777215),DT:this.thr(16777215),DC:this.thr(16777215),DU:this.thr(16777215),ARG:this.thr(16777215),LYS:this.thr(16777215),ASP:this.thr(16777215),GLU:this.thr(16777215),HIS:this.thr(16777215),TRP:this.thr().setHSL(1/3,1,.5),PHE:this.thr().setHSL(1/3,1,.558641975308642),LEU:this.thr().setHSL(1/3,1,.6296296296296295),ILE:this.thr().setHSL(1/3,1,.6496913580246912),TYR:this.thr().setHSL(1/3,1,.5+.69/3.24),MET:this.thr().setHSL(1/3,1,.5+.71/3.24),VAL:this.thr().setHSL(1/3,1,.5+.815/3.24),CYS:this.thr().setHSL(1/3,1,.5+1.035/3.24),PRO:this.thr().setHSL(1/3,1,.5+1.115/3.24),THR:this.thr().setHSL(1/3,1,.5+1.17/3.24),SER:this.thr().setHSL(1/3,1,.5+1.275/3.24),ALA:this.thr().setHSL(1/3,1,.5+1.295/3.24),GLN:this.thr().setHSL(1/3,1,.5+1.43/3.24),ASN:this.thr().setHSL(1/3,1,.5+1.47/3.24),GLY:this.thr().setHSL(1/3,1,1)},this.hydrophobicValues={" G":3," A":3," T":3," C":3," U":3," DG":3," DA":3," DT":3," DC":3," DU":3,G:3,A:3,T:3,C:3,U:3,DG:3,DA:3,DT:3,DC:3,DU:3,ARG:1.5,LYS:1.5,ASP:3,GLU:3,HIS:2,TRP:-2.09,PHE:-1.71,LEU:-1.25,ILE:-1.12,TYR:-.71,MET:-.67,VAL:-.46,CYS:-.02,PRO:.14,THR:.25,SER:.46,ALA:.5,GLN:.77,ASN:.85,GLY:1.15},this.residueAbbrev={ALA:"A (Ala)",ARG:"R (Arg)",ASN:"N (Asn)",ASP:"D (Asp)",CYS:"C (Cys)",GLN:"Q (Gln)",GLU:"E (Glu)",GLY:"G (Gly)",HIS:"H (His)",ILE:"I (Ile)",LEU:"L (Leu)",LYS:"K (Lys)",MET:"M (Met)",PHE:"F (Phe)",PRO:"P (Pro)",SER:"S (Ser)",THR:"T (Thr)",TRP:"W (Trp)",TYR:"Y (Tyr)",VAL:"V (Val)",ASX:"X (Asx)",GLX:"X (Glx)",G:"Guanine",A:"Adenine",T:"Thymine",C:"Cytosine",U:"Uracil",DG:"deoxy-Guanine",DA:"deoxy-Adenine",DT:"deoxy-Thymine",DC:"deoxy-Cytosine",DU:"deoxy-Uracil"},this.ssColors={helix:this.thr(16711680),sheet:this.thr(32768),coil:this.thr(6324479)},this.ssColors2={helix:this.thr(16711680),sheet:this.thr(16762880),coil:this.thr(6324479)},this.resn2restype={ALA:1,ARG:4,ASN:7,ASP:10,CYS:13,GLN:16,GLU:19,GLY:22,HIS:25,ILE:28,LEU:31,LYS:34,MET:37,PHE:40,PRO:43,SER:46,THR:49,TRP:52,TYR:55,VAL:58},this.nuclMainArray=["C1'","C1*","C2'","C2*","C3'","C3*","C4'","C4*","C5'","C5*","O3'","O3*","O4'","O4*","O5'","O5*","P","OP1","O1P","OP2","O2P"],this.b62ResArray=["A","R","N","D","C","Q","E","G","H","I","L","K","M","F","P","S","T","W","Y","V","B","Z","X","*"],this.b62Matrix=[[4,-1,-2,-2,0,-1,-1,0,-2,-1,-1,-1,-1,-2,-1,1,0,-3,-2,0,-2,-1,0,-4],[-1,5,0,-2,-3,1,0,-2,0,-3,-2,2,-1,-3,-2,-1,-1,-3,-2,-3,-1,0,-1,-4],[-2,0,6,1,-3,0,0,0,1,-3,-3,0,-2,-3,-2,1,0,-4,-2,-3,3,0,-1,-4],[-2,-2,1,6,-3,0,2,-1,-1,-3,-4,-1,-3,-3,-1,0,-1,-4,-3,-3,4,1,-1,-4],[0,-3,-3,-3,9,-3,-4,-3,-3,-1,-1,-3,-1,-2,-3,-1,-1,-2,-2,-1,-3,-3,-2,-4],[-1,1,0,0,-3,5,2,-2,0,-3,-2,1,0,-3,-1,0,-1,-2,-1,-2,0,3,-1,-4],[-1,0,0,2,-4,2,5,-2,0,-3,-3,1,-2,-3,-1,0,-1,-3,-2,-2,1,4,-1,-4],[0,-2,0,-1,-3,-2,-2,6,-2,-4,-4,-2,-3,-3,-2,0,-2,-2,-3,-3,-1,-2,-1,-4],[-2,0,1,-1,-3,0,0,-2,8,-3,-3,-1,-2,-1,-2,-1,-2,-2,2,-3,0,0,-1,-4],[-1,-3,-3,-3,-1,-3,-3,-4,-3,4,2,-3,1,0,-3,-2,-1,-3,-1,3,-3,-3,-1,-4],[-1,-2,-3,-4,-1,-2,-3,-4,-3,2,4,-2,2,0,-3,-2,-1,-2,-1,1,-4,-3,-1,-4],[-1,2,0,-1,-3,1,1,-2,-1,-3,-2,5,-1,-3,-1,0,-1,-3,-2,-2,0,1,-1,-4],[-1,-1,-2,-3,-1,0,-2,-3,-2,1,2,-1,5,0,-2,-1,-1,-1,-1,1,-3,-1,-1,-4],[-2,-3,-3,-3,-2,-3,-3,-3,-1,0,0,-3,0,6,-4,-2,-2,1,3,-1,-3,-3,-1,-4],[-1,-2,-2,-1,-3,-1,-1,-2,-2,-3,-3,-1,-2,-4,7,-1,-1,-4,-3,-2,-2,-1,-2,-4],[1,-1,1,0,-1,0,0,0,-1,-2,-2,0,-1,-2,-1,4,1,-3,-2,-2,0,0,0,-4],[0,-1,0,-1,-1,-1,-1,-2,-2,-1,-1,-1,-1,-2,-1,1,5,-2,-2,0,-1,-1,0,-4],[-3,-3,-4,-4,-2,-2,-3,-2,-2,-3,-2,-3,-1,1,-4,-3,-2,11,2,-3,-4,-3,-2,-4],[-2,-2,-2,-3,-2,-1,-2,-3,2,-1,-1,-2,-1,3,-3,-2,-2,2,7,-1,-3,-2,-1,-4],[0,-3,-3,-3,-1,-2,-2,-3,-3,3,1,-2,1,-1,-2,-2,0,-3,-1,4,-3,-2,-1,-4],[-2,-1,3,4,-3,0,1,-1,0,-3,-4,0,-3,-3,-2,0,-1,-4,-3,-3,4,1,-1,-4],[-1,0,0,1,-3,3,4,-2,0,-3,-3,1,-1,-3,-1,0,-1,-3,-2,-2,1,4,-1,-4],[0,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,0,0,-2,-1,-1,-1,-1,-1,-4],[-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,1]]}thr(e){return this.icn3dui,"#0"==e&&(e="#000"),new THREE.Color(e)}}class n{constructor(e){this.icn3dui=e}onId(e,t,s){if(this.icn3dui,!(Object.keys(window).length<2)&&("#"==e.substr(0,1)&&(e=e.substr(1)),document.getElementById(e))){t.split(" ").forEach((t=>{document.getElementById(e).addEventListener(t,s)}))}}onIds(e,t,s){let i=this.icn3dui;Array.isArray(e)?e.forEach((e=>{i.myEventCls.onId(e,t,s)})):i.myEventCls.onId(e,t,s)}}class l{constructor(e){this.icn3dui=e}getRmsdSuprCls(e,t,s){let i,n,l,r,o,a,d,c,h,p,m,u,g,f=this.icn3dui,b=new Array(9),C=new THREE.Vector3,y=new THREE.Vector3,v=[],_=[],w=new Array(3),S=new Array(3),A=new Array(3),x=new Array(3),k=new Array(3),O=new Array(3);if(i=0,s<=1)return{rot:void 0,trans1:void 0,trans2:void 0,rmsd:999};let R=s;for(n=0;n