icn3d 3.50.1 → 3.51.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/css/icn3d.css CHANGED
@@ -125,7 +125,7 @@ button, select, input { font-size: 10px; }
125
125
  .icn3d-nalign {}
126
126
  */
127
127
 
128
- .icn3d-node, .icn3d-ctnode, #rnacanvasSvg text {cursor:pointer!important; }
128
+ .icn3d-node, .icn3d-ctnode, #rnacanvasSvg text, #ig2ddgmSvg .node {cursor:pointer!important; }
129
129
  .icn3d-interaction {cursor:pointer!important; }
130
130
 
131
131
  /* force-directed graph node text */
@@ -296,12 +296,13 @@ input:checked + .icn3d-slider:before {
296
296
  background-color: #369;
297
297
  overflow: auto;
298
298
  }
299
-
299
+ /*
300
300
  svg text {
301
301
  user-select: none!important;
302
302
  -webkit-user-select: none!important;
303
303
  -webkit-tap-highlight-color: transparent!important;
304
304
  }
305
+ */
305
306
 
306
307
  .color-picker,
307
308
  .color-picker:before,
package/icn3d.js CHANGED
@@ -58591,7 +58591,7 @@ class ClickMenu {
58591
58591
  let definedAtomsHtml = ic.definedSetsCls.setAtomMenu(['protein'], bNucleotides);
58592
58592
  if($("#" + me.pre + "atomsCustomNucleotide").length && definedAtomsHtml) {
58593
58593
  $("#" + me.pre + "atomsCustomNucleotide").html(definedAtomsHtml);
58594
- me.htmlCls.dialogCls.openDlg('dl_2ddgm_r2dt', 'Show R2DT Diagram for Nucleotides');
58594
+ me.htmlCls.dialogCls.openDlg('dl_2ddgm_r2dt', 'Show R2DT Diagram for RNAs');
58595
58595
  $("#" + me.pre + "atomsCustomNucleotide").resizable();
58596
58596
  }
58597
58597
  else {
@@ -60520,7 +60520,7 @@ class SetMenu {
60520
60520
 
60521
60521
  html += this.getMenuText('2ddgmwrap', '2D Diagram', undefined, 1, 1);
60522
60522
  html += "<ul>";
60523
- html += this.getLink('2ddgm_r2dt', 'for Nucleotides' + me.htmlCls.wifiStr, 1, 2);
60523
+ html += this.getLink('2ddgm_r2dt', 'for RNAs' + me.htmlCls.wifiStr, 1, 2);
60524
60524
  html += this.getLink('2ddgm_igdgm', 'for Ig Domains' + me.htmlCls.wifiStr, 1, 2);
60525
60525
  if(me.cfg.mmdbid !== undefined || me.cfg.gi !== undefined || me.cfg.blast_rep_id !== undefined || me.cfg.align !== undefined || me.cfg.chainalign !== undefined) {
60526
60526
  html += this.getLink('mn2_2ddgm', 'for Chains ' + me.htmlCls.wifiStr, 1, 2);
@@ -60973,6 +60973,7 @@ class Dialog {
60973
60973
  let bLigplot = $('#' + me.pre + 'dl_ligplot').hasClass('ui-dialog-content'); // initialized
60974
60974
  let bContactmap = $('#' + me.pre + 'dl_contactmap').hasClass('ui-dialog-content'); // initialized
60975
60975
  let b2ddiagram = $('#' + me.pre + 'dl_2ddiagram').hasClass('ui-dialog-content'); // initialized
60976
+ let big2ddgm = $('#' + me.pre + 'dl_ig2ddgm').hasClass('ui-dialog-content'); // initialized
60976
60977
  let brnacanvas = $('#' + me.pre + 'dl_rnacanvas').hasClass('ui-dialog-content'); // initialized
60977
60978
  let bAlignerrormap = $('#' + me.pre + 'dl_alignerrormap').hasClass('ui-dialog-content'); // initialized
60978
60979
  let bTable = $('#' + me.pre + 'dl_interactionsorted').hasClass('ui-dialog-content'); // initialized
@@ -60995,6 +60996,7 @@ class Dialog {
60995
60996
  id2flag.dl_contactmap = 'bContactmap2';
60996
60997
  id2flag.dl_2ddiagram = 'b2ddiagram2';
60997
60998
  id2flag.dl_rnacanvas = 'brnacanvas2';
60999
+ id2flag.dl_ig2ddgm = 'big2ddgm2';
60998
61000
  id2flag.dl_alignerrormap = 'bAlignerrormap2';
60999
61001
  id2flag.dl_interactionsorted = 'bTable2';
61000
61002
  id2flag.dl_alignment = 'bAlignmentInit2';
@@ -61012,6 +61014,7 @@ class Dialog {
61012
61014
  if(bContactmap) status.bContactmap2 = $('#' + me.pre + 'dl_contactmap').dialog( 'isOpen' );
61013
61015
  if(b2ddiagram) status.b2ddiagram2 = $('#' + me.pre + 'dl_2ddiagram').dialog( 'isOpen' );
61014
61016
  if(brnacanvas) status.brnacanvas2 = $('#' + me.pre + 'dl_rnacanvas').dialog( 'isOpen' );
61017
+ if(big2ddgm) status.big2ddgm2 = $('#' + me.pre + 'dl_ig2ddgm').dialog( 'isOpen' );
61015
61018
  if(bAlignerrormap) status.bAlignerror2 = $('#' + me.pre + 'dl_alignerrormap').dialog( 'isOpen' );
61016
61019
  if(bTable) status.bTable2 = $('#' + me.pre + 'dl_interactionsorted').dialog( 'isOpen' );
61017
61020
  if(bAlignmentInit) status.bAlignmentInit2 = $('#' + me.pre + 'dl_alignment').dialog( 'isOpen' );
@@ -61199,7 +61202,7 @@ class Dialog {
61199
61202
 
61200
61203
  let status = this.getDialogStatus().status;
61201
61204
 
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') {
61205
+ 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_ig2ddgm' || id === me.pre + 'dl_alignerrormap' || id === me.pre + 'dl_interactionsorted' || id === me.pre + 'dl_alignment') {
61203
61206
  //var dialogWidth = 0.5 *(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH) - twoddgmWidth * 0.5;
61204
61207
  let dialogWidth = 0.5 *(me.htmlCls.WIDTH) - twoddgmWidth * 0.5;
61205
61208
 
@@ -62165,19 +62168,19 @@ class SetDialog {
62165
62168
  html += "</div>";
62166
62169
 
62167
62170
  html += me.htmlCls.divStr + "dl_2ddgm_r2dt' class='" + dialogClass + "'>";
62168
- html += this.addNotebookTitle('dl_2ddgm_r2dt', '2D Diagram for Nucleotides (R2DT)');
62169
- html += "1. Select a nucleotide chain to show 2D diagram:<br>";
62171
+ html += this.addNotebookTitle('dl_2ddgm_r2dt', '2D Diagram for RNAs (R2DT)');
62172
+ html += "1. Select a RNA chain to show 2D diagram:<br>";
62170
62173
  html += "<select style='max-width:200px' id='" + me.pre + "atomsCustomNucleotide' size='5' style='min-width:130px;'>";
62171
62174
  html += "</select><br>";
62172
62175
  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>";
62173
62176
  html += "</div>";
62174
62177
 
62175
62178
  html += me.htmlCls.divStr + "dl_2ddgm_igdgm' class='" + dialogClass + "'>";
62176
- html += this.addNotebookTitle('dl_2ddgm_igdgm', '2D Diagram for Ig Domains (R2DT)');
62179
+ html += this.addNotebookTitle('dl_2ddgm_igdgm', '2D Diagram for Ig Domains');
62177
62180
  html += "1. Select a protein chain to show Ig diagram. An Excel file containing <br>the Ig diagram will be saved to your computer.<br>";
62178
62181
  html += "<select style='max-width:200px' id='" + me.pre + "atomsCustomProtein' size='5' style='min-width:130px;'>";
62179
62182
  html += "</select><br>";
62180
- html += me.htmlCls.buttonStr + "applyigdgm'>Show Ig Diagram</button><br>";
62183
+ html += "2. " + me.htmlCls.buttonStr + "applyigdgm' style='margin-right:12px;'>Show Ig Diagram</button>" + me.htmlCls.buttonStr + "saveigdgm'>Download Ig Diagrams in Excel</button><br>";
62181
62184
  html += "</div>";
62182
62185
 
62183
62186
  html += me.htmlCls.divStr + "dl_hbonds' class='" + dialogClass + "'>";
@@ -62535,6 +62538,20 @@ class SetDialog {
62535
62538
  html += '<div id="' + me.pre + 'rnacanvasDiv"></div>';
62536
62539
  html += "</div>";
62537
62540
 
62541
+
62542
+ me.ig2ddgmid = me.pre + 'ig2ddgm';
62543
+ html += me.htmlCls.divStr + "dl_ig2ddgm' style='background-color:white' class='" + dialogClass + "'>";
62544
+ html += this.addNotebookTitle('dl_ig2ddgm', '2D Diagram for Ig domains');
62545
+
62546
+ html += "<table><tr><td>Select an Ig domain:<br>";
62547
+ html += me.htmlCls.divNowrapStr + "<select id='" + me.pre + "iglist' size='2' style='min-width:130px;'>";
62548
+ html += "</select></td><td valign='top'>";
62549
+ html += me.htmlCls.space2 + buttonStrTmp + me.ig2ddgmid + '_svg">Download SVG</button></td></tr></table><br>';
62550
+
62551
+ html += '<div id="' + me.pre + 'ig2ddgmDiv"></div>';
62552
+ html += "</div>";
62553
+
62554
+
62538
62555
  html += me.htmlCls.divStr + "dl_alignerrormap' style='background-color:white' class='" + dialogClass + "'>";
62539
62556
  html += this.addNotebookTitle('dl_alignerrormap', 'PAE Map');
62540
62557
 
@@ -65807,7 +65824,17 @@ class Events {
65807
65824
  thisClass.setLogCmd('diagram 2d fr3d | ' + chainid, true);
65808
65825
  });
65809
65826
 
65810
- me.myEventCls.onIds("#" + me.pre + "applyigdgm", "click", async function(e) { let ic = me.icn3d;
65827
+ me.myEventCls.onIds("#" + me.pre + "saveigdgm", "click", async function(e) { let ic = me.icn3d;
65828
+ e.preventDefault();
65829
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
65830
+
65831
+ let chainid = $("#" + ic.pre + "atomsCustomProtein").val();
65832
+
65833
+ let bSave = true;
65834
+ await ic.diagram2dCls.drawIgdgm(chainid, bSave);
65835
+ thisClass.setLogCmd('download 2d ig | ' + chainid, true);
65836
+ });
65837
+ me.myEventCls.onIds("#" + me.pre + "applyigdgm", "click", async function(e) { let ic = me.icn3d;
65811
65838
  e.preventDefault();
65812
65839
  //if(!me.cfg.notebook) dialog.dialog( "close" );
65813
65840
 
@@ -66007,6 +66034,11 @@ class Events {
66007
66034
  ic.saveFileCls.saveFile(chainid + "_seq.txt", "text", [seq]);
66008
66035
  });
66009
66036
 
66037
+ me.myEventCls.onIds("#" + me.ig2ddgmid + "_svg", "click", function(e) { let ic = me.icn3d;
66038
+ e.preventDefault();
66039
+
66040
+ ic.saveFileCls.saveSvg("ig2ddgmSvg", ic.ig2ddgm_chainid + "_ig_2d.svg");
66041
+ });
66010
66042
 
66011
66043
  me.myEventCls.onIds("#" + me.linegraphid + "_svg", "click", function(e) { let ic = me.icn3d;
66012
66044
  e.preventDefault();
@@ -84089,6 +84121,28 @@ class ApplyClbonds {
84089
84121
  } // if
84090
84122
  } // if
84091
84123
 
84124
+ // add crosslink chemicals to the linked protein/nucleotide residues
84125
+ for(let structure in ic.structures) {
84126
+ let clbondArray = ic.clbondpnts[structure];
84127
+ if(clbondArray === undefined) {
84128
+ break;
84129
+ }
84130
+ for(let i = 0, il = clbondArray.length; i < il; i = i + 2) {
84131
+ let resid1 = clbondArray[i];
84132
+ let resid2 = clbondArray[i+1];
84133
+
84134
+ let atom1 = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid1]);
84135
+ let atom2 = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid2]);
84136
+
84137
+ if((ic.proteins.hasOwnProperty(atom1.serial) || ic.nucleotides.hasOwnProperty(atom1.serial)) && ic.chemicals.hasOwnProperty(atom2.serial)) {
84138
+ ic.residues[resid1] = me.hashUtilsCls.unionHash(ic.residues[resid1], ic.residues[resid2]);
84139
+ }
84140
+ else if((ic.proteins.hasOwnProperty(atom2.serial) || ic.nucleotides.hasOwnProperty(atom2.serial)) && ic.chemicals.hasOwnProperty(atom1.serial)) {
84141
+ ic.residues[resid2] = me.hashUtilsCls.unionHash(ic.residues[resid2], ic.residues[resid1]);
84142
+ }
84143
+ }
84144
+ }
84145
+
84092
84146
  return ic.residuesHashClbonds;
84093
84147
  }
84094
84148
 
@@ -84435,7 +84489,7 @@ class ApplyDisplay {
84435
84489
 
84436
84490
  // remove schematic labels
84437
84491
  //if(ic.labels !== undefined) ic.labels['schematic'] = undefined;
84438
- if(ic.labels !== undefined) delete ic.labels['schematic'];
84492
+ if(!bHighlight && ic.labels !== undefined) delete ic.labels['schematic'];
84439
84493
  /*
84440
84494
  if(bHighlight) {
84441
84495
  //let residueHashCalpha = ic.firstAtomObjCls.getResiduesFromCalphaAtoms(ic.hAtoms);
@@ -84456,6 +84510,7 @@ class ApplyDisplay {
84456
84510
  //var bPhosphorusOnly = me.utilsCls.isCalphaPhosOnly(me.hashUtilsCls.hash2Atoms(atomHash), "O3'", "O3*") || me.utilsCls.isCalphaPhosOnly(me.hashUtilsCls.hash2Atoms(atomHash), "P");
84457
84511
  //let bPhosphorusOnly = me.utilsCls.isCalphaPhosOnly(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms));
84458
84512
  let nucleotidesAtoms = me.hashUtilsCls.intHash(atomHash, ic.nucleotides);
84513
+
84459
84514
  let bPhosphorusOnly = me.utilsCls.isCalphaPhosOnly(me.hashUtilsCls.hash2Atoms(nucleotidesAtoms, ic.atoms));
84460
84515
 
84461
84516
  if(style === 'ribbon') {
@@ -84494,13 +84549,13 @@ class ApplyDisplay {
84494
84549
 
84495
84550
  //if(firstAtom.het) { // chemicals
84496
84551
  if(ic.chemicals.hasOwnProperty(firstAtom.serial)) { // chemicals
84497
- ic.residueLabelsCls.addNonCarbonAtomLabels(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms));
84552
+ if(!bHighlight) ic.residueLabelsCls.addNonCarbonAtomLabels(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms));
84498
84553
 
84499
84554
  let bSchematic = true;
84500
84555
  ic.stickCls.createStickRepresentation(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), chemicalSchematicRadius, chemicalSchematicRadius, undefined, bHighlight, bSchematic);
84501
84556
  }
84502
84557
  else { // nucleotides or proteins
84503
- ic.residueLabelsCls.addResidueLabels(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), true);
84558
+ if(!bHighlight) ic.residueLabelsCls.addResidueLabels(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), true);
84504
84559
 
84505
84560
  if(bPhosphorusOnly) {
84506
84561
  ic.cylinderCls.createCylinderCurve(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), ["P"], ic.traceRadius, false, bHighlight);
@@ -90116,7 +90171,7 @@ class SetOption {
90116
90171
  ic.atoms[i].style2 = style;
90117
90172
  }
90118
90173
  }
90119
- else {
90174
+ else {
90120
90175
  for(let i in atoms) {
90121
90176
  ic.atoms[i].style = style;
90122
90177
  }
@@ -118355,7 +118410,7 @@ class ApplyCommand {
118355
118410
  ic.definedSetsCls.deleteSelectedSets();
118356
118411
  }
118357
118412
  else if(command == 'view interactions' || command == 'view 2d diagram') {
118358
- if(me.cfg.mmdbid !== undefined || me.cfg.gi !== undefined) {
118413
+ if(me.cfg.mmdbid !== undefined || me.cfg.gi !== undefined || me.cfg.mmdbafid !== undefined) {
118359
118414
  ic.ParserUtilsCls.set2DDiagrams(ic.inputid);
118360
118415
  }
118361
118416
  }
@@ -119870,27 +119925,31 @@ class DefinedSets {
119870
119925
  let colorStr =(atom === undefined || atom.color === undefined || atom.color.getHexString().toUpperCase() === 'FFFFFF') ? 'DDDDDD' : atom.color.getHexString();
119871
119926
  let color =(atom !== undefined && atom.color !== undefined) ? colorStr : '000000';
119872
119927
 
119873
- if(bNucleotide && atom) {
119928
+ if(bNucleotide) {
119874
119929
  // Handle nucleotide-specific logic
119875
- if(ic.nucleotides.hasOwnProperty(atom.serial) && name.split('_').length == 2 && !ic.structures.hasOwnProperty(name)) {
119930
+ if(atom && ic.nucleotides.hasOwnProperty(atom.serial) && name.split('_').length == 2 && !ic.structures.hasOwnProperty(name)) {
119876
119931
  let selectStr = (cnt == 0) ? "selected" : "";
119877
119932
 
119933
+ if(cnt == 0) this.selectSets([name]);
119934
+
119878
119935
  html += "<option value='" + name + "' style='color:#" + color + "' " + selectStr + ">" + name + "</option>";
119879
119936
  bFoundNucleotide = true;
119880
119937
  ++cnt;
119881
119938
  }
119882
119939
  }
119883
- else if(bProtein && atom) {
119940
+ else if(bProtein) {
119884
119941
  // Handle protein-specific logic
119885
- if(ic.proteins.hasOwnProperty(atom.serial) && name.split('_').length == 2 && !ic.structures.hasOwnProperty(name)) {
119942
+ if(atom && ic.proteins.hasOwnProperty(atom.serial) && name.split('_').length == 2 && !ic.structures.hasOwnProperty(name)) {
119886
119943
  let selectStr = (cnt == 0) ? "selected" : "";
119887
119944
 
119945
+ if(cnt == 0) this.selectSets([name]);
119946
+
119888
119947
  html += "<option value='" + name + "' style='color:#" + color + "' " + selectStr + ">" + name + "</option>";
119889
119948
  bFoundProtein = true;
119890
119949
  ++cnt;
119891
119950
  }
119892
119951
  }
119893
- else {
119952
+ else {
119894
119953
  if(commandnameArray.indexOf(name) != -1) {
119895
119954
  html += "<option value='" + name + "' style='color:#" + color + "' selected='selected'>" + name + "</option>";
119896
119955
  }
@@ -121073,6 +121132,20 @@ class LoadScript {
121073
121132
  await ic.diagram2dCls.drawIgdgm(chainid);
121074
121133
  ic.bRender = false;
121075
121134
  }
121135
+ else if(command.indexOf('update ig') == 0) {
121136
+ let paraArray = command.split(' ');
121137
+ let igIndex_igType = (paraArray.length == 3) ? paraArray[2] : '';
121138
+ await ic.diagram2dCls.show2DdgmForIg(igIndex_igType[0], igIndex_igType[1]);
121139
+ }
121140
+ else if(command.indexOf('download 2d ig') == 0) {
121141
+ let paraArray = command.split(' | ');
121142
+ let pos = command.lastIndexOf(' ');
121143
+ let chainid = (paraArray.length == 2) ? paraArray[1] : command.substr(pos + 1);
121144
+
121145
+ ic.bRender = true;
121146
+ await ic.diagram2dCls.drawIgdgm(chainid, true);
121147
+ ic.bRender = false;
121148
+ }
121076
121149
  else if(command.indexOf('add msa track') == 0) {
121077
121150
  //add msa track | chainid " + chainid + " | startpos " + startpos + " | type " + type + " | fastaList " + fastaList
121078
121151
  let paraArray = command.split(' | ');
@@ -128419,6 +128492,74 @@ class Diagram2d {
128419
128492
  //}
128420
128493
  }
128421
128494
  });
128495
+
128496
+ //$("#" + me.pre + "ig2ddgmDiv").html(svgHtml);
128497
+ $(document).on("change", "#" + me.pre + "iglist", async function(e) { thisClass.icn3d;
128498
+ let igIndex_igType = $("#" + me.pre + "iglist").val().split('_');
128499
+
128500
+ await thisClass.show2DdgmForIg(igIndex_igType[0], igIndex_igType[1]);
128501
+
128502
+ me.htmlCls.clickMenuCls.setLogCmd('update ig ' + igIndex_igType, true);
128503
+ });
128504
+
128505
+ // ig 2D diagram: 2D -> 3D
128506
+ $(document).on('click', '#ig2ddgmSvg .node', function(e) { let ic = thisClass.icn3d;
128507
+ // clear all node color
128508
+ thisClass.resetAllNodes('ig2ddgmSvg');
128509
+
128510
+ $(this).css({'font-size': '20px', 'font-weight': 'bold'});
128511
+
128512
+ //<text x="502.1" y="301.8" class="s9 c8547"><title>Ref. Num. 8547</title> N99 </text>
128513
+ let text = $(this).html().trim();
128514
+ let resnresi = text.substr(text.lastIndexOf(' ') + 1);
128515
+
128516
+ let resid = ic.ncbi2resid[ic.ig2ddgm_chainid + '_' + resnresi.substr(1)];
128517
+
128518
+ // highlight the selected residue
128519
+ if(ic.bCtrl || ic.bShift) {
128520
+ ic.hAtoms = me.hashUtilsCls.unionHash(ic.hAtoms, ic.residues[resid]);
128521
+ }
128522
+ else {
128523
+ ic.hAtoms = ic.residues[resid];
128524
+ }
128525
+
128526
+ ic.hlUpdateCls.showHighlight();
128527
+ });
128528
+
128529
+ // $(document).on('mouseout', '#ig2ddgmSvg .node', function(e) { let ic = thisClass.icn3d;
128530
+ // thisClass.resetAllNodes('ig2ddgmSvg');
128531
+ // });
128532
+
128533
+ // ig 2D diagram: 3D -> 2D
128534
+ $(document).on('icn3d.pick.click icn3d.pick.mouseover', function(ev, data) { let ic = thisClass.icn3d;
128535
+ // get the residues in the selection
128536
+ let ncbiresid = data;
128537
+ let resid = ic.ncbi2resid[ncbiresid];
128538
+
128539
+ if(ic.ig2ddgm_chainid && ic.resid2refnum && ic.resid2refnum[resid]) {
128540
+ let refnumLabel = ic.resid2refnum[resid];
128541
+ let refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
128542
+
128543
+ // clear all node color
128544
+ thisClass.resetAllNodes('ig2ddgmSvg');
128545
+
128546
+ // highlight the residue
128547
+ $("#ig2ddgmSvg .c" + refnumStr).css({'font-size': '20px', 'font-weight': 'bold'});
128548
+ }
128549
+ });
128550
+ }
128551
+
128552
+ // reset all nodes
128553
+ resetAllNodes(id) { let ic = this.icn3d; ic.icn3dui;
128554
+ // Select the SVG container
128555
+ const svg = document.getElementById(id);
128556
+
128557
+ // Select all text-related nodes: <text>
128558
+ const textElements = svg.querySelectorAll('text');
128559
+
128560
+ textElements.forEach((node) => {
128561
+ node.style = {};
128562
+ });
128422
128563
  }
128423
128564
 
128424
128565
  clickNode(node) { let ic = this.icn3d, me = ic.icn3dui;
@@ -129086,7 +129227,12 @@ class Diagram2d {
129086
129227
  html += " line.setAttribute('y2', node2.y);\n";
129087
129228
  html += " line.setAttribute('stroke', 'black');\n";
129088
129229
  html += " line.setAttribute('stroke-width', '1');\n";
129089
- html += " line.setAttribute('title', '" + type + "');\n";
129230
+ //html += " line.setAttribute('title', '" + type + "');\n";
129231
+
129232
+ html += " var title = document.createElementNS('http://www.w3.org/2000/svg', 'title');\n";
129233
+ html += " title.textContent = '" + pos1 + " - " + pos2 + "; " + type + "';\n";
129234
+ html += " line.appendChild(title);\n";
129235
+
129090
129236
  html += " rnaCanvas.drawing.domNode.appendChild(line);";
129091
129237
  html += "}\n";
129092
129238
  }
@@ -129107,10 +129253,12 @@ class Diagram2d {
129107
129253
  $("#" + me.pre + "rnacanvasDiv").html(html);
129108
129254
  }
129109
129255
 
129110
- async drawIgdgm(chainid) { let ic = this.icn3d, me = ic.icn3dui;
129256
+ async drawIgdgm(chainid, bDownload) { let ic = this.icn3d, me = ic.icn3dui;
129111
129257
  // select the current chain
129112
129258
  //ic.hAtoms = me.hashUtilsCls.cloneHash(ic.chains[chainid]);
129113
129259
 
129260
+ ic.ig2ddgm_chainid = chainid;
129261
+
129114
129262
  // run ig detection
129115
129263
  ic.bRunRefnumAgain = true;
129116
129264
  if(!ic.bAnnoShown) await ic.showAnnoCls.showAnnotations();
@@ -129134,7 +129282,7 @@ class Diagram2d {
129134
129282
 
129135
129283
  let igType = ic.ref2igtype[info.refpdbname];
129136
129284
 
129137
- if(igType == 'IgV' || igType == 'IgC1' || igType == 'IgC2' || igType == 'IgI') {
129285
+ if(igType == 'IgV' || igType == 'IgC1' || igType == 'IgC2' || igType == 'IgI' || igType == 'IgFN3') {
129138
129286
  bFound = true;
129139
129287
  }
129140
129288
 
@@ -129142,12 +129290,12 @@ class Diagram2d {
129142
129290
  }
129143
129291
 
129144
129292
  if(!bFound) {
129145
- var aaa = 1; //alert("The Ig type(s) for chain " + chainid + " is/are " + igTypeArray + ". Currently only IgV, IgC1, IgC2 and IgI types are supported for drawing Ig diagrams.");
129293
+ var aaa = 1; //alert("The Ig type(s) for chain " + chainid + " is/are " + igTypeArray + ". Currently only IgV, IgC1, IgC2, IgI and IgFN3 types are supported for drawing Ig diagrams.");
129146
129294
  return;
129147
129295
  }
129148
129296
 
129149
129297
  // get the hash of refnum to resn
129150
- let refnum2resn = {};
129298
+ ic.refnum2resn = {};
129151
129299
  for(let resid in ic.resid2refnum) {
129152
129300
  let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]);
129153
129301
  if(!atom) continue;
@@ -129160,88 +129308,154 @@ class Diagram2d {
129160
129308
 
129161
129309
  if(refnumLabel) {
129162
129310
  refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
129163
- if(!refnum2resn[domainid]) refnum2resn[domainid] = {};
129164
- refnum2resn[domainid][refnumStr] = resn + resid.split('_')[2];
129311
+ if(!ic.refnum2resn[domainid]) ic.refnum2resn[domainid] = {};
129312
+ ic.refnum2resn[domainid][refnumStr] = resn + resid.split('_')[2];
129165
129313
  }
129166
129314
  }
129167
129315
 
129168
- if(ic.bXlsx === undefined) {
129169
- let urlScript = "/Structure/icn3d/script/exceljs.min.js";
129170
- await me.getAjaxPromise(urlScript, 'script');
129316
+ if(bDownload) {
129317
+ if(ic.bXlsx === undefined) {
129318
+ let urlScript = "/Structure/icn3d/script/exceljs.min.js";
129319
+ await me.getAjaxPromise(urlScript, 'script');
129171
129320
 
129172
- ic.bXlsx = true;
129173
- }
129321
+ ic.bXlsx = true;
129322
+ }
129174
129323
 
129175
- const mainWorkbook = new ExcelJS.Workbook();
129324
+ const mainWorkbook = new ExcelJS.Workbook();
129176
129325
 
129177
- let ig2width = {'IgC1': 17, 'IgC2': 18, 'IgI': 19, 'IgV': 19};
129326
+ let ig2width = {'IgC1': 17, 'IgC2': 18, 'IgI': 19, 'IgV': 19};
129178
129327
 
129179
- for(let i = 0, il = igArray.length; i < il; ++i) {
129180
- let domainid = igArray[i].domainid;
129181
- let igType = igTypeArray[i];
129182
- if(!(igType == 'IgV' || igType == 'IgC1' || igType == 'IgC2' || igType == 'IgI')) {
129183
- mainWorkbook.addWorksheet((i + 1) + ". " + igType);
129184
- }
129185
- else {
129186
- let url = "/Structure/icn3d/template/igstrand_template_" + igType + ".xlsx";
129187
- let arrayBuffer = await me.getXMLHttpRqstPromise(url, 'GET', 'arraybuffer', 'xlsx');
129188
-
129189
- const workbook = new ExcelJS.Workbook();
129190
- // Load the workbook from the buffer
129191
- await workbook.xlsx.load(arrayBuffer);
129192
- const worksheet = workbook.getWorksheet(1);
129193
-
129194
- const newSheet = mainWorkbook.addWorksheet();
129195
- // Clone the model to transfer styles and data
129196
- newSheet.model = worksheet.model;
129197
- newSheet.name = (i + 1) + ". " + igType;
129198
-
129199
- // Iterate over all rows that have values
129200
- newSheet.eachRow({ includeEmpty: true }, (row, rowNumber) => {
129201
- // Iterate over all cells in the row
129202
- row.eachCell({ includeEmpty: true }, (cell, colNumber) => {
129203
- //console.log(`Cell [${rowNumber}, ${colNumber}] = ${cell.value}`);
129204
- if (cell.value && !isNaN(cell.value) && cell.value > 1000 && cell.value < 10000) {
129205
- if(refnum2resn[domainid].hasOwnProperty(cell.value)) {
129206
- cell.value = refnum2resn[domainid][cell.value];
129328
+ for(let i = 0, il = igArray.length; i < il; ++i) {
129329
+ let domainid = igArray[i].domainid;
129330
+ let igType = igTypeArray[i];
129331
+ if(!(igType == 'IgV' || igType == 'IgC1' || igType == 'IgC2' || igType == 'IgI' || igType == 'IgFN3')) {
129332
+ mainWorkbook.addWorksheet((i + 1) + ". " + igType);
129333
+ }
129334
+ else {
129335
+ let url = "/Structure/icn3d/template/igstrand_template_" + igType + ".xlsx";
129336
+ let arrayBuffer = await me.getXMLHttpRqstPromise(url, 'GET', 'arraybuffer', 'xlsx');
129337
+
129338
+ const workbook = new ExcelJS.Workbook();
129339
+ // Load the workbook from the buffer
129340
+ await workbook.xlsx.load(arrayBuffer);
129341
+ const worksheet = workbook.getWorksheet(1);
129342
+
129343
+ const newSheet = mainWorkbook.addWorksheet();
129344
+ // Clone the model to transfer styles and data
129345
+ newSheet.model = worksheet.model;
129346
+ newSheet.name = (i + 1) + ". " + igType;
129347
+
129348
+ // Iterate over all rows that have values
129349
+ newSheet.eachRow({ includeEmpty: true }, (row, rowNumber) => {
129350
+ // Iterate over all cells in the row
129351
+ row.eachCell({ includeEmpty: true }, (cell, colNumber) => {
129352
+ //console.log(`Cell [${rowNumber}, ${colNumber}] = ${cell.value}`);
129353
+ if (cell.value && !isNaN(cell.value) && cell.value > 1000 && cell.value < 10000) {
129354
+ if(ic.refnum2resn[domainid].hasOwnProperty(cell.value)) {
129355
+ cell.value = ic.refnum2resn[domainid][cell.value];
129356
+ }
129357
+ else {
129358
+ cell.value = '';
129359
+ }
129207
129360
  }
129208
- else {
129361
+ else if(cell.value == 'NUMBERING') {
129209
129362
  cell.value = '';
129210
129363
  }
129211
- }
129212
- else if(cell.value == 'NUMBERING') {
129213
- cell.value = '';
129214
- }
129364
+ });
129215
129365
  });
129216
- });
129217
129366
 
129218
- // copy the original data
129219
- let colNum = ig2width[igType]; // some extra columns
129220
- for(let i = 1; i <= colNum; ++i) {
129221
- const sourceCol = worksheet.getColumn(i);
129367
+ // copy the original data
129368
+ let colNum = ig2width[igType]; // some extra columns
129369
+ for(let i = 1; i <= colNum; ++i) {
129370
+ const sourceCol = worksheet.getColumn(i);
129222
129371
 
129223
- // Copy values and styles
129224
- sourceCol.eachCell({ includeEmpty: true }, (cell, rowNumber) => {
129225
- const targetCell = newSheet.getRow(rowNumber).getCell(colNum + 2 + i);
129226
-
129227
- targetCell.value = cell.value;
129228
- targetCell.style = cell.style; // Copies font, borders, and fills
129229
- });
129372
+ // Copy values and styles
129373
+ sourceCol.eachCell({ includeEmpty: true }, (cell, rowNumber) => {
129374
+ const targetCell = newSheet.getRow(rowNumber).getCell(colNum + 2 + i);
129375
+
129376
+ targetCell.value = cell.value;
129377
+ targetCell.style = cell.style; // Copies font, borders, and fills
129378
+ });
129230
129379
 
129231
- // reset width for each column
129232
- newSheet.getColumn(colNum + 2 + i).width = worksheet.getColumn(i).width;
129380
+ // reset width for each column
129381
+ newSheet.getColumn(colNum + 2 + i).width = worksheet.getColumn(i).width;
129382
+ }
129233
129383
  }
129234
129384
  }
129235
- }
129236
129385
 
129237
- // Generate the workbook as a Buffer
129238
- const data = await mainWorkbook.xlsx.writeBuffer();
129386
+ // Generate the workbook as a Buffer
129387
+ const data = await mainWorkbook.xlsx.writeBuffer();
129388
+
129389
+ // Access the underlying ArrayBuffer
129390
+ ic.saveFileCls.saveFile(ic.inputid + '_ig_diagram.xlsx', 'xlsx', data);
129391
+ }
129392
+ else { // show interactive SVG
129393
+ // generate a dropdown menu
129394
+ let menuHtml = '';
129395
+ for(let i = 0, il = igArray.length; i < il; ++i) {
129396
+ igArray[i].domainid;
129397
+ let igType = igTypeArray[i];
129398
+
129399
+ let selStr = (i == 0) ? ' selected' : '';
129400
+ menuHtml += "<option value='" + i + '_' + igType + "' " + selStr + ">" + (i+1) + ". " + igType + "</option>";
129401
+ }
129402
+ $("#" + me.pre + "iglist").html(menuHtml);
129403
+
129404
+ await this.show2DdgmForIg(0, igTypeArray[0]); // default
129239
129405
 
129240
- // Access the underlying ArrayBuffer
129241
- ic.saveFileCls.saveFile(ic.inputid + '_ig_diagram.xlsx', 'xlsx', data);
129406
+ $("#" + me.pre + "iglist").resizable();
129407
+ }
129242
129408
 
129243
129409
  ic.drawCls.draw();
129244
129410
  }
129411
+
129412
+ async show2DdgmForIg(igIndex, igType) { let ic = this.icn3d, me = ic.icn3dui;
129413
+ if(!(igType == 'IgV' || igType == 'IgC1' || igType == 'IgC2' || igType == 'IgI' || igType == 'IgFN3')) {
129414
+ var aaa = 1; //alert("This Ig type " + igType + "has no 2D template yet...");
129415
+ return '';
129416
+ }
129417
+ else {
129418
+ let url = "/Structure/icn3d/template/igstrand_template_" + igType + ".svg";
129419
+ let svgHtml = await me.getAjaxPromise(url, 'text');
129420
+
129421
+ let igArray = ic.chain2igArray[ic.ig2ddgm_chainid];
129422
+ let domainid = igArray[igIndex].domainid;
129423
+
129424
+ // loop through all text node
129425
+ let lineArray = svgHtml.split('\n');
129426
+
129427
+ let html = '';
129428
+ for(let i = 0, il = lineArray.length; i < il; ++i) {
129429
+ let line = lineArray[i];
129430
+ if(line.indexOf('<text ') == 0) { // <text x="502.1" y="301.8" class="s9 c8547"><title>Ref. Num. 8547</title> 8547 </text>
129431
+ let pos = line.indexOf('</title> ');
129432
+ let refnumStr = line.substr(pos + 9).split(' ')[0];
129433
+ let refnum = parseInt(refnumStr);
129434
+
129435
+ if(!isNaN(refnumStr) && refnum > 1000 && refnum < 10000) {
129436
+ if(ic.refnum2resn[domainid].hasOwnProperty(refnumStr)) {
129437
+ let resn = ic.refnum2resn[domainid][refnumStr];
129438
+ let pos2 = line.indexOf('class=');
129439
+ html += line.substr(0, pos2) + 'class="node ' + line.substr(pos2 + 7, pos - (pos2 + 7)) + '</title> ' + resn + ' </text>';
129440
+ }
129441
+ else {
129442
+ html += line.substr(0, pos) + '</title> </text>';
129443
+ }
129444
+ }
129445
+ else {
129446
+ html += line + '\n';
129447
+ }
129448
+ }
129449
+ else {
129450
+ html += line + '\n';
129451
+ }
129452
+ }
129453
+
129454
+ $("#" + me.pre + "ig2ddgmDiv").html(html);
129455
+
129456
+ me.htmlCls.dialogCls.openDlg('dl_ig2ddgm', 'Show 2D diagram for Ig ' + (igIndex + 1) + '.' + igType + ' in ' + ic.ig2ddgm_chainid);
129457
+ }
129458
+ }
129245
129459
  }
129246
129460
 
129247
129461
  /**
@@ -135523,7 +135737,7 @@ class iCn3DUI {
135523
135737
  //even when multiple iCn3D viewers are shown together.
135524
135738
  this.pre = this.cfg.divid + "_";
135525
135739
 
135526
- this.REVISION = '3.50.0';
135740
+ this.REVISION = '3.51.0';
135527
135741
 
135528
135742
  // In nodejs, iCn3D defines "window = {navigator: {}}", and added window = {navigator: {}, "__THREE__":"177"}
135529
135743
  this.bNode = (Object.keys(window).length < 3) ? true : false;