icn3d 3.28.12 → 3.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/icn3d.js +1570 -330
  2. package/icn3d.min.js +7 -5
  3. package/icn3d.module.js +1570 -330
  4. package/package.json +1 -1
package/icn3d.module.js CHANGED
@@ -6860,7 +6860,7 @@ class ClickMenu {
6860
6860
  });
6861
6861
 
6862
6862
  me.myEventCls.onIds("#" + me.pre + "mn1_dsn6", "click", function(e) { me.icn3d; //e.preventDefault();
6863
- me.htmlCls.dialogCls.openDlg('dl_dsn6', 'Please input the DSN6 file to display electron density map');
6863
+ me.htmlCls.dialogCls.openDlg('dl_dsn6', 'Please input the map file to display electron density map');
6864
6864
  });
6865
6865
 
6866
6866
 
@@ -6887,7 +6887,7 @@ class ClickMenu {
6887
6887
 
6888
6888
 
6889
6889
  me.myEventCls.onIds("#" + me.pre + "mn1_dsn6url", "click", function(e) { me.icn3d; //e.preventDefault();
6890
- me.htmlCls.dialogCls.openDlg('dl_dsn6url', 'Please input the DSN6 file to display electron density map');
6890
+ me.htmlCls.dialogCls.openDlg('dl_dsn6url', 'Please input the map file to display electron density map');
6891
6891
  });
6892
6892
 
6893
6893
  me.myEventCls.onIds("#" + me.pre + "mn1_exportState", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
@@ -8192,6 +8192,8 @@ class ClickMenu {
8192
8192
  let sigma2fofc = parseFloat($("#" + me.pre + "sigma2fofc" ).val());
8193
8193
  let type = '2fofc';
8194
8194
  await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma2fofc);
8195
+ //ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma2fofc);
8196
+
8195
8197
  //ic.setOptionCls.setOption('map', '2fofc');
8196
8198
  thisClass.setLogCmd('set map 2fofc sigma ' + sigma2fofc, true);
8197
8199
  });
