icn3d 3.28.12 → 3.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/icn3d.js +1570 -330
  2. package/icn3d.min.js +7 -5
  3. package/icn3d.module.js +1570 -330
  4. package/package.json +1 -1
package/icn3d.js CHANGED
@@ -5959,7 +5959,7 @@ class ClickMenu {
5959
5959
  });
5960
5960
 
5961
5961
  me.myEventCls.onIds("#" + me.pre + "mn1_dsn6", "click", function(e) { me.icn3d; //e.preventDefault();
5962
- me.htmlCls.dialogCls.openDlg('dl_dsn6', 'Please input the DSN6 file to display electron density map');
5962
+ me.htmlCls.dialogCls.openDlg('dl_dsn6', 'Please input the map file to display electron density map');
5963
5963
  });
5964
5964
 
5965
5965
 
@@ -5986,7 +5986,7 @@ class ClickMenu {
5986
5986
 
5987
5987
 
5988
5988
  me.myEventCls.onIds("#" + me.pre + "mn1_dsn6url", "click", function(e) { me.icn3d; //e.preventDefault();
5989
- me.htmlCls.dialogCls.openDlg('dl_dsn6url', 'Please input the DSN6 file to display electron density map');
5989
+ me.htmlCls.dialogCls.openDlg('dl_dsn6url', 'Please input the map file to display electron density map');
5990
5990
  });
5991
5991
 
5992
5992
  me.myEventCls.onIds("#" + me.pre + "mn1_exportState", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
@@ -7291,6 +7291,8 @@ class ClickMenu {
7291
7291
  let sigma2fofc = parseFloat($("#" + me.pre + "sigma2fofc" ).val());
7292
7292
  let type = '2fofc';
7293
7293
  await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma2fofc);
7294
+ //ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma2fofc);
7295
+
7294
7296
  //ic.setOptionCls.setOption('map', '2fofc');
7295
7297
  thisClass.setLogCmd('set map 2fofc sigma ' + sigma2fofc, true);
7296
7298
  });
