icn3d 3.21.2 → 3.22.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.module.js CHANGED
@@ -6887,11 +6887,23 @@ class ClickMenu {
6887
6887
  thisClass.setLogCmd("export pqr", true);
6888
6888
  });
6889
6889
 
6890
- me.myEventCls.onIds(["#" + me.pre + "delphipdbh", "#" + me.pre + "phipqr", "#" + me.pre + "phiurlpqr"], "click", async function(e) { me.icn3d; //e.preventDefault();
6891
- let bPdb = true;
6892
- await me.htmlCls.setHtmlCls.exportPqr(bPdb);
6893
- thisClass.setLogCmd("export pdbh", false);
6894
- });
6890
+ // me.myEventCls.onIds("#" + me.pre + "delphipqbh", "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
6891
+ // let bPdb = true;
6892
+ // await me.htmlCls.setHtmlCls.exportPqr(bPdb);
6893
+ // thisClass.setLogCmd("export pdbh", false);
6894
+ // });
6895
+
6896
+ me.myEventCls.onIds("#" + me.pre + "profixpdb", "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
6897
+ let bHydrogen = false;
6898
+ await ic.scapCls.exportPdbProfix(bHydrogen);
6899
+ thisClass.setLogCmd("export pdb missing atoms", true);
6900
+ });
6901
+
6902
+ me.myEventCls.onIds("#" + me.pre + "profixpdbh", "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
6903
+ let bHydrogen = true;
6904
+ await ic.scapCls.exportPdbProfix(bHydrogen);
6905
+ thisClass.setLogCmd("export pdb hydrogen", true);
6906
+ });
6895
6907
 
