icn3d 3.50.1 → 3.51.1

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
@@ -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,9 +84121,82 @@ 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
+
84131
+ let clusterArray = this.clusterLinkedNodes(clbondArray);
84132
+
84133
+ for(let i = 0, il = clusterArray.length; i < il; ++i) {
84134
+ let rootResid = 0;
84135
+ for(let j = 0, jl = clusterArray[i].length; j < jl; ++j) {
84136
+ let resid = clusterArray[i][j];
84137
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]);
84138
+
84139
+ if(ic.proteins.hasOwnProperty(atom.serial) || ic.nucleotides.hasOwnProperty(atom.serial)) {
84140
+ rootResid = resid;
84141
+ break;
84142
+ }
84143
+ }
84144
+
84145
+ if(rootResid) {
84146
+ for(let j = 0, jl = clusterArray[i].length; j < jl; ++j) {
84147
+ let resid = clusterArray[i][j];
84148
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]);
84149
+
84150
+ if(ic.chemicals.hasOwnProperty(atom.serial)) {
84151
+ ic.residues[rootResid] = me.hashUtilsCls.unionHash(ic.residues[rootResid], ic.residues[resid]);
84152
+ }
84153
+ }
84154
+ }
84155
+ }
84156
+ }
84157
+
84092
84158
  return ic.residuesHashClbonds;
84093
84159
  }
84094
84160
 