@@ -9448,12 +9450,14 @@ class SetMenu {
9448
9450
 
9449
9451
  html += this.getMenuSep();
9450
9452
 
9451
- html += this.getMenuText('mn1_dsn6wrap', 'Electron Density(DSN6)', undefined, undefined, 2);
9453
+ html += this.getMenuText('mn1_dsn6wrap', 'Electron Density', undefined, undefined, 2);
9452
9454
  html += "<ul>";
9453
9455
  html += this.getLink('mn1_dsn6', 'Local File', undefined, 3);
9454
9456
  html += this.getLink('mn1_dsn6url', 'URL(CORS) ' + me.htmlCls.wifiStr, undefined, 3);
9455
9457
  html += "</ul>";
9456
9458
 
9459
+ html += "<li><br/></li>";
9460
+
9457
9461
  html += "</ul>";
9458
9462
  html += "</li>";
9459
9463
 
@@ -9559,14 +9563,14 @@ class SetMenu {
9559
9563
  }
9560
9564
 
9561
9565
  //!!!
9562
- /*
9566
+
9563
9567
  html += this.getMenuText('m1_exportrefnum', 'Reference Numbers', undefined, undefined, 2);
9564
9568
  html += "<ul>";
9565
9569
  html += this.getLink('mn1_exportIgstrand', 'Ig Strand', undefined, 3);
9566
9570
  html += this.getLink('mn1_exportKabat', 'Kabat', undefined, 3);
9567
9571
  html += this.getLink('mn1_exportImgt', 'IMGT', undefined, 3);
9568
9572
  html += "</ul>";
9569
- */
9573
+
9570
9574
 
9571
9575
  html += "<li><br/></li>";
9572
9576
 
@@ -10407,8 +10411,8 @@ class SetMenu {
10407
10411
  //}
10408
10412
 
10409
10413
  //!!!
10410
- //html += this.getRadio('mn4_clr', 'mn4_clrIgstrand', 'Ig Strand', undefined, undefined, 2);
10411
- //html += this.getRadio('mn4_clr', 'mn4_clrIgproto', 'Ig Protodomain', undefined, undefined, 2);
10414
+ html += this.getRadio('mn4_clr', 'mn4_clrIgstrand', 'Ig Strand', undefined, undefined, 2);
10415
+ html += this.getRadio('mn4_clr', 'mn4_clrIgproto', 'Ig Protodomain', undefined, undefined, 2);
10412
10416
  }
10413
10417
  else {
10414
10418
  //if(!me.cfg.hidelicense) html += this.getRadio('mn4_clr', 'mn1_delphi2', 'DelPhi<br><span style="padding-left:1.5em;">Potential ' + me.htmlCls.licenseStr + '</span>');
@@ -10539,7 +10543,7 @@ class SetMenu {
10539
10543
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelResidues', 'per Residue', undefined, 1, 2);
10540
10544
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelResnum', 'per Residue & Number', undefined, 1, 2);
10541
10545
  //!!!
10542
- //html += this.getRadio('mn6_addlabel', 'mn6_addlabelRefnum', 'per Reference Number', undefined, 1, 2);
10546
+ html += this.getRadio('mn6_addlabel', 'mn6_addlabelRefnum', 'per Reference Number', undefined, 1, 2);
10543
10547
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelChains', 'per Chain', undefined, undefined, 2);
10544
10548
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelTermini', 'N- & C-Termini', undefined, 1, 2);
10545
10549
  }
@@ -10631,11 +10635,11 @@ class SetMenu {
10631
10635
 
10632
10636
  html += "<ul>";
10633
10637
  //!!!
10634
- /*
10638
+
10635
10639
  html += this.getLink('mn6_igrefYes', 'Show Ig Ref. Number', undefined, 2);
10636
10640
  html += this.getLink('mn6_igrefTpl', 'Ig w/ Specified Template', undefined, 2);
10637
10641
  html += this.getLink('mn6_igrefNo', 'Hide Ig Ref. Number', undefined, 2);
10638
- */
10642
+
10639
10643
  html += this.getMenuSep();
10640
10644
 
10641
10645
  html += this.getLink('mn6_customref', 'Custom Ref. Number', undefined, 2);
@@ -11875,23 +11879,19 @@ class SetDialog {
11875
11879
  html += "</div>";
11876
11880
 
11877
11881
  html += me.htmlCls.divStr + "dl_dsn6' class='" + dialogClass + "'>";
11878
- html += this.addNotebookTitle('dl_dsn6', 'Load a DSN6 file');
11879
- html += "<b>Note</b>: Always load a PDB file before loading DSN6 files. <br/><br/><br/>";
11880
-
11881
- html += "<span style='white-space:nowrap;font-weight:bold;'>2fofc contour at: <select id='" + me.pre + "dsn6sigma2fofc'>";
11882
+ html += this.addNotebookTitle('dl_dsn6', 'Load a map file');
11883
+ 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/>";
11882
11884
 
11883
- let optArray1 = ['0', '0.5', '1', '1.5', '2', '3', '4', '5', '6', '7', '8', '9', '10'];
11884
- html += me.htmlCls.setHtmlCls.getOptionHtml(optArray1, 3);
11885
+ html += "<span style='white-space:nowrap;font-weight:bold;'>2fofc contour at default threshold or at: "
11886
+ + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigma2fofc' value='' size=8> &sigma;</span><br/>";
11887
+ //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/>";
11888
+ 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/>";
11885
11889
 
11886
- html += "</select> &sigma;</span><br/>";
11887
- html += me.htmlCls.inputFileStr + "id='" + me.pre + "dsn6file2fofc'> " + me.htmlCls.buttonStr + "reload_dsn6file2fofc' style='margin-top: 6px;'>Load</button><br><br><br/>";
11890
+ html += "<span style='white-space:nowrap;font-weight:bold;'>fofc contour at default threshold or at: "
11891
+ + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigmafofc' value='' size=8> &sigma;</span><br/>";
11888
11892
 
11889
- html += "<span style='white-space:nowrap;font-weight:bold;'>fofc contour at: <select id='" + me.pre + "dsn6sigmafofc'>";
11890
-
11891
- html += me.htmlCls.setHtmlCls.getOptionHtml(optArray1, 5);
11892
-
11893
- html += "</select> &sigma;</span><br/>";
11894
- html += me.htmlCls.inputFileStr + "id='" + me.pre + "dsn6filefofc'> " + me.htmlCls.buttonStr + "reload_dsn6filefofc' style='margin-top: 6px;'>Load</button><br><br><br>";
11893
+ //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>";
11894
+ 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>";
11895
11895
 
11896
11896
  html += me.htmlCls.buttonStr + "elecmapNo4'>Remove Map</button><br>";
11897
11897
 
@@ -11899,21 +11899,17 @@ class SetDialog {
11899
11899
 
11900
11900
  html += me.htmlCls.divStr + "dl_dsn6url' class='" + dialogClass + "'>";
11901
11901
  html += this.addNotebookTitle('dl_dsn6url', 'Load a selection file via a URL');
11902
- html += "<b>Note</b>: Always load a PDB file before loading DSN6 files. <br/><br/><br/>";
11903
-
11904
- html += "<span style='white-space:nowrap;font-weight:bold;'>2fofc contour at: <select id='" + me.pre + "dsn6sigmaurl2fofc'>";
11905
-
11906
- html += me.htmlCls.setHtmlCls.getOptionHtml(optArray1, 3);
11902
+ 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/>";
11907
11903
 
11908
- html += "</select> &sigma;</span><br/>";
11909
- 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/>";
11904
+ html += "<span style='white-space:nowrap;font-weight:bold;'>2fofc contour at default threshold or at: "
11905
+ + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigmaurl2fofc' value='' size=8> &sigma;</span><br/>";
11910
11906
 
11911
- html += "<span style='white-space:nowrap;font-weight:bold;'>fofc contour at: <select id='" + me.pre + "dsn6sigmaurlfofc'>";
11907
+ 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/>";
11912
11908
 
11913
- html += me.htmlCls.setHtmlCls.getOptionHtml(optArray1, 5);
11909
+ html += "<span style='white-space:nowrap;font-weight:bold;'>fofc contour at default threshold or at: "
11910
+ + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigmaurlfofc' value='' size=8> &sigma;</span><br/>";
11914
11911
 
11915
- html += "</select> &sigma;</span><br/>";
11916
- 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/>";
11912
+ 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>";
11917
11913
 
11918
11914
  html += me.htmlCls.buttonStr + "elecmapNo5'>Remove Map</button><br>";
11919
11915
 
@@ -12253,6 +12249,7 @@ class SetDialog {
12253
12249
  html += this.addNotebookTitle('dl_elecmap2fofc', 'Electron Density 2F0-Fc Map');
12254
12250
  html += "<span style='white-space:nowrap;font-weight:bold;'>Contour at: <select id='" + me.pre + "sigma2fofc'>";
12255
12251
 
12252
+ let optArray1 = ['0', '0.5', '1', '1.5', '2', '3', '4', '5', '6', '7', '8', '9', '10'];
12256
12253
  html += me.htmlCls.setHtmlCls.getOptionHtml(optArray1, 3);
12257
12254
 
12258
12255
  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>";
@@ -12899,7 +12896,7 @@ class Events {
12899
12896
  }
12900
12897
  }
12901
12898
 
12902
- readFile(bAppend, files, index, dataStrAll) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
12899
+ async readFile(bAppend, files, index, dataStrAll) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
12903
12900
  let file = files[index];
12904
12901
  let commandName = (bAppend) ? 'append': 'load';
12905
12902
 
@@ -12936,7 +12933,20 @@ class Events {
12936
12933
  await ic.pdbParserCls.loadPdbData(dataStrAll, undefined, undefined, bAppend);
12937
12934
  }
12938
12935
  else {
12939
- thisClass.readFile(bAppend, files, index + 1, dataStrAll);
12936
+ await thisClass.readFile(bAppend, files, index + 1, dataStrAll);
12937
+ }
12938
+
12939
+ if(bAppend) {
12940
+ if(ic.bSetChainsAdvancedMenu) ic.definedSetsCls.showSets();
12941
+ //if(ic.bSetChainsAdvancedMenu) ic.legendTableCls.showSets();
12942
+
12943
+ ic.bResetAnno = true;
12944
+
12945
+ if(ic.bAnnoShown) {
12946
+ await ic.showAnnoCls.showAnnotations();
12947
+
12948
+ ic.annotationCls.resetAnnoTabAll();
12949
+ }
12940
12950
  }
12941
12951
  };
12942
12952
 
@@ -12971,13 +12981,7 @@ class Events {
12971
12981
 
12972
12982
  ic.dataStrAll = '';
12973
12983
 
12974
- this.readFile(bAppend, files, 0, '');
12975
-
12976
- if(bAppend) {
12977
- if(ic.bSetChainsAdvancedMenu) ic.definedSetsCls.showSets();
12978
- //if(ic.bSetChainsAdvancedMenu) ic.legendTableCls.showSets();
12979
- if(ic.bAnnoShown) await ic.showAnnoCls.showAnnotations();
12980
- }
12984
+ await this.readFile(bAppend, files, 0, '');
12981
12985
  }
12982
12986
  }
12983
12987
 
@@ -13061,7 +13065,10 @@ class Events {
13061
13065
 
13062
13066
  if(bStructures) {
13063
13067
  if(ic.bSetChainsAdvancedMenu) ic.definedSetsCls.showSets();
13064
- if(ic.bAnnoShown) await ic.showAnnoCls.showAnnotations();
13068
+ if(ic.bAnnoShown) {
13069
+ await ic.showAnnoCls.showAnnotations();
13070
+ ic.annotationCls.resetAnnoTabAll();
13071
+ }
13065
13072
  }
13066
13073
  }
13067
13074
  }
@@ -14071,15 +14078,37 @@ class Events {
14071
14078
 
14072
14079
  me.myEventCls.onIds("#" + me.pre + "reload_dsn6file2fofc", "click", function(e) { let ic = me.icn3d;
14073
14080
  e.preventDefault();
14074
- if(!me.cfg.notebook) dialog.dialog( "close" );
14081
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
14075
14082
  ic.dsn6ParserCls.loadDsn6File('2fofc');
14076
14083
  });
14077
14084
  me.myEventCls.onIds("#" + me.pre + "reload_dsn6filefofc", "click", function(e) { let ic = me.icn3d;
14078
14085
  e.preventDefault();
14079
- if(!me.cfg.notebook) dialog.dialog( "close" );
14086
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
14080
14087
  ic.dsn6ParserCls.loadDsn6File('fofc');
14081
14088
  });
14082
14089
 
14090
+ me.myEventCls.onIds("#" + me.pre + "reload_ccp4file2fofc", "click", function(e) { let ic = me.icn3d;
14091
+ e.preventDefault();
14092
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
14093
+ ic.ccp4ParserCls.loadCcp4File('2fofc');
14094
+ });
14095
+ me.myEventCls.onIds("#" + me.pre + "reload_ccp4filefofc", "click", function(e) { let ic = me.icn3d;
14096
+ e.preventDefault();
14097
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
14098
+ ic.ccp4ParserCls.loadCcp4File('fofc');
14099
+ });
14100
+
14101
+ me.myEventCls.onIds("#" + me.pre + "reload_mtzfile2fofc", "click", function(e) { let ic = me.icn3d;
14102
+ e.preventDefault();
14103
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
14104
+ ic.mtzParserCls.loadMtzFile('2fofc');
14105
+ });
14106
+ me.myEventCls.onIds("#" + me.pre + "reload_mtzfilefofc", "click", function(e) { let ic = me.icn3d;
14107
+ e.preventDefault();
14108
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
14109
+ ic.mtzParserCls.loadMtzFile('fofc');
14110
+ });
14111
+
14083
14112
  me.myEventCls.onIds("#" + me.pre + "reload_delphifile", "click", async function(e) { let ic = me.icn3d;
14084
14113
  e.preventDefault();
14085
14114
  if(!me.cfg.notebook) dialog.dialog( "close" );
@@ -14169,15 +14198,37 @@ class Events {
14169
14198
 
14170
14199
  me.myEventCls.onIds("#" + me.pre + "reload_dsn6fileurl2fofc", "click", function(e) { let ic = me.icn3d;
14171
14200
  e.preventDefault();
14172
- if(!me.cfg.notebook) dialog.dialog( "close" );
14201
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
14173
14202
  ic.dsn6ParserCls.loadDsn6FileUrl('2fofc');
14174
14203
  });
14175
14204
  me.myEventCls.onIds("#" + me.pre + "reload_dsn6fileurlfofc", "click", function(e) { let ic = me.icn3d;
14176
14205
  e.preventDefault();
14177
- if(!me.cfg.notebook) dialog.dialog( "close" );
14206
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
14178
14207
  ic.dsn6ParserCls.loadDsn6FileUrl('fofc');
14179
14208
  });
14180
14209
 
14210
+ me.myEventCls.onIds("#" + me.pre + "reload_ccp4fileurl2fofc", "click", function(e) { let ic = me.icn3d;
14211
+ e.preventDefault();
14212
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
14213
+ ic.ccp4ParserCls.loadCcp4FileUrl('2fofc');
14214
+ });
14215
+ me.myEventCls.onIds("#" + me.pre + "reload_ccp4fileurlfofc", "click", function(e) { let ic = me.icn3d;
14216
+ e.preventDefault();
14217
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
14218
+ ic.ccp4ParserCls.loadCcp4FileUrl('fofc');
14219
+ });
14220
+
14221
+ me.myEventCls.onIds("#" + me.pre + "reload_mtzfileurl2fofc", "click", function(e) { let ic = me.icn3d;
14222
+ e.preventDefault();
14223
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
14224
+ ic.mtzParserCls.loadMtzFileUrl('2fofc');
14225
+ });
14226
+ me.myEventCls.onIds("#" + me.pre + "reload_mtzfileurlfofc", "click", function(e) { let ic = me.icn3d;
14227
+ e.preventDefault();
14228
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
14229
+ ic.mtzParserCls.loadMtzFileUrl('fofc');
14230
+ });
14231
+
14181
14232
  me.myEventCls.onIds("#" + me.pre + "reload_pdbfile", "click", async function(e) { me.icn3d;
14182
14233
  e.preventDefault();
14183
14234
 
@@ -15565,7 +15616,7 @@ class AlignSeq {
15565
15616
  // for(let i in ic.alnChains) {
15566
15617
  for (let m = 0, ml = alignChainArray.length; m < ml; ++m) {
15567
15618
  let i = alignChainArray[m];
15568
-
15619
+
15569
15620
  if (index == 0) firstChainid = i;
15570
15621
 
15571
15622
  if (bOnechain && index > 0) {
@@ -29340,8 +29391,8 @@ class ElectronMap {
29340
29391
  this.pLength = 0;
29341
29392
  this.cutRadius = 0;
29342
29393
  this.vpBits = null; // uint8 array of bitmasks
29343
- this.vpDistance = null; // floatarray of _squared_ distances
29344
- this.vpAtomID = null; // intarray
29394
+ this.vpGridTrans = null; // array of translated number of grids
29395
+ this.vpAtomID = null; // uint8 array
29345
29396
  this.vertnumber = 0;
29346
29397
  this.facenumber = 0;
29347
29398
  this.pminx = 0;
@@ -29391,12 +29442,27 @@ ElectronMap.prototype.getFacesAndVertices = function(allatoms, atomlist) {
29391
29442
  atomsToShow[atomlist[i]] = 1;
29392
29443
  let vertices = this.verts;
29393
29444
 
29445
+ let vertTrans = {};
29394
29446
  for(i = 0, il = vertices.length; i < il; i++) {
29395
29447
  let r;
29396
29448
  if(this.type == 'phi') {
29397
29449
  r = new THREE.Vector3(vertices[i].x, vertices[i].y, vertices[i].z).multiplyScalar(1.0/this.header.scale).applyMatrix4(this.matrix);
29398
29450
  }
29399
29451
  else {
29452
+ // ccp4 has no translation vector. Only translated vertices are used.
29453
+ if(this.header.ccp4) {
29454
+ let index = vertices[i].index;
29455
+ let finalIndex;
29456
+ if(this.vpGridTrans[index]) {
29457
+ finalIndex = index;
29458
+
29459
+ vertices[i].x += this.vpGridTrans[finalIndex][0] * this.header.xExtent * this.scaleFactor;
29460
+ vertices[i].y += this.vpGridTrans[finalIndex][1] * this.header.xExtent * this.scaleFactor;
29461
+ vertices[i].z += this.vpGridTrans[finalIndex][2] * this.header.xExtent * this.scaleFactor;
29462
+
29463
+ vertTrans[finalIndex] = 1;
29464
+ }
29465
+ }
29400
29466
  r = new THREE.Vector3(vertices[i].x, vertices[i].y, vertices[i].z).applyMatrix4(this.matrix);
29401
29467
  }
29402
29468
  // vertices[i].x = r.x / this.scaleFactor - this.ptranx;
@@ -29415,13 +29481,22 @@ ElectronMap.prototype.getFacesAndVertices = function(allatoms, atomlist) {
29415
29481
  let fa = this.faces[i], fb = this.faces[i+1], fc = this.faces[i+2];
29416
29482
 
29417
29483
  if(fa !== fb && fb !== fc && fa !== fc){
29418
- finalfaces.push({"a":fa, "b":fb, "c":fc});
29484
+ if(this.header.ccp4) {
29485
+ // only transfered vertices will be used
29486
+ if(vertTrans.hasOwnProperty(vertices[fa].index) && vertTrans.hasOwnProperty(vertices[fb].index)
29487
+ && vertTrans.hasOwnProperty(vertices[fc].index)) {
29488
+ finalfaces.push({"a":fa, "b":fb, "c":fc});
29489
+ }
29490
+ }
29491
+ else {
29492
+ finalfaces.push({"a":fa, "b":fb, "c":fc});
29493
+ }
29419
29494
  }
29420
29495
  }
29421
29496
 
29422
29497
  //try to help the garbage collector
29423
29498
  this.vpBits = null; // uint8 array of bitmasks
29424
- this.vpDistance = null; // floatarray
29499
+ this.vpGridTrans = null; // uint8 array
29425
29500
  this.vpAtomID = null; // intarray
29426
29501
 
29427
29502
  return {
@@ -29480,6 +29555,8 @@ ElectronMap.prototype.initparm = function(inHeader, inData, inMatrix, inIsovalue
29480
29555
  this.cutRadius = this.probeRadius * this.scaleFactor;
29481
29556
 
29482
29557
  this.vpBits = new Uint8Array(this.pLength * this.pWidth * this.pHeight);
29558
+ if(this.header.ccp4) this.vpGridTrans = new Array(this.pLength * this.pWidth * this.pHeight);
29559
+
29483
29560
  this.vpAtomID = new Uint8Array(this.pLength * this.pWidth * this.pHeight);
29484
29561
  };
29485
29562
 
@@ -29505,7 +29582,6 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
29505
29582
  let i, j, k, il, jl, kl;
29506
29583
  for(i = 0, il = this.vpBits.length; i < il; i++) {
29507
29584
  this.vpBits[i] = 0;
29508
- //this.vpDistance[i] = -1.0;
29509
29585
  this.vpAtomID[i] = 0;
29510
29586
  }
29511
29587
 
@@ -29667,6 +29743,7 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
29667
29743
  }
29668
29744
  }
29669
29745
  else {
29746
+ // let index2ori = {};
29670
29747
  for(let serial in atomlist) {
29671
29748
  let atom = atoms[atomlist[serial]];
29672
29749
 
@@ -29697,6 +29774,7 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
29697
29774
 
29698
29775
  for(i = 0, il = indexArray.length; i < il; ++i) {
29699
29776
  let index = indexArray[i];
29777
+
29700
29778
  if(this.type == '2fofc') {
29701
29779
  this.vpBits[index] =(this.dataArray[index] >= this.isovalue) ? 1 : 0;
29702
29780
  //this.vpAtomID[index] =(this.dataArray[index] >= 0) ? 1 : 0; // determine whether it's positive
@@ -29710,6 +29788,7 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
29710
29788
  //this.vpAtomID[index] =(this.dataArray[index] >= 0) ? 1 : 0; // determine whether it's positive
29711
29789
  }
29712
29790
  }
29791
+
29713
29792
  }
29714
29793
  }
29715
29794
 
@@ -29933,7 +30012,18 @@ class Surface {
29933
30012
  cfg.isovalue = ic.mapData.sigma2;
29934
30013
  cfg.type = '2fofc';
29935
30014
 
29936
- ps = this.SetupMap(cfg);
30015
+ //ccp4
30016
+ cfg.ccp4 = ic.mapData.ccp4;
30017
+ cfg.grid = ic.mapData.grid2;
30018
+ cfg.unit_cell = ic.mapData.unit_cell2;
30019
+
30020
+ if(cfg.header || cfg.ccp4) ps = this.SetupMap(cfg);
30021
+ else return;
30022
+
30023
+ if(cfg.ccp4) {
30024
+ ic.mapData = {};
30025
+ return;
30026
+ }
29937
30027
  }
29938
30028
  else if(type == 12) { // fofc
29939
30029
  cfg.header = ic.mapData.header;
@@ -29942,7 +30032,18 @@ class Surface {
29942
30032
  cfg.isovalue = ic.mapData.sigma;
29943
30033
  cfg.type = 'fofc';
29944
30034
 
29945
- ps = this.SetupMap(cfg);
30035
+ //ccp4
30036
+ cfg.ccp4 = ic.mapData.ccp4;
30037
+ cfg.grid = ic.mapData.grid;
30038
+ cfg.unit_cell = ic.mapData.unit_cell;
30039
+
30040
+ if(cfg.header || cfg.ccp4) ps = this.SetupMap(cfg);
30041
+ else return;
30042
+
30043
+ if(cfg.ccp4) {
30044
+ ic.mapData = {};
30045
+ return;
30046
+ }
29946
30047
  }
29947
30048
  else if(type == 13) { // em
29948
30049
  cfg.maxdist = 3; // EM map has no unit cell. It could include more gird space.
@@ -30430,29 +30531,60 @@ class Surface {
30430
30531
  }
30431
30532
 
30432
30533
  SetupMap(data) { let ic = this.icn3d; ic.icn3dui;
30433
- let ps = new ElectronMap(ic);
30434
-
30435
- ps.initparm(data.header, data.data, data.matrix, data.isovalue, data.center, data.maxdist,
30436
- data.pmin, data.pmax, data.water, data.type, data.rmsd_supr, data.loadPhiFrom, data.icn3d);
30534
+ if(data.ccp4) {
30535
+ let radius = 10;
30536
+ let center = (ic.center) ? [ic.center.x, ic.center.y, ic.center.z] : [0,0,0];
30537
+
30538
+ let typeDetail;
30539
+ if(data.type == '2fofc') {
30540
+ typeDetail = '2fofc';
30541
+ let result = ic.ccp4ParserCls.extract_block(data.grid, data.unit_cell, radius, center, typeDetail);
30542
+ let iso = ic.ccp4ParserCls.marchingCubes(result.size, result.values, result.points, data.isovalue, 'marching cubes');
30543
+ ic.ccp4ParserCls.makeChickenWire(iso, typeDetail);
30544
+
30545
+ result = null;
30546
+ iso = null;
30547
+ }
30548
+ else if(data.type == 'fofc') {
30549
+ typeDetail = 'fofc_neg';
30550
+ let result = ic.ccp4ParserCls.extract_block(data.grid, data.unit_cell, radius, center, typeDetail);
30551
+ let iso = ic.ccp4ParserCls.marchingCubes(result.size, result.values, result.points, data.isovalue, 'marching cubes');
30552
+ ic.ccp4ParserCls.makeChickenWire(iso, typeDetail);
30553
+
30554
+ typeDetail = 'fofc_pos';
30555
+ result = ic.ccp4ParserCls.extract_block(data.grid, data.unit_cell, radius, center, typeDetail);
30556
+ iso = ic.ccp4ParserCls.marchingCubes(result.size, result.values, result.points, data.isovalue, 'marching cubes');
30557
+ ic.ccp4ParserCls.makeChickenWire(iso, typeDetail);
30437
30558
 
30438
- ps.fillvoxels(data.allatoms, data.extendedAtoms);
30559
+ result = null;
30560
+ iso = null;
30561
+ }
30562
+ }
30563
+ else {
30564
+ let ps = new ElectronMap(ic);
30565
+
30566
+ ps.initparm(data.header, data.data, data.matrix, data.isovalue, data.center, data.maxdist,
30567
+ data.pmin, data.pmax, data.water, data.type, data.rmsd_supr, data.loadPhiFrom, data.icn3d);
30439
30568
 
30440
- if(!data.header.bSurface) ps.buildboundary();
30569
+ ps.fillvoxels(data.allatoms, data.extendedAtoms);
30441
30570
 
30442
- if(!data.header.bSurface) ps.marchingcube();
30443
-
30444
- ps.vpBits = null; // uint8 array of bitmasks
30445
- //ps.vpDistance = null; // floatarray of _squared_ distances
30446
- ps.vpAtomID = null; // intarray
30571
+ if(!data.header.bSurface) ps.buildboundary();
30447
30572
 
30448
- let result;
30573
+ if(!data.header.bSurface) ps.marchingcube();
30574
+
30575
+ ps.vpBits = null; // uint8 array of bitmasks
30576
+ //ps.vpDistance = null; // floatarray of _squared_ distances
30577
+ ps.vpAtomID = null; // intarray
30449
30578
 
30450
- if(!data.header.bSurface) result = ps.getFacesAndVertices(data.allatoms, data.atomsToShow);
30579
+ let result;
30451
30580
 
30452
- ps.faces = null;
30453
- ps.verts = null;
30581
+ if(!data.header.bSurface) result = ps.getFacesAndVertices(data.allatoms, data.atomsToShow);
30454
30582
 
30455
- return result;
30583
+ ps.faces = null;
30584
+ ps.verts = null;
30585
+
30586
+ return result;
30587
+ }
30456
30588
  }
30457
30589
  }
30458
30590
 
@@ -35939,7 +36071,7 @@ class SetColor {
35939
36071
 
35940
36072
  for(let resid in residueHash) {
35941
36073
  if(!ic.resid2refnum[resid]) {
35942
- color = me.parasCls.thr('#FFFFFF');
36074
+ color = me.parasCls.thr('#00FFFF'); //('#FFFFFF');
35943
36075
  }
35944
36076
  else {
35945
36077
  let refnumLabel = ic.resid2refnum[resid];
@@ -35974,7 +36106,7 @@ class SetColor {
35974
36106
  let residueHash = ic.firstAtomObjCls.getResiduesFromAtoms(atoms);
35975
36107
  for(let resid in residueHash) {
35976
36108
  if(!ic.resid2refnum[resid]) {
35977
- color = me.parasCls.thr('#FFFFFF');
36109
+ color = me.parasCls.thr('#00FFFF'); //('#FFFFFF');
35978
36110
  }
35979
36111
  else {
35980
36112
  let refnumLabel = ic.resid2refnum[resid];
@@ -36944,15 +37076,13 @@ class SetOption {
36944
37076
  const name2color = {
36945
37077
  //"A- Strand": "FF00FF",
36946
37078
  "A Strand": "9400D3", //"663399",
36947
- //"A+ Strand": "9400D3", //"663399",
36948
- "A' Strand": "9400D3", //"663399",
36949
37079
  "B Strand": "ba55d3",
36950
37080
  "C Strand": "0000FF",
36951
37081
  "C' Strand": "6495ED",
36952
37082
  "C'' Strand": "006400",
36953
37083
  "D Strand": "00FF00",
36954
- "E Strand": "F7DC6F", //"FFFF00", //"F0E68C",
36955
- "F Strand": "FFA500",
37084
+ "E Strand": "FFD700", //"FFFF00", //"F0E68C",
37085
+ "F Strand": "FF8C00",
36956
37086
  "G Strand": "FF0000",
36957
37087
  //"G+ Strand": "8B0000",
36958
37088
  "Loop": "CCCCCC"
@@ -36979,15 +37109,15 @@ class SetOption {
36979
37109
  "<b>Protodomain 1</b>": "",
36980
37110
  "A Strand": "0000FF",
36981
37111
  "B Strand": "006400",
36982
- "C Strand": "F7DC6F", //"FFFF00", //"F0E68C",
36983
- "C' Strand": "FFA500",
37112
+ "C Strand": "FFD700", //"FFFF00", //"F0E68C",
37113
+ "C' Strand": "FF8C00",
36984
37114
  "<br><b>Linker</b>": "",
36985
37115
  "C'' Strand": "FF0000",
36986
37116
  "<br><b>Protodomain 2</b>": "",
36987
37117
  "D Strand": "0000FF",
36988
37118
  "E Strand": "006400",
36989
- "F Strand": "F7DC6F", //"FFFF00", //"F0E68C",
36990
- "G Strand": "FFA500",
37119
+ "F Strand": "FFD700", //"FFFF00", //"F0E68C",
37120
+ "G Strand": "FF8C00",
36991
37121
  "": "",
36992
37122
  "Loop": "CCCCCC"
36993
37123
  };
@@ -38189,14 +38319,14 @@ class AnnoDomain {
38189
38319
  let pdbid = pdbArray[index];
38190
38320
  //let url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&domain&molinfor&uid=" + pdbid;
38191
38321
 
38192
- if(index == 0 && ic.mmdb_data !== undefined) {
38322
+ if(!ic.bResetAnno && index == 0 && ic.mmdb_data !== undefined) {
38193
38323
  for(let chnid in ic.protein_chainid) {
38194
38324
  if(chnid.indexOf(pdbid) !== -1) {
38195
38325
  this.showDomainWithData(chnid, ic.mmdb_data);
38196
38326
  }
38197
38327
  }
38198
38328
  }
38199
- else if(ic.mmdb_dataArray[index] !== undefined) {
38329
+ else if(!ic.bResetAnno && ic.mmdb_dataArray[index] !== undefined) {
38200
38330
  for(let chnid in ic.protein_chainid) {
38201
38331
  if(chnid.indexOf(pdbid) !== -1) {
38202
38332
  this.showDomainWithData(chnid, ic.mmdb_dataArray[index]);
@@ -38271,6 +38401,10 @@ class AnnoDomain {
38271
38401
  let domainArray, proteinname;
38272
38402
  let pos = chnid.indexOf('_');
38273
38403
  let chain = chnid.substr(pos + 1);
38404
+ // MMDB symmetry chain has the form of 'A1'
38405
+ if(chain.length > 1 && chain.substr(chain.length - 1) == '1') {
38406
+ chain = chain.substr(0, chain.length - 1);
38407
+ }
38274
38408
 
38275
38409
  if(bCalcDirect) {
38276
38410
  proteinname = chnid;
@@ -39276,7 +39410,11 @@ class Domain3d {
39276
39410
  //this.dcut = 8; // threshold for C-alpha interactions
39277
39411
 
39278
39412
  // It seemed the threshold 7 angstrom works better
39279
- this.dcut = 7; // threshold for C-alpha interactions
39413
+ //this.dcut = 7; // threshold for C-alpha interactions
39414
+ this.dcut = 8; // threshold for C-alpha interactions
39415
+
39416
+ // added by Jiyao
39417
+ this.min_contacts = 5; //3; // minimum number of contacts to be considered as neighbors
39280
39418
 
39281
39419
  this.MAX_SSE = 512;
39282
39420
 
@@ -39310,9 +39448,6 @@ class Domain3d {
39310
39448
  this.c_delta = 3; // cut set parameter
39311
39449
  this.nc_fact = 0.0; // size factor for internal contacts
39312
39450
 
39313
- // added by Jiyao
39314
- this.min_contacts = 3; // minimum number of contacts to be considered as neighbors
39315
-
39316
39451
  //let this.elements[2*this.MAX_SSE]; // sets of this.elements to be split
39317
39452
  this.elements = [];
39318
39453
  this.elements.length = 2*this.MAX_SSE;
@@ -42890,6 +43025,10 @@ class ShowAnno {
42890
43025
  chainLetter = chainLetter.substr(0, chainLetter.indexOf('_'));
42891
43026
  chainidBase = chainArray[i].substr(0, chainArray[i].indexOf('_')) + '_' + chainLetter;
42892
43027
  }
43028
+ else if(chainLetter.length > 1 && chainLetter.substr(chainLetter.length - 1) == '1') { // NCBI modified chainid, e.g., A1
43029
+ chainLetter = chainLetter.substr(0, chainLetter.length - 1);
43030
+ chainidBase = chainArray[i].substr(0, chainArray[i].indexOf('_')) + '_' + chainLetter;
43031
+ }
42893
43032
  else {
42894
43033
  chainidBase = chainArray[i];
42895
43034
  }
@@ -44090,7 +44229,7 @@ class ShowSeq {
44090
44229
  html += '</div>';
44091
44230
  html3 += '</div></div>';
44092
44231
  }
44093
-
44232
+
44094
44233
  if(ic.bShowRefnum && ic.chainid2refpdbname.hasOwnProperty(chnid) && ic.chainid2refpdbname[chnid].length > 0) {
44095
44234
  let result = this.showAllRefNum(giSeq, chnid);
44096
44235
 
@@ -44159,9 +44298,13 @@ class ShowSeq {
44159
44298
 
44160
44299
  if(!ic.chainid2refpdbname[chnid]) return {html: html, html3: html3};
44161
44300
 
44162
- let chainList = ic.refnumCls.getTemplateList(chnid);
44301
+ let result = ic.refnumCls.getTemplateList(chnid);
44302
+ let refpdbnameList = result.refpdbnameList;
44303
+ let scoreList = result.scoreList;
44304
+ let seqidList = result.seqidList;
44305
+ let nresAlignList = result.nresAlignList;
44163
44306
 
44164
- let refStruTitle = (chainList) ? "based on " + chainList : "";
44307
+ 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 + "." : "";
44165
44308
 
44166
44309
  let htmlTmp = '<div class="icn3d-dl_sequence">';
44167
44310
  htmlTmp += '<div class="icn3d-residueLine" style="white-space:nowrap;">';
@@ -44217,7 +44360,8 @@ class ShowSeq {
44217
44360
 
44218
44361
  // auto-generate ref numbers for loops
44219
44362
  let bLoop = false, currStrand = '', prevStrand = '';
44220
- let refnumLabel, refnumStr_ori, refnumStr, postfix, strandPostfix, refnum, refnum3c;
44363
+ let refnumLabel, refnumStr_ori, refnumStr, postfix, strandPostfix, refnum, refnum3c, refnum2c;
44364
+ let bExtendedStrand = false, bSecThird9 = false;
44221
44365
 
44222
44366
  // sometimes one chain may have several Ig domains,set an index for each IgDomain
44223
44367
  let index = 1, bStart = false;
@@ -44243,8 +44387,8 @@ class ShowSeq {
44243
44387
 
44244
44388
  refnumLabel = ic.resid2refnum[residueid];
44245
44389
 
44246
- let firstChar = (refnumLabel) ? refnumLabel.substr(0,1) : ' ';
44247
- if(!bStart && refnumLabel && (firstChar == ' ' || firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
44390
+ let firstChar = (refnumLabel) ? refnumLabel.substr(0,1) : '';
44391
+ if(!bStart && refnumLabel && (firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
44248
44392
  bStart = true;
44249
44393
  resCnt = 1; // the first oen is included
44250
44394
  }
@@ -44261,14 +44405,21 @@ class ShowSeq {
44261
44405
  refnumStr = refnumStr_ori;
44262
44406
  refnum = parseInt(refnumStr);
44263
44407
  refnum3c = (refnum - parseInt(refnum/1000) * 1000).toString();
44408
+ refnum2c = (refnum - parseInt(refnum/100) * 100).toString();
44409
+
44410
+ // for extended strands, since A is 1550 and A+ is 1650, then the AA+ loop will be 1591, 1592, ... 1610, 1611, etc
44411
+ bSecThird9 = refnum3c.substr(0,1) == '9' || refnum2c.substr(0,1) == '9' || refnum2c.substr(0,1) == '0' || refnum2c.substr(0,1) == '1';
44412
+ if(bSecThird9) ic.residIgLoop[residueid] = 1;
44413
+
44264
44414
  strandPostfix = refnumStr.replace(refnum.toString(), '');
44265
44415
 
44266
44416
  postfix = strandPostfix + '_' + index;
44267
44417
 
44268
- let firstTwo = parseInt(refnum.toString().substr(0, 2)); // A- strand
44418
+ let firstTwo = parseInt(refnum.toString().substr(0, 2)); // check extended strands
44419
+ bExtendedStrand = refnum3c.substr(0,1) != '5' && firstTwo != '18'; // all strands and A' (18##)
44269
44420
 
44270
44421
  if(currStrand && currStrand != ' ') {
44271
- if(refnum3c.substr(0,1) != '9' || firstTwo == 10) {
44422
+ if(!bSecThird9 || (bExtendedStrand && !bSecThird9)) {
44272
44423
  let lastTwo = parseInt(refnum.toString().substr(refnum.toString().length - 2, 2));
44273
44424
 
44274
44425
  if(currStrand != prevStrand) { // reset currCnt
@@ -44295,7 +44446,7 @@ class ShowSeq {
44295
44446
  resCntAtAnchor = 0;
44296
44447
  }
44297
44448
 
44298
- if(firstTwo == 10) {
44449
+ if(bExtendedStrand) {
44299
44450
  strandArray[strandCnt].anchorRefnum = 0;
44300
44451
  }
44301
44452
 
@@ -44321,7 +44472,7 @@ class ShowSeq {
44321
44472
  resCntAtAnchor = 0;
44322
44473
  }
44323
44474
 
44324
- if(firstTwo == 10) {
44475
+ if(bExtendedStrand) {
44325
44476
  strandArray[strandCnt - 1].anchorRefnum = 0;
44326
44477
  }
44327
44478
 
@@ -44377,7 +44528,7 @@ class ShowSeq {
44377
44528
  currStrand = refnumLabel.replace(new RegExp(refnumStr,'g'), '');
44378
44529
 
44379
44530
  let firstChar = refnumLabel.substr(0,1);
44380
- if(!bStart && (firstChar == ' ' || firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
44531
+ if(!bStart && (firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
44381
44532
  bStart = true;
44382
44533
  bBeforeAstrand = true;
44383
44534
  loopCnt = 0;
@@ -44650,6 +44801,11 @@ class ShowSeq {
44650
44801
 
44651
44802
  getRefnumHtml(residueid, refnumStr, refnumStr_ori, refnumLabel, currStrand, bLoop, bHidelabel) { let ic = this.icn3d, me = ic.icn3dui;
44652
44803
  let refnum = parseInt(refnumStr).toString();
44804
+
44805
+ let refnum3c = (refnum - parseInt(refnum/1000) * 1000).toString();
44806
+ let firstTwo = parseInt(refnum.toString().substr(0, 2)); // check extended strands
44807
+ let bExtendedStrand = refnum3c.substr(0,1) != '5' && firstTwo != '18'; // all strands and A' (18##)
44808
+
44653
44809
  let color = this.getRefnumColor(currStrand, true);
44654
44810
  let colorStr = (!bLoop) ? 'style="color:' + color + '; text-decoration: underline overline;"' : 'style="color:' + color + '"';
44655
44811
 
@@ -44659,13 +44815,13 @@ class ShowSeq {
44659
44815
 
44660
44816
  let html = '';
44661
44817
 
44662
- if(refnumLabel && (lastTwo == 50 || refnum == 1094) && !bLoop) {
44818
+ if(refnumLabel && lastTwo == 50 && !bExtendedStrand && !bLoop) {
44663
44819
  // highlight the anchor residues
44664
44820
  ic.hAtomsRefnum = me.hashUtilsCls.unionHash(ic.hAtomsRefnum, ic.residues[residueid]);
44665
44821
 
44666
44822
  html += '<span ' + colorStr + ' title="' + refnumLabel + '"><b>' + refnumLabel.substr(0, 1) + '</b>' + refnumLabel.substr(1) + '</span>';
44667
44823
  }
44668
- else if(refnumLabel && lastTwo % 2 == 0 && lastTwo != 52 && refnum != 1096 && !bHidelabel) { // don't show label for the first, middle, and last loop residues
44824
+ else if(refnumLabel && lastTwo % 2 == 0 && lastTwo != 52 && !bHidelabel) { // don't show label for the first, middle, and last loop residues
44669
44825
  // e.g., 2152a
44670
44826
  lastTwoStr = isNaN(refnumStr) ? lastTwoStr + refnumStr.substr(refnumStr.length - 1, 1) : lastTwoStr;
44671
44827
  html += '<span ' + colorStr + ' title="' + refnumLabel + '">' + lastTwoStr + '</span>';
@@ -44678,23 +44834,9 @@ class ShowSeq {
44678
44834
  }
44679
44835
 
44680
44836
  getRefnumColor(currStrand, bText) { let ic = this.icn3d, me = ic.icn3dui;
44681
- if(currStrand == "A-") {
44682
- return '#9400D3'; //'#663399';
44683
- }
44684
- else if(currStrand == "A") {
44685
- return '#9400D3'; //'#663399';
44686
- }
44687
- //else if(currStrand == "A*") {
44688
- else if(currStrand == "A+") {
44689
- return '#9400D3'; //'#663399';
44690
- }
44691
- else if(currStrand == "A'") {
44692
- return '#9400D3'; //'#663399';
44693
- }
44694
- else if(currStrand == "B") {
44695
- return '#ba55d3';
44696
- }
44697
- else if(currStrand == "C") {
44837
+ let strand = (currStrand) ? currStrand.substr(0,1) : '';
44838
+
44839
+ if(currStrand == "C") {
44698
44840
  return '#0000FF';
44699
44841
  }
44700
44842
  else if(currStrand == "C'") {
@@ -44703,39 +44845,44 @@ class ShowSeq {
44703
44845
  else if(currStrand == "C''") {
44704
44846
  return '#006400';
44705
44847
  }
44706
- else if(currStrand == "D") {
44848
+
44849
+ else if(strand == "A") {
44850
+ return '#9400D3'; //'#663399';
44851
+ }
44852
+ else if(strand == "B") {
44853
+ return '#ba55d3';
44854
+ }
44855
+ else if(strand == "D") {
44707
44856
  return '#00FF00';
44708
44857
  }
44709
- else if(currStrand == "E") {
44710
- //return (bText) ? "#F7DC6F" : "#FFFF00";
44711
- return "#F7DC6F";
44858
+ else if(strand == "E") {
44859
+ return "#FFD700";
44712
44860
  }
44713
- else if(currStrand == "F") {
44714
- return '#FFA500';
44861
+ else if(strand == "F") {
44862
+ return '#FF8C00';
44715
44863
  }
44716
- else if(currStrand == "G") {
44864
+ else if(strand == "G") {
44717
44865
  return '#FF0000';
44718
44866
  }
44719
- else if(currStrand == "G+") {
44720
- return '#8B0000';
44721
- }
44722
44867
  else {
44723
44868
  return me.htmlCls.GREYB;
44724
44869
  }
44725
44870
  }
44726
44871
 
44727
44872
  getProtodomainColor(currStrand) { let ic = this.icn3d, me = ic.icn3dui;
44728
- if((currStrand && currStrand.substr(0,1) == "A") || currStrand == "D") {
44873
+ let strand = (currStrand) ? currStrand.substr(0,1) : '';
44874
+
44875
+ if(strand == "A" || strand == "D") {
44729
44876
  return '#0000FF';
44730
44877
  }
44731
- else if(currStrand == "B" || currStrand == "E") {
44878
+ else if(strand == "B" || strand == "E") {
44732
44879
  return '#006400';
44733
44880
  }
44734
- else if(currStrand == "C" || currStrand == "F") {
44735
- return "#F7DC6F"; //"#FFFF00"; //'#F0E68C';
44881
+ else if(currStrand == "C" || strand == "F") {
44882
+ return "#FFD700"; //"#FFFF00"; //'#F0E68C';
44736
44883
  }
44737
- else if(currStrand == "C'" || (currStrand && currStrand.substr(0, 1) == "G")) {
44738
- return '#FFA500';
44884
+ else if(currStrand == "C'" || strand == "G") {
44885
+ return '#FF8C00';
44739
44886
  }
44740
44887
  else if(currStrand == "C''") { //linker
44741
44888
  return '#FF0000';
@@ -45438,8 +45585,8 @@ class HlUpdate {
45438
45585
  updateHlObjects(bForceHighlight) { let ic = this.icn3d; ic.icn3dui;
45439
45586
  ic.hlObjectsCls.removeHlObjects();
45440
45587
 
45441
- if((ic.hAtoms && ic.atoms && Object.keys(ic.hAtoms).length < Object.keys(ic.atoms).length) || bForceHighlight) {
45442
- ic.hlObjectsCls.addHlObjects();
45588
+ if((ic.hAtoms && ic.atoms && Object.keys(ic.hAtoms).length < Object.keys(ic.dAtoms).length) || bForceHighlight) {
45589
+ if(ic.bShowHighlight === undefined || ic.bShowHighlight) ic.hlObjectsCls.addHlObjects();
45443
45590
  ic.definedSetsCls.setMode('selection');
45444
45591
  }
45445
45592
  }
@@ -46519,8 +46666,11 @@ class LineGraph {
46519
46666
 
46520
46667
  // try {
46521
46668
  if(!template) {
46522
- let allPromise = Promise.allSettled(pdbAjaxArray);
46523
- ic.pdbDataArray = await allPromise;
46669
+ //let allPromise = Promise.allSettled(pdbAjaxArray);
46670
+ //ic.pdbDataArray = await allPromise;
46671
+
46672
+ ic.pdbDataArray = await this.promiseWithFixedJobs(pdbAjaxArray);
46673
+
46524
46674
  await thisClass.parseRefPdbData(ic.pdbDataArray, template);
46525
46675
  }
46526
46676
  else {
@@ -46631,6 +46781,7 @@ class LineGraph {
46631
46781
  }
46632
46782
 
46633
46783
  if(!ic.domainid2refpdbname) ic.domainid2refpdbname = {};
46784
+ if(!ic.domainid2score) ic.domainid2score = {};
46634
46785
 
46635
46786
  for(let k = 0, kl = domainAtomsArray.length; k < kl; ++k) {
46636
46787
  let pdb_target = ic.saveFileCls.getAtomPDB(domainAtomsArray[k], undefined, undefined, undefined, undefined, struct);
@@ -46642,7 +46793,7 @@ class LineGraph {
46642
46793
  let atomLast = ic.firstAtomObjCls.getLastAtomObj(domainAtomsArray[k]);
46643
46794
  let resiSum = atomFirst.resi + ':' + atomLast.resi;
46644
46795
  //let domainid = chainid + '-' + k + '_' + Object.keys(domainAtomsArray[k]).length;
46645
- let domainid = chainid + '-' + k + '_' + resiSum;
46796
+ let domainid = chainid + ',' + k + '_' + resiSum;
46646
46797
  ic.domainid2pdb[domainid] = pdb_target;
46647
46798
 
46648
46799
  if(!template) {
@@ -46672,30 +46823,14 @@ class LineGraph {
46672
46823
  }
46673
46824
  }
46674
46825
 
46675
- try {
46826
+ //try {
46676
46827
  if(!template) {
46677
46828
  let dataArray2 = [];
46678
46829
 
46679
46830
  // let allPromise = Promise.allSettled(ajaxArray);
46680
46831
  // dataArray2 = await allPromise;
46681
46832
 
46682
- //split arrays into chunks of 48 jobs or me.cfg.maxajax jobs
46683
- let n = (me.cfg.maxajax) ? me.cfg.maxajax : ic.refpdbArray.length * 6;
46684
-
46685
- for(let i = 0, il = parseInt((ajaxArray.length - 1) / n + 1); i < il; ++i) {
46686
- let currAjaxArray = [];
46687
- if(i == il - 1) { // last one
46688
- currAjaxArray = ajaxArray.slice(i * n, ajaxArray.length);
46689
- }
46690
- else {
46691
- currAjaxArray = ajaxArray.slice(i * n, (i + 1) * n);
46692
- }
46693
-
46694
- let currPromise = Promise.allSettled(currAjaxArray);
46695
- let currDataArray = await currPromise;
46696
-
46697
- dataArray2 = dataArray2.concat(currDataArray);
46698
- }
46833
+ dataArray2 = await this.promiseWithFixedJobs(ajaxArray);
46699
46834
 
46700
46835
  let bRound1 = true;
46701
46836
  await thisClass.parseAlignData(dataArray2, domainidpairArray, bRound1);
@@ -46715,12 +46850,14 @@ class LineGraph {
46715
46850
  let pdbAjaxArray = [];
46716
46851
  pdbAjaxArray.push(pdbAjax);
46717
46852
 
46718
- let allPromise2 = Promise.allSettled(pdbAjaxArray);
46719
- ic.pdbDataArray = await allPromise2;
46853
+ //let allPromise2 = Promise.allSettled(pdbAjaxArray);
46854
+ //ic.pdbDataArray = await allPromise2;
46855
+
46856
+ ic.pdbDataArray = await this.promiseWithFixedJobs(pdbAjaxArray);
46720
46857
 
46721
46858
  for(let domainid in ic.domainid2refpdbname) {
46722
- let refpdbname = ic.domainid2refpdbname[domainid];
46723
- let chainid = domainid.substr(0, domainid.indexOf('-'));
46859
+ ic.domainid2refpdbname[domainid];
46860
+ domainid.substr(0, domainid.indexOf(','));
46724
46861
 
46725
46862
  let pdb_target = ic.domainid2pdb[domainid];
46726
46863
  for(let index = 0, indexl = ic.pdbDataArray.length; index < indexl; ++index) {
@@ -46740,11 +46877,14 @@ class LineGraph {
46740
46877
  }
46741
46878
 
46742
46879
  let dataArray3 = [];
46743
- let allPromise = Promise.allSettled(ajaxArray);
46744
- dataArray3 = await allPromise;
46880
+ //let allPromise = Promise.allSettled(ajaxArray);
46881
+ //dataArray3 = await allPromise;
46882
+
46883
+ dataArray3 = await this.promiseWithFixedJobs(ajaxArray);
46745
46884
 
46746
46885
  await thisClass.parseAlignData(dataArray3, domainidpairArray3);
46747
46886
  }
46887
+ /*
46748
46888
  }
46749
46889
  catch(err) {
46750
46890
  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...";
@@ -46756,17 +46896,23 @@ class LineGraph {
46756
46896
  }
46757
46897
  //console.log("Error in aligning with TM-align...");
46758
46898
  return;
46759
- }
46899
+ }
46900
+ */
46760
46901
  }
46761
46902
 
46762
46903
  getTemplateList(chainid) { let ic = this.icn3d; ic.icn3dui;
46763
- let domainid2refpdbname = {};
46904
+ let domainid2refpdbname = {}, domainid2score = {};
46764
46905
 
46765
46906
  for(let i = 0, il = ic.chainid2refpdbname[chainid].length; i < il; ++i) {
46766
46907
  let refpdbname_domainid = ic.chainid2refpdbname[chainid][i].split('|');
46767
46908
  domainid2refpdbname[refpdbname_domainid[1]] = refpdbname_domainid[0];
46768
46909
  }
46769
46910
 
46911
+ for(let i = 0, il = ic.chainid2score[chainid].length; i < il; ++i) {
46912
+ let score_domainid = ic.chainid2score[chainid][i].split('|');
46913
+ domainid2score[score_domainid[1]] = score_domainid[0];
46914
+ }
46915
+
46770
46916
  let domainidArray = Object.keys(domainid2refpdbname);
46771
46917
  domainidArray.sort(function(id1, id2) {
46772
46918
  let resi1 = parseInt(id1.substr(id1.lastIndexOf('_') + 1));
@@ -46774,13 +46920,28 @@ class LineGraph {
46774
46920
  return resi1 - resi2;
46775
46921
  });
46776
46922
 
46777
- let chainList = '';
46923
+ let refpdbnameList = '';
46924
+ for(let i = 0, il = domainidArray.length; i < il; ++i) {
46925
+ refpdbnameList += domainid2refpdbname[domainidArray[i]];
46926
+ if(i < il - 1) refpdbnameList += ", ";
46927
+ }
46928
+
46929
+ let scoreList = '', seqidList = '', nresAlignList = '';
46778
46930
  for(let i = 0, il = domainidArray.length; i < il; ++i) {
46779
- chainList += domainid2refpdbname[domainidArray[i]];
46780
- if(i < il - 1) chainList += ", ";
46931
+ let itemArray = domainid2score[domainidArray[i]].split('_');
46932
+
46933
+ scoreList += itemArray[0];
46934
+ seqidList += itemArray[1];
46935
+ nresAlignList += itemArray[2];
46936
+
46937
+ if(i < il - 1) {
46938
+ scoreList += ", ";
46939
+ seqidList += ", ";
46940
+ nresAlignList += ", ";
46941
+ }
46781
46942
  }
46782
46943
 
46783
- return chainList;
46944
+ return {'refpdbnameList': refpdbnameList, 'scoreList': scoreList, 'seqidList': seqidList, 'nresAlignList': nresAlignList};
46784
46945
  }
46785
46946
 
46786
46947
  async parseAlignData(dataArray, domainidpairArray, bRound1) { let ic = this.icn3d, me = ic.icn3dui;
@@ -46789,33 +46950,35 @@ class LineGraph {
46789
46950
  let tmscoreThreshold = 0.4; // 0.4; //0.5;
46790
46951
 
46791
46952
  // find the best alignment for each chain
46792
- let domainid2score = {}, domainid2segs = {}, chainid2segs = {};
46953
+ let domainid2segs = {}, chainid2segs = {};
46793
46954
 
46794
46955
  if(!ic.chainid2refpdbname) ic.chainid2refpdbname = {};
46956
+ if(!ic.chainid2score) ic.chainid2score = {};
46795
46957
  if(!ic.domainid2refpdbname) ic.domainid2refpdbname = {};
46958
+ if(!ic.domainid2score) ic.domainid2score = {};
46796
46959
  if(!ic.domainid2ig2kabat) ic.domainid2ig2kabat = {};
46797
46960
  if(!ic.domainid2ig2imgt) ic.domainid2ig2imgt = {};
46798
46961
 
46799
- // ic.chainid2refpdbname = {};
46800
- // ic.domainid2refpdbname = {};
46801
- // ic.domainid2ig2kabat = {};
46802
- // ic.domainid2ig2imgt = {};
46803
-
46804
46962
  let minResidues = 20;
46805
46963
 
46806
46964
  for(let i = 0, il = domainidpairArray.length; i < il; ++i) {
46807
46965
  //let queryData = (me.bNode) ? dataArray[i] : dataArray[i].value; //[0];
46808
46966
  let queryData = dataArray[i].value; //[0];
46809
46967
 
46810
- if(!queryData) {
46968
+ if(!queryData || queryData.length == 0) {
46811
46969
  if(!me.bNode) console.log("The alignment data for " + domainidpairArray[i] + " is unavailable...");
46812
46970
  continue;
46813
46971
  }
46814
-
46815
- if(queryData.length == 0) continue;
46816
46972
 
46973
+ //let domainid_index = domainidpairArray[i].split(',');
46974
+ //let domainid = domainid_index[0];
46975
+ let domainid = domainidpairArray[i].substr(0, domainidpairArray[i].indexOf('|'));
46976
+ let refpdbname = domainidpairArray[i].substr(domainidpairArray[i].indexOf('|') + 1);
46977
+ //let chainid = domainid.split('-')[0];
46978
+
46817
46979
  if(!bRound1) {
46818
46980
  if(queryData[0].score < tmscoreThreshold || queryData[0].num_res < minResidues) {
46981
+ if(!me.bNode) console.log("domainid " + domainid + " and refpdbname " + refpdbname + " were skipped due to a TM-score less than " + tmscoreThreshold);
46819
46982
  continue;
46820
46983
  }
46821
46984
  }
@@ -46827,12 +46990,6 @@ class LineGraph {
46827
46990
  continue;
46828
46991
  }
46829
46992
  }
46830
-
46831
- //let domainid_index = domainidpairArray[i].split(',');
46832
- //let domainid = domainid_index[0];
46833
- let domainid = domainidpairArray[i].substr(0, domainidpairArray[i].indexOf('|'));
46834
- let refpdbname = domainidpairArray[i].substr(domainidpairArray[i].indexOf('|') + 1);
46835
- //let chainid = domainid.split('-')[0];
46836
46993
 
46837
46994
  if(!bRound1) {
46838
46995
  if(!me.bNode) console.log("refpdbname " + refpdbname + " TM-score: " + queryData[0].score);
@@ -46849,16 +47006,16 @@ class LineGraph {
46849
47006
  for(let i = 0, il = queryData[0].segs.length; i < il; ++i) {
46850
47007
  let seg = queryData[0].segs[i];
46851
47008
 
46852
- if(seg.q_start.indexOf('2150') != -1 || seg.q_start.indexOf('2250') != -1) {
47009
+ if(seg.q_start.indexOf('2550') != -1) {
46853
47010
  bBstrand = true;
46854
47011
  }
46855
- else if(seg.q_start.indexOf('3150') != -1 || seg.q_start.indexOf('3250') != -1) {
47012
+ else if(seg.q_start.indexOf('3550') != -1) {
46856
47013
  bCstrand = true;
46857
47014
  }
46858
- else if(seg.q_start.indexOf('7150') != -1 || seg.q_start.indexOf('7250') != -1) {
47015
+ else if(seg.q_start.indexOf('7550') != -1) {
46859
47016
  bEstrand = true;
46860
47017
  }
46861
- else if(seg.q_start.indexOf('8150') != -1 || seg.q_start.indexOf('8250') != -1) {
47018
+ else if(seg.q_start.indexOf('8550') != -1) {
46862
47019
  bFstrand = true;
46863
47020
  }
46864
47021
 
@@ -46869,35 +47026,25 @@ class LineGraph {
46869
47026
  //if(!(bBstrand && bCstrand && bEstrand && bFstrand && bGstrand)) continue;
46870
47027
  if(!(bBstrand && bCstrand && bEstrand && bFstrand)) {
46871
47028
  if(!me.bNode) console.log("Some of the Ig strands B, C, E, F are missing in the domain " + domainid + "...");
46872
- if(ic.domainid2refpdbname[domainid] == refpdbname) delete ic.domainid2refpdbname[domainid];
47029
+ if(ic.domainid2refpdbname[domainid] == refpdbname) {
47030
+ delete ic.domainid2refpdbname[domainid];
47031
+ delete ic.domainid2score[domainid];
47032
+ }
46873
47033
  continue;
46874
47034
  }
46875
47035
  }
46876
47036
 
46877
47037
  if(!bRound1) {
46878
47038
  console.log("domainid: " + domainid);
46879
-
46880
- if(!domainid2score.hasOwnProperty(domainid) || queryData[0].score > domainid2score[domainid]) {
46881
- domainid2score[domainid] = queryData[0].score;
46882
-
46883
- ic.domainid2refpdbname[domainid] = refpdbname;
46884
- domainid2segs[domainid] = queryData[0].segs;
46885
- ic.domainid2ig2kabat[domainid] = queryData[0].ig2kabat;
46886
- ic.domainid2ig2imgt[domainid] = queryData[0].ig2imgt;
46887
- }
46888
47039
  }
46889
- else {
46890
- //let mixScore = 10 / queryData[0].super_rmsd + queryData[0].num_seg / 5;
46891
- let mixScore = queryData[0].score;
46892
47040
 
46893
- if(!domainid2score.hasOwnProperty(domainid) || mixScore > domainid2score[domainid]) {
46894
- domainid2score[domainid] = mixScore;
46895
-
46896
- ic.domainid2refpdbname[domainid] = refpdbname;
46897
- domainid2segs[domainid] = queryData[0].segs;
46898
- ic.domainid2ig2kabat[domainid] = queryData[0].ig2kabat;
46899
- ic.domainid2ig2imgt[domainid] = queryData[0].ig2imgt;
46900
- }
47041
+ if(!ic.domainid2score.hasOwnProperty(domainid) || queryData[0].score >= ic.domainid2score[domainid].split('_')[0]) {
47042
+ ic.domainid2score[domainid] = queryData[0].score + '_' + queryData[0].frac_identical + '_' + queryData[0].num_res ;
47043
+
47044
+ ic.domainid2refpdbname[domainid] = refpdbname;
47045
+ domainid2segs[domainid] = queryData[0].segs;
47046
+ ic.domainid2ig2kabat[domainid] = queryData[0].ig2kabat;
47047
+ ic.domainid2ig2imgt[domainid] = queryData[0].ig2imgt;
46901
47048
  }
46902
47049
  }
46903
47050
 
@@ -46912,7 +47059,7 @@ class LineGraph {
46912
47059
  let pdbAjaxArray = [];
46913
47060
  let refpdbname = ic.domainid2refpdbname[domainid];
46914
47061
  //let pdbid = domainid.substr(0, domainid.indexOf('_'));
46915
- let chainid = domainid.substr(0, domainid.indexOf('-'));
47062
+ let chainid = domainid.substr(0, domainid.indexOf(','));
46916
47063
 
46917
47064
  //if(ic.refpdbHash.hasOwnProperty(pdbid)) {
46918
47065
  if(ic.refpdbHash.hasOwnProperty(chainid)) {
@@ -46935,8 +47082,10 @@ class LineGraph {
46935
47082
  pdbAjaxArray.push(pdbAjax);
46936
47083
  }
46937
47084
 
46938
- let allPromise2 = Promise.allSettled(pdbAjaxArray);
46939
- ic.pdbDataArray = await allPromise2;
47085
+ //let allPromise2 = Promise.allSettled(pdbAjaxArray);
47086
+ //ic.pdbDataArray = await allPromise2;
47087
+
47088
+ ic.pdbDataArray = await this.promiseWithFixedJobs(pdbAjaxArray);
46940
47089
 
46941
47090
  let pdb_target = ic.domainid2pdb[domainid];
46942
47091
  for(let index = 0, indexl = ic.pdbDataArray.length; index < indexl; ++index) {
@@ -46959,49 +47108,46 @@ class LineGraph {
46959
47108
  //let allPromise = Promise.allSettled(ajaxArray);
46960
47109
  //dataArray3 = await allPromise;
46961
47110
 
46962
- //split arrays into chunks of 48 jobs or me.cfg.maxajax jobs
46963
- let n = (me.cfg.maxajax) ? me.cfg.maxajax : ic.refpdbArray.length * 6;
46964
-
46965
- for(let i = 0, il = parseInt((ajaxArray.length - 1) / n + 1); i < il; ++i) {
46966
- let currAjaxArray = [];
46967
- if(i == il - 1) { // last one
46968
- currAjaxArray = ajaxArray.slice(i * n, ajaxArray.length);
46969
- }
46970
- else {
46971
- currAjaxArray = ajaxArray.slice(i * n, (i + 1) * n);
46972
- }
46973
-
46974
- let currPromise = Promise.allSettled(currAjaxArray);
46975
- let currDataArray = await currPromise;
46976
-
46977
- dataArray3 = dataArray3.concat(currDataArray);
46978
- }
47111
+ dataArray3 = await this.promiseWithFixedJobs(ajaxArray);
46979
47112
 
46980
47113
  await thisClass.parseAlignData(dataArray3, domainidpairArray3, false);
46981
47114
 
46982
47115
  // end of round 2
46983
47116
  return;
46984
47117
  }
46985
-
47118
+
46986
47119
  // combine domainid into chainid
46987
47120
  let processedChainid = {};
46988
47121
  for(let domainid in ic.domainid2refpdbname) {
46989
- let chainid = domainid.split('-')[0];
47122
+ // remove the first round template
47123
+ if(ic.domainid2refpdbname[domainid].substr(0,1) == '1') {
47124
+ delete ic.domainid2refpdbname[domainid];
47125
+ delete ic.domainid2score[domainid];
47126
+ continue;
47127
+ }
46990
47128
 
46991
- if(!processedChainid.hasOwnProperty(chainid)) ic.chainid2refpdbname[chainid] = [];
47129
+ let chainid = domainid.split(',')[0];
47130
+
47131
+ if(!processedChainid.hasOwnProperty(chainid)) {
47132
+ ic.chainid2refpdbname[chainid] = [];
47133
+ ic.chainid2score[chainid] = [];
47134
+ }
46992
47135
  processedChainid[chainid] = 1;
46993
47136
 
46994
47137
  if(!ic.chainid2refpdbname.hasOwnProperty(chainid)) ic.chainid2refpdbname[chainid] = [];
46995
47138
  ic.chainid2refpdbname[chainid].push(ic.domainid2refpdbname[domainid] + '|' + domainid);
47139
+
47140
+ if(!ic.chainid2score.hasOwnProperty(chainid)) ic.chainid2score[chainid] = [];
47141
+ ic.chainid2score[chainid].push(ic.domainid2score[domainid] + '|' + domainid);
46996
47142
  }
46997
-
47143
+
46998
47144
  // combine domainid into chainid
46999
47145
  for(let domainid in domainid2segs) {
47000
- let chainid = domainid.split('-')[0];
47146
+ let chainid = domainid.split(',')[0];
47001
47147
  if(!chainid2segs[chainid]) chainid2segs[chainid] = [];
47002
47148
  chainid2segs[chainid] = chainid2segs[chainid].concat(domainid2segs[domainid]);
47003
47149
  }
47004
-
47150
+
47005
47151
  // assign ic.resid2refnum, ic.refnum2residArray, ic.chainsMapping
47006
47152
  if(!ic.resid2refnum) ic.resid2refnum = {};
47007
47153
  if(!ic.refnum2residArray) ic.refnum2residArray = {};
@@ -47014,11 +47160,18 @@ class LineGraph {
47014
47160
 
47015
47161
  let refpdbnameArray = ic.chainid2refpdbname[chainid];
47016
47162
 
47017
- let chainList = this.getTemplateList(chainid);
47163
+ let result = this.getTemplateList(chainid);
47164
+ let refpdbnameList = result.refpdbnameList;
47165
+ let scoreList = result.scoreList;
47166
+ let seqidList = result.seqidList;
47167
+ let nresAlignList = result.nresAlignList;
47018
47168
 
47019
- //if(!me.bNode) console.log("The reference PDB(s) for chain " + chainid + " are " + chainList);
47020
- if(!me.bNode) console.log("The reference PDB(s) for chain " + chainid + " are " + chainList);
47021
- ic.refPdbList.push("The reference PDB(s) for chain " + chainid + " are " + chainList);
47169
+ 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 + ".";
47170
+ if(!me.bNode) {
47171
+ console.log(message);
47172
+ me.htmlCls.clickMenuCls.setLogCmd(message, true);
47173
+ }
47174
+ ic.refPdbList.push(message);
47022
47175
 
47023
47176
  let prevStrand;
47024
47177
  let bCd19 = refpdbnameArray.length == 1 && refpdbnameArray[0] == 'CD19_6al5A_human_C2orV-n1';
@@ -47088,51 +47241,52 @@ class LineGraph {
47088
47241
  getLabelFromRefnum(oriRefnum, prevStrand, bCd19) { let ic = this.icn3d; ic.icn3dui;
47089
47242
  let refnum = parseInt(oriRefnum);
47090
47243
 
47091
- // A-: 10xx
47092
- // A: 11xx
47093
- // A+ continue A
47094
- // A': 12xx
47095
- // B: 21xx
47096
- // C: 32xx
47097
- // C': 42xx
47098
- // C'': 51xx, 52xx
47099
- // D: 61xx
47100
- // E: 71xx
47101
- // E+: continue E
47102
- // F: 82xx
47103
- // G: 91xx, 92xx
47104
- // G+: continue G
47105
-
47106
- // if(refnum < 100) return " " + oriRefnum;
47107
- // else if(refnum >= 100 && refnum < 1000) {
47108
- // if(bCd19) return " " + oriRefnum;
47109
- // else return "A^" + oriRefnum;
47110
- // }
47111
- if(refnum < 900) return undefined;
47112
- else if(refnum >= 900 && refnum < 1000) return " " + oriRefnum;
47113
- else if(refnum >= 1000 && refnum < 1100) return "A-" + oriRefnum;
47114
- else if(refnum >= 1100 && refnum < 1200) return "A" + oriRefnum; // could be A+
47115
- else if(refnum >= 1200 && refnum < 1300) return "A'" + oriRefnum;
47116
- //else if(refnum >= 1300 && refnum < 1400) return "A+" + oriRefnum;
47117
- else if(refnum >= 1300 && refnum < 2000) {
47118
- if(prevStrand && prevStrand.substr(0, 1) == 'A') {
47119
- return prevStrand + oriRefnum;
47120
- }
47121
- else {
47122
- return "A" + oriRefnum;
47123
- }
47124
- }
47125
- else if(refnum >= 2000 && refnum < 3000) return "B" + oriRefnum;
47126
- else if(refnum >= 3000 && refnum < 4000) return "C" + oriRefnum;
47127
- else if(refnum >= 4000 && refnum < 5000) return "C'" + oriRefnum;
47128
- else if(refnum >= 5000 && refnum < 6000) return "C''" + oriRefnum;
47129
- else if(refnum >= 6000 && refnum < 7000) return "D" + oriRefnum;
47130
- else if(refnum >= 7000 && refnum < 8000) return "E" + oriRefnum; // could be E+
47131
- else if(refnum >= 8000 && refnum < 9000) return "F" + oriRefnum;
47132
- else if(refnum >= 9000 && refnum < 9300) return "G" + oriRefnum; // could be G+
47133
- //else if(refnum >= 9400 && refnum < 9500) return "G+" + oriRefnum;
47134
- else if(refnum >= 9300) return "G" + oriRefnum;
47135
- }
47244
+ //N-terminus = 0999-0001
47245
+ //A--- = 12xx
47246
+ //A-- = 13xx
47247
+ //A- = 14xx
47248
+ //A = 15xx (anchor 1550)
47249
+ //A+ = 16xx
47250
+ //A' = 18xx (anchor 1850)
47251
+ //B = 25xx (anchor 2550)
47252
+ //C-- = 33xx
47253
+ //C- = 34xx
47254
+ //C = 35xx (anchor 3550)
47255
+ //C' = 45xx (anchor 4550)
47256
+ //C'' = 55xx (anchor 5550)
47257
+ //D = 65xx (anchor 3550)
47258
+ //E = 75xx (anchor 7550)
47259
+ //E+ = 76xx
47260
+ //F = 85xx (anchor 8550)
47261
+ //G = 95xx (anchor 9550)
47262
+ //G+ = 96xx
47263
+ //G++ = 97xx
47264
+ //C-terminus = 9901-9999 (no anchor, numbering going forward)
47265
+
47266
+ // loops may have numbers such as 1310, 1410
47267
+
47268
+ if(refnum < 1000) return undefined;
47269
+ else if(refnum >= 1200 && refnum < 1290) return "A---" + oriRefnum;
47270
+ else if(refnum >= 1320 && refnum < 1390) return "A--" + oriRefnum;
47271
+ else if(refnum >= 1420 && refnum < 1490) return "A-" + oriRefnum;
47272
+ else if(refnum >= 1520 && refnum < 1590) return "A" + oriRefnum;
47273
+ else if(refnum >= 1620 && refnum < 1690) return "A+" + oriRefnum;
47274
+ else if(refnum >= 1820 && refnum < 1890) return "A'" + oriRefnum;
47275
+ else if(refnum >= 2000 && refnum < 2900) return "B" + oriRefnum;
47276
+ else if(refnum >= 3300 && refnum < 3390) return "C--" + oriRefnum;
47277
+ else if(refnum >= 3420 && refnum < 3490) return "C-" + oriRefnum;
47278
+ else if(refnum >= 3520 && refnum < 3590) return "C" + oriRefnum;
47279
+ else if(refnum >= 4000 && refnum < 4900) return "C'" + oriRefnum;
47280
+ else if(refnum >= 5000 && refnum < 5900) return "C''" + oriRefnum;
47281
+ else if(refnum >= 6000 && refnum < 6900) return "D" + oriRefnum;
47282
+ else if(refnum >= 7500 && refnum < 7590) return "E" + oriRefnum;
47283
+ else if(refnum >= 7620 && refnum < 7900) return "E+" + oriRefnum;
47284
+ else if(refnum >= 8000 && refnum < 8900) return "F" + oriRefnum;
47285
+ else if(refnum >= 9500 && refnum < 9590) return "G" + oriRefnum;
47286
+ else if(refnum >= 9620 && refnum < 9690) return "G+" + oriRefnum;
47287
+ else if(refnum >= 9720 && refnum < 9790) return "G++" + oriRefnum;
47288
+ else if(refnum > 9900) return undefined;
47289
+ else return " " + oriRefnum; }
47136
47290
 
47137
47291
  async parseCustomRefFile(data) { let ic = this.icn3d; ic.icn3dui;
47138
47292
  ic.bShowCustomRefnum = true;
@@ -47314,6 +47468,32 @@ class LineGraph {
47314
47468
  return refData;
47315
47469
  }
47316
47470
  }
47471
+
47472
+ async promiseWithFixedJobs(ajaxArray) { let ic = this.icn3d, me = ic.icn3dui;
47473
+ let dataArray3 = [];
47474
+ //let allPromise = Promise.allSettled(ajaxArray);
47475
+ //dataArray3 = await allPromise;
47476
+
47477
+ //split arrays into chunks of 48 jobs or me.cfg.maxajax jobs
47478
+ let n = (me.cfg.maxajax) ? me.cfg.maxajax : ic.refpdbArray.length * 6;
47479
+
47480
+ for(let i = 0, il = parseInt((ajaxArray.length - 1) / n + 1); i < il; ++i) {
47481
+ let currAjaxArray = [];
47482
+ if(i == il - 1) { // last one
47483
+ currAjaxArray = ajaxArray.slice(i * n, ajaxArray.length);
47484
+ }
47485
+ else {
47486
+ currAjaxArray = ajaxArray.slice(i * n, (i + 1) * n);
47487
+ }
47488
+
47489
+ let currPromise = Promise.allSettled(currAjaxArray);
47490
+ let currDataArray = await currPromise;
47491
+
47492
+ dataArray3 = dataArray3.concat(currDataArray);
47493
+ }
47494
+
47495
+ return dataArray3;
47496
+ }
47317
47497
  }
47318
47498
 
47319
47499
  /**
@@ -48622,7 +48802,7 @@ class ViewInterPairs {
48622
48802
 
48623
48803
  if(ic.bD3 === undefined) {
48624
48804
  //let url = "https://d3js.org/d3.v4.min.js";
48625
- let url = "https://www.ncbi.nlm.nih.gov/Structure/icn3d/script/d3v4-force-all.min.js";
48805
+ let url = "./script/d3v4-force-all.min.js";
48626
48806
  await me.getAjaxPromise(url, 'script');
48627
48807
 
48628
48808
  ic.bD3 = true;
@@ -49897,7 +50077,7 @@ class AlignParser {
49897
50077
  for(let j = 0, jl = mmdbTmp.molecules.length; j < jl; ++j) {
49898
50078
  let molecule = mmdbTmp.molecules[j];
49899
50079
  let molid = molecule.moleculeId;
49900
- let chainName = molecule.chain.trim();
50080
+ let chainName = molecule.chain.trim().replace(/_/g, ''); // change "A_1" to "A1"
49901
50081
  if(chainNameHash[chainName] === undefined) {
49902
50082
  chainNameHash[chainName] = 1;
49903
50083
  }
@@ -50308,6 +50488,8 @@ class ChainalignParser {
50308
50488
 
50309
50489
  let queryData = {}; // check whether undefined
50310
50490
 
50491
+ me.htmlCls.clickMenuCls.setLogCmd("Align " + mmdbid_t + " with " + mmdbid_q, false);
50492
+
50311
50493
  this.processAlign(align, index, queryData, bEqualMmdbid, bEqualChain);
50312
50494
  }
50313
50495
 
@@ -50405,6 +50587,8 @@ class ChainalignParser {
50405
50587
  continue;
50406
50588
  }
50407
50589
 
50590
+ me.htmlCls.clickMenuCls.setLogCmd("Align " + mmdbid1 + " with " + mmdbid2, false);
50591
+
50408
50592
  let bNoAlert = true;
50409
50593
  let bAligned = this.processAlign(align, i, queryData, bEqualMmdbid, bEqualChain, bNoAlert);
50410
50594
 
@@ -50855,6 +51039,8 @@ class ChainalignParser {
50855
51039
  let bEqualMmdbid = (mmdbid_q == mmdbid_t);
50856
51040
  let bEqualChain = (chain_q == chain_t);
50857
51041
 
51042
+ me.htmlCls.clickMenuCls.setLogCmd("Align " + mmdbid_t + " with " + mmdbid_q, false);
51043
+
50858
51044
  this.processAlign(align, index-1, queryData, bEqualMmdbid, bEqualChain);
50859
51045
  }
50860
51046
  }
@@ -50915,6 +51101,7 @@ class ChainalignParser {
50915
51101
  ic.qt_start_end[index] = align[0].segs;
50916
51102
 
50917
51103
  let rmsd = align[0].super_rmsd;
51104
+ console.log();
50918
51105
 
50919
51106
  let logStr = "alignment RMSD: " + rmsd.toPrecision(4);
50920
51107
  if(me.cfg.aligntool == 'tmalign') logStr += "; TM-score: " + align[0].score.toPrecision(4);
@@ -51184,10 +51371,10 @@ class Dsn6Parser {
51184
51371
  // https://edmaps.rcsb.org/maps/1kq2_fofc.dsn6
51185
51372
 
51186
51373
  let url = "https://edmaps.rcsb.org/maps/" + pdbid.toLowerCase() + "_" + type + ".dsn6";
51187
- await this.dsn6ParserBase(url, type, sigma);
51374
+ await this.dsn6ParserBase(url, type, sigma, 'url', true);
51188
51375
  }
51189
51376
 
51190
- async dsn6ParserBase(url, type, sigma) { let ic = this.icn3d, me = ic.icn3dui;
51377
+ async dsn6ParserBase(url, type, sigma, location, bInputSigma) { let ic = this.icn3d, me = ic.icn3dui;
51191
51378
  let thisClass = this;
51192
51379
 
51193
51380
  //https://stackoverflow.com/questions/33902299/using-jquery-ajax-to-download-a-binary-file
@@ -51201,7 +51388,7 @@ class Dsn6Parser {
51201
51388
  }
51202
51389
  else {
51203
51390
  let arrayBuffer = await me.getXMLHttpRqstPromise(url, 'GET', 'arraybuffer', 'rcsbEdmaps');
51204
- thisClass.loadDsn6Data(arrayBuffer, type, sigma);
51391
+ sigma = thisClass.loadDsn6Data(arrayBuffer, type, sigma, location, bInputSigma);
51205
51392
 
51206
51393
  if(type == '2fofc') {
51207
51394
  ic.bAjax2fofc = true;
@@ -51212,9 +51399,11 @@ class Dsn6Parser {
51212
51399
 
51213
51400
  ic.setOptionCls.setOption('map', type);
51214
51401
  }
51402
+
51403
+ return sigma;
51215
51404
  }
51216
51405
 
51217
- loadDsn6Data(dsn6data, type, sigma) { let ic = this.icn3d; ic.icn3dui;
51406
+ loadDsn6Data(dsn6data, type, sigma, location, bInputSigma) { let ic = this.icn3d; ic.icn3dui;
51218
51407
  // DSN6 http://www.uoxray.uoregon.edu/tnt/manual/node104.html
51219
51408
  // BRIX http://svn.cgl.ucsf.edu/svn/chimera/trunk/libs/VolumeData/dsn6/brix-1.html
51220
51409
 
@@ -51263,9 +51452,9 @@ class Dsn6Parser {
51263
51452
  }
51264
51453
  }
51265
51454
 
51266
- header.zStart = intView[ 2 ];
51267
51455
  header.xStart = intView[ 0 ]; // NXSTART
51268
51456
  header.yStart = intView[ 1 ];
51457
+ header.zStart = intView[ 2 ];
51269
51458
 
51270
51459
  header.xExtent = intView[ 3 ]; // NX
51271
51460
  header.yExtent = intView[ 4 ];
@@ -51301,6 +51490,7 @@ class Dsn6Parser {
51301
51490
  let zBlocks = Math.ceil(header.zExtent / 8);
51302
51491
 
51303
51492
  // loop over blocks
51493
+ let maxValue = -999;
51304
51494
  for(let zz = 0; zz < zBlocks; ++zz) {
51305
51495
  for(let yy = 0; yy < yBlocks; ++yy) {
51306
51496
  for(let xx = 0; xx < xBlocks; ++xx) {
@@ -51316,6 +51506,7 @@ class Dsn6Parser {
51316
51506
  if(x < header.xExtent && y < header.yExtent && z < header.zExtent) {
51317
51507
  let idx =((((x * header.yExtent) + y) * header.zExtent) + z);
51318
51508
  data[ idx ] =(byteView[ offset ] - summand) / divisor;
51509
+ if(data[ idx ] > maxValue) maxValue = data[ idx ];
51319
51510
  ++offset;
51320
51511
  } else {
51321
51512
  offset += 8 - i;
@@ -51328,6 +51519,10 @@ class Dsn6Parser {
51328
51519
  }
51329
51520
  }
51330
51521
 
51522
+ if(!bInputSigma) {
51523
+ sigma = this.setSigma(maxValue, location, type, sigma);
51524
+ }
51525
+
51331
51526
  if(type == '2fofc') {
51332
51527
  ic.mapData.header2 = header;
51333
51528
  ic.mapData.data2 = data;
@@ -51342,6 +51537,32 @@ class Dsn6Parser {
51342
51537
  ic.mapData.type = type;
51343
51538
  ic.mapData.sigma = sigma;
51344
51539
  }
51540
+
51541
+ return sigma;
51542
+ }
51543
+
51544
+ setSigma(maxValue, location, type, sigma) { let ic = this.icn3d, me = ic.icn3dui;
51545
+ let inputId;
51546
+ if(location == 'file') {
51547
+ inputId = 'dsn6sigma' + type;
51548
+ }
51549
+ else if(location == 'url') {
51550
+ inputId = 'dsn6sigmaurl' + type;
51551
+ }
51552
+
51553
+ let factor = (type == '2fofc') ? 0.5 : 0.3;
51554
+
51555
+ if(inputId) {
51556
+ if(!($("#" + me.pre + inputId).val())) {
51557
+ sigma = (factor * maxValue).toFixed(2);
51558
+ $("#" + me.pre + inputId).val(sigma);
51559
+ }
51560
+ else {
51561
+ sigma = $("#" + me.pre + inputId).val();
51562
+ }
51563
+ }
51564
+
51565
+ return sigma;
51345
51566
  }
51346
51567
 
51347
51568
  getMatrix(header) { let ic = this.icn3d; ic.icn3dui;
@@ -51415,7 +51636,9 @@ class Dsn6Parser {
51415
51636
  let reader = new FileReader();
51416
51637
  reader.onload = function(e) { let ic = thisClass.icn3d;
51417
51638
  let arrayBuffer = e.target.result; // or = reader.result;
51418
- thisClass.loadDsn6Data(arrayBuffer, type, sigma);
51639
+
51640
+ sigma = thisClass.loadDsn6Data(arrayBuffer, type, sigma, 'file');
51641
+
51419
51642
  if(type == '2fofc') {
51420
51643
  ic.bAjax2fofc = true;
51421
51644
  }
@@ -51423,21 +51646,1006 @@ class Dsn6Parser {
51423
51646
  ic.bAjaxfofc = true;
51424
51647
  }
51425
51648
  ic.setOptionCls.setOption('map', type);
51426
- me.htmlCls.clickMenuCls.setLogCmd('load dsn6 file ' + $("#" + ic.pre + "dsn6file" + type).val(), false);
51649
+ me.htmlCls.clickMenuCls.setLogCmd('load map file ' + $("#" + ic.pre + "dsn6file" + type).val() + ' with sigma ' + sigma, false);
51427
51650
  };
51428
51651
  reader.readAsArrayBuffer(file);
51429
51652
  }
51430
51653
  }
51431
51654
 
51432
51655
  loadDsn6FileUrl(type) {var ic = this.icn3d, me = ic.icn3dui;
51656
+ let url = $("#" + ic.pre + "dsn6fileurl" + type).val();
51657
+ let sigma = $("#" + ic.pre + "dsn6sigmaurl" + type).val();
51658
+ if(!url) {
51659
+ alert("Please input the file URL before clicking 'Load'");
51660
+ }
51661
+ else {
51662
+ sigma = this.dsn6ParserBase(url, type, sigma, 'url');
51663
+ me.htmlCls.clickMenuCls.setLogCmd('set map ' + type + ' sigma ' + sigma + ' file dsn6 | ' + encodeURIComponent(url), true);
51664
+ }
51665
+ }
51666
+
51667
+ }
51668
+
51669
+ /**
51670
+ * @file Ccp4 Parser
51671
+ * @author Marcin Wojdyr <wojdyr@gmail.com>
51672
+ * @private
51673
+ * Modified by Jiyao Wang / https://github.com/ncbi/icn3d
51674
+ */
51675
+
51676
+ class Ccp4Parser {
51677
+ constructor(icn3d) {
51678
+ this.icn3d = icn3d;
51679
+ }
51680
+
51681
+ async ccp4ParserBase(url, type, sigma, location) { let ic = this.icn3d, me = ic.icn3dui;
51682
+ let thisClass = this;
51683
+
51684
+ //https://stackoverflow.com/questions/33902299/using-jquery-ajax-to-download-a-binary-file
51685
+ // if(type == '2fofc' && ic.bAjax2fofcccp4) {
51686
+ // ic.mapData.sigma2 = sigma;
51687
+ // ic.setOptionCls.setOption('map', type);
51688
+ // }
51689
+ // else if(type == 'fofc' && ic.bAjaxfofcccp4) {
51690
+ // ic.mapData.sigma = sigma;
51691
+ // ic.setOptionCls.setOption('map', type);
51692
+ // }
51693
+ // else {
51694
+ let arrayBuffer = await me.getXMLHttpRqstPromise(url, 'GET', 'arraybuffer', '');
51695
+ let bInputSigma = true;
51696
+ sigma = thisClass.load_map_from_buffer(arrayBuffer, type, sigma, location, bInputSigma);
51697
+
51698
+ // if(type == '2fofc') {
51699
+ // ic.bAjax2fofcccp4 = true;
51700
+ // }
51701
+ // else if(type == 'fofc') {
51702
+ // ic.bAjaxfofcccp4 = true;
51703
+ // }
51704
+
51705
+ ic.setOptionCls.setOption('map', type);
51706
+
51707
+ return sigma;
51708
+ // }
51709
+ }
51710
+
51711
+ // modified from_ccp4() at https://github.com/uglymol/uglymol.github.io/blob/master/src/elmap.js
51712
+ load_map_from_buffer(buf, type, sigma, location, bInputSigma) { let ic = this.icn3d; ic.icn3dui;
51713
+ if (buf.byteLength < 1024) throw Error('File shorter than 1024 bytes.');
51714
+
51715
+ //console.log('buf type: ' + Object.prototype.toString.call(buf));
51716
+ // for now we assume both file and host are little endian
51717
+ const iview = new Int32Array(buf, 0, 256);
51718
+ // word 53 - character string 'MAP ' to identify file type
51719
+ if (iview[52] !== 0x2050414d) throw Error('not a CCP4 map');
51720
+
51721
+ // map has 3 dimensions referred to as columns (fastest changing), rows
51722
+ // and sections (c-r-s)
51723
+ const n_crs = [iview[0], iview[1], iview[2]]; // 108, 108, 108
51724
+ const mode = iview[3]; //2
51725
+ let nb;
51726
+ if (mode === 2) nb = 4;
51727
+ else if (mode === 0) nb = 1;
51728
+ else throw Error('Only Mode 2 and Mode 0 of CCP4 map is supported.');
51729
+
51730
+ const start = [iview[4], iview[5], iview[6]]; // 0,0,0
51731
+ const n_grid = [iview[7], iview[8], iview[9]]; // 108,108,108
51732
+ const nsymbt = iview[23]; // size of extended header in bytes
51733
+ // nsymbt = 1920
51734
+
51735
+ if (1024 + nsymbt + nb*n_crs[0]*n_crs[1]*n_crs[2] !== buf.byteLength) {
51736
+ throw Error('ccp4 file too short or too long');
51737
+ }
51738
+
51739
+ const fview = new Float32Array(buf, 0, buf.byteLength / 4);
51740
+ const grid = new GridArray(n_grid);
51741
+ 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
51742
+
51743
+ // MAPC, MAPR, MAPS - axis corresp to cols, rows, sections (1,2,3 for X,Y,Z)
51744
+ const map_crs = [iview[16], iview[17], iview[18]]; // 2,1,3
51745
+ const ax = map_crs.indexOf(1);
51746
+ const ay = map_crs.indexOf(2);
51747
+ const az = map_crs.indexOf(3);
51748
+
51749
+ const min = fview[19]; // -0.49
51750
+ const max = fview[20]; // 0.94
51751
+ //const sg_number = iview[22];
51752
+ //const lskflg = iview[24];
51753
+
51754
+ if (nsymbt % 4 !== 0) {
51755
+ throw Error('CCP4 map with NSYMBT not divisible by 4 is not supported.');
51756
+ }
51757
+ let data_view;
51758
+ if (mode === 2) data_view = fview;
51759
+ else /* mode === 0 */ data_view = new Int8Array(buf);
51760
+ let idx = (1024 + nsymbt) / nb | 0; //736
51761
+
51762
+ // We assume that if DMEAN and RMS from the header are not clearly wrong
51763
+ // they are what the user wants. Because the map can cover a small part
51764
+ // of the asu and its rmsd may be different than the total rmsd.
51765
+ // let stats = { mean: 0.0, rms: 1.0 };
51766
+ // stats.mean = fview[21]; //0
51767
+ // stats.rms = fview[54]; //0.15
51768
+ // if (stats.mean < min || stats.mean > max || stats.rms <= 0) {
51769
+ // stats = this.calculate_stddev(data_view, idx);
51770
+ // }
51771
+
51772
+ let b1 = 1;
51773
+ let b0 = 0;
51774
+ // if the file was converted by mapmode2to0 - scale the data
51775
+ if (mode === 0 && iview[39] === -128 && iview[40] === 127) { //39:0, 40:0
51776
+ // scaling f(x)=b1*x+b0 such that f(-128)=min and f(127)=max
51777
+ b1 = (max - min) / 255.0;
51778
+ b0 = 0.5 * (min + max + b1);
51779
+ }
51780
+
51781
+ const end = [start[0] + n_crs[0], start[1] + n_crs[1], start[2] + n_crs[2]];
51782
+ let it = [0, 0, 0];
51783
+ let maxValue = -999;
51784
+ for (it[2] = start[2]; it[2] < end[2]; it[2]++) { // sections
51785
+ for (it[1] = start[1]; it[1] < end[1]; it[1]++) { // rows
51786
+ for (it[0] = start[0]; it[0] < end[0]; it[0]++) { // cols
51787
+ let value = b1 * data_view[idx] + b0;
51788
+ grid.set_grid_value(it[ax], it[ay], it[az], value);
51789
+
51790
+ if(value > maxValue) maxValue = value;
51791
+ idx++;
51792
+ }
51793
+ }
51794
+ }
51795
+
51796
+ /*
51797
+ if (expand_symmetry && nsymbt > 0) {
51798
+ const u8view = new Uint8Array(buf);
51799
+ for (let i = 0; i+80 <= nsymbt; i += 80) {
51800
+ let j;
51801
+ let symop = '';
51802
+ for (j = 0; j < 80; ++j) {
51803
+ symop += String.fromCharCode(u8view[1024 + i + j]);
51804
+ }
51805
+ if (/^\s*x\s*,\s*y\s*,\s*z\s*$/i.test(symop)) continue; // skip x,y,z
51806
+ //console.log('sym ops', symop.trim());
51807
+ let mat = this.parse_symop(symop);
51808
+ // Note: we apply here symops to grid points instead of coordinates.
51809
+ // In the cases we came across it is equivalent, but in general not.
51810
+ for (j = 0; j < 3; ++j) {
51811
+ mat[j][3] = Math.round(mat[j][3] * n_grid[j]) | 0;
51812
+ }
51813
+ idx = (1024 + nsymbt) / nb | 0;
51814
+ let xyz = [0, 0, 0];
51815
+ for (it[2] = start[2]; it[2] < end[2]; it[2]++) { // sections
51816
+ for (it[1] = start[1]; it[1] < end[1]; it[1]++) { // rows
51817
+ for (it[0] = start[0]; it[0] < end[0]; it[0]++) { // cols
51818
+ for (j = 0; j < 3; ++j) {
51819
+ xyz[j] = it[ax] * mat[j][0] + it[ay] * mat[j][1] +
51820
+ it[az] * mat[j][2] + mat[j][3];
51821
+ }
51822
+ let value = b1 * data_view[idx] + b0;
51823
+ grid.set_grid_value(xyz[0], xyz[1], xyz[2], value);
51824
+
51825
+ if(value > maxValue) maxValue = value;
51826
+ idx++;
51827
+ }
51828
+ }
51829
+ }
51830
+ }
51831
+ }
51832
+ */
51833
+
51834
+ if(!bInputSigma) {
51835
+ sigma = ic.dsn6ParserCls.setSigma(maxValue, location, type, sigma);
51836
+ }
51837
+
51838
+ if(type == '2fofc') {
51839
+ ic.mapData.ccp4 = 1;
51840
+ ic.mapData.grid2 = grid;
51841
+ ic.mapData.unit_cell2 = unit_cell;
51842
+ ic.mapData.type2 = type;
51843
+ ic.mapData.sigma2 = sigma;
51844
+ }
51845
+ else {
51846
+ ic.mapData.ccp4 = 1;
51847
+ ic.mapData.grid = grid;
51848
+ ic.mapData.unit_cell = unit_cell;
51849
+ ic.mapData.type = type;
51850
+ ic.mapData.sigma = sigma;
51851
+ }
51852
+
51853
+ return sigma;
51854
+ }
51855
+
51856
+ load_maps_from_mtz_buffer(mtz, type, sigma, location, bInputSigma) { let ic = this.icn3d; ic.icn3dui;
51857
+ let is_diff = (type == 'fofc'); // diff: fofc, non-diff: 2fofc
51858
+ let dataArray = mtz.calculate_map(is_diff);
51859
+
51860
+ let mc = mtz.cell;
51861
+ const unit_cell = new UnitCell(mc.a, mc.b, mc.c, mc.alpha, mc.beta, mc.gamma);
51862
+
51863
+ let maxValue = -999;
51864
+ for(let i = 0, il = dataArray.length; i < il; ++i) {
51865
+ if(dataArray[i] > maxValue) maxValue = dataArray[i];
51866
+ }
51867
+
51868
+ if(!bInputSigma) {
51869
+ sigma = ic.dsn6ParserCls.setSigma(maxValue, location, type, sigma);
51870
+ }
51871
+
51872
+ const grid = new GridArray([mtz.nx, mtz.ny, mtz.nz]);
51873
+ grid.values.set(dataArray);
51874
+
51875
+ if(type == '2fofc') {
51876
+ ic.mapData.ccp4 = 1;
51877
+ ic.mapData.grid2 = grid;
51878
+ ic.mapData.unit_cell2 = unit_cell;
51879
+ ic.mapData.type2 = type;
51880
+ ic.mapData.sigma2 = sigma;
51881
+ }
51882
+ else {
51883
+ ic.mapData.ccp4 = 1;
51884
+ ic.mapData.grid = grid;
51885
+ ic.mapData.unit_cell = unit_cell;
51886
+ ic.mapData.type = type;
51887
+ ic.mapData.sigma = sigma;
51888
+ }
51889
+
51890
+ mtz.delete();
51891
+
51892
+ return sigma;
51893
+ }
51894
+
51895
+ // calculate_stddev(a, offset) {
51896
+ // let sum = 0;
51897
+ // let sq_sum = 0;
51898
+ // const alen = a.length;
51899
+ // for (let i = offset; i < alen; i++) {
51900
+ // sum += a[i];
51901
+ // sq_sum += a[i] * a[i];
51902
+ // }
51903
+ // const mean = sum / (alen - offset);
51904
+ // const variance = sq_sum / (alen - offset) - mean * mean;
51905
+ // return {mean: mean, rms: Math.sqrt(variance)};
51906
+ // }
51907
+
51908
+ parse_symop(symop) {
51909
+ const ops = symop.toLowerCase().replace(/\s+/g, '').split(',');
51910
+ if (ops.length !== 3) throw Error('Unexpected symop: ' + symop);
51911
+ let mat = [];
51912
+ for (let i = 0; i < 3; i++) {
51913
+ const terms = ops[i].split(/(?=[+-])/);
51914
+ let row = [0, 0, 0, 0];
51915
+ for (let j = 0; j < terms.length; j++) {
51916
+ const term = terms[j];
51917
+ const sign = (term[0] === '-' ? -1 : 1);
51918
+ let m = terms[j].match(/^[+-]?([xyz])$/);
51919
+ if (m) {
51920
+ const pos = {x: 0, y: 1, z: 2}[m[1]];
51921
+ row[pos] = sign;
51922
+ } else {
51923
+ m = terms[j].match(/^[+-]?(\d)\/(\d)$/);
51924
+ if (!m) throw Error('What is ' + terms[j] + ' in ' + symop);
51925
+ row[3] = sign * Number(m[1]) / Number(m[2]);
51926
+ }
51927
+ }
51928
+ mat.push(row);
51929
+ }
51930
+ return mat;
51931
+ }
51932
+
51933
+ loadCcp4File(type) {let ic = this.icn3d, me = ic.icn3dui;
51934
+ let thisClass = this;
51935
+
51936
+ let file = $("#" + ic.pre + "dsn6file" + type)[0].files[0];
51937
+ let sigma = $("#" + ic.pre + "dsn6sigma" + type).val();
51938
+ if(!file) {
51939
+ alert("Please select a file before clicking 'Load'");
51940
+ }
51941
+ else {
51942
+ me.utilsCls.checkFileAPI();
51943
+ let reader = new FileReader();
51944
+ reader.onload = function(e) { let ic = thisClass.icn3d;
51945
+ let arrayBuffer = e.target.result; // or = reader.result;
51946
+ sigma = thisClass.load_map_from_buffer(arrayBuffer, type, sigma, 'file');
51947
+
51948
+ // if(type == '2fofc') {
51949
+ // ic.bAjax2fofcCcp4 = true;
51950
+ // }
51951
+ // else if(type == 'fofc') {
51952
+ // ic.bAjaxfofcCcp4 = true;
51953
+ // }
51954
+ ic.setOptionCls.setOption('map', type);
51955
+ me.htmlCls.clickMenuCls.setLogCmd('load map file ' + $("#" + ic.pre + "dsn6file" + type).val() + ' with sigma ' + sigma, false);
51956
+ };
51957
+ reader.readAsArrayBuffer(file);
51958
+ }
51959
+ }
51960
+
51961
+ async loadCcp4FileUrl(type) { let ic = this.icn3d, me = ic.icn3dui;
51433
51962
  let url = $("#" + ic.pre + "dsn6fileurl" + type).val();
51434
51963
  let sigma = $("#" + ic.pre + "dsn6sigmaurl" + type).val();
51435
51964
  if(!url) {
51436
51965
  alert("Please input the file URL before clicking 'Load'");
51437
51966
  }
51438
51967
  else {
51439
- this.dsn6ParserBase(url, type, sigma);
51440
- me.htmlCls.clickMenuCls.setLogCmd('set map ' + type + ' sigma ' + sigma + ' | ' + encodeURIComponent(url), true);
51968
+ sigma = await this.ccp4ParserBase(url, type, sigma, 'file');
51969
+
51970
+ me.htmlCls.clickMenuCls.setLogCmd('set map ' + type + ' sigma ' + sigma + ' file ccp4 | ' + encodeURIComponent(url), true);
51971
+ }
51972
+ }
51973
+
51974
+ // Extract a block of density for calculating an isosurface using the
51975
+ // separate marching cubes implementation.
51976
+ extract_block(grid, unit_cell, radius, center, typeDetail) { let ic = this.icn3d; ic.icn3dui;
51977
+ // let grid = this.grid;
51978
+ // let unit_cell = this.unit_cell;
51979
+ if (grid == null || unit_cell == null) { return; }
51980
+ let fc = unit_cell.fractionalize(center);
51981
+
51982
+ let r = [radius / unit_cell.parameters[0],
51983
+ radius / unit_cell.parameters[1],
51984
+ radius / unit_cell.parameters[2]];
51985
+ let grid_min = grid.frac2grid([fc[0] - r[0], fc[1] - r[1], fc[2] - r[2]]);
51986
+ let grid_max = grid.frac2grid([fc[0] + r[0], fc[1] + r[1], fc[2] + r[2]]);
51987
+
51988
+ let size = [grid_max[0] - grid_min[0] + 1,
51989
+ grid_max[1] - grid_min[1] + 1,
51990
+ grid_max[2] - grid_min[2] + 1];
51991
+ let points = [];
51992
+ let values = [];
51993
+ let threshold = 1;
51994
+ let bAtoms = ic.hAtoms && Object.keys(ic.hAtoms).length > 0;
51995
+ for (let i = grid_min[0]; i <= grid_max[0]; i++) {
51996
+ for (let j = grid_min[1]; j <= grid_max[1]; j++) {
51997
+ for (let k = grid_min[2]; k <= grid_max[2]; k++) {
51998
+ let frac = grid.grid2frac(i, j, k);
51999
+ let orth = unit_cell.orthogonalize(frac);
52000
+ points.push(orth);
52001
+
52002
+ // get overlap between map and atoms
52003
+ let positoin = new THREE.Vector3(orth[0], orth[1], orth[2]);
52004
+ let atomsNear = ic.rayCls.getAtomsFromPosition(positoin, threshold, ic.hAtoms);
52005
+
52006
+ let map_value = (atomsNear || !bAtoms) ? grid.get_grid_value(i, j, k) : 0;
52007
+
52008
+ if(typeDetail == 'fofc_pos' && map_value < 0) map_value = 0;
52009
+ if(typeDetail == 'fofc_neg') map_value = (map_value > 0) ? 0 : -map_value;
52010
+
52011
+ values.push(map_value);
52012
+ }
52013
+ }
52014
+ }
52015
+
52016
+ return {size: size, values: values, points: points};
52017
+ // this.block.set(points, values, size);
52018
+ };
52019
+
52020
+ marchingCubes(dims, values, points, isolevel, method) { let ic = this.icn3d; ic.icn3dui;
52021
+ const edgeTable = new Int32Array([
52022
+ 0x0 , 0x0 , 0x202, 0x302, 0x406, 0x406, 0x604, 0x704,
52023
+ 0x804, 0x805, 0xa06, 0xa06, 0xc0a, 0xd03, 0xe08, 0xf00,
52024
+ 0x90 , 0x98 , 0x292, 0x292, 0x496, 0x49e, 0x694, 0x694,
52025
+ 0x894, 0x894, 0xa96, 0xa96, 0xc9a, 0xc92, 0xe91, 0xe90,
52026
+ 0x230, 0x230, 0x33 , 0x13a, 0x636, 0x636, 0x434, 0x43c,
52027
+ 0xa34, 0xa35, 0x837, 0x936, 0xe3a, 0xf32, 0xc31, 0xd30,
52028
+ 0x2a0, 0x2a8, 0xa3 , 0xaa , 0x6a6, 0x6af, 0x5a4, 0x4ac,
52029
+ 0xaa4, 0xaa4, 0x9a6, 0x8a6, 0xfaa, 0xea3, 0xca1, 0xca0,
52030
+ 0x460, 0x460, 0x662, 0x762, 0x66 , 0x66 , 0x265, 0x364,
52031
+ 0xc64, 0xc65, 0xe66, 0xe66, 0x86a, 0x863, 0xa69, 0xa60,
52032
+ 0x4f0, 0x4f8, 0x6f2, 0x6f2, 0xf6 , 0xfe , 0x2f5, 0x2fc,
52033
+ 0xcf4, 0xcf4, 0xef6, 0xef6, 0x8fa, 0x8f3, 0xaf9, 0xaf0,
52034
+ 0x650, 0x650, 0x453, 0x552, 0x256, 0x256, 0x54 , 0x154,
52035
+ 0xe54, 0xf54, 0xc57, 0xd56, 0xa5a, 0xb52, 0x859, 0x950,
52036
+ 0x7c0, 0x6c1, 0x5c2, 0x4c2, 0x3c6, 0x2ce, 0xc5 , 0xc4 ,
52037
+ 0xfc4, 0xec5, 0xdc6, 0xcc6, 0xbca, 0xac2, 0x8c1, 0x8c0,
52038
+ 0x8c0, 0x8c0, 0xac2, 0xbc2, 0xcc6, 0xcc6, 0xec4, 0xfcc,
52039
+ 0xc4 , 0xc5 , 0x2c6, 0x3c6, 0x4c2, 0x5c2, 0x6c1, 0x7c0,
52040
+ 0x950, 0x859, 0xb52, 0xa5a, 0xd56, 0xc57, 0xe54, 0xe5c,
52041
+ 0x154, 0x54 , 0x25e, 0x256, 0x552, 0x453, 0x658, 0x650,
52042
+ 0xaf0, 0xaf0, 0x8f3, 0x8fa, 0xef6, 0xef6, 0xcf4, 0xcfc,
52043
+ 0x2f4, 0x3f5, 0xff , 0x1f6, 0x6f2, 0x6f3, 0x4f9, 0x5f0,
52044
+ 0xa60, 0xa69, 0x863, 0x86a, 0xe66, 0xe67, 0xd65, 0xc6c,
52045
+ 0x364, 0x265, 0x166, 0x66 , 0x76a, 0x663, 0x460, 0x460,
52046
+ 0xca0, 0xca0, 0xea2, 0xfa2, 0x8a6, 0x8a6, 0xaa4, 0xba4,
52047
+ 0x4ac, 0x5a4, 0x6ae, 0x7a6, 0xaa , 0xa3 , 0x2a8, 0x2a0,
52048
+ 0xd30, 0xc31, 0xf32, 0xe3a, 0x936, 0x837, 0xb35, 0xa34,
52049
+ 0x43c, 0x434, 0x73e, 0x636, 0x13a, 0x33 , 0x339, 0x230,
52050
+ 0xe90, 0xe90, 0xc92, 0xc9a, 0xa96, 0xa96, 0x894, 0x89c,
52051
+ 0x694, 0x695, 0x49f, 0x496, 0x292, 0x392, 0x98 , 0x90 ,
52052
+ 0xf00, 0xe08, 0xd03, 0xc0a, 0xa06, 0xa0e, 0x805, 0x804,
52053
+ 0x704, 0x604, 0x506, 0x406, 0x302, 0x202, 0x0 , 0x0]);
52054
+
52055
+ const segTable = [
52056
+ [],
52057
+ [],
52058
+ [1, 9],
52059
+ [1, 8, 1, 9],
52060
+ [2, 10, 10, 1],
52061
+ [2, 10, 10, 1],
52062
+ [9, 2, 2, 10, 10, 9],
52063
+ [2, 8, 2, 10, 10, 8, 10, 9],
52064
+ [11, 2],
52065
+ [0, 11, 11, 2],
52066
+ [1, 9, 11, 2],
52067
+ [1, 11, 11, 2, 1, 9, 9, 11],
52068
+ [3, 10, 10, 1, 11, 10],
52069
+ [0, 10, 10, 1, 8, 10, 11, 10],
52070
+ [3, 9, 11, 9, 11, 10, 10, 9],
52071
+ [8, 10, 10, 9, 11, 10],
52072
+ [4, 7],
52073
+ [4, 3, 4, 7],
52074
+ [1, 9, 4, 7],
52075
+ [4, 1, 1, 9, 4, 7, 7, 1],
52076
+ [2, 10, 10, 1, 4, 7],
52077
+ [3, 4, 4, 7, 2, 10, 10, 1],
52078
+ [9, 2, 2, 10, 10, 9, 4, 7],
52079
+ [2, 10, 10, 9, 9, 2, 9, 7, 7, 2, 4, 7],
52080
+ [4, 7, 11, 2],
52081
+ [11, 4, 4, 7, 11, 2, 2, 4],
52082
+ [1, 9, 4, 7, 11, 2],
52083
+ [4, 7, 11, 4, 11, 9, 11, 2, 2, 9, 1, 9],
52084
+ [3, 10, 10, 1, 11, 10, 4, 7],
52085
+ [1, 11, 11, 10, 10, 1, 1, 4, 4, 11, 4, 7],
52086
+ [4, 7, 0, 11, 11, 9, 11, 10, 10, 9],
52087
+ [4, 7, 11, 4, 11, 9, 11, 10, 10, 9],
52088
+ [9, 5, 5, 4],
52089
+ [9, 5, 5, 4],
52090
+ [0, 5, 5, 4, 1, 5],
52091
+ [8, 5, 5, 4, 3, 5, 1, 5],
52092
+ [2, 10, 10, 1, 9, 5, 5, 4],
52093
+ [2, 10, 10, 1, 9, 5, 5, 4],
52094
+ [5, 2, 2, 10, 10, 5, 5, 4, 4, 2],
52095
+ [2, 10, 10, 5, 5, 2, 5, 3, 5, 4, 4, 3],
52096
+ [9, 5, 5, 4, 11, 2],
52097
+ [0, 11, 11, 2, 9, 5, 5, 4],
52098
+ [0, 5, 5, 4, 1, 5, 11, 2],
52099
+ [1, 5, 5, 2, 5, 8, 8, 2, 11, 2, 5, 4],
52100
+ [10, 3, 11, 10, 10, 1, 9, 5, 5, 4],
52101
+ [9, 5, 5, 4, 8, 1, 8, 10, 10, 1, 11, 10],
52102
+ [5, 4, 0, 5, 0, 11, 11, 5, 11, 10, 10, 5],
52103
+ [5, 4, 8, 5, 8, 10, 10, 5, 11, 10],
52104
+ [9, 7, 5, 7, 9, 5],
52105
+ [9, 3, 9, 5, 5, 3, 5, 7],
52106
+ [0, 7, 1, 7, 1, 5, 5, 7],
52107
+ [1, 5, 5, 3, 5, 7],
52108
+ [9, 7, 9, 5, 5, 7, 10, 1, 2, 10],
52109
+ [10, 1, 2, 10, 9, 5, 5, 0, 5, 3, 5, 7],
52110
+ [2, 8, 2, 5, 5, 8, 5, 7, 10, 5, 2, 10],
52111
+ [2, 10, 10, 5, 5, 2, 5, 3, 5, 7],
52112
+ [7, 9, 9, 5, 5, 7, 11, 2],
52113
+ [9, 5, 5, 7, 7, 9, 7, 2, 2, 9, 11, 2],
52114
+ [11, 2, 1, 8, 1, 7, 1, 5, 5, 7],
52115
+ [11, 2, 1, 11, 1, 7, 1, 5, 5, 7],
52116
+ [9, 5, 5, 8, 5, 7, 10, 1, 3, 10, 11, 10],
52117
+ [5, 7, 7, 0, 0, 5, 9, 5, 11, 0, 0, 10, 10, 1, 11, 10],
52118
+ [11, 10, 10, 0, 0, 11, 10, 5, 5, 0, 0, 7, 5, 7],
52119
+ [11, 10, 10, 5, 5, 11, 5, 7],
52120
+ [10, 6, 6, 5, 5, 10],
52121
+ [5, 10, 10, 6, 6, 5],
52122
+ [1, 9, 5, 10, 10, 6, 6, 5],
52123
+ [1, 8, 1, 9, 5, 10, 10, 6, 6, 5],
52124
+ [1, 6, 6, 5, 5, 1, 2, 6],
52125
+ [1, 6, 6, 5, 5, 1, 2, 6],
52126
+ [9, 6, 6, 5, 5, 9, 0, 6, 2, 6],
52127
+ [5, 9, 8, 5, 8, 2, 2, 5, 2, 6, 6, 5],
52128
+ [11, 2, 10, 6, 6, 5, 5, 10],
52129
+ [11, 0, 11, 2, 10, 6, 6, 5, 5, 10],
52130
+ [1, 9, 11, 2, 5, 10, 10, 6, 6, 5],
52131
+ [5, 10, 10, 6, 6, 5, 1, 9, 9, 2, 9, 11, 11, 2],
52132
+ [6, 3, 11, 6, 6, 5, 5, 3, 5, 1],
52133
+ [11, 0, 11, 5, 5, 0, 5, 1, 11, 6, 6, 5],
52134
+ [11, 6, 6, 3, 6, 0, 6, 5, 5, 0, 5, 9],
52135
+ [6, 5, 5, 9, 9, 6, 9, 11, 11, 6],
52136
+ [5, 10, 10, 6, 6, 5, 4, 7],
52137
+ [4, 3, 4, 7, 6, 5, 5, 10, 10, 6],
52138
+ [1, 9, 5, 10, 10, 6, 6, 5, 4, 7],
52139
+ [10, 6, 6, 5, 5, 10, 1, 9, 9, 7, 7, 1, 4, 7],
52140
+ [6, 1, 2, 6, 6, 5, 5, 1, 4, 7],
52141
+ [2, 5, 5, 1, 2, 6, 6, 5, 4, 3, 4, 7],
52142
+ [4, 7, 0, 5, 5, 9, 0, 6, 6, 5, 2, 6],
52143
+ [3, 9, 9, 7, 4, 7, 2, 9, 5, 9, 9, 6, 6, 5, 2, 6],
52144
+ [11, 2, 4, 7, 10, 6, 6, 5, 5, 10],
52145
+ [5, 10, 10, 6, 6, 5, 4, 7, 7, 2, 2, 4, 11, 2],
52146
+ [1, 9, 4, 7, 11, 2, 5, 10, 10, 6, 6, 5],
52147
+ [9, 2, 1, 9, 9, 11, 11, 2, 4, 11, 4, 7, 5, 10, 10, 6, 6, 5],
52148
+ [4, 7, 11, 5, 5, 3, 5, 1, 11, 6, 6, 5],
52149
+ [5, 1, 1, 11, 11, 5, 11, 6, 6, 5, 0, 11, 11, 4, 4, 7],
52150
+ [0, 5, 5, 9, 0, 6, 6, 5, 3, 6, 11, 6, 4, 7],
52151
+ [6, 5, 5, 9, 9, 6, 9, 11, 11, 6, 4, 7, 7, 9],
52152
+ [10, 4, 9, 10, 6, 4, 10, 6],
52153
+ [4, 10, 10, 6, 6, 4, 9, 10],
52154
+ [10, 0, 1, 10, 10, 6, 6, 0, 6, 4],
52155
+ [1, 8, 1, 6, 6, 8, 6, 4, 1, 10, 10, 6],
52156
+ [1, 4, 9, 1, 2, 4, 2, 6, 6, 4],
52157
+ [2, 9, 9, 1, 2, 4, 2, 6, 6, 4],
52158
+ [2, 4, 2, 6, 6, 4],
52159
+ [2, 8, 2, 4, 2, 6, 6, 4],
52160
+ [10, 4, 9, 10, 10, 6, 6, 4, 11, 2],
52161
+ [8, 2, 11, 2, 9, 10, 10, 4, 10, 6, 6, 4],
52162
+ [11, 2, 1, 6, 6, 0, 6, 4, 1, 10, 10, 6],
52163
+ [6, 4, 4, 1, 1, 6, 1, 10, 10, 6, 8, 1, 1, 11, 11, 2],
52164
+ [9, 6, 6, 4, 9, 3, 3, 6, 9, 1, 11, 6],
52165
+ [11, 1, 1, 8, 11, 6, 6, 1, 9, 1, 1, 4, 6, 4],
52166
+ [11, 6, 6, 3, 6, 0, 6, 4],
52167
+ [6, 4, 8, 6, 11, 6],
52168
+ [7, 10, 10, 6, 6, 7, 8, 10, 9, 10],
52169
+ [0, 7, 0, 10, 10, 7, 9, 10, 6, 7, 10, 6],
52170
+ [10, 6, 6, 7, 7, 10, 1, 10, 7, 1, 8, 1],
52171
+ [10, 6, 6, 7, 7, 10, 7, 1, 1, 10],
52172
+ [2, 6, 6, 1, 6, 8, 8, 1, 9, 1, 6, 7],
52173
+ [2, 6, 6, 9, 9, 2, 9, 1, 6, 7, 7, 9, 9, 3],
52174
+ [0, 7, 0, 6, 6, 7, 2, 6],
52175
+ [2, 7, 6, 7, 2, 6],
52176
+ [11, 2, 10, 6, 6, 8, 8, 10, 9, 10, 6, 7],
52177
+ [0, 7, 7, 2, 11, 2, 9, 7, 6, 7, 7, 10, 10, 6, 9, 10],
52178
+ [1, 8, 1, 7, 1, 10, 10, 7, 6, 7, 10, 6, 11, 2],
52179
+ [11, 2, 1, 11, 1, 7, 10, 6, 6, 1, 1, 10, 6, 7],
52180
+ [9, 6, 6, 8, 6, 7, 9, 1, 1, 6, 11, 6, 6, 3],
52181
+ [9, 1, 11, 6, 6, 7],
52182
+ [0, 7, 0, 6, 6, 7, 11, 0, 11, 6],
52183
+ [11, 6, 6, 7],
52184
+ [7, 6, 6, 11],
52185
+ [7, 6, 6, 11],
52186
+ [1, 9, 7, 6, 6, 11],
52187
+ [8, 1, 1, 9, 7, 6, 6, 11],
52188
+ [10, 1, 2, 10, 6, 11, 7, 6],
52189
+ [2, 10, 10, 1, 6, 11, 7, 6],
52190
+ [2, 9, 2, 10, 10, 9, 6, 11, 7, 6],
52191
+ [6, 11, 7, 6, 2, 10, 10, 3, 10, 8, 10, 9],
52192
+ [7, 2, 6, 2, 7, 6],
52193
+ [7, 0, 7, 6, 6, 0, 6, 2],
52194
+ [2, 7, 7, 6, 6, 2, 1, 9],
52195
+ [1, 6, 6, 2, 1, 8, 8, 6, 1, 9, 7, 6],
52196
+ [10, 7, 7, 6, 6, 10, 10, 1, 1, 7],
52197
+ [10, 7, 7, 6, 6, 10, 1, 7, 10, 1, 1, 8],
52198
+ [7, 0, 7, 10, 10, 0, 10, 9, 6, 10, 7, 6],
52199
+ [7, 6, 6, 10, 10, 7, 10, 8, 10, 9],
52200
+ [6, 8, 4, 6, 6, 11],
52201
+ [3, 6, 6, 11, 0, 6, 4, 6],
52202
+ [8, 6, 6, 11, 4, 6, 1, 9],
52203
+ [4, 6, 6, 9, 6, 3, 3, 9, 1, 9, 6, 11],
52204
+ [6, 8, 4, 6, 6, 11, 2, 10, 10, 1],
52205
+ [2, 10, 10, 1, 0, 11, 0, 6, 6, 11, 4, 6],
52206
+ [4, 11, 4, 6, 6, 11, 2, 9, 2, 10, 10, 9],
52207
+ [10, 9, 9, 3, 3, 10, 2, 10, 4, 3, 3, 6, 6, 11, 4, 6],
52208
+ [8, 2, 4, 2, 4, 6, 6, 2],
52209
+ [4, 2, 4, 6, 6, 2],
52210
+ [1, 9, 3, 4, 4, 2, 4, 6, 6, 2],
52211
+ [1, 9, 4, 1, 4, 2, 4, 6, 6, 2],
52212
+ [8, 1, 8, 6, 6, 1, 4, 6, 6, 10, 10, 1],
52213
+ [10, 1, 0, 10, 0, 6, 6, 10, 4, 6],
52214
+ [4, 6, 6, 3, 3, 4, 6, 10, 10, 3, 3, 9, 10, 9],
52215
+ [10, 9, 4, 10, 6, 10, 4, 6],
52216
+ [9, 5, 5, 4, 7, 6, 6, 11],
52217
+ [9, 5, 5, 4, 7, 6, 6, 11],
52218
+ [5, 0, 1, 5, 5, 4, 7, 6, 6, 11],
52219
+ [7, 6, 6, 11, 3, 4, 3, 5, 5, 4, 1, 5],
52220
+ [9, 5, 5, 4, 10, 1, 2, 10, 7, 6, 6, 11],
52221
+ [6, 11, 7, 6, 2, 10, 10, 1, 9, 5, 5, 4],
52222
+ [7, 6, 6, 11, 5, 4, 4, 10, 10, 5, 4, 2, 2, 10],
52223
+ [3, 4, 3, 5, 5, 4, 2, 5, 10, 5, 2, 10, 7, 6, 6, 11],
52224
+ [7, 2, 7, 6, 6, 2, 5, 4, 9, 5],
52225
+ [9, 5, 5, 4, 8, 6, 6, 0, 6, 2, 7, 6],
52226
+ [3, 6, 6, 2, 7, 6, 1, 5, 5, 0, 5, 4],
52227
+ [6, 2, 2, 8, 8, 6, 7, 6, 1, 8, 8, 5, 5, 4, 1, 5],
52228
+ [9, 5, 5, 4, 10, 1, 1, 6, 6, 10, 1, 7, 7, 6],
52229
+ [1, 6, 6, 10, 10, 1, 1, 7, 7, 6, 0, 7, 9, 5, 5, 4],
52230
+ [0, 10, 10, 4, 10, 5, 5, 4, 3, 10, 6, 10, 10, 7, 7, 6],
52231
+ [7, 6, 6, 10, 10, 7, 10, 8, 5, 4, 4, 10, 10, 5],
52232
+ [6, 9, 9, 5, 5, 6, 6, 11, 11, 9],
52233
+ [3, 6, 6, 11, 0, 6, 0, 5, 5, 6, 9, 5],
52234
+ [0, 11, 0, 5, 5, 11, 1, 5, 5, 6, 6, 11],
52235
+ [6, 11, 3, 6, 3, 5, 5, 6, 1, 5],
52236
+ [2, 10, 10, 1, 9, 5, 5, 11, 11, 9, 5, 6, 6, 11],
52237
+ [0, 11, 0, 6, 6, 11, 9, 6, 5, 6, 9, 5, 2, 10, 10, 1],
52238
+ [8, 5, 5, 11, 5, 6, 6, 11, 0, 5, 10, 5, 5, 2, 2, 10],
52239
+ [6, 11, 3, 6, 3, 5, 5, 6, 2, 10, 10, 3, 10, 5],
52240
+ [5, 8, 9, 5, 5, 2, 2, 8, 5, 6, 6, 2],
52241
+ [9, 5, 5, 6, 6, 9, 6, 0, 6, 2],
52242
+ [1, 5, 5, 8, 8, 1, 5, 6, 6, 8, 8, 2, 6, 2],
52243
+ [1, 5, 5, 6, 6, 1, 6, 2],
52244
+ [3, 6, 6, 1, 6, 10, 10, 1, 8, 6, 5, 6, 6, 9, 9, 5],
52245
+ [10, 1, 0, 10, 0, 6, 6, 10, 9, 5, 5, 0, 5, 6],
52246
+ [5, 6, 6, 10, 10, 5],
52247
+ [10, 5, 5, 6, 6, 10],
52248
+ [11, 5, 5, 10, 10, 11, 7, 5],
52249
+ [11, 5, 5, 10, 10, 11, 7, 5],
52250
+ [5, 11, 7, 5, 5, 10, 10, 11, 1, 9],
52251
+ [10, 7, 7, 5, 5, 10, 10, 11, 8, 1, 1, 9],
52252
+ [11, 1, 2, 11, 7, 1, 7, 5, 5, 1],
52253
+ [2, 7, 7, 1, 7, 5, 5, 1, 2, 11],
52254
+ [9, 7, 7, 5, 5, 9, 9, 2, 2, 7, 2, 11],
52255
+ [7, 5, 5, 2, 2, 7, 2, 11, 5, 9, 9, 2, 2, 8],
52256
+ [2, 5, 5, 10, 10, 2, 3, 5, 7, 5],
52257
+ [8, 2, 8, 5, 5, 2, 7, 5, 10, 2, 5, 10],
52258
+ [1, 9, 5, 10, 10, 3, 3, 5, 7, 5, 10, 2],
52259
+ [8, 2, 2, 9, 1, 9, 7, 2, 10, 2, 2, 5, 5, 10, 7, 5],
52260
+ [3, 5, 5, 1, 7, 5],
52261
+ [7, 0, 7, 1, 7, 5, 5, 1],
52262
+ [3, 9, 3, 5, 5, 9, 7, 5],
52263
+ [7, 9, 5, 9, 7, 5],
52264
+ [5, 8, 4, 5, 5, 10, 10, 8, 10, 11],
52265
+ [5, 0, 4, 5, 5, 11, 11, 0, 5, 10, 10, 11],
52266
+ [1, 9, 4, 10, 10, 8, 10, 11, 4, 5, 5, 10],
52267
+ [10, 11, 11, 4, 4, 10, 4, 5, 5, 10, 3, 4, 4, 1, 1, 9],
52268
+ [2, 5, 5, 1, 2, 8, 8, 5, 2, 11, 4, 5],
52269
+ [4, 11, 11, 0, 4, 5, 5, 11, 2, 11, 11, 1, 5, 1],
52270
+ [2, 5, 5, 0, 5, 9, 2, 11, 11, 5, 4, 5, 5, 8],
52271
+ [4, 5, 5, 9, 2, 11],
52272
+ [2, 5, 5, 10, 10, 2, 3, 5, 3, 4, 4, 5],
52273
+ [5, 10, 10, 2, 2, 5, 2, 4, 4, 5],
52274
+ [3, 10, 10, 2, 3, 5, 5, 10, 8, 5, 4, 5, 1, 9],
52275
+ [5, 10, 10, 2, 2, 5, 2, 4, 4, 5, 1, 9, 9, 2],
52276
+ [4, 5, 5, 8, 5, 3, 5, 1],
52277
+ [4, 5, 5, 0, 5, 1],
52278
+ [4, 5, 5, 8, 5, 3, 0, 5, 5, 9],
52279
+ [4, 5, 5, 9],
52280
+ [4, 11, 7, 4, 9, 11, 9, 10, 10, 11],
52281
+ [9, 7, 7, 4, 9, 11, 9, 10, 10, 11],
52282
+ [1, 10, 10, 11, 11, 1, 11, 4, 4, 1, 7, 4],
52283
+ [1, 4, 4, 3, 1, 10, 10, 4, 7, 4, 4, 11, 10, 11],
52284
+ [4, 11, 7, 4, 9, 11, 9, 2, 2, 11, 9, 1],
52285
+ [9, 7, 7, 4, 9, 11, 9, 1, 1, 11, 2, 11],
52286
+ [7, 4, 4, 11, 4, 2, 2, 11],
52287
+ [7, 4, 4, 11, 4, 2, 2, 11, 3, 4],
52288
+ [2, 9, 9, 10, 10, 2, 2, 7, 7, 9, 7, 4],
52289
+ [9, 10, 10, 7, 7, 9, 7, 4, 10, 2, 2, 7, 7, 0],
52290
+ [7, 10, 10, 3, 10, 2, 7, 4, 4, 10, 1, 10, 10, 0],
52291
+ [1, 10, 10, 2, 7, 4],
52292
+ [9, 1, 1, 4, 1, 7, 7, 4],
52293
+ [9, 1, 1, 4, 1, 7, 7, 4, 8, 1],
52294
+ [3, 4, 7, 4],
52295
+ [7, 4],
52296
+ [9, 10, 10, 8, 10, 11],
52297
+ [9, 3, 9, 11, 9, 10, 10, 11],
52298
+ [1, 10, 10, 0, 10, 8, 10, 11],
52299
+ [1, 10, 10, 3, 10, 11],
52300
+ [2, 11, 11, 1, 11, 9, 9, 1],
52301
+ [9, 3, 9, 11, 2, 9, 9, 1, 2, 11],
52302
+ [2, 11, 11, 0],
52303
+ [2, 11],
52304
+ [8, 2, 8, 10, 10, 2, 9, 10],
52305
+ [9, 10, 10, 2, 2, 9],
52306
+ [8, 2, 8, 10, 10, 2, 1, 8, 1, 10],
52307
+ [1, 10, 10, 2],
52308
+ [8, 1, 9, 1],
52309
+ [9, 1],
52310
+ [],
52311
+ []];
52312
+
52313
+ const snap = (method === 'snapped MC');
52314
+ // const seg_table = (method === 'squarish' ? segTable2 : segTable);
52315
+ const seg_table = segTable;
52316
+
52317
+ let vlist = new Array(12);
52318
+ const vert_offsets = this.calculateVertOffsets(dims);
52319
+
52320
+ const edgeIndex = [[0,1], [1,2], [2,3], [3,0], [4,5], [5,6],
52321
+ [6,7], [7,4], [0,4], [1,5], [2,6], [3,7]];
52322
+
52323
+ let vertex_values = new Float32Array(8);
52324
+ let p0 = [0, 0, 0]; // unused initial value - to make Flow happy
52325
+ let vertex_points = [p0, p0, p0, p0, p0, p0, p0, p0];
52326
+ const size_x = dims[0];
52327
+ const size_y = dims[1];
52328
+ const size_z = dims[2];
52329
+ if (values == null || points == null) return;
52330
+ let vertices = [];
52331
+ let segments = [];
52332
+ let vertex_count = 0;
52333
+ for (let x = 0; x < size_x - 1; x++) {
52334
+ for (let y = 0; y < size_y - 1; y++) {
52335
+ for (let z = 0; z < size_z - 1; z++) {
52336
+ const offset0 = z + size_z * (y + size_y * x);
52337
+ let cubeindex = 0;
52338
+ let i;
52339
+ let j;
52340
+ for (i = 0; i < 8; ++i) {
52341
+ j = offset0 + vert_offsets[i];
52342
+ cubeindex |= (values[j] < isolevel) ? 1 << i : 0;
52343
+ }
52344
+ if (cubeindex === 0 || cubeindex === 255) continue;
52345
+ for (i = 0; i < 8; ++i) {
52346
+ j = offset0 + vert_offsets[i];
52347
+ vertex_values[i] = values[j];
52348
+ vertex_points[i] = points[j];
52349
+ }
52350
+
52351
+ // 12 bit number, indicates which edges are crossed by the isosurface
52352
+ const edge_mask = edgeTable[cubeindex];
52353
+
52354
+ // check which edges are crossed, and estimate the point location
52355
+ // using a weighted average of scalar values at edge endpoints.
52356
+ for (i = 0; i < 12; ++i) {
52357
+ if ((edge_mask & (1 << i)) !== 0) {
52358
+ const e = edgeIndex[i];
52359
+ let mu = (isolevel - vertex_values[e[0]]) /
52360
+ (vertex_values[e[1]] - vertex_values[e[0]]);
52361
+ if (snap === true) {
52362
+ if (mu > 0.85) mu = 1;
52363
+ else if (mu < 0.15) mu = 0;
52364
+ }
52365
+ const p1 = vertex_points[e[0]];
52366
+ const p2 = vertex_points[e[1]];
52367
+ // The number of added vertices could be roughly halved
52368
+ // if we avoided duplicates between neighbouring cells.
52369
+ // Using a map for lookups is too slow, perhaps a big
52370
+ // array would do?
52371
+ vertices.push(p1[0] + (p2[0] - p1[0]) * mu,
52372
+ p1[1] + (p2[1] - p1[1]) * mu,
52373
+ p1[2] + (p2[2] - p1[2]) * mu);
52374
+ vlist[i] = vertex_count++;
52375
+ }
52376
+ }
52377
+ const t = seg_table[cubeindex];
52378
+ for (i = 0; i < t.length; i++) {
52379
+ segments.push(vlist[t[i]]);
52380
+ }
52381
+ }
52382
+ }
52383
+ }
52384
+
52385
+ return { vertices: vertices, segments: segments };
52386
+ }
52387
+
52388
+ // return offsets relative to vertex [0,0,0]
52389
+ calculateVertOffsets(dims) { let ic = this.icn3d; ic.icn3dui;
52390
+ let vert_offsets = [];
52391
+ const cubeVerts = [[0,0,0], [1,0,0], [1,1,0], [0,1,0],
52392
+ [0,0,1], [1,0,1], [1,1,1], [0,1,1]];
52393
+
52394
+ for (let i = 0; i < 8; ++i) {
52395
+ const v = cubeVerts[i];
52396
+ vert_offsets.push(v[0] + dims[2] * (v[1] + dims[1] * v[2]));
52397
+ }
52398
+ return vert_offsets;
52399
+ }
52400
+
52401
+ makeChickenWire(data, typeDetail) { let ic = this.icn3d, me = ic.icn3dui;
52402
+ let geom = new THREE.BufferGeometry();
52403
+ let position = new Float32Array(data.vertices);
52404
+ geom.setAttribute('position', new THREE.BufferAttribute(position, 3));
52405
+
52406
+ // Although almost all browsers support OES_element_index_uint nowadays,
52407
+ // use Uint32 indexes only when needed.
52408
+ let arr = (data.vertices.length < 3*65536 ? new Uint16Array(data.segments) : new Uint32Array(data.segments));
52409
+
52410
+ geom.setIndex(new THREE.BufferAttribute(arr, 1));
52411
+
52412
+ let colorFor2fofc = me.parasCls.thr('#00FFFF');
52413
+ let colorForfofcPos = me.parasCls.thr('#00FF00');
52414
+ let colorForfofcNeg = me.parasCls.thr('#ff0000');
52415
+
52416
+ let color = (typeDetail == '2fofc') ? colorFor2fofc : ((typeDetail == 'fofc_pos') ? colorForfofcPos : colorForfofcNeg);
52417
+ let material = new THREE.LineBasicMaterial({ linewidth: 1, color: color });
52418
+ //return new THREE.LineSegments(geom, material);
52419
+
52420
+ let mesh = new THREE.LineSegments(geom, material);
52421
+ ic.mdl.add(mesh);
52422
+
52423
+ ic.prevMaps.push(mesh);
52424
+ }
52425
+ }
52426
+
52427
+
52428
+ class UnitCell {
52429
+ /*::
52430
+ parameters: number[]
52431
+ orth: number[]
52432
+ frac: number[]
52433
+ */
52434
+ // eslint-disable-next-line max-params
52435
+ constructor(a /*:number*/, b /*:number*/, c /*:number*/,
52436
+ alpha /*:number*/, beta /*:number*/, gamma /*:number*/) {
52437
+ if (a <= 0 || b <= 0 || c <= 0 || alpha <= 0 || beta <= 0 || gamma <= 0) {
52438
+ throw Error('Zero or negative unit cell parameter(s).');
52439
+ }
52440
+ this.parameters = [a, b, c, alpha, beta, gamma];
52441
+ const deg2rad = Math.PI / 180.0;
52442
+ const cos_alpha = Math.cos(deg2rad * alpha);
52443
+ const cos_beta = Math.cos(deg2rad * beta);
52444
+ const cos_gamma = Math.cos(deg2rad * gamma);
52445
+ const sin_alpha = Math.sin(deg2rad * alpha);
52446
+ const sin_beta = Math.sin(deg2rad * beta);
52447
+ const sin_gamma = Math.sin(deg2rad * gamma);
52448
+ if (sin_alpha === 0 || sin_beta === 0 || sin_gamma === 0) {
52449
+ throw Error('Impossible angle - N*180deg.');
52450
+ }
52451
+ const cos_alpha_star_sin_beta = (cos_beta * cos_gamma - cos_alpha) /
52452
+ sin_gamma;
52453
+ const cos_alpha_star = cos_alpha_star_sin_beta / sin_beta;
52454
+ const s1rca2 = Math.sqrt(1.0 - cos_alpha_star * cos_alpha_star);
52455
+ // The orthogonalization matrix we use is described in ITfC B p.262:
52456
+ // "An alternative mode of orthogonalization, used by the Protein
52457
+ // Data Bank and most programs, is to align the a1 axis of the unit
52458
+ // cell with the Cartesian X_1 axis, and to align the a*_3 axis with the
52459
+ // Cartesian X_3 axis."
52460
+ //
52461
+ // Zeros in the matrices below are kept to make matrix multiplication
52462
+ // faster: they make extract_block() 2x (!) faster on V8 4.5.103,
52463
+ // no difference on FF 50.
52464
+ /* eslint-disable no-multi-spaces, comma-spacing */
52465
+ this.orth = [a, b * cos_gamma, c * cos_beta,
52466
+ 0.0, b * sin_gamma, -c * cos_alpha_star_sin_beta,
52467
+ 0.0, 0.0 , c * sin_beta * s1rca2];
52468
+ // based on xtal.js which is based on cctbx.uctbx
52469
+ this.frac = [
52470
+ 1.0 / a,
52471
+ -cos_gamma / (sin_gamma * a),
52472
+ -(cos_gamma * cos_alpha_star_sin_beta + cos_beta * sin_gamma) /
52473
+ (sin_beta * s1rca2 * sin_gamma * a),
52474
+ 0.0,
52475
+ 1.0 / (sin_gamma * b),
52476
+ cos_alpha_star / (s1rca2 * sin_gamma * b),
52477
+ 0.0,
52478
+ 0.0,
52479
+ 1.0 / (sin_beta * s1rca2 * c),
52480
+ ];
52481
+ }
52482
+
52483
+ // This function is only used with matrices frac and orth, which have 3 zeros.
52484
+ // We skip these elements, but it doesn't affect performance (on FF50 and V8).
52485
+ multiply(xyz, mat) {
52486
+ /* eslint-disable indent */
52487
+ return [mat[0] * xyz[0] + mat[1] * xyz[1] + mat[2] * xyz[2],
52488
+ /*mat[3] * xyz[0]*/+ mat[4] * xyz[1] + mat[5] * xyz[2],
52489
+ /*mat[6] * xyz[0] + mat[7] * xyz[1]*/+ mat[8] * xyz[2]];
52490
+ }
52491
+
52492
+ fractionalize(xyz /*:[number,number,number]*/) {
52493
+ return this.multiply(xyz, this.frac);
52494
+ }
52495
+
52496
+ orthogonalize(xyz /*:[number,number,number]*/) {
52497
+ return this.multiply(xyz, this.orth);
52498
+ }
52499
+ }
52500
+
52501
+
52502
+ class GridArray {
52503
+ /*::
52504
+ dim: number[]
52505
+ values: Float32Array
52506
+ */
52507
+ constructor(dim /*:number[]*/) {
52508
+ this.dim = dim; // dimensions of the grid for the entire unit cell
52509
+ this.values = new Float32Array(dim[0] * dim[1] * dim[2]);
52510
+ }
52511
+
52512
+ modulo(a, b) {
52513
+ const reminder = a % b;
52514
+ return reminder >= 0 ? reminder : reminder + b;
52515
+ }
52516
+
52517
+ grid2index(i/*:number*/, j/*:number*/, k/*:number*/) {
52518
+ i = this.modulo(i, this.dim[0]);
52519
+ j = this.modulo(j, this.dim[1]);
52520
+ k = this.modulo(k, this.dim[2]);
52521
+ return this.dim[2] * (this.dim[1] * i + j) + k;
52522
+ }
52523
+
52524
+ grid2index_unchecked(i/*:number*/, j/*:number*/, k/*:number*/) {
52525
+ return this.dim[2] * (this.dim[1] * i + j) + k;
52526
+ }
52527
+
52528
+ grid2frac(i/*:number*/, j/*:number*/, k/*:number*/) {
52529
+ return [i / this.dim[0], j / this.dim[1], k / this.dim[2]];
52530
+ }
52531
+
52532
+ // return grid coordinates (rounded down) for the given fractional coordinates
52533
+ frac2grid(xyz/*:number[]*/) {
52534
+ // at one point "| 0" here made extract_block() 40% faster on V8 3.14,
52535
+ // but I don't see any effect now
52536
+ return [Math.floor(xyz[0] * this.dim[0]) | 0,
52537
+ Math.floor(xyz[1] * this.dim[1]) | 0,
52538
+ Math.floor(xyz[2] * this.dim[2]) | 0];
52539
+ }
52540
+
52541
+ set_grid_value(i/*:number*/, j/*:number*/, k/*:number*/, value/*:number*/) {
52542
+ const idx = this.grid2index(i, j, k);
52543
+ this.values[idx] = value;
52544
+ }
52545
+
52546
+ get_grid_value(i/*:number*/, j/*:number*/, k/*:number*/) {
52547
+ const idx = this.grid2index(i, j, k);
52548
+ return this.values[idx];
52549
+ }
52550
+ }
52551
+
52552
+ /**
52553
+ * @file Mtz Parser
52554
+ * @author Marcin Wojdyr <wojdyr@gmail.com>
52555
+ * @private
52556
+ * Modified by Jiyao Wang / https://github.com/ncbi/icn3d
52557
+ */
52558
+
52559
+ class MtzParser {
52560
+ constructor(icn3d) {
52561
+ this.icn3d = icn3d;
52562
+ }
52563
+
52564
+ async mtzParserBase(url, type, sigma, location, bInputSigma) { let ic = this.icn3d, me = ic.icn3dui;
52565
+ let thisClass = this;
52566
+
52567
+ //https://stackoverflow.com/questions/33902299/using-jquery-ajax-to-download-a-binary-file
52568
+ // if(type == '2fofc' && ic.bAjax2fofcccp4) {
52569
+ // ic.mapData.sigma2 = sigma;
52570
+ // ic.setOptionCls.setOption('map', type);
52571
+ // }
52572
+ // else if(type == 'fofc' && ic.bAjaxfofcccp4) {
52573
+ // ic.mapData.sigma = sigma;
52574
+ // ic.setOptionCls.setOption('map', type);
52575
+ // }
52576
+ // else {
52577
+ let arrayBuffer = await me.getXMLHttpRqstPromise(url, 'GET', 'arraybuffer', '');
52578
+ sigma = await thisClass.loadMtzFileBase(arrayBuffer, type, sigma, location, bInputSigma, url);
52579
+
52580
+ // if(type == '2fofc') {
52581
+ // ic.bAjax2fofcccp4 = true;
52582
+ // }
52583
+ // else if(type == 'fofc') {
52584
+ // ic.bAjaxfofcccp4 = true;
52585
+ // }
52586
+
52587
+ ic.setOptionCls.setOption('map', type);
52588
+
52589
+ return sigma;
52590
+ // }
52591
+ }
52592
+
52593
+ loadMtzFile(type) {var ic = this.icn3d, me = ic.icn3dui;
52594
+ let thisClass = this;
52595
+
52596
+ let file = $("#" + ic.pre + "dsn6file" + type)[0].files[0];
52597
+ let sigma = $("#" + ic.pre + "dsn6sigma" + type).val();
52598
+ if(!file) {
52599
+ alert("Please select a file before clicking 'Load'");
52600
+ }
52601
+ else {
52602
+ me.utilsCls.checkFileAPI();
52603
+ let reader = new FileReader();
52604
+ reader.onload = async function(e) { let ic = thisClass.icn3d;
52605
+ sigma = await thisClass.loadMtzFileBase(e.target.result, type, sigma, 'file');
52606
+ me.htmlCls.clickMenuCls.setLogCmd('load map file ' + $("#" + ic.pre + "dsn6file" + type).val() + ' with sigma ' + sigma, false);
52607
+ };
52608
+ reader.readAsArrayBuffer(file);
52609
+ }
52610
+ }
52611
+
52612
+ async loadMtzFileBase(data, type, sigma, location, bInputSigma, url) {var ic = this.icn3d, me = ic.icn3dui;
52613
+ if(ic.bMtz === undefined) {
52614
+ let url = "./script/mtz.js";
52615
+ await me.getAjaxPromise(url, 'script');
52616
+
52617
+ ic.bMtz = true;
52618
+ }
52619
+
52620
+ GemmiMtz().then(function(Gemmi) {
52621
+ let mtz = Gemmi.readMtz(data);
52622
+
52623
+ sigma = ic.ccp4ParserCls.load_maps_from_mtz_buffer(mtz, type, sigma, location, bInputSigma);
52624
+
52625
+ // if(type == '2fofc') {
52626
+ // ic.bAjax2fofcCcp4 = true;
52627
+ // }
52628
+ // else if(type == 'fofc') {
52629
+ // ic.bAjaxfofcCcp4 = true;
52630
+ // }
52631
+ ic.setOptionCls.setOption('map', type);
52632
+ if(url) me.htmlCls.clickMenuCls.setLogCmd('set map ' + type + ' sigma ' + sigma + ' file mtz | ' + encodeURIComponent(url), true);
52633
+
52634
+ return sigma;
52635
+ });
52636
+ }
52637
+
52638
+ async loadMtzFileUrl(type) {var ic = this.icn3d; ic.icn3dui;
52639
+ let url = $("#" + ic.pre + "dsn6fileurl" + type).val();
52640
+ let sigma = $("#" + ic.pre + "dsn6sigmaurl" + type).val();
52641
+ if(!url) {
52642
+ alert("Please input the file URL before clicking 'Load'");
52643
+ }
52644
+ else {
52645
+ sigma = await this.mtzParserBase(url, type, sigma, 'url');
52646
+
52647
+ console.log("### sigma " + sigma);
52648
+ //me.htmlCls.clickMenuCls.setLogCmd('set map ' + type + ' sigma ' + sigma + ' file mtz | ' + encodeURIComponent(url), true);
51441
52649
  }
51442
52650
  }
51443
52651
 
@@ -54209,7 +55417,7 @@ class DensityCifParser {
54209
55417
  this.icn3d = icn3d;
54210
55418
  }
54211
55419
 
54212
- async densityCifParser(pdbid, type, sigma, emd) { let ic = this.icn3d, me = ic.icn3dui;
55420
+ async densityCifParser(pdbid, type, sigma, emd, bOutput) { let ic = this.icn3d, me = ic.icn3dui;
54213
55421
  let thisClass = this;
54214
55422
 
54215
55423
  let url;
@@ -54271,6 +55479,9 @@ class DensityCifParser {
54271
55479
  ic.mapData.header2 = header;
54272
55480
 
54273
55481
  ic.mapData.data2 = density.data;
55482
+ for(let i = 0; i < density.data.length; ++i) {
55483
+ density.data[i];
55484
+ }
54274
55485
 
54275
55486
  let origin = density.box.origin;
54276
55487
  let dimensions = density.box.dimensions;
@@ -54305,6 +55516,7 @@ class DensityCifParser {
54305
55516
  origin = density.box.origin;
54306
55517
  dimensions = density.box.dimensions;
54307
55518
  basis = density.spacegroup.basis;
55519
+
54308
55520
  scale = new THREE.Matrix4().makeScale(
54309
55521
  dimensions[0] / (sampleCount[0] ),
54310
55522
  dimensions[1] / (sampleCount[1] ),
@@ -55933,7 +57145,10 @@ class ParserUtils {
55933
57145
 
55934
57146
  if(bAppend) {
55935
57147
  if(ic.bSetChainsAdvancedMenu) ic.definedSetsCls.showSets();
55936
- if(ic.bAnnoShown) await ic.showAnnoCls.showAnnotations();
57148
+ if(ic.bAnnoShown) {
57149
+ await ic.showAnnoCls.showAnnotations();
57150
+ ic.annotationCls.resetAnnoTabAll();
57151
+ }
55937
57152
  }
55938
57153
 
55939
57154
  // Realign by sequence alignment with the residues in "segment", i.e., transmembrane helix
@@ -57263,12 +58478,12 @@ class SetSeqAlign {
57263
58478
 
57264
58479
  if(i > 0) {
57265
58480
  let index1 = alignIndex;
57266
-
58481
+
57267
58482
  for(let j = prevIndex1 + 1, jl = start1; j < jl; ++j) {
57268
- if(posChain1[j]) continue;
58483
+ //if(posChain1[j]) continue;
57269
58484
  posChain1[j] = 1;
57270
58485
 
57271
- if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid1][j] === undefined) break;
58486
+ //if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid1][j] === undefined) break;
57272
58487
 
57273
58488
  //let resi = this.getResiAferAlign(chainid1, bRealign, j + 1);
57274
58489
  let resi = this.getResiAferAlign(chainid1, bRealign, j);
@@ -57279,18 +58494,19 @@ class SetSeqAlign {
57279
58494
 
57280
58495
  color = me.htmlCls.GREY8;
57281
58496
  classname = 'icn3d-nalign';
57282
-
58497
+
57283
58498
  ic.nalignHash1[chainid1 + '_' + resi] = 1;
57284
58499
  this.setSeqPerResi(chainid1, chainid1, chainid2, resi, resn, false, color, undefined, classname, true, false, index1);
57285
58500
  ++index1;
57286
58501
  }
57287
58502
 
57288
58503
  let index2 = alignIndex;
58504
+
57289
58505
  for(let j = prevIndex2 + 1, jl = start2; j < jl; ++j) {
57290
- if(posChain2[j]) continue;
58506
+ //if(posChain2[j]) continue;
57291
58507
  posChain2[j] = 1;
57292
58508
 
57293
- if(ic.chainsSeq[chainid2] === undefined || ic.chainsSeq[chainid2] === undefined) break;
58509
+ //if(ic.chainsSeq[chainid2] === undefined || ic.chainsSeq[chainid2] === undefined) break;
57294
58510
 
57295
58511
  //let resi = this.getResiAferAlign(chainid2, bRealign, j + 1);
57296
58512
  let resi = this.getResiAferAlign(chainid2, bRealign, j);
@@ -57336,7 +58552,7 @@ class SetSeqAlign {
57336
58552
  }
57337
58553
 
57338
58554
  for(let j = 0; j <= end1 - start1; ++j) {
57339
- if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid2] === undefined) break;
58555
+ ///if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid2] === undefined) break;
57340
58556
 
57341
58557
  let resi1, resi2, resn1, resn2;
57342
58558
  /*
@@ -57366,15 +58582,17 @@ class SetSeqAlign {
57366
58582
  if(resn1 == '?' || resn2 == '?') continue;
57367
58583
  }
57368
58584
  else {
57369
- if(ic.chainsSeq[chainid1][j + start1] === undefined || ic.chainsSeq[chainid2][j + start2] === undefined) continue;
58585
+ ///if(ic.chainsSeq[chainid1][j + start1] === undefined || ic.chainsSeq[chainid2][j + start2] === undefined) continue;
57370
58586
 
57371
58587
  // resi1 = ic.chainsSeq[chainid1][j + start1].resi;
57372
58588
  // resi2 = ic.chainsSeq[chainid2][j + start2].resi;
57373
58589
  // resn1 = ic.chainsSeq[chainid1][j + start1].name.toUpperCase();
57374
58590
  // resn2 = ic.chainsSeq[chainid2][j + start2].name.toUpperCase();
57375
58591
 
57376
- resi1 = this.getResiAferAlign(chainid1, bRealign, j + start1 + 1);
57377
- resi2 = this.getResiAferAlign(chainid2, bRealign, j + start2 + 1);
58592
+ // resi1 = this.getResiAferAlign(chainid1, bRealign, j + start1 + 1);
58593
+ // resi2 = this.getResiAferAlign(chainid2, bRealign, j + start2 + 1);
58594
+ resi1 = this.getResiAferAlign(chainid1, bRealign, j + start1);
58595
+ resi2 = this.getResiAferAlign(chainid2, bRealign, j + start2);
57378
58596
  resn1 = this.getResnFromResi(chainid1, resi1).toUpperCase();
57379
58597
  resn2 = this.getResnFromResi(chainid2, resi2).toUpperCase();
57380
58598
  }
@@ -62423,14 +63641,15 @@ class LoadScript {
62423
63641
  let bFinalStep =(i === steps - 1) ? true : false;
62424
63642
 
62425
63643
  if(!ic.commands[i].trim()) continue;
62426
- let nAtoms = Object.keys(ic.atoms).length;
63644
+ let nAtoms = (ic.atoms) ? Object.keys(ic.atoms).length : 0;
62427
63645
 
62428
63646
  if(nAtoms == 0 && ic.commands[i].indexOf('load') == -1) continue;
62429
63647
 
62430
63648
  let strArray = ic.commands[i].split("|||");
62431
63649
  let command = strArray[0].trim();
62432
63650
 
62433
- if(ic.inputid) ic.bNotLoadStructure = true;
63651
+ // sometimes URL has an ID input, then load a structure in commands
63652
+ //if(ic.inputid) ic.bNotLoadStructure = true;
62434
63653
 
62435
63654
  if(command.indexOf('load') !== -1) {
62436
63655
  if(end === 0 && start === end) {
@@ -62466,18 +63685,7 @@ class LoadScript {
62466
63685
  }
62467
63686
  }
62468
63687
  else if(command.indexOf('set map') == 0 && command.indexOf('set map wireframe') == -1) {
62469
- //set map 2fofc sigma 1.5
62470
- let urlArray = strArray[0].trim().split(' | ');
62471
-
62472
- let str = urlArray[0].substr(8);
62473
- let paraArray = str.split(" ");
62474
-
62475
- if(paraArray.length == 3 && paraArray[1] == 'sigma') {
62476
- paraArray[2];
62477
- paraArray[0];
62478
-
62479
- await thisClass.applyCommandMap(strArray[0].trim());
62480
- }
63688
+ await thisClass.applyCommandMap(strArray[0].trim());
62481
63689
  }
62482
63690
  else if(command.indexOf('set emmap') == 0 && command.indexOf('set emmap wireframe') == -1) {
62483
63691
  //set emmap percentage 70
@@ -62977,17 +64185,34 @@ class LoadScript {
62977
64185
  // ic.deferredMap = $.Deferred(function() { let ic = thisClass.icn3d;
62978
64186
  //"set map 2fofc sigma 1.5"
62979
64187
  // or "set map 2fofc sigma 1.5 | [url]"
64188
+
64189
+ // added more para later
64190
+ //"set map 2fofc sigma 1.5 file dsn6"
64191
+ // or "set map 2fofc sigma 1.5 file dsn6 | [url]"
62980
64192
  let urlArray = command.split(" | ");
62981
64193
 
62982
64194
  let str = urlArray[0].substr(8);
62983
64195
  let paraArray = str.split(" ");
62984
64196
 
62985
- if(paraArray.length == 3 && paraArray[1] == 'sigma') {
64197
+ //if(paraArray.length == 3 && paraArray[1] == 'sigma') {
64198
+ if(paraArray[1] == 'sigma') {
62986
64199
  let sigma = paraArray[2];
62987
64200
  let type = paraArray[0];
62988
64201
 
64202
+ let fileType = 'dsn6';
64203
+ if(paraArray.length == 5) fileType = paraArray[4];
64204
+
62989
64205
  if(urlArray.length == 2) {
62990
- await ic.dsn6ParserCls.dsn6ParserBase(urlArray[1], type, sigma);
64206
+ let bInputSigma = true;
64207
+ if(fileType == 'dsn6') {
64208
+ await ic.dsn6ParserCls.dsn6ParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
64209
+ }
64210
+ else if(fileType == 'ccp4') {
64211
+ await ic.ccp4ParserCls.ccp4ParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
64212
+ }
64213
+ else if(fileType == 'mtz') {
64214
+ await ic.mtzParserCls.mtzParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
64215
+ }
62991
64216
  }
62992
64217
  else {
62993
64218
  await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma);
@@ -71931,7 +73156,7 @@ class Ray {
71931
73156
  }
71932
73157
 
71933
73158
  // from iview (http://istar.cse.cuhk.edu.hk/iview/)
71934
- getAtomsFromPosition(point, threshold) { let ic = this.icn3d, me = ic.icn3dui;
73159
+ getAtomsFromPosition(point, threshold, atoms) { let ic = this.icn3d, me = ic.icn3dui;
71935
73160
  let i;
71936
73161
 
71937
73162
  if(threshold === undefined || threshold === null) {
@@ -71939,7 +73164,8 @@ class Ray {
71939
73164
  }
71940
73165
 
71941
73166
  //for (i in ic.atoms) {
71942
- for (i in ic.dAtoms) {
73167
+ let atomHash = (atoms) ? atoms : ic.dAtoms;
73168
+ for (i in atomHash) {
71943
73169
  let atom = ic.atoms[i];
71944
73170
 
71945
73171
  if(ic.ions.hasOwnProperty(i) && ic.opts['ions'] === 'sphere') {
@@ -72332,13 +73558,25 @@ class Picking {
72332
73558
  y += me.htmlCls.MENU_HEIGHT;
72333
73559
  }
72334
73560
  let text =(ic.pk == 1) ? atom.resn + atom.resi + '@' + atom.name : atom.resn + atom.resi;
73561
+ let chainid = atom.structure + '_' + atom.chain;
73562
+ let textWidth;
72335
73563
  if(ic.structures !== undefined && Object.keys(ic.structures).length > 1) {
72336
- text = atom.structure + '_' + atom.chain + ' ' + text;
72337
- $("#" + ic.pre + "popup").css("width", "160px");
73564
+ text = chainid + ' ' + text;
73565
+ textWidth = (ic.chainid2refpdbname && ic.chainid2refpdbname[chainid]) ? 160 + 80 : 160;
73566
+ $("#" + ic.pre + "popup").css("width", textWidth + "px");
72338
73567
  }
72339
73568
  else {
72340
- $("#" + ic.pre + "popup").css("width", "80px");
73569
+ textWidth = (ic.chainid2refpdbname && ic.chainid2refpdbname[chainid]) ? 80 + 80 : 80;
73570
+ $("#" + ic.pre + "popup").css("width", textWidth + "px");
72341
73571
  }
73572
+
73573
+
73574
+ if(ic.chainid2refpdbname && ic.chainid2refpdbname[chainid]) {
73575
+ let refnumLabel = ic.resid2refnum[chainid + '_' + atom.resi];
73576
+
73577
+ if(refnumLabel) text += ', Ig: ' + refnumLabel;
73578
+ }
73579
+
72342
73580
  $("#" + ic.pre + "popup").html(text);
72343
73581
  $("#" + ic.pre + "popup").css("top", y).css("left", x+20).show();
72344
73582
  }
@@ -73499,6 +74737,8 @@ class iCn3D {
73499
74737
  this.alignParserCls = new AlignParser(this);
73500
74738
  this.chainalignParserCls = new ChainalignParser(this);
73501
74739
  this.dsn6ParserCls = new Dsn6Parser(this);
74740
+ this.ccp4ParserCls = new Ccp4Parser(this);
74741
+ this.mtzParserCls = new MtzParser(this);
73502
74742
  this.mmcifParserCls = new MmcifParser(this);
73503
74743
  this.mmdbParserCls = new MmdbParser(this);
73504
74744
  this.mmtfParserCls = new MmtfParser(this);
@@ -73761,7 +75001,7 @@ class iCn3DUI {
73761
75001
  //even when multiple iCn3D viewers are shown together.
73762
75002
  this.pre = this.cfg.divid + "_";
73763
75003
 
73764
- this.REVISION = '3.28.4';
75004
+ this.REVISION = '3.29.0';
73765
75005
 
73766
75006
  // In nodejs, iCn3D defines "window = {navigator: {}}"
73767
75007
  this.bNode = (Object.keys(window).length < 2) ? true : false;