icn3d 3.28.11 → 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 +1600 -349
  2. package/icn3d.min.js +7 -5
  3. package/icn3d.module.js +1600 -349
  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
-
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
-
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/>";
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/>";
10987
10983
 
10988
- html += "<span style='white-space:nowrap;font-weight:bold;'>fofc contour at: <select id='" + me.pre + "dsn6sigmafofc'>";
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/>";
10989
10988
 
10990
- html += me.htmlCls.setHtmlCls.getOptionHtml(optArray1, 5);
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/>";
10991
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
  }
@@ -12286,9 +12293,9 @@ class Events {
12286
12293
  thisClass.setLogCmd("clear selection", true);
12287
12294
  });
12288
12295
 
12289
- me.myEventCls.onIds(["#" + me.pre + "alternate", "#" + me.pre + "mn2_alternate", "#" + me.pre + "alternate2"], "click", function(e) { let ic = me.icn3d;
12296
+ me.myEventCls.onIds(["#" + me.pre + "alternate", "#" + me.pre + "mn2_alternate", "#" + me.pre + "alternate2"], "click", async function(e) { let ic = me.icn3d;
12290
12297
  ic.bAlternate = true;
12291
- ic.alternateCls.alternateStructures();
12298
+ await ic.alternateCls.alternateStructures();
12292
12299
  ic.bAlternate = false;
12293
12300
 
12294
12301
  thisClass.setLogCmd("alternate structures", false);
@@ -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) {
@@ -15567,6 +15618,7 @@ class SetHtml {
15567
15618
  let matchedStrData = "Start of data file======\n";
15568
15619
  let posData = imageStr.indexOf(matchedStrData);
15569
15620
  ic.bInputfile =(posData == -1) ? false : true;
15621
+ ic.bInputPNGWithData = ic.bInputfile;
15570
15622
  let commandStr = (command) ? command.replace(/;/g, "\n") : '';
15571
15623
 
15572
15624
  let statefile;
@@ -28438,8 +28490,8 @@ class ElectronMap {
28438
28490
  this.pLength = 0;
28439
28491
  this.cutRadius = 0;
28440
28492
  this.vpBits = null; // uint8 array of bitmasks
28441
- this.vpDistance = null; // floatarray of _squared_ distances
28442
- this.vpAtomID = null; // intarray
28493
+ this.vpGridTrans = null; // array of translated number of grids
28494
+ this.vpAtomID = null; // uint8 array
28443
28495
  this.vertnumber = 0;
28444
28496
  this.facenumber = 0;
28445
28497
  this.pminx = 0;
@@ -28489,12 +28541,27 @@ ElectronMap.prototype.getFacesAndVertices = function(allatoms, atomlist) {
28489
28541
  atomsToShow[atomlist[i]] = 1;
28490
28542
  let vertices = this.verts;
28491
28543
 
28544
+ let vertTrans = {};
28492
28545
  for(i = 0, il = vertices.length; i < il; i++) {
28493
28546
  let r;
28494
28547
  if(this.type == 'phi') {
28495
28548
  r = new THREE.Vector3(vertices[i].x, vertices[i].y, vertices[i].z).multiplyScalar(1.0/this.header.scale).applyMatrix4(this.matrix);
28496
28549
  }
28497
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
+ }
28498
28565
  r = new THREE.Vector3(vertices[i].x, vertices[i].y, vertices[i].z).applyMatrix4(this.matrix);
28499
28566
  }
28500
28567
  // vertices[i].x = r.x / this.scaleFactor - this.ptranx;
@@ -28513,13 +28580,22 @@ ElectronMap.prototype.getFacesAndVertices = function(allatoms, atomlist) {
28513
28580
  let fa = this.faces[i], fb = this.faces[i+1], fc = this.faces[i+2];
28514
28581
 
28515
28582
  if(fa !== fb && fb !== fc && fa !== fc){
28516
- 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
+ }
28517
28593
  }
28518
28594
  }
28519
28595
 
28520
28596
  //try to help the garbage collector
28521
28597
  this.vpBits = null; // uint8 array of bitmasks
28522
- this.vpDistance = null; // floatarray
28598
+ this.vpGridTrans = null; // uint8 array
28523
28599
  this.vpAtomID = null; // intarray
28524
28600
 
28525
28601
  return {
@@ -28578,6 +28654,8 @@ ElectronMap.prototype.initparm = function(inHeader, inData, inMatrix, inIsovalue
28578
28654
  this.cutRadius = this.probeRadius * this.scaleFactor;
28579
28655
 
28580
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
+
28581
28659
  this.vpAtomID = new Uint8Array(this.pLength * this.pWidth * this.pHeight);
28582
28660
  };
28583
28661
 
@@ -28603,7 +28681,6 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
28603
28681
  let i, j, k, il, jl, kl;
28604
28682
  for(i = 0, il = this.vpBits.length; i < il; i++) {
28605
28683
  this.vpBits[i] = 0;
28606
- //this.vpDistance[i] = -1.0;
28607
28684
  this.vpAtomID[i] = 0;
28608
28685
  }
28609
28686
 
@@ -28765,6 +28842,7 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
28765
28842
  }
28766
28843
  }
28767
28844
  else {
28845
+ // let index2ori = {};
28768
28846
  for(let serial in atomlist) {
28769
28847
  let atom = atoms[atomlist[serial]];
28770
28848
 
@@ -28795,6 +28873,7 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
28795
28873
 
28796
28874
  for(i = 0, il = indexArray.length; i < il; ++i) {
28797
28875
  let index = indexArray[i];
28876
+
28798
28877
  if(this.type == '2fofc') {
28799
28878
  this.vpBits[index] =(this.dataArray[index] >= this.isovalue) ? 1 : 0;
28800
28879
  //this.vpAtomID[index] =(this.dataArray[index] >= 0) ? 1 : 0; // determine whether it's positive
@@ -28808,6 +28887,7 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
28808
28887
  //this.vpAtomID[index] =(this.dataArray[index] >= 0) ? 1 : 0; // determine whether it's positive
28809
28888
  }
28810
28889
  }
28890
+
28811
28891
  }
28812
28892
  }
28813
28893
 
@@ -29031,7 +29111,18 @@ class Surface {
29031
29111
  cfg.isovalue = ic.mapData.sigma2;
29032
29112
  cfg.type = '2fofc';
29033
29113
 
29034
- 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
+ }
29035
29126
  }
29036
29127
  else if(type == 12) { // fofc
29037
29128
  cfg.header = ic.mapData.header;
@@ -29040,7 +29131,18 @@ class Surface {
29040
29131
  cfg.isovalue = ic.mapData.sigma;
29041
29132
  cfg.type = 'fofc';
29042
29133
 
29043
- 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
+ }
29044
29146
  }
29045
29147
  else if(type == 13) { // em
29046
29148
  cfg.maxdist = 3; // EM map has no unit cell. It could include more gird space.
@@ -29528,29 +29630,60 @@ class Surface {
29528
29630
  }
29529
29631
 
29530
29632
  SetupMap(data) { let ic = this.icn3d; ic.icn3dui;
29531
- let ps = new ElectronMap(ic);
29532
-
29533
- ps.initparm(data.header, data.data, data.matrix, data.isovalue, data.center, data.maxdist,
29534
- 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);
29535
29657
 
29536
- 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);
29537
29667
 
29538
- if(!data.header.bSurface) ps.buildboundary();
29668
+ ps.fillvoxels(data.allatoms, data.extendedAtoms);
29539
29669
 
29540
- if(!data.header.bSurface) ps.marchingcube();
29541
-
29542
- ps.vpBits = null; // uint8 array of bitmasks
29543
- //ps.vpDistance = null; // floatarray of _squared_ distances
29544
- ps.vpAtomID = null; // intarray
29670
+ if(!data.header.bSurface) ps.buildboundary();
29545
29671
 
29546
- 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
29547
29677
 
29548
- if(!data.header.bSurface) result = ps.getFacesAndVertices(data.allatoms, data.atomsToShow);
29678
+ let result;
29549
29679
 
29550
- ps.faces = null;
29551
- ps.verts = null;
29680
+ if(!data.header.bSurface) result = ps.getFacesAndVertices(data.allatoms, data.atomsToShow);
29552
29681
 
29553
- return result;
29682
+ ps.faces = null;
29683
+ ps.verts = null;
29684
+
29685
+ return result;
29686
+ }
29554
29687
  }
29555
29688
  }
29556
29689
 
@@ -32511,7 +32644,7 @@ class Alternate {
32511
32644
 
32512
32645
  // change the display atom when alternating
32513
32646
  //Show structures one by one.
32514
- alternateStructures() { let ic = this.icn3d, me = ic.icn3dui;
32647
+ async alternateStructures() { let ic = this.icn3d, me = ic.icn3dui;
32515
32648
  ic.bAlternate = true;
32516
32649
 
32517
32650
  //ic.transformCls.zoominSelection();
@@ -32609,16 +32742,24 @@ class Alternate {
32609
32742
  ic.applyMapCls.removeEmmaps();
32610
32743
  ic.applyMapCls.applyEmmapOptions();
32611
32744
 
32612
- // allow the alternation of DelPhi map
32745
+ // allow the alternation of DelPhi map
32746
+ /*
32747
+ // Option 1: recalculate =========
32748
+ ic.applyMapCls.removePhimaps();
32749
+ await ic.delphiCls.loadDelphiFile('delphi');
32750
+
32751
+ ic.applyMapCls.removeSurfaces();
32752
+ await ic.delphiCls.loadDelphiFile('delphi2');
32753
+ // ==============
32754
+ */
32755
+
32756
+ // Option 2: NO recalculate, just show separately =========
32613
32757
  ic.applyMapCls.removePhimaps();
32614
32758
  ic.applyMapCls.applyPhimapOptions();
32615
- // should recalculate the potential
32616
- //ic.loadDelphiFileBase('delphi');
32617
32759
 
32618
32760
  ic.applyMapCls.removeSurfaces();
32619
32761
  ic.applyMapCls.applyphisurfaceOptions();
32620
- // should recalculate the potential
32621
- //ic.loadDelphiFileBase('delphi2');
32762
+ // ==============
32622
32763
 
32623
32764
  // alternate the PCA axes
32624
32765
  ic.axes = [];
@@ -32635,9 +32776,9 @@ class Alternate {
32635
32776
  ic.bShowHighlight = true;
32636
32777
  }
32637
32778
 
32638
- alternateWrapper() { let ic = this.icn3d; ic.icn3dui;
32779
+ async alternateWrapper() { let ic = this.icn3d; ic.icn3dui;
32639
32780
  ic.bAlternate = true;
32640
- this.alternateStructures();
32781
+ await this.alternateStructures();
32641
32782
  ic.bAlternate = false;
32642
32783
  }
32643
32784
 
@@ -35029,7 +35170,7 @@ class SetColor {
35029
35170
 
35030
35171
  for(let resid in residueHash) {
35031
35172
  if(!ic.resid2refnum[resid]) {
35032
- color = me.parasCls.thr('#FFFFFF');
35173
+ color = me.parasCls.thr('#00FFFF'); //('#FFFFFF');
35033
35174
  }
35034
35175
  else {
35035
35176
  let refnumLabel = ic.resid2refnum[resid];
@@ -35064,7 +35205,7 @@ class SetColor {
35064
35205
  let residueHash = ic.firstAtomObjCls.getResiduesFromAtoms(atoms);
35065
35206
  for(let resid in residueHash) {
35066
35207
  if(!ic.resid2refnum[resid]) {
35067
- color = me.parasCls.thr('#FFFFFF');
35208
+ color = me.parasCls.thr('#00FFFF'); //('#FFFFFF');
35068
35209
  }
35069
35210
  else {
35070
35211
  let refnumLabel = ic.resid2refnum[resid];
@@ -36034,15 +36175,13 @@ class SetOption {
36034
36175
  const name2color = {
36035
36176
  //"A- Strand": "FF00FF",
36036
36177
  "A Strand": "9400D3", //"663399",
36037
- //"A+ Strand": "9400D3", //"663399",
36038
- "A' Strand": "9400D3", //"663399",
36039
36178
  "B Strand": "ba55d3",
36040
36179
  "C Strand": "0000FF",
36041
36180
  "C' Strand": "6495ED",
36042
36181
  "C'' Strand": "006400",
36043
36182
  "D Strand": "00FF00",
36044
- "E Strand": "F7DC6F", //"FFFF00", //"F0E68C",
36045
- "F Strand": "FFA500",
36183
+ "E Strand": "FFD700", //"FFFF00", //"F0E68C",
36184
+ "F Strand": "FF8C00",
36046
36185
  "G Strand": "FF0000",
36047
36186
  //"G+ Strand": "8B0000",
36048
36187
  "Loop": "CCCCCC"
@@ -36069,15 +36208,15 @@ class SetOption {
36069
36208
  "<b>Protodomain 1</b>": "",
36070
36209
  "A Strand": "0000FF",
36071
36210
  "B Strand": "006400",
36072
- "C Strand": "F7DC6F", //"FFFF00", //"F0E68C",
36073
- "C' Strand": "FFA500",
36211
+ "C Strand": "FFD700", //"FFFF00", //"F0E68C",
36212
+ "C' Strand": "FF8C00",
36074
36213
  "<br><b>Linker</b>": "",
36075
36214
  "C'' Strand": "FF0000",
36076
36215
  "<br><b>Protodomain 2</b>": "",
36077
36216
  "D Strand": "0000FF",
36078
36217
  "E Strand": "006400",
36079
- "F Strand": "F7DC6F", //"FFFF00", //"F0E68C",
36080
- "G Strand": "FFA500",
36218
+ "F Strand": "FFD700", //"FFFF00", //"F0E68C",
36219
+ "G Strand": "FF8C00",
36081
36220
  "": "",
36082
36221
  "Loop": "CCCCCC"
36083
36222
  };
@@ -37279,14 +37418,14 @@ class AnnoDomain {
37279
37418
  let pdbid = pdbArray[index];
37280
37419
  //let url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&domain&molinfor&uid=" + pdbid;
37281
37420
 
37282
- if(index == 0 && ic.mmdb_data !== undefined) {
37421
+ if(!ic.bResetAnno && index == 0 && ic.mmdb_data !== undefined) {
37283
37422
  for(let chnid in ic.protein_chainid) {
37284
37423
  if(chnid.indexOf(pdbid) !== -1) {
37285
37424
  this.showDomainWithData(chnid, ic.mmdb_data);
37286
37425
  }
37287
37426
  }
37288
37427
  }
37289
- else if(ic.mmdb_dataArray[index] !== undefined) {
37428
+ else if(!ic.bResetAnno && ic.mmdb_dataArray[index] !== undefined) {
37290
37429
  for(let chnid in ic.protein_chainid) {
37291
37430
  if(chnid.indexOf(pdbid) !== -1) {
37292
37431
  this.showDomainWithData(chnid, ic.mmdb_dataArray[index]);
@@ -37361,6 +37500,10 @@ class AnnoDomain {
37361
37500
  let domainArray, proteinname;
37362
37501
  let pos = chnid.indexOf('_');
37363
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
+ }
37364
37507
 
37365
37508
  if(bCalcDirect) {
37366
37509
  proteinname = chnid;
@@ -38366,7 +38509,11 @@ class Domain3d {
38366
38509
  //this.dcut = 8; // threshold for C-alpha interactions
38367
38510
 
38368
38511
  // It seemed the threshold 7 angstrom works better
38369
- 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
38370
38517
 
38371
38518
  this.MAX_SSE = 512;
38372
38519
 
@@ -38400,9 +38547,6 @@ class Domain3d {
38400
38547
  this.c_delta = 3; // cut set parameter
38401
38548
  this.nc_fact = 0.0; // size factor for internal contacts
38402
38549
 
38403
- // added by Jiyao
38404
- this.min_contacts = 3; // minimum number of contacts to be considered as neighbors
38405
-
38406
38550
  //let this.elements[2*this.MAX_SSE]; // sets of this.elements to be split
38407
38551
  this.elements = [];
38408
38552
  this.elements.length = 2*this.MAX_SSE;
@@ -41980,6 +42124,10 @@ class ShowAnno {
41980
42124
  chainLetter = chainLetter.substr(0, chainLetter.indexOf('_'));
41981
42125
  chainidBase = chainArray[i].substr(0, chainArray[i].indexOf('_')) + '_' + chainLetter;
41982
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
+ }
41983
42131
  else {
41984
42132
  chainidBase = chainArray[i];
41985
42133
  }
@@ -43180,7 +43328,7 @@ class ShowSeq {
43180
43328
  html += '</div>';
43181
43329
  html3 += '</div></div>';
43182
43330
  }
43183
-
43331
+
43184
43332
  if(ic.bShowRefnum && ic.chainid2refpdbname.hasOwnProperty(chnid) && ic.chainid2refpdbname[chnid].length > 0) {
43185
43333
  let result = this.showAllRefNum(giSeq, chnid);
43186
43334
 
@@ -43249,9 +43397,13 @@ class ShowSeq {
43249
43397
 
43250
43398
  if(!ic.chainid2refpdbname[chnid]) return {html: html, html3: html3};
43251
43399
 
43252
- 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;
43253
43405
 
43254
- 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 + "." : "";
43255
43407
 
43256
43408
  let htmlTmp = '<div class="icn3d-dl_sequence">';
43257
43409
  htmlTmp += '<div class="icn3d-residueLine" style="white-space:nowrap;">';
@@ -43307,7 +43459,8 @@ class ShowSeq {
43307
43459
 
43308
43460
  // auto-generate ref numbers for loops
43309
43461
  let bLoop = false, currStrand = '', prevStrand = '';
43310
- 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;
43311
43464
 
43312
43465
  // sometimes one chain may have several Ig domains,set an index for each IgDomain
43313
43466
  let index = 1, bStart = false;
@@ -43333,8 +43486,8 @@ class ShowSeq {
43333
43486
 
43334
43487
  refnumLabel = ic.resid2refnum[residueid];
43335
43488
 
43336
- let firstChar = (refnumLabel) ? refnumLabel.substr(0,1) : ' ';
43337
- 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
43338
43491
  bStart = true;
43339
43492
  resCnt = 1; // the first oen is included
43340
43493
  }
@@ -43351,14 +43504,21 @@ class ShowSeq {
43351
43504
  refnumStr = refnumStr_ori;
43352
43505
  refnum = parseInt(refnumStr);
43353
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
+
43354
43513
  strandPostfix = refnumStr.replace(refnum.toString(), '');
43355
43514
 
43356
43515
  postfix = strandPostfix + '_' + index;
43357
43516
 
43358
- 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##)
43359
43519
 
43360
43520
  if(currStrand && currStrand != ' ') {
43361
- if(refnum3c.substr(0,1) != '9' || firstTwo == 10) {
43521
+ if(!bSecThird9 || (bExtendedStrand && !bSecThird9)) {
43362
43522
  let lastTwo = parseInt(refnum.toString().substr(refnum.toString().length - 2, 2));
43363
43523
 
43364
43524
  if(currStrand != prevStrand) { // reset currCnt
@@ -43385,7 +43545,7 @@ class ShowSeq {
43385
43545
  resCntAtAnchor = 0;
43386
43546
  }
43387
43547
 
43388
- if(firstTwo == 10) {
43548
+ if(bExtendedStrand) {
43389
43549
  strandArray[strandCnt].anchorRefnum = 0;
43390
43550
  }
43391
43551
 
@@ -43411,7 +43571,7 @@ class ShowSeq {
43411
43571
  resCntAtAnchor = 0;
43412
43572
  }
43413
43573
 
43414
- if(firstTwo == 10) {
43574
+ if(bExtendedStrand) {
43415
43575
  strandArray[strandCnt - 1].anchorRefnum = 0;
43416
43576
  }
43417
43577
 
@@ -43467,7 +43627,7 @@ class ShowSeq {
43467
43627
  currStrand = refnumLabel.replace(new RegExp(refnumStr,'g'), '');
43468
43628
 
43469
43629
  let firstChar = refnumLabel.substr(0,1);
43470
- 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
43471
43631
  bStart = true;
43472
43632
  bBeforeAstrand = true;
43473
43633
  loopCnt = 0;
@@ -43740,6 +43900,11 @@ class ShowSeq {
43740
43900
 
43741
43901
  getRefnumHtml(residueid, refnumStr, refnumStr_ori, refnumLabel, currStrand, bLoop, bHidelabel) { let ic = this.icn3d, me = ic.icn3dui;
43742
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
+
43743
43908
  let color = this.getRefnumColor(currStrand, true);
43744
43909
  let colorStr = (!bLoop) ? 'style="color:' + color + '; text-decoration: underline overline;"' : 'style="color:' + color + '"';
43745
43910
 
@@ -43749,13 +43914,13 @@ class ShowSeq {
43749
43914
 
43750
43915
  let html = '';
43751
43916
 
43752
- if(refnumLabel && (lastTwo == 50 || refnum == 1094) && !bLoop) {
43917
+ if(refnumLabel && lastTwo == 50 && !bExtendedStrand && !bLoop) {
43753
43918
  // highlight the anchor residues
43754
43919
  ic.hAtomsRefnum = me.hashUtilsCls.unionHash(ic.hAtomsRefnum, ic.residues[residueid]);
43755
43920
 
43756
43921
  html += '<span ' + colorStr + ' title="' + refnumLabel + '"><b>' + refnumLabel.substr(0, 1) + '</b>' + refnumLabel.substr(1) + '</span>';
43757
43922
  }
43758
- 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
43759
43924
  // e.g., 2152a
43760
43925
  lastTwoStr = isNaN(refnumStr) ? lastTwoStr + refnumStr.substr(refnumStr.length - 1, 1) : lastTwoStr;
43761
43926
  html += '<span ' + colorStr + ' title="' + refnumLabel + '">' + lastTwoStr + '</span>';
@@ -43768,23 +43933,9 @@ class ShowSeq {
43768
43933
  }
43769
43934
 
43770
43935
  getRefnumColor(currStrand, bText) { let ic = this.icn3d, me = ic.icn3dui;
43771
- if(currStrand == "A-") {
43772
- return '#9400D3'; //'#663399';
43773
- }
43774
- else if(currStrand == "A") {
43775
- return '#9400D3'; //'#663399';
43776
- }
43777
- //else if(currStrand == "A*") {
43778
- else if(currStrand == "A+") {
43779
- return '#9400D3'; //'#663399';
43780
- }
43781
- else if(currStrand == "A'") {
43782
- return '#9400D3'; //'#663399';
43783
- }
43784
- else if(currStrand == "B") {
43785
- return '#ba55d3';
43786
- }
43787
- else if(currStrand == "C") {
43936
+ let strand = (currStrand) ? currStrand.substr(0,1) : '';
43937
+
43938
+ if(currStrand == "C") {
43788
43939
  return '#0000FF';
43789
43940
  }
43790
43941
  else if(currStrand == "C'") {
@@ -43793,39 +43944,44 @@ class ShowSeq {
43793
43944
  else if(currStrand == "C''") {
43794
43945
  return '#006400';
43795
43946
  }
43796
- 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") {
43797
43955
  return '#00FF00';
43798
43956
  }
43799
- else if(currStrand == "E") {
43800
- //return (bText) ? "#F7DC6F" : "#FFFF00";
43801
- return "#F7DC6F";
43957
+ else if(strand == "E") {
43958
+ return "#FFD700";
43802
43959
  }
43803
- else if(currStrand == "F") {
43804
- return '#FFA500';
43960
+ else if(strand == "F") {
43961
+ return '#FF8C00';
43805
43962
  }
43806
- else if(currStrand == "G") {
43963
+ else if(strand == "G") {
43807
43964
  return '#FF0000';
43808
43965
  }
43809
- else if(currStrand == "G+") {
43810
- return '#8B0000';
43811
- }
43812
43966
  else {
43813
43967
  return me.htmlCls.GREYB;
43814
43968
  }
43815
43969
  }
43816
43970
 
43817
43971
  getProtodomainColor(currStrand) { let ic = this.icn3d, me = ic.icn3dui;
43818
- if((currStrand && currStrand.substr(0,1) == "A") || currStrand == "D") {
43972
+ let strand = (currStrand) ? currStrand.substr(0,1) : '';
43973
+
43974
+ if(strand == "A" || strand == "D") {
43819
43975
  return '#0000FF';
43820
43976
  }
43821
- else if(currStrand == "B" || currStrand == "E") {
43977
+ else if(strand == "B" || strand == "E") {
43822
43978
  return '#006400';
43823
43979
  }
43824
- else if(currStrand == "C" || currStrand == "F") {
43825
- return "#F7DC6F"; //"#FFFF00"; //'#F0E68C';
43980
+ else if(currStrand == "C" || strand == "F") {
43981
+ return "#FFD700"; //"#FFFF00"; //'#F0E68C';
43826
43982
  }
43827
- else if(currStrand == "C'" || (currStrand && currStrand.substr(0, 1) == "G")) {
43828
- return '#FFA500';
43983
+ else if(currStrand == "C'" || strand == "G") {
43984
+ return '#FF8C00';
43829
43985
  }
43830
43986
  else if(currStrand == "C''") { //linker
43831
43987
  return '#FF0000';
@@ -44528,8 +44684,8 @@ class HlUpdate {
44528
44684
  updateHlObjects(bForceHighlight) { let ic = this.icn3d; ic.icn3dui;
44529
44685
  ic.hlObjectsCls.removeHlObjects();
44530
44686
 
44531
- if((ic.hAtoms && ic.atoms && Object.keys(ic.hAtoms).length < Object.keys(ic.atoms).length) || bForceHighlight) {
44532
- 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();
44533
44689
  ic.definedSetsCls.setMode('selection');
44534
44690
  }
44535
44691
  }
@@ -45609,8 +45765,11 @@ class LineGraph {
45609
45765
 
45610
45766
  // try {
45611
45767
  if(!template) {
45612
- let allPromise = Promise.allSettled(pdbAjaxArray);
45613
- ic.pdbDataArray = await allPromise;
45768
+ //let allPromise = Promise.allSettled(pdbAjaxArray);
45769
+ //ic.pdbDataArray = await allPromise;
45770
+
45771
+ ic.pdbDataArray = await this.promiseWithFixedJobs(pdbAjaxArray);
45772
+
45614
45773
  await thisClass.parseRefPdbData(ic.pdbDataArray, template);
45615
45774
  }
45616
45775
  else {
@@ -45721,6 +45880,7 @@ class LineGraph {
45721
45880
  }
45722
45881
 
45723
45882
  if(!ic.domainid2refpdbname) ic.domainid2refpdbname = {};
45883
+ if(!ic.domainid2score) ic.domainid2score = {};
45724
45884
 
45725
45885
  for(let k = 0, kl = domainAtomsArray.length; k < kl; ++k) {
45726
45886
  let pdb_target = ic.saveFileCls.getAtomPDB(domainAtomsArray[k], undefined, undefined, undefined, undefined, struct);
@@ -45732,7 +45892,7 @@ class LineGraph {
45732
45892
  let atomLast = ic.firstAtomObjCls.getLastAtomObj(domainAtomsArray[k]);
45733
45893
  let resiSum = atomFirst.resi + ':' + atomLast.resi;
45734
45894
  //let domainid = chainid + '-' + k + '_' + Object.keys(domainAtomsArray[k]).length;
45735
- let domainid = chainid + '-' + k + '_' + resiSum;
45895
+ let domainid = chainid + ',' + k + '_' + resiSum;
45736
45896
  ic.domainid2pdb[domainid] = pdb_target;
45737
45897
 
45738
45898
  if(!template) {
@@ -45762,30 +45922,14 @@ class LineGraph {
45762
45922
  }
45763
45923
  }
45764
45924
 
45765
- try {
45925
+ //try {
45766
45926
  if(!template) {
45767
45927
  let dataArray2 = [];
45768
45928
 
45769
45929
  // let allPromise = Promise.allSettled(ajaxArray);
45770
45930
  // dataArray2 = await allPromise;
45771
45931
 
45772
- //split arrays into chunks of 48 jobs or me.cfg.maxajax jobs
45773
- let n = (me.cfg.maxajax) ? me.cfg.maxajax : ic.refpdbArray.length * 6;
45774
-
45775
- for(let i = 0, il = parseInt((ajaxArray.length - 1) / n + 1); i < il; ++i) {
45776
- let currAjaxArray = [];
45777
- if(i == il - 1) { // last one
45778
- currAjaxArray = ajaxArray.slice(i * n, ajaxArray.length);
45779
- }
45780
- else {
45781
- currAjaxArray = ajaxArray.slice(i * n, (i + 1) * n);
45782
- }
45783
-
45784
- let currPromise = Promise.allSettled(currAjaxArray);
45785
- let currDataArray = await currPromise;
45786
-
45787
- dataArray2 = dataArray2.concat(currDataArray);
45788
- }
45932
+ dataArray2 = await this.promiseWithFixedJobs(ajaxArray);
45789
45933
 
45790
45934
  let bRound1 = true;
45791
45935
  await thisClass.parseAlignData(dataArray2, domainidpairArray, bRound1);
@@ -45805,12 +45949,14 @@ class LineGraph {
45805
45949
  let pdbAjaxArray = [];
45806
45950
  pdbAjaxArray.push(pdbAjax);
45807
45951
 
45808
- let allPromise2 = Promise.allSettled(pdbAjaxArray);
45809
- ic.pdbDataArray = await allPromise2;
45952
+ //let allPromise2 = Promise.allSettled(pdbAjaxArray);
45953
+ //ic.pdbDataArray = await allPromise2;
45954
+
45955
+ ic.pdbDataArray = await this.promiseWithFixedJobs(pdbAjaxArray);
45810
45956
 
45811
45957
  for(let domainid in ic.domainid2refpdbname) {
45812
- let refpdbname = ic.domainid2refpdbname[domainid];
45813
- let chainid = domainid.substr(0, domainid.indexOf('-'));
45958
+ ic.domainid2refpdbname[domainid];
45959
+ domainid.substr(0, domainid.indexOf(','));
45814
45960
 
45815
45961
  let pdb_target = ic.domainid2pdb[domainid];
45816
45962
  for(let index = 0, indexl = ic.pdbDataArray.length; index < indexl; ++index) {
@@ -45830,11 +45976,14 @@ class LineGraph {
45830
45976
  }
45831
45977
 
45832
45978
  let dataArray3 = [];
45833
- let allPromise = Promise.allSettled(ajaxArray);
45834
- dataArray3 = await allPromise;
45979
+ //let allPromise = Promise.allSettled(ajaxArray);
45980
+ //dataArray3 = await allPromise;
45981
+
45982
+ dataArray3 = await this.promiseWithFixedJobs(ajaxArray);
45835
45983
 
45836
45984
  await thisClass.parseAlignData(dataArray3, domainidpairArray3);
45837
45985
  }
45986
+ /*
45838
45987
  }
45839
45988
  catch(err) {
45840
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...";
@@ -45846,17 +45995,23 @@ class LineGraph {
45846
45995
  }
45847
45996
  //console.log("Error in aligning with TM-align...");
45848
45997
  return;
45849
- }
45998
+ }
45999
+ */
45850
46000
  }
45851
46001
 
45852
46002
  getTemplateList(chainid) { let ic = this.icn3d; ic.icn3dui;
45853
- let domainid2refpdbname = {};
46003
+ let domainid2refpdbname = {}, domainid2score = {};
45854
46004
 
45855
46005
  for(let i = 0, il = ic.chainid2refpdbname[chainid].length; i < il; ++i) {
45856
46006
  let refpdbname_domainid = ic.chainid2refpdbname[chainid][i].split('|');
45857
46007
  domainid2refpdbname[refpdbname_domainid[1]] = refpdbname_domainid[0];
45858
46008
  }
45859
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
+
45860
46015
  let domainidArray = Object.keys(domainid2refpdbname);
45861
46016
  domainidArray.sort(function(id1, id2) {
45862
46017
  let resi1 = parseInt(id1.substr(id1.lastIndexOf('_') + 1));
@@ -45864,13 +46019,28 @@ class LineGraph {
45864
46019
  return resi1 - resi2;
45865
46020
  });
45866
46021
 
45867
- 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 = '';
45868
46029
  for(let i = 0, il = domainidArray.length; i < il; ++i) {
45869
- chainList += domainid2refpdbname[domainidArray[i]];
45870
- 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
+ }
45871
46041
  }
45872
46042
 
45873
- return chainList;
46043
+ return {'refpdbnameList': refpdbnameList, 'scoreList': scoreList, 'seqidList': seqidList, 'nresAlignList': nresAlignList};
45874
46044
  }
45875
46045
 
45876
46046
  async parseAlignData(dataArray, domainidpairArray, bRound1) { let ic = this.icn3d, me = ic.icn3dui;
@@ -45879,33 +46049,35 @@ class LineGraph {
45879
46049
  let tmscoreThreshold = 0.4; // 0.4; //0.5;
45880
46050
 
45881
46051
  // find the best alignment for each chain
45882
- let domainid2score = {}, domainid2segs = {}, chainid2segs = {};
46052
+ let domainid2segs = {}, chainid2segs = {};
45883
46053
 
45884
46054
  if(!ic.chainid2refpdbname) ic.chainid2refpdbname = {};
46055
+ if(!ic.chainid2score) ic.chainid2score = {};
45885
46056
  if(!ic.domainid2refpdbname) ic.domainid2refpdbname = {};
46057
+ if(!ic.domainid2score) ic.domainid2score = {};
45886
46058
  if(!ic.domainid2ig2kabat) ic.domainid2ig2kabat = {};
45887
46059
  if(!ic.domainid2ig2imgt) ic.domainid2ig2imgt = {};
45888
46060
 
45889
- // ic.chainid2refpdbname = {};
45890
- // ic.domainid2refpdbname = {};
45891
- // ic.domainid2ig2kabat = {};
45892
- // ic.domainid2ig2imgt = {};
45893
-
45894
46061
  let minResidues = 20;
45895
46062
 
45896
46063
  for(let i = 0, il = domainidpairArray.length; i < il; ++i) {
45897
46064
  //let queryData = (me.bNode) ? dataArray[i] : dataArray[i].value; //[0];
45898
46065
  let queryData = dataArray[i].value; //[0];
45899
46066
 
45900
- if(!queryData) {
46067
+ if(!queryData || queryData.length == 0) {
45901
46068
  if(!me.bNode) console.log("The alignment data for " + domainidpairArray[i] + " is unavailable...");
45902
46069
  continue;
45903
46070
  }
45904
-
45905
- if(queryData.length == 0) continue;
45906
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
+
45907
46078
  if(!bRound1) {
45908
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);
45909
46081
  continue;
45910
46082
  }
45911
46083
  }
@@ -45917,12 +46089,6 @@ class LineGraph {
45917
46089
  continue;
45918
46090
  }
45919
46091
  }
45920
-
45921
- //let domainid_index = domainidpairArray[i].split(',');
45922
- //let domainid = domainid_index[0];
45923
- let domainid = domainidpairArray[i].substr(0, domainidpairArray[i].indexOf('|'));
45924
- let refpdbname = domainidpairArray[i].substr(domainidpairArray[i].indexOf('|') + 1);
45925
- //let chainid = domainid.split('-')[0];
45926
46092
 
45927
46093
  if(!bRound1) {
45928
46094
  if(!me.bNode) console.log("refpdbname " + refpdbname + " TM-score: " + queryData[0].score);
@@ -45939,16 +46105,16 @@ class LineGraph {
45939
46105
  for(let i = 0, il = queryData[0].segs.length; i < il; ++i) {
45940
46106
  let seg = queryData[0].segs[i];
45941
46107
 
45942
- if(seg.q_start.indexOf('2150') != -1 || seg.q_start.indexOf('2250') != -1) {
46108
+ if(seg.q_start.indexOf('2550') != -1) {
45943
46109
  bBstrand = true;
45944
46110
  }
45945
- else if(seg.q_start.indexOf('3150') != -1 || seg.q_start.indexOf('3250') != -1) {
46111
+ else if(seg.q_start.indexOf('3550') != -1) {
45946
46112
  bCstrand = true;
45947
46113
  }
45948
- else if(seg.q_start.indexOf('7150') != -1 || seg.q_start.indexOf('7250') != -1) {
46114
+ else if(seg.q_start.indexOf('7550') != -1) {
45949
46115
  bEstrand = true;
45950
46116
  }
45951
- else if(seg.q_start.indexOf('8150') != -1 || seg.q_start.indexOf('8250') != -1) {
46117
+ else if(seg.q_start.indexOf('8550') != -1) {
45952
46118
  bFstrand = true;
45953
46119
  }
45954
46120
 
@@ -45959,35 +46125,25 @@ class LineGraph {
45959
46125
  //if(!(bBstrand && bCstrand && bEstrand && bFstrand && bGstrand)) continue;
45960
46126
  if(!(bBstrand && bCstrand && bEstrand && bFstrand)) {
45961
46127
  if(!me.bNode) console.log("Some of the Ig strands B, C, E, F are missing in the domain " + domainid + "...");
45962
- 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
+ }
45963
46132
  continue;
45964
46133
  }
45965
46134
  }
45966
46135
 
45967
46136
  if(!bRound1) {
45968
46137
  console.log("domainid: " + domainid);
45969
-
45970
- if(!domainid2score.hasOwnProperty(domainid) || queryData[0].score > domainid2score[domainid]) {
45971
- domainid2score[domainid] = queryData[0].score;
45972
-
45973
- ic.domainid2refpdbname[domainid] = refpdbname;
45974
- domainid2segs[domainid] = queryData[0].segs;
45975
- ic.domainid2ig2kabat[domainid] = queryData[0].ig2kabat;
45976
- ic.domainid2ig2imgt[domainid] = queryData[0].ig2imgt;
45977
- }
45978
46138
  }
45979
- else {
45980
- //let mixScore = 10 / queryData[0].super_rmsd + queryData[0].num_seg / 5;
45981
- let mixScore = queryData[0].score;
45982
46139
 
45983
- if(!domainid2score.hasOwnProperty(domainid) || mixScore > domainid2score[domainid]) {
45984
- domainid2score[domainid] = mixScore;
45985
-
45986
- ic.domainid2refpdbname[domainid] = refpdbname;
45987
- domainid2segs[domainid] = queryData[0].segs;
45988
- ic.domainid2ig2kabat[domainid] = queryData[0].ig2kabat;
45989
- ic.domainid2ig2imgt[domainid] = queryData[0].ig2imgt;
45990
- }
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;
45991
46147
  }
45992
46148
  }
45993
46149
 
@@ -46002,7 +46158,7 @@ class LineGraph {
46002
46158
  let pdbAjaxArray = [];
46003
46159
  let refpdbname = ic.domainid2refpdbname[domainid];
46004
46160
  //let pdbid = domainid.substr(0, domainid.indexOf('_'));
46005
- let chainid = domainid.substr(0, domainid.indexOf('-'));
46161
+ let chainid = domainid.substr(0, domainid.indexOf(','));
46006
46162
 
46007
46163
  //if(ic.refpdbHash.hasOwnProperty(pdbid)) {
46008
46164
  if(ic.refpdbHash.hasOwnProperty(chainid)) {
@@ -46025,8 +46181,10 @@ class LineGraph {
46025
46181
  pdbAjaxArray.push(pdbAjax);
46026
46182
  }
46027
46183
 
46028
- let allPromise2 = Promise.allSettled(pdbAjaxArray);
46029
- ic.pdbDataArray = await allPromise2;
46184
+ //let allPromise2 = Promise.allSettled(pdbAjaxArray);
46185
+ //ic.pdbDataArray = await allPromise2;
46186
+
46187
+ ic.pdbDataArray = await this.promiseWithFixedJobs(pdbAjaxArray);
46030
46188
 
46031
46189
  let pdb_target = ic.domainid2pdb[domainid];
46032
46190
  for(let index = 0, indexl = ic.pdbDataArray.length; index < indexl; ++index) {
@@ -46049,49 +46207,46 @@ class LineGraph {
46049
46207
  //let allPromise = Promise.allSettled(ajaxArray);
46050
46208
  //dataArray3 = await allPromise;
46051
46209
 
46052
- //split arrays into chunks of 48 jobs or me.cfg.maxajax jobs
46053
- let n = (me.cfg.maxajax) ? me.cfg.maxajax : ic.refpdbArray.length * 6;
46054
-
46055
- for(let i = 0, il = parseInt((ajaxArray.length - 1) / n + 1); i < il; ++i) {
46056
- let currAjaxArray = [];
46057
- if(i == il - 1) { // last one
46058
- currAjaxArray = ajaxArray.slice(i * n, ajaxArray.length);
46059
- }
46060
- else {
46061
- currAjaxArray = ajaxArray.slice(i * n, (i + 1) * n);
46062
- }
46063
-
46064
- let currPromise = Promise.allSettled(currAjaxArray);
46065
- let currDataArray = await currPromise;
46066
-
46067
- dataArray3 = dataArray3.concat(currDataArray);
46068
- }
46210
+ dataArray3 = await this.promiseWithFixedJobs(ajaxArray);
46069
46211
 
46070
46212
  await thisClass.parseAlignData(dataArray3, domainidpairArray3, false);
46071
46213
 
46072
46214
  // end of round 2
46073
46215
  return;
46074
46216
  }
46075
-
46217
+
46076
46218
  // combine domainid into chainid
46077
46219
  let processedChainid = {};
46078
46220
  for(let domainid in ic.domainid2refpdbname) {
46079
- 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
+ }
46227
+
46228
+ let chainid = domainid.split(',')[0];
46080
46229
 
46081
- if(!processedChainid.hasOwnProperty(chainid)) ic.chainid2refpdbname[chainid] = [];
46230
+ if(!processedChainid.hasOwnProperty(chainid)) {
46231
+ ic.chainid2refpdbname[chainid] = [];
46232
+ ic.chainid2score[chainid] = [];
46233
+ }
46082
46234
  processedChainid[chainid] = 1;
46083
46235
 
46084
46236
  if(!ic.chainid2refpdbname.hasOwnProperty(chainid)) ic.chainid2refpdbname[chainid] = [];
46085
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);
46086
46241
  }
46087
-
46242
+
46088
46243
  // combine domainid into chainid
46089
46244
  for(let domainid in domainid2segs) {
46090
- let chainid = domainid.split('-')[0];
46245
+ let chainid = domainid.split(',')[0];
46091
46246
  if(!chainid2segs[chainid]) chainid2segs[chainid] = [];
46092
46247
  chainid2segs[chainid] = chainid2segs[chainid].concat(domainid2segs[domainid]);
46093
46248
  }
46094
-
46249
+
46095
46250
  // assign ic.resid2refnum, ic.refnum2residArray, ic.chainsMapping
46096
46251
  if(!ic.resid2refnum) ic.resid2refnum = {};
46097
46252
  if(!ic.refnum2residArray) ic.refnum2residArray = {};
@@ -46104,11 +46259,18 @@ class LineGraph {
46104
46259
 
46105
46260
  let refpdbnameArray = ic.chainid2refpdbname[chainid];
46106
46261
 
46107
- 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;
46108
46267
 
46109
- //if(!me.bNode) console.log("The reference PDB(s) for chain " + chainid + " are " + chainList);
46110
- if(!me.bNode) console.log("The reference PDB(s) for chain " + chainid + " are " + chainList);
46111
- 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);
46112
46274
 
46113
46275
  let prevStrand;
46114
46276
  let bCd19 = refpdbnameArray.length == 1 && refpdbnameArray[0] == 'CD19_6al5A_human_C2orV-n1';
@@ -46178,51 +46340,52 @@ class LineGraph {
46178
46340
  getLabelFromRefnum(oriRefnum, prevStrand, bCd19) { let ic = this.icn3d; ic.icn3dui;
46179
46341
  let refnum = parseInt(oriRefnum);
46180
46342
 
46181
- // A-: 10xx
46182
- // A: 11xx
46183
- // A+ continue A
46184
- // A': 12xx
46185
- // B: 21xx
46186
- // C: 32xx
46187
- // C': 42xx
46188
- // C'': 51xx, 52xx
46189
- // D: 61xx
46190
- // E: 71xx
46191
- // E+: continue E
46192
- // F: 82xx
46193
- // G: 91xx, 92xx
46194
- // G+: continue G
46195
-
46196
- // if(refnum < 100) return " " + oriRefnum;
46197
- // else if(refnum >= 100 && refnum < 1000) {
46198
- // if(bCd19) return " " + oriRefnum;
46199
- // else return "A^" + oriRefnum;
46200
- // }
46201
- if(refnum < 900) return undefined;
46202
- else if(refnum >= 900 && refnum < 1000) return " " + oriRefnum;
46203
- else if(refnum >= 1000 && refnum < 1100) return "A-" + oriRefnum;
46204
- else if(refnum >= 1100 && refnum < 1200) return "A" + oriRefnum; // could be A+
46205
- else if(refnum >= 1200 && refnum < 1300) return "A'" + oriRefnum;
46206
- //else if(refnum >= 1300 && refnum < 1400) return "A+" + oriRefnum;
46207
- else if(refnum >= 1300 && refnum < 2000) {
46208
- if(prevStrand && prevStrand.substr(0, 1) == 'A') {
46209
- return prevStrand + oriRefnum;
46210
- }
46211
- else {
46212
- return "A" + oriRefnum;
46213
- }
46214
- }
46215
- else if(refnum >= 2000 && refnum < 3000) return "B" + oriRefnum;
46216
- else if(refnum >= 3000 && refnum < 4000) return "C" + oriRefnum;
46217
- else if(refnum >= 4000 && refnum < 5000) return "C'" + oriRefnum;
46218
- else if(refnum >= 5000 && refnum < 6000) return "C''" + oriRefnum;
46219
- else if(refnum >= 6000 && refnum < 7000) return "D" + oriRefnum;
46220
- else if(refnum >= 7000 && refnum < 8000) return "E" + oriRefnum; // could be E+
46221
- else if(refnum >= 8000 && refnum < 9000) return "F" + oriRefnum;
46222
- else if(refnum >= 9000 && refnum < 9300) return "G" + oriRefnum; // could be G+
46223
- //else if(refnum >= 9400 && refnum < 9500) return "G+" + oriRefnum;
46224
- else if(refnum >= 9300) return "G" + oriRefnum;
46225
- }
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; }
46226
46389
 
46227
46390
  async parseCustomRefFile(data) { let ic = this.icn3d; ic.icn3dui;
46228
46391
  ic.bShowCustomRefnum = true;
@@ -46404,6 +46567,32 @@ class LineGraph {
46404
46567
  return refData;
46405
46568
  }
46406
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
+ }
46407
46596
  }
46408
46597
 
46409
46598
  /**
@@ -47712,7 +47901,7 @@ class ViewInterPairs {
47712
47901
 
47713
47902
  if(ic.bD3 === undefined) {
47714
47903
  //let url = "https://d3js.org/d3.v4.min.js";
47715
- 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";
47716
47905
  await me.getAjaxPromise(url, 'script');
47717
47906
 
47718
47907
  ic.bD3 = true;
@@ -48987,7 +49176,7 @@ class AlignParser {
48987
49176
  for(let j = 0, jl = mmdbTmp.molecules.length; j < jl; ++j) {
48988
49177
  let molecule = mmdbTmp.molecules[j];
48989
49178
  let molid = molecule.moleculeId;
48990
- let chainName = molecule.chain.trim();
49179
+ let chainName = molecule.chain.trim().replace(/_/g, ''); // change "A_1" to "A1"
48991
49180
  if(chainNameHash[chainName] === undefined) {
48992
49181
  chainNameHash[chainName] = 1;
48993
49182
  }
@@ -49398,6 +49587,8 @@ class ChainalignParser {
49398
49587
 
49399
49588
  let queryData = {}; // check whether undefined
49400
49589
 
49590
+ me.htmlCls.clickMenuCls.setLogCmd("Align " + mmdbid_t + " with " + mmdbid_q, false);
49591
+
49401
49592
  this.processAlign(align, index, queryData, bEqualMmdbid, bEqualChain);
49402
49593
  }
49403
49594
 
@@ -49495,6 +49686,8 @@ class ChainalignParser {
49495
49686
  continue;
49496
49687
  }
49497
49688
 
49689
+ me.htmlCls.clickMenuCls.setLogCmd("Align " + mmdbid1 + " with " + mmdbid2, false);
49690
+
49498
49691
  let bNoAlert = true;
49499
49692
  let bAligned = this.processAlign(align, i, queryData, bEqualMmdbid, bEqualChain, bNoAlert);
49500
49693
 
@@ -49945,6 +50138,8 @@ class ChainalignParser {
49945
50138
  let bEqualMmdbid = (mmdbid_q == mmdbid_t);
49946
50139
  let bEqualChain = (chain_q == chain_t);
49947
50140
 
50141
+ me.htmlCls.clickMenuCls.setLogCmd("Align " + mmdbid_t + " with " + mmdbid_q, false);
50142
+
49948
50143
  this.processAlign(align, index-1, queryData, bEqualMmdbid, bEqualChain);
49949
50144
  }
49950
50145
  }
@@ -50005,6 +50200,7 @@ class ChainalignParser {
50005
50200
  ic.qt_start_end[index] = align[0].segs;
50006
50201
 
50007
50202
  let rmsd = align[0].super_rmsd;
50203
+ console.log();
50008
50204
 
50009
50205
  let logStr = "alignment RMSD: " + rmsd.toPrecision(4);
50010
50206
  if(me.cfg.aligntool == 'tmalign') logStr += "; TM-score: " + align[0].score.toPrecision(4);
@@ -50274,10 +50470,10 @@ class Dsn6Parser {
50274
50470
  // https://edmaps.rcsb.org/maps/1kq2_fofc.dsn6
50275
50471
 
50276
50472
  let url = "https://edmaps.rcsb.org/maps/" + pdbid.toLowerCase() + "_" + type + ".dsn6";
50277
- await this.dsn6ParserBase(url, type, sigma);
50473
+ await this.dsn6ParserBase(url, type, sigma, 'url', true);
50278
50474
  }
50279
50475
 
50280
- 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;
50281
50477
  let thisClass = this;
50282
50478
 
50283
50479
  //https://stackoverflow.com/questions/33902299/using-jquery-ajax-to-download-a-binary-file
@@ -50291,7 +50487,7 @@ class Dsn6Parser {
50291
50487
  }
50292
50488
  else {
50293
50489
  let arrayBuffer = await me.getXMLHttpRqstPromise(url, 'GET', 'arraybuffer', 'rcsbEdmaps');
50294
- thisClass.loadDsn6Data(arrayBuffer, type, sigma);
50490
+ sigma = thisClass.loadDsn6Data(arrayBuffer, type, sigma, location, bInputSigma);
50295
50491
 
50296
50492
  if(type == '2fofc') {
50297
50493
  ic.bAjax2fofc = true;
@@ -50302,9 +50498,11 @@ class Dsn6Parser {
50302
50498
 
50303
50499
  ic.setOptionCls.setOption('map', type);
50304
50500
  }
50501
+
50502
+ return sigma;
50305
50503
  }
50306
50504
 
50307
- loadDsn6Data(dsn6data, type, sigma) { let ic = this.icn3d; ic.icn3dui;
50505
+ loadDsn6Data(dsn6data, type, sigma, location, bInputSigma) { let ic = this.icn3d; ic.icn3dui;
50308
50506
  // DSN6 http://www.uoxray.uoregon.edu/tnt/manual/node104.html
50309
50507
  // BRIX http://svn.cgl.ucsf.edu/svn/chimera/trunk/libs/VolumeData/dsn6/brix-1.html
50310
50508
 
@@ -50353,9 +50551,9 @@ class Dsn6Parser {
50353
50551
  }
50354
50552
  }
50355
50553
 
50356
- header.zStart = intView[ 2 ];
50357
50554
  header.xStart = intView[ 0 ]; // NXSTART
50358
50555
  header.yStart = intView[ 1 ];
50556
+ header.zStart = intView[ 2 ];
50359
50557
 
50360
50558
  header.xExtent = intView[ 3 ]; // NX
50361
50559
  header.yExtent = intView[ 4 ];
@@ -50391,6 +50589,7 @@ class Dsn6Parser {
50391
50589
  let zBlocks = Math.ceil(header.zExtent / 8);
50392
50590
 
50393
50591
  // loop over blocks
50592
+ let maxValue = -999;
50394
50593
  for(let zz = 0; zz < zBlocks; ++zz) {
50395
50594
  for(let yy = 0; yy < yBlocks; ++yy) {
50396
50595
  for(let xx = 0; xx < xBlocks; ++xx) {
@@ -50406,6 +50605,7 @@ class Dsn6Parser {
50406
50605
  if(x < header.xExtent && y < header.yExtent && z < header.zExtent) {
50407
50606
  let idx =((((x * header.yExtent) + y) * header.zExtent) + z);
50408
50607
  data[ idx ] =(byteView[ offset ] - summand) / divisor;
50608
+ if(data[ idx ] > maxValue) maxValue = data[ idx ];
50409
50609
  ++offset;
50410
50610
  } else {
50411
50611
  offset += 8 - i;
@@ -50418,6 +50618,10 @@ class Dsn6Parser {
50418
50618
  }
50419
50619
  }
50420
50620
 
50621
+ if(!bInputSigma) {
50622
+ sigma = this.setSigma(maxValue, location, type, sigma);
50623
+ }
50624
+
50421
50625
  if(type == '2fofc') {
50422
50626
  ic.mapData.header2 = header;
50423
50627
  ic.mapData.data2 = data;
@@ -50432,6 +50636,32 @@ class Dsn6Parser {
50432
50636
  ic.mapData.type = type;
50433
50637
  ic.mapData.sigma = sigma;
50434
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;
50435
50665
  }
50436
50666
 
50437
50667
  getMatrix(header) { let ic = this.icn3d; ic.icn3dui;
@@ -50505,7 +50735,9 @@ class Dsn6Parser {
50505
50735
  let reader = new FileReader();
50506
50736
  reader.onload = function(e) { let ic = thisClass.icn3d;
50507
50737
  let arrayBuffer = e.target.result; // or = reader.result;
50508
- thisClass.loadDsn6Data(arrayBuffer, type, sigma);
50738
+
50739
+ sigma = thisClass.loadDsn6Data(arrayBuffer, type, sigma, 'file');
50740
+
50509
50741
  if(type == '2fofc') {
50510
50742
  ic.bAjax2fofc = true;
50511
50743
  }
@@ -50513,21 +50745,1006 @@ class Dsn6Parser {
50513
50745
  ic.bAjaxfofc = true;
50514
50746
  }
50515
50747
  ic.setOptionCls.setOption('map', type);
50516
- 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);
50517
50749
  };
50518
50750
  reader.readAsArrayBuffer(file);
50519
50751
  }
50520
50752
  }
50521
50753
 
50522
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;
51061
+ let url = $("#" + ic.pre + "dsn6fileurl" + type).val();
51062
+ let sigma = $("#" + ic.pre + "dsn6sigmaurl" + type).val();
51063
+ if(!url) {
51064
+ var aaa = 1; //alert("Please input the file URL before clicking 'Load'");
51065
+ }
51066
+ else {
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;
50523
51738
  let url = $("#" + ic.pre + "dsn6fileurl" + type).val();
50524
51739
  let sigma = $("#" + ic.pre + "dsn6sigmaurl" + type).val();
50525
51740
  if(!url) {
50526
51741
  var aaa = 1; //alert("Please input the file URL before clicking 'Load'");
50527
51742
  }
50528
51743
  else {
50529
- this.dsn6ParserBase(url, type, sigma);
50530
- me.htmlCls.clickMenuCls.setLogCmd('set map ' + type + ' sigma ' + sigma + ' | ' + encodeURIComponent(url), true);
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);
50531
51748
  }
50532
51749
  }
50533
51750
 
@@ -53299,7 +54516,7 @@ class DensityCifParser {
53299
54516
  this.icn3d = icn3d;
53300
54517
  }
53301
54518
 
53302
- 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;
53303
54520
  let thisClass = this;
53304
54521
 
53305
54522
  let url;
@@ -53361,6 +54578,9 @@ class DensityCifParser {
53361
54578
  ic.mapData.header2 = header;
53362
54579
 
53363
54580
  ic.mapData.data2 = density.data;
54581
+ for(let i = 0; i < density.data.length; ++i) {
54582
+ density.data[i];
54583
+ }
53364
54584
 
53365
54585
  let origin = density.box.origin;
53366
54586
  let dimensions = density.box.dimensions;
@@ -53395,6 +54615,7 @@ class DensityCifParser {
53395
54615
  origin = density.box.origin;
53396
54616
  dimensions = density.box.dimensions;
53397
54617
  basis = density.spacegroup.basis;
54618
+
53398
54619
  scale = new THREE.Matrix4().makeScale(
53399
54620
  dimensions[0] / (sampleCount[0] ),
53400
54621
  dimensions[1] / (sampleCount[1] ),
@@ -55023,7 +56244,10 @@ class ParserUtils {
55023
56244
 
55024
56245
  if(bAppend) {
55025
56246
  if(ic.bSetChainsAdvancedMenu) ic.definedSetsCls.showSets();
55026
- if(ic.bAnnoShown) await ic.showAnnoCls.showAnnotations();
56247
+ if(ic.bAnnoShown) {
56248
+ await ic.showAnnoCls.showAnnotations();
56249
+ ic.annotationCls.resetAnnoTabAll();
56250
+ }
55027
56251
  }
55028
56252
 
55029
56253
  // Realign by sequence alignment with the residues in "segment", i.e., transmembrane helix
@@ -56353,14 +57577,15 @@ class SetSeqAlign {
56353
57577
 
56354
57578
  if(i > 0) {
56355
57579
  let index1 = alignIndex;
56356
-
57580
+
56357
57581
  for(let j = prevIndex1 + 1, jl = start1; j < jl; ++j) {
56358
- if(posChain1[j]) continue;
57582
+ //if(posChain1[j]) continue;
56359
57583
  posChain1[j] = 1;
56360
57584
 
56361
- if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid1][j] === undefined) break;
57585
+ //if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid1][j] === undefined) break;
56362
57586
 
56363
- let resi = this.getResiAferAlign(chainid1, bRealign, j + 1);
57587
+ //let resi = this.getResiAferAlign(chainid1, bRealign, j + 1);
57588
+ let resi = this.getResiAferAlign(chainid1, bRealign, j);
56364
57589
  // let resn = (bRealign && me.cfg.aligntool == 'tmalign') ? this.getResnFromResi(chainid1, j).toLowerCase() : ic.chainsSeq[chainid1][j].name.toLowerCase();
56365
57590
  let resn = this.getResnFromResi(chainid1, resi).toLowerCase();
56366
57591
 
@@ -56368,24 +57593,25 @@ class SetSeqAlign {
56368
57593
 
56369
57594
  color = me.htmlCls.GREY8;
56370
57595
  classname = 'icn3d-nalign';
56371
-
57596
+
56372
57597
  ic.nalignHash1[chainid1 + '_' + resi] = 1;
56373
57598
  this.setSeqPerResi(chainid1, chainid1, chainid2, resi, resn, false, color, undefined, classname, true, false, index1);
56374
57599
  ++index1;
56375
57600
  }
56376
57601
 
56377
57602
  let index2 = alignIndex;
57603
+
56378
57604
  for(let j = prevIndex2 + 1, jl = start2; j < jl; ++j) {
56379
- if(posChain2[j]) continue;
57605
+ //if(posChain2[j]) continue;
56380
57606
  posChain2[j] = 1;
56381
57607
 
56382
- if(ic.chainsSeq[chainid2] === undefined || ic.chainsSeq[chainid2] === undefined) break;
57608
+ //if(ic.chainsSeq[chainid2] === undefined || ic.chainsSeq[chainid2] === undefined) break;
56383
57609
 
56384
- let resi = this.getResiAferAlign(chainid2, bRealign, j + 1);
57610
+ //let resi = this.getResiAferAlign(chainid2, bRealign, j + 1);
57611
+ let resi = this.getResiAferAlign(chainid2, bRealign, j);
56385
57612
  // let resn = (bRealign && me.cfg.aligntool == 'tmalign') ? this.getResnFromResi(chainid2, j).toLowerCase() : ic.chainsSeq[chainid2][j].name.toLowerCase();
56386
57613
  let resn = this.getResnFromResi(chainid2, resi).toLowerCase();
56387
57614
 
56388
-
56389
57615
  if(resn == '?') continue;
56390
57616
 
56391
57617
  color = me.htmlCls.GREY8;
@@ -56425,7 +57651,7 @@ class SetSeqAlign {
56425
57651
  }
56426
57652
 
56427
57653
  for(let j = 0; j <= end1 - start1; ++j) {
56428
- if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid2] === undefined) break;
57654
+ ///if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid2] === undefined) break;
56429
57655
 
56430
57656
  let resi1, resi2, resn1, resn2;
56431
57657
  /*
@@ -56455,15 +57681,17 @@ class SetSeqAlign {
56455
57681
  if(resn1 == '?' || resn2 == '?') continue;
56456
57682
  }
56457
57683
  else {
56458
- 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;
56459
57685
 
56460
57686
  // resi1 = ic.chainsSeq[chainid1][j + start1].resi;
56461
57687
  // resi2 = ic.chainsSeq[chainid2][j + start2].resi;
56462
57688
  // resn1 = ic.chainsSeq[chainid1][j + start1].name.toUpperCase();
56463
57689
  // resn2 = ic.chainsSeq[chainid2][j + start2].name.toUpperCase();
56464
57690
 
56465
- resi1 = this.getResiAferAlign(chainid1, bRealign, j + start1 + 1);
56466
- 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);
56467
57695
  resn1 = this.getResnFromResi(chainid1, resi1).toUpperCase();
56468
57696
  resn2 = this.getResnFromResi(chainid2, resi2).toUpperCase();
56469
57697
  }
@@ -56926,7 +58154,6 @@ class SetSeqAlign {
56926
58154
  start1Pos = start1;
56927
58155
  end1Pos = end1;
56928
58156
  }
56929
-
56930
58157
  //let range = resi2range_t[resiStart1];
56931
58158
 
56932
58159
  // if the mapping does not start from start_t, add gaps to the query seq
@@ -56950,7 +58177,7 @@ class SetSeqAlign {
56950
58177
  pos2 = result.pos2;
56951
58178
  let notAlnLen1 = pos2 - (pos1 + 1);
56952
58179
  let notAlnLen2 = start2 - (prevIndex2 + 1);
56953
-
58180
+
56954
58181
  // insert non-aligned residues in query seq
56955
58182
  this.insertNotAlignRes(chainid2, prevIndex2+1, notAlnLen2, bRealign);
56956
58183
 
@@ -61513,14 +62740,15 @@ class LoadScript {
61513
62740
  let bFinalStep =(i === steps - 1) ? true : false;
61514
62741
 
61515
62742
  if(!ic.commands[i].trim()) continue;
61516
- let nAtoms = Object.keys(ic.atoms).length;
62743
+ let nAtoms = (ic.atoms) ? Object.keys(ic.atoms).length : 0;
61517
62744
 
61518
62745
  if(nAtoms == 0 && ic.commands[i].indexOf('load') == -1) continue;
61519
62746
 
61520
62747
  let strArray = ic.commands[i].split("|||");
61521
62748
  let command = strArray[0].trim();
61522
62749
 
61523
- 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;
61524
62752
 
61525
62753
  if(command.indexOf('load') !== -1) {
61526
62754
  if(end === 0 && start === end) {
@@ -61556,18 +62784,7 @@ class LoadScript {
61556
62784
  }
61557
62785
  }
61558
62786
  else if(command.indexOf('set map') == 0 && command.indexOf('set map wireframe') == -1) {
61559
- //set map 2fofc sigma 1.5
61560
- let urlArray = strArray[0].trim().split(' | ');
61561
-
61562
- let str = urlArray[0].substr(8);
61563
- let paraArray = str.split(" ");
61564
-
61565
- if(paraArray.length == 3 && paraArray[1] == 'sigma') {
61566
- paraArray[2];
61567
- paraArray[0];
61568
-
61569
- await thisClass.applyCommandMap(strArray[0].trim());
61570
- }
62787
+ await thisClass.applyCommandMap(strArray[0].trim());
61571
62788
  }
61572
62789
  else if(command.indexOf('set emmap') == 0 && command.indexOf('set emmap wireframe') == -1) {
61573
62790
  //set emmap percentage 70
@@ -61932,8 +63149,10 @@ class LoadScript {
61932
63149
  let id = loadStr.substr(loadStr.lastIndexOf(' ') + 1);
61933
63150
  if(id.length == 4) id = id.toUpperCase();
61934
63151
 
61935
- // skip loading the structure if it was loaded before
61936
- if(ic.structures && ic.structures.hasOwnProperty(id)) return;
63152
+ // skip loading the structure if
63153
+ // 1. PDB was in the iCn3D PNG Image file
63154
+ // 2. it was loaded before
63155
+ if(ic.bInputPNGWithData || (ic.structures && ic.structures.hasOwnProperty(id))) return;
61937
63156
 
61938
63157
  ic.inputid = id;
61939
63158
  if(command.indexOf('load mmtf') !== -1) {
@@ -62065,17 +63284,34 @@ class LoadScript {
62065
63284
  // ic.deferredMap = $.Deferred(function() { let ic = thisClass.icn3d;
62066
63285
  //"set map 2fofc sigma 1.5"
62067
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]"
62068
63291
  let urlArray = command.split(" | ");
62069
63292
 
62070
63293
  let str = urlArray[0].substr(8);
62071
63294
  let paraArray = str.split(" ");
62072
63295
 
62073
- if(paraArray.length == 3 && paraArray[1] == 'sigma') {
63296
+ //if(paraArray.length == 3 && paraArray[1] == 'sigma') {
63297
+ if(paraArray[1] == 'sigma') {
62074
63298
  let sigma = paraArray[2];
62075
63299
  let type = paraArray[0];
62076
63300
 
63301
+ let fileType = 'dsn6';
63302
+ if(paraArray.length == 5) fileType = paraArray[4];
63303
+
62077
63304
  if(urlArray.length == 2) {
62078
- 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
+ }
62079
63315
  }
62080
63316
  else {
62081
63317
  await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma);
@@ -71019,7 +72255,7 @@ class Ray {
71019
72255
  }
71020
72256
 
71021
72257
  // from iview (http://istar.cse.cuhk.edu.hk/iview/)
71022
- getAtomsFromPosition(point, threshold) { let ic = this.icn3d, me = ic.icn3dui;
72258
+ getAtomsFromPosition(point, threshold, atoms) { let ic = this.icn3d, me = ic.icn3dui;
71023
72259
  let i;
71024
72260
 
71025
72261
  if(threshold === undefined || threshold === null) {
@@ -71027,7 +72263,8 @@ class Ray {
71027
72263
  }
71028
72264
 
71029
72265
  //for (i in ic.atoms) {
71030
- for (i in ic.dAtoms) {
72266
+ let atomHash = (atoms) ? atoms : ic.dAtoms;
72267
+ for (i in atomHash) {
71031
72268
  let atom = ic.atoms[i];
71032
72269
 
71033
72270
  if(ic.ions.hasOwnProperty(i) && ic.opts['ions'] === 'sphere') {
@@ -71099,7 +72336,7 @@ class Control {
71099
72336
  ic.typetext = false;
71100
72337
  });
71101
72338
 
71102
- $(document).bind('keydown', function (e) {
72339
+ $(document).bind('keydown', async function (e) {
71103
72340
  //document.addEventListener('keydown', function (e) {
71104
72341
  if(e.shiftKey || e.keyCode === 16) {
71105
72342
  ic.bShift = true;
@@ -71237,7 +72474,7 @@ class Control {
71237
72474
 
71238
72475
  else if(e.keyCode === 65 ) { // A, alternate
71239
72476
  if(Object.keys(ic.structures).length > 1) {
71240
- ic.alternateCls.alternateWrapper();
72477
+ await ic.alternateCls.alternateWrapper();
71241
72478
  }
71242
72479
  }
71243
72480
 
@@ -71420,13 +72657,25 @@ class Picking {
71420
72657
  y += me.htmlCls.MENU_HEIGHT;
71421
72658
  }
71422
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;
71423
72662
  if(ic.structures !== undefined && Object.keys(ic.structures).length > 1) {
71424
- text = atom.structure + '_' + atom.chain + ' ' + text;
71425
- $("#" + 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");
71426
72666
  }
71427
72667
  else {
71428
- $("#" + ic.pre + "popup").css("width", "80px");
72668
+ textWidth = (ic.chainid2refpdbname && ic.chainid2refpdbname[chainid]) ? 80 + 80 : 80;
72669
+ $("#" + ic.pre + "popup").css("width", textWidth + "px");
71429
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
+
71430
72679
  $("#" + ic.pre + "popup").html(text);
71431
72680
  $("#" + ic.pre + "popup").css("top", y).css("left", x+20).show();
71432
72681
  }
@@ -72587,6 +73836,8 @@ class iCn3D {
72587
73836
  this.alignParserCls = new AlignParser(this);
72588
73837
  this.chainalignParserCls = new ChainalignParser(this);
72589
73838
  this.dsn6ParserCls = new Dsn6Parser(this);
73839
+ this.ccp4ParserCls = new Ccp4Parser(this);
73840
+ this.mtzParserCls = new MtzParser(this);
72590
73841
  this.mmcifParserCls = new MmcifParser(this);
72591
73842
  this.mmdbParserCls = new MmdbParser(this);
72592
73843
  this.mmtfParserCls = new MmtfParser(this);
@@ -72849,7 +74100,7 @@ class iCn3DUI {
72849
74100
  //even when multiple iCn3D viewers are shown together.
72850
74101
  this.pre = this.cfg.divid + "_";
72851
74102
 
72852
- this.REVISION = '3.28.4';
74103
+ this.REVISION = '3.29.0';
72853
74104
 
72854
74105
  // In nodejs, iCn3D defines "window = {navigator: {}}"
72855
74106
  this.bNode = (Object.keys(window).length < 2) ? true : false;