84161
+ clusterLinkedNodes(clbondArray) { let ic = this.icn3d; ic.icn3dui;
84162
+ const parent = new Map();
84163
+
84164
+ // Find the root of a node, with path compression
84165
+ function find(node) {
84166
+ if (!parent.has(node)) parent.set(node, node);
84167
+ if (parent.get(node) !== node) {
84168
+ parent.set(node, find(parent.get(node))); // path compression
84169
+ }
84170
+ return parent.get(node);
84171
+ }
84172
+
84173
+ // Union two nodes into the same cluster
84174
+ function union(a, b) {
84175
+ const rootA = find(a);
84176
+ const rootB = find(b);
84177
+ if (rootA !== rootB) parent.set(rootA, rootB);
84178
+ }
84179
+
84180
+ // Process all pairs
84181
+ // for (const [a, b] of pairs) {
84182
+ // union(a, b);
84183
+ // }
84184
+
84185
+ for(let i = 0, il = clbondArray.length; i < il; i = i + 2) {
84186
+ union(clbondArray[i], clbondArray[i+1]);
84187
+ }
84188
+
84189
+ // Group nodes by their root
84190
+ const clusters = new Map();
84191
+ for (const node of parent.keys()) {
84192
+ const root = find(node);
84193
+ if (!clusters.has(root)) clusters.set(root, []);
84194
+ clusters.get(root).push(node);
84195
+ }
84196
+
84197
+ return Array.from(clusters.values());
84198
+ }
84199
+
84095
84200
  applyClbondsOptions_base(type) { let ic = this.icn3d, me = ic.icn3dui;
84096
84201
  // only apply to displayed atoms
84097
84202
  let atomHash = me.hashUtilsCls.cloneHash(ic.chemicals);
@@ -84194,6 +84299,9 @@ class ApplyMissingRes {
84194
84299
  let bStart = false;
84195
84300
  let startResid, currResid, prevResid;
84196
84301
  let bCurrCoord, bPrevCoord = false;
84302
+
84303
+ if(!ic.chainsSeq[chainid]) continue;
84304
+
84197
84305
  for(let i = 0, il = ic.chainsSeq[chainid].length; i < il; ++i) {
84198
84306
  currResid = chainid + '_' + ic.chainsSeq[chainid][i].resi;
84199
84307
 
@@ -84435,7 +84543,7 @@ class ApplyDisplay {
84435
84543
 
84436
84544
  // remove schematic labels
84437
84545
  //if(ic.labels !== undefined) ic.labels['schematic'] = undefined;
84438
- if(ic.labels !== undefined) delete ic.labels['schematic'];
84546
+ if(!bHighlight && ic.labels !== undefined) delete ic.labels['schematic'];
84439
84547
  /*
84440
84548
  if(bHighlight) {
84441
84549
  //let residueHashCalpha = ic.firstAtomObjCls.getResiduesFromCalphaAtoms(ic.hAtoms);
@@ -84456,6 +84564,7 @@ class ApplyDisplay {
84456
84564
  //var bPhosphorusOnly = me.utilsCls.isCalphaPhosOnly(me.hashUtilsCls.hash2Atoms(atomHash), "O3'", "O3*") || me.utilsCls.isCalphaPhosOnly(me.hashUtilsCls.hash2Atoms(atomHash), "P");
84457
84565
  //let bPhosphorusOnly = me.utilsCls.isCalphaPhosOnly(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms));
84458
84566
  let nucleotidesAtoms = me.hashUtilsCls.intHash(atomHash, ic.nucleotides);
84567
+
84459
84568
  let bPhosphorusOnly = me.utilsCls.isCalphaPhosOnly(me.hashUtilsCls.hash2Atoms(nucleotidesAtoms, ic.atoms));
84460
84569
 
84461
84570
  if(style === 'ribbon') {
@@ -84494,13 +84603,13 @@ class ApplyDisplay {
84494
84603
 
84495
84604
  //if(firstAtom.het) { // chemicals
84496
84605
  if(ic.chemicals.hasOwnProperty(firstAtom.serial)) { // chemicals
84497
- ic.residueLabelsCls.addNonCarbonAtomLabels(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms));
84606
+ if(!bHighlight) ic.residueLabelsCls.addNonCarbonAtomLabels(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms));
84498
84607
 
84499
84608
  let bSchematic = true;
84500
84609
  ic.stickCls.createStickRepresentation(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), chemicalSchematicRadius, chemicalSchematicRadius, undefined, bHighlight, bSchematic);
84501
84610
  }
84502
84611
  else { // nucleotides or proteins
84503
- ic.residueLabelsCls.addResidueLabels(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), true);
84612
+ if(!bHighlight) ic.residueLabelsCls.addResidueLabels(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), true);
84504
84613
 
84505
84614
  if(bPhosphorusOnly) {
84506
84615
  ic.cylinderCls.createCylinderCurve(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), ["P"], ic.traceRadius, false, bHighlight);
@@ -90116,7 +90225,7 @@ class SetOption {
90116
90225
  ic.atoms[i].style2 = style;
90117
90226
  }
90118
90227
  }
90119
- else {
90228
+ else {
90120
90229
  for(let i in atoms) {
90121
90230
  ic.atoms[i].style = style;
90122
90231
  }
@@ -107193,11 +107302,11 @@ class BcifParser {
107193
107302
 
107194
107303
  let chain1Array = struct_conn.getColumn("ptnr1_auth_asym_id");
107195
107304
  let name1Array = struct_conn.getColumn("ptnr1_label_atom_id");
107196
- let resi1Array = struct_conn.getColumn("ptnr1_label_seq_id");
107305
+ let resi1Array = struct_conn.getColumn("ptnr1_auth_seq_id");
107197
107306
 
107198
107307
  let chain2Array = struct_conn.getColumn("ptnr2_auth_asym_id");
107199
107308
  let name2Array = struct_conn.getColumn("ptnr2_label_atom_id");
107200
- let resi2Array = struct_conn.getColumn("ptnr2_label_seq_id");
107309
+ let resi2Array = struct_conn.getColumn("ptnr2_auth_seq_id");
107201
107310
 
107202
107311
  let connSize = struct_conn.rowCount;
107203
107312
  for (let i = 0; i < connSize; ++i) {
@@ -107389,7 +107498,7 @@ class BcifParser {
107389
107498
  else {
107390
107499
  // bond between this atom and all other atom in the same residue
107391
107500
  for(let j in mResi2Atoms[currResi]) { // j is atom.id
107392
- if(this.hasCovalentBond(atom, mResi2Atoms[currResi][j], para)) {
107501
+ if(this.hasCovalentBond2(atom, mResi2Atoms[currResi][j], para)) {
107393
107502
  if(!mId2Set.hasOwnProperty(atom.id)) mId2Set[atom.id] = {};
107394
107503
  if(!mId2Set.hasOwnProperty(mResi2Atoms[currResi][j].id)) mId2Set[mResi2Atoms[currResi][j].id] = {};
107395
107504
  mId2Set[atom.id][mResi2Atoms[currResi][j].id] = 1;
@@ -107402,7 +107511,7 @@ class BcifParser {
107402
107511
 
107403
107512
  // bond between N and previous C
107404
107513
  if(name == "N" && prevC.id != "") {
107405
- if(this.hasCovalentBond(atom, prevC, para)) {
107514
+ if(this.hasCovalentBond2(atom, prevC, para)) {
107406
107515
  if(!mId2Set.hasOwnProperty(atom.id)) mId2Set[atom.id] = {};
107407
107516
  if(!mId2Set.hasOwnProperty(prevC.id)) mId2Set[prevC.id] = {};
107408
107517
  mId2Set[atom.id][prevC.id] = 1;
@@ -107743,7 +107852,7 @@ class BcifParser {
107743
107852
  return text;
107744
107853
  }
107745
107854
 
107746
- hasCovalentBond(atom1, atom2, para) { let ic = this.icn3d; ic.icn3dui;
107855
+ hasCovalentBond2(atom1, atom2, para) { let ic = this.icn3d; ic.icn3dui;
107747
107856
  let r = this.mElem2Radius[atom1.elem] + this.mElem2Radius[atom2.elem];
107748
107857
 
107749
107858
  let dx = (atom1.x - atom2.x);
@@ -116017,6 +116126,10 @@ class LoadPDB {
116017
116126
  setResidMapping() { let ic = this.icn3d; ic.icn3dui;
116018
116127
  // set ic.ncbi2resid and ic.resid2ncbi
116019
116128
  for(let chainid in ic.chainsSeq) {
116129
+ if(!ic.chainsSeq[chainid]) {
116130
+ continue;
116131
+ }
116132
+
116020
116133
  for(let j = 0, jl = ic.chainsSeq[chainid].length; j < jl; ++j) {
116021
116134
  // NCBI residue number starts from 1 and increases continuously
116022
116135
  let residNCBI = chainid + '_' + (j+1).toString();
@@ -116366,6 +116479,7 @@ class LoadCIF {
116366
116479
  chain1Array = resi1Array = resi2Array = [];
116367
116480
  }
116368
116481
 
116482
+ // let vBonds = [];
116369
116483
  if(block.getCategory("_struct_conn")) {
116370
116484
  ic.bSsbondProvided = true;
116371
116485
 
@@ -116376,11 +116490,13 @@ class LoadCIF {
116376
116490
 
116377
116491
  let chain1Array = struct_conn.getColumn("ptnr1_auth_asym_id");
116378
116492
  let name1Array = struct_conn.getColumn("ptnr1_label_atom_id");
116379
- let resi1Array = struct_conn.getColumn("ptnr1_label_seq_id");
116493
+ let resi1Array = struct_conn.getColumn("ptnr1_auth_seq_id");
116494
+ // let resn1Array = struct_conn.getColumn("ptnr1_auth_comp_id");
116380
116495
 
116381
116496
  let chain2Array = struct_conn.getColumn("ptnr2_auth_asym_id");
116382
116497
  let name2Array = struct_conn.getColumn("ptnr2_label_atom_id");
116383
- let resi2Array = struct_conn.getColumn("ptnr2_label_seq_id");
116498
+ let resi2Array = struct_conn.getColumn("ptnr2_auth_seq_id");
116499
+ // let resn2Array = struct_conn.getColumn("ptnr2_auth_comp_id");
116384
116500
 
116385
116501
  let connSize = struct_conn.rowCount;
116386
116502
  for (let i = 0; i < connSize; ++i) {
@@ -116389,21 +116505,24 @@ class LoadCIF {
116389
116505
  let chain1 = chain1Array.getString(i);
116390
116506
  name1Array.getString(i);
116391
116507
  let resi1 = resi1Array.getString(i);
116508
+ // let resn1 = resn1Array.getString(i);
116392
116509
  let id1 = structure + '_' + chain1 + "_" + resi1;
116510
+
116511
+ // let chain1Tmp = (me.parasCls.residueAbbrev.hasOwnProperty(resn1)) ? chain1 : resn1;
116512
+ // let bondId1 = chain1Tmp + "_" + resi1 + "_" + name1;
116393
116513
 
116394
116514
  let chain2 = chain2Array.getString(i);
116395
116515
  name2Array.getString(i);
116396
116516
  let resi2 = resi2Array.getString(i);
116517
+ // let resn2 = resn2Array.getString(i);
116397
116518
  let id2 = structure + '_' + chain2 + "_" + resi2;
116398
-
116399
- // Verify that the linkage is covalent, as indicated by the conn_type_id attribute2
116400
-
116401
- // if (conn_type_id == "covale") {
116402
- // vBonds.push(id1);
116403
- // vBonds.push(id2);
116404
- // }
116405
-
116406
- if(conn_type_id == "disulf") {
116519
+
116520
+ // let chain2Tmp = (me.parasCls.residueAbbrev.hasOwnProperty(resn2)) ? chain2 : resn2;
116521
+ // let bondId2 = chain2Tmp + "_" + resi2 + "_" + name2;
116522
+
116523
+ // Verify that the linkage is covalent, as indicated by the conn_type_id attribute2
116524
+ if (conn_type_id == "covale") ;
116525
+ else if(conn_type_id == "disulf") {
116407
116526
  if(ic.ssbondpnts[structure] === undefined) ic.ssbondpnts[structure] = [];
116408
116527
 
116409
116528
  ic.ssbondpnts[structure].push(id1);
@@ -116536,6 +116655,7 @@ class LoadCIF {
116536
116655
  let nameArray = atom_site.getColumn("label_atom_id");
116537
116656
  let entiyidArray = atom_site.getColumn("label_entity_id");
116538
116657
 
116658
+ // check 3QUM
116539
116659
  let chainArray = atom_site.getColumn("auth_asym_id");
116540
116660
 
116541
116661
  let resiArray = atom_site.getColumn("label_seq_id");
@@ -116557,7 +116677,6 @@ class LoadCIF {
116557
116677
  let sChain = {};
116558
116678
  let prevModelNum = '';
116559
116679
  if(!ic.molid2chain) ic.molid2chain = {};
116560
-
116561
116680
  for (let i = 0; i < atomSize; ++i) {
116562
116681
  let modelNum = modelNumArray.getString(i);
116563
116682
  if(i > 0 && modelNum != prevModelNum) {
@@ -116585,7 +116704,6 @@ class LoadCIF {
116585
116704
 
116586
116705
  let autochain = autochainArray.getString(i);
116587
116706
 
116588
-
116589
116707
  resi = oriResi;
116590
116708
 
116591
116709
  let molecueType;
@@ -116604,7 +116722,7 @@ class LoadCIF {
116604
116722
  }
116605
116723
  else {
116606
116724
  molecueType = "ligand"; // ligands or ions
116607
- chain = resn;
116725
+ if(chain == "?" || chain == ".") chain = resn; // check 3QUM
116608
116726
  }
116609
116727
  }
116610
116728
  if(chain === '') chain = 'A';
@@ -116694,6 +116812,8 @@ class LoadCIF {
116694
116812
  let z = zArray.getFloat(i);
116695
116813
  let coord = new Vector3$1(x, y, z);
116696
116814
 
116815
+ let id = serial.toString();
116816
+
116697
116817
  let atomDetails = {
116698
116818
  het: (atom_hetatm == "HETATM"), // optional, used to determine chemicals, water, ions, etc
116699
116819
  serial: serial, // required, unique atom id
@@ -116850,6 +116970,30 @@ class LoadCIF {
116850
116970
  ic.residues[residueNum] = residuesTmp;
116851
116971
  if(ic.chains[chainNum] === undefined) ic.chains[chainNum] = {};
116852
116972
  ic.chains[chainNum] = me.hashUtilsCls.unionHash2Atoms(ic.chains[chainNum], chainsTmp, ic.atoms);
116973
+ /*
116974
+ /// add the defined bonds
116975
+ for(let i = 0; i < vBonds.length; i = i + 2) {
116976
+ let id1 = mName2Serial[vBonds[i]];
116977
+ let id2 = mName2Serial[vBonds[i+1]];
116978
+
116979
+ if(!mId2Set.hasOwnProperty(id1)) mId2Set[id1] = {};
116980
+ if(!mId2Set.hasOwnProperty(id2)) mId2Set[id2] = {};
116981
+ mId2Set[id1][id2] = 1;
116982
+ mId2Set[id2][id1] = 1;
116983
+ }
116984
+
116985
+ for(let id in mId2Set) {
116986
+ let sConnId = mId2Set[id];
116987
+ let vConnId = Object.keys(sConnId);
116988
+ let serial = parseInt(id);
116989
+
116990
+ for(let j = 0, jl = vConnId.length; j < jl; ++j) {
116991
+ if(vConnId[j] === 'undefined' || !ic.atoms[serial]) continue;
116992
+ if(!ic.atoms[serial].bonds) ic.atoms[serial].bonds = [];
116993
+ ic.atoms[serial].bonds.push(parseInt(vConnId[j]));
116994
+ }
116995
+ }
116996
+ */
116853
116997
 
116854
116998
  // clear memory
116855
116999
  atom_hetatmArray = resnArray = elemArray = nameArray = chainArray = resiArray = resiOriArray
@@ -117021,6 +117165,41 @@ class LoadCIF {
117021
117165
  }
117022
117166
  }
117023
117167
 
117168
+ // check the bonds between chemicals and all other atoms
117169
+ let processedChemicals = {};
117170
+ for(let i in ic.chemicals) {
117171
+ console.log(" i = ", i, " processedChemicals = ", processedChemicals);
117172
+ if(processedChemicals.hasOwnProperty(i)) continue;
117173
+
117174
+ let atom = ic.atoms[i];
117175
+ let resid = atom.structure + '_' + atom.chain + '_' + atom.resi;
117176
+
117177
+ let radius = 4;
117178
+ let residueAtoms = ic.residues[resid];
117179
+ let otherAtoms = me.hashUtilsCls.exclHash(ic.atoms, residueAtoms);
117180
+ let neighborAtoms = ic.contactCls.getAtomsWithinAtom(otherAtoms, residueAtoms, radius);
117181
+
117182
+ for(let j in residueAtoms) {
117183
+ let startAtom = ic.atoms[j];
117184
+ for(let k in neighborAtoms) {
117185
+ let neighborAtom = ic.atoms[k];
117186
+ let neighborResid = neighborAtom.structure + '_' + neighborAtom.chain + '_' + neighborAtom.resi;
117187
+ if(resid === neighborResid) continue;
117188
+
117189
+ if(me.utilsCls.hasCovalentBond(startAtom, neighborAtom)) {
117190
+ // Handle covalent bond
117191
+ if(!startAtom.bonds) startAtom.bonds = [];
117192
+ if(!neighborAtom.bonds) neighborAtom.bonds = [];
117193
+
117194
+ startAtom.bonds.push(neighborAtom.serial);
117195
+ neighborAtom.bonds.push(startAtom.serial);
117196
+ }
117197
+ }
117198
+ }
117199
+
117200
+ processedChemicals = me.hashUtilsCls.unionHash(processedChemicals, ic.residues[resid]);
117201
+ }
117202
+
117024
117203
  ic.pmin = pmin;
117025
117204
  ic.pmax = pmax;
117026
117205
 
@@ -118355,7 +118534,7 @@ class ApplyCommand {
118355
118534
  ic.definedSetsCls.deleteSelectedSets();
118356
118535
  }
118357
118536
  else if(command == 'view interactions' || command == 'view 2d diagram') {
118358
- if(me.cfg.mmdbid !== undefined || me.cfg.gi !== undefined) {
118537
+ if(me.cfg.mmdbid !== undefined || me.cfg.gi !== undefined || me.cfg.mmdbafid !== undefined) {
118359
118538
  ic.ParserUtilsCls.set2DDiagrams(ic.inputid);
118360
118539
  }
118361
118540
  }
@@ -119870,27 +120049,31 @@ class DefinedSets {
119870
120049
  let colorStr =(atom === undefined || atom.color === undefined || atom.color.getHexString().toUpperCase() === 'FFFFFF') ? 'DDDDDD' : atom.color.getHexString();
119871
120050
  let color =(atom !== undefined && atom.color !== undefined) ? colorStr : '000000';
119872
120051
 
119873
- if(bNucleotide && atom) {
120052
+ if(bNucleotide) {
119874
120053
  // Handle nucleotide-specific logic
119875
- if(ic.nucleotides.hasOwnProperty(atom.serial) && name.split('_').length == 2 && !ic.structures.hasOwnProperty(name)) {
120054
+ if(atom && ic.nucleotides.hasOwnProperty(atom.serial) && name.split('_').length == 2 && !ic.structures.hasOwnProperty(name)) {
119876
120055
  let selectStr = (cnt == 0) ? "selected" : "";
119877
120056
 
120057
+ if(cnt == 0) this.selectSets([name]);
120058
+
119878
120059
  html += "<option value='" + name + "' style='color:#" + color + "' " + selectStr + ">" + name + "</option>";
119879
120060
  bFoundNucleotide = true;
119880
120061
  ++cnt;
119881
120062
  }
119882
120063
  }
119883
- else if(bProtein && atom) {
120064
+ else if(bProtein) {
119884
120065
  // Handle protein-specific logic
119885
- if(ic.proteins.hasOwnProperty(atom.serial) && name.split('_').length == 2 && !ic.structures.hasOwnProperty(name)) {
120066
+ if(atom && ic.proteins.hasOwnProperty(atom.serial) && name.split('_').length == 2 && !ic.structures.hasOwnProperty(name)) {
119886
120067
  let selectStr = (cnt == 0) ? "selected" : "";
119887
120068
 
120069
+ if(cnt == 0) this.selectSets([name]);
120070
+
119888
120071
  html += "<option value='" + name + "' style='color:#" + color + "' " + selectStr + ">" + name + "</option>";
119889
120072
  bFoundProtein = true;
119890
120073
  ++cnt;
119891
120074
  }
119892
120075
  }
119893
- else {
120076
+ else {
119894
120077
  if(commandnameArray.indexOf(name) != -1) {
119895
120078
  html += "<option value='" + name + "' style='color:#" + color + "' selected='selected'>" + name + "</option>";
119896
120079
  }
@@ -121073,6 +121256,20 @@ class LoadScript {
121073
121256
  await ic.diagram2dCls.drawIgdgm(chainid);
121074
121257
  ic.bRender = false;
121075
121258
  }
121259
+ else if(command.indexOf('update ig') == 0) {
121260
+ let paraArray = command.split(' ');
121261
+ let igIndex_igType = (paraArray.length == 3) ? paraArray[2] : '';
121262
+ await ic.diagram2dCls.show2DdgmForIg(igIndex_igType[0], igIndex_igType[1]);
121263
+ }
121264
+ else if(command.indexOf('download 2d ig') == 0) {
121265
+ let paraArray = command.split(' | ');
121266
+ let pos = command.lastIndexOf(' ');
121267
+ let chainid = (paraArray.length == 2) ? paraArray[1] : command.substr(pos + 1);
121268
+
121269
+ ic.bRender = true;
121270
+ await ic.diagram2dCls.drawIgdgm(chainid, true);
121271
+ ic.bRender = false;
121272
+ }
121076
121273
  else if(command.indexOf('add msa track') == 0) {
121077
121274
  //add msa track | chainid " + chainid + " | startpos " + startpos + " | type " + type + " | fastaList " + fastaList
121078
121275
  let paraArray = command.split(' | ');
@@ -128419,6 +128616,74 @@ class Diagram2d {
128419
128616
  //}
128420
128617
  }
128421
128618
  });
128619
+
128620
+ //$("#" + me.pre + "ig2ddgmDiv").html(svgHtml);
128621
+ $(document).on("change", "#" + me.pre + "iglist", async function(e) { thisClass.icn3d;
128622
+ let igIndex_igType = $("#" + me.pre + "iglist").val().split('_');
128623
+
128624
+ await thisClass.show2DdgmForIg(igIndex_igType[0], igIndex_igType[1]);
128625
+
128626
+ me.htmlCls.clickMenuCls.setLogCmd('update ig ' + igIndex_igType, true);
128627
+ });
128628
+
128629
+ // ig 2D diagram: 2D -> 3D
128630
+ $(document).on('click', '#ig2ddgmSvg .node', function(e) { let ic = thisClass.icn3d;
128631
+ // clear all node color
128632
+ thisClass.resetAllNodes('ig2ddgmSvg');
128633
+
128634
+ $(this).css({'font-size': '20px', 'font-weight': 'bold'});
128635
+
128636
+ //<text x="502.1" y="301.8" class="s9 c8547"><title>Ref. Num. 8547</title> N99 </text>
128637
+ let text = $(this).html().trim();
128638
+ let resnresi = text.substr(text.lastIndexOf(' ') + 1);
128639
+
128640
+ let resid = ic.ncbi2resid[ic.ig2ddgm_chainid + '_' + resnresi.substr(1)];
128641
+
128642
+ // highlight the selected residue
128643
+ if(ic.bCtrl || ic.bShift) {
128644
+ ic.hAtoms = me.hashUtilsCls.unionHash(ic.hAtoms, ic.residues[resid]);
128645
+ }
128646
+ else {
128647
+ ic.hAtoms = ic.residues[resid];
128648
+ }
128649
+
128650
+ ic.hlUpdateCls.showHighlight();
128651
+ });
128652
+
128653
+ // $(document).on('mouseout', '#ig2ddgmSvg .node', function(e) { let ic = thisClass.icn3d;
128654
+ // thisClass.resetAllNodes('ig2ddgmSvg');
128655
+ // });
128656
+
128657
+ // ig 2D diagram: 3D -> 2D
128658
+ $(document).on('icn3d.pick.click icn3d.pick.mouseover', function(ev, data) { let ic = thisClass.icn3d;
128659
+ // get the residues in the selection
128660
+ let ncbiresid = data;
128661
+ let resid = ic.ncbi2resid[ncbiresid];
128662
+
128663
+ if(ic.ig2ddgm_chainid && ic.resid2refnum && ic.resid2refnum[resid]) {
128664
+ let refnumLabel = ic.resid2refnum[resid];
128665
+ let refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
128666
+
128667
+ // clear all node color
128668
+ thisClass.resetAllNodes('ig2ddgmSvg');
128669
+
128670
+ // highlight the residue
128671
+ $("#ig2ddgmSvg .c" + refnumStr).css({'font-size': '20px', 'font-weight': 'bold'});
128672
+ }
128673
+ });
128674
+ }
128675
+
128676
+ // reset all nodes
128677
+ resetAllNodes(id) { let ic = this.icn3d; ic.icn3dui;
128678
+ // Select the SVG container
128679
+ const svg = document.getElementById(id);
128680
+
128681
+ // Select all text-related nodes: <text>
128682
+ const textElements = svg.querySelectorAll('text');
128683
+
128684
+ textElements.forEach((node) => {
128685
+ node.style = {};
128686
+ });
128422
128687
  }
128423
128688
 
128424
128689
  clickNode(node) { let ic = this.icn3d, me = ic.icn3dui;
@@ -129086,7 +129351,12 @@ class Diagram2d {
129086
129351
  html += " line.setAttribute('y2', node2.y);\n";
129087
129352
  html += " line.setAttribute('stroke', 'black');\n";
129088
129353
  html += " line.setAttribute('stroke-width', '1');\n";
129089
- html += " line.setAttribute('title', '" + type + "');\n";
129354
+ //html += " line.setAttribute('title', '" + type + "');\n";
129355
+
129356
+ html += " var title = document.createElementNS('http://www.w3.org/2000/svg', 'title');\n";
129357
+ html += " title.textContent = '" + pos1 + " - " + pos2 + "; " + type + "';\n";
129358
+ html += " line.appendChild(title);\n";
129359
+
129090
129360
  html += " rnaCanvas.drawing.domNode.appendChild(line);";
129091
129361
  html += "}\n";
129092
129362
  }
@@ -129107,10 +129377,12 @@ class Diagram2d {
129107
129377
  $("#" + me.pre + "rnacanvasDiv").html(html);
129108
129378
  }
129109
129379
 
129110
- async drawIgdgm(chainid) { let ic = this.icn3d, me = ic.icn3dui;
129380
+ async drawIgdgm(chainid, bDownload) { let ic = this.icn3d, me = ic.icn3dui;
129111
129381
  // select the current chain
129112
129382
  //ic.hAtoms = me.hashUtilsCls.cloneHash(ic.chains[chainid]);
129113
129383
 
129384
+ ic.ig2ddgm_chainid = chainid;
129385
+
129114
129386
  // run ig detection
129115
129387
  ic.bRunRefnumAgain = true;
129116
129388
  if(!ic.bAnnoShown) await ic.showAnnoCls.showAnnotations();
@@ -129134,7 +129406,7 @@ class Diagram2d {
129134
129406
 
129135
129407
  let igType = ic.ref2igtype[info.refpdbname];
129136
129408
 
129137
- if(igType == 'IgV' || igType == 'IgC1' || igType == 'IgC2' || igType == 'IgI') {
129409
+ if(igType == 'IgV' || igType == 'IgC1' || igType == 'IgC2' || igType == 'IgI' || igType == 'IgFN3') {
129138
129410
  bFound = true;
129139
129411
  }
129140
129412
 
@@ -129142,12 +129414,12 @@ class Diagram2d {
129142
129414
  }
129143
129415
 
129144
129416
  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.");
129417
+ 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
129418
  return;
129147
129419
  }
129148
129420
 
129149
129421
  // get the hash of refnum to resn
129150
- let refnum2resn = {};
129422
+ ic.refnum2resn = {};
129151
129423
  for(let resid in ic.resid2refnum) {
129152
129424
  let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]);
129153
129425
  if(!atom) continue;
@@ -129160,88 +129432,154 @@ class Diagram2d {
129160
129432
 
129161
129433
  if(refnumLabel) {
129162
129434
  refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
129163
- if(!refnum2resn[domainid]) refnum2resn[domainid] = {};
129164
- refnum2resn[domainid][refnumStr] = resn + resid.split('_')[2];
129435
+ if(!ic.refnum2resn[domainid]) ic.refnum2resn[domainid] = {};
129436
+ ic.refnum2resn[domainid][refnumStr] = resn + resid.split('_')[2];
129165
129437
  }
129166
129438
  }
129167
129439
 
129168
- if(ic.bXlsx === undefined) {
129169
- let urlScript = "/Structure/icn3d/script/exceljs.min.js";
129170
- await me.getAjaxPromise(urlScript, 'script');
129440
+ if(bDownload) {
129441
+ if(ic.bXlsx === undefined) {
129442
+ let urlScript = "/Structure/icn3d/script/exceljs.min.js";
129443
+ await me.getAjaxPromise(urlScript, 'script');
129171
129444
 
129172
- ic.bXlsx = true;
129173
- }
129445
+ ic.bXlsx = true;
129446
+ }
129174
129447
 
129175
- const mainWorkbook = new ExcelJS.Workbook();
129448
+ const mainWorkbook = new ExcelJS.Workbook();
129176
129449
 
129177
- let ig2width = {'IgC1': 17, 'IgC2': 18, 'IgI': 19, 'IgV': 19};
129450
+ let ig2width = {'IgC1': 17, 'IgC2': 18, 'IgI': 19, 'IgV': 19};
129178
129451
 
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];
129452
+ for(let i = 0, il = igArray.length; i < il; ++i) {
129453
+ let domainid = igArray[i].domainid;
129454
+ let igType = igTypeArray[i];
129455
+ if(!(igType == 'IgV' || igType == 'IgC1' || igType == 'IgC2' || igType == 'IgI' || igType == 'IgFN3')) {
129456
+ mainWorkbook.addWorksheet((i + 1) + ". " + igType);
129457
+ }
129458
+ else {
129459
+ let url = "/Structure/icn3d/template/igstrand_template_" + igType + ".xlsx";
129460
+ let arrayBuffer = await me.getXMLHttpRqstPromise(url, 'GET', 'arraybuffer', 'xlsx');
129461
+
129462
+ const workbook = new ExcelJS.Workbook();
129463
+ // Load the workbook from the buffer
129464
+ await workbook.xlsx.load(arrayBuffer);
129465
+ const worksheet = workbook.getWorksheet(1);
129466
+
129467
+ const newSheet = mainWorkbook.addWorksheet();
129468
+ // Clone the model to transfer styles and data
129469
+ newSheet.model = worksheet.model;
129470
+ newSheet.name = (i + 1) + ". " + igType;
129471
+
129472
+ // Iterate over all rows that have values
129473
+ newSheet.eachRow({ includeEmpty: true }, (row, rowNumber) => {
129474
+ // Iterate over all cells in the row
129475
+ row.eachCell({ includeEmpty: true }, (cell, colNumber) => {
129476
+ //console.log(`Cell [${rowNumber}, ${colNumber}] = ${cell.value}`);
129477
+ if (cell.value && !isNaN(cell.value) && cell.value > 1000 && cell.value < 10000) {
129478
+ if(ic.refnum2resn[domainid].hasOwnProperty(cell.value)) {
129479
+ cell.value = ic.refnum2resn[domainid][cell.value];
129480
+ }
129481
+ else {
129482
+ cell.value = '';
129483
+ }
129207
129484
  }
129208
- else {
129485
+ else if(cell.value == 'NUMBERING') {
129209
129486
  cell.value = '';
129210
129487
  }
129211
- }
129212
- else if(cell.value == 'NUMBERING') {
129213
- cell.value = '';
129214
- }
129488
+ });
129215
129489
  });
129216
- });
129217
129490
 
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);
129491
+ // copy the original data
129492
+ let colNum = ig2width[igType]; // some extra columns
129493
+ for(let i = 1; i <= colNum; ++i) {
129494
+ const sourceCol = worksheet.getColumn(i);
129222
129495
 
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
- });
129496
+ // Copy values and styles
129497
+ sourceCol.eachCell({ includeEmpty: true }, (cell, rowNumber) => {
129498
+ const targetCell = newSheet.getRow(rowNumber).getCell(colNum + 2 + i);
129499
+
129500
+ targetCell.value = cell.value;
129501
+ targetCell.style = cell.style; // Copies font, borders, and fills
129502
+ });
129230
129503
 
129231
- // reset width for each column
129232
- newSheet.getColumn(colNum + 2 + i).width = worksheet.getColumn(i).width;
129504
+ // reset width for each column
129505
+ newSheet.getColumn(colNum + 2 + i).width = worksheet.getColumn(i).width;
129506
+ }
129233
129507
  }
129234
129508
  }
129235
- }
129236
129509
 
129237
- // Generate the workbook as a Buffer
129238
- const data = await mainWorkbook.xlsx.writeBuffer();
129510
+ // Generate the workbook as a Buffer
129511
+ const data = await mainWorkbook.xlsx.writeBuffer();
129512
+
129513
+ // Access the underlying ArrayBuffer
129514
+ ic.saveFileCls.saveFile(ic.inputid + '_ig_diagram.xlsx', 'xlsx', data);
129515
+ }
129516
+ else { // show interactive SVG
129517
+ // generate a dropdown menu
129518
+ let menuHtml = '';
129519
+ for(let i = 0, il = igArray.length; i < il; ++i) {
129520
+ igArray[i].domainid;
129521
+ let igType = igTypeArray[i];
129522
+
129523
+ let selStr = (i == 0) ? ' selected' : '';
129524
+ menuHtml += "<option value='" + i + '_' + igType + "' " + selStr + ">" + (i+1) + ". " + igType + "</option>";
129525
+ }
129526
+ $("#" + me.pre + "iglist").html(menuHtml);
129527
+
129528
+ await this.show2DdgmForIg(0, igTypeArray[0]); // default
129239
129529
 
129240
- // Access the underlying ArrayBuffer
129241
- ic.saveFileCls.saveFile(ic.inputid + '_ig_diagram.xlsx', 'xlsx', data);
129530
+ $("#" + me.pre + "iglist").resizable();
129531
+ }
129242
129532
 
129243
129533
  ic.drawCls.draw();
129244
129534
  }
129535
+
129536
+ async show2DdgmForIg(igIndex, igType) { let ic = this.icn3d, me = ic.icn3dui;
129537
+ if(!(igType == 'IgV' || igType == 'IgC1' || igType == 'IgC2' || igType == 'IgI' || igType == 'IgFN3')) {
129538
+ var aaa = 1; //alert("This Ig type " + igType + "has no 2D template yet...");
129539
+ return '';
129540
+ }
129541
+ else {
129542
+ let url = "/Structure/icn3d/template/igstrand_template_" + igType + ".svg";
129543
+ let svgHtml = await me.getAjaxPromise(url, 'text');
129544
+
129545
+ let igArray = ic.chain2igArray[ic.ig2ddgm_chainid];
129546
+ let domainid = igArray[igIndex].domainid;
129547
+
129548
+ // loop through all text node
129549
+ let lineArray = svgHtml.split('\n');
129550
+
129551
+ let html = '';
129552
+ for(let i = 0, il = lineArray.length; i < il; ++i) {
129553
+ let line = lineArray[i];
129554
+ if(line.indexOf('<text ') == 0) { // <text x="502.1" y="301.8" class="s9 c8547"><title>Ref. Num. 8547</title> 8547 </text>
129555
+ let pos = line.indexOf('</title> ');
129556
+ let refnumStr = line.substr(pos + 9).split(' ')[0];
129557
+ let refnum = parseInt(refnumStr);
129558
+
129559
+ if(!isNaN(refnumStr) && refnum > 1000 && refnum < 10000) {
129560
+ if(ic.refnum2resn[domainid].hasOwnProperty(refnumStr)) {
129561
+ let resn = ic.refnum2resn[domainid][refnumStr];
129562
+ let pos2 = line.indexOf('class=');
129563
+ html += line.substr(0, pos2) + 'class="node ' + line.substr(pos2 + 7, pos - (pos2 + 7)) + '</title> ' + resn + ' </text>';
129564
+ }
129565
+ else {
129566
+ html += line.substr(0, pos) + '</title> </text>';
129567
+ }
129568
+ }
129569
+ else {
129570
+ html += line + '\n';
129571
+ }
129572
+ }
129573
+ else {
129574
+ html += line + '\n';
129575
+ }
129576
+ }
129577
+
129578
+ $("#" + me.pre + "ig2ddgmDiv").html(html);
129579
+
129580
+ me.htmlCls.dialogCls.openDlg('dl_ig2ddgm', 'Show 2D diagram for Ig ' + (igIndex + 1) + '.' + igType + ' in ' + ic.ig2ddgm_chainid);
129581
+ }
129582
+ }
129245
129583
  }
129246
129584
 
129247
129585
  /**
@@ -135523,7 +135861,7 @@ class iCn3DUI {
135523
135861
  //even when multiple iCn3D viewers are shown together.
135524
135862
  this.pre = this.cfg.divid + "_";
135525
135863
 
135526
- this.REVISION = '3.50.0';
135864
+ this.REVISION = '3.51.0';
135527
135865
 
135528
135866
  // In nodejs, iCn3D defines "window = {navigator: {}}", and added window = {navigator: {}, "__THREE__":"177"}
135529
135867
  this.bNode = (Object.keys(window).length < 3) ? true : false;