6896
6908
  me.myEventCls.onIds("#" + me.pre + "mn1_exportStl", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
6897
6909
  thisClass.setLogCmd("export stl file", false);
@@ -8679,7 +8691,7 @@ class ClickMenu {
8679
8691
  type: 'POST',
8680
8692
  data: {
8681
8693
  q : pdbstr,
8682
- database: ["afdb50", "afdb-swissprot", "gmgcl_id", "pdb100"],
8694
+ database: ["afdb50", "afdb-swissprot", "gmgcl_id", "pdb100", "afdb-proteome", "mgnify_esm30"],
8683
8695
  mode: "3diaa"
8684
8696
  },
8685
8697
  dataType: 'text',
@@ -9399,7 +9411,8 @@ class SetMenu {
9399
9411
  html += this.getLink('mn1_exportCounts', 'Residue Counts', undefined, 2);
9400
9412
 
9401
9413
  html += this.getLink('mn1_exportPdbRes', 'PDB', 1, 2);
9402
- html += this.getLink('delphipdbh', 'PDB with Hydrogens', undefined, 2);
9414
+ html += this.getLink('profixpdb', 'PDB with Missing Atoms', undefined, 2);
9415
+ html += this.getLink('profixpdbh', 'PDB with Hydrogens', undefined, 2);
9403
9416
 
9404
9417
  if(me.cfg.cid === undefined) {
9405
9418
  html += this.getLink('mn1_exportSecondary', 'Secondary Structure', undefined, 2);
@@ -10231,6 +10244,10 @@ class SetMenu {
10231
10244
  html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', undefined, undefined, 2);
10232
10245
  html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', true, undefined, 2);
10233
10246
  }
10247
+ else {
10248
+ html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', undefined, undefined, 2);
10249
+ html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', undefined, undefined, 2);
10250
+ }
10234
10251
 
10235
10252
  //if(me.cfg.afid) html += this.getRadio('mn4_clr', 'mn4_clrConfidence', 'AF Confidence');
10236
10253
  //if(!me.cfg.mmtfid && !me.cfg.pdbid && !me.cfg.opmid && !me.cfg.mmdbid && !me.cfg.gi && !me.cfg.uniprotid && !me.cfg.blast_rep_id && !me.cfg.cid && !me.cfg.mmcifid && !me.cfg.align && !me.cfg.chainalign) {
@@ -10305,6 +10322,15 @@ class SetMenu {
10305
10322
 
10306
10323
  html += this.getLink('mn6_hbondsYes', 'Interactions', 1, 1);
10307
10324
 
10325
+ html += this.getMenuText('mn1_window', 'Bring to Front', undefined, undefined, 1);
10326
+ html += "<ul>";
10327
+ html += this.getLink('mn1_window_table', 'Interaction Table', undefined, 2);
10328
+ html += this.getLink('mn1_window_linegraph', '2D Interaction Network', undefined, 2);
10329
+ html += this.getLink('mn1_window_scatterplot', '2D Interaction Map', undefined, 2);
10330
+ html += this.getLink('mn1_window_graph', '2D Graph(Force-Directed)', undefined, 2);
10331
+ html += "</ul>";
10332
+ html += "</li>";
10333
+
10308
10334
  html += this.getLink('mn6_contactmap', 'Contact Map', undefined, 1);
10309
10335
 
10310
10336
  if(!me.cfg.notebook) {
@@ -11415,10 +11441,11 @@ class SetDialog {
11415
11441
 
11416
11442
  html += me.htmlCls.divStr + "dl_customref' class='" + dialogClass + "'>";
11417
11443
  html += '<div style="width:550px;">You can define your own reference numbers in a custom file using Excel, and then export it as a CSV file. An example file is shown below with cells separated by commas.<br>';
11418
- html += '<pre>refnum,11,12,,21,22<br>';
11419
- html += '1TUP_A,100,101,,,132<br>';
11420
- html += '1TUP_B,110,111,,141,142</pre>';
11421
- html += 'The first row defines the reference residue numbers. The 1st cell could be anything. The rest cells are reference residue numbers (e.g., 11, 12, 21, 22) or empty cells. Each chain has a separate row. The first cell of the second row is the chain ID "1TUP_A". The rest cells are the corresponding real residue numbers for reference residue numbers in the first row. For example, the reference numbers for residues 100, 101, and 132 in the chain 1TUP_A are 11, 12, and 22, respectively. The thrid row shows the real residue numbers for the chain "1TUP_B".<br><br>';
11444
+ html += '<pre>refnum,11,12,,21,22,,10C,11C,20C<br>';
11445
+ html += '1TUP_A,100,101,,,132,,,,<br>';
11446
+ html += '1TUP_B,110,111,,141,142,,,,</pre>';
11447
+ html += '1TUP_C,,,,,,,200,201,230</pre>';
11448
+ html += 'The first row defines the reference residue numbers, which could be any strings. The 1st cell could be anything. The rest cells are reference residue numbers (e.g., 11, 21, 10C, etc.) or empty cells. Each chain has a separate row. The first cell of the second row is the chain ID "1TUP_A". The rest cells are the corresponding real residue numbers for reference residue numbers in the first row. For example, the reference numbers for residues 100, 101, and 132 in the chain 1TUP_A are 11, 12, and 22, respectively. The fourth row shows another set of reference numners for the chain "1TUP_C". It could be a chain from a different structure.<br><br>';
11422
11449
  html += 'To select all residues corresponding to the reference numbers, you can simplay replace ":" with "%" in the <a href="https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d.html#selectb" target="_blank">Specification</a>. For example, "%12" selects the residue 101 in 1TUP_A and the residue 111 in 1TUP_B. ".A%12" has the chain "A" filter and selects the residue 101 in 1TUP_A.<br>';
11423
11450
  html += '</div><br>';
11424
11451
  html += "Custom File: " + me.htmlCls.inputFileStr + "id='" + me.pre + "cstreffile' size=8> <br><br>";
@@ -11794,11 +11821,14 @@ class SetDialog {
11794
11821
 
11795
11822
  html += me.htmlCls.divStr + "dl_realignbystruct' class='" + dialogClass + "'>";
11796
11823
 
11797
- html += me.htmlCls.divNowrapStr + "1. Select sets in two chains below <br>or use your current selection:</div><br>";
11824
+ html += me.htmlCls.divNowrapStr + "<b>1</b>. Select sets in two chains below <br>or use your current selection:</div><br>";
11798
11825
  html += "<div style='text-indent:1.1em'><select id='" + me.pre + "atomsCustomRealignByStruct' multiple size='5' style='min-width:130px;'>";
11799
11826
  html += "</select></div><br>";
11800
11827
 
11801
- html += "<div>2. " + me.htmlCls.buttonStr + "applyRealignByStruct_tmalign'>Realign with TM-align</button>" + me.htmlCls.buttonStr + "applyRealignByStruct' style='margin-left:30px'>Realign with VAST</button></div><br>";
11828
+ html += "<div><b>2a</b>. <div style='display:inline-block; width:80px'>MSA:</div> " + me.htmlCls.buttonStr + "applyRealignByStructMsa_tmalign'>Realign with TM-align</button>" + me.htmlCls.buttonStr + "applyRealignByStructMsa' style='margin-left:30px'>Realign with VAST</button></div><br>";
11829
+
11830
+ html += "<div>or <b>2b</b>. <div style='display:inline-block; width:65px'>Pairwise:</div> " + me.htmlCls.buttonStr + "applyRealignByStruct_tmalign'>Realign with TM-align</button>" + me.htmlCls.buttonStr + "applyRealignByStruct' style='margin-left:30px'>Realign with VAST</button></div><br>";
11831
+
11802
11832
  html += "</div>";
11803
11833
 
11804
11834
  html += me.htmlCls.divStr + "dl_realigntwostru' class='" + dialogClass + "'>";
@@ -12471,6 +12501,32 @@ class Events {
12471
12501
  thisClass.setLogCmd('select ' + select + ' | name ' + commandname, true);
12472
12502
  }
12473
12503
 
12504
+ async setRealign(alignType, bMsa) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
12505
+ let nameArray = $("#" + me.pre + "atomsCustomRealignByStruct").val();
12506
+ if(nameArray.length > 0) {
12507
+ ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(nameArray);
12508
+ }
12509
+
12510
+ me.cfg.aligntool = alignType;
12511
+
12512
+ if(bMsa) {
12513
+ await ic.realignParserCls.realignOnStructAlignMsa(nameArray);
12514
+ }
12515
+ else {
12516
+ await ic.realignParserCls.realignOnStructAlign();
12517
+ }
12518
+
12519
+ let alignStr = (alignType == 'vast') ? 'structure align' : 'tmalign';
12520
+ alignStr += (bMsa) ? ' msa' : '';
12521
+
12522
+ if(nameArray.length > 0) {
12523
+ thisClass.setLogCmd("realign on " + alignStr + " | " + nameArray, true);
12524
+ }
12525
+ else {
12526
+ thisClass.setLogCmd("realign on " + alignStr, true);
12527
+ }
12528
+ }
12529
+
12474
12530
  readFile(bAppend, files, index, dataStrAll) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
12475
12531
  let file = files[index];
12476
12532
  let commandName = (bAppend) ? 'append': 'load';
@@ -12781,42 +12837,32 @@ class Events {
12781
12837
  }
12782
12838
  });
12783
12839
 
12784
- me.myEventCls.onIds("#" + me.pre + "applyRealignByStruct", "click", async function(e) { let ic = me.icn3d;
12840
+ me.myEventCls.onIds("#" + me.pre + "applyRealignByStruct", "click", async function(e) { me.icn3d;
12785
12841
  e.preventDefault();
12786
12842
  if(!me.cfg.notebook) dialog.dialog( "close" );
12787
- let nameArray = $("#" + me.pre + "atomsCustomRealignByStruct").val();
12788
- if(nameArray.length > 0) {
12789
- ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(nameArray);
12790
- }
12791
-
12792
- me.cfg.aligntool = 'vast';
12793
-
12794
- await ic.realignParserCls.realignOnStructAlign();
12795
- if(nameArray.length > 0) {
12796
- thisClass.setLogCmd("realign on structure align | " + nameArray, true);
12797
- }
12798
- else {
12799
- thisClass.setLogCmd("realign on structure align", true);
12800
- }
12843
+
12844
+ await thisClass.setRealign('vast', false);
12801
12845
  });
12802
12846
 
12803
- me.myEventCls.onIds("#" + me.pre + "applyRealignByStruct_tmalign", "click", async function(e) { let ic = me.icn3d;
12847
+ me.myEventCls.onIds("#" + me.pre + "applyRealignByStruct_tmalign", "click", async function(e) { me.icn3d;
12804
12848
  e.preventDefault();
12805
12849
  if(!me.cfg.notebook) dialog.dialog( "close" );
12806
- let nameArray = $("#" + me.pre + "atomsCustomRealignByStruct").val();
12807
- if(nameArray.length > 0) {
12808
- ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(nameArray);
12809
- }
12810
12850
 
12811
- me.cfg.aligntool = 'tmalign';
12812
-
12813
- await ic.realignParserCls.realignOnStructAlign();
12814
- if(nameArray.length > 0) {
12815
- thisClass.setLogCmd("realign on tmalign | " + nameArray, true);
12816
- }
12817
- else {
12818
- thisClass.setLogCmd("realign on tmalign", true);
12819
- }
12851
+ await thisClass.setRealign('tmalign', false);
12852
+ });
12853
+
12854
+ me.myEventCls.onIds("#" + me.pre + "applyRealignByStructMsa", "click", async function(e) { me.icn3d;
12855
+ e.preventDefault();
12856
+ if(!me.cfg.notebook) dialog.dialog( "close" );
12857
+
12858
+ await thisClass.setRealign('vast', true);
12859
+ });
12860
+
12861
+ me.myEventCls.onIds("#" + me.pre + "applyRealignByStructMsa_tmalign", "click", async function(e) { me.icn3d;
12862
+ e.preventDefault();
12863
+ if(!me.cfg.notebook) dialog.dialog( "close" );
12864
+
12865
+ await thisClass.setRealign('tmalign', true);
12820
12866
  });
12821
12867
 
12822
12868
  me.myEventCls.onIds("#" + me.pre + "applyRealignByStruct_vastplus", "click", async function(e) { let ic = me.icn3d;
@@ -15903,7 +15949,7 @@ class SetHtml {
15903
15949
  else if(pos != -1) {
15904
15950
  let url = imageStr.substr(pos + matchedStr.length);
15905
15951
  me.htmlCls.clickMenuCls.setLogCmd('load iCn3D PNG image ' + $("#" + me.pre + "pngimage").val(), false);
15906
- window.open(url);
15952
+ window.open(url, '_self');
15907
15953
  }
15908
15954
  else if(posState != -1) {
15909
15955
  let matchedStrData = "Start of data file======\n";
@@ -33956,7 +34002,7 @@ class SetColor {
33956
34002
  let b = atom.b;
33957
34003
 
33958
34004
  // PDB
33959
- b = (atom.structure.length < 6) ? 100 - b : b;
34005
+ b = (atom.structure.substr(0, 4) != ic.defaultPdbId && atom.structure.length < 6) ? 100 - b : b;
33960
34006
 
33961
34007
  if(b >= 90) {
33962
34008
  atom.color = me.parasCls.thr().setRGB(0, 0.325, 0.839);
@@ -33994,7 +34040,7 @@ class SetColor {
33994
34040
  if(b > 100) b = 100;
33995
34041
 
33996
34042
  // AlphaFold
33997
- b = (atom.structure.length > 5) ? 100 - b : b;
34043
+ b = (atom.structure.substr(0, 4) != ic.defaultPdbId && atom.structure.length > 5) ? 100 - b : b;
33998
34044
 
33999
34045
  let s1 = (ic.middB - b) * ic.spanBinv1;
34000
34046
  let s2 = (b - ic.middB) * ic.spanBinv2;
@@ -34901,7 +34947,7 @@ class AnnoCddSite {
34901
34947
 
34902
34948
  let linkStr = (bCoordinates) ? 'icn3d-link icn3d-blue' : '';
34903
34949
 
34904
- let htmlTmp2 = '<div class="icn3d-seqTitle ' + linkStr + '" site="site" posarray="' + adjustedResPosArray.toString() + '" shorttitle="' + title + '" setname="' + chnid + '_site_' + index + '" anno="sequence" chain="' + chnid + '" title="' + fulltitle + '">' + title + ' </div>';
34950
+ let htmlTmp2 = '<div class="icn3d-seqTitle ' + linkStr + '" site="site" posarray="' + resPosArray.toString() + '" shorttitle="' + title + '" setname="' + chnid + '_site_' + index + '" anno="sequence" chain="' + chnid + '" title="' + fulltitle + '">' + title + ' </div>';
34905
34951
  let htmlTmp3 = '<span class="icn3d-residueNum" title="residue count">' + resCnt.toString() + ' Res</span>';
34906
34952
  let htmlTmp = '<span class="icn3d-seqLine">';
34907
34953
  html3 += htmlTmp2 + htmlTmp3 + '<br>';
@@ -35073,8 +35119,9 @@ class AnnoCddSite {
35073
35119
  let from = parseInt(fromArray[i]), to = parseInt(toArray[i]);
35074
35120
 
35075
35121
  for(let j = from; j <= to; ++j) {
35076
-
35077
- let resid = chnid + "_" + j;
35122
+ let resi = ic.ParserUtilsCls.getResi(chnid, j);
35123
+ //let resid = chnid + "_" + j;
35124
+ let resid = chnid + "_" + resi;
35078
35125
 
35079
35126
  if(ic.residues.hasOwnProperty(resid)) {
35080
35127
  bCoordinates = true;
@@ -40826,7 +40873,7 @@ class ShowSeq {
40826
40873
 
40827
40874
  //if(ic.resid2refnum.hasOwnProperty(residueid)) {
40828
40875
  let refnumLabel = ic.resid2refnum[residueid];
40829
- if(refnumLabel) {
40876
+ if(refnumLabel) {
40830
40877
  let refnumStr_ori = refnumLabel.replace(/'/g, '').substr(1);
40831
40878
  let refnumStr;
40832
40879
  if(bCustom) {
@@ -42001,7 +42048,9 @@ class LineGraph {
42001
42048
  nodeArray2 = nodeArrays.nodeArray2;
42002
42049
  ic.lineGraphStr = '{\n';
42003
42050
 
42004
- let structureArray = ic.resid2specCls.atoms2structureArray(ic.hAtoms);
42051
+ //let structureArray = ic.resid2specCls.atoms2structureArray(ic.hAtoms);
42052
+ let structureArray = Object.keys(ic.structures);
42053
+
42005
42054
  //if(Object.keys(ic.structures).length > 1) {
42006
42055
  if(structureArray.length > 1) {
42007
42056
 
@@ -42769,6 +42818,7 @@ class GetGraph {
42769
42818
 
42770
42819
  updateGraphColor() { let ic = this.icn3d, me = ic.icn3dui;
42771
42820
  // change graph color
42821
+
42772
42822
  if(ic.graphStr !== undefined) {
42773
42823
  let graphJson = JSON.parse(ic.graphStr);
42774
42824
  let resid2color = {};
@@ -44892,7 +44942,7 @@ class ContactMap {
44892
44942
 
44893
44943
  let graphStr = '{\n';
44894
44944
 
44895
- let struc1 = (ic.structures.length > 0) ? ic.structures[0] : 'stru';
44945
+ let struc1 = (ic.structures.length > 0) ? ic.structures[0] : ic.defaultPdbId;
44896
44946
  let len1 = nodeArray1.length,
44897
44947
  len2 = nodeArray2.length;
44898
44948
  let factor = 1;
@@ -45432,7 +45482,8 @@ class ChainalignParser {
45432
45482
  }
45433
45483
  }
45434
45484
 
45435
- async downloadChainalignmentPart2b(chainresiCalphaHash2, chainidArray, hAtoms, dataArray, indexArray, mmdbid_t, struArray) { let ic = this.icn3d, me = ic.icn3dui;
45485
+ async downloadChainalignmentPart2b(chainresiCalphaHash2, chainidArray, hAtoms, dataArray,
45486
+ indexArray, mmdbid_t, struArray) { let ic = this.icn3d, me = ic.icn3dui;
45436
45487
  //let bTargetTransformed = (ic.qt_start_end[0]) ? true : false;
45437
45488
 
45438
45489
  // modify the previous trans and rotation matrix
@@ -45777,7 +45828,7 @@ class ChainalignParser {
45777
45828
  let chainid = chainidArray[i];
45778
45829
  let pos = chainid.indexOf('_');
45779
45830
  let struct = chainid.substr(0, pos);
45780
- if(struct != 'stru') struct = struct.toUpperCase();
45831
+ if(struct != ic.defaultPdbId) struct = struct.toUpperCase();
45781
45832
 
45782
45833
  if(!struct2cnt.hasOwnProperty(struct)) {
45783
45834
  struct2cnt[struct] = 1;
@@ -45963,11 +46014,16 @@ class ChainalignParser {
45963
46014
  if(ic.afChainIndexHash.hasOwnProperty(index)) {
45964
46015
  ++missedChainCnt;
45965
46016
 
45966
- // need to pass C-alpha coords and get transformation matrix from backend
45967
- ic.t_trans_add[index-1] = {"x":0, "y":0, "z":0};
45968
- ic.q_trans_sub[index-1] = {"x":0, "y":0, "z":0};
46017
+
45969
46018
 
45970
- if(me.cfg.aligntool == 'tmalign') ic.q_trans_add[index-1] = {"x":0, "y":0, "z":0};
46019
+ if(me.cfg.aligntool == 'tmalign') {
46020
+ ic.q_trans_add[index-1] = {"x":0, "y":0, "z":0};
46021
+ }
46022
+ else {
46023
+ // need to pass C-alpha coords and get transformation matrix from backend
46024
+ ic.t_trans_add[index-1] = {"x":0, "y":0, "z":0};
46025
+ ic.q_trans_sub[index-1] = {"x":0, "y":0, "z":0};
46026
+ }
45971
46027
 
45972
46028
  ic.q_rotation[index-1] = {"x1":1, "y1":0, "z1":0, "x2":0, "y2":1, "z2":0, "x3":0, "y3":0, "z3":1};
45973
46029
  ic.qt_start_end[index-1] = undefined;
@@ -46024,10 +46080,14 @@ class ChainalignParser {
46024
46080
  ic.q_rotation.push(align[0].q_rotation);
46025
46081
  ic.qt_start_end.push(align[0].segs);
46026
46082
  */
46027
- ic.t_trans_add[index] = align[0].t_trans_add;
46028
- ic.q_trans_sub[index] = align[0].q_trans_sub;
46029
46083
 
46030
- if(me.cfg.aligntool == 'tmalign') ic.q_trans_add[index] = align[0].q_trans_add;
46084
+ if(me.cfg.aligntool == 'tmalign') {
46085
+ ic.q_trans_add[index] = align[0].q_trans_add;
46086
+ }
46087
+ else {
46088
+ ic.t_trans_add[index] = align[0].t_trans_add;
46089
+ ic.q_trans_sub[index] = align[0].q_trans_sub;
46090
+ }
46031
46091
 
46032
46092
  ic.q_rotation[index] = align[0].q_rotation;
46033
46093
  ic.qt_start_end[index] = align[0].segs;
@@ -46574,11 +46634,11 @@ class MmcifParser {
46574
46634
 
46575
46635
  //ic.bCid = undefined;
46576
46636
 
46577
- let data1 = await me.getAjaxPromise(url, 'text', false, 'The structure " + mmcifid + " was not found...');
46637
+ let data1 = await me.getAjaxPromise(url, 'text', false, "The structure " + mmcifid + " was not found...");
46578
46638
 
46579
46639
  url = me.htmlCls.baseUrl + "mmcifparser/mmcifparser.cgi";
46580
46640
  let dataObj = {'mmcifheader': data1};
46581
- let data = await me.getAjaxPostPromise(url, dataObj, false, 'The mmCIF data of " + mmcifid + " can not be parsed...');
46641
+ let data = await me.getAjaxPostPromise(url, dataObj, false, "The mmCIF data of " + mmcifid + " can not be parsed...");
46582
46642
 
46583
46643
  if(data.emd !== undefined) ic.emd = data.emd;
46584
46644
  if(data.organism !== undefined) ic.organism = data.organism;
@@ -46638,7 +46698,7 @@ class MmcifParser {
46638
46698
  //loadAtomDataIn. The deferred parameter was resolved after the parsing so that other javascript code can be executed.
46639
46699
  async loadMmcifData(data, mmcifid) { let ic = this.icn3d; ic.icn3dui;
46640
46700
  if(!mmcifid) mmcifid = data.mmcif;
46641
- if(!mmcifid) mmcifid = 'stru';
46701
+ if(!mmcifid) mmcifid = ic.defaultPdbId;
46642
46702
 
46643
46703
  if(data.atoms !== undefined) {
46644
46704
  ic.init();
@@ -47735,7 +47795,7 @@ class OpmParser {
47735
47795
 
47736
47796
  async loadOpmData(data, pdbid, bFull, type, pdbid2) { let ic = this.icn3d, me = ic.icn3dui;
47737
47797
  try {
47738
- if(!pdbid) pdbid = 'stru';
47798
+ if(!pdbid) pdbid = ic.defaultPdbId;
47739
47799
  let url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&opm&uid=" + pdbid.toLowerCase();
47740
47800
 
47741
47801
  let opmdata = await me.getAjaxPromise(url, 'jsonp', false);
@@ -47940,20 +48000,22 @@ class PdbParser {
47940
48000
  if(me.cfg.opmid === undefined) ic.ParserUtilsCls.transformToOpmOri(pdbid);
47941
48001
 
47942
48002
  if(ic.biomtMatrices !== undefined && ic.biomtMatrices.length > 1) {
47943
- $("#" + ic.pre + "assemblyWrapper").show();
48003
+ if(!me.bNode) $("#" + ic.pre + "assemblyWrapper").show();
47944
48004
 
47945
48005
  ic.asuCnt = ic.biomtMatrices.length;
47946
48006
  }
47947
48007
 
47948
- if(ic.emd !== undefined) {
47949
- $("#" + ic.pre + "mapWrapper1").hide();
47950
- $("#" + ic.pre + "mapWrapper2").hide();
47951
- $("#" + ic.pre + "mapWrapper3").hide();
47952
- }
47953
- else {
47954
- $("#" + ic.pre + "emmapWrapper1").hide();
47955
- $("#" + ic.pre + "emmapWrapper2").hide();
47956
- $("#" + ic.pre + "emmapWrapper3").hide();
48008
+ if(!me.bNode) {
48009
+ if(ic.emd !== undefined) {
48010
+ $("#" + ic.pre + "mapWrapper1").hide();
48011
+ $("#" + ic.pre + "mapWrapper2").hide();
48012
+ $("#" + ic.pre + "mapWrapper3").hide();
48013
+ }
48014
+ else {
48015
+ $("#" + ic.pre + "emmapWrapper1").hide();
48016
+ $("#" + ic.pre + "emmapWrapper2").hide();
48017
+ $("#" + ic.pre + "emmapWrapper3").hide();
48018
+ }
47957
48019
  }
47958
48020
 
47959
48021
  // calculate secondary structures if not available
@@ -47974,7 +48036,7 @@ class PdbParser {
47974
48036
  else {
47975
48037
  await this.loadPdbDataRender(bAppend);
47976
48038
 
47977
- await ic.ParserUtilsCls.checkMemProteinAndRotate();
48039
+ if(!me.bNode) await ic.ParserUtilsCls.checkMemProteinAndRotate();
47978
48040
 
47979
48041
  /// if(ic.deferredOpm !== undefined) ic.deferredOpm.resolve();
47980
48042
  }
@@ -48796,6 +48858,8 @@ class RealignParser {
48796
48858
  let ajaxArray = [], chainidPairArray = [];
48797
48859
  let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
48798
48860
  let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
48861
+
48862
+ //let cnt = 0;
48799
48863
  let structArray = Object.keys(struct2domain);
48800
48864
  for(let s = 0, sl = structArray.length; s < sl; ++s) {
48801
48865
  let struct1 = structArray[s];
@@ -48808,13 +48872,13 @@ class RealignParser {
48808
48872
 
48809
48873
  for(let i = 0, il = chainidArray1.length; i < il; ++i) {
48810
48874
  let chainid1 = chainidArray1[i];
48875
+ let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(struct2domain[struct1][chainid1]);
48811
48876
  for(let j = 0, jl = chainidArray2.length; j < jl; ++j) {
48812
48877
  let chainid2 = chainidArray2[j];
48813
48878
 
48814
48879
  let alignAjax;
48815
48880
 
48816
48881
  if(me.cfg.aligntool != 'tmalign') {
48817
- let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(struct2domain[struct1][chainid1]);
48818
48882
  let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(struct2domain[struct2][chainid2]);
48819
48883
 
48820
48884
  let dataObj = {'domains1': jsonStr_q, 'domains2': jsonStr_t};
@@ -48832,7 +48896,8 @@ class RealignParser {
48832
48896
  }
48833
48897
 
48834
48898
  ajaxArray.push(alignAjax);
48835
- chainidPairArray.push(chainid1 + ',' + chainid2); // chainid2 is target
48899
+ chainidPairArray.push(chainid1 + ',' + chainid2);
48900
+ //++cnt;
48836
48901
  }
48837
48902
  }
48838
48903
  }
@@ -48849,6 +48914,87 @@ class RealignParser {
48849
48914
  }
48850
48915
  }
48851
48916
 
48917
+ async realignOnStructAlignMsa(nameArray) { let ic = this.icn3d, me = ic.icn3dui;
48918
+ // each 3D domain should have at least 3 secondary structures
48919
+ let minSseCnt = 3;
48920
+ let chainid2domain = {};
48921
+
48922
+ for(let i = 0, il = nameArray.length; i < il; ++i) {
48923
+ let chainid = nameArray[i];
48924
+ let atoms = me.hashUtilsCls.intHash(ic.hAtoms, ic.chains[chainid]);
48925
+ let sseCnt = 0;
48926
+ for(let serial in atoms) {
48927
+ if(ic.atoms[serial].ssbegin) ++sseCnt;
48928
+ if(sseCnt == minSseCnt) {
48929
+ chainid2domain[chainid] = atoms;
48930
+ break;
48931
+ }
48932
+ }
48933
+ }
48934
+
48935
+ let ajaxArray = [], indexArray = [], struArray = [];
48936
+ let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
48937
+ let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
48938
+
48939
+ let chainid1 = nameArray[0];
48940
+ let struct1 = chainid1.substr(0, chainid1.indexOf('_'));
48941
+ let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(chainid2domain[chainid1]);
48942
+
48943
+ for(let i = 1, il = nameArray.length; i < il; ++i) {
48944
+ let chainid2 = nameArray[i];
48945
+ let struct2 = chainid2.substr(0, chainid2.indexOf('_'));
48946
+
48947
+ let alignAjax;
48948
+
48949
+ if(me.cfg.aligntool != 'tmalign') {
48950
+ let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(chainid2domain[chainid2]);
48951
+
48952
+ let dataObj = {'domains1': jsonStr_q, 'domains2': jsonStr_t};
48953
+ alignAjax = me.getAjaxPostPromise(urlalign, dataObj);
48954
+ }
48955
+ else {
48956
+ // let pdb_target = ic.saveFileCls.getAtomPDB(chainid2domain[chainid1], undefined, undefined, undefined, undefined, struct1);
48957
+ // let pdb_query = ic.saveFileCls.getAtomPDB(chainid2domain[chainid2], undefined, undefined, undefined, undefined, struct2);
48958
+
48959
+ let pdb_target = ic.saveFileCls.getAtomPDB(ic.chains[chainid1], undefined, undefined, undefined, undefined, struct1);
48960
+ let pdb_query = ic.saveFileCls.getAtomPDB(ic.chains[chainid2], undefined, undefined, undefined, undefined, struct2);
48961
+
48962
+ let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target};
48963
+ alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
48964
+ }
48965
+
48966
+ ajaxArray.push(alignAjax);
48967
+ //chainidPairArray.push(chainid1 + ',' + chainid2);
48968
+
48969
+ indexArray.push(i - 1);
48970
+ struArray.push(struct2);
48971
+
48972
+ //++cnt;
48973
+ }
48974
+
48975
+ let allPromise = Promise.allSettled(ajaxArray);
48976
+ //try {
48977
+ let dataArray = await allPromise;
48978
+ //ic.qt_start_end = []; // reset the alignment
48979
+ //await ic.chainalignParserCls.downloadChainalignmentPart2bRealignMsa(dataArray, chainidPairArray);
48980
+
48981
+ // set trans and rotation matrix
48982
+ ic.t_trans_add = [];
48983
+ ic.q_trans_sub = [];
48984
+
48985
+ if(me.cfg.aligntool == 'tmalign') ic.q_trans_add = [];
48986
+
48987
+ ic.q_rotation = [];
48988
+ ic.qt_start_end = [];
48989
+
48990
+ await ic.chainalignParserCls.downloadChainalignmentPart2b(undefined, nameArray, undefined, dataArray,
48991
+ indexArray, struct1, struArray);
48992
+ // }
48993
+ // catch(err) {
48994
+ // if(ic.bRender) alert("These structures can NOT be aligned to each other...");
48995
+ // }
48996
+ }
48997
+
48852
48998
  async realignChainOnSeqAlign(chainresiCalphaHash2, chainidArray, bRealign, bPredefined) { let ic = this.icn3d, me = ic.icn3dui;
48853
48999
  let thisClass = this;
48854
49000
 
@@ -50622,7 +50768,7 @@ class ParserUtils {
50622
50768
 
50623
50769
  //var dxymax = npoint / 2.0 * step;
50624
50770
 
50625
- pdbid =(pdbid) ? pdbid.toUpperCase() : 'stru';
50771
+ pdbid =(pdbid) ? pdbid.toUpperCase() : ic.defaultPdbId;
50626
50772
 
50627
50773
  ic.structures[pdbid].push(pdbid + '_MEM');
50628
50774
  ic.chains[pdbid + '_MEM'] = {};
@@ -50864,7 +51010,7 @@ class ParserUtils {
50864
51010
  let afMemdata = await me.getAjaxPromise(url2, 'text');
50865
51011
 
50866
51012
  ic.bAfMem = true;
50867
- $("#" + me.pre + "togglememli").show(); // show the menu "View > Toggle Membrane"
51013
+ if(!me.bNode) $("#" + me.pre + "togglememli").show(); // show the menu "View > Toggle Membrane"
50868
51014
 
50869
51015
  // append the PDB
50870
51016
  let pdbid = data.pdbid.substr(0, data.pdbid.indexOf('_'));
@@ -53045,7 +53191,7 @@ class LoadPDB {
53045
53191
 
53046
53192
  //let chainMissingResidueArray = {}
53047
53193
 
53048
- let id = (pdbid) ? pdbid : 'stru';
53194
+ let id = (pdbid) ? pdbid : ic.defaultPdbId;
53049
53195
  let structure = id;
53050
53196
 
53051
53197
  let prevMissingChain = '';
@@ -53065,18 +53211,18 @@ class LoadPDB {
53065
53211
 
53066
53212
  if(id == '') {
53067
53213
  if(bAppend) {
53068
- id = "stru";
53214
+ id = ic.defaultPdbId;
53069
53215
  }
53070
53216
  else {
53071
- //if(!ic.inputid) ic.inputid = 'stru';
53072
- id = (ic.inputid && ic.inputid.indexOf('/') == -1) ? ic.inputid.substr(0, 10) : "stru"; //ic.filename.substr(0, 4);
53217
+ //if(!ic.inputid) ic.inputid = ic.defaultPdbId;
53218
+ id = (ic.inputid && ic.inputid.indexOf('/') == -1) ? ic.inputid.substr(0, 10) : ic.defaultPdbId; //ic.filename.substr(0, 4);
53073
53219
  }
53074
53220
  }
53075
53221
 
53076
53222
  structure = id;
53077
53223
 
53078
- if(id == 'stru' || bMutation) { // bMutation: side chain prediction
53079
- //if(id == 'stru') {
53224
+ if(id == ic.defaultPdbId || bMutation) { // bMutation: side chain prediction
53225
+ //if(id == ic.defaultPdbId) {
53080
53226
  structure = (moleculeNum === 1) ? id : id + moleculeNum.toString();
53081
53227
  }
53082
53228
 
@@ -53191,12 +53337,12 @@ class LoadPDB {
53191
53337
  ic.organism = ic.organism.substr(0, ic.organism.length - 1);
53192
53338
  } else if (record === 'ENDMDL') {
53193
53339
  ++moleculeNum;
53194
- id = 'stru';
53340
+ id = ic.defaultPdbId;
53195
53341
 
53196
53342
  structure = id;
53197
53343
 
53198
- if(id == 'stru' || bMutation) { // bMutation: side chain prediction
53199
- //if(id == 'stru') {
53344
+ if(id == ic.defaultPdbId || bMutation) { // bMutation: side chain prediction
53345
+ //if(id == ic.defaultPdbId) {
53200
53346
  structure = (moleculeNum === 1) ? id : id + moleculeNum.toString();
53201
53347
  }
53202
53348
 
@@ -53219,8 +53365,8 @@ class LoadPDB {
53219
53365
  } else if (record === 'ATOM ' || record === 'HETATM') {
53220
53366
  structure = id;
53221
53367
 
53222
- if(id == 'stru' || bMutation) { // bMutation: side chain prediction
53223
- //if(id == 'stru') {
53368
+ if(id == ic.defaultPdbId || bMutation) { // bMutation: side chain prediction
53369
+ //if(id == ic.defaultPdbId) {
53224
53370
  structure = (moleculeNum === 1) ? id : id + moleculeNum.toString();
53225
53371
  }
53226
53372
 
@@ -54692,6 +54838,12 @@ class ApplyCommand {
54692
54838
  else if(command == 'export pdb') {
54693
54839
  me.htmlCls.setHtmlCls.exportPdb();
54694
54840
  }
54841
+ else if(command == 'export pdb missing atoms') {
54842
+ await ic.scapCls.exportPdbProfix(false);
54843
+ }
54844
+ else if(command == 'export pdb hydrogen') {
54845
+ await ic.scapCls.exportPdbProfix(true);
54846
+ }
54695
54847
  else if(command == 'export secondary structure') {
54696
54848
  me.htmlCls.setHtmlCls.exportSecondary();
54697
54849
  }
@@ -55865,21 +56017,23 @@ class ApplyCommand {
55865
56017
  else if(command.indexOf('window') == 0) {
55866
56018
  let secondPart = command.substr(command.indexOf(' ') + 1);
55867
56019
 
55868
- if(secondPart == "aligned sequences") {
56020
+ setTimeout(function(){
56021
+ if(secondPart == "aligned sequences") {
55869
56022
  me.htmlCls.dialogCls.openDlg('dl_alignment', 'Select residues in aligned sequences');
55870
- }
55871
- else if(secondPart == "interaction table") {
55872
- me.htmlCls.dialogCls.openDlg('dl_allinteraction', 'Show interactions');
55873
- }
55874
- else if(secondPart == "interaction graph") {
55875
- me.htmlCls.dialogCls.openDlg('dl_linegraph', 'Show interactions between two lines of residue nodes');
55876
- }
55877
- else if(secondPart == "interaction scatterplot") {
55878
- me.htmlCls.dialogCls.openDlg('dl_scatterplot', 'Show interactions as scatterplot');
55879
- }
55880
- else if(secondPart == "force-directed graph") {
55881
- me.htmlCls.dialogCls.openDlg('dl_graph', 'Force-directed graph');
55882
- }
56023
+ }
56024
+ else if(secondPart == "interaction table") {
56025
+ me.htmlCls.dialogCls.openDlg('dl_allinteraction', 'Show interactions');
56026
+ }
56027
+ else if(secondPart == "interaction graph") {
56028
+ me.htmlCls.dialogCls.openDlg('dl_linegraph', 'Show interactions between two lines of residue nodes');
56029
+ }
56030
+ else if(secondPart == "interaction scatterplot") {
56031
+ me.htmlCls.dialogCls.openDlg('dl_scatterplot', 'Show interactions as scatterplot');
56032
+ }
56033
+ else if(secondPart == "force-directed graph") {
56034
+ me.htmlCls.dialogCls.openDlg('dl_graph', 'Force-directed graph');
56035
+ }
56036
+ }, 1000);
55883
56037
  }
55884
56038
  else if(command.indexOf('set theme') == 0) {
55885
56039
  let color = command.substr(command.lastIndexOf(' ') + 1);
@@ -57080,6 +57234,17 @@ class LoadScript {
57080
57234
  await this.execCommandsBase(start, end, steps);
57081
57235
  }
57082
57236
 
57237
+ getNameArray(command) { let ic = this.icn3d; ic.icn3dui;
57238
+ let paraArray = command.split(' | ');
57239
+ let nameArray = [];
57240
+ if(paraArray.length == 2) {
57241
+ nameArray = paraArray[1].split(',');
57242
+ ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(nameArray);
57243
+ }
57244
+
57245
+ return nameArray;
57246
+ }
57247
+
57083
57248
  async execCommandsBase(start, end, steps, bFinalStep) { let ic = this.icn3d, me = ic.icn3dui;
57084
57249
  let thisClass = this;
57085
57250
  let i;
@@ -57221,31 +57386,37 @@ class LoadScript {
57221
57386
  await ic.scapCls.applyCommandScap(command);
57222
57387
  }
57223
57388
  else if(command.indexOf('realign on seq align') == 0) {
57224
- let paraArray = command.split(' | ');
57225
- if(paraArray.length == 2) {
57226
- let nameArray = paraArray[1].split(',');
57227
- ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(nameArray);
57228
- }
57389
+ this.getNameArray(command);
57229
57390
 
57230
57391
  await thisClass.applyCommandRealign(command);
57231
57392
  }
57393
+ else if(command.indexOf('realign on structure align msa') == 0) {
57394
+ let nameArray = this.getNameArray(command);
57395
+
57396
+ me.cfg.aligntool = 'vast';
57397
+
57398
+ await ic.realignParserCls.realignOnStructAlignMsa(nameArray);
57399
+ }
57232
57400
  else if(command.indexOf('realign on structure align') == 0) {
57233
- let paraArray = command.split(' | ');
57234
- if(paraArray.length == 2) {
57235
- let nameArray = paraArray[1].split(',');
57236
- ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(nameArray);
57237
- }
57401
+ this.getNameArray(command);
57238
57402
 
57239
57403
  me.cfg.aligntool = 'vast';
57240
57404
 
57241
- await thisClass.applyCommandRealignByStruct(command);
57405
+ await ic.realignParserCls.realignOnStructAlign();
57406
+ }
57407
+ else if(command.indexOf('realign on tmalign msa') == 0) {
57408
+ let nameArray = this.getNameArray(command);
57409
+
57410
+ me.cfg.aligntool = 'tmalign';
57411
+
57412
+ await ic.realignParserCls.realignOnStructAlignMsa(nameArray);
57242
57413
  }
57243
57414
  else if(command.indexOf('realign on tmalign') == 0) {
57244
- thisClass.getHAtoms(ic.commands[i]);
57415
+ this.getNameArray(command);
57245
57416
 
57246
57417
  me.cfg.aligntool = 'tmalign';
57247
57418
 
57248
- await thisClass.applyCommandRealignByStruct(ic.commands[i]);
57419
+ await ic.realignParserCls.realignOnStructAlign();
57249
57420
  }
57250
57421
  else if(command.indexOf('realign on vastplus') == 0) {
57251
57422
  thisClass.getHAtoms(ic.commands[i]);
@@ -60245,7 +60416,7 @@ class Dssp {
60245
60416
  async showIgRefNum() { let ic = this.icn3d, me = ic.icn3dui;
60246
60417
  let thisClass = this;
60247
60418
 
60248
- if(Object.keys(ic.resid2refnum).length > 0) {
60419
+ if(ic.resid2refnum && Object.keys(ic.resid2refnum).length > 0) {
60249
60420
  ic.bShowRefnum = true;
60250
60421
 
60251
60422
  // open sequence view
@@ -60292,16 +60463,17 @@ class Dssp {
60292
60463
  let ajaxArray = [];
60293
60464
  let domainidpairArray = [];
60294
60465
 
60295
- me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
60466
+ let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
60296
60467
 
60297
60468
  ic.resid2domainid = {};
60298
60469
 
60299
60470
  for(let i = 0, il = struArray.length; i < il; ++i) {
60300
60471
  let struct = struArray[i];
60301
60472
  let chainidArray = ic.structures[struct];
60302
-
60473
+
60303
60474
  for(let j = 0, jl = chainidArray.length; j < jl; ++j) {
60304
60475
  let chainid = chainidArray[j];
60476
+
60305
60477
  if(!ic.proteins.hasOwnProperty(ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chainid]).serial)) continue;
60306
60478
  if(ic.chainsSeq[chainid].length < 50) continue; // peptide
60307
60479
 
@@ -60336,20 +60508,19 @@ class Dssp {
60336
60508
  domainAtomsArray.push(domainAtoms);
60337
60509
  }
60338
60510
  }
60339
-
60511
+
60340
60512
  for(let k = 0, kl = domainAtomsArray.length; k < kl; ++k) {
60513
+
60341
60514
  let pdb_target = ic.saveFileCls.getAtomPDB(domainAtomsArray[k], undefined, undefined, undefined, undefined, struct);
60342
60515
  let domainid = chainid + '-' + k;
60343
60516
  for(let index = 0, indexl = dataArray.length; index < indexl; ++index) {
60344
- let struct2 = "stru" + index;
60517
+ let struct2 = ic.defaultPdbId + index;
60345
60518
  let pdb_query = dataArray[index].value; //[0];
60346
-
60347
60519
  let header = 'HEADER ' + struct2 + '\n';
60348
60520
  pdb_query = header + pdb_query;
60349
60521
 
60350
60522
  let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target, "queryid": ic.refpdbArray[index]};
60351
- let alignAjax = me.getAjaxPostPromise(url, dataObj);
60352
-
60523
+ let alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
60353
60524
  ajaxArray.push(alignAjax);
60354
60525
 
60355
60526
  domainidpairArray.push(domainid + "," + index);
@@ -60360,18 +60531,19 @@ class Dssp {
60360
60531
 
60361
60532
  let allPromise = Promise.allSettled(ajaxArray);
60362
60533
  try {
60363
- let dataArray = await allPromise;
60364
- await thisClass.parseAlignData(dataArray, domainidpairArray);
60534
+ let dataArray2 = await allPromise;
60535
+
60536
+ await thisClass.parseAlignData(dataArray2, domainidpairArray);
60365
60537
 
60366
60538
  /// if(ic.deferredRefnum !== undefined) ic.deferredRefnum.resolve();
60367
60539
  }
60368
60540
  catch(err) {
60369
- console.log("Error in aligning with TM-align...");
60541
+ if(!me.bNode) console.log("Error in aligning with TM-align...");
60370
60542
  return;
60371
60543
  }
60372
60544
  }
60373
60545
 
60374
- async parseAlignData(dataArray, domainidpairArray) { let ic = this.icn3d; ic.icn3dui;
60546
+ async parseAlignData(dataArray, domainidpairArray) { let ic = this.icn3d, me = ic.icn3dui;
60375
60547
  let thisClass = this;
60376
60548
 
60377
60549
  let tmscoreThreshold = 0.4; //0.5;
@@ -60380,9 +60552,12 @@ class Dssp {
60380
60552
  let domainid2score = {}, domainid2segs = {}, chainid2segs = {};
60381
60553
  ic.chainid2index = {};
60382
60554
  ic.domainid2ig2kabat = {};
60555
+
60383
60556
  for(let i = 0, il = domainidpairArray.length; i < il; ++i) {
60384
60557
  let queryData = dataArray[i].value; //[0];
60558
+
60385
60559
  if(queryData.length == 0) continue;
60560
+
60386
60561
  if(queryData[0].score < tmscoreThreshold || queryData[0].num_res < 50) continue;
60387
60562
 
60388
60563
  let domainid_index = domainidpairArray[i].split(',');
@@ -60394,6 +60569,7 @@ class Dssp {
60394
60569
  let bBstrand = false, bCstrand = false, bEstrand = false, bFstrand = false;
60395
60570
  for(let i = 0, il = queryData[0].segs.length; i < il; ++i) {
60396
60571
  let seg = queryData[0].segs[i];
60572
+
60397
60573
  if(seg.q_start.indexOf('2050') != -1) {
60398
60574
  bBstrand = true;
60399
60575
  }
@@ -60413,12 +60589,13 @@ class Dssp {
60413
60589
  //if(bBstrand && bCstrand && bEstrand && bFstrand && bGstrand) break;
60414
60590
  if(bBstrand && bCstrand && bEstrand && bFstrand) break;
60415
60591
  }
60592
+
60416
60593
  //if(!(bBstrand && bCstrand && bEstrand && bFstrand && bGstrand)) continue;
60417
60594
  if(!(bBstrand && bCstrand && bEstrand && bFstrand)) continue;
60418
60595
 
60419
60596
  if(!domainid2score.hasOwnProperty(domainid) || queryData[0].score > domainid2score[domainid]) {
60420
60597
  domainid2score[domainid] = queryData[0].score;
60421
- console.log(domainid + ' TM-score: ' + domainid2score[domainid] + ' matched ' + ic.refpdbArray[domainid_index[1]]);
60598
+ if(!me.bNode) console.log(domainid + ' TM-score: ' + domainid2score[domainid] + ' matched ' + ic.refpdbArray[domainid_index[1]]);
60422
60599
  ic.chainid2index[chainid] = domainid_index[1]; // could be several, just take the recent one for simplicity
60423
60600
  domainid2segs[domainid] = queryData[0].segs;
60424
60601
  ic.domainid2ig2kabat[domainid] = queryData[0].ig2kabat;
@@ -60438,7 +60615,7 @@ console.log(domainid + ' TM-score: ' + domainid2score[domainid] + ' matched ' +
60438
60615
  if(!ic.chainsMapping) ic.chainsMapping = {};
60439
60616
  for(let chainid in chainid2segs) {
60440
60617
  let segArray = chainid2segs[chainid];
60441
- console.log("One of the reference PDBs for chain chainid: " + ic.refpdbArray[ic.chainid2index[chainid]]);
60618
+ if(!me.bNode) console.log("One of the reference PDBs for chain chainid: " + ic.refpdbArray[ic.chainid2index[chainid]]);
60442
60619
 
60443
60620
  for(let i = 0, il = segArray.length; i < il; ++i) {
60444
60621
  let seg = segArray[i];
@@ -60708,11 +60885,12 @@ console.log("free energy: " + energy + " kcal/mol");
60708
60885
 
60709
60886
  // get the full mutatnt PDB
60710
60887
  let pdbDataMutant = ic.saveFileCls.getAtomPDB(ic.atoms, false, false, false, chainResi2pdb);
60888
+
60711
60889
  ic.hAtoms = {};
60712
60890
  let bMutation = true;
60713
60891
  ic.loadPDBCls.loadPDB(pdbDataMutant, pdbid, false, false, bMutation, bAddition);
60714
60892
  //let allAtoms2 = me.hashUtilsCls.cloneHash(ic.hAtoms);
60715
-
60893
+
60716
60894
  ic.setStyleCls.setAtomStyleByOptions(ic.opts);
60717
60895
  ic.setColorCls.setColorByOptions(ic.opts, ic.hAtoms);
60718
60896
 
@@ -60767,11 +60945,10 @@ console.log("free energy: " + energy + " kcal/mol");
60767
60945
  }
60768
60946
 
60769
60947
  if(bPdb) {
60770
- //let pdbStr = '';
60771
- //pdbStr += ic.saveFileCls.getAtomPDB(ic.hAtoms);
60948
+ // let file_pref =(ic.inputid) ? ic.inputid : "custom";
60949
+ // ic.saveFileCls.saveFile(file_pref + '_' + snpStr + '.pdb', 'text', [pdbDataMutant]);
60772
60950
 
60773
- let file_pref =(ic.inputid) ? ic.inputid : "custom";
60774
- ic.saveFileCls.saveFile(file_pref + '_' + snpStr + '.pdb', 'text', [pdbDataMutant]);
60951
+ await thisClass.exportPdbProfix(false, pdbDataMutant, snpStr);
60775
60952
 
60776
60953
  ic.drawCls.draw();
60777
60954
  }
@@ -60822,7 +60999,40 @@ console.log("free energy: " + energy + " kcal/mol");
60822
60999
 
60823
61000
  /// if(ic.deferredScap !== undefined) ic.deferredScap.resolve();
60824
61001
  return;
60825
- } }
61002
+ }
61003
+ }
61004
+
61005
+ async exportPdbProfix(bHydrogen, pdb, snpStr) { let ic = this.icn3d, me = ic.icn3dui;
61006
+ let pdbStr;
61007
+
61008
+ if(pdb) {
61009
+ pdbStr = pdb;
61010
+ }
61011
+ else {
61012
+ let atoms = me.hashUtilsCls.intHash(ic.dAtoms, ic.hAtoms);
61013
+ pdbStr += ic.saveFileCls.getAtomPDB(atoms);
61014
+ }
61015
+
61016
+ let url = me.htmlCls.baseUrl + "scap/scap.cgi";
61017
+ let hydrogenStr = (bHydrogen) ? '1' : '0';
61018
+ let dataObj = {'pdb': pdbStr, 'profix': '1', 'hydrogen': hydrogenStr};
61019
+
61020
+ let data;
61021
+
61022
+ try {
61023
+ data = await me.getAjaxPostPromise(url, dataObj, undefined, undefined, undefined, undefined, 'text');
61024
+ }
61025
+ catch(err) {
61026
+ alert("There are some problems in adding missing atoms or hydrogens...");
61027
+ return;
61028
+ }
61029
+
61030
+ let file_pref =(ic.inputid) ? ic.inputid : "custom";
61031
+ let postfix = (bHydrogen) ? "add_hydrogen" : "add_missing_atoms";
61032
+ if(snpStr) postfix = snpStr;
61033
+
61034
+ ic.saveFileCls.saveFile(file_pref + '_icn3d_' + postfix + '.pdb', 'text', [data]);
61035
+ }
60826
61036
  }
60827
61037
 
60828
61038
  /**
@@ -64666,10 +64876,11 @@ class SaveFile {
64666
64876
  }
64667
64877
 
64668
64878
  // if(!bNoSs) {
64669
- let prevResi, stru;
64879
+ let prevResi, stru, chainid;
64670
64880
  for(let i in calphaHash) {
64671
64881
  let atom = ic.atoms[i];
64672
64882
  stru = atom.structure;
64883
+ chainid = atom.structure + '_' + atom.chain;
64673
64884
 
64674
64885
  if(atom.ssbegin) {
64675
64886
  if(atom.ss == 'helix') {
@@ -64690,7 +64901,9 @@ class SaveFile {
64690
64901
  if(atom.ssend) {
64691
64902
  if(atom.ss == 'helix') {
64692
64903
  bHelixEnd = true;
64693
- let helixLen = ic.resid2ncbi[atom.resi] - ic.resid2ncbi[prevResi];
64904
+ let residEnd = ic.resid2ncbi[chainid + '_' + atom.resi];
64905
+ let residStart = ic.resid2ncbi[chainid + '_' + prevResi];
64906
+ let helixLen = (residEnd && residStart) ? parseInt(residEnd.substr(residEnd.lastIndexOf('_') + 1)) - parseInt(residStart.substr(residStart.lastIndexOf('_') + 1)) : 0;
64694
64907
  let helixType = 1;
64695
64908
  if(bHelixBegin) stru2header[stru] += atom.resn.padStart(5, ' ') + atom.chain.replace(/_/gi, '').substr(0, 2).padStart(2, ' ')
64696
64909
  + atom.resi.toString().padStart(5, ' ') + ' ' + helixType + helixLen.toString().padStart(36, ' ') + '\n';
@@ -64771,7 +64984,7 @@ class SaveFile {
64771
64984
  }
64772
64985
 
64773
64986
  let chainResi = atom.chain + '_' + atom.resi;
64774
- if(chainResi2pdb && chainResi2pdb.hasOwnProperty(chainResi)) {
64987
+ if(chainResi2pdb && chainResi2pdb.hasOwnProperty(chainResi)) {
64775
64988
  if(!addedChainResiHash.hasOwnProperty(chainResi)) {
64776
64989
  pdbStr += chainResi2pdb[chainResi];
64777
64990
  addedChainResiHash[chainResi] = 1;
@@ -64936,7 +65149,7 @@ class SaveFile {
64936
65149
  }
64937
65150
 
64938
65151
  pdbStr += connStr;
64939
-
65152
+
64940
65153
  if(bMulStruc) pdbStr += '\nENDMDL\n';
64941
65154
 
64942
65155
  return pdbStr;
@@ -65090,13 +65303,23 @@ class SaveFile {
65090
65303
  setStructureTitle(url, title, titlelinkColor) {var ic = this.icn3d, me = ic.icn3dui;
65091
65304
  if(ic.molTitle.length > 40) title = ic.molTitle.substr(0, 40) + "...";
65092
65305
 
65093
- //var asymmetricStr =(ic.bAssemblyUseAsu) ? "(Asymmetric Unit)" : "";
65094
- let asymmetricStr = "";
65306
+ let text = ic.inputid.toUpperCase();
65095
65307
 
65096
65308
  let idName = (isNaN(ic.inputid) && ic.inputid.length > 5) ? "AlphaFold ID" : "PDB ID";
65309
+ if(ic.inputid.indexOf('http') != -1) {
65310
+ idName = "Data from";
65311
+ url = ic.inputid;
65312
+ text = ic.inputid;
65313
+ }
65314
+
65097
65315
  if(me.cfg.refseqid) idName = 'NCBI Protein Acc.';
65098
65316
 
65099
- $("#" + ic.pre + "title").html(idName + " <a id='" + ic.pre + "titlelink' href='" + url + "' style='color:" + titlelinkColor + "' target='_blank'>" + ic.inputid.toUpperCase() + "</a>" + asymmetricStr + ": " + title);
65317
+ if(!ic.inputid || ic.inputid.substr(0, 4) == ic.defaultPdbId) {
65318
+ $("#" + ic.pre + "title").html(title);
65319
+ }
65320
+ else {
65321
+ $("#" + ic.pre + "title").html(idName + " <a id='" + ic.pre + "titlelink' href='" + url + "' style='color:" + titlelinkColor + "' target='_blank'>" + text + "</a>: " + title);
65322
+ }
65100
65323
  }
65101
65324
 
65102
65325
  getLinkToStructureSummary(bLog) {var ic = this.icn3d, me = ic.icn3dui;
@@ -65182,7 +65405,7 @@ class ShareLink {
65182
65405
  if(bPngHtml) url += "&random=" + parseInt(Math.random() * 1000); // generate a new shorten URL and thus image name everytime
65183
65406
  //var inputid =(ic.inputid) ? ic.inputid : "custom";
65184
65407
  let inputid = Object.keys(ic.structures).join('_');
65185
- if(inputid == 'stru') {
65408
+ if(inputid == ic.defaultPdbId) {
65186
65409
  if(ic.filename) {
65187
65410
  inputid = ic.filename;
65188
65411
  }
@@ -67734,6 +67957,7 @@ class iCn3D {
67734
67957
  this.transparentRenderOrder = false; // false: regular transparency; true: expensive renderOrder for each face
67735
67958
 
67736
67959
  this.AFUniprotVersion = 'v4';
67960
+ this.defaultPdbId = 'stru';
67737
67961
 
67738
67962
  if(!this.icn3dui.bNode) {
67739
67963
  if ( bWebGL2 && bVR) {
@@ -68317,7 +68541,7 @@ class iCn3DUI {
68317
68541
  //even when multiple iCn3D viewers are shown together.
68318
68542
  this.pre = this.cfg.divid + "_";
68319
68543
 
68320
- this.REVISION = '3.21.1';
68544
+ this.REVISION = '3.22.0';
68321
68545
 
68322
68546
  // In nodejs, iCn3D defines "window = {navigator: {}}"
68323
68547
  this.bNode = (Object.keys(window).length < 2) ? true : false;
@@ -68788,7 +69012,7 @@ iCn3DUI.prototype.getAjaxPromise = function(url, dataType, beforeSend, alertMess
68788
69012
  if(beforeSend) me.icn3d.ParserUtilsCls.showLoading();
68789
69013
  },
68790
69014
  complete: function() {
68791
- if(complete) ic.ParserUtilsCls.hideLoading();
69015
+ if(complete) me.icn3d.ParserUtilsCls.hideLoading();
68792
69016
  },
68793
69017
  success: function(data) {
68794
69018
  resolve(data);
@@ -68817,7 +69041,7 @@ iCn3DUI.prototype.getAjaxPostPromise = function(url, data, beforeSend, alertMess
68817
69041
  if(beforeSend) me.icn3d.ParserUtilsCls.showLoading();
68818
69042
  },
68819
69043
  complete: function() {
68820
- if(complete) ic.ParserUtilsCls.hideLoading();
69044
+ if(complete) me.icn3d.ParserUtilsCls.hideLoading();
68821
69045
  },
68822
69046
  success: function(data) {
68823
69047
  resolve(data);