icn3d 3.49.5 → 3.50.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
@@ -54657,6 +54657,19 @@ class UtilsCls {
54657
54657
 
54658
54658
  return date.getFullYear().toString() + monthStr + dateStr;
54659
54659
  }
54660
+
54661
+ compMatrix(mat1, mat2, len) { this.icn3dui;
54662
+ let eps = 1e-6;
54663
+ let bEqual = true;
54664
+ for (let i = 0; i < len; i++) {
54665
+ if (Math.abs(mat1.elements[i] - mat2.elements[i]) > eps) {
54666
+ bEqual = false;
54667
+ break;
54668
+ }
54669
+ }
54670
+
54671
+ return bEqual;
54672
+ }
54660
54673
  }
54661
54674
 
54662
54675
  /**
@@ -58574,7 +58587,8 @@ class ClickMenu {
58574
58587
  me.myEventCls.onIds("#" + me.pre + "2ddgm_r2dt", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
58575
58588
  thisClass.SetChainsAdvancedMenu();
58576
58589
 
58577
- let definedAtomsHtml = ic.definedSetsCls.setAtomMenu(['protein'], true);
58590
+ let bNucleotides = true;
58591
+ let definedAtomsHtml = ic.definedSetsCls.setAtomMenu(['protein'], bNucleotides);
58578
58592
  if($("#" + me.pre + "atomsCustomNucleotide").length && definedAtomsHtml) {
58579
58593
  $("#" + me.pre + "atomsCustomNucleotide").html(definedAtomsHtml);
58580
58594
  me.htmlCls.dialogCls.openDlg('dl_2ddgm_r2dt', 'Show R2DT Diagram for Nucleotides');
@@ -60506,7 +60520,7 @@ class SetMenu {
60506
60520
 
60507
60521
  html += this.getMenuText('2ddgmwrap', '2D Diagram', undefined, 1, 1);
60508
60522
  html += "<ul>";
60509
- html += this.getLink('2ddgm_r2dt', 'for Nucleotides (R2DT)' + me.htmlCls.wifiStr, 1, 2);
60523
+ html += this.getLink('2ddgm_r2dt', 'for Nucleotides' + me.htmlCls.wifiStr, 1, 2);
60510
60524
  html += this.getLink('2ddgm_igdgm', 'for Ig Domains' + me.htmlCls.wifiStr, 1, 2);
60511
60525
  if(me.cfg.mmdbid !== undefined || me.cfg.gi !== undefined || me.cfg.blast_rep_id !== undefined || me.cfg.align !== undefined || me.cfg.chainalign !== undefined) {
60512
60526
  html += this.getLink('mn2_2ddgm', 'for Chains ' + me.htmlCls.wifiStr, 1, 2);
@@ -60959,6 +60973,7 @@ class Dialog {
60959
60973
  let bLigplot = $('#' + me.pre + 'dl_ligplot').hasClass('ui-dialog-content'); // initialized
60960
60974
  let bContactmap = $('#' + me.pre + 'dl_contactmap').hasClass('ui-dialog-content'); // initialized
60961
60975
  let b2ddiagram = $('#' + me.pre + 'dl_2ddiagram').hasClass('ui-dialog-content'); // initialized
60976
+ let brnacanvas = $('#' + me.pre + 'dl_rnacanvas').hasClass('ui-dialog-content'); // initialized
60962
60977
  let bAlignerrormap = $('#' + me.pre + 'dl_alignerrormap').hasClass('ui-dialog-content'); // initialized
60963
60978
  let bTable = $('#' + me.pre + 'dl_interactionsorted').hasClass('ui-dialog-content'); // initialized
60964
60979
  let bAlignmentInit = $('#' + me.pre + 'dl_alignment').hasClass('ui-dialog-content'); // initialized
@@ -60979,6 +60994,7 @@ class Dialog {
60979
60994
  id2flag.dl_ligplot = 'bLigplot2';
60980
60995
  id2flag.dl_contactmap = 'bContactmap2';
60981
60996
  id2flag.dl_2ddiagram = 'b2ddiagram2';
60997
+ id2flag.dl_rnacanvas = 'brnacanvas2';
60982
60998
  id2flag.dl_alignerrormap = 'bAlignerrormap2';
60983
60999
  id2flag.dl_interactionsorted = 'bTable2';
60984
61000
  id2flag.dl_alignment = 'bAlignmentInit2';
@@ -60995,6 +61011,7 @@ class Dialog {
60995
61011
  if(bLigplot) status.bLigplot2 = $('#' + me.pre + 'dl_ligplot').dialog( 'isOpen' );
60996
61012
  if(bContactmap) status.bContactmap2 = $('#' + me.pre + 'dl_contactmap').dialog( 'isOpen' );
60997
61013
  if(b2ddiagram) status.b2ddiagram2 = $('#' + me.pre + 'dl_2ddiagram').dialog( 'isOpen' );
61014
+ if(brnacanvas) status.brnacanvas2 = $('#' + me.pre + 'dl_rnacanvas').dialog( 'isOpen' );
60998
61015
  if(bAlignerrormap) status.bAlignerror2 = $('#' + me.pre + 'dl_alignerrormap').dialog( 'isOpen' );
60999
61016
  if(bTable) status.bTable2 = $('#' + me.pre + 'dl_interactionsorted').dialog( 'isOpen' );
61000
61017
  if(bAlignmentInit) status.bAlignmentInit2 = $('#' + me.pre + 'dl_alignment').dialog( 'isOpen' );
@@ -61080,7 +61097,7 @@ class Dialog {
61080
61097
 
61081
61098
  d3.select("#" + me.svgid).attr("width", width).attr("height", height);
61082
61099
  }
61083
- else if(id == me.pre + 'dl_linegraph' || id == me.pre + 'dl_scatterplot' || id == me.pre + 'dl_ligplot' || id == me.pre + 'dl_contactmap' || id == me.pre + 'dl_2ddiagram' || id == me.pre + 'dl_alignerrormap') {
61100
+ else if(id == me.pre + 'dl_linegraph' || id == me.pre + 'dl_scatterplot' || id == me.pre + 'dl_ligplot' || id == me.pre + 'dl_contactmap' || id == me.pre + 'dl_alignerrormap') {
61084
61101
  let oriWidth =(status.bTwoddgmInit2 || status.bSetsInit2) ?(me.htmlCls.WIDTH - twoddgmWidth)/2 : me.htmlCls.WIDTH / 2;
61085
61102
  let ratio = $("#" + id).width() / oriWidth;
61086
61103
 
@@ -61104,10 +61121,6 @@ class Dialog {
61104
61121
  let width = ic.contactmapWidth * ratio;
61105
61122
  $("#" + me.contactmapid).attr("width", width);
61106
61123
  }
61107
- // else if(id == me.pre + 'dl_2ddiagram') {
61108
- // let width = ic.twoddiagramWidth * ratio;
61109
- // $("#" + me.twoddiagramid).attr("width", width);
61110
- // }
61111
61124
  else if(id == me.pre + 'dl_alignerrormap') {
61112
61125
  let width = ic.alignerrormapWidth * ratio;
61113
61126
  $("#" + me.alignerrormapid).attr("width", width);
@@ -61186,7 +61199,7 @@ class Dialog {
61186
61199
 
61187
61200
  let status = this.getDialogStatus().status;
61188
61201
 
61189
- if(id === me.pre + 'dl_selectannotations' || id === me.pre + 'dl_graph' || id === me.pre + 'dl_linegraph' || id === me.pre + 'dl_scatterplot' || id === me.pre + 'dl_rmsdplot' || id === me.pre + 'dl_hbondplot' || id === me.pre + 'dl_ligplot' || id === me.pre + 'dl_contactmap' || id === me.pre + 'dl_2ddiagram' || id === me.pre + 'dl_alignerrormap' || id === me.pre + 'dl_interactionsorted' || id === me.pre + 'dl_alignment') {
61202
+ if(id === me.pre + 'dl_selectannotations' || id === me.pre + 'dl_graph' || id === me.pre + 'dl_linegraph' || id === me.pre + 'dl_scatterplot' || id === me.pre + 'dl_rmsdplot' || id === me.pre + 'dl_hbondplot' || id === me.pre + 'dl_ligplot' || id === me.pre + 'dl_contactmap' || id === me.pre + 'dl_2ddiagram' || id === me.pre + 'dl_rnacanvas' || id === me.pre + 'dl_alignerrormap' || id === me.pre + 'dl_interactionsorted' || id === me.pre + 'dl_alignment') {
61190
61203
  //var dialogWidth = 0.5 *(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH) - twoddgmWidth * 0.5;
61191
61204
  let dialogWidth = 0.5 *(me.htmlCls.WIDTH) - twoddgmWidth * 0.5;
61192
61205
 
@@ -61222,17 +61235,18 @@ class Dialog {
61222
61235
  modal: false,
61223
61236
  position: position,
61224
61237
  close: function(e) {
61225
- if((id === me.pre + 'dl_selectannotations' &&(!status.bAlignmentInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2))
61226
- ||(id === me.pre + 'dl_graph' &&(!status.bSelectannotationsInit2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2))
61227
- ||(id === me.pre + 'dl_alignment' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2))
61228
- ||(id === me.pre + 'dl_interactionsorted' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2))
61229
- ||(id === me.pre + 'dl_linegraph' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2))
61230
- ||(id === me.pre + 'dl_scatterplot' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2))
61231
- ||(id === me.pre + 'dl_ligplot' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2))
61232
- ||(id === me.pre + 'dl_contactmap' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2))
61233
- ||(id === me.pre + 'dl_alignerrormap' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2))
61234
- ||(id === me.pre + 'dl_hbondplot' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.b2ddiagram2))
61235
- ||(id === me.pre + 'dl_2ddiagram' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2))
61238
+ if((id === me.pre + 'dl_selectannotations' &&(!status.bAlignmentInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2) &&(!status.brnacanvas2))
61239
+ ||(id === me.pre + 'dl_graph' &&(!status.bSelectannotationsInit2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2) &&(!status.brnacanvas2))
61240
+ ||(id === me.pre + 'dl_alignment' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2) &&(!status.brnacanvas2))
61241
+ ||(id === me.pre + 'dl_interactionsorted' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2) &&(!status.brnacanvas2))
61242
+ ||(id === me.pre + 'dl_linegraph' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2) &&(!status.brnacanvas2))
61243
+ ||(id === me.pre + 'dl_scatterplot' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2) &&(!status.brnacanvas2))
61244
+ ||(id === me.pre + 'dl_ligplot' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2) &&(!status.brnacanvas2))
61245
+ ||(id === me.pre + 'dl_contactmap' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2) &&(!status.brnacanvas2))
61246
+ ||(id === me.pre + 'dl_alignerrormap' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2) &&(!status.brnacanvas2))
61247
+ ||(id === me.pre + 'dl_hbondplot' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.b2ddiagram2) &&(!status.brnacanvas2))
61248
+ ||(id === me.pre + 'dl_2ddiagram' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2) &&(!status.brnacanvas2))
61249
+ ||(id === me.pre + 'dl_rnacanvas' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2) &&(!status.bHbondplot2) &&(!status.b2ddiagram2))
61236
61250
  ) {
61237
61251
  if(status.bTwoddgmInit2 || status.bTwodctnInit2 || status.bSetsInit2) {
61238
61252
  let canvasWidth = me.utilsCls.isMobile() ? me.htmlCls.WIDTH : me.htmlCls.WIDTH - twoddgmWidth;
@@ -61258,7 +61272,7 @@ class Dialog {
61258
61272
 
61259
61273
  d3.select("#" + me.svgid).attr("width", width).attr("height", height);
61260
61274
  }
61261
- else if(id == me.pre + 'dl_linegraph' || id == me.pre + 'dl_scatterplot' || id == me.pre + 'dl_ligplot' || id == me.pre + 'dl_contactmap' || id == me.pre + 'dl_2ddiagram' || id == me.pre + 'dl_alignerrormap') {
61275
+ else if(id == me.pre + 'dl_linegraph' || id == me.pre + 'dl_scatterplot' || id == me.pre + 'dl_ligplot' || id == me.pre + 'dl_contactmap' || id == me.pre + 'dl_alignerrormap') {
61262
61276
  let oriWidth =(status.bTwoddgmInit2 || status.bSetsInit2) ?(me.htmlCls.WIDTH - twoddgmWidth)/2 : me.htmlCls.WIDTH / 2;
61263
61277
  let ratio = $("#" + id).width() / oriWidth;
61264
61278
 
@@ -61278,10 +61292,6 @@ class Dialog {
61278
61292
  let width = ic.contactmapWidth * ratio;
61279
61293
  $("#" + me.contactmapid).attr("width", width);
61280
61294
  }
61281
- // else if(id == me.pre + 'dl_2ddiagram') {
61282
- // let width = ic.twoddiagramWidth * ratio;
61283
- // $("#" + me.twoddiagramid).attr("width", width);
61284
- // }
61285
61295
  else if(id == me.pre + 'dl_alignerrormap') {
61286
61296
  let width = ic.alignerrormapWidth * ratio;
61287
61297
  $("#" + me.alignerrormapid).attr("width", width);
@@ -61418,7 +61428,7 @@ class Dialog {
61418
61428
  let width = 400, height = 150;
61419
61429
  let twoddgmWidth = me.htmlCls.width2d + 20;
61420
61430
 
61421
- if(id === me.pre + 'dl_selectannotations' || id === me.pre + 'dl_graph' || id === me.pre + 'dl_linegraph' || id === me.pre + 'dl_scatterplot' || id === me.pre + 'dl_rmsdplot' || id === me.pre + 'dl_hbondplot' || id === me.pre + 'dl_ligplot' || id === me.pre + 'dl_contactmap' || id === me.pre + 'dl_2ddiagram' || id === me.pre + 'dl_alignerrormap' || id === me.pre + 'dl_interactionsorted' || id === me.pre + 'dl_alignment') {
61431
+ if(id === me.pre + 'dl_selectannotations' || id === me.pre + 'dl_graph' || id === me.pre + 'dl_linegraph' || id === me.pre + 'dl_scatterplot' || id === me.pre + 'dl_rmsdplot' || id === me.pre + 'dl_hbondplot' || id === me.pre + 'dl_ligplot' || id === me.pre + 'dl_contactmap' || id === me.pre + 'dl_2ddiagram' || id === me.pre + 'dl_rnacanvas' || id === me.pre + 'dl_alignerrormap' || id === me.pre + 'dl_interactionsorted' || id === me.pre + 'dl_alignment') {
61422
61432
  $( "#" + id ).show();
61423
61433
  $( "#" + id + "_nb").show();
61424
61434
  $( "#" + id + "_title").html(title);
@@ -61463,11 +61473,6 @@ class Dialog {
61463
61473
 
61464
61474
  $("#" + me.contactmapid).attr("width", width);
61465
61475
  }
61466
- // else if(id == me.pre + 'dl_2ddiagram') {
61467
- // let width = ic.twoddiagramWidth * ratio;
61468
-
61469
- // $("#" + me.twoddiagramid).attr("width", width);
61470
- // }
61471
61476
  else if(id == me.pre + 'dl_alignerrormap') {
61472
61477
  let width = ic.alignerrormapWidth * ratio;
61473
61478
 
@@ -61568,7 +61573,7 @@ class SetDialog {
61568
61573
 
61569
61574
  me.svgid_ct = me.pre + "icn3d_cartoon";
61570
61575
 
61571
- let buttonStrTmp = '<button class="icn3d-commandTitle" style="-webkit-appearance:button; height:24px;background-color:#DDD;" id="';
61576
+ let buttonStrTmp = '<button class="icn3d-commandTitle" style="-webkit-appearance:button; height:24px;background-color:#DDD; margin:1px;" id="';
61572
61577
  let tmpStr = 'icn3d-node-text';
61573
61578
  html += me.htmlCls.divNowrapStr + "Dynamically generated for selected residues. <br>Nodes can be dragged or clicked.</div>";
61574
61579
  html += me.htmlCls.divNowrapStr + buttonStrTmp + me.svgid_ct + '_svg">SVG</button>' + me.htmlCls.space2;
@@ -62161,10 +62166,10 @@ class SetDialog {
62161
62166
 
62162
62167
  html += me.htmlCls.divStr + "dl_2ddgm_r2dt' class='" + dialogClass + "'>";
62163
62168
  html += this.addNotebookTitle('dl_2ddgm_r2dt', '2D Diagram for Nucleotides (R2DT)');
62164
- html += "1. Select a nucleotide chain to show R2DT diagram:<br>";
62169
+ html += "1. Select a nucleotide chain to show 2D diagram:<br>";
62165
62170
  html += "<select style='max-width:200px' id='" + me.pre + "atomsCustomNucleotide' size='5' style='min-width:130px;'>";
62166
62171
  html += "</select><br>";
62167
- html += me.htmlCls.buttonStr + "applyr2dt'>Show R2DT Diagram</button> <br><br>(Hints: Click on Residues in 2D to highlight in 3D. <br>Ctrl + click to select multiple residues.)<br>";
62172
+ html += "2. " + me.htmlCls.buttonStr + "applyr2dt'>R2DT Diagram</button>" + me.htmlCls.buttonStr + "applyfr3d' style='margin-left:12px'>2D Diagram with RNAcanvas</button><br><br>(Hints: Click on Residues in 2D to highlight in 3D. <br>Ctrl + click to select multiple residues.)<br>";
62168
62173
  html += "</div>";
62169
62174
 
62170
62175
  html += me.htmlCls.divStr + "dl_2ddgm_igdgm' class='" + dialogClass + "'>";
@@ -62503,8 +62508,31 @@ class SetDialog {
62503
62508
  html += "</div>";
62504
62509
 
62505
62510
  html += me.htmlCls.divStr + "dl_2ddiagram' style='background-color:white' class='" + dialogClass + "'>";
62506
- html += this.addNotebookTitle('dl_2ddiagram', '2D Diagram');
62507
- html += '<div id="' + me.pre + '2ddiagramDiv"></div>';
62511
+ html += this.addNotebookTitle('dl_2ddiagram', 'R2DT Diagram');
62512
+ html += '<div id="' + me.pre + '2ddiagramDiv"></div><br>';
62513
+ html += "<b>Download</b>: " + me.htmlCls.buttonStr + "r2dt_svg'>SVG</button>" + me.htmlCls.buttonStr + "r2dt_dotb' style='margin-left:12px'>Dot-Bracket</button>" + me.htmlCls.buttonStr + "r2dt_seq' style='margin-left:12px'>Sequence</button><br>";
62514
+ html += "</div>";
62515
+
62516
+ me.rnacanvasid = me.pre + 'rancanvas';
62517
+ html += me.htmlCls.divStr + "dl_rnacanvas' style='background-color:white' class='" + dialogClass + "'>";
62518
+ html += this.addNotebookTitle('dl_rnacanvas', '2D Diagram with RNAcanvas');
62519
+
62520
+ me.lwTypes = ['cWW', 'tWW', 'cWH', 'tWH', 'cWS', 'tWS', 'cHH', 'tHH', 'cHS', 'tHS', 'cSS', 'tSS']; // exclude 'cWW'
62521
+ html += "<table><tr><td>Show non-nested BPs:<br>";
62522
+ html += me.htmlCls.divNowrapStr + "<select id='" + me.pre + "basepairType' multiple size='2' style='min-width:130px;'>";
62523
+ html += "<option value='' selected>None</option>";
62524
+ html += "<option value='" + me.lwTypes.join(',') + "'>All</option>";
62525
+ for(let i = 0, il = me.lwTypes.length; i < il; i++) {
62526
+ let name = me.lwTypes[i];
62527
+ html += "<option value='" + name + "'>" + name + "</option>";
62528
+ }
62529
+ html += "</select></td><td valign='top'>";
62530
+
62531
+ html += me.htmlCls.space2 + buttonStrTmp + me.rnacanvasid + '_wconly">Show Only Nested BPs</button><br>';
62532
+ html += me.htmlCls.space2 + buttonStrTmp + me.rnacanvasid + '_dotb">Download Dot-Bracket</button><br>';
62533
+ html += me.htmlCls.space2 + buttonStrTmp + me.rnacanvasid + '_fr3d">FR3D Basepairs</button></td></tr></table><br>';
62534
+
62535
+ html += '<div id="' + me.pre + 'rnacanvasDiv"></div>';
62508
62536
  html += "</div>";
62509
62537
 
62510
62538
  html += me.htmlCls.divStr + "dl_alignerrormap' style='background-color:white' class='" + dialogClass + "'>";
@@ -65763,10 +65791,22 @@ class Events {
65763
65791
  //if(!me.cfg.notebook) dialog.dialog( "close" );
65764
65792
 
65765
65793
  let chainid = $("#" + ic.pre + "atomsCustomNucleotide").val();
65794
+ ic.r2dt_chainid = chainid;
65766
65795
 
65767
65796
  await ic.diagram2dCls.drawR2dt(chainid);
65768
65797
  thisClass.setLogCmd('diagram 2d nucleotide | ' + chainid, true);
65769
65798
  });
65799
+
65800
+ me.myEventCls.onIds("#" + me.pre + "applyfr3d", "click", async function(e) { let ic = me.icn3d;
65801
+ e.preventDefault();
65802
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
65803
+
65804
+ let chainid = $("#" + ic.pre + "atomsCustomNucleotide").val();
65805
+
65806
+ await ic.diagram2dCls.drawRnacanvas(chainid);
65807
+ thisClass.setLogCmd('diagram 2d fr3d | ' + chainid, true);
65808
+ });
65809
+
65770
65810
  me.myEventCls.onIds("#" + me.pre + "applyigdgm", "click", async function(e) { let ic = me.icn3d;
65771
65811
  e.preventDefault();
65772
65812
  //if(!me.cfg.notebook) dialog.dialog( "close" );
@@ -65917,6 +65957,57 @@ class Events {
65917
65957
  thisClass.setLogCmd("cartoon label " + className, true);
65918
65958
  });
65919
65959
 
65960
+ me.myEventCls.onIds("#" + me.rnacanvasid + "_wconly", "click", function(e) { me.icn3d;
65961
+ e.preventDefault();
65962
+
65963
+ $('#' + me.pre + 'basepairType').val($('#' + me.pre + 'basepairType option:first').val()).trigger('change');
65964
+ });
65965
+ me.myEventCls.onIds("#" + me.rnacanvasid + "_svg", "click", function(e) { let ic = me.icn3d;
65966
+ e.preventDefault();
65967
+
65968
+ ic.saveFileCls.saveSvg("rnacanvasSvg", ic.inputid + "_rnacanvas.svg");
65969
+ });
65970
+ me.myEventCls.onIds("#" + me.rnacanvasid + "_dotb", "click", function(e) { let ic = me.icn3d;
65971
+ e.preventDefault();
65972
+
65973
+ ic.saveFileCls.saveFile(ic.inputid + "_dot_bracket.txt", "text", [ic.dot_bracket]);
65974
+ });
65975
+
65976
+ me.myEventCls.onIds("#" + me.rnacanvasid + "_fr3d", "click", function(e) { let ic = me.icn3d;
65977
+ e.preventDefault();
65978
+
65979
+ let url = 'https://rna.bgsu.edu/rna3dhub/pdb/' + Object.keys(ic.structures)[0] + '/interactions/fr3d/basepairs/';
65980
+
65981
+ window.open(url, '_blank');
65982
+ });
65983
+
65984
+ me.myEventCls.onIds("#" + me.pre + "r2dt_svg", "click", function(e) { let ic = me.icn3d;
65985
+ e.preventDefault();
65986
+
65987
+ let bClassName = true;
65988
+ ic.saveFileCls.saveSvg("rnaTopoSvg", ic.r2dt_chainid + "_r2dt.svg", undefined, undefined, bClassName);
65989
+ });
65990
+ me.myEventCls.onIds("#" + me.pre + "r2dt_dotb", "click", async function(e) { let ic = me.icn3d;
65991
+ e.preventDefault();
65992
+
65993
+ let chainid = $("#" + ic.pre + "atomsCustomNucleotide").val();
65994
+ let result = await ic.diagram2dCls.getDotbracket(chainid);
65995
+ ic.saveFileCls.saveFile(chainid + "_dot_bracket.txt", "text", [result.dotb]);
65996
+ });
65997
+
65998
+ me.myEventCls.onIds("#" + me.pre + "r2dt_seq", "click", function(e) { let ic = me.icn3d;
65999
+ e.preventDefault();
66000
+
66001
+ let chainid = $("#" + ic.pre + "atomsCustomNucleotide").val();
66002
+ let seq = '';
66003
+ for(let i = 0; i < ic.chainsSeq[chainid].length; ++i) {
66004
+ seq += ic.chainsSeq[chainid][i].name;
66005
+ }
66006
+
66007
+ ic.saveFileCls.saveFile(chainid + "_seq.txt", "text", [seq]);
66008
+ });
66009
+
66010
+
65920
66011
  me.myEventCls.onIds("#" + me.linegraphid + "_svg", "click", function(e) { let ic = me.icn3d;
65921
66012
  e.preventDefault();
65922
66013
 
@@ -78084,7 +78175,7 @@ class Line$1 {
78084
78175
  let radius = (line.radius) ? line.radius : ic.lineRadius;
78085
78176
  let opacity = (line.opacity) ? line.opacity : 1.0;
78086
78177
 
78087
- let colorStr = '#' + line.color.replace(/\#/g, '');
78178
+ let colorStr = (line.color) ? '#' + line.color.replace(/\#/g, '') : '#000';
78088
78179
 
78089
78180
  let color = me.parasCls.thr(colorStr);
78090
78181
 
@@ -80120,6 +80211,24 @@ class CartoonNucl {
80120
80211
  let currentChain, currentResi, currentO3;
80121
80212
  let prevOO = null;
80122
80213
 
80214
+ // add one extra residue for highlighting one residue
80215
+ if(bHighlight === 1) {
80216
+ let residueArray= ic.resid2specCls.atoms2residues(Object.keys(atomlist));
80217
+
80218
+ if(residueArray.length == 1) {
80219
+ let ncbiresid = ic.resid2ncbi[residueArray[0]];
80220
+ ic.firstAtomObjCls.getFirstAtomObj(atomlist);
80221
+ let ncbiresi = ncbiresid.substr(ncbiresid.lastIndexOf('_') + 1);
80222
+ let ncbiresid2 = ncbiresid.substr(0, ncbiresid.lastIndexOf('_')) + '_' + (parseInt(ncbiresi) + 1).toString();
80223
+ let residueid2 = ic.ncbi2resid[ncbiresid2];
80224
+
80225
+ if(ic.residues.hasOwnProperty(residueid2)) {
80226
+ let atomsAdjust = me.hashUtilsCls.hash2Atoms(ic.residues[residueid2], ic.atoms);
80227
+ atomlist = me.hashUtilsCls.unionHash(atomlist, atomsAdjust);
80228
+ }
80229
+ }
80230
+ }
80231
+
80123
80232
  for (i in atomlist) {
80124
80233
  let atom = atomlist[i];
80125
80234
  if (atom === undefined) continue;
@@ -84064,7 +84173,7 @@ class ApplyMissingRes {
84064
84173
  line.serial1 = ic.missingResResid2serial[resid0 + ',' + resid1];
84065
84174
  line.serial2 = ic.missingResResid2serial[resid1 + ',' + resid0];
84066
84175
 
84067
- line.color = (ic.atoms[line.serial1]) ? "#" + ic.atoms[line.serial1].color.getHexString() : undefined;
84176
+ line.color = (ic.atoms[line.serial1] && ic.atoms[line.serial1].color) ? "#" + ic.atoms[line.serial1].color.getHexString() : undefined;
84068
84177
 
84069
84178
  line.radius = ic.coilWidth;
84070
84179
 
@@ -86391,7 +86500,7 @@ class Instancing {
86391
86500
  }
86392
86501
  }
86393
86502
 
86394
- drawSymmetryMatesNoInstancing() { let ic = this.icn3d; ic.icn3dui;
86503
+ drawSymmetryMatesNoInstancing() { let ic = this.icn3d, me = ic.icn3dui;
86395
86504
  if (ic.biomtMatrices === undefined || ic.biomtMatrices.length == 0) return;
86396
86505
  let cnt = 1; // itself
86397
86506
  let centerSum = ic.center.clone();
@@ -86409,7 +86518,7 @@ class Instancing {
86409
86518
  if (mat === undefined) continue;
86410
86519
 
86411
86520
  // skip itself
86412
- if(mat.equals(identity)) continue;
86521
+ if(me.utilsCls.compMatrix(mat, identity, 16)) continue;
86413
86522
 
86414
86523
  let symmetryMate;
86415
86524
 
@@ -86685,7 +86794,7 @@ class Instancing {
86685
86794
  }
86686
86795
  }
86687
86796
 
86688
- drawSymmetryMatesInstancing() { let ic = this.icn3d; ic.icn3dui;
86797
+ drawSymmetryMatesInstancing() { let ic = this.icn3d, me = ic.icn3dui;
86689
86798
  if (ic.biomtMatrices === undefined || ic.biomtMatrices.length == 0) return;
86690
86799
  let cnt = 1; // itself
86691
86800
  let centerSum = ic.center.clone();
@@ -86707,10 +86816,13 @@ class Instancing {
86707
86816
  let mat = ic.biomtMatrices[i];
86708
86817
  if (mat === undefined) continue;
86709
86818
 
86710
- let matArray = mat.toArray();
86819
+ let matArray = mat.toArray().map(x => parseFloat(x)); // some values are string and others are number
86820
+ mat.fromArray(matArray);
86711
86821
 
86712
86822
  // skip itself
86713
- if(mat.equals(identity)) continue;
86823
+ //if(mat.equals(identity)) continue; // equals seemed to have some problem in comparing two matrices
86824
+ let bEqual = me.utilsCls.compMatrix(mat, identity, 16);
86825
+ if(bEqual) continue;
86714
86826
 
86715
86827
  ic.matricesElements1.push(matArray[0], matArray[1], matArray[2], matArray[3]);
86716
86828
  ic.matricesElements2.push(matArray[4], matArray[5], matArray[6], matArray[7]);
@@ -86718,7 +86830,7 @@ class Instancing {
86718
86830
  ic.matricesElements4.push(matArray[12], matArray[13], matArray[14], matArray[15]);
86719
86831
 
86720
86832
  let center = ic.center.clone();
86721
- center.applyMatrix4(mat);
86833
+ center.applyMatrix4(mat);
86722
86834
  centerSum.add(center);
86723
86835
 
86724
86836
  ++cnt;
@@ -86944,7 +87056,7 @@ class Alternate {
86944
87056
  }
86945
87057
 
86946
87058
  ic.setColorCls.applyPrevColor();
86947
-
87059
+
86948
87060
  if(ic.biomtMatrices !== undefined && ic.biomtMatrices.length > 1) {
86949
87061
  if(ic.bAssembly && Object.keys(ic.structures).length == 1 && ((me.cfg.mmdbid === undefined && me.cfg.bu == 1)
86950
87062
  || (me.cfg.mmdbid !== undefined && me.cfg.bu == 1 && Object.keys(ic.atoms).length * ic.biomtMatrices.length > ic.maxatomcnt)) ) {
@@ -86972,6 +87084,7 @@ class Alternate {
86972
87084
  }
86973
87085
 
86974
87086
  this.applyTransformation(ic._zoomFactor, ic.mouseChange, ic.quaternion);
87087
+
86975
87088
  this.render(bVrAr);
86976
87089
  }
86977
87090
  //ic.impostorCls.clearImpostors();
@@ -97706,6 +97819,8 @@ class ShowAnno {
97706
97819
  ic.maxAnnoLength = ic.maxAnnoLengthOri;
97707
97820
  }
97708
97821
 
97822
+ ic.nucleotide_chainid = nucleotide_chainid;
97823
+
97709
97824
  return {'nucleotide_chainid': nucleotide_chainid, 'chemical_chainid': chemical_chainid, 'chemical_set': chemical_set};
97710
97825
  }
97711
97826
 
@@ -102915,14 +103030,23 @@ class DrawGraph {
102915
103030
  }).strength(function(d) { return 0.4; }))
102916
103031
  .force("x", d3v4.forceX(parentWidth / 2).strength(function(d) { return 0.02; }));
102917
103032
  } else if (me.htmlCls.force == 3) { // circle
103033
+ // me.htmlCls.simulation.force("r", d3v4.forceRadial(function(d) {
103034
+ // if (d.s == 'a') {
103035
+ // return 200;
103036
+ // } else {
103037
+ // return 100;
103038
+ // }
103039
+
103040
+ // }, parentWidth / 2, parentHeight / 2).strength(function(d) { return 0.8; }));
103041
+
102918
103042
  me.htmlCls.simulation.force("r", d3v4.forceRadial(function(d) {
102919
103043
  if (d.s == 'a') {
102920
- return 200;
103044
+ return 60; //200;
102921
103045
  } else {
102922
- return 100;
103046
+ return 30; //100;
102923
103047
  }
102924
103048
 
102925
- }, parentWidth / 2, parentHeight / 2).strength(function(d) { return 0.8; }));
103049
+ }, parentWidth / 2, parentHeight / 2).strength(function(d) { return 0.1; }));
102926
103050
  } else if (me.htmlCls.force == 4) ;
102927
103051
 
102928
103052
  me.htmlCls.simulation
@@ -106208,7 +106332,8 @@ class MmcifParser {
106208
106332
  if(ic.bAssemblyUseAsu) {
106209
106333
  for(let i = 0, il = data.assembly.length; i < il; ++i) {
106210
106334
  let mat4 = new Matrix4$1();
106211
- mat4.fromArray(data.assembly[i]);
106335
+ let tmpArray = data.assembly[i].map(x => parseFloat(x)); // some values are string and others are number
106336
+ mat4.fromArray(tmpArray);
106212
106337
 
106213
106338
  // sometimes an extra matrix as included, e.g., PDb ID 2GTL
106214
106339
  if(i == 0 && data.assembly[i][0] != 1) continue;
@@ -106288,14 +106413,14 @@ class MmcifParser {
106288
106413
  async loadMultipleMmcifData(data, mmcifid, bAppend) { let ic = this.icn3d; ic.icn3dui;
106289
106414
  let bText = true;
106290
106415
  ic.loadCIFCls.loadCIF(data, mmcifid, bText, bAppend);
106291
-
106416
+
106292
106417
  if(Object.keys(ic.structures).length > 1) {
106293
106418
  ic.opts['color'] = 'structure';
106294
106419
  }
106295
106420
 
106296
106421
  ic.opmParserCls.modifyUIMapAssembly();
106297
106422
 
106298
- ic.pdbParserCls.addSecondary(bAppend);
106423
+ await ic.pdbParserCls.addSecondary(bAppend);
106299
106424
 
106300
106425
  // ic.setStyleCls.setAtomStyleByOptions(ic.opts);
106301
106426
  // ic.setColorCls.setColorByOptions(ic.opts, ic.atoms);
@@ -108177,7 +108302,8 @@ class PdbParser {
108177
108302
  // DSSP only works for structures with all atoms. The Calpha only structures didn't work
108178
108303
  //if(!ic.bSecondaryStructure && !bCalphaOnly) {
108179
108304
  let bCalcSecondary = false;
108180
- if(ic.bSecondaryStructure && Object.keys(ic.structures).length == 1) {
108305
+ // if(ic.bSecondaryStructure && Object.keys(ic.structures).length == 1) {
108306
+ if(ic.bSecondaryStructure) {
108181
108307
  bCalcSecondary = false;
108182
108308
  }
108183
108309
  else 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) {
@@ -108185,7 +108311,7 @@ class PdbParser {
108185
108311
  }
108186
108312
 
108187
108313
  // if(!ic.bSecondaryStructure && Object.keys(ic.proteins).length > 0) {
108188
- if((!ic.bSecondaryStructure || bCalcSecondary) && Object.keys(ic.proteins).length > 0 && !bNoDssp) {
108314
+ if((!ic.bSecondaryStructure || bCalcSecondary) && Object.keys(ic.proteins).length > 0 && !bNoDssp) {
108189
108315
  await this.applyCommandDssp(bAppend);
108190
108316
  }
108191
108317
  else {
@@ -108230,7 +108356,7 @@ class PdbParser {
108230
108356
 
108231
108357
  if(me.cfg.rotate !== undefined) ic.resizeCanvasCls.rotStruc(me.cfg.rotate, true);
108232
108358
 
108233
- if(bAppend && !me.bNode) {
108359
+ if(bAppend && Object.keys(ic.structures).length == 1 && !me.bNode) {
108234
108360
  // show all
108235
108361
  ic.definedSetsCls.setModeAndDisplay('all');
108236
108362
  }
@@ -116307,9 +116433,9 @@ class LoadCIF {
116307
116433
  if(struct_oper_id == "X0") continue;
116308
116434
 
116309
116435
  if (ic.biomtMatrices[i] == undefined) ic.biomtMatrices[i] = new Matrix4$1().identity();
116310
- ic.biomtMatrices[i].set(m11Array.getString(i), m12Array.getString(i), m13Array.getString(i), m14Array.getString(i),
116311
- m21Array.getString(i), m22Array.getString(i), m23Array.getString(i), m24Array.getString(i),
116312
- m31Array.getString(i), m32Array.getString(i), m33Array.getString(i), m34Array.getString(i),
116436
+ ic.biomtMatrices[i].set(parseFloat(m11Array.getString(i)), parseFloat(m12Array.getString(i)), parseFloat(m13Array.getString(i)), parseFloat(m14Array.getString(i)),
116437
+ parseFloat(m21Array.getString(i)), parseFloat(m22Array.getString(i)), parseFloat(m23Array.getString(i)), parseFloat(m24Array.getString(i)),
116438
+ parseFloat(m31Array.getString(i)), parseFloat(m32Array.getString(i)), parseFloat(m33Array.getString(i)), parseFloat(m34Array.getString(i)),
116313
116439
  0, 0, 0, 1);
116314
116440
  }
116315
116441
 
@@ -116341,6 +116467,44 @@ class LoadCIF {
116341
116467
  ic.pmid = block.getCategory("_citation").getColumn("pdbx_database_id_PubMed").getString(0);
116342
116468
  }
116343
116469
 
116470
+ // retrieve RNA pair info
116471
+ let pairInfo = block.getCategory("_ndb_base_pair_list");
116472
+
116473
+ if(pairInfo) {
116474
+ let chainArray2, pairidArray, pos1Array, pos2Array, resn1Array, resn2Array;
116475
+ chainArray2 = pairInfo.getColumn("asym_id_1");
116476
+ pairidArray = pairInfo.getColumn("base_pair_id");
116477
+ pos1Array = pairInfo.getColumn("seq_id_1");
116478
+ pos2Array = pairInfo.getColumn("seq_id_2");
116479
+ resn1Array = pairInfo.getColumn("comp_id_1");
116480
+ resn2Array = pairInfo.getColumn("comp_id_2");
116481
+ let pairSize = pairInfo.rowCount;
116482
+
116483
+ let annoInfo = block.getCategory("_ndb_base_pair_annotation");
116484
+
116485
+ let pairidArray2, typeArray;
116486
+ pairidArray2 = annoInfo.getColumn("base_pair_id");
116487
+ typeArray = annoInfo.getColumn("l-w_family");
116488
+
116489
+ ic.chain2pairs_resns_lw = {};
116490
+ for(let i = 0; i < pairSize; ++i) {
116491
+ if(pairidArray.getString(i) == pairidArray2.getString(i)) {
116492
+ let chain = chainArray2.getString(i);
116493
+ let pos1 = pos1Array.getString(i);
116494
+ let pos2 = pos2Array.getString(i);
116495
+ let resn1 = resn1Array.getString(i);
116496
+ let resn2 = resn2Array.getString(i);
116497
+ let lwtype = typeArray.getString(i);
116498
+ if(!ic.chain2pairs_resns_lw[chain]) ic.chain2pairs_resns_lw[chain] = [];
116499
+ ic.chain2pairs_resns_lw[chain].push(pos1);
116500
+ ic.chain2pairs_resns_lw[chain].push(pos2);
116501
+ ic.chain2pairs_resns_lw[chain].push(resn1);
116502
+ ic.chain2pairs_resns_lw[chain].push(resn2);
116503
+ ic.chain2pairs_resns_lw[chain].push(lwtype);
116504
+ }
116505
+ }
116506
+ }
116507
+
116344
116508
  // Retrieve the table corresponding to the atom_site category, which delineates atomic constituents
116345
116509
  let atom_site = block.getCategory("_atom_site");
116346
116510
  let atomSize = atom_site.rowCount;
@@ -119663,6 +119827,7 @@ class DefinedSets {
119663
119827
  });
119664
119828
 
119665
119829
  let bFoundNucleotide = false, bFoundProtein = false;
119830
+ let cnt = 0;
119666
119831
  for(let i = 0, il = nameArray.length; i < il; ++i) {
119667
119832
  let name = nameArray[i];
119668
119833
 
@@ -119687,16 +119852,22 @@ class DefinedSets {
119687
119852
 
119688
119853
  if(bNucleotide && atom) {
119689
119854
  // Handle nucleotide-specific logic
119690
- if(ic.nucleotides.hasOwnProperty(atom.serial) && name != 'nucleotides' && !ic.structures.hasOwnProperty(name)) {
119691
- html += "<option value='" + name + "' style='color:#" + color + "'>" + name + "</option>";
119855
+ if(ic.nucleotides.hasOwnProperty(atom.serial) && name.split('_').length == 2 && !ic.structures.hasOwnProperty(name)) {
119856
+ let selectStr = (cnt == 0) ? "selected" : "";
119857
+
119858
+ html += "<option value='" + name + "' style='color:#" + color + "' " + selectStr + ">" + name + "</option>";
119692
119859
  bFoundNucleotide = true;
119860
+ ++cnt;
119693
119861
  }
119694
119862
  }
119695
119863
  else if(bProtein && atom) {
119696
119864
  // Handle protein-specific logic
119697
- if(ic.proteins.hasOwnProperty(atom.serial) && name != 'proteins' && !ic.structures.hasOwnProperty(name)) {
119698
- html += "<option value='" + name + "' style='color:#" + color + "'>" + name + "</option>";
119865
+ if(ic.proteins.hasOwnProperty(atom.serial) && name.split('_').length == 2 && !ic.structures.hasOwnProperty(name)) {
119866
+ let selectStr = (cnt == 0) ? "selected" : "";
119867
+
119868
+ html += "<option value='" + name + "' style='color:#" + color + "' " + selectStr + ">" + name + "</option>";
119699
119869
  bFoundProtein = true;
119870
+ ++cnt;
119700
119871
  }
119701
119872
  }
119702
119873
  else {
@@ -119706,6 +119877,7 @@ class DefinedSets {
119706
119877
  else {
119707
119878
  html += "<option value='" + name + "' style='color:#" + color + "'>" + name + "</option>";
119708
119879
  }
119880
+ ++cnt;
119709
119881
  }
119710
119882
  }
119711
119883
 
@@ -120851,15 +121023,31 @@ class LoadScript {
120851
121023
  }
120852
121024
  else if(command.indexOf('diagram 2d nucleotide') == 0) {
120853
121025
  let paraArray = command.split(' | ');
120854
- let chainid = paraArray[1];
121026
+ let pos = command.lastIndexOf(' ');
121027
+ let chainid = (paraArray.length == 2) ? paraArray[1] : command.substr(pos + 1);
120855
121028
 
120856
121029
  ic.bRender = true;
120857
121030
  await ic.diagram2dCls.drawR2dt(chainid);
120858
121031
  ic.bRender = false;
120859
121032
  }
121033
+ else if(command.indexOf('diagram 2d fr3d') == 0) {
121034
+ let paraArray = command.split(' | ');
121035
+ let pos = command.lastIndexOf(' ');
121036
+ let chainid = (paraArray.length == 2) ? paraArray[1] : command.substr(pos + 1);
121037
+
121038
+ ic.bRender = true;
121039
+ await ic.diagram2dCls.drawRnacanvas(chainid);
121040
+ ic.bRender = false;
121041
+ }
121042
+ else if(command.indexOf('update rnacanvas') == 0) {
121043
+ let paraArray = command.split(' ');
121044
+ let nonWC = (paraArray.length == 3) ? paraArray[2] : '';
121045
+ ic.diagram2dCls.updateRnacanvas(nonWC);
121046
+ }
120860
121047
  else if(command.indexOf('diagram 2d ig') == 0) {
120861
121048
  let paraArray = command.split(' | ');
120862
- let chainid = paraArray[1];
121049
+ let pos = command.lastIndexOf(' ');
121050
+ let chainid = (paraArray.length == 2) ? paraArray[1] : command.substr(pos + 1);
120863
121051
 
120864
121052
  ic.bRender = true;
120865
121053
  await ic.diagram2dCls.drawIgdgm(chainid);
@@ -121979,7 +122167,7 @@ class SelectByCommand {
121979
122167
  residueAtomArray = Object.keys(atomHash);
121980
122168
  }
121981
122169
 
121982
- if(commandname != "") {
122170
+ if(!commandname) {
121983
122171
  ic.selectionCls.addCustomSelection(residueAtomArray, commandname, commanddesc, select, bSelectResidues);
121984
122172
 
121985
122173
  let nameArray = [commandname];
@@ -128175,55 +128363,42 @@ class Diagram2d {
128175
128363
  thisClass.clickNode(this);
128176
128364
  });
128177
128365
 
128178
- // event for R2DT
128179
- //document.addEventListener('click', (event) => {
128180
- $(document).on("click", "r2dt-web", function(e) { let ic = thisClass.icn3d;
128181
- // The 2nd element in the path is the actual clicked g element
128182
- const path = e.originalEvent.composedPath();
128183
- const clickedElement = path[1];
128184
- let titleElem = clickedElement.querySelector('title');
128366
+ $(document).on("change", "#" + me.pre + "basepairType", function(e) { thisClass.icn3d;
128367
+ let nonWC = $("#" + me.pre + "basepairType").val().join(',');
128185
128368
 
128186
- if(titleElem) {
128187
- titleElem.style.cursor = "pointer";
128188
- let title = titleElem.textContent; // e.g., 14 (position.label in template: 14.A)
128189
- let textArray = title.split(' ');
128190
- let position_resn = textArray[textArray.length - 1].split('.');
128191
- let pos = position_resn[0];
128192
- let resn = position_resn[1].substr(0, position_resn[1].length - 1);
128369
+ thisClass.updateRnacanvas(nonWC);
128370
+ me.htmlCls.clickMenuCls.setLogCmd('update rnacanvas ' + nonWC, true);
128371
+ });
128193
128372
 
128194
- let resid = ic.ncbi2resid[ic.r2dt_chainid + '_' + pos];
128195
- let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]);
128373
+ $(document).on("from_rnacanvas", function(event, data) {
128374
+ let pos_resn = data.split('_');
128375
+ let resn = pos_resn[1];
128196
128376
 
128197
- if(!atom) {
128198
- var aaa = 1; //alert("This residue has no 3D coordinates...");
128199
- }
128200
- else {
128201
- let oneLetterRes = me.utilsCls.residueName2Abbr(atom.resn);
128377
+ let resid = ic.ncbi2resid[ic.rnacanvas_chainid + '_' + pos_resn[0]];
128378
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]);
128202
128379
 
128203
- let realResn = (resn == 'T') ? 'U' : resn;
128380
+ if(!atom) {
128381
+ var aaa = 1; //alert('This residue has no 3D coordinates...');
128382
+ }
128383
+ else {
128384
+ let oneLetterRes = me.utilsCls.residueName2Abbr(atom.resn);
128204
128385
 
128205
- if(resn != oneLetterRes && realResn != oneLetterRes) {
128206
- var aaa = 1; //alert("The residue number in R2DT didn't match that in 3D view...");
128386
+ if(resn != oneLetterRes) {
128387
+ console.log('The residue name in 2D ' + resn + ' did not match that in 3D view ' + oneLetterRes + '...');
128388
+ }
128389
+ //else {
128390
+ // highlight the selected residue
128391
+ if(ic.bCtrl || ic.bShift) {
128392
+ ic.hAtoms = me.hashUtilsCls.unionHash(ic.hAtoms, ic.residues[resid]);
128207
128393
  }
128208
128394
  else {
128209
- // highlight the selected residue
128210
- if(ic.bCtrl || ic.bShift) {
128211
- ic.hAtoms = me.hashUtilsCls.unionHash(ic.hAtoms, ic.residues[resid]);
128212
- }
128213
- else {
128214
- ic.hAtoms = ic.residues[resid];
128215
- }
128216
-
128217
- ic.hlUpdateCls.showHighlight();
128395
+ ic.hAtoms = ic.residues[resid];
128218
128396
  }
128219
- }
128220
128397
 
128221
- // highlight the selected residue in 2D
128222
- let textElem = clickedElement.querySelector('text');
128223
- textElem.setAttribute("stroke", "#f8b84e");
128224
- textElem.setAttribute("stroke-width", "0.5px");
128398
+ ic.hlUpdateCls.showHighlight();
128399
+ //}
128225
128400
  }
128226
- });
128401
+ });
128227
128402
  }
128228
128403
 
128229
128404
  clickNode(node) { let ic = this.icn3d, me = ic.icn3dui;
@@ -128450,33 +128625,473 @@ class Diagram2d {
128450
128625
  }
128451
128626
 
128452
128627
  async drawR2dt(chainid) { let ic = this.icn3d, me = ic.icn3dui;
128453
- ic.r2dt_chainid = chainid;
128628
+ ic.bAddedCursors = false;
128454
128629
 
128455
- let url = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi?chainid2rnaid=" + chainid;
128630
+ let pos = chainid.lastIndexOf('_');
128631
+ let pdbid = chainid.substr(0, pos);
128632
+ let chain = chainid.substr(pos + 1);
128456
128633
 
128457
- let data = await me.getAjaxPromise(url, 'jsonp');
128634
+ //https://9c5d031c.na-hackathon-2026.pages.dev/api.json
128635
+ //https://www.ebi.ac.uk/pdbe/static/entry/1ffk_2_9.json, or 1ffk_1_0.json [pdbid_molid_chain]
128636
+ if(!ic.chainid2molid) {
128637
+ ic.chainid2molid = {};
128638
+
128639
+ await ic.showAnnoCls.showAnnotations();
128640
+ let molidTmp = 1;
128641
+ for(let id in ic.nucleotide_chainid) {
128642
+ ic.chainid2molid[id] = molidTmp;
128643
+ ++molidTmp;
128644
+ }
128645
+ }
128646
+
128647
+ let molid = ic.chainid2molid[chainid] ? ic.chainid2molid[chainid] : 1;
128648
+
128649
+ let url = "https://www.ebi.ac.uk/pdbe/static/entry/" + pdbid.toLowerCase() + "_" + molid + "_" + chain + ".json";
128650
+ let apiData = await me.getAjaxPromise(url, 'json', undefined, 'The chain ' + chainid + ' with molid ' + molid + ' has no R2DT information in PDBe...');
128651
+
128652
+ //https://9c5d031c.na-hackathon-2026.pages.dev/fr3d.json
128653
+ //https://www.ebi.ac.uk/pdbe/static/entry/1ffk_9_basepair.json
128654
+ let url2 = "https://www.ebi.ac.uk/pdbe/static/entry/" + pdbid.toLowerCase() + "_" + chain + "_basepair.json";
128655
+ let fr3dData = await me.getAjaxPromise(url2, 'json', undefined, 'The chain ' + chainid + ' with molid ' + molid + ' has no FR3D information in PDBe...');
128458
128656
 
128459
128657
  let html = '';
128460
- if(data && data.rnaid) {
128461
- html += '<r2dt-web search=\'{"urs": "' + data.rnaid + '"}\' />';
128462
- html += '<script type="text/javascript" src="https://rnacentral.github.io/r2dt-web/dist/r2dt-web.js"></script>';
128463
- $("#" + me.pre + "2ddiagramDiv").html(html);
128464
- me.htmlCls.dialogCls.openDlg('dl_2ddiagram', 'Show R2DT Diagram for chain ' + chainid);
128658
+
128659
+ html += "<link rel='stylesheet' type='text/css' href='./script/pdb-rna-viewer-0.3.0.css'>\n";
128660
+ html += "<div id='pdb-rna-viewer' style='width: " + ($(window).width() / 2 - 150) + "px; height: " + ($(window).height() - 240) + "px'></div>\n";
128661
+ html += "<script type='text/javascript' src='./script/pdb-rna-viewer-plugin-0.3.0.js'></script>\n";
128662
+ html += "<script type='text/javascript'>\n";
128663
+ html += " var rnaPlugin = new PdbRnaViewerPlugin();\n";
128664
+ html += " rnaPlugin.render(\n";
128665
+ html += " document.getElementById('pdb-rna-viewer'),\n";
128666
+ html += " {\n";
128667
+ html += " pdbId: '" + pdbid.toLowerCase() + "',\n";
128668
+ html += " entityId: '1',\n";
128669
+ html += " chainId: '" + chain + "',\n";
128670
+ html += " subscribeEvents: true,\n";
128671
+ html += " apiData: " + JSON.stringify(apiData) + ",\n";
128672
+ html += " FR3DData: " + JSON.stringify(fr3dData) + ",\n";
128673
+ html += " theme: { unobservedColor: '#bbbbbb' },\n";
128674
+ html += " }\n";
128675
+ html += " );\n";
128676
+ html += "</script>\n";
128677
+
128678
+ $("#" + me.pre + "2ddiagramDiv").html(html);
128679
+
128680
+ setTimeout(function(){
128681
+ // grey out residues without 3D coordinates
128682
+ const unobserved = apiData.unobserved_label_seq_ids || [];
128683
+ const PDB_LOWER = pdbid.toLowerCase();
128684
+ unobserved.forEach((seqId) => {
128685
+ document
128686
+ .querySelectorAll(`text.rnaview_${PDB_LOWER}_${seqId}`)
128687
+ .forEach((el) => { el.setAttribute('fill', '#bbbbbb');});
128688
+ });
128689
+
128690
+ // click 2D to show in 3D
128691
+ document.addEventListener('PDB.RNA.viewer.click', (ev) => {
128692
+ // $(document).on("PDB.RNA.viewer.click", function(ev, data) {
128693
+ let posArray = [];
128694
+ const d = ev.eventData || ev.detail || {};
128695
+ if (Array.isArray(d.label_seq_ids)) posArray = d.label_seq_ids;
128696
+ if (d.label_seq_id !== undefined && d.label_seq_id !== null) posArray = [d.label_seq_id];
128697
+
128698
+ let hAtoms = {};
128699
+ for(let i = 0, il = posArray.length; i < il; ++i) {
128700
+ let resid = ic.ncbi2resid[chainid + '_' + posArray[i]];
128701
+ // highlight the selected residue
128702
+ hAtoms = me.hashUtilsCls.unionHash(hAtoms, ic.residues[resid]);
128703
+ }
128704
+
128705
+ if(ic.bCtrl || ic.bShift) {
128706
+ ic.hAtoms = me.hashUtilsCls.unionHash(ic.hAtoms, hAtoms);
128707
+ }
128708
+ else {
128709
+ ic.hAtoms = hAtoms;
128710
+ }
128711
+
128712
+ ic.hlUpdateCls.showHighlight();
128713
+ });
128714
+
128715
+ // click 3D to highlight in 2D
128716
+ $(document).on("icn3d.pick.click", function(ev, data) {
128717
+ // get the residue position in the selection
128718
+ let ncbiresid = data;
128719
+ let pos = ncbiresid.substr(ncbiresid.lastIndexOf('_') + 1);
128720
+
128721
+ document.dispatchEvent(new CustomEvent('protvista-click', {
128722
+ detail: { start: pos, end: pos }
128723
+ }));
128724
+ });
128725
+
128726
+ $(document).on("icn3d.pick.mouseover", function(ev, data) {
128727
+ // get the residue position in the selection
128728
+ let ncbiresid = data;
128729
+ let pos = ncbiresid.substr(ncbiresid.lastIndexOf('_') + 1);
128730
+
128731
+ document.dispatchEvent(new CustomEvent('protvista-mouseover', {
128732
+ detail: { start: pos, end: pos }
128733
+ }));
128734
+ });
128735
+
128736
+ }, 1000);
128737
+
128738
+ me.htmlCls.dialogCls.openDlg('dl_2ddiagram', 'Show R2DT Diagram for chain ' + chainid);
128739
+ }
128740
+
128741
+ async getDotbracket(chainid) { let ic = this.icn3d, me = ic.icn3dui;
128742
+ let pos = chainid.lastIndexOf('_');
128743
+ let pdbid = chainid.substr(0, pos);
128744
+ let chain = chainid.substr(pos + 1);
128745
+
128746
+ let result;
128747
+ if(ic.chain2pairs_resns_lw) {
128748
+ let pairs_resns_lw = ic.chain2pairs_resns_lw[chain];
128749
+ let pairs = [], lw2pairs = {};
128750
+
128751
+ for(let i = 0, il = pairs_resns_lw.length; i < il; i += 5) {
128752
+ let pos1 = pairs_resns_lw[i];
128753
+ let pos2 = pairs_resns_lw[i + 1];
128754
+ pairs_resns_lw[i + 2];
128755
+ pairs_resns_lw[i + 3];
128756
+ let lw = pairs_resns_lw[i + 4];
128757
+
128758
+ if(lw == 'cWW') {
128759
+ pairs.push([parseInt(pos1), parseInt(pos2)]);
128760
+ }
128761
+ else {
128762
+ if(!lw2pairs[lw]) lw2pairs[lw] = [];
128763
+ lw2pairs[lw].push(parseInt(pos1));
128764
+ lw2pairs[lw].push(parseInt(pos2));
128765
+ }
128766
+ }
128767
+
128768
+ result = this.pairs2dotbracket(pairs, lw2pairs, chainid);
128769
+ }
128770
+ else {
128771
+ let url = "https://rna.bgsu.edu/rna3dhub/pdb/" + pdbid + "/interactions/fr3d/basepairs/tsv";
128772
+
128773
+ let data = await me.getAjaxPromise(url, 'text');
128774
+ if(!data || data == 'Not a valid PDB id.') {
128775
+ var aaa = 1; //alert('The chain ' + chainid + ' has no basepair information in FR3D...');
128776
+ return;
128777
+ }
128778
+
128779
+ let ret2 = this.fr3d2pairs(data, chainid); //pairs_lw2pairs_annotations
128780
+ // annotations = ret2.anno;
128781
+ result = this.pairs2dotbracket(ret2.pairs, ret2.lw2pairs, chainid);
128782
+ }
128783
+
128784
+
128785
+ return result;
128786
+ }
128787
+
128788
+ fr3d2pairs(data, chainid) { let ic = this.icn3d; ic.icn3dui;
128789
+ let pos = chainid.lastIndexOf('_');
128790
+ let chain = chainid.substr(pos + 1);
128791
+
128792
+ let lines = data.split('\n');
128793
+
128794
+ let pairs = []; // 0-based, only for canonical base pairs
128795
+ let lw2pairs = {}; // 1-based, for non-canonical base pairs and base stacking interactions
128796
+ for (let i in lines) {
128797
+ let line = lines[i]; // e.g., 9CFN|1|A|A|2 cWW 9CFN|1|A|U|38
128798
+ let from_type_to = line.trim().split('\t');
128799
+ if(from_type_to.length != 3) continue;
128800
+
128801
+ let fromArray = from_type_to[0].split('|'), toArray = from_type_to[2].split('|');
128802
+ if(fromArray.length != 5 || toArray.length != 5) continue;
128803
+ if(fromArray[2] != chain || toArray[2] != chain) continue;
128804
+ let resi1 = fromArray[4], resi2 = toArray[4];
128805
+ let ncbiResid1 = ic.resid2ncbi[chainid + '_' + resi1], ncbiResid2 = ic.resid2ncbi[chainid + '_' + resi2];
128806
+ let pos1 = parseInt(ncbiResid1.substr(ncbiResid1.lastIndexOf('_') + 1)) - 1, pos2 = parseInt(ncbiResid2.substr(ncbiResid2.lastIndexOf('_') + 1)) - 1;
128465
128807
 
128466
- // set cursor for all nodes
128467
- setTimeout(function(){
128468
- let r2dt = document.querySelector('r2dt-web').shadowRoot;
128469
- let elemArray = r2dt.querySelectorAll('g:has(title)');
128470
- for(let i = 0, il = elemArray.length; i < il; ++i) {
128471
- if(!elemArray[i].hasAttribute('id')) { // skip the main g element
128472
- elemArray[i].style.cursor = "pointer";
128808
+ if(pos1 > pos2) continue; // each pair is listed twice in FR3D data, with the from and to residues swapped. Only process the one with pos1 < pos2 to avoid duplication.
128809
+
128810
+ if(from_type_to[1] == 'cWW') {
128811
+ if(fromArray[2] == chain && toArray[2] == chain) {
128812
+ pairs.push([Math.min(pos1, pos2), Math.max(pos1, pos2)]);
128813
+ }
128814
+ }
128815
+ else {
128816
+ let type = from_type_to[1];
128817
+ if(!lw2pairs[type]) lw2pairs[type] = [];
128818
+
128819
+ lw2pairs[type].push(pos1);
128820
+ lw2pairs[type].push(pos2);
128821
+ }
128822
+
128823
+ }
128824
+
128825
+ return {'pairs': pairs, 'lw2pairs': lw2pairs};
128826
+ }
128827
+
128828
+ isCrossed(pair1, pair2) {
128829
+ let i = pair1[0], j = pair1[1];
128830
+ let k = pair2[0], l = pair2[1];
128831
+ return (i < k && k < j && j < l) || (k < i && i < l && l < j);
128832
+ }
128833
+
128834
+ // modified from a python script by Eugene Baulin (https://imol.institute/leaders/baulin-group/)
128835
+ // pairs: list of (i, j) with 0 <= i < j < length
128836
+ pairs2dotbracket(pairs, lw2pairs, chainid) { let ic = this.icn3d; ic.icn3dui;
128837
+ //Dot-bracket notation for RNA secondary structures with pseudoknots.
128838
+
128839
+ //Positions are 0-indexed. Crossing pairs require different bracket types.
128840
+ //Levels are minimized by greedy coloring of the crossing graph, with pairs
128841
+ //sorted by ascending conflict count so that pairs involved in fewer crossings
128842
+ //(which form larger conflict-free groups) occupy the lower bracket levels.
128843
+
128844
+ //Bracket levels: () [] {} <> Aa Bb Cc ... Zz (30 levels total).
128845
+
128846
+ let BRACKETS = ['()', '[]', '{}', '<>'];
128847
+ for(let ch of 'ABCDEFGHIJKLMNOPQRSTUVWXYZ') {
128848
+ BRACKETS.push(ch + ch.toLowerCase());
128849
+ }
128850
+
128851
+ pairs.sort((a, b) => parseInt(a[0]) - parseInt(b[0]));
128852
+
128853
+ // Pairs with fewer crossings tend to belong to larger conflict-free groups
128854
+ // and should occupy lower levels. Sort ascending by crossing count so they
128855
+ // are placed at level 0 first; break ties by left endpoint for determinism.
128856
+ let pairstr2crosscnt = {};
128857
+ for(let i = 0, il = pairs.length; i < il; ++i) {
128858
+ let pairstr1 = pairs[i][0] + '_' + pairs[i][1];
128859
+ for(let j = i + 1; j < il; ++j) {
128860
+ let pairstr2 = pairs[j][0] + '_' + pairs[j][1];
128861
+ if(this.isCrossed(pairs[i], pairs[j])) {
128862
+ pairstr2crosscnt[pairstr1] = (pairstr2crosscnt[pairstr1] || 0) + 1;
128863
+ pairstr2crosscnt[pairstr2] = (pairstr2crosscnt[pairstr2] || 0) + 1;
128864
+ }
128865
+ }
128866
+ }
128867
+
128868
+ let pairsSortbyCross = pairs.sort((a, b) => {
128869
+ let pairstr1 = a[0] + '_' + a[1], pairstr2 = b[0] + '_' + b[1];
128870
+ let crosscnt1 = pairstr2crosscnt[pairstr1] || 0, crosscnt2 = pairstr2crosscnt[pairstr2] || 0;
128871
+ if(crosscnt1 != crosscnt2) {
128872
+ return crosscnt1 - crosscnt2;
128873
+ } else {
128874
+ return a[0] - b[0];
128875
+ }
128876
+ });
128877
+
128878
+ // Greedy level assignment: for each pair (in conflict-count order),
128879
+ // use the lowest level whose existing pairs do not cross it.
128880
+ let levels = []; // each level is an array of pairs
128881
+ for(let index = 0, indexl = pairsSortbyCross.length; index < indexl; ++index) {
128882
+ let pair = pairsSortbyCross[index];
128883
+
128884
+ if(levels.length == 0) {
128885
+ levels.push([pair]);
128886
+ continue;
128887
+ }
128888
+
128889
+ let bCrossed = false;
128890
+ for(let i = 0, il = levels.length; i < il; ++i) {
128891
+ bCrossed = false;
128892
+
128893
+ let level_pairs = levels[i];
128894
+
128895
+ for(let j = 0, jl = level_pairs.length; j < jl; ++j) {
128896
+ if(this.isCrossed(pair, level_pairs[j])) {
128897
+ bCrossed = true;
128898
+ break;
128473
128899
  }
128474
128900
  }
128475
- }, 1000);
128901
+
128902
+ if(!bCrossed) {
128903
+ levels[i].push(pair);
128904
+ break;
128905
+ }
128906
+ }
128907
+
128908
+ if(bCrossed) {
128909
+ levels.push([pair]);
128910
+ }
128476
128911
  }
128477
- else {
128478
- var aaa = 1; //alert("No R2DT diagram can be found for chain " + chainid);
128912
+
128913
+ // Relabel so larger groups use lower-level brackets, minimising the total
128914
+ // number of characters at higher levels. Bracket types are just labels —
128915
+ // any permutation of levels is valid as long as pairs on the same level
128916
+ // do not cross.
128917
+ levels.sort((a, b) => b.length - a.length); // sort descending by group size
128918
+
128919
+ let dotb = [], seq = '';
128920
+ for(let i = 0; i < ic.chainsSeq[chainid].length; ++i) {
128921
+ dotb.push('.');
128922
+ seq += ic.chainsSeq[chainid][i].name;
128479
128923
  }
128924
+
128925
+ let type = 'cWW';
128926
+ if(!lw2pairs[type]) lw2pairs[type] = [];
128927
+
128928
+ for(let i = 0, il = levels.length; i < il; ++i) {
128929
+ let pairs = levels[i];
128930
+ for(let j = 0, jl = pairs.length; j < jl; ++j) {
128931
+ dotb[pairs[j][0]] = BRACKETS[i][0];
128932
+ dotb[pairs[j][1]] = BRACKETS[i][1];
128933
+
128934
+ if(i > 0) { // level 0 is for nested base pairs
128935
+ lw2pairs[type].push(pairs[j][0] + 1); // 1-based
128936
+ lw2pairs[type].push(pairs[j][1] + 1);
128937
+ }
128938
+ }
128939
+ }
128940
+
128941
+ return {'dotb': dotb.join(''), 'seq': seq, 'lw2pairs': lw2pairs};
128942
+ }
128943
+
128944
+ async drawRnacanvas(chainid) { let ic = this.icn3d, me = ic.icn3dui;
128945
+ ic.bAddedCursors = false;
128946
+
128947
+ ic.rnacanvas_chainid = chainid;
128948
+
128949
+ let pos = chainid.lastIndexOf('_');
128950
+ chainid.substr(0, pos);
128951
+
128952
+ let result = await this.getDotbracket(chainid);
128953
+
128954
+ ic.dot_bracket = result.dotb;
128955
+ ic.rnaseq = result.seq;
128956
+ ic.lw2pairs = result.lw2pairs;
128957
+
128958
+ let nonWC = '';
128959
+ this.updateRnacanvas(nonWC);
128960
+ //me.htmlCls.clickMenuCls.setLogCmd('update forna ' + nonWC, true);
128961
+
128962
+ me.htmlCls.dialogCls.openDlg('dl_rnacanvas', 'Show 2D Diagram for chain ' + chainid + ' with RNAcanvas');
128963
+ $("#" + me.pre + "basepairType").resizable();
128964
+ }
128965
+
128966
+ updateRnacanvas(nonWC) { let ic = this.icn3d, me = ic.icn3dui;
128967
+ let html = '';
128968
+
128969
+ html += "<div id='rnacanvasSvg'></div>\n";
128970
+
128971
+ html += "<script type='module'>\n";
128972
+ //html += " import 'https://cdn.jsdelivr.net/npm/@rnacanvas/embedded@3.1.0';\n";
128973
+ html += " import './script/rnacanvas-4.0.0.js';\n";
128974
+ html += "</script>\n";
128975
+
128976
+ html += "<script type='text/javascript'>\n";
128977
+ html += "var attempts = 0;\n";
128978
+ html += "var tick = () => {\n";
128979
+ html += " if (typeof RNAcanvas !== 'undefined') {\n";
128980
+
128981
+ // html += "<script type='text/javascript'>\n";
128982
+ // html += "setTimeout(function(){\n";
128983
+ html += " // create a new RNAcanvas app instance\n";
128984
+ html += " var rnaCanvas = new RNAcanvas();\n";
128985
+ html += " // Target your container and append the canvas element\n";
128986
+ html += " var container = document.getElementById('rnacanvasSvg');\n";
128987
+ html += " rnaCanvas.appendTo(container);\n";
128988
+ html += " // control the size of the component\n";
128989
+ html += " rnaCanvas.domNode.style.width = '" + ($(window).width() / 2 - 150) + "px';\n";
128990
+ html += " rnaCanvas.domNode.style.height = '" + ($(window).height() - 200) + "px';\n";
128991
+ //html += " rnaCanvas.domNode.style.width = '600px';\n";
128992
+ //html += " rnaCanvas.domNode.style.height = '600px';\n";
128993
+ html += " // Render the structure\n";
128994
+ html += " rnaCanvas.drawDotBracket('" + ic.rnaseq + "', '" + ic.dot_bracket + "');\n";
128995
+ html += " // add padding around the drawn structure\n";
128996
+ html += " rnaCanvas.drawing.setPadding(20);\n";
128997
+ //html += " rnaCanvas.drawing.setPadding(1000);\n";
128998
+ html += " // bring the drawn structure into view\n";
128999
+ html += " rnaCanvas.drawingView.fitToContent();\n";
129000
+ html += " $('.UDedZ1UaiPZJsRmm1yxA').hide();\n"; // hide the "Powered by RNAcanvas" label
129001
+
129002
+ html += "var pos2node = {}, id2pos = {};\n";
129003
+ html += "var nodes = rnaCanvas.drawing.bases;\n";
129004
+
129005
+ html += "for (var i = 0, il = nodes.length; i < il; i++) {\n";
129006
+ html += " pos2node[i + 1] = nodes[i];\n";
129007
+ html += " id2pos[nodes[i].id] = i + 1;\n";
129008
+ html += "}\n";
129009
+
129010
+ html += "$(document).on('click', '#rnacanvasSvg svg text', function(e) {\n";
129011
+ html += " var id = $(this).attr('id');\n";
129012
+ html += " // clear all node color\n";
129013
+ html += " for (var i = 0, il = nodes.length; i < il; i++) {\n";
129014
+ html += " nodes[i].setAttribute('fill', '#000');\n";
129015
+ html += " }\n";
129016
+ html += " $(this)[0].setAttribute('fill', '#f8b84e');\n";
129017
+
129018
+ html += " var pos = id2pos[id];\n";
129019
+ html += " var resn = $(this).text().split(' ')[0];\n"; //C Position 8
129020
+ html += " $(document).trigger('from_rnacanvas', pos + '_' + resn);\n";
129021
+ html += " document.dispatchEvent(event);\n";
129022
+ html += "});\n";
129023
+
129024
+ html += "$(document).on('mouseover', '#rnacanvasSvg svg text', function(e) {\n";
129025
+ html += " var id = $(this).attr('id');\n";
129026
+ html += " $(this)[0].setAttribute('fill', '#f8b84e');\n";
129027
+
129028
+ html += " if(!$(this)[0].querySelector('title')) {\n";
129029
+ html += " var title = document.createElementNS('http://www.w3.org/2000/svg', 'title');\n";
129030
+ html += " title.textContent = ' Position ' + id2pos[id];\n";
129031
+ html += " $(this)[0].appendChild(title);\n";
129032
+ html += " }\n";
129033
+ html += "});\n";
129034
+
129035
+ html += "$(document).on('mouseout', '#rnacanvasSvg svg text', function(e) {\n";
129036
+ html += " var id = $(this).attr('id');\n";
129037
+ html += " $(this)[0].setAttribute('fill', '#000');\n";
129038
+ html += "});\n";
129039
+
129040
+ // click 3D to highlight in 2D
129041
+ html += "$(document).on('icn3d.pick.click icn3d.pick.mouseover', function(ev, data) {\n";
129042
+ html += " // get the residues in the selection\n";
129043
+ html += " var ncbiresid = data;\n";
129044
+ html += " var pos = ncbiresid.substr(ncbiresid.lastIndexOf('_') + 1);\n";
129045
+
129046
+ html += " // clear all node color\n";
129047
+ html += " for (var i = 0, il = nodes.length; i < il; i++) {\n";
129048
+ html += " nodes[i].setAttribute('fill', '#000');\n";
129049
+ html += " }\n";
129050
+
129051
+ html += " var node = pos2node[parseInt(pos)];\n";
129052
+ html += " node.setAttribute('fill', '#f8b84e');\n";
129053
+ html += "});\n";
129054
+
129055
+ if(nonWC) {
129056
+ let lwTypesTmp = nonWC.split(',');
129057
+ let lwTypes = [...new Set(lwTypesTmp)]; // unique
129058
+
129059
+ for(let i = 0, il = lwTypes.length; i < il; ++i) {
129060
+ let type = lwTypes[i];
129061
+ let pairs = ic.lw2pairs[type];
129062
+ if(!pairs) continue;
129063
+
129064
+ for(let j = 0, jl = pairs.length; j < jl; j += 2) {
129065
+ let pos1 = pairs[j], pos2 = pairs[j + 1];
129066
+ html += "if(pos2node[" + pos1 + "] && pos2node[" + pos2 + "]) {\n";
129067
+ html += " var node1 = pos2node[" + pos1 + "].centerPoint;\n";
129068
+ html += " var node2 = pos2node[" + pos2 + "].centerPoint;\n";
129069
+ html += " const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');\n";
129070
+ html += " line.setAttribute('x1', node1.x);\n";
129071
+ html += " line.setAttribute('y1', node1.y);\n";
129072
+ html += " line.setAttribute('x2', node2.x);\n";
129073
+ html += " line.setAttribute('y2', node2.y);\n";
129074
+ html += " line.setAttribute('stroke', 'black');\n";
129075
+ html += " line.setAttribute('stroke-width', '1');\n";
129076
+ html += " line.setAttribute('title', '" + type + "');\n";
129077
+ html += " rnaCanvas.drawing.domNode.appendChild(line);";
129078
+ html += "}\n";
129079
+ }
129080
+ }
129081
+ }
129082
+
129083
+ // html += "}, 10000);\n";
129084
+
129085
+ html += " return;\n";
129086
+ html += " }\n";
129087
+ html += " if (attempts++ > 200) return;\n";
129088
+ html += " setTimeout(tick, 100);\n";
129089
+ html += "};\n";
129090
+ html += "tick();\n";
129091
+
129092
+ html += "</script>\n";
129093
+
129094
+ $("#" + me.pre + "rnacanvasDiv").html(html);
128480
129095
  }
128481
129096
 
128482
129097
  async drawIgdgm(chainid) { let ic = this.icn3d, me = ic.icn3dui;
@@ -128533,7 +129148,7 @@ class Diagram2d {
128533
129148
  if(refnumLabel) {
128534
129149
  refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
128535
129150
  if(!refnum2resn[domainid]) refnum2resn[domainid] = {};
128536
- refnum2resn[domainid][refnumStr] = resn;
129151
+ refnum2resn[domainid][refnumStr] = resn + resid.split('_')[2];
128537
129152
  }
128538
129153
  }
128539
129154
 
@@ -128546,6 +129161,8 @@ class Diagram2d {
128546
129161
 
128547
129162
  const mainWorkbook = new ExcelJS.Workbook();
128548
129163
 
129164
+ let ig2width = {'IgC1': 17, 'IgC2': 18, 'IgI': 19, 'IgV': 19};
129165
+
128549
129166
  for(let i = 0, il = igArray.length; i < il; ++i) {
128550
129167
  let domainid = igArray[i].domainid;
128551
129168
  let igType = igTypeArray[i];
@@ -128563,10 +129180,8 @@ class Diagram2d {
128563
129180
 
128564
129181
  const newSheet = mainWorkbook.addWorksheet();
128565
129182
  // Clone the model to transfer styles and data
128566
- newSheet.model = {
128567
- ...worksheet.model,
128568
- name: (i + 1) + ". " + igType
128569
- };
129183
+ newSheet.model = worksheet.model;
129184
+ newSheet.name = (i + 1) + ". " + igType;
128570
129185
 
128571
129186
  // Iterate over all rows that have values
128572
129187
  newSheet.eachRow({ includeEmpty: true }, (row, rowNumber) => {
@@ -128581,8 +129196,28 @@ class Diagram2d {
128581
129196
  cell.value = '';
128582
129197
  }
128583
129198
  }
129199
+ else if(cell.value == 'NUMBERING') {
129200
+ cell.value = '';
129201
+ }
128584
129202
  });
128585
129203
  });
129204
+
129205
+ // copy the original data
129206
+ let colNum = ig2width[igType]; // some extra columns
129207
+ for(let i = 1; i <= colNum; ++i) {
129208
+ const sourceCol = worksheet.getColumn(i);
129209
+
129210
+ // Copy values and styles
129211
+ sourceCol.eachCell({ includeEmpty: true }, (cell, rowNumber) => {
129212
+ const targetCell = newSheet.getRow(rowNumber).getCell(colNum + 2 + i);
129213
+
129214
+ targetCell.value = cell.value;
129215
+ targetCell.style = cell.style; // Copies font, borders, and fills
129216
+ });
129217
+
129218
+ // reset width for each column
129219
+ newSheet.getColumn(colNum + 2 + i).width = worksheet.getColumn(i).width;
129220
+ }
128586
129221
  }
128587
129222
  }
128588
129223
 
@@ -130631,7 +131266,7 @@ class SaveFile {
130631
131266
  }
130632
131267
  }
130633
131268
 
130634
- saveSvg(id, filename, bContactmap, bLigplot) { let ic = this.icn3d, me = ic.icn3dui;
131269
+ saveSvg(id, filename, bContactmap, bLigplot, bClassName) { let ic = this.icn3d, me = ic.icn3dui;
130635
131270
  if(me.bNode) return '';
130636
131271
 
130637
131272
  let width = $("#" + id).width();
@@ -130644,17 +131279,24 @@ class SaveFile {
130644
131279
  height += ic.len4ang;
130645
131280
  }
130646
131281
 
130647
- let svgXml = this.getSvgXml(id, width, height, bContactmap, bLigplot);
131282
+ let svgXml = this.getSvgXml(id, width, height, bContactmap, bLigplot, bClassName);
131283
+
131284
+ if(id == me.rnacanvasid) { // replace the font to 8
131285
+ svgXml = svgXml.replace('font-size: 18px', 'font-size: 8px');
131286
+ }
130648
131287
 
130649
131288
  let blob = new Blob([svgXml], {type: "image/svg+xml"});
130650
131289
  saveAs(blob, filename);
130651
131290
  }
130652
131291
 
130653
- getSvgXml(id, width, height, bContactmap, bLigplot) { let ic = this.icn3d, me = ic.icn3dui;
131292
+ getSvgXml(id, width, height, bContactmap, bLigplot, bClassName) { let ic = this.icn3d, me = ic.icn3dui;
130654
131293
  if(me.bNode) return '';
130655
131294
 
130656
131295
  // font is not good
130657
- let svg_data = document.getElementById(id).innerHTML; //put id of your svg element here
131296
+ let svg_data = (!bClassName) ? document.getElementById(id).innerHTML : document.querySelector('.' + id).innerHTML; //put id of your svg element here
131297
+ svg_data = svg_data.replace(/ fill=" #ccc"=""/g, '" fill="#ccc"'); // fix some data
131298
+ svg_data = svg_data.replace(/style="cursor: pointer;"/g, '');
131299
+ svg_data = svg_data.replace(/ font-size="/g, ' style="font-size: ');
130658
131300
 
130659
131301
  let startX = (bLigplot) ? -30 : 0;
130660
131302
  let startY = (bLigplot) ? -30 : 0;
@@ -130944,10 +131586,10 @@ class SaveFile {
130944
131586
  for(let n = 0; n < 3; ++n) {
130945
131587
  let nNum = n + 1;
130946
131588
  stru2header[stru] += "REMARK 350 BIOMT" + nNum.toString() + " " + mNum.toString().padStart(2, ' ')
130947
- + " " + ic.biomtMatrices[m].elements[n + 0].toFixed(6).toString().padStart(9, ' ')
130948
- + " " + ic.biomtMatrices[m].elements[n + 4].toFixed(6).toString().padStart(9, ' ')
130949
- + " " + ic.biomtMatrices[m].elements[n + 8].toFixed(6).toString().padStart(9, ' ')
130950
- + " " + ic.biomtMatrices[m].elements[n + 12].toFixed(6).toString().padStart(14, ' ') + "\n";
131589
+ + " " + parseFloat(ic.biomtMatrices[m].elements[n + 0]).toFixed(6).toString().padStart(9, ' ')
131590
+ + " " + parseFloat(ic.biomtMatrices[m].elements[n + 4]).toFixed(6).toString().padStart(9, ' ')
131591
+ + " " + parseFloat(ic.biomtMatrices[m].elements[n + 8]).toFixed(6).toString().padStart(9, ' ')
131592
+ + " " + parseFloat(ic.biomtMatrices[m].elements[n + 12]).toFixed(6).toString().padStart(14, ' ') + "\n";
130951
131593
  }
130952
131594
  }
130953
131595
  }
@@ -132388,7 +133030,7 @@ class Export3D {
132388
133030
  let mat = ic.biomtMatrices[i];
132389
133031
  if(mat === undefined) continue;
132390
133032
  // skip itself
132391
- if(mat.equals(identity)) continue;
133033
+ if(me.utilsCls.compMatrix(mat, identity, 16)) continue;
132392
133034
  let time =(i + 1) * 100;
132393
133035
  //https://stackoverflow.com/questions/1190642/how-can-i-pass-a-parameter-to-a-settimeout-callback
132394
133036
  setTimeout(function(mat, index){
@@ -132430,7 +133072,7 @@ class Export3D {
132430
133072
  let mat = ic.biomtMatrices[i];
132431
133073
  if(mat === undefined) continue;
132432
133074
  // skip itself
132433
- if(mat.equals(identity)) continue;
133075
+ if(me.utilsCls.compMatrix(mat, identity, 16)) continue;
132434
133076
  let time =(i + 1) * 100;
132435
133077
  //https://stackoverflow.com/questions/1190642/how-can-i-pass-a-parameter-to-a-settimeout-callback
132436
133078
  setTimeout(function(mat, index){
@@ -132547,7 +133189,7 @@ class Export3D {
132547
133189
  if(mat1 === undefined) continue;
132548
133190
 
132549
133191
  // skip itself
132550
- if(mat1.equals(identity)) continue;
133192
+ if(me.utilsCls.compMatrix(mat1, identity, 16)) continue;
132551
133193
 
132552
133194
  blobArray = this.processStlMeshGroup( ic.mdl, blobArray, mat1 );
132553
133195
 
@@ -132646,7 +133288,7 @@ class Export3D {
132646
133288
 
132647
133289
  //http://gun.teipir.gr/VRML-amgem/spec/part1/examples.html
132648
133290
  //Save the VRML file for 3D color printing.
132649
- saveVrmlFile( mat ){ let ic = this.icn3d; ic.icn3dui;
133291
+ saveVrmlFile( mat ){ let ic = this.icn3d, me = ic.icn3dui;
132650
133292
  if(Object.keys(ic.dAtoms).length > 50000) {
132651
133293
  var aaa = 1; //alert('Please display a subset of the structure to export 3D files. Then merge the files for 3D printing...');
132652
133294
  return [''];
@@ -132677,7 +133319,7 @@ class Export3D {
132677
133319
  if(mat1 === undefined) continue;
132678
133320
 
132679
133321
  // skip itself
132680
- if(mat1.equals(identity)) continue;
133322
+ if(me.utilsCls.compMatrix(mat1, identity, 16)) continue;
132681
133323
 
132682
133324
  result = this.processVrmlMeshGroup( ic.mdl, vrmlStrArray, vertexCnt, mat1 );
132683
133325
  vrmlStrArray = result.vrmlStrArray;
@@ -133327,6 +133969,9 @@ class Picking {
133327
133969
  this.showPickingBase(atom, x, y);
133328
133970
 
133329
133971
  if(ic.pk != 0) {
133972
+ let resid = atom.structure + '_' + atom.chain + '_' + atom.resi;
133973
+ let ncbiresid = (ic.resid2ncbi[resid]) ? ic.resid2ncbi[resid] : resid;
133974
+
133330
133975
  if(x !== undefined && y !== undefined) { // mouse over
133331
133976
  if(me.cfg.showmenu != undefined && me.cfg.showmenu == true) {
133332
133977
  y += me.htmlCls.MENU_HEIGHT;
@@ -133353,6 +133998,8 @@ class Picking {
133353
133998
 
133354
133999
  $("#" + ic.pre + "popup").html(text);
133355
134000
  $("#" + ic.pre + "popup").css("top", y).css("left", x+20).show();
134001
+
134002
+ $(document).trigger('icn3d.pick.mouseover', ncbiresid);
133356
134003
  }
133357
134004
  else {
133358
134005
  // highlight the sequence background
@@ -133365,6 +134012,8 @@ class Picking {
133365
134012
  // update the interaction flag
133366
134013
  ic.bSphereCalc = false;
133367
134014
  ic.bHbondCalc = false;
134015
+
134016
+ $(document).trigger('icn3d.pick.click', ncbiresid);
133368
134017
  }
133369
134018
  }
133370
134019
  }
@@ -134861,7 +135510,7 @@ class iCn3DUI {
134861
135510
  //even when multiple iCn3D viewers are shown together.
134862
135511
  this.pre = this.cfg.divid + "_";
134863
135512
 
134864
- this.REVISION = '3.49.2';
135513
+ this.REVISION = '3.50.0';
134865
135514
 
134866
135515
  // In nodejs, iCn3D defines "window = {navigator: {}}", and added window = {navigator: {}, "__THREE__":"177"}
134867
135516
  this.bNode = (Object.keys(window).length < 3) ? true : false;