@@ -8547,12 +8549,14 @@ class SetMenu {
8547
8549
 
8548
8550
  html += this.getMenuSep();
8549
8551
 
8550
- html += this.getMenuText('mn1_dsn6wrap', 'Electron Density(DSN6)', undefined, undefined, 2);
8552
+ html += this.getMenuText('mn1_dsn6wrap', 'Electron Density', undefined, undefined, 2);
8551
8553
  html += "<ul>";
8552
8554
  html += this.getLink('mn1_dsn6', 'Local File', undefined, 3);
8553
8555
  html += this.getLink('mn1_dsn6url', 'URL(CORS) ' + me.htmlCls.wifiStr, undefined, 3);
8554
8556
  html += "</ul>";
8555
8557
 
8558
+ html += "<li><br/></li>";
8559
+
8556
8560
  html += "</ul>";
8557
8561
  html += "</li>";
8558
8562
 
@@ -8658,14 +8662,14 @@ class SetMenu {
8658
8662
  }
8659
8663
 
8660
8664
  //!!!
8661
- /*
8665
+
8662
8666
  html += this.getMenuText('m1_exportrefnum', 'Reference Numbers', undefined, undefined, 2);
8663
8667
  html += "<ul>";
8664
8668
  html += this.getLink('mn1_exportIgstrand', 'Ig Strand', undefined, 3);
8665
8669
  html += this.getLink('mn1_exportKabat', 'Kabat', undefined, 3);
8666
8670
  html += this.getLink('mn1_exportImgt', 'IMGT', undefined, 3);
8667
8671
  html += "</ul>";
8668
- */
8672
+
8669
8673
 
8670
8674
  html += "<li><br/></li>";
8671
8675
 
@@ -9506,8 +9510,8 @@ class SetMenu {
9506
9510
  //}
9507
9511
 
9508
9512
  //!!!
9509
- //html += this.getRadio('mn4_clr', 'mn4_clrIgstrand', 'Ig Strand', undefined, undefined, 2);
9510
- //html += this.getRadio('mn4_clr', 'mn4_clrIgproto', 'Ig Protodomain', undefined, undefined, 2);
9513
+ html += this.getRadio('mn4_clr', 'mn4_clrIgstrand', 'Ig Strand', undefined, undefined, 2);
9514
+ html += this.getRadio('mn4_clr', 'mn4_clrIgproto', 'Ig Protodomain', undefined, undefined, 2);
9511
9515
  }
9512
9516
  else {
9513
9517
  //if(!me.cfg.hidelicense) html += this.getRadio('mn4_clr', 'mn1_delphi2', 'DelPhi<br><span style="padding-left:1.5em;">Potential ' + me.htmlCls.licenseStr + '</span>');
@@ -9638,7 +9642,7 @@ class SetMenu {
9638
9642
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelResidues', 'per Residue', undefined, 1, 2);
9639
9643
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelResnum', 'per Residue & Number', undefined, 1, 2);
9640
9644
  //!!!
9641
- //html += this.getRadio('mn6_addlabel', 'mn6_addlabelRefnum', 'per Reference Number', undefined, 1, 2);
9645
+ html += this.getRadio('mn6_addlabel', 'mn6_addlabelRefnum', 'per Reference Number', undefined, 1, 2);
9642
9646
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelChains', 'per Chain', undefined, undefined, 2);
9643
9647
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelTermini', 'N- & C-Termini', undefined, 1, 2);
9644
9648
  }
@@ -9730,11 +9734,11 @@ class SetMenu {
9730
9734
 
9731
9735
  html += "<ul>";
9732
9736
  //!!!
9733
- /*
9737
+
9734
9738
  html += this.getLink('mn6_igrefYes', 'Show Ig Ref. Number', undefined, 2);
9735
9739
  html += this.getLink('mn6_igrefTpl', 'Ig w/ Specified Template', undefined, 2);
9736
9740
  html += this.getLink('mn6_igrefNo', 'Hide Ig Ref. Number', undefined, 2);
9737
- */
9741
+
9738
9742
  html += this.getMenuSep();
9739
9743
 
9740
9744
  html += this.getLink('mn6_customref', 'Custom Ref. Number', undefined, 2);
@@ -10974,23 +10978,19 @@ class SetDialog {
10974
10978
  html += "</div>";
10975
10979
 
10976
10980
  html += me.htmlCls.divStr + "dl_dsn6' class='" + dialogClass + "'>";
10977
- html += this.addNotebookTitle('dl_dsn6', 'Load a DSN6 file');
10978
- html += "<b>Note</b>: Always load a PDB file before loading DSN6 files. <br/><br/><br/>";
10979
-
10980
- html += "<span style='white-space:nowrap;font-weight:bold;'>2fofc contour at: <select id='" + me.pre + "dsn6sigma2fofc'>";
10981
+ html += this.addNotebookTitle('dl_dsn6', 'Load a map file');
10982
+ html += "<b>Note</b>: Always load a PDB file before loading map files. If you don't specify the threshold <br>below, a default one will be chosen.<br/><br/><br/>";
10981
10983
 
10982
- let optArray1 = ['0', '0.5', '1', '1.5', '2', '3', '4', '5', '6', '7', '8', '9', '10'];
10983
- html += me.htmlCls.setHtmlCls.getOptionHtml(optArray1, 3);
10984
+ html += "<span style='white-space:nowrap;font-weight:bold;'>2fofc contour at default threshold or at: "
10985
+ + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigma2fofc' value='' size=8> &sigma;</span><br/>";
10986
+ //html += me.htmlCls.inputFileStr + "id='" + me.pre + "dsn6file2fofc'> " + me.htmlCls.buttonStr + "reload_dsn6file2fofc' style='margin: 6px 20px 0 0;'>Load DSN6</button><br><br><br/>";
10987
+ html += me.htmlCls.inputFileStr + "id='" + me.pre + "dsn6file2fofc'> " + me.htmlCls.buttonStr + "reload_dsn6file2fofc' style='margin: 6px 20px 0 0;'>Load DSN6</button>" + me.htmlCls.buttonStr + "reload_ccp4file2fofc' style='margin: 6px 20px 0 0;'>Load CCP4</button>" + me.htmlCls.buttonStr + "reload_mtzfile2fofc' style='margin-top: 6px;'>Load MTZ</button><br><br><br/>";
10984
10988
 
10985
- html += "</select> &sigma;</span><br/>";
10986
- html += me.htmlCls.inputFileStr + "id='" + me.pre + "dsn6file2fofc'> " + me.htmlCls.buttonStr + "reload_dsn6file2fofc' style='margin-top: 6px;'>Load</button><br><br><br/>";
10989
+ html += "<span style='white-space:nowrap;font-weight:bold;'>fofc contour at default threshold or at: "
10990
+ + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigmafofc' value='' size=8> &sigma;</span><br/>";
10987
10991
 
10988
- html += "<span style='white-space:nowrap;font-weight:bold;'>fofc contour at: <select id='" + me.pre + "dsn6sigmafofc'>";
10989
-
10990
- html += me.htmlCls.setHtmlCls.getOptionHtml(optArray1, 5);
10991
-
10992
- html += "</select> &sigma;</span><br/>";
10993
- html += me.htmlCls.inputFileStr + "id='" + me.pre + "dsn6filefofc'> " + me.htmlCls.buttonStr + "reload_dsn6filefofc' style='margin-top: 6px;'>Load</button><br><br><br>";
10992
+ //html += me.htmlCls.inputFileStr + "id='" + me.pre + "dsn6filefofc'> " + me.htmlCls.buttonStr + "reload_dsn6filefofc' style='margin: 6px 20px 0 0;'>Load DSN6</button><br><br><br>";
10993
+ html += me.htmlCls.inputFileStr + "id='" + me.pre + "dsn6filefofc'> " + me.htmlCls.buttonStr + "reload_dsn6filefofc' style='margin: 6px 20px 0 0;'>Load DSN6</button>" + me.htmlCls.buttonStr + "reload_ccp4filefofc' style='margin: 6px 20px 0 0;'>Load CCP4</button>" + me.htmlCls.buttonStr + "reload_mtzfilefofc' style='margin-top: 6px;'>Load MTZ</button><br><br><br>";
10994
10994
 
10995
10995
  html += me.htmlCls.buttonStr + "elecmapNo4'>Remove Map</button><br>";
10996
10996
 
@@ -10998,21 +10998,17 @@ class SetDialog {
10998
10998
 
10999
10999
  html += me.htmlCls.divStr + "dl_dsn6url' class='" + dialogClass + "'>";
11000
11000
  html += this.addNotebookTitle('dl_dsn6url', 'Load a selection file via a URL');
11001
- html += "<b>Note</b>: Always load a PDB file before loading DSN6 files. <br/><br/><br/>";
11002
-
11003
- html += "<span style='white-space:nowrap;font-weight:bold;'>2fofc contour at: <select id='" + me.pre + "dsn6sigmaurl2fofc'>";
11004
-
11005
- html += me.htmlCls.setHtmlCls.getOptionHtml(optArray1, 3);
11001
+ html += "<b>Note</b>: Always load a PDB file before loading map files. If you don't specify the threshold <br>below, a default one will be chosen.<br/><br/><br/>";
11006
11002
 
11007
- html += "</select> &sigma;</span><br/>";
11008
- html += "URL in the same host: " + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6fileurl2fofc' size=20>" + me.htmlCls.space3 + me.htmlCls.buttonStr + "reload_dsn6fileurl2fofc' style='margin-top: 6px;'>Load</button><br><br><br/>";
11003
+ html += "<span style='white-space:nowrap;font-weight:bold;'>2fofc contour at default threshold or at: "
11004
+ + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigmaurl2fofc' value='' size=8> &sigma;</span><br/>";
11009
11005
 
11010
- html += "<span style='white-space:nowrap;font-weight:bold;'>fofc contour at: <select id='" + me.pre + "dsn6sigmaurlfofc'>";
11006
+ html += "URL in the same host: " + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6fileurl2fofc' size=20>" + me.htmlCls.space3 + me.htmlCls.buttonStr + "reload_dsn6fileurl2fofc' style='margin: 6px 20px 0 0;'>Load DSN6</button>" + me.htmlCls.buttonStr + "reload_ccp4fileurl2fofc' style='margin: 6px 20px 0 0;'>Load CCP4</button>" + me.htmlCls.buttonStr + "reload_mtzfileurl2fofc' style='margin-top: 6px;'>Load MTZ</button><br><br><br/>";
11011
11007
 
11012
- html += me.htmlCls.setHtmlCls.getOptionHtml(optArray1, 5);
11008
+ html += "<span style='white-space:nowrap;font-weight:bold;'>fofc contour at default threshold or at: "
11009
+ + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigmaurlfofc' value='' size=8> &sigma;</span><br/>";
11013
11010
 
11014
- html += "</select> &sigma;</span><br/>";
11015
- html += "URL in the same host: " + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6fileurlfofc' size=20>" + me.htmlCls.space3 + me.htmlCls.buttonStr + "reload_dsn6fileurlfofc' style='margin-top: 6px;'>Load</button><br><br><br/>";
11011
+ html += "URL in the same host: " + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6fileurlfofc' size=20>" + me.htmlCls.space3 + me.htmlCls.buttonStr + "reload_dsn6fileurlfofc' style='margin: 6px 20px 0 0;'>Load DSN6</button>" + me.htmlCls.buttonStr + "reload_ccp4fileurlfofc' style='margin: 6px 20px 0 0;'>Load CCP4</button>" + me.htmlCls.buttonStr + "reload_mtzfileurlfofc' style='margin-top: 6px;'>Load MTZ</button><br><br><br>";
11016
11012
 
11017
11013
  html += me.htmlCls.buttonStr + "elecmapNo5'>Remove Map</button><br>";
11018
11014
 
@@ -11352,6 +11348,7 @@ class SetDialog {
11352
11348
  html += this.addNotebookTitle('dl_elecmap2fofc', 'Electron Density 2F0-Fc Map');
11353
11349
  html += "<span style='white-space:nowrap;font-weight:bold;'>Contour at: <select id='" + me.pre + "sigma2fofc'>";
11354
11350
 
11351
+ let optArray1 = ['0', '0.5', '1', '1.5', '2', '3', '4', '5', '6', '7', '8', '9', '10'];
11355
11352
  html += me.htmlCls.setHtmlCls.getOptionHtml(optArray1, 3);
11356
11353
 
11357
11354
  html += "</select> &sigma;</span> <span style='white-space:nowrap; margin-left:30px;'>" + me.htmlCls.buttonStr + "applymap2fofc'>Display</button></span> <span style='white-space:nowrap; margin-left:30px;'>" + me.htmlCls.buttonStr + "elecmapNo2'>Remove Map</button></span>";
@@ -11998,7 +11995,7 @@ class Events {
11998
11995
  }
11999
11996
  }
12000
11997
 
12001
- readFile(bAppend, files, index, dataStrAll) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
11998
+ async readFile(bAppend, files, index, dataStrAll) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
12002
11999
  let file = files[index];
12003
12000
  let commandName = (bAppend) ? 'append': 'load';
12004
12001
 
@@ -12035,7 +12032,20 @@ class Events {
12035
12032
  await ic.pdbParserCls.loadPdbData(dataStrAll, undefined, undefined, bAppend);
12036
12033
  }
12037
12034
  else {
12038
- thisClass.readFile(bAppend, files, index + 1, dataStrAll);
12035
+ await thisClass.readFile(bAppend, files, index + 1, dataStrAll);
12036
+ }
12037
+
12038
+ if(bAppend) {
12039
+ if(ic.bSetChainsAdvancedMenu) ic.definedSetsCls.showSets();
12040
+ //if(ic.bSetChainsAdvancedMenu) ic.legendTableCls.showSets();
12041
+
12042
+ ic.bResetAnno = true;
12043
+
12044
+ if(ic.bAnnoShown) {
12045
+ await ic.showAnnoCls.showAnnotations();
12046
+
12047
+ ic.annotationCls.resetAnnoTabAll();
12048
+ }
12039
12049
  }
12040
12050
  };
12041
12051
 
@@ -12070,13 +12080,7 @@ class Events {
12070
12080
 
12071
12081
  ic.dataStrAll = '';
12072
12082
 
12073
- this.readFile(bAppend, files, 0, '');
12074
-
12075
- if(bAppend) {
12076
- if(ic.bSetChainsAdvancedMenu) ic.definedSetsCls.showSets();
12077
- //if(ic.bSetChainsAdvancedMenu) ic.legendTableCls.showSets();
12078
- if(ic.bAnnoShown) await ic.showAnnoCls.showAnnotations();
12079
- }
12083
+ await this.readFile(bAppend, files, 0, '');
12080
12084
  }
12081
12085
  }
12082
12086
 
@@ -12160,7 +12164,10 @@ class Events {
12160
12164
 
12161
12165
  if(bStructures) {
12162
12166
  if(ic.bSetChainsAdvancedMenu) ic.definedSetsCls.showSets();
12163
- if(ic.bAnnoShown) await ic.showAnnoCls.showAnnotations();
12167
+ if(ic.bAnnoShown) {
12168
+ await ic.showAnnoCls.showAnnotations();
12169
+ ic.annotationCls.resetAnnoTabAll();
12170
+ }
12164
12171
  }
12165
12172
  }
12166
12173
  }
@@ -13170,15 +13177,37 @@ class Events {
13170
13177
 
13171
13178
  me.myEventCls.onIds("#" + me.pre + "reload_dsn6file2fofc", "click", function(e) { let ic = me.icn3d;
13172
13179
  e.preventDefault();
13173
- if(!me.cfg.notebook) dialog.dialog( "close" );
13180
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
13174
13181
  ic.dsn6ParserCls.loadDsn6File('2fofc');
13175
13182
  });
13176
13183
  me.myEventCls.onIds("#" + me.pre + "reload_dsn6filefofc", "click", function(e) { let ic = me.icn3d;
13177
13184
  e.preventDefault();
13178
- if(!me.cfg.notebook) dialog.dialog( "close" );
13185
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
13179
13186
  ic.dsn6ParserCls.loadDsn6File('fofc');
13180
13187
  });
13181
13188
 
13189
+ me.myEventCls.onIds("#" + me.pre + "reload_ccp4file2fofc", "click", function(e) { let ic = me.icn3d;
13190
+ e.preventDefault();
13191
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
13192
+ ic.ccp4ParserCls.loadCcp4File('2fofc');
13193
+ });
13194
+ me.myEventCls.onIds("#" + me.pre + "reload_ccp4filefofc", "click", function(e) { let ic = me.icn3d;
13195
+ e.preventDefault();
13196
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
13197
+ ic.ccp4ParserCls.loadCcp4File('fofc');
13198
+ });
13199
+
13200
+ me.myEventCls.onIds("#" + me.pre + "reload_mtzfile2fofc", "click", function(e) { let ic = me.icn3d;
13201
+ e.preventDefault();
13202
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
13203
+ ic.mtzParserCls.loadMtzFile('2fofc');
13204
+ });
13205
+ me.myEventCls.onIds("#" + me.pre + "reload_mtzfilefofc", "click", function(e) { let ic = me.icn3d;
13206
+ e.preventDefault();
13207
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
13208
+ ic.mtzParserCls.loadMtzFile('fofc');
13209
+ });
13210
+
13182
13211
  me.myEventCls.onIds("#" + me.pre + "reload_delphifile", "click", async function(e) { let ic = me.icn3d;
13183
13212
  e.preventDefault();
13184
13213
  if(!me.cfg.notebook) dialog.dialog( "close" );
@@ -13268,15 +13297,37 @@ class Events {
13268
13297
 
13269
13298
  me.myEventCls.onIds("#" + me.pre + "reload_dsn6fileurl2fofc", "click", function(e) { let ic = me.icn3d;
13270
13299
  e.preventDefault();
13271
- if(!me.cfg.notebook) dialog.dialog( "close" );
13300
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
13272
13301
  ic.dsn6ParserCls.loadDsn6FileUrl('2fofc');
13273
13302
  });
13274
13303
  me.myEventCls.onIds("#" + me.pre + "reload_dsn6fileurlfofc", "click", function(e) { let ic = me.icn3d;
13275
13304
  e.preventDefault();
13276
- if(!me.cfg.notebook) dialog.dialog( "close" );
13305
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
13277
13306
  ic.dsn6ParserCls.loadDsn6FileUrl('fofc');
13278
13307
  });
13279
13308
 
13309
+ me.myEventCls.onIds("#" + me.pre + "reload_ccp4fileurl2fofc", "click", function(e) { let ic = me.icn3d;
13310
+ e.preventDefault();
13311
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
13312
+ ic.ccp4ParserCls.loadCcp4FileUrl('2fofc');
13313
+ });
13314
+ me.myEventCls.onIds("#" + me.pre + "reload_ccp4fileurlfofc", "click", function(e) { let ic = me.icn3d;
13315
+ e.preventDefault();
13316
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
13317
+ ic.ccp4ParserCls.loadCcp4FileUrl('fofc');
13318
+ });
13319
+
13320
+ me.myEventCls.onIds("#" + me.pre + "reload_mtzfileurl2fofc", "click", function(e) { let ic = me.icn3d;
13321
+ e.preventDefault();
13322
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
13323
+ ic.mtzParserCls.loadMtzFileUrl('2fofc');
13324
+ });
13325
+ me.myEventCls.onIds("#" + me.pre + "reload_mtzfileurlfofc", "click", function(e) { let ic = me.icn3d;
13326
+ e.preventDefault();
13327
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
13328
+ ic.mtzParserCls.loadMtzFileUrl('fofc');
13329
+ });
13330
+
13280
13331
  me.myEventCls.onIds("#" + me.pre + "reload_pdbfile", "click", async function(e) { me.icn3d;
13281
13332
  e.preventDefault();
13282
13333
 
@@ -14664,7 +14715,7 @@ class AlignSeq {
14664
14715
  // for(let i in ic.alnChains) {
14665
14716
  for (let m = 0, ml = alignChainArray.length; m < ml; ++m) {
14666
14717
  let i = alignChainArray[m];
14667
-
14718
+
14668
14719
  if (index == 0) firstChainid = i;
14669
14720
 
14670
14721
  if (bOnechain && index > 0) {
@@ -28439,8 +28490,8 @@ class ElectronMap {
28439
28490
  this.pLength = 0;
28440
28491
  this.cutRadius = 0;
28441
28492
  this.vpBits = null; // uint8 array of bitmasks
28442
- this.vpDistance = null; // floatarray of _squared_ distances
28443
- this.vpAtomID = null; // intarray
28493
+ this.vpGridTrans = null; // array of translated number of grids
28494
+ this.vpAtomID = null; // uint8 array
28444
28495
  this.vertnumber = 0;
28445
28496
  this.facenumber = 0;
28446
28497
  this.pminx = 0;
@@ -28490,12 +28541,27 @@ ElectronMap.prototype.getFacesAndVertices = function(allatoms, atomlist) {
28490
28541
  atomsToShow[atomlist[i]] = 1;
28491
28542
  let vertices = this.verts;
28492
28543
 
28544
+ let vertTrans = {};
28493
28545
  for(i = 0, il = vertices.length; i < il; i++) {
28494
28546
  let r;
28495
28547
  if(this.type == 'phi') {
28496
28548
  r = new THREE.Vector3(vertices[i].x, vertices[i].y, vertices[i].z).multiplyScalar(1.0/this.header.scale).applyMatrix4(this.matrix);
28497
28549
  }
28498
28550
  else {
28551
+ // ccp4 has no translation vector. Only translated vertices are used.
28552
+ if(this.header.ccp4) {
28553
+ let index = vertices[i].index;
28554
+ let finalIndex;
28555
+ if(this.vpGridTrans[index]) {
28556
+ finalIndex = index;
28557
+
28558
+ vertices[i].x += this.vpGridTrans[finalIndex][0] * this.header.xExtent * this.scaleFactor;
28559
+ vertices[i].y += this.vpGridTrans[finalIndex][1] * this.header.xExtent * this.scaleFactor;
28560
+ vertices[i].z += this.vpGridTrans[finalIndex][2] * this.header.xExtent * this.scaleFactor;
28561
+
28562
+ vertTrans[finalIndex] = 1;
28563
+ }
28564
+ }
28499
28565
  r = new THREE.Vector3(vertices[i].x, vertices[i].y, vertices[i].z).applyMatrix4(this.matrix);
28500
28566
  }
28501
28567
  // vertices[i].x = r.x / this.scaleFactor - this.ptranx;
@@ -28514,13 +28580,22 @@ ElectronMap.prototype.getFacesAndVertices = function(allatoms, atomlist) {
28514
28580
  let fa = this.faces[i], fb = this.faces[i+1], fc = this.faces[i+2];
28515
28581
 
28516
28582
  if(fa !== fb && fb !== fc && fa !== fc){
28517
- finalfaces.push({"a":fa, "b":fb, "c":fc});
28583
+ if(this.header.ccp4) {
28584
+ // only transfered vertices will be used
28585
+ if(vertTrans.hasOwnProperty(vertices[fa].index) && vertTrans.hasOwnProperty(vertices[fb].index)
28586
+ && vertTrans.hasOwnProperty(vertices[fc].index)) {
28587
+ finalfaces.push({"a":fa, "b":fb, "c":fc});
28588
+ }
28589
+ }
28590
+ else {
28591
+ finalfaces.push({"a":fa, "b":fb, "c":fc});
28592
+ }
28518
28593
  }
28519
28594
  }
28520
28595
 
28521
28596
  //try to help the garbage collector
28522
28597
  this.vpBits = null; // uint8 array of bitmasks
28523
- this.vpDistance = null; // floatarray
28598
+ this.vpGridTrans = null; // uint8 array
28524
28599
  this.vpAtomID = null; // intarray
28525
28600
 
28526
28601
  return {
@@ -28579,6 +28654,8 @@ ElectronMap.prototype.initparm = function(inHeader, inData, inMatrix, inIsovalue
28579
28654
  this.cutRadius = this.probeRadius * this.scaleFactor;
28580
28655
 
28581
28656
  this.vpBits = new Uint8Array(this.pLength * this.pWidth * this.pHeight);
28657
+ if(this.header.ccp4) this.vpGridTrans = new Array(this.pLength * this.pWidth * this.pHeight);
28658
+
28582
28659
  this.vpAtomID = new Uint8Array(this.pLength * this.pWidth * this.pHeight);
28583
28660
  };
28584
28661
 
@@ -28604,7 +28681,6 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
28604
28681
  let i, j, k, il, jl, kl;
28605
28682
  for(i = 0, il = this.vpBits.length; i < il; i++) {
28606
28683
  this.vpBits[i] = 0;
28607
- //this.vpDistance[i] = -1.0;
28608
28684
  this.vpAtomID[i] = 0;
28609
28685
  }
28610
28686
 
@@ -28766,6 +28842,7 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
28766
28842
  }
28767
28843
  }
28768
28844
  else {
28845
+ // let index2ori = {};
28769
28846
  for(let serial in atomlist) {
28770
28847
  let atom = atoms[atomlist[serial]];
28771
28848
 
@@ -28796,6 +28873,7 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
28796
28873
 
28797
28874
  for(i = 0, il = indexArray.length; i < il; ++i) {
28798
28875
  let index = indexArray[i];
28876
+
28799
28877
  if(this.type == '2fofc') {
28800
28878
  this.vpBits[index] =(this.dataArray[index] >= this.isovalue) ? 1 : 0;
28801
28879
  //this.vpAtomID[index] =(this.dataArray[index] >= 0) ? 1 : 0; // determine whether it's positive
@@ -28809,6 +28887,7 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
28809
28887
  //this.vpAtomID[index] =(this.dataArray[index] >= 0) ? 1 : 0; // determine whether it's positive
28810
28888
  }
28811
28889
  }
28890
+
28812
28891
  }
28813
28892
  }
28814
28893
 
@@ -29032,7 +29111,18 @@ class Surface {
29032
29111
  cfg.isovalue = ic.mapData.sigma2;
29033
29112
  cfg.type = '2fofc';
29034
29113
 
29035
- ps = this.SetupMap(cfg);
29114
+ //ccp4
29115
+ cfg.ccp4 = ic.mapData.ccp4;
29116
+ cfg.grid = ic.mapData.grid2;
29117
+ cfg.unit_cell = ic.mapData.unit_cell2;
29118
+
29119
+ if(cfg.header || cfg.ccp4) ps = this.SetupMap(cfg);
29120
+ else return;
29121
+
29122
+ if(cfg.ccp4) {
29123
+ ic.mapData = {};
29124
+ return;
29125
+ }
29036
29126
  }
29037
29127
  else if(type == 12) { // fofc
29038
29128
  cfg.header = ic.mapData.header;
@@ -29041,7 +29131,18 @@ class Surface {
29041
29131
  cfg.isovalue = ic.mapData.sigma;
29042
29132
  cfg.type = 'fofc';
29043
29133
 
29044
- ps = this.SetupMap(cfg);
29134
+ //ccp4
29135
+ cfg.ccp4 = ic.mapData.ccp4;
29136
+ cfg.grid = ic.mapData.grid;
29137
+ cfg.unit_cell = ic.mapData.unit_cell;
29138
+
29139
+ if(cfg.header || cfg.ccp4) ps = this.SetupMap(cfg);
29140
+ else return;
29141
+
29142
+ if(cfg.ccp4) {
29143
+ ic.mapData = {};
29144
+ return;
29145
+ }
29045
29146
  }
29046
29147
  else if(type == 13) { // em
29047
29148
  cfg.maxdist = 3; // EM map has no unit cell. It could include more gird space.
@@ -29529,29 +29630,60 @@ class Surface {
29529
29630
  }
29530
29631
 
29531
29632
  SetupMap(data) { let ic = this.icn3d; ic.icn3dui;
29532
- let ps = new ElectronMap(ic);
29533
-
29534
- ps.initparm(data.header, data.data, data.matrix, data.isovalue, data.center, data.maxdist,
29535
- data.pmin, data.pmax, data.water, data.type, data.rmsd_supr, data.loadPhiFrom, data.icn3d);
29633
+ if(data.ccp4) {
29634
+ let radius = 10;
29635
+ let center = (ic.center) ? [ic.center.x, ic.center.y, ic.center.z] : [0,0,0];
29636
+
29637
+ let typeDetail;
29638
+ if(data.type == '2fofc') {
29639
+ typeDetail = '2fofc';
29640
+ let result = ic.ccp4ParserCls.extract_block(data.grid, data.unit_cell, radius, center, typeDetail);
29641
+ let iso = ic.ccp4ParserCls.marchingCubes(result.size, result.values, result.points, data.isovalue, 'marching cubes');
29642
+ ic.ccp4ParserCls.makeChickenWire(iso, typeDetail);
29643
+
29644
+ result = null;
29645
+ iso = null;
29646
+ }
29647
+ else if(data.type == 'fofc') {
29648
+ typeDetail = 'fofc_neg';
29649
+ let result = ic.ccp4ParserCls.extract_block(data.grid, data.unit_cell, radius, center, typeDetail);
29650
+ let iso = ic.ccp4ParserCls.marchingCubes(result.size, result.values, result.points, data.isovalue, 'marching cubes');
29651
+ ic.ccp4ParserCls.makeChickenWire(iso, typeDetail);
29652
+
29653
+ typeDetail = 'fofc_pos';
29654
+ result = ic.ccp4ParserCls.extract_block(data.grid, data.unit_cell, radius, center, typeDetail);
29655
+ iso = ic.ccp4ParserCls.marchingCubes(result.size, result.values, result.points, data.isovalue, 'marching cubes');
29656
+ ic.ccp4ParserCls.makeChickenWire(iso, typeDetail);
29536
29657
 
29537
- ps.fillvoxels(data.allatoms, data.extendedAtoms);
29658
+ result = null;
29659
+ iso = null;
29660
+ }
29661
+ }
29662
+ else {
29663
+ let ps = new ElectronMap(ic);
29664
+
29665
+ ps.initparm(data.header, data.data, data.matrix, data.isovalue, data.center, data.maxdist,
29666
+ data.pmin, data.pmax, data.water, data.type, data.rmsd_supr, data.loadPhiFrom, data.icn3d);
29538
29667
 
29539
- if(!data.header.bSurface) ps.buildboundary();
29668
+ ps.fillvoxels(data.allatoms, data.extendedAtoms);
29540
29669
 
29541
- if(!data.header.bSurface) ps.marchingcube();
29542
-
29543
- ps.vpBits = null; // uint8 array of bitmasks
29544
- //ps.vpDistance = null; // floatarray of _squared_ distances
29545
- ps.vpAtomID = null; // intarray
29670
+ if(!data.header.bSurface) ps.buildboundary();
29546
29671
 
29547
- let result;
29672
+ if(!data.header.bSurface) ps.marchingcube();
29673
+
29674
+ ps.vpBits = null; // uint8 array of bitmasks
29675
+ //ps.vpDistance = null; // floatarray of _squared_ distances
29676
+ ps.vpAtomID = null; // intarray
29548
29677
 
29549
- if(!data.header.bSurface) result = ps.getFacesAndVertices(data.allatoms, data.atomsToShow);
29678
+ let result;
29550
29679
 
29551
- ps.faces = null;
29552
- ps.verts = null;
29680
+ if(!data.header.bSurface) result = ps.getFacesAndVertices(data.allatoms, data.atomsToShow);
29553
29681
 
29554
- return result;
29682
+ ps.faces = null;
29683
+ ps.verts = null;
29684
+
29685
+ return result;
29686
+ }
29555
29687
  }
29556
29688
  }
29557
29689
 
@@ -35038,7 +35170,7 @@ class SetColor {
35038
35170
 
35039
35171
  for(let resid in residueHash) {
35040
35172
  if(!ic.resid2refnum[resid]) {
35041
- color = me.parasCls.thr('#FFFFFF');
35173
+ color = me.parasCls.thr('#00FFFF'); //('#FFFFFF');
35042
35174
  }
35043
35175
  else {
35044
35176
  let refnumLabel = ic.resid2refnum[resid];
@@ -35073,7 +35205,7 @@ class SetColor {
35073
35205
  let residueHash = ic.firstAtomObjCls.getResiduesFromAtoms(atoms);
35074
35206
  for(let resid in residueHash) {
35075
35207
  if(!ic.resid2refnum[resid]) {
35076
- color = me.parasCls.thr('#FFFFFF');
35208
+ color = me.parasCls.thr('#00FFFF'); //('#FFFFFF');
35077
35209
  }
35078
35210
  else {
35079
35211
  let refnumLabel = ic.resid2refnum[resid];
@@ -36043,15 +36175,13 @@ class SetOption {
36043
36175
  const name2color = {
36044
36176
  //"A- Strand": "FF00FF",
36045
36177
  "A Strand": "9400D3", //"663399",
36046
- //"A+ Strand": "9400D3", //"663399",
36047
- "A' Strand": "9400D3", //"663399",
36048
36178
  "B Strand": "ba55d3",
36049
36179
  "C Strand": "0000FF",
36050
36180
  "C' Strand": "6495ED",
36051
36181
  "C'' Strand": "006400",
36052
36182
  "D Strand": "00FF00",
36053
- "E Strand": "F7DC6F", //"FFFF00", //"F0E68C",
36054
- "F Strand": "FFA500",
36183
+ "E Strand": "FFD700", //"FFFF00", //"F0E68C",
36184
+ "F Strand": "FF8C00",
36055
36185
  "G Strand": "FF0000",
36056
36186
  //"G+ Strand": "8B0000",
36057
36187
  "Loop": "CCCCCC"
@@ -36078,15 +36208,15 @@ class SetOption {
36078
36208
  "<b>Protodomain 1</b>": "",
36079
36209
  "A Strand": "0000FF",
36080
36210
  "B Strand": "006400",
36081
- "C Strand": "F7DC6F", //"FFFF00", //"F0E68C",
36082
- "C' Strand": "FFA500",
36211
+ "C Strand": "FFD700", //"FFFF00", //"F0E68C",
36212
+ "C' Strand": "FF8C00",
36083
36213
  "<br><b>Linker</b>": "",
36084
36214
  "C'' Strand": "FF0000",
36085
36215
  "<br><b>Protodomain 2</b>": "",
36086
36216
  "D Strand": "0000FF",
36087
36217
  "E Strand": "006400",
36088
- "F Strand": "F7DC6F", //"FFFF00", //"F0E68C",
36089
- "G Strand": "FFA500",
36218
+ "F Strand": "FFD700", //"FFFF00", //"F0E68C",
36219
+ "G Strand": "FF8C00",
36090
36220
  "": "",
36091
36221
  "Loop": "CCCCCC"
36092
36222
  };
@@ -37288,14 +37418,14 @@ class AnnoDomain {
37288
37418
  let pdbid = pdbArray[index];
37289
37419
  //let url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&domain&molinfor&uid=" + pdbid;
37290
37420
 
37291
- if(index == 0 && ic.mmdb_data !== undefined) {
37421
+ if(!ic.bResetAnno && index == 0 && ic.mmdb_data !== undefined) {
37292
37422
  for(let chnid in ic.protein_chainid) {
37293
37423
  if(chnid.indexOf(pdbid) !== -1) {
37294
37424
  this.showDomainWithData(chnid, ic.mmdb_data);
37295
37425
  }
37296
37426
  }
37297
37427
  }
37298
- else if(ic.mmdb_dataArray[index] !== undefined) {
37428
+ else if(!ic.bResetAnno && ic.mmdb_dataArray[index] !== undefined) {
37299
37429
  for(let chnid in ic.protein_chainid) {
37300
37430
  if(chnid.indexOf(pdbid) !== -1) {
37301
37431
  this.showDomainWithData(chnid, ic.mmdb_dataArray[index]);
@@ -37370,6 +37500,10 @@ class AnnoDomain {
37370
37500
  let domainArray, proteinname;
37371
37501
  let pos = chnid.indexOf('_');
37372
37502
  let chain = chnid.substr(pos + 1);
37503
+ // MMDB symmetry chain has the form of 'A1'
37504
+ if(chain.length > 1 && chain.substr(chain.length - 1) == '1') {
37505
+ chain = chain.substr(0, chain.length - 1);
37506
+ }
37373
37507
 
37374
37508
  if(bCalcDirect) {
37375
37509
  proteinname = chnid;
@@ -38375,7 +38509,11 @@ class Domain3d {
38375
38509
  //this.dcut = 8; // threshold for C-alpha interactions
38376
38510
 
38377
38511
  // It seemed the threshold 7 angstrom works better
38378
- this.dcut = 7; // threshold for C-alpha interactions
38512
+ //this.dcut = 7; // threshold for C-alpha interactions
38513
+ this.dcut = 8; // threshold for C-alpha interactions
38514
+
38515
+ // added by Jiyao
38516
+ this.min_contacts = 5; //3; // minimum number of contacts to be considered as neighbors
38379
38517
 
38380
38518
  this.MAX_SSE = 512;
38381
38519
 
@@ -38409,9 +38547,6 @@ class Domain3d {
38409
38547
  this.c_delta = 3; // cut set parameter
38410
38548
  this.nc_fact = 0.0; // size factor for internal contacts
38411
38549
 
38412
- // added by Jiyao
38413
- this.min_contacts = 3; // minimum number of contacts to be considered as neighbors
38414
-
38415
38550
  //let this.elements[2*this.MAX_SSE]; // sets of this.elements to be split
38416
38551
  this.elements = [];
38417
38552
  this.elements.length = 2*this.MAX_SSE;
@@ -41989,6 +42124,10 @@ class ShowAnno {
41989
42124
  chainLetter = chainLetter.substr(0, chainLetter.indexOf('_'));
41990
42125
  chainidBase = chainArray[i].substr(0, chainArray[i].indexOf('_')) + '_' + chainLetter;
41991
42126
  }
42127
+ else if(chainLetter.length > 1 && chainLetter.substr(chainLetter.length - 1) == '1') { // NCBI modified chainid, e.g., A1
42128
+ chainLetter = chainLetter.substr(0, chainLetter.length - 1);
42129
+ chainidBase = chainArray[i].substr(0, chainArray[i].indexOf('_')) + '_' + chainLetter;
42130
+ }
41992
42131
  else {
41993
42132
  chainidBase = chainArray[i];
41994
42133
  }
@@ -43189,7 +43328,7 @@ class ShowSeq {
43189
43328
  html += '</div>';
43190
43329
  html3 += '</div></div>';
43191
43330
  }
43192
-
43331
+
43193
43332
  if(ic.bShowRefnum && ic.chainid2refpdbname.hasOwnProperty(chnid) && ic.chainid2refpdbname[chnid].length > 0) {
43194
43333
  let result = this.showAllRefNum(giSeq, chnid);
43195
43334
 
@@ -43258,9 +43397,13 @@ class ShowSeq {
43258
43397
 
43259
43398
  if(!ic.chainid2refpdbname[chnid]) return {html: html, html3: html3};
43260
43399
 
43261
- let chainList = ic.refnumCls.getTemplateList(chnid);
43400
+ let result = ic.refnumCls.getTemplateList(chnid);
43401
+ let refpdbnameList = result.refpdbnameList;
43402
+ let scoreList = result.scoreList;
43403
+ let seqidList = result.seqidList;
43404
+ let nresAlignList = result.nresAlignList;
43262
43405
 
43263
- let refStruTitle = (chainList) ? "based on " + chainList : "";
43406
+ let refStruTitle = (refpdbnameList) ? "based on " + refpdbnameList + ". The TM-score(s) is(are) " + scoreList + ". The sequence identitie(s) is(are) " + seqidList + ". The number of aligned residue(s) is(are) " + nresAlignList + "." : "";
43264
43407
 
43265
43408
  let htmlTmp = '<div class="icn3d-dl_sequence">';
43266
43409
  htmlTmp += '<div class="icn3d-residueLine" style="white-space:nowrap;">';
@@ -43316,7 +43459,8 @@ class ShowSeq {
43316
43459
 
43317
43460
  // auto-generate ref numbers for loops
43318
43461
  let bLoop = false, currStrand = '', prevStrand = '';
43319
- let refnumLabel, refnumStr_ori, refnumStr, postfix, strandPostfix, refnum, refnum3c;
43462
+ let refnumLabel, refnumStr_ori, refnumStr, postfix, strandPostfix, refnum, refnum3c, refnum2c;
43463
+ let bExtendedStrand = false, bSecThird9 = false;
43320
43464
 
43321
43465
  // sometimes one chain may have several Ig domains,set an index for each IgDomain
43322
43466
  let index = 1, bStart = false;
@@ -43342,8 +43486,8 @@ class ShowSeq {
43342
43486
 
43343
43487
  refnumLabel = ic.resid2refnum[residueid];
43344
43488
 
43345
- let firstChar = (refnumLabel) ? refnumLabel.substr(0,1) : ' ';
43346
- if(!bStart && refnumLabel && (firstChar == ' ' || firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
43489
+ let firstChar = (refnumLabel) ? refnumLabel.substr(0,1) : '';
43490
+ if(!bStart && refnumLabel && (firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
43347
43491
  bStart = true;
43348
43492
  resCnt = 1; // the first oen is included
43349
43493
  }
@@ -43360,14 +43504,21 @@ class ShowSeq {
43360
43504
  refnumStr = refnumStr_ori;
43361
43505
  refnum = parseInt(refnumStr);
43362
43506
  refnum3c = (refnum - parseInt(refnum/1000) * 1000).toString();
43507
+ refnum2c = (refnum - parseInt(refnum/100) * 100).toString();
43508
+
43509
+ // for extended strands, since A is 1550 and A+ is 1650, then the AA+ loop will be 1591, 1592, ... 1610, 1611, etc
43510
+ bSecThird9 = refnum3c.substr(0,1) == '9' || refnum2c.substr(0,1) == '9' || refnum2c.substr(0,1) == '0' || refnum2c.substr(0,1) == '1';
43511
+ if(bSecThird9) ic.residIgLoop[residueid] = 1;
43512
+
43363
43513
  strandPostfix = refnumStr.replace(refnum.toString(), '');
43364
43514
 
43365
43515
  postfix = strandPostfix + '_' + index;
43366
43516
 
43367
- let firstTwo = parseInt(refnum.toString().substr(0, 2)); // A- strand
43517
+ let firstTwo = parseInt(refnum.toString().substr(0, 2)); // check extended strands
43518
+ bExtendedStrand = refnum3c.substr(0,1) != '5' && firstTwo != '18'; // all strands and A' (18##)
43368
43519
 
43369
43520
  if(currStrand && currStrand != ' ') {
43370
- if(refnum3c.substr(0,1) != '9' || firstTwo == 10) {
43521
+ if(!bSecThird9 || (bExtendedStrand && !bSecThird9)) {
43371
43522
  let lastTwo = parseInt(refnum.toString().substr(refnum.toString().length - 2, 2));
43372
43523
 
43373
43524
  if(currStrand != prevStrand) { // reset currCnt
@@ -43394,7 +43545,7 @@ class ShowSeq {
43394
43545
  resCntAtAnchor = 0;
43395
43546
  }
43396
43547
 
43397
- if(firstTwo == 10) {
43548
+ if(bExtendedStrand) {
43398
43549
  strandArray[strandCnt].anchorRefnum = 0;
43399
43550
  }
43400
43551
 
@@ -43420,7 +43571,7 @@ class ShowSeq {
43420
43571
  resCntAtAnchor = 0;
43421
43572
  }
43422
43573
 
43423
- if(firstTwo == 10) {
43574
+ if(bExtendedStrand) {
43424
43575
  strandArray[strandCnt - 1].anchorRefnum = 0;
43425
43576
  }
43426
43577
 
@@ -43476,7 +43627,7 @@ class ShowSeq {
43476
43627
  currStrand = refnumLabel.replace(new RegExp(refnumStr,'g'), '');
43477
43628
 
43478
43629
  let firstChar = refnumLabel.substr(0,1);
43479
- if(!bStart && (firstChar == ' ' || firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
43630
+ if(!bStart && (firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
43480
43631
  bStart = true;
43481
43632
  bBeforeAstrand = true;
43482
43633
  loopCnt = 0;
@@ -43749,6 +43900,11 @@ class ShowSeq {
43749
43900
 
43750
43901
  getRefnumHtml(residueid, refnumStr, refnumStr_ori, refnumLabel, currStrand, bLoop, bHidelabel) { let ic = this.icn3d, me = ic.icn3dui;
43751
43902
  let refnum = parseInt(refnumStr).toString();
43903
+
43904
+ let refnum3c = (refnum - parseInt(refnum/1000) * 1000).toString();
43905
+ let firstTwo = parseInt(refnum.toString().substr(0, 2)); // check extended strands
43906
+ let bExtendedStrand = refnum3c.substr(0,1) != '5' && firstTwo != '18'; // all strands and A' (18##)
43907
+
43752
43908
  let color = this.getRefnumColor(currStrand, true);
43753
43909
  let colorStr = (!bLoop) ? 'style="color:' + color + '; text-decoration: underline overline;"' : 'style="color:' + color + '"';
43754
43910
 
@@ -43758,13 +43914,13 @@ class ShowSeq {
43758
43914
 
43759
43915
  let html = '';
43760
43916
 
43761
- if(refnumLabel && (lastTwo == 50 || refnum == 1094) && !bLoop) {
43917
+ if(refnumLabel && lastTwo == 50 && !bExtendedStrand && !bLoop) {
43762
43918
  // highlight the anchor residues
43763
43919
  ic.hAtomsRefnum = me.hashUtilsCls.unionHash(ic.hAtomsRefnum, ic.residues[residueid]);
43764
43920
 
43765
43921
  html += '<span ' + colorStr + ' title="' + refnumLabel + '"><b>' + refnumLabel.substr(0, 1) + '</b>' + refnumLabel.substr(1) + '</span>';
43766
43922
  }
43767
- else if(refnumLabel && lastTwo % 2 == 0 && lastTwo != 52 && refnum != 1096 && !bHidelabel) { // don't show label for the first, middle, and last loop residues
43923
+ else if(refnumLabel && lastTwo % 2 == 0 && lastTwo != 52 && !bHidelabel) { // don't show label for the first, middle, and last loop residues
43768
43924
  // e.g., 2152a
43769
43925
  lastTwoStr = isNaN(refnumStr) ? lastTwoStr + refnumStr.substr(refnumStr.length - 1, 1) : lastTwoStr;
43770
43926
  html += '<span ' + colorStr + ' title="' + refnumLabel + '">' + lastTwoStr + '</span>';
@@ -43777,23 +43933,9 @@ class ShowSeq {
43777
43933
  }
43778
43934
 
43779
43935
  getRefnumColor(currStrand, bText) { let ic = this.icn3d, me = ic.icn3dui;
43780
- if(currStrand == "A-") {
43781
- return '#9400D3'; //'#663399';
43782
- }
43783
- else if(currStrand == "A") {
43784
- return '#9400D3'; //'#663399';
43785
- }
43786
- //else if(currStrand == "A*") {
43787
- else if(currStrand == "A+") {
43788
- return '#9400D3'; //'#663399';
43789
- }
43790
- else if(currStrand == "A'") {
43791
- return '#9400D3'; //'#663399';
43792
- }
43793
- else if(currStrand == "B") {
43794
- return '#ba55d3';
43795
- }
43796
- else if(currStrand == "C") {
43936
+ let strand = (currStrand) ? currStrand.substr(0,1) : '';
43937
+
43938
+ if(currStrand == "C") {
43797
43939
  return '#0000FF';
43798
43940
  }
43799
43941
  else if(currStrand == "C'") {
@@ -43802,39 +43944,44 @@ class ShowSeq {
43802
43944
  else if(currStrand == "C''") {
43803
43945
  return '#006400';
43804
43946
  }
43805
- else if(currStrand == "D") {
43947
+
43948
+ else if(strand == "A") {
43949
+ return '#9400D3'; //'#663399';
43950
+ }
43951
+ else if(strand == "B") {
43952
+ return '#ba55d3';
43953
+ }
43954
+ else if(strand == "D") {
43806
43955
  return '#00FF00';
43807
43956
  }
43808
- else if(currStrand == "E") {
43809
- //return (bText) ? "#F7DC6F" : "#FFFF00";
43810
- return "#F7DC6F";
43957
+ else if(strand == "E") {
43958
+ return "#FFD700";
43811
43959
  }
43812
- else if(currStrand == "F") {
43813
- return '#FFA500';
43960
+ else if(strand == "F") {
43961
+ return '#FF8C00';
43814
43962
  }
43815
- else if(currStrand == "G") {
43963
+ else if(strand == "G") {
43816
43964
  return '#FF0000';
43817
43965
  }
43818
- else if(currStrand == "G+") {
43819
- return '#8B0000';
43820
- }
43821
43966
  else {
43822
43967
  return me.htmlCls.GREYB;
43823
43968
  }
43824
43969
  }
43825
43970
 
43826
43971
  getProtodomainColor(currStrand) { let ic = this.icn3d, me = ic.icn3dui;
43827
- if((currStrand && currStrand.substr(0,1) == "A") || currStrand == "D") {
43972
+ let strand = (currStrand) ? currStrand.substr(0,1) : '';
43973
+
43974
+ if(strand == "A" || strand == "D") {
43828
43975
  return '#0000FF';
43829
43976
  }
43830
- else if(currStrand == "B" || currStrand == "E") {
43977
+ else if(strand == "B" || strand == "E") {
43831
43978
  return '#006400';
43832
43979
  }
43833
- else if(currStrand == "C" || currStrand == "F") {
43834
- return "#F7DC6F"; //"#FFFF00"; //'#F0E68C';
43980
+ else if(currStrand == "C" || strand == "F") {
43981
+ return "#FFD700"; //"#FFFF00"; //'#F0E68C';
43835
43982
  }
43836
- else if(currStrand == "C'" || (currStrand && currStrand.substr(0, 1) == "G")) {
43837
- return '#FFA500';
43983
+ else if(currStrand == "C'" || strand == "G") {
43984
+ return '#FF8C00';
43838
43985
  }
43839
43986
  else if(currStrand == "C''") { //linker
43840
43987
  return '#FF0000';
@@ -44537,8 +44684,8 @@ class HlUpdate {
44537
44684
  updateHlObjects(bForceHighlight) { let ic = this.icn3d; ic.icn3dui;
44538
44685
  ic.hlObjectsCls.removeHlObjects();
44539
44686
 
44540
- if((ic.hAtoms && ic.atoms && Object.keys(ic.hAtoms).length < Object.keys(ic.atoms).length) || bForceHighlight) {
44541
- ic.hlObjectsCls.addHlObjects();
44687
+ if((ic.hAtoms && ic.atoms && Object.keys(ic.hAtoms).length < Object.keys(ic.dAtoms).length) || bForceHighlight) {
44688
+ if(ic.bShowHighlight === undefined || ic.bShowHighlight) ic.hlObjectsCls.addHlObjects();
44542
44689
  ic.definedSetsCls.setMode('selection');
44543
44690
  }
44544
44691
  }
@@ -45618,8 +45765,11 @@ class LineGraph {
45618
45765
 
45619
45766
  // try {
45620
45767
  if(!template) {
45621
- let allPromise = Promise.allSettled(pdbAjaxArray);
45622
- ic.pdbDataArray = await allPromise;
45768
+ //let allPromise = Promise.allSettled(pdbAjaxArray);
45769
+ //ic.pdbDataArray = await allPromise;
45770
+
45771
+ ic.pdbDataArray = await this.promiseWithFixedJobs(pdbAjaxArray);
45772
+
45623
45773
  await thisClass.parseRefPdbData(ic.pdbDataArray, template);
45624
45774
  }
45625
45775
  else {
@@ -45730,6 +45880,7 @@ class LineGraph {
45730
45880
  }
45731
45881
 
45732
45882
  if(!ic.domainid2refpdbname) ic.domainid2refpdbname = {};
45883
+ if(!ic.domainid2score) ic.domainid2score = {};
45733
45884
 
45734
45885
  for(let k = 0, kl = domainAtomsArray.length; k < kl; ++k) {
45735
45886
  let pdb_target = ic.saveFileCls.getAtomPDB(domainAtomsArray[k], undefined, undefined, undefined, undefined, struct);
@@ -45741,7 +45892,7 @@ class LineGraph {
45741
45892
  let atomLast = ic.firstAtomObjCls.getLastAtomObj(domainAtomsArray[k]);
45742
45893
  let resiSum = atomFirst.resi + ':' + atomLast.resi;
45743
45894
  //let domainid = chainid + '-' + k + '_' + Object.keys(domainAtomsArray[k]).length;
45744
- let domainid = chainid + '-' + k + '_' + resiSum;
45895
+ let domainid = chainid + ',' + k + '_' + resiSum;
45745
45896
  ic.domainid2pdb[domainid] = pdb_target;
45746
45897
 
45747
45898
  if(!template) {
@@ -45771,30 +45922,14 @@ class LineGraph {
45771
45922
  }
45772
45923
  }
45773
45924
 
45774
- try {
45925
+ //try {
45775
45926
  if(!template) {
45776
45927
  let dataArray2 = [];
45777
45928
 
45778
45929
  // let allPromise = Promise.allSettled(ajaxArray);
45779
45930
  // dataArray2 = await allPromise;
45780
45931
 
45781
- //split arrays into chunks of 48 jobs or me.cfg.maxajax jobs
45782
- let n = (me.cfg.maxajax) ? me.cfg.maxajax : ic.refpdbArray.length * 6;
45783
-
45784
- for(let i = 0, il = parseInt((ajaxArray.length - 1) / n + 1); i < il; ++i) {
45785
- let currAjaxArray = [];
45786
- if(i == il - 1) { // last one
45787
- currAjaxArray = ajaxArray.slice(i * n, ajaxArray.length);
45788
- }
45789
- else {
45790
- currAjaxArray = ajaxArray.slice(i * n, (i + 1) * n);
45791
- }
45792
-
45793
- let currPromise = Promise.allSettled(currAjaxArray);
45794
- let currDataArray = await currPromise;
45795
-
45796
- dataArray2 = dataArray2.concat(currDataArray);
45797
- }
45932
+ dataArray2 = await this.promiseWithFixedJobs(ajaxArray);
45798
45933
 
45799
45934
  let bRound1 = true;
45800
45935
  await thisClass.parseAlignData(dataArray2, domainidpairArray, bRound1);
@@ -45814,12 +45949,14 @@ class LineGraph {
45814
45949
  let pdbAjaxArray = [];
45815
45950
  pdbAjaxArray.push(pdbAjax);
45816
45951
 
45817
- let allPromise2 = Promise.allSettled(pdbAjaxArray);
45818
- ic.pdbDataArray = await allPromise2;
45952
+ //let allPromise2 = Promise.allSettled(pdbAjaxArray);
45953
+ //ic.pdbDataArray = await allPromise2;
45954
+
45955
+ ic.pdbDataArray = await this.promiseWithFixedJobs(pdbAjaxArray);
45819
45956
 
45820
45957
  for(let domainid in ic.domainid2refpdbname) {
45821
- let refpdbname = ic.domainid2refpdbname[domainid];
45822
- let chainid = domainid.substr(0, domainid.indexOf('-'));
45958
+ ic.domainid2refpdbname[domainid];
45959
+ domainid.substr(0, domainid.indexOf(','));
45823
45960
 
45824
45961
  let pdb_target = ic.domainid2pdb[domainid];
45825
45962
  for(let index = 0, indexl = ic.pdbDataArray.length; index < indexl; ++index) {
@@ -45839,11 +45976,14 @@ class LineGraph {
45839
45976
  }
45840
45977
 
45841
45978
  let dataArray3 = [];
45842
- let allPromise = Promise.allSettled(ajaxArray);
45843
- dataArray3 = await allPromise;
45979
+ //let allPromise = Promise.allSettled(ajaxArray);
45980
+ //dataArray3 = await allPromise;
45981
+
45982
+ dataArray3 = await this.promiseWithFixedJobs(ajaxArray);
45844
45983
 
45845
45984
  await thisClass.parseAlignData(dataArray3, domainidpairArray3);
45846
45985
  }
45986
+ /*
45847
45987
  }
45848
45988
  catch(err) {
45849
45989
  let mess = "Some of " + ajaxArray.length + " TM-align alignments failed. Please select a chain or a subset to assing reference numbers to avoid overloading the server...";
@@ -45855,17 +45995,23 @@ class LineGraph {
45855
45995
  }
45856
45996
  //console.log("Error in aligning with TM-align...");
45857
45997
  return;
45858
- }
45998
+ }
45999
+ */
45859
46000
  }
45860
46001
 
45861
46002
  getTemplateList(chainid) { let ic = this.icn3d; ic.icn3dui;
45862
- let domainid2refpdbname = {};
46003
+ let domainid2refpdbname = {}, domainid2score = {};
45863
46004
 
45864
46005
  for(let i = 0, il = ic.chainid2refpdbname[chainid].length; i < il; ++i) {
45865
46006
  let refpdbname_domainid = ic.chainid2refpdbname[chainid][i].split('|');
45866
46007
  domainid2refpdbname[refpdbname_domainid[1]] = refpdbname_domainid[0];
45867
46008
  }
45868
46009
 
46010
+ for(let i = 0, il = ic.chainid2score[chainid].length; i < il; ++i) {
46011
+ let score_domainid = ic.chainid2score[chainid][i].split('|');
46012
+ domainid2score[score_domainid[1]] = score_domainid[0];
46013
+ }
46014
+
45869
46015
  let domainidArray = Object.keys(domainid2refpdbname);
45870
46016
  domainidArray.sort(function(id1, id2) {
45871
46017
  let resi1 = parseInt(id1.substr(id1.lastIndexOf('_') + 1));
@@ -45873,13 +46019,28 @@ class LineGraph {
45873
46019
  return resi1 - resi2;
45874
46020
  });
45875
46021
 
45876
- let chainList = '';
46022
+ let refpdbnameList = '';
46023
+ for(let i = 0, il = domainidArray.length; i < il; ++i) {
46024
+ refpdbnameList += domainid2refpdbname[domainidArray[i]];
46025
+ if(i < il - 1) refpdbnameList += ", ";
46026
+ }
46027
+
46028
+ let scoreList = '', seqidList = '', nresAlignList = '';
45877
46029
  for(let i = 0, il = domainidArray.length; i < il; ++i) {
45878
- chainList += domainid2refpdbname[domainidArray[i]];
45879
- if(i < il - 1) chainList += ", ";
46030
+ let itemArray = domainid2score[domainidArray[i]].split('_');
46031
+
46032
+ scoreList += itemArray[0];
46033
+ seqidList += itemArray[1];
46034
+ nresAlignList += itemArray[2];
46035
+
46036
+ if(i < il - 1) {
46037
+ scoreList += ", ";
46038
+ seqidList += ", ";
46039
+ nresAlignList += ", ";
46040
+ }
45880
46041
  }
45881
46042
 
45882
- return chainList;
46043
+ return {'refpdbnameList': refpdbnameList, 'scoreList': scoreList, 'seqidList': seqidList, 'nresAlignList': nresAlignList};
45883
46044
  }
45884
46045
 
45885
46046
  async parseAlignData(dataArray, domainidpairArray, bRound1) { let ic = this.icn3d, me = ic.icn3dui;
@@ -45888,33 +46049,35 @@ class LineGraph {
45888
46049
  let tmscoreThreshold = 0.4; // 0.4; //0.5;
45889
46050
 
45890
46051
  // find the best alignment for each chain
45891
- let domainid2score = {}, domainid2segs = {}, chainid2segs = {};
46052
+ let domainid2segs = {}, chainid2segs = {};
45892
46053
 
45893
46054
  if(!ic.chainid2refpdbname) ic.chainid2refpdbname = {};
46055
+ if(!ic.chainid2score) ic.chainid2score = {};
45894
46056
  if(!ic.domainid2refpdbname) ic.domainid2refpdbname = {};
46057
+ if(!ic.domainid2score) ic.domainid2score = {};
45895
46058
  if(!ic.domainid2ig2kabat) ic.domainid2ig2kabat = {};
45896
46059
  if(!ic.domainid2ig2imgt) ic.domainid2ig2imgt = {};
45897
46060
 
45898
- // ic.chainid2refpdbname = {};
45899
- // ic.domainid2refpdbname = {};
45900
- // ic.domainid2ig2kabat = {};
45901
- // ic.domainid2ig2imgt = {};
45902
-
45903
46061
  let minResidues = 20;
45904
46062
 
45905
46063
  for(let i = 0, il = domainidpairArray.length; i < il; ++i) {
45906
46064
  //let queryData = (me.bNode) ? dataArray[i] : dataArray[i].value; //[0];
45907
46065
  let queryData = dataArray[i].value; //[0];
45908
46066
 
45909
- if(!queryData) {
46067
+ if(!queryData || queryData.length == 0) {
45910
46068
  if(!me.bNode) console.log("The alignment data for " + domainidpairArray[i] + " is unavailable...");
45911
46069
  continue;
45912
46070
  }
45913
-
45914
- if(queryData.length == 0) continue;
45915
46071
 
46072
+ //let domainid_index = domainidpairArray[i].split(',');
46073
+ //let domainid = domainid_index[0];
46074
+ let domainid = domainidpairArray[i].substr(0, domainidpairArray[i].indexOf('|'));
46075
+ let refpdbname = domainidpairArray[i].substr(domainidpairArray[i].indexOf('|') + 1);
46076
+ //let chainid = domainid.split('-')[0];
46077
+
45916
46078
  if(!bRound1) {
45917
46079
  if(queryData[0].score < tmscoreThreshold || queryData[0].num_res < minResidues) {
46080
+ if(!me.bNode) console.log("domainid " + domainid + " and refpdbname " + refpdbname + " were skipped due to a TM-score less than " + tmscoreThreshold);
45918
46081
  continue;
45919
46082
  }
45920
46083
  }
@@ -45926,12 +46089,6 @@ class LineGraph {
45926
46089
  continue;
45927
46090
  }
45928
46091
  }
45929
-
45930
- //let domainid_index = domainidpairArray[i].split(',');
45931
- //let domainid = domainid_index[0];
45932
- let domainid = domainidpairArray[i].substr(0, domainidpairArray[i].indexOf('|'));
45933
- let refpdbname = domainidpairArray[i].substr(domainidpairArray[i].indexOf('|') + 1);
45934
- //let chainid = domainid.split('-')[0];
45935
46092
 
45936
46093
  if(!bRound1) {
45937
46094
  if(!me.bNode) console.log("refpdbname " + refpdbname + " TM-score: " + queryData[0].score);
@@ -45948,16 +46105,16 @@ class LineGraph {
45948
46105
  for(let i = 0, il = queryData[0].segs.length; i < il; ++i) {
45949
46106
  let seg = queryData[0].segs[i];
45950
46107
 
45951
- if(seg.q_start.indexOf('2150') != -1 || seg.q_start.indexOf('2250') != -1) {
46108
+ if(seg.q_start.indexOf('2550') != -1) {
45952
46109
  bBstrand = true;
45953
46110
  }
45954
- else if(seg.q_start.indexOf('3150') != -1 || seg.q_start.indexOf('3250') != -1) {
46111
+ else if(seg.q_start.indexOf('3550') != -1) {
45955
46112
  bCstrand = true;
45956
46113
  }
45957
- else if(seg.q_start.indexOf('7150') != -1 || seg.q_start.indexOf('7250') != -1) {
46114
+ else if(seg.q_start.indexOf('7550') != -1) {
45958
46115
  bEstrand = true;
45959
46116
  }
45960
- else if(seg.q_start.indexOf('8150') != -1 || seg.q_start.indexOf('8250') != -1) {
46117
+ else if(seg.q_start.indexOf('8550') != -1) {
45961
46118
  bFstrand = true;
45962
46119
  }
45963
46120
 
@@ -45968,35 +46125,25 @@ class LineGraph {
45968
46125
  //if(!(bBstrand && bCstrand && bEstrand && bFstrand && bGstrand)) continue;
45969
46126
  if(!(bBstrand && bCstrand && bEstrand && bFstrand)) {
45970
46127
  if(!me.bNode) console.log("Some of the Ig strands B, C, E, F are missing in the domain " + domainid + "...");
45971
- if(ic.domainid2refpdbname[domainid] == refpdbname) delete ic.domainid2refpdbname[domainid];
46128
+ if(ic.domainid2refpdbname[domainid] == refpdbname) {
46129
+ delete ic.domainid2refpdbname[domainid];
46130
+ delete ic.domainid2score[domainid];
46131
+ }
45972
46132
  continue;
45973
46133
  }
45974
46134
  }
45975
46135
 
45976
46136
  if(!bRound1) {
45977
46137
  console.log("domainid: " + domainid);
45978
-
45979
- if(!domainid2score.hasOwnProperty(domainid) || queryData[0].score > domainid2score[domainid]) {
45980
- domainid2score[domainid] = queryData[0].score;
45981
-
45982
- ic.domainid2refpdbname[domainid] = refpdbname;
45983
- domainid2segs[domainid] = queryData[0].segs;
45984
- ic.domainid2ig2kabat[domainid] = queryData[0].ig2kabat;
45985
- ic.domainid2ig2imgt[domainid] = queryData[0].ig2imgt;
45986
- }
45987
46138
  }
45988
- else {
45989
- //let mixScore = 10 / queryData[0].super_rmsd + queryData[0].num_seg / 5;
45990
- let mixScore = queryData[0].score;
45991
46139
 
45992
- if(!domainid2score.hasOwnProperty(domainid) || mixScore > domainid2score[domainid]) {
45993
- domainid2score[domainid] = mixScore;
45994
-
45995
- ic.domainid2refpdbname[domainid] = refpdbname;
45996
- domainid2segs[domainid] = queryData[0].segs;
45997
- ic.domainid2ig2kabat[domainid] = queryData[0].ig2kabat;
45998
- ic.domainid2ig2imgt[domainid] = queryData[0].ig2imgt;
45999
- }
46140
+ if(!ic.domainid2score.hasOwnProperty(domainid) || queryData[0].score >= ic.domainid2score[domainid].split('_')[0]) {
46141
+ ic.domainid2score[domainid] = queryData[0].score + '_' + queryData[0].frac_identical + '_' + queryData[0].num_res ;
46142
+
46143
+ ic.domainid2refpdbname[domainid] = refpdbname;
46144
+ domainid2segs[domainid] = queryData[0].segs;
46145
+ ic.domainid2ig2kabat[domainid] = queryData[0].ig2kabat;
46146
+ ic.domainid2ig2imgt[domainid] = queryData[0].ig2imgt;
46000
46147
  }
46001
46148
  }
46002
46149
 
@@ -46011,7 +46158,7 @@ class LineGraph {
46011
46158
  let pdbAjaxArray = [];
46012
46159
  let refpdbname = ic.domainid2refpdbname[domainid];
46013
46160
  //let pdbid = domainid.substr(0, domainid.indexOf('_'));
46014
- let chainid = domainid.substr(0, domainid.indexOf('-'));
46161
+ let chainid = domainid.substr(0, domainid.indexOf(','));
46015
46162
 
46016
46163
  //if(ic.refpdbHash.hasOwnProperty(pdbid)) {
46017
46164
  if(ic.refpdbHash.hasOwnProperty(chainid)) {
@@ -46034,8 +46181,10 @@ class LineGraph {
46034
46181
  pdbAjaxArray.push(pdbAjax);
46035
46182
  }
46036
46183
 
46037
- let allPromise2 = Promise.allSettled(pdbAjaxArray);
46038
- ic.pdbDataArray = await allPromise2;
46184
+ //let allPromise2 = Promise.allSettled(pdbAjaxArray);
46185
+ //ic.pdbDataArray = await allPromise2;
46186
+
46187
+ ic.pdbDataArray = await this.promiseWithFixedJobs(pdbAjaxArray);
46039
46188
 
46040
46189
  let pdb_target = ic.domainid2pdb[domainid];
46041
46190
  for(let index = 0, indexl = ic.pdbDataArray.length; index < indexl; ++index) {
@@ -46058,49 +46207,46 @@ class LineGraph {
46058
46207
  //let allPromise = Promise.allSettled(ajaxArray);
46059
46208
  //dataArray3 = await allPromise;
46060
46209
 
46061
- //split arrays into chunks of 48 jobs or me.cfg.maxajax jobs
46062
- let n = (me.cfg.maxajax) ? me.cfg.maxajax : ic.refpdbArray.length * 6;
46063
-
46064
- for(let i = 0, il = parseInt((ajaxArray.length - 1) / n + 1); i < il; ++i) {
46065
- let currAjaxArray = [];
46066
- if(i == il - 1) { // last one
46067
- currAjaxArray = ajaxArray.slice(i * n, ajaxArray.length);
46068
- }
46069
- else {
46070
- currAjaxArray = ajaxArray.slice(i * n, (i + 1) * n);
46071
- }
46072
-
46073
- let currPromise = Promise.allSettled(currAjaxArray);
46074
- let currDataArray = await currPromise;
46075
-
46076
- dataArray3 = dataArray3.concat(currDataArray);
46077
- }
46210
+ dataArray3 = await this.promiseWithFixedJobs(ajaxArray);
46078
46211
 
46079
46212
  await thisClass.parseAlignData(dataArray3, domainidpairArray3, false);
46080
46213
 
46081
46214
  // end of round 2
46082
46215
  return;
46083
46216
  }
46084
-
46217
+
46085
46218
  // combine domainid into chainid
46086
46219
  let processedChainid = {};
46087
46220
  for(let domainid in ic.domainid2refpdbname) {
46088
- let chainid = domainid.split('-')[0];
46221
+ // remove the first round template
46222
+ if(ic.domainid2refpdbname[domainid].substr(0,1) == '1') {
46223
+ delete ic.domainid2refpdbname[domainid];
46224
+ delete ic.domainid2score[domainid];
46225
+ continue;
46226
+ }
46089
46227
 
46090
- if(!processedChainid.hasOwnProperty(chainid)) ic.chainid2refpdbname[chainid] = [];
46228
+ let chainid = domainid.split(',')[0];
46229
+
46230
+ if(!processedChainid.hasOwnProperty(chainid)) {
46231
+ ic.chainid2refpdbname[chainid] = [];
46232
+ ic.chainid2score[chainid] = [];
46233
+ }
46091
46234
  processedChainid[chainid] = 1;
46092
46235
 
46093
46236
  if(!ic.chainid2refpdbname.hasOwnProperty(chainid)) ic.chainid2refpdbname[chainid] = [];
46094
46237
  ic.chainid2refpdbname[chainid].push(ic.domainid2refpdbname[domainid] + '|' + domainid);
46238
+
46239
+ if(!ic.chainid2score.hasOwnProperty(chainid)) ic.chainid2score[chainid] = [];
46240
+ ic.chainid2score[chainid].push(ic.domainid2score[domainid] + '|' + domainid);
46095
46241
  }
46096
-
46242
+
46097
46243
  // combine domainid into chainid
46098
46244
  for(let domainid in domainid2segs) {
46099
- let chainid = domainid.split('-')[0];
46245
+ let chainid = domainid.split(',')[0];
46100
46246
  if(!chainid2segs[chainid]) chainid2segs[chainid] = [];
46101
46247
  chainid2segs[chainid] = chainid2segs[chainid].concat(domainid2segs[domainid]);
46102
46248
  }
46103
-
46249
+
46104
46250
  // assign ic.resid2refnum, ic.refnum2residArray, ic.chainsMapping
46105
46251
  if(!ic.resid2refnum) ic.resid2refnum = {};
46106
46252
  if(!ic.refnum2residArray) ic.refnum2residArray = {};
@@ -46113,11 +46259,18 @@ class LineGraph {
46113
46259
 
46114
46260
  let refpdbnameArray = ic.chainid2refpdbname[chainid];
46115
46261
 
46116
- let chainList = this.getTemplateList(chainid);
46262
+ let result = this.getTemplateList(chainid);
46263
+ let refpdbnameList = result.refpdbnameList;
46264
+ let scoreList = result.scoreList;
46265
+ let seqidList = result.seqidList;
46266
+ let nresAlignList = result.nresAlignList;
46117
46267
 
46118
- //if(!me.bNode) console.log("The reference PDB(s) for chain " + chainid + " are " + chainList);
46119
- if(!me.bNode) console.log("The reference PDB(s) for chain " + chainid + " are " + chainList);
46120
- ic.refPdbList.push("The reference PDB(s) for chain " + chainid + " are " + chainList);
46268
+ 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 + ".";
46269
+ if(!me.bNode) {
46270
+ console.log(message);
46271
+ me.htmlCls.clickMenuCls.setLogCmd(message, true);
46272
+ }
46273
+ ic.refPdbList.push(message);
46121
46274
 
46122
46275
  let prevStrand;
46123
46276
  let bCd19 = refpdbnameArray.length == 1 && refpdbnameArray[0] == 'CD19_6al5A_human_C2orV-n1';
@@ -46187,51 +46340,52 @@ class LineGraph {
46187
46340
  getLabelFromRefnum(oriRefnum, prevStrand, bCd19) { let ic = this.icn3d; ic.icn3dui;
46188
46341
  let refnum = parseInt(oriRefnum);
46189
46342
 
46190
- // A-: 10xx
46191
- // A: 11xx
46192
- // A+ continue A
46193
- // A': 12xx
46194
- // B: 21xx
46195
- // C: 32xx
46196
- // C': 42xx
46197
- // C'': 51xx, 52xx
46198
- // D: 61xx
46199
- // E: 71xx
46200
- // E+: continue E
46201
- // F: 82xx
46202
- // G: 91xx, 92xx
46203
- // G+: continue G
46204
-
46205
- // if(refnum < 100) return " " + oriRefnum;
46206
- // else if(refnum >= 100 && refnum < 1000) {
46207
- // if(bCd19) return " " + oriRefnum;
46208
- // else return "A^" + oriRefnum;
46209
- // }
46210
- if(refnum < 900) return undefined;
46211
- else if(refnum >= 900 && refnum < 1000) return " " + oriRefnum;
46212
- else if(refnum >= 1000 && refnum < 1100) return "A-" + oriRefnum;
46213
- else if(refnum >= 1100 && refnum < 1200) return "A" + oriRefnum; // could be A+
46214
- else if(refnum >= 1200 && refnum < 1300) return "A'" + oriRefnum;
46215
- //else if(refnum >= 1300 && refnum < 1400) return "A+" + oriRefnum;
46216
- else if(refnum >= 1300 && refnum < 2000) {
46217
- if(prevStrand && prevStrand.substr(0, 1) == 'A') {
46218
- return prevStrand + oriRefnum;
46219
- }
46220
- else {
46221
- return "A" + oriRefnum;
46222
- }
46223
- }
46224
- else if(refnum >= 2000 && refnum < 3000) return "B" + oriRefnum;
46225
- else if(refnum >= 3000 && refnum < 4000) return "C" + oriRefnum;
46226
- else if(refnum >= 4000 && refnum < 5000) return "C'" + oriRefnum;
46227
- else if(refnum >= 5000 && refnum < 6000) return "C''" + oriRefnum;
46228
- else if(refnum >= 6000 && refnum < 7000) return "D" + oriRefnum;
46229
- else if(refnum >= 7000 && refnum < 8000) return "E" + oriRefnum; // could be E+
46230
- else if(refnum >= 8000 && refnum < 9000) return "F" + oriRefnum;
46231
- else if(refnum >= 9000 && refnum < 9300) return "G" + oriRefnum; // could be G+
46232
- //else if(refnum >= 9400 && refnum < 9500) return "G+" + oriRefnum;
46233
- else if(refnum >= 9300) return "G" + oriRefnum;
46234
- }
46343
+ //N-terminus = 0999-0001
46344
+ //A--- = 12xx
46345
+ //A-- = 13xx
46346
+ //A- = 14xx
46347
+ //A = 15xx (anchor 1550)
46348
+ //A+ = 16xx
46349
+ //A' = 18xx (anchor 1850)
46350
+ //B = 25xx (anchor 2550)
46351
+ //C-- = 33xx
46352
+ //C- = 34xx
46353
+ //C = 35xx (anchor 3550)
46354
+ //C' = 45xx (anchor 4550)
46355
+ //C'' = 55xx (anchor 5550)
46356
+ //D = 65xx (anchor 3550)
46357
+ //E = 75xx (anchor 7550)
46358
+ //E+ = 76xx
46359
+ //F = 85xx (anchor 8550)
46360
+ //G = 95xx (anchor 9550)
46361
+ //G+ = 96xx
46362
+ //G++ = 97xx
46363
+ //C-terminus = 9901-9999 (no anchor, numbering going forward)
46364
+
46365
+ // loops may have numbers such as 1310, 1410
46366
+
46367
+ if(refnum < 1000) return undefined;
46368
+ else if(refnum >= 1200 && refnum < 1290) return "A---" + oriRefnum;
46369
+ else if(refnum >= 1320 && refnum < 1390) return "A--" + oriRefnum;
46370
+ else if(refnum >= 1420 && refnum < 1490) return "A-" + oriRefnum;
46371
+ else if(refnum >= 1520 && refnum < 1590) return "A" + oriRefnum;
46372
+ else if(refnum >= 1620 && refnum < 1690) return "A+" + oriRefnum;
46373
+ else if(refnum >= 1820 && refnum < 1890) return "A'" + oriRefnum;
46374
+ else if(refnum >= 2000 && refnum < 2900) return "B" + oriRefnum;
46375
+ else if(refnum >= 3300 && refnum < 3390) return "C--" + oriRefnum;
46376
+ else if(refnum >= 3420 && refnum < 3490) return "C-" + oriRefnum;
46377
+ else if(refnum >= 3520 && refnum < 3590) return "C" + oriRefnum;
46378
+ else if(refnum >= 4000 && refnum < 4900) return "C'" + oriRefnum;
46379
+ else if(refnum >= 5000 && refnum < 5900) return "C''" + oriRefnum;
46380
+ else if(refnum >= 6000 && refnum < 6900) return "D" + oriRefnum;
46381
+ else if(refnum >= 7500 && refnum < 7590) return "E" + oriRefnum;
46382
+ else if(refnum >= 7620 && refnum < 7900) return "E+" + oriRefnum;
46383
+ else if(refnum >= 8000 && refnum < 8900) return "F" + oriRefnum;
46384
+ else if(refnum >= 9500 && refnum < 9590) return "G" + oriRefnum;
46385
+ else if(refnum >= 9620 && refnum < 9690) return "G+" + oriRefnum;
46386
+ else if(refnum >= 9720 && refnum < 9790) return "G++" + oriRefnum;
46387
+ else if(refnum > 9900) return undefined;
46388
+ else return " " + oriRefnum; }
46235
46389
 
46236
46390
  async parseCustomRefFile(data) { let ic = this.icn3d; ic.icn3dui;
46237
46391
  ic.bShowCustomRefnum = true;
@@ -46413,6 +46567,32 @@ class LineGraph {
46413
46567
  return refData;
46414
46568
  }
46415
46569
  }
46570
+
46571
+ async promiseWithFixedJobs(ajaxArray) { let ic = this.icn3d, me = ic.icn3dui;
46572
+ let dataArray3 = [];
46573
+ //let allPromise = Promise.allSettled(ajaxArray);
46574
+ //dataArray3 = await allPromise;
46575
+
46576
+ //split arrays into chunks of 48 jobs or me.cfg.maxajax jobs
46577
+ let n = (me.cfg.maxajax) ? me.cfg.maxajax : ic.refpdbArray.length * 6;
46578
+
46579
+ for(let i = 0, il = parseInt((ajaxArray.length - 1) / n + 1); i < il; ++i) {
46580
+ let currAjaxArray = [];
46581
+ if(i == il - 1) { // last one
46582
+ currAjaxArray = ajaxArray.slice(i * n, ajaxArray.length);
46583
+ }
46584
+ else {
46585
+ currAjaxArray = ajaxArray.slice(i * n, (i + 1) * n);
46586
+ }
46587
+
46588
+ let currPromise = Promise.allSettled(currAjaxArray);
46589
+ let currDataArray = await currPromise;
46590
+
46591
+ dataArray3 = dataArray3.concat(currDataArray);
46592
+ }
46593
+
46594
+ return dataArray3;
46595
+ }
46416
46596
  }
46417
46597
 
46418
46598
  /**
@@ -47721,7 +47901,7 @@ class ViewInterPairs {
47721
47901
 
47722
47902
  if(ic.bD3 === undefined) {
47723
47903
  //let url = "https://d3js.org/d3.v4.min.js";
47724
- let url = "https://www.ncbi.nlm.nih.gov/Structure/icn3d/script/d3v4-force-all.min.js";
47904
+ let url = "./script/d3v4-force-all.min.js";
47725
47905
  await me.getAjaxPromise(url, 'script');
47726
47906
 
47727
47907
  ic.bD3 = true;
@@ -48996,7 +49176,7 @@ class AlignParser {
48996
49176
  for(let j = 0, jl = mmdbTmp.molecules.length; j < jl; ++j) {
48997
49177
  let molecule = mmdbTmp.molecules[j];
48998
49178
  let molid = molecule.moleculeId;
48999
- let chainName = molecule.chain.trim();
49179
+ let chainName = molecule.chain.trim().replace(/_/g, ''); // change "A_1" to "A1"
49000
49180
  if(chainNameHash[chainName] === undefined) {
49001
49181
  chainNameHash[chainName] = 1;
49002
49182
  }
@@ -49407,6 +49587,8 @@ class ChainalignParser {
49407
49587
 
49408
49588
  let queryData = {}; // check whether undefined
49409
49589
 
49590
+ me.htmlCls.clickMenuCls.setLogCmd("Align " + mmdbid_t + " with " + mmdbid_q, false);
49591
+
49410
49592
  this.processAlign(align, index, queryData, bEqualMmdbid, bEqualChain);
49411
49593
  }
49412
49594
 
@@ -49504,6 +49686,8 @@ class ChainalignParser {
49504
49686
  continue;
49505
49687
  }
49506
49688
 
49689
+ me.htmlCls.clickMenuCls.setLogCmd("Align " + mmdbid1 + " with " + mmdbid2, false);
49690
+
49507
49691
  let bNoAlert = true;
49508
49692
  let bAligned = this.processAlign(align, i, queryData, bEqualMmdbid, bEqualChain, bNoAlert);
49509
49693
 
@@ -49954,6 +50138,8 @@ class ChainalignParser {
49954
50138
  let bEqualMmdbid = (mmdbid_q == mmdbid_t);
49955
50139
  let bEqualChain = (chain_q == chain_t);
49956
50140
 
50141
+ me.htmlCls.clickMenuCls.setLogCmd("Align " + mmdbid_t + " with " + mmdbid_q, false);
50142
+
49957
50143
  this.processAlign(align, index-1, queryData, bEqualMmdbid, bEqualChain);
49958
50144
  }
49959
50145
  }
@@ -50014,6 +50200,7 @@ class ChainalignParser {
50014
50200
  ic.qt_start_end[index] = align[0].segs;
50015
50201
 
50016
50202
  let rmsd = align[0].super_rmsd;
50203
+ console.log();
50017
50204
 
50018
50205
  let logStr = "alignment RMSD: " + rmsd.toPrecision(4);
50019
50206
  if(me.cfg.aligntool == 'tmalign') logStr += "; TM-score: " + align[0].score.toPrecision(4);
@@ -50283,10 +50470,10 @@ class Dsn6Parser {
50283
50470
  // https://edmaps.rcsb.org/maps/1kq2_fofc.dsn6
50284
50471
 
50285
50472
  let url = "https://edmaps.rcsb.org/maps/" + pdbid.toLowerCase() + "_" + type + ".dsn6";
50286
- await this.dsn6ParserBase(url, type, sigma);
50473
+ await this.dsn6ParserBase(url, type, sigma, 'url', true);
50287
50474
  }
50288
50475
 
50289
- async dsn6ParserBase(url, type, sigma) { let ic = this.icn3d, me = ic.icn3dui;
50476
+ async dsn6ParserBase(url, type, sigma, location, bInputSigma) { let ic = this.icn3d, me = ic.icn3dui;
50290
50477
  let thisClass = this;
50291
50478
 
50292
50479
  //https://stackoverflow.com/questions/33902299/using-jquery-ajax-to-download-a-binary-file
@@ -50300,7 +50487,7 @@ class Dsn6Parser {
50300
50487
  }
50301
50488
  else {
50302
50489
  let arrayBuffer = await me.getXMLHttpRqstPromise(url, 'GET', 'arraybuffer', 'rcsbEdmaps');
50303
- thisClass.loadDsn6Data(arrayBuffer, type, sigma);
50490
+ sigma = thisClass.loadDsn6Data(arrayBuffer, type, sigma, location, bInputSigma);
50304
50491
 
50305
50492
  if(type == '2fofc') {
50306
50493
  ic.bAjax2fofc = true;
@@ -50311,9 +50498,11 @@ class Dsn6Parser {
50311
50498
 
50312
50499
  ic.setOptionCls.setOption('map', type);
50313
50500
  }
50501
+
50502
+ return sigma;
50314
50503
  }
50315
50504
 
50316
- loadDsn6Data(dsn6data, type, sigma) { let ic = this.icn3d; ic.icn3dui;
50505
+ loadDsn6Data(dsn6data, type, sigma, location, bInputSigma) { let ic = this.icn3d; ic.icn3dui;
50317
50506
  // DSN6 http://www.uoxray.uoregon.edu/tnt/manual/node104.html
50318
50507
  // BRIX http://svn.cgl.ucsf.edu/svn/chimera/trunk/libs/VolumeData/dsn6/brix-1.html
50319
50508
 
@@ -50362,9 +50551,9 @@ class Dsn6Parser {
50362
50551
  }
50363
50552
  }
50364
50553
 
50365
- header.zStart = intView[ 2 ];
50366
50554
  header.xStart = intView[ 0 ]; // NXSTART
50367
50555
  header.yStart = intView[ 1 ];
50556
+ header.zStart = intView[ 2 ];
50368
50557
 
50369
50558
  header.xExtent = intView[ 3 ]; // NX
50370
50559
  header.yExtent = intView[ 4 ];
@@ -50400,6 +50589,7 @@ class Dsn6Parser {
50400
50589
  let zBlocks = Math.ceil(header.zExtent / 8);
50401
50590
 
50402
50591
  // loop over blocks
50592
+ let maxValue = -999;
50403
50593
  for(let zz = 0; zz < zBlocks; ++zz) {
50404
50594
  for(let yy = 0; yy < yBlocks; ++yy) {
50405
50595
  for(let xx = 0; xx < xBlocks; ++xx) {
@@ -50415,6 +50605,7 @@ class Dsn6Parser {
50415
50605
  if(x < header.xExtent && y < header.yExtent && z < header.zExtent) {
50416
50606
  let idx =((((x * header.yExtent) + y) * header.zExtent) + z);
50417
50607
  data[ idx ] =(byteView[ offset ] - summand) / divisor;
50608
+ if(data[ idx ] > maxValue) maxValue = data[ idx ];
50418
50609
  ++offset;
50419
50610
  } else {
50420
50611
  offset += 8 - i;
@@ -50427,6 +50618,10 @@ class Dsn6Parser {
50427
50618
  }
50428
50619
  }
50429
50620
 
50621
+ if(!bInputSigma) {
50622
+ sigma = this.setSigma(maxValue, location, type, sigma);
50623
+ }
50624
+
50430
50625
  if(type == '2fofc') {
50431
50626
  ic.mapData.header2 = header;
50432
50627
  ic.mapData.data2 = data;
@@ -50441,6 +50636,32 @@ class Dsn6Parser {
50441
50636
  ic.mapData.type = type;
50442
50637
  ic.mapData.sigma = sigma;
50443
50638
  }
50639
+
50640
+ return sigma;
50641
+ }
50642
+
50643
+ setSigma(maxValue, location, type, sigma) { let ic = this.icn3d, me = ic.icn3dui;
50644
+ let inputId;
50645
+ if(location == 'file') {
50646
+ inputId = 'dsn6sigma' + type;
50647
+ }
50648
+ else if(location == 'url') {
50649
+ inputId = 'dsn6sigmaurl' + type;
50650
+ }
50651
+
50652
+ let factor = (type == '2fofc') ? 0.5 : 0.3;
50653
+
50654
+ if(inputId) {
50655
+ if(!($("#" + me.pre + inputId).val())) {
50656
+ sigma = (factor * maxValue).toFixed(2);
50657
+ $("#" + me.pre + inputId).val(sigma);
50658
+ }
50659
+ else {
50660
+ sigma = $("#" + me.pre + inputId).val();
50661
+ }
50662
+ }
50663
+
50664
+ return sigma;
50444
50665
  }
50445
50666
 
50446
50667
  getMatrix(header) { let ic = this.icn3d; ic.icn3dui;
@@ -50514,7 +50735,9 @@ class Dsn6Parser {
50514
50735
  let reader = new FileReader();
50515
50736
  reader.onload = function(e) { let ic = thisClass.icn3d;
50516
50737
  let arrayBuffer = e.target.result; // or = reader.result;
50517
- thisClass.loadDsn6Data(arrayBuffer, type, sigma);
50738
+
50739
+ sigma = thisClass.loadDsn6Data(arrayBuffer, type, sigma, 'file');
50740
+
50518
50741
  if(type == '2fofc') {
50519
50742
  ic.bAjax2fofc = true;
50520
50743
  }
@@ -50522,21 +50745,1006 @@ class Dsn6Parser {
50522
50745
  ic.bAjaxfofc = true;
50523
50746
  }
50524
50747
  ic.setOptionCls.setOption('map', type);
50525
- me.htmlCls.clickMenuCls.setLogCmd('load dsn6 file ' + $("#" + ic.pre + "dsn6file" + type).val(), false);
50748
+ me.htmlCls.clickMenuCls.setLogCmd('load map file ' + $("#" + ic.pre + "dsn6file" + type).val() + ' with sigma ' + sigma, false);
50526
50749
  };
50527
50750
  reader.readAsArrayBuffer(file);
50528
50751
  }
50529
50752
  }
50530
50753
 
50531
50754
  loadDsn6FileUrl(type) {var ic = this.icn3d, me = ic.icn3dui;
50755
+ let url = $("#" + ic.pre + "dsn6fileurl" + type).val();
50756
+ let sigma = $("#" + ic.pre + "dsn6sigmaurl" + type).val();
50757
+ if(!url) {
50758
+ var aaa = 1; //alert("Please input the file URL before clicking 'Load'");
50759
+ }
50760
+ else {
50761
+ sigma = this.dsn6ParserBase(url, type, sigma, 'url');
50762
+ me.htmlCls.clickMenuCls.setLogCmd('set map ' + type + ' sigma ' + sigma + ' file dsn6 | ' + encodeURIComponent(url), true);
50763
+ }
50764
+ }
50765
+
50766
+ }
50767
+
50768
+ /**
50769
+ * @file Ccp4 Parser
50770
+ * @author Marcin Wojdyr <wojdyr@gmail.com>
50771
+ * @private
50772
+ * Modified by Jiyao Wang / https://github.com/ncbi/icn3d
50773
+ */
50774
+
50775
+ class Ccp4Parser {
50776
+ constructor(icn3d) {
50777
+ this.icn3d = icn3d;
50778
+ }
50779
+
50780
+ async ccp4ParserBase(url, type, sigma, location) { let ic = this.icn3d, me = ic.icn3dui;
50781
+ let thisClass = this;
50782
+
50783
+ //https://stackoverflow.com/questions/33902299/using-jquery-ajax-to-download-a-binary-file
50784
+ // if(type == '2fofc' && ic.bAjax2fofcccp4) {
50785
+ // ic.mapData.sigma2 = sigma;
50786
+ // ic.setOptionCls.setOption('map', type);
50787
+ // }
50788
+ // else if(type == 'fofc' && ic.bAjaxfofcccp4) {
50789
+ // ic.mapData.sigma = sigma;
50790
+ // ic.setOptionCls.setOption('map', type);
50791
+ // }
50792
+ // else {
50793
+ let arrayBuffer = await me.getXMLHttpRqstPromise(url, 'GET', 'arraybuffer', '');
50794
+ let bInputSigma = true;
50795
+ sigma = thisClass.load_map_from_buffer(arrayBuffer, type, sigma, location, bInputSigma);
50796
+
50797
+ // if(type == '2fofc') {
50798
+ // ic.bAjax2fofcccp4 = true;
50799
+ // }
50800
+ // else if(type == 'fofc') {
50801
+ // ic.bAjaxfofcccp4 = true;
50802
+ // }
50803
+
50804
+ ic.setOptionCls.setOption('map', type);
50805
+
50806
+ return sigma;
50807
+ // }
50808
+ }
50809
+
50810
+ // modified from_ccp4() at https://github.com/uglymol/uglymol.github.io/blob/master/src/elmap.js
50811
+ load_map_from_buffer(buf, type, sigma, location, bInputSigma) { let ic = this.icn3d; ic.icn3dui;
50812
+ if (buf.byteLength < 1024) throw Error('File shorter than 1024 bytes.');
50813
+
50814
+ //console.log('buf type: ' + Object.prototype.toString.call(buf));
50815
+ // for now we assume both file and host are little endian
50816
+ const iview = new Int32Array(buf, 0, 256);
50817
+ // word 53 - character string 'MAP ' to identify file type
50818
+ if (iview[52] !== 0x2050414d) throw Error('not a CCP4 map');
50819
+
50820
+ // map has 3 dimensions referred to as columns (fastest changing), rows
50821
+ // and sections (c-r-s)
50822
+ const n_crs = [iview[0], iview[1], iview[2]]; // 108, 108, 108
50823
+ const mode = iview[3]; //2
50824
+ let nb;
50825
+ if (mode === 2) nb = 4;
50826
+ else if (mode === 0) nb = 1;
50827
+ else throw Error('Only Mode 2 and Mode 0 of CCP4 map is supported.');
50828
+
50829
+ const start = [iview[4], iview[5], iview[6]]; // 0,0,0
50830
+ const n_grid = [iview[7], iview[8], iview[9]]; // 108,108,108
50831
+ const nsymbt = iview[23]; // size of extended header in bytes
50832
+ // nsymbt = 1920
50833
+
50834
+ if (1024 + nsymbt + nb*n_crs[0]*n_crs[1]*n_crs[2] !== buf.byteLength) {
50835
+ throw Error('ccp4 file too short or too long');
50836
+ }
50837
+
50838
+ const fview = new Float32Array(buf, 0, buf.byteLength / 4);
50839
+ const grid = new GridArray(n_grid);
50840
+ 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
50841
+
50842
+ // MAPC, MAPR, MAPS - axis corresp to cols, rows, sections (1,2,3 for X,Y,Z)
50843
+ const map_crs = [iview[16], iview[17], iview[18]]; // 2,1,3
50844
+ const ax = map_crs.indexOf(1);
50845
+ const ay = map_crs.indexOf(2);
50846
+ const az = map_crs.indexOf(3);
50847
+
50848
+ const min = fview[19]; // -0.49
50849
+ const max = fview[20]; // 0.94
50850
+ //const sg_number = iview[22];
50851
+ //const lskflg = iview[24];
50852
+
50853
+ if (nsymbt % 4 !== 0) {
50854
+ throw Error('CCP4 map with NSYMBT not divisible by 4 is not supported.');
50855
+ }
50856
+ let data_view;
50857
+ if (mode === 2) data_view = fview;
50858
+ else /* mode === 0 */ data_view = new Int8Array(buf);
50859
+ let idx = (1024 + nsymbt) / nb | 0; //736
50860
+
50861
+ // We assume that if DMEAN and RMS from the header are not clearly wrong
50862
+ // they are what the user wants. Because the map can cover a small part
50863
+ // of the asu and its rmsd may be different than the total rmsd.
50864
+ // let stats = { mean: 0.0, rms: 1.0 };
50865
+ // stats.mean = fview[21]; //0
50866
+ // stats.rms = fview[54]; //0.15
50867
+ // if (stats.mean < min || stats.mean > max || stats.rms <= 0) {
50868
+ // stats = this.calculate_stddev(data_view, idx);
50869
+ // }
50870
+
50871
+ let b1 = 1;
50872
+ let b0 = 0;
50873
+ // if the file was converted by mapmode2to0 - scale the data
50874
+ if (mode === 0 && iview[39] === -128 && iview[40] === 127) { //39:0, 40:0
50875
+ // scaling f(x)=b1*x+b0 such that f(-128)=min and f(127)=max
50876
+ b1 = (max - min) / 255.0;
50877
+ b0 = 0.5 * (min + max + b1);
50878
+ }
50879
+
50880
+ const end = [start[0] + n_crs[0], start[1] + n_crs[1], start[2] + n_crs[2]];
50881
+ let it = [0, 0, 0];
50882
+ let maxValue = -999;
50883
+ for (it[2] = start[2]; it[2] < end[2]; it[2]++) { // sections
50884
+ for (it[1] = start[1]; it[1] < end[1]; it[1]++) { // rows
50885
+ for (it[0] = start[0]; it[0] < end[0]; it[0]++) { // cols
50886
+ let value = b1 * data_view[idx] + b0;
50887
+ grid.set_grid_value(it[ax], it[ay], it[az], value);
50888
+
50889
+ if(value > maxValue) maxValue = value;
50890
+ idx++;
50891
+ }
50892
+ }
50893
+ }
50894
+
50895
+ /*
50896
+ if (expand_symmetry && nsymbt > 0) {
50897
+ const u8view = new Uint8Array(buf);
50898
+ for (let i = 0; i+80 <= nsymbt; i += 80) {
50899
+ let j;
50900
+ let symop = '';
50901
+ for (j = 0; j < 80; ++j) {
50902
+ symop += String.fromCharCode(u8view[1024 + i + j]);
50903
+ }
50904
+ if (/^\s*x\s*,\s*y\s*,\s*z\s*$/i.test(symop)) continue; // skip x,y,z
50905
+ //console.log('sym ops', symop.trim());
50906
+ let mat = this.parse_symop(symop);
50907
+ // Note: we apply here symops to grid points instead of coordinates.
50908
+ // In the cases we came across it is equivalent, but in general not.
50909
+ for (j = 0; j < 3; ++j) {
50910
+ mat[j][3] = Math.round(mat[j][3] * n_grid[j]) | 0;
50911
+ }
50912
+ idx = (1024 + nsymbt) / nb | 0;
50913
+ let xyz = [0, 0, 0];
50914
+ for (it[2] = start[2]; it[2] < end[2]; it[2]++) { // sections
50915
+ for (it[1] = start[1]; it[1] < end[1]; it[1]++) { // rows
50916
+ for (it[0] = start[0]; it[0] < end[0]; it[0]++) { // cols
50917
+ for (j = 0; j < 3; ++j) {
50918
+ xyz[j] = it[ax] * mat[j][0] + it[ay] * mat[j][1] +
50919
+ it[az] * mat[j][2] + mat[j][3];
50920
+ }
50921
+ let value = b1 * data_view[idx] + b0;
50922
+ grid.set_grid_value(xyz[0], xyz[1], xyz[2], value);
50923
+
50924
+ if(value > maxValue) maxValue = value;
50925
+ idx++;
50926
+ }
50927
+ }
50928
+ }
50929
+ }
50930
+ }
50931
+ */
50932
+
50933
+ if(!bInputSigma) {
50934
+ sigma = ic.dsn6ParserCls.setSigma(maxValue, location, type, sigma);
50935
+ }
50936
+
50937
+ if(type == '2fofc') {
50938
+ ic.mapData.ccp4 = 1;
50939
+ ic.mapData.grid2 = grid;
50940
+ ic.mapData.unit_cell2 = unit_cell;
50941
+ ic.mapData.type2 = type;
50942
+ ic.mapData.sigma2 = sigma;
50943
+ }
50944
+ else {
50945
+ ic.mapData.ccp4 = 1;
50946
+ ic.mapData.grid = grid;
50947
+ ic.mapData.unit_cell = unit_cell;
50948
+ ic.mapData.type = type;
50949
+ ic.mapData.sigma = sigma;
50950
+ }
50951
+
50952
+ return sigma;
50953
+ }
50954
+
50955
+ load_maps_from_mtz_buffer(mtz, type, sigma, location, bInputSigma) { let ic = this.icn3d; ic.icn3dui;
50956
+ let is_diff = (type == 'fofc'); // diff: fofc, non-diff: 2fofc
50957
+ let dataArray = mtz.calculate_map(is_diff);
50958
+
50959
+ let mc = mtz.cell;
50960
+ const unit_cell = new UnitCell(mc.a, mc.b, mc.c, mc.alpha, mc.beta, mc.gamma);
50961
+
50962
+ let maxValue = -999;
50963
+ for(let i = 0, il = dataArray.length; i < il; ++i) {
50964
+ if(dataArray[i] > maxValue) maxValue = dataArray[i];
50965
+ }
50966
+
50967
+ if(!bInputSigma) {
50968
+ sigma = ic.dsn6ParserCls.setSigma(maxValue, location, type, sigma);
50969
+ }
50970
+
50971
+ const grid = new GridArray([mtz.nx, mtz.ny, mtz.nz]);
50972
+ grid.values.set(dataArray);
50973
+
50974
+ if(type == '2fofc') {
50975
+ ic.mapData.ccp4 = 1;
50976
+ ic.mapData.grid2 = grid;
50977
+ ic.mapData.unit_cell2 = unit_cell;
50978
+ ic.mapData.type2 = type;
50979
+ ic.mapData.sigma2 = sigma;
50980
+ }
50981
+ else {
50982
+ ic.mapData.ccp4 = 1;
50983
+ ic.mapData.grid = grid;
50984
+ ic.mapData.unit_cell = unit_cell;
50985
+ ic.mapData.type = type;
50986
+ ic.mapData.sigma = sigma;
50987
+ }
50988
+
50989
+ mtz.delete();
50990
+
50991
+ return sigma;
50992
+ }
50993
+
50994
+ // calculate_stddev(a, offset) {
50995
+ // let sum = 0;
50996
+ // let sq_sum = 0;
50997
+ // const alen = a.length;
50998
+ // for (let i = offset; i < alen; i++) {
50999
+ // sum += a[i];
51000
+ // sq_sum += a[i] * a[i];
51001
+ // }
51002
+ // const mean = sum / (alen - offset);
51003
+ // const variance = sq_sum / (alen - offset) - mean * mean;
51004
+ // return {mean: mean, rms: Math.sqrt(variance)};
51005
+ // }
51006
+
51007
+ parse_symop(symop) {
51008
+ const ops = symop.toLowerCase().replace(/\s+/g, '').split(',');
51009
+ if (ops.length !== 3) throw Error('Unexpected symop: ' + symop);
51010
+ let mat = [];
51011
+ for (let i = 0; i < 3; i++) {
51012
+ const terms = ops[i].split(/(?=[+-])/);
51013
+ let row = [0, 0, 0, 0];
51014
+ for (let j = 0; j < terms.length; j++) {
51015
+ const term = terms[j];
51016
+ const sign = (term[0] === '-' ? -1 : 1);
51017
+ let m = terms[j].match(/^[+-]?([xyz])$/);
51018
+ if (m) {
51019
+ const pos = {x: 0, y: 1, z: 2}[m[1]];
51020
+ row[pos] = sign;
51021
+ } else {
51022
+ m = terms[j].match(/^[+-]?(\d)\/(\d)$/);
51023
+ if (!m) throw Error('What is ' + terms[j] + ' in ' + symop);
51024
+ row[3] = sign * Number(m[1]) / Number(m[2]);
51025
+ }
51026
+ }
51027
+ mat.push(row);
51028
+ }
51029
+ return mat;
51030
+ }
51031
+
51032
+ loadCcp4File(type) {let ic = this.icn3d, me = ic.icn3dui;
51033
+ let thisClass = this;
51034
+
51035
+ let file = $("#" + ic.pre + "dsn6file" + type)[0].files[0];
51036
+ let sigma = $("#" + ic.pre + "dsn6sigma" + type).val();
51037
+ if(!file) {
51038
+ var aaa = 1; //alert("Please select a file before clicking 'Load'");
51039
+ }
51040
+ else {
51041
+ me.utilsCls.checkFileAPI();
51042
+ let reader = new FileReader();
51043
+ reader.onload = function(e) { let ic = thisClass.icn3d;
51044
+ let arrayBuffer = e.target.result; // or = reader.result;
51045
+ sigma = thisClass.load_map_from_buffer(arrayBuffer, type, sigma, 'file');
51046
+
51047
+ // if(type == '2fofc') {
51048
+ // ic.bAjax2fofcCcp4 = true;
51049
+ // }
51050
+ // else if(type == 'fofc') {
51051
+ // ic.bAjaxfofcCcp4 = true;
51052
+ // }
51053
+ ic.setOptionCls.setOption('map', type);
51054
+ me.htmlCls.clickMenuCls.setLogCmd('load map file ' + $("#" + ic.pre + "dsn6file" + type).val() + ' with sigma ' + sigma, false);
51055
+ };
51056
+ reader.readAsArrayBuffer(file);
51057
+ }
51058
+ }
51059
+
51060
+ async loadCcp4FileUrl(type) { let ic = this.icn3d, me = ic.icn3dui;
50532
51061
  let url = $("#" + ic.pre + "dsn6fileurl" + type).val();
50533
51062
  let sigma = $("#" + ic.pre + "dsn6sigmaurl" + type).val();
50534
51063
  if(!url) {
50535
51064
  var aaa = 1; //alert("Please input the file URL before clicking 'Load'");
50536
51065
  }
50537
51066
  else {
50538
- this.dsn6ParserBase(url, type, sigma);
50539
- me.htmlCls.clickMenuCls.setLogCmd('set map ' + type + ' sigma ' + sigma + ' | ' + encodeURIComponent(url), true);
51067
+ sigma = await this.ccp4ParserBase(url, type, sigma, 'file');
51068
+
51069
+ me.htmlCls.clickMenuCls.setLogCmd('set map ' + type + ' sigma ' + sigma + ' file ccp4 | ' + encodeURIComponent(url), true);
51070
+ }
51071
+ }
51072
+
51073
+ // Extract a block of density for calculating an isosurface using the
51074
+ // separate marching cubes implementation.
51075
+ extract_block(grid, unit_cell, radius, center, typeDetail) { let ic = this.icn3d; ic.icn3dui;
51076
+ // let grid = this.grid;
51077
+ // let unit_cell = this.unit_cell;
51078
+ if (grid == null || unit_cell == null) { return; }
51079
+ let fc = unit_cell.fractionalize(center);
51080
+
51081
+ let r = [radius / unit_cell.parameters[0],
51082
+ radius / unit_cell.parameters[1],
51083
+ radius / unit_cell.parameters[2]];
51084
+ let grid_min = grid.frac2grid([fc[0] - r[0], fc[1] - r[1], fc[2] - r[2]]);
51085
+ let grid_max = grid.frac2grid([fc[0] + r[0], fc[1] + r[1], fc[2] + r[2]]);
51086
+
51087
+ let size = [grid_max[0] - grid_min[0] + 1,
51088
+ grid_max[1] - grid_min[1] + 1,
51089
+ grid_max[2] - grid_min[2] + 1];
51090
+ let points = [];
51091
+ let values = [];
51092
+ let threshold = 1;
51093
+ let bAtoms = ic.hAtoms && Object.keys(ic.hAtoms).length > 0;
51094
+ for (let i = grid_min[0]; i <= grid_max[0]; i++) {
51095
+ for (let j = grid_min[1]; j <= grid_max[1]; j++) {
51096
+ for (let k = grid_min[2]; k <= grid_max[2]; k++) {
51097
+ let frac = grid.grid2frac(i, j, k);
51098
+ let orth = unit_cell.orthogonalize(frac);
51099
+ points.push(orth);
51100
+
51101
+ // get overlap between map and atoms
51102
+ let positoin = new THREE.Vector3(orth[0], orth[1], orth[2]);
51103
+ let atomsNear = ic.rayCls.getAtomsFromPosition(positoin, threshold, ic.hAtoms);
51104
+
51105
+ let map_value = (atomsNear || !bAtoms) ? grid.get_grid_value(i, j, k) : 0;
51106
+
51107
+ if(typeDetail == 'fofc_pos' && map_value < 0) map_value = 0;
51108
+ if(typeDetail == 'fofc_neg') map_value = (map_value > 0) ? 0 : -map_value;
51109
+
51110
+ values.push(map_value);
51111
+ }
51112
+ }
51113
+ }
51114
+
51115
+ return {size: size, values: values, points: points};
51116
+ // this.block.set(points, values, size);
51117
+ };
51118
+
51119
+ marchingCubes(dims, values, points, isolevel, method) { let ic = this.icn3d; ic.icn3dui;
51120
+ const edgeTable = new Int32Array([
51121
+ 0x0 , 0x0 , 0x202, 0x302, 0x406, 0x406, 0x604, 0x704,
51122
+ 0x804, 0x805, 0xa06, 0xa06, 0xc0a, 0xd03, 0xe08, 0xf00,
51123
+ 0x90 , 0x98 , 0x292, 0x292, 0x496, 0x49e, 0x694, 0x694,
51124
+ 0x894, 0x894, 0xa96, 0xa96, 0xc9a, 0xc92, 0xe91, 0xe90,
51125
+ 0x230, 0x230, 0x33 , 0x13a, 0x636, 0x636, 0x434, 0x43c,
51126
+ 0xa34, 0xa35, 0x837, 0x936, 0xe3a, 0xf32, 0xc31, 0xd30,
51127
+ 0x2a0, 0x2a8, 0xa3 , 0xaa , 0x6a6, 0x6af, 0x5a4, 0x4ac,
51128
+ 0xaa4, 0xaa4, 0x9a6, 0x8a6, 0xfaa, 0xea3, 0xca1, 0xca0,
51129
+ 0x460, 0x460, 0x662, 0x762, 0x66 , 0x66 , 0x265, 0x364,
51130
+ 0xc64, 0xc65, 0xe66, 0xe66, 0x86a, 0x863, 0xa69, 0xa60,
51131
+ 0x4f0, 0x4f8, 0x6f2, 0x6f2, 0xf6 , 0xfe , 0x2f5, 0x2fc,
51132
+ 0xcf4, 0xcf4, 0xef6, 0xef6, 0x8fa, 0x8f3, 0xaf9, 0xaf0,
51133
+ 0x650, 0x650, 0x453, 0x552, 0x256, 0x256, 0x54 , 0x154,
51134
+ 0xe54, 0xf54, 0xc57, 0xd56, 0xa5a, 0xb52, 0x859, 0x950,
51135
+ 0x7c0, 0x6c1, 0x5c2, 0x4c2, 0x3c6, 0x2ce, 0xc5 , 0xc4 ,
51136
+ 0xfc4, 0xec5, 0xdc6, 0xcc6, 0xbca, 0xac2, 0x8c1, 0x8c0,
51137
+ 0x8c0, 0x8c0, 0xac2, 0xbc2, 0xcc6, 0xcc6, 0xec4, 0xfcc,
51138
+ 0xc4 , 0xc5 , 0x2c6, 0x3c6, 0x4c2, 0x5c2, 0x6c1, 0x7c0,
51139
+ 0x950, 0x859, 0xb52, 0xa5a, 0xd56, 0xc57, 0xe54, 0xe5c,
51140
+ 0x154, 0x54 , 0x25e, 0x256, 0x552, 0x453, 0x658, 0x650,
51141
+ 0xaf0, 0xaf0, 0x8f3, 0x8fa, 0xef6, 0xef6, 0xcf4, 0xcfc,
51142
+ 0x2f4, 0x3f5, 0xff , 0x1f6, 0x6f2, 0x6f3, 0x4f9, 0x5f0,
51143
+ 0xa60, 0xa69, 0x863, 0x86a, 0xe66, 0xe67, 0xd65, 0xc6c,
51144
+ 0x364, 0x265, 0x166, 0x66 , 0x76a, 0x663, 0x460, 0x460,
51145
+ 0xca0, 0xca0, 0xea2, 0xfa2, 0x8a6, 0x8a6, 0xaa4, 0xba4,
51146
+ 0x4ac, 0x5a4, 0x6ae, 0x7a6, 0xaa , 0xa3 , 0x2a8, 0x2a0,
51147
+ 0xd30, 0xc31, 0xf32, 0xe3a, 0x936, 0x837, 0xb35, 0xa34,
51148
+ 0x43c, 0x434, 0x73e, 0x636, 0x13a, 0x33 , 0x339, 0x230,
51149
+ 0xe90, 0xe90, 0xc92, 0xc9a, 0xa96, 0xa96, 0x894, 0x89c,
51150
+ 0x694, 0x695, 0x49f, 0x496, 0x292, 0x392, 0x98 , 0x90 ,
51151
+ 0xf00, 0xe08, 0xd03, 0xc0a, 0xa06, 0xa0e, 0x805, 0x804,
51152
+ 0x704, 0x604, 0x506, 0x406, 0x302, 0x202, 0x0 , 0x0]);
51153
+
51154
+ const segTable = [
51155
+ [],
51156
+ [],
51157
+ [1, 9],
51158
+ [1, 8, 1, 9],
51159
+ [2, 10, 10, 1],
51160
+ [2, 10, 10, 1],
51161
+ [9, 2, 2, 10, 10, 9],
51162
+ [2, 8, 2, 10, 10, 8, 10, 9],
51163
+ [11, 2],
51164
+ [0, 11, 11, 2],
51165
+ [1, 9, 11, 2],
51166
+ [1, 11, 11, 2, 1, 9, 9, 11],
51167
+ [3, 10, 10, 1, 11, 10],
51168
+ [0, 10, 10, 1, 8, 10, 11, 10],
51169
+ [3, 9, 11, 9, 11, 10, 10, 9],
51170
+ [8, 10, 10, 9, 11, 10],
51171
+ [4, 7],
51172
+ [4, 3, 4, 7],
51173
+ [1, 9, 4, 7],
51174
+ [4, 1, 1, 9, 4, 7, 7, 1],
51175
+ [2, 10, 10, 1, 4, 7],
51176
+ [3, 4, 4, 7, 2, 10, 10, 1],
51177
+ [9, 2, 2, 10, 10, 9, 4, 7],
51178
+ [2, 10, 10, 9, 9, 2, 9, 7, 7, 2, 4, 7],
51179
+ [4, 7, 11, 2],
51180
+ [11, 4, 4, 7, 11, 2, 2, 4],
51181
+ [1, 9, 4, 7, 11, 2],
51182
+ [4, 7, 11, 4, 11, 9, 11, 2, 2, 9, 1, 9],
51183
+ [3, 10, 10, 1, 11, 10, 4, 7],
51184
+ [1, 11, 11, 10, 10, 1, 1, 4, 4, 11, 4, 7],
51185
+ [4, 7, 0, 11, 11, 9, 11, 10, 10, 9],
51186
+ [4, 7, 11, 4, 11, 9, 11, 10, 10, 9],
51187
+ [9, 5, 5, 4],
51188
+ [9, 5, 5, 4],
51189
+ [0, 5, 5, 4, 1, 5],
51190
+ [8, 5, 5, 4, 3, 5, 1, 5],
51191
+ [2, 10, 10, 1, 9, 5, 5, 4],
51192
+ [2, 10, 10, 1, 9, 5, 5, 4],
51193
+ [5, 2, 2, 10, 10, 5, 5, 4, 4, 2],
51194
+ [2, 10, 10, 5, 5, 2, 5, 3, 5, 4, 4, 3],
51195
+ [9, 5, 5, 4, 11, 2],
51196
+ [0, 11, 11, 2, 9, 5, 5, 4],
51197
+ [0, 5, 5, 4, 1, 5, 11, 2],
51198
+ [1, 5, 5, 2, 5, 8, 8, 2, 11, 2, 5, 4],
51199
+ [10, 3, 11, 10, 10, 1, 9, 5, 5, 4],
51200
+ [9, 5, 5, 4, 8, 1, 8, 10, 10, 1, 11, 10],
51201
+ [5, 4, 0, 5, 0, 11, 11, 5, 11, 10, 10, 5],
51202
+ [5, 4, 8, 5, 8, 10, 10, 5, 11, 10],
51203
+ [9, 7, 5, 7, 9, 5],
51204
+ [9, 3, 9, 5, 5, 3, 5, 7],
51205
+ [0, 7, 1, 7, 1, 5, 5, 7],
51206
+ [1, 5, 5, 3, 5, 7],
51207
+ [9, 7, 9, 5, 5, 7, 10, 1, 2, 10],
51208
+ [10, 1, 2, 10, 9, 5, 5, 0, 5, 3, 5, 7],
51209
+ [2, 8, 2, 5, 5, 8, 5, 7, 10, 5, 2, 10],
51210
+ [2, 10, 10, 5, 5, 2, 5, 3, 5, 7],
51211
+ [7, 9, 9, 5, 5, 7, 11, 2],
51212
+ [9, 5, 5, 7, 7, 9, 7, 2, 2, 9, 11, 2],
51213
+ [11, 2, 1, 8, 1, 7, 1, 5, 5, 7],
51214
+ [11, 2, 1, 11, 1, 7, 1, 5, 5, 7],
51215
+ [9, 5, 5, 8, 5, 7, 10, 1, 3, 10, 11, 10],
51216
+ [5, 7, 7, 0, 0, 5, 9, 5, 11, 0, 0, 10, 10, 1, 11, 10],
51217
+ [11, 10, 10, 0, 0, 11, 10, 5, 5, 0, 0, 7, 5, 7],
51218
+ [11, 10, 10, 5, 5, 11, 5, 7],
51219
+ [10, 6, 6, 5, 5, 10],
51220
+ [5, 10, 10, 6, 6, 5],
51221
+ [1, 9, 5, 10, 10, 6, 6, 5],
51222
+ [1, 8, 1, 9, 5, 10, 10, 6, 6, 5],
51223
+ [1, 6, 6, 5, 5, 1, 2, 6],
51224
+ [1, 6, 6, 5, 5, 1, 2, 6],
51225
+ [9, 6, 6, 5, 5, 9, 0, 6, 2, 6],
51226
+ [5, 9, 8, 5, 8, 2, 2, 5, 2, 6, 6, 5],
51227
+ [11, 2, 10, 6, 6, 5, 5, 10],
51228
+ [11, 0, 11, 2, 10, 6, 6, 5, 5, 10],
51229
+ [1, 9, 11, 2, 5, 10, 10, 6, 6, 5],
51230
+ [5, 10, 10, 6, 6, 5, 1, 9, 9, 2, 9, 11, 11, 2],
51231
+ [6, 3, 11, 6, 6, 5, 5, 3, 5, 1],
51232
+ [11, 0, 11, 5, 5, 0, 5, 1, 11, 6, 6, 5],
51233
+ [11, 6, 6, 3, 6, 0, 6, 5, 5, 0, 5, 9],
51234
+ [6, 5, 5, 9, 9, 6, 9, 11, 11, 6],
51235
+ [5, 10, 10, 6, 6, 5, 4, 7],
51236
+ [4, 3, 4, 7, 6, 5, 5, 10, 10, 6],
51237
+ [1, 9, 5, 10, 10, 6, 6, 5, 4, 7],
51238
+ [10, 6, 6, 5, 5, 10, 1, 9, 9, 7, 7, 1, 4, 7],
51239
+ [6, 1, 2, 6, 6, 5, 5, 1, 4, 7],
51240
+ [2, 5, 5, 1, 2, 6, 6, 5, 4, 3, 4, 7],
51241
+ [4, 7, 0, 5, 5, 9, 0, 6, 6, 5, 2, 6],
51242
+ [3, 9, 9, 7, 4, 7, 2, 9, 5, 9, 9, 6, 6, 5, 2, 6],
51243
+ [11, 2, 4, 7, 10, 6, 6, 5, 5, 10],
51244
+ [5, 10, 10, 6, 6, 5, 4, 7, 7, 2, 2, 4, 11, 2],
51245
+ [1, 9, 4, 7, 11, 2, 5, 10, 10, 6, 6, 5],
51246
+ [9, 2, 1, 9, 9, 11, 11, 2, 4, 11, 4, 7, 5, 10, 10, 6, 6, 5],
51247
+ [4, 7, 11, 5, 5, 3, 5, 1, 11, 6, 6, 5],
51248
+ [5, 1, 1, 11, 11, 5, 11, 6, 6, 5, 0, 11, 11, 4, 4, 7],
51249
+ [0, 5, 5, 9, 0, 6, 6, 5, 3, 6, 11, 6, 4, 7],
51250
+ [6, 5, 5, 9, 9, 6, 9, 11, 11, 6, 4, 7, 7, 9],
51251
+ [10, 4, 9, 10, 6, 4, 10, 6],
51252
+ [4, 10, 10, 6, 6, 4, 9, 10],
51253
+ [10, 0, 1, 10, 10, 6, 6, 0, 6, 4],
51254
+ [1, 8, 1, 6, 6, 8, 6, 4, 1, 10, 10, 6],
51255
+ [1, 4, 9, 1, 2, 4, 2, 6, 6, 4],
51256
+ [2, 9, 9, 1, 2, 4, 2, 6, 6, 4],
51257
+ [2, 4, 2, 6, 6, 4],
51258
+ [2, 8, 2, 4, 2, 6, 6, 4],
51259
+ [10, 4, 9, 10, 10, 6, 6, 4, 11, 2],
51260
+ [8, 2, 11, 2, 9, 10, 10, 4, 10, 6, 6, 4],
51261
+ [11, 2, 1, 6, 6, 0, 6, 4, 1, 10, 10, 6],
51262
+ [6, 4, 4, 1, 1, 6, 1, 10, 10, 6, 8, 1, 1, 11, 11, 2],
51263
+ [9, 6, 6, 4, 9, 3, 3, 6, 9, 1, 11, 6],
51264
+ [11, 1, 1, 8, 11, 6, 6, 1, 9, 1, 1, 4, 6, 4],
51265
+ [11, 6, 6, 3, 6, 0, 6, 4],
51266
+ [6, 4, 8, 6, 11, 6],
51267
+ [7, 10, 10, 6, 6, 7, 8, 10, 9, 10],
51268
+ [0, 7, 0, 10, 10, 7, 9, 10, 6, 7, 10, 6],
51269
+ [10, 6, 6, 7, 7, 10, 1, 10, 7, 1, 8, 1],
51270
+ [10, 6, 6, 7, 7, 10, 7, 1, 1, 10],
51271
+ [2, 6, 6, 1, 6, 8, 8, 1, 9, 1, 6, 7],
51272
+ [2, 6, 6, 9, 9, 2, 9, 1, 6, 7, 7, 9, 9, 3],
51273
+ [0, 7, 0, 6, 6, 7, 2, 6],
51274
+ [2, 7, 6, 7, 2, 6],
51275
+ [11, 2, 10, 6, 6, 8, 8, 10, 9, 10, 6, 7],
51276
+ [0, 7, 7, 2, 11, 2, 9, 7, 6, 7, 7, 10, 10, 6, 9, 10],
51277
+ [1, 8, 1, 7, 1, 10, 10, 7, 6, 7, 10, 6, 11, 2],
51278
+ [11, 2, 1, 11, 1, 7, 10, 6, 6, 1, 1, 10, 6, 7],
51279
+ [9, 6, 6, 8, 6, 7, 9, 1, 1, 6, 11, 6, 6, 3],
51280
+ [9, 1, 11, 6, 6, 7],
51281
+ [0, 7, 0, 6, 6, 7, 11, 0, 11, 6],
51282
+ [11, 6, 6, 7],
51283
+ [7, 6, 6, 11],
51284
+ [7, 6, 6, 11],
51285
+ [1, 9, 7, 6, 6, 11],
51286
+ [8, 1, 1, 9, 7, 6, 6, 11],
51287
+ [10, 1, 2, 10, 6, 11, 7, 6],
51288
+ [2, 10, 10, 1, 6, 11, 7, 6],
51289
+ [2, 9, 2, 10, 10, 9, 6, 11, 7, 6],
51290
+ [6, 11, 7, 6, 2, 10, 10, 3, 10, 8, 10, 9],
51291
+ [7, 2, 6, 2, 7, 6],
51292
+ [7, 0, 7, 6, 6, 0, 6, 2],
51293
+ [2, 7, 7, 6, 6, 2, 1, 9],
51294
+ [1, 6, 6, 2, 1, 8, 8, 6, 1, 9, 7, 6],
51295
+ [10, 7, 7, 6, 6, 10, 10, 1, 1, 7],
51296
+ [10, 7, 7, 6, 6, 10, 1, 7, 10, 1, 1, 8],
51297
+ [7, 0, 7, 10, 10, 0, 10, 9, 6, 10, 7, 6],
51298
+ [7, 6, 6, 10, 10, 7, 10, 8, 10, 9],
51299
+ [6, 8, 4, 6, 6, 11],
51300
+ [3, 6, 6, 11, 0, 6, 4, 6],
51301
+ [8, 6, 6, 11, 4, 6, 1, 9],
51302
+ [4, 6, 6, 9, 6, 3, 3, 9, 1, 9, 6, 11],
51303
+ [6, 8, 4, 6, 6, 11, 2, 10, 10, 1],
51304
+ [2, 10, 10, 1, 0, 11, 0, 6, 6, 11, 4, 6],
51305
+ [4, 11, 4, 6, 6, 11, 2, 9, 2, 10, 10, 9],
51306
+ [10, 9, 9, 3, 3, 10, 2, 10, 4, 3, 3, 6, 6, 11, 4, 6],
51307
+ [8, 2, 4, 2, 4, 6, 6, 2],
51308
+ [4, 2, 4, 6, 6, 2],
51309
+ [1, 9, 3, 4, 4, 2, 4, 6, 6, 2],
51310
+ [1, 9, 4, 1, 4, 2, 4, 6, 6, 2],
51311
+ [8, 1, 8, 6, 6, 1, 4, 6, 6, 10, 10, 1],
51312
+ [10, 1, 0, 10, 0, 6, 6, 10, 4, 6],
51313
+ [4, 6, 6, 3, 3, 4, 6, 10, 10, 3, 3, 9, 10, 9],
51314
+ [10, 9, 4, 10, 6, 10, 4, 6],
51315
+ [9, 5, 5, 4, 7, 6, 6, 11],
51316
+ [9, 5, 5, 4, 7, 6, 6, 11],
51317
+ [5, 0, 1, 5, 5, 4, 7, 6, 6, 11],
51318
+ [7, 6, 6, 11, 3, 4, 3, 5, 5, 4, 1, 5],
51319
+ [9, 5, 5, 4, 10, 1, 2, 10, 7, 6, 6, 11],
51320
+ [6, 11, 7, 6, 2, 10, 10, 1, 9, 5, 5, 4],
51321
+ [7, 6, 6, 11, 5, 4, 4, 10, 10, 5, 4, 2, 2, 10],
51322
+ [3, 4, 3, 5, 5, 4, 2, 5, 10, 5, 2, 10, 7, 6, 6, 11],
51323
+ [7, 2, 7, 6, 6, 2, 5, 4, 9, 5],
51324
+ [9, 5, 5, 4, 8, 6, 6, 0, 6, 2, 7, 6],
51325
+ [3, 6, 6, 2, 7, 6, 1, 5, 5, 0, 5, 4],
51326
+ [6, 2, 2, 8, 8, 6, 7, 6, 1, 8, 8, 5, 5, 4, 1, 5],
51327
+ [9, 5, 5, 4, 10, 1, 1, 6, 6, 10, 1, 7, 7, 6],
51328
+ [1, 6, 6, 10, 10, 1, 1, 7, 7, 6, 0, 7, 9, 5, 5, 4],
51329
+ [0, 10, 10, 4, 10, 5, 5, 4, 3, 10, 6, 10, 10, 7, 7, 6],
51330
+ [7, 6, 6, 10, 10, 7, 10, 8, 5, 4, 4, 10, 10, 5],
51331
+ [6, 9, 9, 5, 5, 6, 6, 11, 11, 9],
51332
+ [3, 6, 6, 11, 0, 6, 0, 5, 5, 6, 9, 5],
51333
+ [0, 11, 0, 5, 5, 11, 1, 5, 5, 6, 6, 11],
51334
+ [6, 11, 3, 6, 3, 5, 5, 6, 1, 5],
51335
+ [2, 10, 10, 1, 9, 5, 5, 11, 11, 9, 5, 6, 6, 11],
51336
+ [0, 11, 0, 6, 6, 11, 9, 6, 5, 6, 9, 5, 2, 10, 10, 1],
51337
+ [8, 5, 5, 11, 5, 6, 6, 11, 0, 5, 10, 5, 5, 2, 2, 10],
51338
+ [6, 11, 3, 6, 3, 5, 5, 6, 2, 10, 10, 3, 10, 5],
51339
+ [5, 8, 9, 5, 5, 2, 2, 8, 5, 6, 6, 2],
51340
+ [9, 5, 5, 6, 6, 9, 6, 0, 6, 2],
51341
+ [1, 5, 5, 8, 8, 1, 5, 6, 6, 8, 8, 2, 6, 2],
51342
+ [1, 5, 5, 6, 6, 1, 6, 2],
51343
+ [3, 6, 6, 1, 6, 10, 10, 1, 8, 6, 5, 6, 6, 9, 9, 5],
51344
+ [10, 1, 0, 10, 0, 6, 6, 10, 9, 5, 5, 0, 5, 6],
51345
+ [5, 6, 6, 10, 10, 5],
51346
+ [10, 5, 5, 6, 6, 10],
51347
+ [11, 5, 5, 10, 10, 11, 7, 5],
51348
+ [11, 5, 5, 10, 10, 11, 7, 5],
51349
+ [5, 11, 7, 5, 5, 10, 10, 11, 1, 9],
51350
+ [10, 7, 7, 5, 5, 10, 10, 11, 8, 1, 1, 9],
51351
+ [11, 1, 2, 11, 7, 1, 7, 5, 5, 1],
51352
+ [2, 7, 7, 1, 7, 5, 5, 1, 2, 11],
51353
+ [9, 7, 7, 5, 5, 9, 9, 2, 2, 7, 2, 11],
51354
+ [7, 5, 5, 2, 2, 7, 2, 11, 5, 9, 9, 2, 2, 8],
51355
+ [2, 5, 5, 10, 10, 2, 3, 5, 7, 5],
51356
+ [8, 2, 8, 5, 5, 2, 7, 5, 10, 2, 5, 10],
51357
+ [1, 9, 5, 10, 10, 3, 3, 5, 7, 5, 10, 2],
51358
+ [8, 2, 2, 9, 1, 9, 7, 2, 10, 2, 2, 5, 5, 10, 7, 5],
51359
+ [3, 5, 5, 1, 7, 5],
51360
+ [7, 0, 7, 1, 7, 5, 5, 1],
51361
+ [3, 9, 3, 5, 5, 9, 7, 5],
51362
+ [7, 9, 5, 9, 7, 5],
51363
+ [5, 8, 4, 5, 5, 10, 10, 8, 10, 11],
51364
+ [5, 0, 4, 5, 5, 11, 11, 0, 5, 10, 10, 11],
51365
+ [1, 9, 4, 10, 10, 8, 10, 11, 4, 5, 5, 10],
51366
+ [10, 11, 11, 4, 4, 10, 4, 5, 5, 10, 3, 4, 4, 1, 1, 9],
51367
+ [2, 5, 5, 1, 2, 8, 8, 5, 2, 11, 4, 5],
51368
+ [4, 11, 11, 0, 4, 5, 5, 11, 2, 11, 11, 1, 5, 1],
51369
+ [2, 5, 5, 0, 5, 9, 2, 11, 11, 5, 4, 5, 5, 8],
51370
+ [4, 5, 5, 9, 2, 11],
51371
+ [2, 5, 5, 10, 10, 2, 3, 5, 3, 4, 4, 5],
51372
+ [5, 10, 10, 2, 2, 5, 2, 4, 4, 5],
51373
+ [3, 10, 10, 2, 3, 5, 5, 10, 8, 5, 4, 5, 1, 9],
51374
+ [5, 10, 10, 2, 2, 5, 2, 4, 4, 5, 1, 9, 9, 2],
51375
+ [4, 5, 5, 8, 5, 3, 5, 1],
51376
+ [4, 5, 5, 0, 5, 1],
51377
+ [4, 5, 5, 8, 5, 3, 0, 5, 5, 9],
51378
+ [4, 5, 5, 9],
51379
+ [4, 11, 7, 4, 9, 11, 9, 10, 10, 11],
51380
+ [9, 7, 7, 4, 9, 11, 9, 10, 10, 11],
51381
+ [1, 10, 10, 11, 11, 1, 11, 4, 4, 1, 7, 4],
51382
+ [1, 4, 4, 3, 1, 10, 10, 4, 7, 4, 4, 11, 10, 11],
51383
+ [4, 11, 7, 4, 9, 11, 9, 2, 2, 11, 9, 1],
51384
+ [9, 7, 7, 4, 9, 11, 9, 1, 1, 11, 2, 11],
51385
+ [7, 4, 4, 11, 4, 2, 2, 11],
51386
+ [7, 4, 4, 11, 4, 2, 2, 11, 3, 4],
51387
+ [2, 9, 9, 10, 10, 2, 2, 7, 7, 9, 7, 4],
51388
+ [9, 10, 10, 7, 7, 9, 7, 4, 10, 2, 2, 7, 7, 0],
51389
+ [7, 10, 10, 3, 10, 2, 7, 4, 4, 10, 1, 10, 10, 0],
51390
+ [1, 10, 10, 2, 7, 4],
51391
+ [9, 1, 1, 4, 1, 7, 7, 4],
51392
+ [9, 1, 1, 4, 1, 7, 7, 4, 8, 1],
51393
+ [3, 4, 7, 4],
51394
+ [7, 4],
51395
+ [9, 10, 10, 8, 10, 11],
51396
+ [9, 3, 9, 11, 9, 10, 10, 11],
51397
+ [1, 10, 10, 0, 10, 8, 10, 11],
51398
+ [1, 10, 10, 3, 10, 11],
51399
+ [2, 11, 11, 1, 11, 9, 9, 1],
51400
+ [9, 3, 9, 11, 2, 9, 9, 1, 2, 11],
51401
+ [2, 11, 11, 0],
51402
+ [2, 11],
51403
+ [8, 2, 8, 10, 10, 2, 9, 10],
51404
+ [9, 10, 10, 2, 2, 9],
51405
+ [8, 2, 8, 10, 10, 2, 1, 8, 1, 10],
51406
+ [1, 10, 10, 2],
51407
+ [8, 1, 9, 1],
51408
+ [9, 1],
51409
+ [],
51410
+ []];
51411
+
51412
+ const snap = (method === 'snapped MC');
51413
+ // const seg_table = (method === 'squarish' ? segTable2 : segTable);
51414
+ const seg_table = segTable;
51415
+
51416
+ let vlist = new Array(12);
51417
+ const vert_offsets = this.calculateVertOffsets(dims);
51418
+
51419
+ const edgeIndex = [[0,1], [1,2], [2,3], [3,0], [4,5], [5,6],
51420
+ [6,7], [7,4], [0,4], [1,5], [2,6], [3,7]];
51421
+
51422
+ let vertex_values = new Float32Array(8);
51423
+ let p0 = [0, 0, 0]; // unused initial value - to make Flow happy
51424
+ let vertex_points = [p0, p0, p0, p0, p0, p0, p0, p0];
51425
+ const size_x = dims[0];
51426
+ const size_y = dims[1];
51427
+ const size_z = dims[2];
51428
+ if (values == null || points == null) return;
51429
+ let vertices = [];
51430
+ let segments = [];
51431
+ let vertex_count = 0;
51432
+ for (let x = 0; x < size_x - 1; x++) {
51433
+ for (let y = 0; y < size_y - 1; y++) {
51434
+ for (let z = 0; z < size_z - 1; z++) {
51435
+ const offset0 = z + size_z * (y + size_y * x);
51436
+ let cubeindex = 0;
51437
+ let i;
51438
+ let j;
51439
+ for (i = 0; i < 8; ++i) {
51440
+ j = offset0 + vert_offsets[i];
51441
+ cubeindex |= (values[j] < isolevel) ? 1 << i : 0;
51442
+ }
51443
+ if (cubeindex === 0 || cubeindex === 255) continue;
51444
+ for (i = 0; i < 8; ++i) {
51445
+ j = offset0 + vert_offsets[i];
51446
+ vertex_values[i] = values[j];
51447
+ vertex_points[i] = points[j];
51448
+ }
51449
+
51450
+ // 12 bit number, indicates which edges are crossed by the isosurface
51451
+ const edge_mask = edgeTable[cubeindex];
51452
+
51453
+ // check which edges are crossed, and estimate the point location
51454
+ // using a weighted average of scalar values at edge endpoints.
51455
+ for (i = 0; i < 12; ++i) {
51456
+ if ((edge_mask & (1 << i)) !== 0) {
51457
+ const e = edgeIndex[i];
51458
+ let mu = (isolevel - vertex_values[e[0]]) /
51459
+ (vertex_values[e[1]] - vertex_values[e[0]]);
51460
+ if (snap === true) {
51461
+ if (mu > 0.85) mu = 1;
51462
+ else if (mu < 0.15) mu = 0;
51463
+ }
51464
+ const p1 = vertex_points[e[0]];
51465
+ const p2 = vertex_points[e[1]];
51466
+ // The number of added vertices could be roughly halved
51467
+ // if we avoided duplicates between neighbouring cells.
51468
+ // Using a map for lookups is too slow, perhaps a big
51469
+ // array would do?
51470
+ vertices.push(p1[0] + (p2[0] - p1[0]) * mu,
51471
+ p1[1] + (p2[1] - p1[1]) * mu,
51472
+ p1[2] + (p2[2] - p1[2]) * mu);
51473
+ vlist[i] = vertex_count++;
51474
+ }
51475
+ }
51476
+ const t = seg_table[cubeindex];
51477
+ for (i = 0; i < t.length; i++) {
51478
+ segments.push(vlist[t[i]]);
51479
+ }
51480
+ }
51481
+ }
51482
+ }
51483
+
51484
+ return { vertices: vertices, segments: segments };
51485
+ }
51486
+
51487
+ // return offsets relative to vertex [0,0,0]
51488
+ calculateVertOffsets(dims) { let ic = this.icn3d; ic.icn3dui;
51489
+ let vert_offsets = [];
51490
+ const cubeVerts = [[0,0,0], [1,0,0], [1,1,0], [0,1,0],
51491
+ [0,0,1], [1,0,1], [1,1,1], [0,1,1]];
51492
+
51493
+ for (let i = 0; i < 8; ++i) {
51494
+ const v = cubeVerts[i];
51495
+ vert_offsets.push(v[0] + dims[2] * (v[1] + dims[1] * v[2]));
51496
+ }
51497
+ return vert_offsets;
51498
+ }
51499
+
51500
+ makeChickenWire(data, typeDetail) { let ic = this.icn3d, me = ic.icn3dui;
51501
+ let geom = new THREE.BufferGeometry();
51502
+ let position = new Float32Array(data.vertices);
51503
+ geom.setAttribute('position', new THREE.BufferAttribute(position, 3));
51504
+
51505
+ // Although almost all browsers support OES_element_index_uint nowadays,
51506
+ // use Uint32 indexes only when needed.
51507
+ let arr = (data.vertices.length < 3*65536 ? new Uint16Array(data.segments) : new Uint32Array(data.segments));
51508
+
51509
+ geom.setIndex(new THREE.BufferAttribute(arr, 1));
51510
+
51511
+ let colorFor2fofc = me.parasCls.thr('#00FFFF');
51512
+ let colorForfofcPos = me.parasCls.thr('#00FF00');
51513
+ let colorForfofcNeg = me.parasCls.thr('#ff0000');
51514
+
51515
+ let color = (typeDetail == '2fofc') ? colorFor2fofc : ((typeDetail == 'fofc_pos') ? colorForfofcPos : colorForfofcNeg);
51516
+ let material = new THREE.LineBasicMaterial({ linewidth: 1, color: color });
51517
+ //return new THREE.LineSegments(geom, material);
51518
+
51519
+ let mesh = new THREE.LineSegments(geom, material);
51520
+ ic.mdl.add(mesh);
51521
+
51522
+ ic.prevMaps.push(mesh);
51523
+ }
51524
+ }
51525
+
51526
+
51527
+ class UnitCell {
51528
+ /*::
51529
+ parameters: number[]
51530
+ orth: number[]
51531
+ frac: number[]
51532
+ */
51533
+ // eslint-disable-next-line max-params
51534
+ constructor(a /*:number*/, b /*:number*/, c /*:number*/,
51535
+ alpha /*:number*/, beta /*:number*/, gamma /*:number*/) {
51536
+ if (a <= 0 || b <= 0 || c <= 0 || alpha <= 0 || beta <= 0 || gamma <= 0) {
51537
+ throw Error('Zero or negative unit cell parameter(s).');
51538
+ }
51539
+ this.parameters = [a, b, c, alpha, beta, gamma];
51540
+ const deg2rad = Math.PI / 180.0;
51541
+ const cos_alpha = Math.cos(deg2rad * alpha);
51542
+ const cos_beta = Math.cos(deg2rad * beta);
51543
+ const cos_gamma = Math.cos(deg2rad * gamma);
51544
+ const sin_alpha = Math.sin(deg2rad * alpha);
51545
+ const sin_beta = Math.sin(deg2rad * beta);
51546
+ const sin_gamma = Math.sin(deg2rad * gamma);
51547
+ if (sin_alpha === 0 || sin_beta === 0 || sin_gamma === 0) {
51548
+ throw Error('Impossible angle - N*180deg.');
51549
+ }
51550
+ const cos_alpha_star_sin_beta = (cos_beta * cos_gamma - cos_alpha) /
51551
+ sin_gamma;
51552
+ const cos_alpha_star = cos_alpha_star_sin_beta / sin_beta;
51553
+ const s1rca2 = Math.sqrt(1.0 - cos_alpha_star * cos_alpha_star);
51554
+ // The orthogonalization matrix we use is described in ITfC B p.262:
51555
+ // "An alternative mode of orthogonalization, used by the Protein
51556
+ // Data Bank and most programs, is to align the a1 axis of the unit
51557
+ // cell with the Cartesian X_1 axis, and to align the a*_3 axis with the
51558
+ // Cartesian X_3 axis."
51559
+ //
51560
+ // Zeros in the matrices below are kept to make matrix multiplication
51561
+ // faster: they make extract_block() 2x (!) faster on V8 4.5.103,
51562
+ // no difference on FF 50.
51563
+ /* eslint-disable no-multi-spaces, comma-spacing */
51564
+ this.orth = [a, b * cos_gamma, c * cos_beta,
51565
+ 0.0, b * sin_gamma, -c * cos_alpha_star_sin_beta,
51566
+ 0.0, 0.0 , c * sin_beta * s1rca2];
51567
+ // based on xtal.js which is based on cctbx.uctbx
51568
+ this.frac = [
51569
+ 1.0 / a,
51570
+ -cos_gamma / (sin_gamma * a),
51571
+ -(cos_gamma * cos_alpha_star_sin_beta + cos_beta * sin_gamma) /
51572
+ (sin_beta * s1rca2 * sin_gamma * a),
51573
+ 0.0,
51574
+ 1.0 / (sin_gamma * b),
51575
+ cos_alpha_star / (s1rca2 * sin_gamma * b),
51576
+ 0.0,
51577
+ 0.0,
51578
+ 1.0 / (sin_beta * s1rca2 * c),
51579
+ ];
51580
+ }
51581
+
51582
+ // This function is only used with matrices frac and orth, which have 3 zeros.
51583
+ // We skip these elements, but it doesn't affect performance (on FF50 and V8).
51584
+ multiply(xyz, mat) {
51585
+ /* eslint-disable indent */
51586
+ return [mat[0] * xyz[0] + mat[1] * xyz[1] + mat[2] * xyz[2],
51587
+ /*mat[3] * xyz[0]*/+ mat[4] * xyz[1] + mat[5] * xyz[2],
51588
+ /*mat[6] * xyz[0] + mat[7] * xyz[1]*/+ mat[8] * xyz[2]];
51589
+ }
51590
+
51591
+ fractionalize(xyz /*:[number,number,number]*/) {
51592
+ return this.multiply(xyz, this.frac);
51593
+ }
51594
+
51595
+ orthogonalize(xyz /*:[number,number,number]*/) {
51596
+ return this.multiply(xyz, this.orth);
51597
+ }
51598
+ }
51599
+
51600
+
51601
+ class GridArray {
51602
+ /*::
51603
+ dim: number[]
51604
+ values: Float32Array
51605
+ */
51606
+ constructor(dim /*:number[]*/) {
51607
+ this.dim = dim; // dimensions of the grid for the entire unit cell
51608
+ this.values = new Float32Array(dim[0] * dim[1] * dim[2]);
51609
+ }
51610
+
51611
+ modulo(a, b) {
51612
+ const reminder = a % b;
51613
+ return reminder >= 0 ? reminder : reminder + b;
51614
+ }
51615
+
51616
+ grid2index(i/*:number*/, j/*:number*/, k/*:number*/) {
51617
+ i = this.modulo(i, this.dim[0]);
51618
+ j = this.modulo(j, this.dim[1]);
51619
+ k = this.modulo(k, this.dim[2]);
51620
+ return this.dim[2] * (this.dim[1] * i + j) + k;
51621
+ }
51622
+
51623
+ grid2index_unchecked(i/*:number*/, j/*:number*/, k/*:number*/) {
51624
+ return this.dim[2] * (this.dim[1] * i + j) + k;
51625
+ }
51626
+
51627
+ grid2frac(i/*:number*/, j/*:number*/, k/*:number*/) {
51628
+ return [i / this.dim[0], j / this.dim[1], k / this.dim[2]];
51629
+ }
51630
+
51631
+ // return grid coordinates (rounded down) for the given fractional coordinates
51632
+ frac2grid(xyz/*:number[]*/) {
51633
+ // at one point "| 0" here made extract_block() 40% faster on V8 3.14,
51634
+ // but I don't see any effect now
51635
+ return [Math.floor(xyz[0] * this.dim[0]) | 0,
51636
+ Math.floor(xyz[1] * this.dim[1]) | 0,
51637
+ Math.floor(xyz[2] * this.dim[2]) | 0];
51638
+ }
51639
+
51640
+ set_grid_value(i/*:number*/, j/*:number*/, k/*:number*/, value/*:number*/) {
51641
+ const idx = this.grid2index(i, j, k);
51642
+ this.values[idx] = value;
51643
+ }
51644
+
51645
+ get_grid_value(i/*:number*/, j/*:number*/, k/*:number*/) {
51646
+ const idx = this.grid2index(i, j, k);
51647
+ return this.values[idx];
51648
+ }
51649
+ }
51650
+
51651
+ /**
51652
+ * @file Mtz Parser
51653
+ * @author Marcin Wojdyr <wojdyr@gmail.com>
51654
+ * @private
51655
+ * Modified by Jiyao Wang / https://github.com/ncbi/icn3d
51656
+ */
51657
+
51658
+ class MtzParser {
51659
+ constructor(icn3d) {
51660
+ this.icn3d = icn3d;
51661
+ }
51662
+
51663
+ async mtzParserBase(url, type, sigma, location, bInputSigma) { let ic = this.icn3d, me = ic.icn3dui;
51664
+ let thisClass = this;
51665
+
51666
+ //https://stackoverflow.com/questions/33902299/using-jquery-ajax-to-download-a-binary-file
51667
+ // if(type == '2fofc' && ic.bAjax2fofcccp4) {
51668
+ // ic.mapData.sigma2 = sigma;
51669
+ // ic.setOptionCls.setOption('map', type);
51670
+ // }
51671
+ // else if(type == 'fofc' && ic.bAjaxfofcccp4) {
51672
+ // ic.mapData.sigma = sigma;
51673
+ // ic.setOptionCls.setOption('map', type);
51674
+ // }
51675
+ // else {
51676
+ let arrayBuffer = await me.getXMLHttpRqstPromise(url, 'GET', 'arraybuffer', '');
51677
+ sigma = await thisClass.loadMtzFileBase(arrayBuffer, type, sigma, location, bInputSigma, url);
51678
+
51679
+ // if(type == '2fofc') {
51680
+ // ic.bAjax2fofcccp4 = true;
51681
+ // }
51682
+ // else if(type == 'fofc') {
51683
+ // ic.bAjaxfofcccp4 = true;
51684
+ // }
51685
+
51686
+ ic.setOptionCls.setOption('map', type);
51687
+
51688
+ return sigma;
51689
+ // }
51690
+ }
51691
+
51692
+ loadMtzFile(type) {var ic = this.icn3d, me = ic.icn3dui;
51693
+ let thisClass = this;
51694
+
51695
+ let file = $("#" + ic.pre + "dsn6file" + type)[0].files[0];
51696
+ let sigma = $("#" + ic.pre + "dsn6sigma" + type).val();
51697
+ if(!file) {
51698
+ var aaa = 1; //alert("Please select a file before clicking 'Load'");
51699
+ }
51700
+ else {
51701
+ me.utilsCls.checkFileAPI();
51702
+ let reader = new FileReader();
51703
+ reader.onload = async function(e) { let ic = thisClass.icn3d;
51704
+ sigma = await thisClass.loadMtzFileBase(e.target.result, type, sigma, 'file');
51705
+ me.htmlCls.clickMenuCls.setLogCmd('load map file ' + $("#" + ic.pre + "dsn6file" + type).val() + ' with sigma ' + sigma, false);
51706
+ };
51707
+ reader.readAsArrayBuffer(file);
51708
+ }
51709
+ }
51710
+
51711
+ async loadMtzFileBase(data, type, sigma, location, bInputSigma, url) {var ic = this.icn3d, me = ic.icn3dui;
51712
+ if(ic.bMtz === undefined) {
51713
+ let url = "./script/mtz.js";
51714
+ await me.getAjaxPromise(url, 'script');
51715
+
51716
+ ic.bMtz = true;
51717
+ }
51718
+
51719
+ GemmiMtz().then(function(Gemmi) {
51720
+ let mtz = Gemmi.readMtz(data);
51721
+
51722
+ sigma = ic.ccp4ParserCls.load_maps_from_mtz_buffer(mtz, type, sigma, location, bInputSigma);
51723
+
51724
+ // if(type == '2fofc') {
51725
+ // ic.bAjax2fofcCcp4 = true;
51726
+ // }
51727
+ // else if(type == 'fofc') {
51728
+ // ic.bAjaxfofcCcp4 = true;
51729
+ // }
51730
+ ic.setOptionCls.setOption('map', type);
51731
+ if(url) me.htmlCls.clickMenuCls.setLogCmd('set map ' + type + ' sigma ' + sigma + ' file mtz | ' + encodeURIComponent(url), true);
51732
+
51733
+ return sigma;
51734
+ });
51735
+ }
51736
+
51737
+ async loadMtzFileUrl(type) {var ic = this.icn3d; ic.icn3dui;
51738
+ let url = $("#" + ic.pre + "dsn6fileurl" + type).val();
51739
+ let sigma = $("#" + ic.pre + "dsn6sigmaurl" + type).val();
51740
+ if(!url) {
51741
+ var aaa = 1; //alert("Please input the file URL before clicking 'Load'");
51742
+ }
51743
+ else {
51744
+ sigma = await this.mtzParserBase(url, type, sigma, 'url');
51745
+
51746
+ console.log("### sigma " + sigma);
51747
+ //me.htmlCls.clickMenuCls.setLogCmd('set map ' + type + ' sigma ' + sigma + ' file mtz | ' + encodeURIComponent(url), true);
50540
51748
  }
50541
51749
  }
50542
51750
 
@@ -53308,7 +54516,7 @@ class DensityCifParser {
53308
54516
  this.icn3d = icn3d;
53309
54517
  }
53310
54518
 
53311
- async densityCifParser(pdbid, type, sigma, emd) { let ic = this.icn3d, me = ic.icn3dui;
54519
+ async densityCifParser(pdbid, type, sigma, emd, bOutput) { let ic = this.icn3d, me = ic.icn3dui;
53312
54520
  let thisClass = this;
53313
54521
 
53314
54522
  let url;
@@ -53370,6 +54578,9 @@ class DensityCifParser {
53370
54578
  ic.mapData.header2 = header;
53371
54579
 
53372
54580
  ic.mapData.data2 = density.data;
54581
+ for(let i = 0; i < density.data.length; ++i) {
54582
+ density.data[i];
54583
+ }
53373
54584
 
53374
54585
  let origin = density.box.origin;
53375
54586
  let dimensions = density.box.dimensions;
@@ -53404,6 +54615,7 @@ class DensityCifParser {
53404
54615
  origin = density.box.origin;
53405
54616
  dimensions = density.box.dimensions;
53406
54617
  basis = density.spacegroup.basis;
54618
+
53407
54619
  scale = new THREE.Matrix4().makeScale(
53408
54620
  dimensions[0] / (sampleCount[0] ),
53409
54621
  dimensions[1] / (sampleCount[1] ),
@@ -55032,7 +56244,10 @@ class ParserUtils {
55032
56244
 
55033
56245
  if(bAppend) {
55034
56246
  if(ic.bSetChainsAdvancedMenu) ic.definedSetsCls.showSets();
55035
- if(ic.bAnnoShown) await ic.showAnnoCls.showAnnotations();
56247
+ if(ic.bAnnoShown) {
56248
+ await ic.showAnnoCls.showAnnotations();
56249
+ ic.annotationCls.resetAnnoTabAll();
56250
+ }
55036
56251
  }
55037
56252
 
55038
56253
  // Realign by sequence alignment with the residues in "segment", i.e., transmembrane helix
@@ -56362,12 +57577,12 @@ class SetSeqAlign {
56362
57577
 
56363
57578
  if(i > 0) {
56364
57579
  let index1 = alignIndex;
56365
-
57580
+
56366
57581
  for(let j = prevIndex1 + 1, jl = start1; j < jl; ++j) {
56367
- if(posChain1[j]) continue;
57582
+ //if(posChain1[j]) continue;
56368
57583
  posChain1[j] = 1;
56369
57584
 
56370
- if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid1][j] === undefined) break;
57585
+ //if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid1][j] === undefined) break;
56371
57586
 
56372
57587
  //let resi = this.getResiAferAlign(chainid1, bRealign, j + 1);
56373
57588
  let resi = this.getResiAferAlign(chainid1, bRealign, j);
@@ -56378,18 +57593,19 @@ class SetSeqAlign {
56378
57593
 
56379
57594
  color = me.htmlCls.GREY8;
56380
57595
  classname = 'icn3d-nalign';
56381
-
57596
+
56382
57597
  ic.nalignHash1[chainid1 + '_' + resi] = 1;
56383
57598
  this.setSeqPerResi(chainid1, chainid1, chainid2, resi, resn, false, color, undefined, classname, true, false, index1);
56384
57599
  ++index1;
56385
57600
  }
56386
57601
 
56387
57602
  let index2 = alignIndex;
57603
+
56388
57604
  for(let j = prevIndex2 + 1, jl = start2; j < jl; ++j) {
56389
- if(posChain2[j]) continue;
57605
+ //if(posChain2[j]) continue;
56390
57606
  posChain2[j] = 1;
56391
57607
 
56392
- if(ic.chainsSeq[chainid2] === undefined || ic.chainsSeq[chainid2] === undefined) break;
57608
+ //if(ic.chainsSeq[chainid2] === undefined || ic.chainsSeq[chainid2] === undefined) break;
56393
57609
 
56394
57610
  //let resi = this.getResiAferAlign(chainid2, bRealign, j + 1);
56395
57611
  let resi = this.getResiAferAlign(chainid2, bRealign, j);
@@ -56435,7 +57651,7 @@ class SetSeqAlign {
56435
57651
  }
56436
57652
 
56437
57653
  for(let j = 0; j <= end1 - start1; ++j) {
56438
- if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid2] === undefined) break;
57654
+ ///if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid2] === undefined) break;
56439
57655
 
56440
57656
  let resi1, resi2, resn1, resn2;
56441
57657
  /*
@@ -56465,15 +57681,17 @@ class SetSeqAlign {
56465
57681
  if(resn1 == '?' || resn2 == '?') continue;
56466
57682
  }
56467
57683
  else {
56468
- if(ic.chainsSeq[chainid1][j + start1] === undefined || ic.chainsSeq[chainid2][j + start2] === undefined) continue;
57684
+ ///if(ic.chainsSeq[chainid1][j + start1] === undefined || ic.chainsSeq[chainid2][j + start2] === undefined) continue;
56469
57685
 
56470
57686
  // resi1 = ic.chainsSeq[chainid1][j + start1].resi;
56471
57687
  // resi2 = ic.chainsSeq[chainid2][j + start2].resi;
56472
57688
  // resn1 = ic.chainsSeq[chainid1][j + start1].name.toUpperCase();
56473
57689
  // resn2 = ic.chainsSeq[chainid2][j + start2].name.toUpperCase();
56474
57690
 
56475
- resi1 = this.getResiAferAlign(chainid1, bRealign, j + start1 + 1);
56476
- resi2 = this.getResiAferAlign(chainid2, bRealign, j + start2 + 1);
57691
+ // resi1 = this.getResiAferAlign(chainid1, bRealign, j + start1 + 1);
57692
+ // resi2 = this.getResiAferAlign(chainid2, bRealign, j + start2 + 1);
57693
+ resi1 = this.getResiAferAlign(chainid1, bRealign, j + start1);
57694
+ resi2 = this.getResiAferAlign(chainid2, bRealign, j + start2);
56477
57695
  resn1 = this.getResnFromResi(chainid1, resi1).toUpperCase();
56478
57696
  resn2 = this.getResnFromResi(chainid2, resi2).toUpperCase();
56479
57697
  }
@@ -61522,14 +62740,15 @@ class LoadScript {
61522
62740
  let bFinalStep =(i === steps - 1) ? true : false;
61523
62741
 
61524
62742
  if(!ic.commands[i].trim()) continue;
61525
- let nAtoms = Object.keys(ic.atoms).length;
62743
+ let nAtoms = (ic.atoms) ? Object.keys(ic.atoms).length : 0;
61526
62744
 
61527
62745
  if(nAtoms == 0 && ic.commands[i].indexOf('load') == -1) continue;
61528
62746
 
61529
62747
  let strArray = ic.commands[i].split("|||");
61530
62748
  let command = strArray[0].trim();
61531
62749
 
61532
- if(ic.inputid) ic.bNotLoadStructure = true;
62750
+ // sometimes URL has an ID input, then load a structure in commands
62751
+ //if(ic.inputid) ic.bNotLoadStructure = true;
61533
62752
 
61534
62753
  if(command.indexOf('load') !== -1) {
61535
62754
  if(end === 0 && start === end) {
@@ -61565,18 +62784,7 @@ class LoadScript {
61565
62784
  }
61566
62785
  }
61567
62786
  else if(command.indexOf('set map') == 0 && command.indexOf('set map wireframe') == -1) {
61568
- //set map 2fofc sigma 1.5
61569
- let urlArray = strArray[0].trim().split(' | ');
61570
-
61571
- let str = urlArray[0].substr(8);
61572
- let paraArray = str.split(" ");
61573
-
61574
- if(paraArray.length == 3 && paraArray[1] == 'sigma') {
61575
- paraArray[2];
61576
- paraArray[0];
61577
-
61578
- await thisClass.applyCommandMap(strArray[0].trim());
61579
- }
62787
+ await thisClass.applyCommandMap(strArray[0].trim());
61580
62788
  }
61581
62789
  else if(command.indexOf('set emmap') == 0 && command.indexOf('set emmap wireframe') == -1) {
61582
62790
  //set emmap percentage 70
@@ -62076,17 +63284,34 @@ class LoadScript {
62076
63284
  // ic.deferredMap = $.Deferred(function() { let ic = thisClass.icn3d;
62077
63285
  //"set map 2fofc sigma 1.5"
62078
63286
  // or "set map 2fofc sigma 1.5 | [url]"
63287
+
63288
+ // added more para later
63289
+ //"set map 2fofc sigma 1.5 file dsn6"
63290
+ // or "set map 2fofc sigma 1.5 file dsn6 | [url]"
62079
63291
  let urlArray = command.split(" | ");
62080
63292
 
62081
63293
  let str = urlArray[0].substr(8);
62082
63294
  let paraArray = str.split(" ");
62083
63295
 
62084
- if(paraArray.length == 3 && paraArray[1] == 'sigma') {
63296
+ //if(paraArray.length == 3 && paraArray[1] == 'sigma') {
63297
+ if(paraArray[1] == 'sigma') {
62085
63298
  let sigma = paraArray[2];
62086
63299
  let type = paraArray[0];
62087
63300
 
63301
+ let fileType = 'dsn6';
63302
+ if(paraArray.length == 5) fileType = paraArray[4];
63303
+
62088
63304
  if(urlArray.length == 2) {
62089
- await ic.dsn6ParserCls.dsn6ParserBase(urlArray[1], type, sigma);
63305
+ let bInputSigma = true;
63306
+ if(fileType == 'dsn6') {
63307
+ await ic.dsn6ParserCls.dsn6ParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
63308
+ }
63309
+ else if(fileType == 'ccp4') {
63310
+ await ic.ccp4ParserCls.ccp4ParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
63311
+ }
63312
+ else if(fileType == 'mtz') {
63313
+ await ic.mtzParserCls.mtzParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
63314
+ }
62090
63315
  }
62091
63316
  else {
62092
63317
  await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma);
@@ -71030,7 +72255,7 @@ class Ray {
71030
72255
  }
71031
72256
 
71032
72257
  // from iview (http://istar.cse.cuhk.edu.hk/iview/)
71033
- getAtomsFromPosition(point, threshold) { let ic = this.icn3d, me = ic.icn3dui;
72258
+ getAtomsFromPosition(point, threshold, atoms) { let ic = this.icn3d, me = ic.icn3dui;
71034
72259
  let i;
71035
72260
 
71036
72261
  if(threshold === undefined || threshold === null) {
@@ -71038,7 +72263,8 @@ class Ray {
71038
72263
  }
71039
72264
 
71040
72265
  //for (i in ic.atoms) {
71041
- for (i in ic.dAtoms) {
72266
+ let atomHash = (atoms) ? atoms : ic.dAtoms;
72267
+ for (i in atomHash) {
71042
72268
  let atom = ic.atoms[i];
71043
72269
 
71044
72270
  if(ic.ions.hasOwnProperty(i) && ic.opts['ions'] === 'sphere') {
@@ -71431,13 +72657,25 @@ class Picking {
71431
72657
  y += me.htmlCls.MENU_HEIGHT;
71432
72658
  }
71433
72659
  let text =(ic.pk == 1) ? atom.resn + atom.resi + '@' + atom.name : atom.resn + atom.resi;
72660
+ let chainid = atom.structure + '_' + atom.chain;
72661
+ let textWidth;
71434
72662
  if(ic.structures !== undefined && Object.keys(ic.structures).length > 1) {
71435
- text = atom.structure + '_' + atom.chain + ' ' + text;
71436
- $("#" + ic.pre + "popup").css("width", "160px");
72663
+ text = chainid + ' ' + text;
72664
+ textWidth = (ic.chainid2refpdbname && ic.chainid2refpdbname[chainid]) ? 160 + 80 : 160;
72665
+ $("#" + ic.pre + "popup").css("width", textWidth + "px");
71437
72666
  }
71438
72667
  else {
71439
- $("#" + ic.pre + "popup").css("width", "80px");
72668
+ textWidth = (ic.chainid2refpdbname && ic.chainid2refpdbname[chainid]) ? 80 + 80 : 80;
72669
+ $("#" + ic.pre + "popup").css("width", textWidth + "px");
71440
72670
  }
72671
+
72672
+
72673
+ if(ic.chainid2refpdbname && ic.chainid2refpdbname[chainid]) {
72674
+ let refnumLabel = ic.resid2refnum[chainid + '_' + atom.resi];
72675
+
72676
+ if(refnumLabel) text += ', Ig: ' + refnumLabel;
72677
+ }
72678
+
71441
72679
  $("#" + ic.pre + "popup").html(text);
71442
72680
  $("#" + ic.pre + "popup").css("top", y).css("left", x+20).show();
71443
72681
  }
@@ -72598,6 +73836,8 @@ class iCn3D {
72598
73836
  this.alignParserCls = new AlignParser(this);
72599
73837
  this.chainalignParserCls = new ChainalignParser(this);
72600
73838
  this.dsn6ParserCls = new Dsn6Parser(this);
73839
+ this.ccp4ParserCls = new Ccp4Parser(this);
73840
+ this.mtzParserCls = new MtzParser(this);
72601
73841
  this.mmcifParserCls = new MmcifParser(this);
72602
73842
  this.mmdbParserCls = new MmdbParser(this);
72603
73843
  this.mmtfParserCls = new MmtfParser(this);
@@ -72860,7 +74100,7 @@ class iCn3DUI {
72860
74100
  //even when multiple iCn3D viewers are shown together.
72861
74101
  this.pre = this.cfg.divid + "_";
72862
74102
 
72863
- this.REVISION = '3.28.4';
74103
+ this.REVISION = '3.29.0';
72864
74104
 
72865
74105
  // In nodejs, iCn3D defines "window = {navigator: {}}"
72866
74106
  this.bNode = (Object.keys(window).length < 2) ? true : false;