icn3d 3.40.4 → 3.41.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.
package/icn3d.js CHANGED
@@ -8827,9 +8827,9 @@ class ClickMenu {
8827
8827
  }
8828
8828
 
8829
8829
  getHiddenMenusFromCache() { let me = this.icn3dui; me.icn3d;
8830
- // me.htmlCls.shownMenus = {};
8830
+ me.htmlCls.shownMenus = {};
8831
8831
 
8832
- // let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
8832
+ let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
8833
8833
 
8834
8834
  let idArrayStr = (localStorage) ? localStorage.getItem('hiddenmenus') : '';
8835
8835
 
@@ -8838,31 +8838,23 @@ class ClickMenu {
8838
8838
 
8839
8839
  let idArray = JSON.parse(idArrayStr);
8840
8840
 
8841
- // for(let i = 0, il = idArray.length; i < il; ++i) {
8842
- // me.htmlCls.shownMenus[idArray[i]] = 1;
8843
- // }
8844
8841
  for(let menu in me.htmlCls.allMenus) {
8845
8842
  if(idArray.indexOf(menu) == -1) {
8846
8843
  me.htmlCls.shownMenus[menu] = 1;
8847
8844
  }
8848
8845
  }
8849
8846
  }
8850
- //###
8851
8847
  else {
8852
- me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
8848
+ if(mode == 'all') {
8849
+ me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
8850
+ }
8851
+ else if(!mode || mode == 'simple') {
8852
+ me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
8853
+ }
8854
+ else {
8855
+ me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
8856
+ }
8853
8857
  }
8854
-
8855
- // else {
8856
- // if(mode == 'all') {
8857
- // me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
8858
- // }
8859
- // else if(!mode || mode == 'simple') {
8860
- // me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
8861
- // }
8862
- // else {
8863
- // me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
8864
- // }
8865
- // }
8866
8858
  }
8867
8859
 
8868
8860
  displayShownMenus() { let me = this.icn3dui; me.icn3d;
@@ -10822,12 +10814,17 @@ class ClickMenu {
10822
10814
  // var aaa = 1; //alert("The url is more than 4000 characters and may not work.");
10823
10815
  //}
10824
10816
  //else {
10825
- url = url.replace("icn3d/full.html?", "icn3d/full2.html?");
10817
+ // url = url.replace("icn3d/full.html?", "icn3d/full2.html?");
10818
+
10819
+ url = url.replace(/icn3d\/full[_\d\.]*\.html\?/, "icn3d/full2.html?");
10820
+
10826
10821
  url = url.replace("icn3d/?", "icn3d/full2.html?");
10822
+
10827
10823
  url += '&closepopup=1';
10828
10824
  let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
10829
10825
  window.open(url, urlTarget);
10830
- thisClass.setLogCmd('side by side | ' + url, true);
10826
+ // thisClass.setLogCmd('side by side | ' + url, true);
10827
+ thisClass.setLogCmd('side by side | ' + url, false);
10831
10828
  //}
10832
10829
  });
10833
10830
 
@@ -11336,7 +11333,7 @@ class SetMenu {
11336
11333
 
11337
11334
  let tdStr = '<td valign="top">';
11338
11335
 
11339
- // html += tdStr + this.setMenuMode() + '</td>';
11336
+ html += tdStr + this.setMenuMode() + '</td>';
11340
11337
 
11341
11338
  html += tdStr + this.setMenu1() + '</td>';
11342
11339
 
@@ -11347,12 +11344,11 @@ class SetMenu {
11347
11344
  html += tdStr + this.setMenu4() + '</td>';
11348
11345
 
11349
11346
  html += tdStr + this.setMenu5() + '</td>';
11350
- //html += tdStr + this.setMenu5b() + '</td>';
11351
11347
  html += tdStr + this.setMenu6() + '</td>';
11352
11348
 
11353
11349
  // reset the menus at the end of the menus
11354
- // let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
11355
- // this.resetMenu(mode);
11350
+ let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
11351
+ this.resetMenu(mode);
11356
11352
 
11357
11353
  // me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
11358
11354
 
@@ -11460,7 +11456,7 @@ class SetMenu {
11460
11456
  }
11461
11457
  html += "<div>";
11462
11458
 
11463
- // html += '<li>' + this.setMenuMode(true);
11459
+ html += '<li>' + this.setMenuMode(true);
11464
11460
 
11465
11461
  let liStr = "<li><span class='icn3d-menu-color'";
11466
11462
 
@@ -11481,8 +11477,8 @@ class SetMenu {
11481
11477
  html += this.setMenu6_base();
11482
11478
 
11483
11479
  // reset the menus at the end of the menus
11484
- // let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
11485
- // this.resetMenu(mode);
11480
+ let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
11481
+ this.resetMenu(mode);
11486
11482
 
11487
11483
  // me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
11488
11484
 
@@ -11572,7 +11568,7 @@ class SetMenu {
11572
11568
 
11573
11569
  html += me.htmlCls.divStr + "selection' style='display:none;'><div style='position:absolute; z-index:555; float:left; display:table-row; margin: 32px 0px 0px 0px;'>";
11574
11570
  //html += "<table style='margin-top: 3px; width:100px;'>";
11575
- html += "<table style='margin-top: 3px; width:770px; background-color:#EEE;'>";
11571
+ html += "<table style='margin: 3px 0px 0px 76px; width:770px; background-color:#EEE;'>";
11576
11572
 
11577
11573
  html += this.setTools_base();
11578
11574
 
@@ -11888,9 +11884,9 @@ class SetMenu {
11888
11884
  html += "</ul>";
11889
11885
  html += "</li>";
11890
11886
 
11891
- html += this.getMenuText('mn1_aligntwostru', 'Protein Complexes', undefined, undefined, 2);
11887
+ html += this.getMenuText('mn1_aligntwostru', 'Protein Complexes', undefined, 1, 2);
11892
11888
  html += "<ul>";
11893
- html += this.getLink('mn1_align', 'Two PDB Structures ' + me.htmlCls.wifiStr, undefined, 3);
11889
+ html += this.getLink('mn1_align', 'Two PDB Structures ' + me.htmlCls.wifiStr, 1, 3);
11894
11890
  html += this.getLink('mn1_alignaf', 'Two AlphaFold Structures ' + me.htmlCls.wifiStr, undefined, 3);
11895
11891
  html += "</ul>";
11896
11892
 
@@ -11944,8 +11940,8 @@ class SetMenu {
11944
11940
  html += "<ul>";
11945
11941
  html += this.getMenuText('mn1_savepngimage', 'iCn3D PNG Image', undefined, 1, 2);
11946
11942
  html += "<ul>";
11947
- html += this.getLink('mn1_exportCanvas', 'Original Size & HTML', 1, 3);
11948
- html += this.getLink('mn1_exportCanvas1', 'Original Size', undefined, 3);
11943
+ html += this.getLink('mn1_exportCanvas', 'Original Size & HTML', undefined, 3);
11944
+ html += this.getLink('mn1_exportCanvas1', 'Original Size', 1, 3);
11949
11945
 
11950
11946
  html += this.getLink('mn1_exportCanvas2', '2X Large', undefined, 3);
11951
11947
  html += this.getLink('mn1_exportCanvas4', '4X Large', undefined, 3);
@@ -12032,7 +12028,7 @@ class SetMenu {
12032
12028
  html += "<ul class='icn3d-mn-item'>";
12033
12029
 
12034
12030
  html += this.getLink('mn2_definedsets', 'Defined Sets', 1, 1);
12035
- html += this.getLink('mn2_selectall', 'All', undefined, 1);
12031
+ html += this.getLink('mn2_selectall', 'All', 1, 1);
12036
12032
  html += this.getLink('mn2_selectdisplayed', 'Displayed Set', undefined, 1);
12037
12033
  html += this.getLink('mn2_aroundsphere', 'by Distance', 1, 1);
12038
12034
 
@@ -12048,10 +12044,10 @@ class SetMenu {
12048
12044
  html += "</li>";
12049
12045
 
12050
12046
  html += this.getLink('mn2_selectcomplement', 'Inverse', undefined, 1);
12051
- html += this.getLink('mn2_selectmainchains', 'Main Chains', undefined, 1);
12052
- html += this.getLink('mn2_selectsidechains', 'Side Chains', undefined, 1);
12047
+ html += this.getLink('mn2_selectmainchains', 'Main Chains', 1, 1);
12048
+ html += this.getLink('mn2_selectsidechains', 'Side Chains', 1, 1);
12053
12049
  html += this.getLink('mn2_selectmainsidechains', 'Main & Side Chains', undefined, 1);
12054
- html += this.getLink('mn2_command', 'Advanced', undefined, 1);
12050
+ html += this.getLink('mn2_command', 'Advanced', 1, 1);
12055
12051
 
12056
12052
  if(me.cfg.cid === undefined) {
12057
12053
  html += this.getMenuText('mn2_selon3d', 'Select on 3D', undefined, 1, 1);
@@ -12084,7 +12080,7 @@ class SetMenu {
12084
12080
  html += this.getMenuSep();
12085
12081
 
12086
12082
  html += this.getLink('mn2_saveselection', 'Save Selection', 1, 1);
12087
- html += this.getLink('clearall', 'Clear Selection', undefined, 1);
12083
+ html += this.getLink('clearall', 'Clear Selection', 1, 1);
12088
12084
  html += this.getLink('mn2_saveresidue', 'Save Res. in Sel.', 1, 1);
12089
12085
 
12090
12086
  html += this.getMenuSep();
@@ -12149,7 +12145,7 @@ class SetMenu {
12149
12145
  html += this.getLinkWrapper('mn2_alternate', 'Alternate(Key "a")', 'mn2_alternateWrap', undefined, 1);
12150
12146
 
12151
12147
  if(me.cfg.opmid !== undefined) {
12152
- html += this.getLinkWrapper('togglemem', 'Toggle Membrane', 'togglememli', undefined, 1);
12148
+ html += this.getLinkWrapper('togglemem', 'Toggle Membrane', 'togglememli', 1, 1);
12153
12149
  }
12154
12150
  //else if(me.cfg.mmdbafid !== undefined || me.cfg.afid !== undefined) {
12155
12151
  else if(me.cfg.cid === undefined) {
@@ -12164,14 +12160,14 @@ class SetMenu {
12164
12160
 
12165
12161
  html += this.getMenuSep();
12166
12162
 
12167
- html += this.getMenuText('mn2_vrarhints', 'VR & AR Hints', undefined, 1, 1);
12163
+ html += this.getMenuText('mn2_vrarhints', 'VR & AR Hints', undefined, undefined, 1);
12168
12164
  html += "<ul>";
12169
- html += this.getMenuUrl("vrhint", me.htmlCls.baseUrl + "icn3d/icn3d.html#vr", "VR: VR Headsets", 1, 2);
12170
- html += this.getMenuUrl("arhint", me.htmlCls.baseUrl + "icn3d/icn3d.html#ar", "AR: Chrome in Android", 1, 2);
12165
+ html += this.getMenuUrl("vrhint", me.htmlCls.baseUrl + "icn3d/icn3d.html#vr", "VR: VR Headsets", undefined, 2);
12166
+ html += this.getMenuUrl("arhint", me.htmlCls.baseUrl + "icn3d/icn3d.html#ar", "AR: Chrome in Android", undefined, 2);
12171
12167
  html += "</ul>";
12172
12168
  html += "</li>";
12173
12169
 
12174
- html += this.getLink('mn6_sidebyside', 'Side by Side', 1, 1);
12170
+ html += this.getLink('mn6_sidebyside', 'Side by Side', undefined, 1);
12175
12171
 
12176
12172
  html += this.getMenuText('mn2_rotate', 'Rotate', undefined, 1, 1);
12177
12173
  html += "<ul>";
@@ -12283,7 +12279,7 @@ class SetMenu {
12283
12279
  html += this.getRadio('mn3_proteins', 'mn3_proteinsRibbon', 'Ribbon', true, 1, 2);
12284
12280
  }
12285
12281
 
12286
- html += this.getRadio('mn3_proteins', 'mn3_proteinsStrand', 'Strand', undefined, undefined, 2);
12282
+ html += this.getRadio('mn3_proteins', 'mn3_proteinsStrand', 'Strand', undefined, 1, 2);
12287
12283
  html += this.getRadio('mn3_proteins', 'mn3_proteinsCylinder', 'Cylinder and Plate', undefined, undefined, 2);
12288
12284
  html += this.getRadio('mn3_proteins', 'mn3_proteinsSchematic', 'Schematic', undefined, 1, 2);
12289
12285
 
@@ -12295,7 +12291,7 @@ class SetMenu {
12295
12291
  }
12296
12292
 
12297
12293
  html += this.getRadio('mn3_proteins', 'mn3_proteinsBackbone', 'Backbone', undefined, undefined, 2);
12298
- html += this.getRadio('mn3_proteins', 'mn3_proteinsBfactor', 'B-factor Tube', undefined, 1, 2);
12294
+ html += this.getRadio('mn3_proteins', 'mn3_proteinsBfactor', 'B-factor Tube', undefined, undefined, 2);
12299
12295
  html += this.getRadio('mn3_proteins', 'mn3_proteinsLines', 'Lines', undefined, 1, 2);
12300
12296
  html += this.getRadio('mn3_proteins', 'mn3_proteinsStick', 'Stick', undefined, 1, 2);
12301
12297
  html += this.getRadio('mn3_proteins', 'mn3_proteinsBallstick', 'Ball and Stick', undefined, 1, 2);
@@ -12359,10 +12355,10 @@ class SetMenu {
12359
12355
  html += "</li>";
12360
12356
 
12361
12357
  //if(me.cfg.cid !== undefined) {
12362
- html += this.getMenuText('mn3_hydrogenswrap', 'Hydrogens', undefined, 1, 1);
12358
+ html += this.getMenuText('mn3_hydrogenswrap', 'Hydrogens', undefined, undefined, 1);
12363
12359
  html += "<ul>";
12364
- html += this.getRadio('mn3_hydrogens', 'mn3_hydrogensYes', 'Show', true, 1, 2);
12365
- html += this.getRadio('mn3_hydrogens', 'mn3_hydrogensNo', 'Hide', undefined, 1, 2);
12360
+ html += this.getRadio('mn3_hydrogens', 'mn3_hydrogensYes', 'Show', true, undefined, 2);
12361
+ html += this.getRadio('mn3_hydrogens', 'mn3_hydrogensNo', 'Hide', undefined, undefined, 2);
12366
12362
  html += "</ul>";
12367
12363
  html += "</li>";
12368
12364
  //}
@@ -12737,7 +12733,7 @@ class SetMenu {
12737
12733
 
12738
12734
  html += "</ul>";
12739
12735
 
12740
- html += this.getRadio('mn4_clr', 'mn4_clrCustom', 'Color Picker', undefined, undefined, 1);
12736
+ html += this.getRadio('mn4_clr', 'mn4_clrCustom', 'Color Picker', undefined, 1, 1);
12741
12737
  html += this.getMenuSep();
12742
12738
 
12743
12739
  if(me.cfg.cid === undefined) {
@@ -12778,7 +12774,7 @@ class SetMenu {
12778
12774
  html += this.getRadio('mn4_clr', 'mn4_clrBfactorNorm', 'Percentile', undefined, 1, 2);
12779
12775
  html += "</ul>";
12780
12776
 
12781
- html += this.getRadio('mn4_clr', 'mn4_clrArea', 'Solvent<br><span style="padding-left:1.5em;">Accessibility</span>', undefined, undefined, 1);
12777
+ html += this.getRadio('mn4_clr', 'mn4_clrArea', 'Solvent<br><span style="padding-left:1.5em;">Accessibility</span>', undefined, 1, 1);
12782
12778
 
12783
12779
  html += this.getRadio('mn4_clr', 'mn4_clrStructure', 'Structure', undefined, 1, 1);
12784
12780
 
@@ -12790,7 +12786,7 @@ class SetMenu {
12790
12786
  }
12791
12787
 
12792
12788
  //if(me.cfg.mmdbid !== undefined || me.cfg.gi !== undefined) {
12793
- html += this.getRadio('mn4_clr', 'mn4_clrdomain', '3D Domain', undefined, undefined, 1);
12789
+ html += this.getRadio('mn4_clr', 'mn4_clrdomain', '3D Domain', undefined, 1, 1);
12794
12790
  //}
12795
12791
 
12796
12792
  if(me.cfg.cid === undefined) {
@@ -12810,16 +12806,16 @@ class SetMenu {
12810
12806
  html += this.getRadio('mn4_clr', 'mn4_clrAtom', 'Atom', undefined, 1, 1);
12811
12807
 
12812
12808
  if(me.cfg.align !== undefined || me.cfg.chainalign !== undefined) {
12813
- html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', true, undefined, 2);
12814
- html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', undefined, undefined, 2);
12809
+ html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', true, undefined, 1);
12810
+ html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', undefined, undefined, 1);
12815
12811
  }
12816
12812
  else if(me.cfg.blast_rep_id !== undefined) {
12817
- html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', undefined, undefined, 2);
12818
- html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', true, undefined, 2);
12813
+ html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', undefined, undefined, 1);
12814
+ html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', true, undefined, 1);
12819
12815
  }
12820
12816
  else {
12821
- html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', undefined, undefined, 2);
12822
- html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', undefined, undefined, 2);
12817
+ html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', undefined, undefined, 1);
12818
+ html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', undefined, undefined, 1);
12823
12819
  }
12824
12820
 
12825
12821
  //if(me.cfg.afid) html += this.getRadio('mn4_clr', 'mn4_clrConfidence', 'AF Confidence');
@@ -12827,8 +12823,8 @@ class SetMenu {
12827
12823
  html += this.getRadio('mn4_clr', 'mn4_clrConfidence', 'pLDDT', undefined, 1, 1);
12828
12824
  //}
12829
12825
 
12830
- html += this.getRadio('mn4_clr', 'mn4_clrIgstrand', 'Ig Strand', undefined, undefined, 2);
12831
- html += this.getRadio('mn4_clr', 'mn4_clrIgproto', 'Ig Protodomain', undefined, undefined, 2);
12826
+ html += this.getRadio('mn4_clr', 'mn4_clrIgstrand', 'Ig Strand', undefined, undefined, 1);
12827
+ html += this.getRadio('mn4_clr', 'mn4_clrIgproto', 'Ig Protodomain', undefined, undefined, 1);
12832
12828
  }
12833
12829
  else {
12834
12830
  //if(!me.cfg.hidelicense) html += this.getRadio('mn4_clr', 'mn1_delphi2', 'DelPhi<br><span style="padding-left:1.5em;">Potential ' + me.htmlCls.licenseStr + '</span>');
@@ -12881,7 +12877,7 @@ class SetMenu {
12881
12877
  html += this.getLink('mn6_selectannotations', 'Seq. & Annotations ' + me.htmlCls.wifiStr, 1, 1);
12882
12878
 
12883
12879
  //if(me.cfg.align !== undefined || me.cfg.chainalign !== undefined) { // || ic.bRealign || ic.bSymd || ic.bInputfile) {
12884
- html += this.getLink('mn2_alignment', 'Aligned Seq. ' + me.htmlCls.wifiStr, undefined, 1);
12880
+ html += this.getLink('mn2_alignment', 'Aligned Seq. ' + me.htmlCls.wifiStr, 1, 1);
12885
12881
  //}
12886
12882
 
12887
12883
  if(me.cfg.mmdbid !== undefined || me.cfg.gi !== undefined || me.cfg.blast_rep_id !== undefined || me.cfg.align !== undefined || me.cfg.chainalign !== undefined) {
@@ -12951,27 +12947,27 @@ class SetMenu {
12951
12947
  html += "</ul>";
12952
12948
  html += "</li>";
12953
12949
 
12954
- html += this.getMenuText('mn6_anglewrap', 'Angle', undefined, 1, 1);
12950
+ html += this.getMenuText('mn6_anglewrap', 'Angle', undefined, undefined, 1);
12955
12951
  html += "<ul>";
12956
- html += this.getRadio('mn6_angle', 'mn6_angleManySets', 'among Many Sets', undefined, 1, 2);
12952
+ html += this.getRadio('mn6_angle', 'mn6_angleManySets', 'among Many Sets', undefined, undefined, 2);
12957
12953
  html += this.getRadio('mn6_angle', 'mn6_angleTwoSets', 'b/w Two Vectors', undefined, undefined, 2);
12958
12954
  html += "</ul>";
12959
12955
  html += "</li>";
12960
12956
 
12961
- html += this.getLink('mn6_area', 'Surface Area', 1, 1);
12957
+ html += this.getLink('mn6_area', 'Surface Area', undefined, 1);
12962
12958
 
12963
12959
  html += this.getMenuText('mn6_addlabelwrap', 'Label', undefined, 1, 1);
12964
12960
  html += "<ul>";
12965
12961
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelYes', 'by Picking Atoms', undefined, undefined, 2);
12966
12962
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelSelection', 'per Selection', undefined, undefined, 2);
12967
12963
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelAtoms', 'per Atom', undefined, undefined, 2);
12968
- html += this.getRadio('mn6_addlabel', 'mn6_addlabelElements', 'per Atom Element', undefined, 1, 2);
12964
+ html += this.getRadio('mn6_addlabel', 'mn6_addlabelElements', 'per Atom Element', undefined, undefined, 2);
12969
12965
  if(me.cfg.cid === undefined) {
12970
12966
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelResidues', 'per Residue', undefined, 1, 2);
12971
12967
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelResnum', 'per Residue & Number', undefined, 1, 2);
12972
12968
 
12973
- html += this.getRadio('mn6_addlabel', 'mn6_addlabelRefnum', 'per Reference Number', undefined, 1, 2);
12974
- html += this.getRadio('mn6_addlabel', 'mn6_addlabelIg', 'per Ig Domain', undefined, 1, 2);
12969
+ html += this.getRadio('mn6_addlabel', 'mn6_addlabelRefnum', 'per Reference Number', undefined, undefined, 2);
12970
+ html += this.getRadio('mn6_addlabel', 'mn6_addlabelIg', 'per Ig Domain', undefined, undefined, 2);
12975
12971
 
12976
12972
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelChains', 'per Chain', undefined, undefined, 2);
12977
12973
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelTermini', 'N- & C-Termini', undefined, 1, 2);
@@ -13008,10 +13004,10 @@ class SetMenu {
13008
13004
  html += this.getMenuSep();
13009
13005
 
13010
13006
  if(me.cfg.cid === undefined) {
13011
- html += this.getMenuText('mn6_chemicalbindingwrap', 'Chem. Binding', undefined, undefined, 1);
13007
+ html += this.getMenuText('mn6_chemicalbindingwrap', 'Chem. Binding', undefined, 1, 1);
13012
13008
  html += "<ul>";
13013
- html += this.getRadio('mn6_chemicalbinding', 'mn6_chemicalbindingshow', 'Show', undefined, undefined, 2);
13014
- html += this.getRadio('mn6_chemicalbinding', 'mn6_chemicalbindinghide', 'Hide', true, undefined, 2);
13009
+ html += this.getRadio('mn6_chemicalbinding', 'mn6_chemicalbindingshow', 'Show', undefined, 1, 2);
13010
+ html += this.getRadio('mn6_chemicalbinding', 'mn6_chemicalbindinghide', 'Hide', true, 1, 2);
13015
13011
  html += "</ul>";
13016
13012
  html += "</li>";
13017
13013
 
@@ -13170,7 +13166,7 @@ class SetMenu {
13170
13166
 
13171
13167
  //html += liStr + "https://www.ncbi.nlm.nih.gov/structure' target='_blank'>Search Structure " + me.htmlCls.wifiStr + "</a></li>";
13172
13168
  //html += liStr + me.htmlCls.baseUrl + "icn3d/icn3d.html#citing' target='_blank'>Citing iCn3D</a></li>";
13173
- html += this.getMenuUrl('citing', me.htmlCls.baseUrl + "icn3d/icn3d.html#citing", "Citing iCn3D", undefined, 1);
13169
+ html += this.getMenuUrl('citing', me.htmlCls.baseUrl + "icn3d/icn3d.html#citing", "Citing iCn3D", 1, 1);
13174
13170
 
13175
13171
  html += this.getMenuText('mn6_source', 'Source Code', undefined, 1, 1);
13176
13172
  html += "<ul>";
@@ -15732,6 +15728,13 @@ class Events {
15732
15728
  $("#" + me.pre + id).resizable();
15733
15729
  }
15734
15730
 
15731
+ exportMsa(type) { let me = this.icn3dui, ic = me.icn3d;
15732
+ let text = ic.msa[type].join('\n\n');
15733
+ let fileType = (type == 'fasta') ? '.fasta' : (type == 'clustal') ? '.aln' : '.txt';
15734
+
15735
+ ic.saveFileCls.saveFile(ic.inputid + '_align' + fileType, 'text', [text]);
15736
+ }
15737
+
15735
15738
  async launchMmdb(ids, bBiounit, hostUrl, bAppend) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
15736
15739
  if(!me.cfg.notebook) dialog.dialog( "close" );
15737
15740
 
@@ -18482,6 +18485,24 @@ class Events {
18482
18485
  ic.selectionCls.saveSelection(name, name);
18483
18486
  });
18484
18487
 
18488
+ me.myEventCls.onIds("#" + me.pre + "saveFasta", "click", function(e) { me.icn3d;
18489
+ e.stopImmediatePropagation();
18490
+ thisClass.exportMsa('fasta');
18491
+ thisClass.setLogCmd('Save alignment in FASTA format', false);
18492
+ });
18493
+
18494
+ me.myEventCls.onIds("#" + me.pre + "saveClustal", "click", function(e) { me.icn3d;
18495
+ e.stopImmediatePropagation();
18496
+ thisClass.exportMsa('clustal');
18497
+ thisClass.setLogCmd('Save alignment in CLUSTALW format', false);
18498
+ });
18499
+
18500
+ me.myEventCls.onIds("#" + me.pre + "saveResbyres", "click", function(e) { me.icn3d;
18501
+ e.stopImmediatePropagation();
18502
+ thisClass.exportMsa('resbyres');
18503
+ thisClass.setLogCmd('Save alignment in Residue by Residue format to be used in File > Align (or Realign) > Multiple Chain > Residue by Residue', false);
18504
+ });
18505
+
18485
18506
  $(document).on("click", "." + me.pre + "outputselection", function(e) { let ic = me.icn3d;
18486
18507
  e.stopImmediatePropagation();
18487
18508
  ic.bSelectResidue = false;
@@ -19341,7 +19362,9 @@ class SetHtml {
19341
19362
 
19342
19363
  sequencesHtml += '<div style="width:20px; margin-left:3px; display:inline-block;"><span id="' + me.pre + 'alignseqguide' + suffix + '_expand" class="ui-icon ui-icon-plus icn3d-expand icn3d-link" style="width:15px;" title="Expand"></span><span id="' + me.pre + 'alignseqguide' + suffix + '_shrink" class="ui-icon ui-icon-minus icn3d-shrink icn3d-link" style="display:none; width:15px;" title="Shrink"></span></div> ';
19343
19364
 
19344
- sequencesHtml += "<div style='min-width:200px; display:inline-block;''><b>Selection:</b> Name: " + me.htmlCls.inputTextStr + "id='" + me.pre + "alignseq_command_name' value='alseq_" + index + "' size='10'> " + me.htmlCls.space2 + "<button style='white-space:nowrap;' id='" + me.pre + "alignseq_saveselection'>Save</button> <button style='white-space:nowrap; margin-left:20px;' id='" + me.pre + "alignseq_clearselection'>Clear</button></div><br/>";
19365
+ sequencesHtml += "<div style='min-width:200px; display:inline-block;'><b>Selection:</b> Name: " + me.htmlCls.inputTextStr + "id='" + me.pre + "alignseq_command_name' value='alseq_" + index + "' size='10'> " + me.htmlCls.space2 + "<button style='white-space:nowrap;' id='" + me.pre + "alignseq_saveselection'>Save</button> <button style='white-space:nowrap; margin-left:20px;' id='" + me.pre + "alignseq_clearselection'>Clear</button></div><br/>";
19366
+
19367
+ sequencesHtml += "<div style='min-width:200px; display:inline-block; margin-top:3px'><b>Save Alignment</b>: " + "<button style='white-space:nowrap;' id='" + me.pre + "saveFasta'>FASTA</button> <button style='white-space:nowrap; margin-left:20px;' id='" + me.pre + "saveClustal'>CLUSTAL</button> <button style='white-space:nowrap; margin-left:20px;' id='" + me.pre + "saveResbyres'>Residue by Residue</button></div><br/>";
19345
19368
 
19346
19369
  sequencesHtml += me.htmlCls.divStr + "alignseqguide" + suffix + "' style='display:none; white-space:normal;' class='icn3d-box'>";
19347
19370
 
@@ -19350,7 +19373,9 @@ class SetHtml {
19350
19373
  let resCategories = "<b>Residue labeling:</b> aligned residue with coordinates: UPPER case letter; non-aligned residue with coordinates: lower case letter which can be highlighted; residue missing coordinates: lower case letter which can NOT be highlighted.";
19351
19374
  let scroll =(me.utilsCls.isMac() && !me.utilsCls.isMobile()) ? "<br/><br/><b>Turn on scroll bar:</b> System preferences -> General -> show scroll bars -> check Always" : "";
19352
19375
 
19353
- sequencesHtml += resCategories + scroll + "<br/></div>";
19376
+ sequencesHtml += resCategories + scroll + "<br/>";
19377
+
19378
+ sequencesHtml += "</div>";
19354
19379
 
19355
19380
  return sequencesHtml;
19356
19381
  }
@@ -33249,7 +33274,6 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
33249
33274
  //this.vpAtomID[index] =(this.dataArray[index] >= 0) ? 1 : 0; // determine whether it's positive
33250
33275
  }
33251
33276
  }
33252
-
33253
33277
  }
33254
33278
  }
33255
33279
 
@@ -59641,12 +59665,15 @@ class DensityCifParser {
59641
59665
  let thisClass = this;
59642
59666
 
59643
59667
  let url;
59644
- let detail = (me.utilsCls.isMobile() || me.cfg.notebook) ? 0 : 4; //4;
59668
+ let detail = (me.utilsCls.isMobile() || me.cfg.notebook) ? 2 : 4; //0 : 4;
59645
59669
 
59646
59670
  //https://www.ebi.ac.uk/pdbe/densities/doc.html
59647
59671
  if(type == '2fofc' || type == 'fofc') {
59648
- detail = 0;
59649
- url = "https://www.ebi.ac.uk/pdbe/densities/x-ray/" + pdbid.toLowerCase() + "/cell?detail=" + detail;
59672
+ //detail = 0;
59673
+
59674
+ // url = "https://www.ebi.ac.uk/pdbe/densities/x-ray/" + pdbid.toLowerCase() + "/cell?detail=" + detail;
59675
+ let min_max = ic.contactCls.getExtent(ic.atoms);
59676
+ url = "https://www.ebi.ac.uk/pdbe/volume-server/x-ray/" + pdbid.toLowerCase() + "/box/" + min_max[0][0] + "," + min_max[0][1] + "," + min_max[0][2] + "/" + min_max[1][0] + "," + min_max[1][1] + "," + min_max[1][2] + "?detail=" + detail;
59650
59677
  }
59651
59678
  else if(type == 'em') {
59652
59679
  url = "https://www.ebi.ac.uk/pdbe/densities/emd/" + emd.toLowerCase() + "/cell?detail=" + detail;
@@ -59719,6 +59746,33 @@ class DensityCifParser {
59719
59746
  // return sigma;
59720
59747
  }
59721
59748
 
59749
+ setMatrix(density) { let ic = this.icn3d; ic.icn3dui;
59750
+ let sampleCount = density.box.sampleCount;
59751
+ let header = {xExtent: sampleCount[0], yExtent: sampleCount[1], zExtent: sampleCount[2], mean: density.valuesInfo.mean, sigma: density.valuesInfo.sigma, max: density.valuesInfo.max, min: density.valuesInfo.min};
59752
+ for(let i = 0; i < density.data.length; ++i) {
59753
+ density.data[i];
59754
+ }
59755
+
59756
+ let origin = density.box.origin;
59757
+ let dimensions = density.box.dimensions;
59758
+ let basis = density.spacegroup.basis;
59759
+ let scale = new THREE.Matrix4().makeScale(
59760
+ dimensions[0] / (sampleCount[0] ),
59761
+ dimensions[1] / (sampleCount[1] ),
59762
+ dimensions[2] / (sampleCount[2] ));
59763
+ let translate = new THREE.Matrix4().makeTranslation(origin[0], origin[1], origin[2]);
59764
+ let fromFrac = new THREE.Matrix4().set(
59765
+ basis.x[0], basis.y[0], basis.z[0], 0.0,
59766
+ 0.0, basis.y[1], basis.z[1], 0.0,
59767
+ 0.0, 0.0, basis.z[2], 0.0,
59768
+ 0.0, 0.0, 0.0, 1.0);
59769
+
59770
+ //var toFrac = new LiteMol.Visualization.THREE.Matrix4().getInverse(fromFrac);
59771
+ let matrix = fromFrac.multiply(translate).multiply(scale);
59772
+
59773
+ return {matrix: matrix, header: header};
59774
+ }
59775
+
59722
59776
  parseChannels(densitydata, type, sigma) { let ic = this.icn3d; ic.icn3dui;
59723
59777
  let cif = this.BinaryParse(densitydata);
59724
59778
 
@@ -59728,92 +59782,35 @@ class DensityCifParser {
59728
59782
 
59729
59783
  // '2fofc'
59730
59784
  let density = twoDensity;
59731
- let sampleCount = density.box.sampleCount;
59732
- let header = {xExtent: sampleCount[0], yExtent: sampleCount[1], zExtent: sampleCount[2], mean: density.valuesInfo.mean, sigma: density.valuesInfo.sigma};
59733
- ic.mapData.header2 = header;
59734
-
59735
- ic.mapData.data2 = density.data;
59736
- for(let i = 0; i < density.data.length; ++i) {
59737
- density.data[i];
59738
- }
59739
-
59740
- let origin = density.box.origin;
59741
- let dimensions = density.box.dimensions;
59742
- let basis = density.spacegroup.basis;
59743
- let scale = new THREE.Matrix4().makeScale(
59744
- dimensions[0] / (sampleCount[0] ),
59745
- dimensions[1] / (sampleCount[1] ),
59746
- dimensions[2] / (sampleCount[2] ));
59747
- let translate = new THREE.Matrix4().makeTranslation(origin[0], origin[1], origin[2]);
59748
- let fromFrac = new THREE.Matrix4().set(
59749
- basis.x[0], basis.y[0], basis.z[0], 0.0,
59750
- 0.0, basis.y[1], basis.z[1], 0.0,
59751
- 0.0, 0.0, basis.z[2], 0.0,
59752
- 0.0, 0.0, 0.0, 1.0);
59785
+ let result = this.setMatrix(density);
59753
59786
 
59754
- //var toFrac = new LiteMol.Visualization.THREE.Matrix4().getInverse(fromFrac);
59755
- let matrix = fromFrac.multiply(translate).multiply(scale);
59756
-
59757
- ic.mapData.matrix2 = matrix;
59787
+ ic.mapData.matrix2 = result.matrix;
59788
+ ic.mapData.header2 = result.header;
59758
59789
 
59790
+ ic.mapData.data2 = density.data;
59759
59791
  ic.mapData.type2 = type;
59760
59792
  ic.mapData.sigma2 = sigma;
59761
59793
 
59762
59794
  // 'fofc'
59763
59795
  density = oneDensity;
59764
- sampleCount = density.box.sampleCount;
59765
- header = {xExtent: sampleCount[0], yExtent: sampleCount[1], zExtent: sampleCount[2], mean: density.valuesInfo.mean, sigma: density.valuesInfo.sigma};
59766
- ic.mapData.header = header;
59767
-
59768
- ic.mapData.data = density.data;
59796
+ result = this.setMatrix(density);
59769
59797
 
59770
- origin = density.box.origin;
59771
- dimensions = density.box.dimensions;
59772
- basis = density.spacegroup.basis;
59773
-
59774
- scale = new THREE.Matrix4().makeScale(
59775
- dimensions[0] / (sampleCount[0] ),
59776
- dimensions[1] / (sampleCount[1] ),
59777
- dimensions[2] / (sampleCount[2] ));
59778
- translate = new THREE.Matrix4().makeTranslation(origin[0], origin[1], origin[2]);
59779
- fromFrac = new THREE.Matrix4().set(
59780
- basis.x[0], basis.y[0], basis.z[0], 0.0,
59781
- 0.0, basis.y[1], basis.z[1], 0.0,
59782
- 0.0, 0.0, basis.z[2], 0.0,
59783
- 0.0, 0.0, 0.0, 1.0);
59784
- //var toFrac = new LiteMol.Visualization.THREE.Matrix4().getInverse(fromFrac);
59785
- matrix = fromFrac.multiply(translate).multiply(scale);
59786
- ic.mapData.matrix = matrix;
59798
+ ic.mapData.matrix = result.matrix;
59799
+ ic.mapData.header = result.header;
59787
59800
 
59801
+ ic.mapData.data = density.data;
59788
59802
  ic.mapData.type = type;
59789
59803
  ic.mapData.sigma = sigma;
59790
59804
  }
59791
59805
  else if(type == 'em') {
59792
59806
  let density = this.getChannel(cif, 'EM');
59793
59807
 
59794
- let sampleCount = density.box.sampleCount;
59795
- let header = {xExtent: sampleCount[0], yExtent: sampleCount[1], zExtent: sampleCount[2], max: density.valuesInfo.max, min: density.valuesInfo.min};
59796
- ic.mapData.headerEm = header;
59808
+ let result = this.setMatrix(density);
59797
59809
 
59798
- ic.mapData.dataEm = density.data;
59799
-
59800
- let origin = density.box.origin;
59801
- let dimensions = density.box.dimensions;
59802
- let basis = density.spacegroup.basis;
59803
- let scale = new THREE.Matrix4().makeScale(
59804
- dimensions[0] / (sampleCount[0] ),
59805
- dimensions[1] / (sampleCount[1] ),
59806
- dimensions[2] / (sampleCount[2] ));
59807
- let translate = new THREE.Matrix4().makeTranslation(origin[0], origin[1], origin[2]);
59808
- let fromFrac = new THREE.Matrix4().set(
59809
- basis.x[0], basis.y[0], basis.z[0], 0.0,
59810
- 0.0, basis.y[1], basis.z[1], 0.0,
59811
- 0.0, 0.0, basis.z[2], 0.0,
59812
- 0.0, 0.0, 0.0, 1.0);
59813
- //var toFrac = new LiteMol.Visualization.THREE.Matrix4().getInverse(fromFrac);
59814
- let matrix = fromFrac.multiply(translate).multiply(scale);
59815
- ic.mapData.matrixEm = matrix;
59810
+ ic.mapData.matrixEm = result.matrix;
59811
+ ic.mapData.headerEm = result.header;
59816
59812
 
59813
+ ic.mapData.dataEm = density.data;
59817
59814
  ic.mapData.typeEm = type;
59818
59815
  ic.mapData.sigmaEm = sigma;
59819
59816
  }
@@ -62293,6 +62290,7 @@ class SetSeqAlign {
62293
62290
  setSeqAlign(seqalign, alignedStructures) { let ic = this.icn3d, me = ic.icn3dui;
62294
62291
  let mmdbid1 = alignedStructures[0][0].pdbId;
62295
62292
  let mmdbid2 = alignedStructures[0][1].pdbId;
62293
+ let chainid1, chainid2;
62296
62294
 
62297
62295
  ic.conservedName1 = mmdbid1 + '_cons';
62298
62296
  ic.nonConservedName1 = mmdbid1 + '_ncons';
@@ -62316,7 +62314,7 @@ class SetSeqAlign {
62316
62314
  let molid1 = alignData.moleculeId;
62317
62315
 
62318
62316
  let chain1 = ic.pdbid_molid2chain[mmdbid1 + '_' + molid1];
62319
- let chainid1 = mmdbid1 + '_' + chain1;
62317
+ chainid1 = mmdbid1 + '_' + chain1;
62320
62318
 
62321
62319
  let id2aligninfo = {};
62322
62320
  let start = alignData.sequence.length, end = -1;
@@ -62348,7 +62346,7 @@ class SetSeqAlign {
62348
62346
  let molid2 = alignData.moleculeId;
62349
62347
 
62350
62348
  let chain2 = ic.pdbid_molid2chain[mmdbid2 + '_' + molid2];
62351
- let chainid2 = mmdbid2 + '_' + chain2;
62349
+ chainid2 = mmdbid2 + '_' + chain2;
62352
62350
 
62353
62351
  // annotation title for the master seq only
62354
62352
  if(ic.alnChainsAnTtl[chainid1] === undefined ) ic.alnChainsAnTtl[chainid1] = [];
@@ -62516,7 +62514,9 @@ class SetSeqAlign {
62516
62514
  ic.alnChainsAnno[chainid1][3].push(numberStr); // symbol: 10, 20, etc, empty for rest
62517
62515
 
62518
62516
  ++alignIndex;
62519
- } // end for(let j
62517
+ } // end for(let j
62518
+
62519
+ this.setMsaFormat([chainid1, chainid2]);
62520
62520
  } // end for(let i
62521
62521
 
62522
62522
  seqalign = {};
@@ -62596,7 +62596,7 @@ class SetSeqAlign {
62596
62596
  }
62597
62597
 
62598
62598
  setSeqAlignChain(chainid, chainIndex, chainidArray) { let ic = this.icn3d, me = ic.icn3dui;
62599
- let hAtoms = {};
62599
+ let hAtoms = {};
62600
62600
 
62601
62601
  let bRealign = (chainidArray) ? true : false;
62602
62602
  let mmdbid1, mmdbid2, chain1, chain2, chainid1, chainid2, pos1, pos2;
@@ -62817,23 +62817,6 @@ class SetSeqAlign {
62817
62817
  ///if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid2] === undefined) break;
62818
62818
 
62819
62819
  let resi1, resi2, resn1, resn2;
62820
- /*
62821
- if(bRealign) { // tmalign: just one residue in this for loop
62822
- if(me.cfg.aligntool == 'tmalign') {
62823
- resi1 = ic.qt_start_end[chainIndex][i].t_start;
62824
- resi2 = ic.qt_start_end[chainIndex][i].q_start;
62825
- }
62826
- else {
62827
- resi1 = j + start1;
62828
- resi2 = j + start2;
62829
- }
62830
-
62831
- resn1 = this.getResnFromResi(chainid1, resi1).toUpperCase();
62832
- resn2 = this.getResnFromResi(chainid2, resi2).toUpperCase();
62833
-
62834
- if(resn1 == '?' || resn2 == '?') continue;
62835
- }
62836
- */
62837
62820
  if(bRealign && me.cfg.aligntool == 'tmalign') { // tmalign: just one residue in this for loop
62838
62821
  resi1 = ic.qt_start_end[chainIndex][i].t_start;
62839
62822
  resi2 = ic.qt_start_end[chainIndex][i].q_start;
@@ -62844,15 +62827,6 @@ class SetSeqAlign {
62844
62827
  if(resn1 == '?' || resn2 == '?') continue;
62845
62828
  }
62846
62829
  else {
62847
- ///if(ic.chainsSeq[chainid1][j + start1] === undefined || ic.chainsSeq[chainid2][j + start2] === undefined) continue;
62848
-
62849
- // resi1 = ic.chainsSeq[chainid1][j + start1].resi;
62850
- // resi2 = ic.chainsSeq[chainid2][j + start2].resi;
62851
- // resn1 = ic.chainsSeq[chainid1][j + start1].name.toUpperCase();
62852
- // resn2 = ic.chainsSeq[chainid2][j + start2].name.toUpperCase();
62853
-
62854
- // resi1 = this.getResiAferAlign(chainid1, bRealign, j + start1 + 1);
62855
- // resi2 = this.getResiAferAlign(chainid2, bRealign, j + start2 + 1);
62856
62830
  resi1 = this.getResiAferAlign(chainid1, bRealign, j + start1);
62857
62831
  resi2 = this.getResiAferAlign(chainid2, bRealign, j + start2);
62858
62832
  resn1 = this.getResnFromResi(chainid1, resi1).toUpperCase();
@@ -62892,14 +62866,15 @@ class SetSeqAlign {
62892
62866
 
62893
62867
  prevIndex1 = end1;
62894
62868
  prevIndex2 = end2;
62895
- } // end for(let i
62869
+ } // end for(let i
62870
+
62871
+ this.setMsaFormat([chainid1, chainid2]);
62896
62872
 
62897
62873
  return hAtoms;
62898
62874
  }
62899
62875
 
62900
62876
  setSeqAlignChainForAll(chainidArray, index_alignLen, bRealign) { let ic = this.icn3d, me = ic.icn3dui;
62901
62877
  let hAtoms = {};
62902
-
62903
62878
  let chainid1 = chainidArray[0];
62904
62879
 
62905
62880
  ic.alnChainsAnno[chainid1] = [];
@@ -63053,7 +63028,8 @@ class SetSeqAlign {
63053
63028
  resObject.aligned = (resid2range_t[resid]) ? true : false;
63054
63029
  resObject.color = (resid2range_t[resid]) ? '#FF0000' : me.htmlCls.GREYC; // color by identity
63055
63030
  resObject.color2 = (resid2range_t[resid]) ? '#FF0000' : me.htmlCls.GREYC; // color by conservation
63056
- resObject.class = (resid2range_t[resid]) ? 'icn3d-align' : 'icn3d-nalign';
63031
+ // resObject.class = (resid2range_t[resid]) ? 'icn3d-align' : 'icn3d-nalign';
63032
+ resObject.class = (resid2range_t[resid]) ? 'icn3d-cons' : 'icn3d-nalign';
63057
63033
 
63058
63034
  ic.alnChainsSeq[chainid1].push(resObject);
63059
63035
 
@@ -63072,7 +63048,9 @@ class SetSeqAlign {
63072
63048
  let hAtomsTmp = this.mergeTwoSeqForAll(chainidArray, index, alignedChainIndice, resid2range_t, start_t, end_t, bRealign);
63073
63049
 
63074
63050
  hAtoms = me.hashUtilsCls.unionHash(hAtoms, hAtomsTmp);
63075
- }
63051
+ }
63052
+
63053
+ this.setMsaFormat(chainidArray);
63076
63054
 
63077
63055
  // 3. assign the variable ic.alnChainsAnno
63078
63056
  for(let i = 0; i < 3 + 2*n; ++i) {
@@ -63143,7 +63121,7 @@ class SetSeqAlign {
63143
63121
  resObject.aligned = (bGap) ? false : bAligned;
63144
63122
  resObject.color = (bGap || !bAligned) ? me.htmlCls.GREYC : ((resn == resn_t) ? "#FF0000" : "#0000FF"); // color by identity
63145
63123
  resObject.color2 = (bGap || !bAligned) ? me.htmlCls.GREYC : '#' + ic.showAnnoCls.getColorhexFromBlosum62(resn, resn_t); // color by conservation
63146
- resObject.class = (bGap || !bAligned) ? 'icn3d-nalign' : 'icn3d-align';
63124
+ resObject.class = (bGap || !bAligned) ? 'icn3d-nalign' : ((resn == resn_t) ? "icn3d-cons" : "icn3d-ncons");
63147
63125
 
63148
63126
  return resObject;
63149
63127
  }
@@ -63417,7 +63395,7 @@ class SetSeqAlign {
63417
63395
  pos2 = result.pos2;
63418
63396
  for(let i = pos1; i < pos2; ++i) {
63419
63397
  //for(let i = pos1; i <= pos2; ++i) {
63420
- ic.alnChainsSeq[chainid2].push(gapResObject2);
63398
+ ic.alnChainsSeq[chainid2].push(gapResObject2);
63421
63399
  }
63422
63400
 
63423
63401
  return hAtoms;
@@ -63744,6 +63722,107 @@ class SetSeqAlign {
63744
63722
  }
63745
63723
  }
63746
63724
  }
63725
+
63726
+ setMsaFormat(chainidArray) { let ic = this.icn3d; ic.icn3dui;
63727
+ //set MSA
63728
+ let fastaFormat = '', clustalFormat = 'CLUSTALW\n\n', resbyresFormat = '';
63729
+ let chainArrayClustal = [];
63730
+
63731
+ let consArray = [], resiArrayTemplate = [];
63732
+ let chainidTemplate = chainidArray[0];
63733
+ for(let i = 0, il = chainidArray.length; i < il; ++i) {
63734
+ let chainid = chainidArray[i];
63735
+ fastaFormat += '>' + chainid + '\n';
63736
+
63737
+ let clustalArray = [];
63738
+ let clustalLine = chainid.padEnd(20, ' ');
63739
+ let consLine = ''.padEnd(20, ' ');
63740
+
63741
+ let resiArrayTarget = [], resiArrayQuery = [];
63742
+
63743
+ let cnt = 0;
63744
+ for(let j = 0, jl = ic.alnChainsSeq[chainid].length; j < jl; ++j) {
63745
+ let resn = ic.alnChainsSeq[chainid][j].resn;
63746
+ fastaFormat += resn;
63747
+ clustalLine += resn;
63748
+ if(i == il - 1) {
63749
+ let alignedClass = ic.alnChainsSeq[chainid][j].class;
63750
+ if(alignedClass == 'icn3d-cons') {
63751
+ consLine += '*';
63752
+ }
63753
+ else if(alignedClass == 'icn3d-ncons') {
63754
+ consLine += '.';
63755
+ }
63756
+ else {
63757
+ consLine += ' ';
63758
+ }
63759
+ }
63760
+
63761
+ // residue by residue
63762
+ if(i == 0) {
63763
+ resiArrayTemplate.push(ic.alnChainsSeq[chainid][j].resi);
63764
+ }
63765
+ else {
63766
+ if(ic.alnChainsSeq[chainid][j].aligned) {
63767
+ resiArrayTarget.push(ic.alnChainsSeq[chainidTemplate][j].resi);
63768
+ resiArrayQuery.push(ic.alnChainsSeq[chainid][j].resi);
63769
+ }
63770
+ }
63771
+
63772
+ ++cnt;
63773
+
63774
+ if(cnt % 60 == 0) {
63775
+ fastaFormat += '\n';
63776
+ clustalLine += ' ' + String(parseInt(cnt / 60) * 60);
63777
+ clustalArray.push(clustalLine);
63778
+ clustalLine = chainid.padEnd(20, ' ');
63779
+
63780
+ if(i == il - 1) {
63781
+ consArray.push(consLine);
63782
+ consLine = ''.padEnd(20, ' ');
63783
+ }
63784
+ }
63785
+ }
63786
+
63787
+ // add last line
63788
+ if(cnt % 60 != 0) {
63789
+ clustalArray.push(clustalLine);
63790
+ if(i == il - 1) {
63791
+ consArray.push(consLine);
63792
+ }
63793
+ }
63794
+
63795
+ fastaFormat += '\n';
63796
+
63797
+ chainArrayClustal.push(clustalArray);
63798
+ if(i == il - 1) chainArrayClustal.push(consArray);
63799
+
63800
+ // residue by residue
63801
+ let resiRangeStr1 = ic.resid2specCls.resi2range(resiArrayTarget, true);
63802
+ let resiRangeStr2 = ic.resid2specCls.resi2range(resiArrayQuery, true);
63803
+
63804
+ if(i > 0) resbyresFormat += resiRangeStr1 + ' | ' + resiRangeStr2 + '\n';
63805
+ }
63806
+
63807
+ // CLUSTALW
63808
+ for(let j = 0, jl = chainArrayClustal[0].length; j < jl; ++j) {
63809
+ for(let i = 0, il = chainArrayClustal.length; i < il; ++i) {
63810
+ clustalFormat += chainArrayClustal[i][j] + '\n';
63811
+ }
63812
+ clustalFormat += '\n';
63813
+ }
63814
+
63815
+ // seq MSA
63816
+ if(!ic.msa) ic.msa = {};
63817
+
63818
+ if(!ic.msa['fasta']) ic.msa['fasta'] = [];
63819
+ if(!ic.msa['clustal']) ic.msa['clustal'] = [];
63820
+ if(!ic.msa['resbyres']) ic.msa['resbyres'] = [];
63821
+
63822
+ ic.msa['fasta'].push(fastaFormat);
63823
+ ic.msa['clustal'].push(clustalFormat);
63824
+ ic.msa['resbyres'].push(resbyresFormat);
63825
+ }
63747
63826
  }
63748
63827
 
63749
63828
  /**
@@ -71368,8 +71447,8 @@ class Resid2spec {
71368
71447
  return spec;
71369
71448
  }
71370
71449
 
71371
- resi2range(resiArray) {var ic = this.icn3d; ic.icn3dui;
71372
- let range = [];
71450
+ resi2range(resiArray, bString) {var ic = this.icn3d; ic.icn3dui;
71451
+ let range = [], rangeStr = '';
71373
71452
 
71374
71453
  let resiArraySorted = resiArray.sort(function(a, b) {
71375
71454
  return parseInt(a) - parseInt(b);
@@ -71380,9 +71459,14 @@ class Resid2spec {
71380
71459
  for(let j = 0, jl = resiArraySorted.length; j < jl; ++j) {
71381
71460
  resi = resiArraySorted[j];
71382
71461
 
71383
- if(j != 0 && resi != prevResi + 1) {
71462
+ if(j != 0 && parseInt(resi) != parseInt(prevResi) + 1) {
71384
71463
  range.push(startResi);
71385
71464
  range.push(prevResi);
71465
+
71466
+ if(rangeStr) rangeStr += ',';
71467
+ if(startResi == prevResi) rangeStr += startResi;
71468
+ else rangeStr += startResi + '-' + prevResi;
71469
+
71386
71470
  startResi = resi;
71387
71471
  }
71388
71472
 
@@ -71392,8 +71476,13 @@ class Resid2spec {
71392
71476
  // last residue
71393
71477
  range.push(startResi);
71394
71478
  range.push(prevResi);
71395
-
71396
- return range;
71479
+
71480
+ if(rangeStr) rangeStr += ',';
71481
+ if(startResi == prevResi) rangeStr += startResi;
71482
+ else rangeStr += startResi + '-' + prevResi;
71483
+
71484
+ if(bString) return rangeStr;
71485
+ else return range;
71397
71486
  }
71398
71487
 
71399
71488
  atoms2spec(atomHash) {var ic = this.icn3d; ic.icn3dui;
@@ -79006,6 +79095,8 @@ class SaveFile {
79006
79095
  for(let i = 0, il = residueArray.length; i < il; ++i) {
79007
79096
  let resid = residueArray[i];
79008
79097
  let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]);
79098
+ if(!atom) continue;
79099
+
79009
79100
  let chainid = atom.structure + '_' + atom.chain;
79010
79101
  let resnAbbr = me.utilsCls.residueName2Abbr(atom.resn);
79011
79102
  let resName = resnAbbr + atom.resi;
@@ -82986,7 +83077,7 @@ class iCn3DUI {
82986
83077
  //even when multiple iCn3D viewers are shown together.
82987
83078
  this.pre = this.cfg.divid + "_";
82988
83079
 
82989
- this.REVISION = '3.40.3';
83080
+ this.REVISION = '3.41.0';
82990
83081
 
82991
83082
  // In nodejs, iCn3D defines "window = {navigator: {}}"
82992
83083
  this.bNode = (Object.keys(window).length < 2) ? true : false;