icn3d 3.33.1 → 3.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/icn3d.module.js CHANGED
@@ -11301,8 +11301,8 @@ class ClickMenu {
11301
11301
  //if(!me.cfg.notebook) dialog.dialog( "close" );
11302
11302
  let sigma2fofc = parseFloat($("#" + me.pre + "sigma2fofc" ).val());
11303
11303
  let type = '2fofc';
11304
- await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma2fofc);
11305
- //ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma2fofc);
11304
+ //await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma2fofc);
11305
+ await ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma2fofc);
11306
11306
 
11307
11307
  //ic.setOptionCls.setOption('map', '2fofc');
11308
11308
  thisClass.setLogCmd('set map 2fofc sigma ' + sigma2fofc, true);
@@ -11314,7 +11314,8 @@ class ClickMenu {
11314
11314
  //if(!me.cfg.notebook) dialog.dialog( "close" );
11315
11315
  let sigmafofc = parseFloat($("#" + me.pre + "sigmafofc" ).val());
11316
11316
  let type = 'fofc';
11317
- await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigmafofc);
11317
+ //await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigmafofc);
11318
+ await ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma2fofc);
11318
11319
  //ic.setOptionCls.setOption('map', 'fofc');
11319
11320
  thisClass.setLogCmd('set map fofc sigma ' + sigmafofc, true);
11320
11321
  });
@@ -11863,6 +11864,18 @@ class ClickMenu {
11863
11864
  me.htmlCls.dialogCls.openDlg('dl_contact', 'Set contact map');
11864
11865
  });
11865
11866
 
11867
+ me.myEventCls.onIds(["#" + me.pre + "mn6_DSSP"], "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
11868
+ thisClass.setLogCmd('set dssp sse', true);
11869
+ await ic.pdbParserCls.applyCommandDssp();
11870
+ ic.bResetAnno = true;
11871
+
11872
+ if(ic.bAnnoShown) {
11873
+ await ic.showAnnoCls.showAnnotations();
11874
+
11875
+ ic.annotationCls.resetAnnoTabAll();
11876
+ }
11877
+ });
11878
+
11866
11879
 
11867
11880
  me.myEventCls.onIds("#" + me.pre + "mn6_hbondsNo", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
11868
11881
  ic.showInterCls.hideHbondsContacts();
@@ -13783,6 +13796,8 @@ class SetMenu {
13783
13796
  html += "</ul>";
13784
13797
  html += "</li>";
13785
13798
 
13799
+ html += this.getLink('mn6_DSSP', 'DSSP Secondary', undefined, 1);
13800
+
13786
13801
  let bOnePdb = me.cfg.mmtfid !== undefined || me.cfg.pdbid !== undefined || me.cfg.opmid !== undefined || me.cfg.mmcifid !== undefined || me.cfg.mmdbid !== undefined || me.cfg.mmdbafid !== undefined || me.cfg.gi !== undefined || me.cfg.blast_rep_id !== undefined;
13787
13802
 
13788
13803
  if(bOnePdb) {
@@ -14074,6 +14089,7 @@ class Dialog {
14074
14089
  let bGraph = $('#' + me.pre + 'dl_graph').hasClass('ui-dialog-content'); // initialized
14075
14090
  let bLineGraph = $('#' + me.pre + 'dl_linegraph').hasClass('ui-dialog-content'); // initialized
14076
14091
  let bScatterplot = $('#' + me.pre + 'dl_scatterplot').hasClass('ui-dialog-content'); // initialized
14092
+ let bLigplot = $('#' + me.pre + 'dl_ligplot').hasClass('ui-dialog-content'); // initialized
14077
14093
  let bContactmap = $('#' + me.pre + 'dl_contactmap').hasClass('ui-dialog-content'); // initialized
14078
14094
  let bAlignerrormap = $('#' + me.pre + 'dl_alignerrormap').hasClass('ui-dialog-content'); // initialized
14079
14095
  let bTable = $('#' + me.pre + 'dl_interactionsorted').hasClass('ui-dialog-content'); // initialized
@@ -14083,13 +14099,14 @@ class Dialog {
14083
14099
  let bSetsInit = $('#' + me.pre + 'dl_definedsets').hasClass('ui-dialog-content'); // initialized
14084
14100
 
14085
14101
  status.bSelectannotationsInit2 = false, status.bGraph2 = false, status.bLineGraph2 = false;
14086
- status.bScatterplot2 = false, status.bTable2 = false, status.bAlignmentInit2 = false;
14102
+ status.bScatterplot2 = false, status.bLigplot2 = false, status.bTable2 = false, status.bAlignmentInit2 = false;
14087
14103
  status.bTwoddgmInit2 = false, status.bTwodctnInit2 = false, status.bSetsInit2 = false;
14088
14104
 
14089
14105
  id2flag.dl_selectannotations = 'bSelectannotationsInit2';
14090
14106
  id2flag.dl_graph = 'bGraph2';
14091
14107
  id2flag.dl_linegraph = 'bLineGraph2';
14092
- id2flag.dl_scatterplot = 'bScatterplot2';
14108
+ id2flag.dl_scatterplot = 'bScatterplot2';
14109
+ id2flag.dl_ligplot = 'bLigplot2';
14093
14110
  id2flag.dl_contactmap = 'bContactmap2';
14094
14111
  id2flag.dl_alignerrormap = 'bAlignerrormap2';
14095
14112
  id2flag.dl_interactionsorted = 'bTable2';
@@ -14102,6 +14119,7 @@ class Dialog {
14102
14119
  if(bGraph) status.bGraph2 = $('#' + me.pre + 'dl_graph').dialog( 'isOpen' );
14103
14120
  if(bLineGraph) status.bLineGraph2 = $('#' + me.pre + 'dl_linegraph').dialog( 'isOpen' );
14104
14121
  if(bScatterplot) status.bScatterplot2 = $('#' + me.pre + 'dl_scatterplot').dialog( 'isOpen' );
14122
+ if(bLigplot) status.bLigplot2 = $('#' + me.pre + 'dl_ligplot').dialog( 'isOpen' );
14105
14123
  if(bContactmap) status.bContactmap2 = $('#' + me.pre + 'dl_contactmap').dialog( 'isOpen' );
14106
14124
  if(bAlignerrormap) status.bAlignerror2 = $('#' + me.pre + 'dl_alignerrormap').dialog( 'isOpen' );
14107
14125
  if(bTable) status.bTable2 = $('#' + me.pre + 'dl_interactionsorted').dialog( 'isOpen' );
@@ -14188,7 +14206,7 @@ class Dialog {
14188
14206
 
14189
14207
  d3.select("#" + me.svgid).attr("width", width).attr("height", height);
14190
14208
  }
14191
- else if(id == me.pre + 'dl_linegraph' || id == me.pre + 'dl_scatterplot' || id == me.pre + 'dl_contactmap' || id == me.pre + 'dl_alignerrormap') {
14209
+ 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') {
14192
14210
  let oriWidth =(status.bTwoddgmInit2 || status.bSetsInit2) ?(me.htmlCls.WIDTH - twoddgmWidth)/2 : me.htmlCls.WIDTH / 2;
14193
14211
  let ratio = $("#" + id).width() / oriWidth;
14194
14212
 
@@ -14200,6 +14218,14 @@ class Dialog {
14200
14218
  let width = ic.scatterplotWidth * ratio;
14201
14219
  $("#" + me.scatterplotid).attr("width", width);
14202
14220
  }
14221
+ else if(id == me.pre + 'dl_ligplot') {
14222
+ let width = ic.ligplotWidth * ratio;
14223
+ $("#" + me.ligplotid).attr("width", width);
14224
+ }
14225
+ else if(id == me.pre + 'dl_ligplot') {
14226
+ let width = ic.ligplotWidth * ratio;
14227
+ $("#" + me.ligplotid).attr("width", width);
14228
+ }
14203
14229
  else if(id == me.pre + 'dl_contactmap') {
14204
14230
  let width = ic.contactmapWidth * ratio;
14205
14231
  $("#" + me.contactmapid).attr("width", width);
@@ -14253,7 +14279,7 @@ class Dialog {
14253
14279
  close: function(e) {
14254
14280
  let status = thisClass.getDialogStatus().status;
14255
14281
 
14256
- if((!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bTable2) &&(!status.bAlignmentInit2) ) {
14282
+ if((!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bTable2) &&(!status.bAlignmentInit2) ) {
14257
14283
  //ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH, me.htmlCls.HEIGHT - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT, true);
14258
14284
  ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH, me.htmlCls.HEIGHT, true);
14259
14285
  }
@@ -14282,7 +14308,7 @@ class Dialog {
14282
14308
 
14283
14309
  let status = this.getDialogStatus().status;
14284
14310
 
14285
- 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_contactmap' || id === me.pre + 'dl_alignerrormap' || id === me.pre + 'dl_interactionsorted' || id === me.pre + 'dl_alignment') {
14311
+ 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_ligplot' || id === me.pre + 'dl_contactmap' || id === me.pre + 'dl_alignerrormap' || id === me.pre + 'dl_interactionsorted' || id === me.pre + 'dl_alignment') {
14286
14312
  //var dialogWidth = 0.5 *(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH) - twoddgmWidth * 0.5;
14287
14313
  let dialogWidth = 0.5 *(me.htmlCls.WIDTH) - twoddgmWidth * 0.5;
14288
14314
 
@@ -14318,14 +14344,15 @@ class Dialog {
14318
14344
  modal: false,
14319
14345
  position: position,
14320
14346
  close: function(e) {
14321
- if((id === me.pre + 'dl_selectannotations' &&(!status.bAlignmentInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
14322
- ||(id === me.pre + 'dl_graph' &&(!status.bSelectannotationsInit2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
14323
- ||(id === me.pre + 'dl_alignment' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
14324
- ||(id === me.pre + 'dl_interactionsorted' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
14325
- ||(id === me.pre + 'dl_linegraph' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
14326
- ||(id === me.pre + 'dl_scatterplot' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
14327
- ||(id === me.pre + 'dl_contactmap' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bAlignerrormap2))
14328
- ||(id === me.pre + 'dl_alignerrormap' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2))
14347
+ if((id === me.pre + 'dl_selectannotations' &&(!status.bAlignmentInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
14348
+ ||(id === me.pre + 'dl_graph' &&(!status.bSelectannotationsInit2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
14349
+ ||(id === me.pre + 'dl_alignment' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
14350
+ ||(id === me.pre + 'dl_interactionsorted' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
14351
+ ||(id === me.pre + 'dl_linegraph' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
14352
+ ||(id === me.pre + 'dl_scatterplot' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
14353
+ ||(id === me.pre + 'dl_ligplot' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
14354
+ ||(id === me.pre + 'dl_contactmap' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bAlignerrormap2))
14355
+ ||(id === me.pre + 'dl_alignerrormap' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2))
14329
14356
  ) {
14330
14357
  if(status.bTwoddgmInit2 || status.bTwodctnInit2 || status.bSetsInit2) {
14331
14358
  let canvasWidth = me.utilsCls.isMobile() ? me.htmlCls.WIDTH : me.htmlCls.WIDTH - twoddgmWidth;
@@ -14351,7 +14378,7 @@ class Dialog {
14351
14378
 
14352
14379
  d3.select("#" + me.svgid).attr("width", width).attr("height", height);
14353
14380
  }
14354
- else if(id == me.pre + 'dl_linegraph' || id == me.pre + 'dl_scatterplot' || id == me.pre + 'dl_contactmap' || id == me.pre + 'dl_alignerrormap') {
14381
+ 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') {
14355
14382
  let oriWidth =(status.bTwoddgmInit2 || status.bSetsInit2) ?(me.htmlCls.WIDTH - twoddgmWidth)/2 : me.htmlCls.WIDTH / 2;
14356
14383
  let ratio = $("#" + id).width() / oriWidth;
14357
14384
 
@@ -14363,6 +14390,10 @@ class Dialog {
14363
14390
  let width = ic.scatterplotWidth * ratio;
14364
14391
  $("#" + me.scatterplotid).attr("width", width);
14365
14392
  }
14393
+ else if(id == me.pre + 'dl_ligplot') {
14394
+ let width = ic.ligplotWidth * ratio;
14395
+ $("#" + me.ligplotid).attr("width", width);
14396
+ }
14366
14397
  else if(id == me.pre + 'dl_contactmap') {
14367
14398
  let width = ic.contactmapWidth * ratio;
14368
14399
  $("#" + me.contactmapid).attr("width", width);
@@ -14384,7 +14415,7 @@ class Dialog {
14384
14415
 
14385
14416
  //if(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH >= me.htmlCls.HEIGHT - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT) {
14386
14417
  if(me.htmlCls.WIDTH >= me.htmlCls.HEIGHT) {
14387
- if(status.bSelectannotationsInit2 || status.bGraph2 || status.bLineGraph2 || status.bScatterplot2 || status.bTable2 || status.bAlignmentInit2) {
14418
+ if(status.bSelectannotationsInit2 || status.bGraph2 || status.bLineGraph2 || status.bScatterplot2 || status.bLigplot2 || status.bTable2 || status.bAlignmentInit2) {
14388
14419
  //tmpWidth = 0.5 *(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH) - twoddgmWidth * 0.5;
14389
14420
  tmpWidth = 0.5 *(me.htmlCls.WIDTH) - twoddgmWidth * 0.5;
14390
14421
  }
@@ -14423,7 +14454,7 @@ class Dialog {
14423
14454
 
14424
14455
  //if(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH >= me.htmlCls.HEIGHT - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT) {
14425
14456
  if(me.htmlCls.WIDTH >= me.htmlCls.HEIGHT) {
14426
- if(status.bSelectannotationsInit2 || status.bGraph2 || status.bLineGraph2 || status.bScatterplot2 || status.bTable2 || status.bAlignmentInit2) {
14457
+ if(status.bSelectannotationsInit2 || status.bGraph2 || status.bLineGraph2 || status.bScatterplot2 || status.bLigplot2 || status.bTable2 || status.bAlignmentInit2) {
14427
14458
  //tmpWidth = 0.5 *(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH) - twoddgmWidth * 0.5;
14428
14459
  tmpWidth = 0.5 *(me.htmlCls.WIDTH) - twoddgmWidth * 0.5;
14429
14460
  }
@@ -14503,7 +14534,7 @@ class Dialog {
14503
14534
  let width = 400, height = 150;
14504
14535
  let twoddgmWidth = me.htmlCls.width2d + 20;
14505
14536
 
14506
- 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_contactmap' || id === me.pre + 'dl_alignerrormap' || id === me.pre + 'dl_interactionsorted' || id === me.pre + 'dl_alignment') {
14537
+ 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_ligplot' || id === me.pre + 'dl_contactmap' || id === me.pre + 'dl_alignerrormap' || id === me.pre + 'dl_interactionsorted' || id === me.pre + 'dl_alignment') {
14507
14538
  $( "#" + id ).show();
14508
14539
  $( "#" + id + "_nb").show();
14509
14540
  $( "#" + id + "_title").html(title);
@@ -14538,6 +14569,11 @@ class Dialog {
14538
14569
 
14539
14570
  $("#" + me.scatterplotid).attr("width", width);
14540
14571
  }
14572
+ else if(id == me.pre + 'dl_ligplot') {
14573
+ let width = ic.ligplotWidth * ratio;
14574
+
14575
+ $("#" + me.ligplotid).attr("width", width);
14576
+ }
14541
14577
  else if(id == me.pre + 'dl_contactmap') {
14542
14578
  let width = ic.contactmapWidth * ratio;
14543
14579
 
@@ -15083,14 +15119,14 @@ class SetDialog {
15083
15119
 
15084
15120
  html += "<span style='white-space:nowrap;font-weight:bold;'>2fofc contour at default threshold or at: "
15085
15121
  + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigma2fofc' value='' size=8> &sigma;</span><br/>";
15086
- //html += me.htmlCls.inputFileStr + "id='" + me.pre + "dsn6file2fofc'> " + me.htmlCls.buttonStr + "reload_dsn6file2fofc' style='margin: 6px 20px 0 0;'>Load DSN6</button><br><br><br/>";
15087
- html += me.htmlCls.inputFileStr + "id='" + me.pre + "dsn6file2fofc'><br>" + me.htmlCls.buttonStr + "reload_dsn6file2fofc' style='margin: 6px 20px 0 0;'>Load DSN6</button>" + me.htmlCls.buttonStr + "reload_ccp4file2fofc' style='margin: 6px 20px 0 0;'>Load CCP4</button>" + me.htmlCls.buttonStr + "reload_mtzfile2fofc' style='margin: 6px 20px 0 0;'>Load MTZ</button>" + me.htmlCls.buttonStr + "reload_rcsbmtzfile2fofc' style='margin-top: 6px;'>Load RCSB MTZ</button><br><br><br/>";
15122
+ //html += me.htmlCls.inputFileStr + "id='" + me.pre + "dsn6file2fofc'><br>" + me.htmlCls.buttonStr + "reload_dsn6file2fofc' style='margin: 6px 20px 0 0;'>Load DSN6</button>" + me.htmlCls.buttonStr + "reload_ccp4file2fofc' style='margin: 6px 20px 0 0;'>Load CCP4</button>" + me.htmlCls.buttonStr + "reload_mtzfile2fofc' style='margin: 6px 20px 0 0;'>Load MTZ</button>" + me.htmlCls.buttonStr + "reload_rcsbmtzfile2fofc' style='margin-top: 6px;'>Load RCSB MTZ</button><br><br><br/>";
15123
+ html += me.htmlCls.inputFileStr + "id='" + me.pre + "dsn6file2fofc'><br>" + me.htmlCls.buttonStr + "reload_ccp4file2fofc' style='margin: 6px 20px 0 0;'>Load CCP4</button>" + me.htmlCls.buttonStr + "reload_mtzfile2fofc' style='margin: 6px 20px 0 0;'>Load MTZ</button>" + me.htmlCls.buttonStr + "reload_rcsbmtzfile2fofc' style='margin-top: 6px;'>Load RCSB MTZ</button><br><br><br/>";
15088
15124
 
15089
15125
  html += "<span style='white-space:nowrap;font-weight:bold;'>fofc contour at default threshold or at: "
15090
15126
  + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigmafofc' value='' size=8> &sigma;</span><br/>";
15091
15127
 
15092
- //html += me.htmlCls.inputFileStr + "id='" + me.pre + "dsn6filefofc'> " + me.htmlCls.buttonStr + "reload_dsn6filefofc' style='margin: 6px 20px 0 0;'>Load DSN6</button><br><br><br>";
15093
- html += me.htmlCls.inputFileStr + "id='" + me.pre + "dsn6filefofc'><br>" + me.htmlCls.buttonStr + "reload_dsn6filefofc' style='margin: 6px 20px 0 0;'>Load DSN6</button>" + me.htmlCls.buttonStr + "reload_ccp4filefofc' style='margin: 6px 20px 0 0;'>Load CCP4</button>" + me.htmlCls.buttonStr + "reload_mtzfilefofc' style='margin: 6px 20px 0 0;'>Load MTZ</button>" + me.htmlCls.buttonStr + "reload_rcsbmtzfilefofc' style='margin-top: 6px;'>Load RCSB MTZ</button><br><br><br>";
15128
+ //html += me.htmlCls.inputFileStr + "id='" + me.pre + "dsn6filefofc'><br>" + me.htmlCls.buttonStr + "reload_dsn6filefofc' style='margin: 6px 20px 0 0;'>Load DSN6</button>" + me.htmlCls.buttonStr + "reload_ccp4filefofc' style='margin: 6px 20px 0 0;'>Load CCP4</button>" + me.htmlCls.buttonStr + "reload_mtzfilefofc' style='margin: 6px 20px 0 0;'>Load MTZ</button>" + me.htmlCls.buttonStr + "reload_rcsbmtzfilefofc' style='margin-top: 6px;'>Load RCSB MTZ</button><br><br><br>";
15129
+ html += me.htmlCls.inputFileStr + "id='" + me.pre + "dsn6filefofc'><br>" + me.htmlCls.buttonStr + "reload_ccp4filefofc' style='margin: 6px 20px 0 0;'>Load CCP4</button>" + me.htmlCls.buttonStr + "reload_mtzfilefofc' style='margin: 6px 20px 0 0;'>Load MTZ</button>" + me.htmlCls.buttonStr + "reload_rcsbmtzfilefofc' style='margin-top: 6px;'>Load RCSB MTZ</button><br><br><br>";
15094
15130
 
15095
15131
 
15096
15132
  html += me.htmlCls.buttonStr + "elecmapNo4'>Remove Map</button><br>";
@@ -15104,12 +15140,16 @@ class SetDialog {
15104
15140
  html += "<span style='white-space:nowrap;font-weight:bold;'>2fofc contour at default threshold or at: "
15105
15141
  + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigmaurl2fofc' value='' size=8> &sigma;</span><br/>";
15106
15142
 
15107
- html += "URL in the same host: " + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6fileurl2fofc' size=20><br>" + me.htmlCls.buttonStr + "reload_dsn6fileurl2fofc' style='margin: 6px 20px 0 0;'>Load DSN6</button>" + me.htmlCls.buttonStr + "reload_ccp4fileurl2fofc' style='margin: 6px 20px 0 0;'>Load CCP4</button>" + me.htmlCls.buttonStr + "reload_mtzfileurl2fofc' style='margin: 6px 20px 0 0;'>Load MTZ</button>" + me.htmlCls.buttonStr + "reload_rcsbmtzfileurl2fofc' style='margin-top: 6px;'>Load RCSB MTZ</button><br><br><br/>";
15143
+ //html += "URL in the same host: " + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6fileurl2fofc' size=20><br>" + me.htmlCls.buttonStr + "reload_dsn6fileurl2fofc' style='margin: 6px 20px 0 0;'>Load DSN6</button>" + me.htmlCls.buttonStr + "reload_ccp4fileurl2fofc' style='margin: 6px 20px 0 0;'>Load CCP4</button>" + me.htmlCls.buttonStr + "reload_mtzfileurl2fofc' style='margin: 6px 20px 0 0;'>Load MTZ</button>" + me.htmlCls.buttonStr + "reload_rcsbmtzfileurl2fofc' style='margin-top: 6px;'>Load RCSB MTZ</button><br><br><br/>";
15144
+
15145
+ html += "URL in the same host: " + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6fileurl2fofc' size=20><br>" + me.htmlCls.buttonStr + "reload_ccp4fileurl2fofc' style='margin: 6px 20px 0 0;'>Load CCP4</button>" + me.htmlCls.buttonStr + "reload_mtzfileurl2fofc' style='margin: 6px 20px 0 0;'>Load MTZ</button>" + me.htmlCls.buttonStr + "reload_rcsbmtzfileurl2fofc' style='margin-top: 6px;'>Load RCSB MTZ</button><br><br><br/>";
15108
15146
 
15109
15147
  html += "<span style='white-space:nowrap;font-weight:bold;'>fofc contour at default threshold or at: "
15110
15148
  + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigmaurlfofc' value='' size=8> &sigma;</span><br/>";
15111
15149
 
15112
- html += "URL in the same host: " + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6fileurlfofc' size=20><br>" + me.htmlCls.buttonStr + "reload_dsn6fileurlfofc' style='margin: 6px 20px 0 0;'>Load DSN6</button>" + me.htmlCls.buttonStr + "reload_ccp4fileurlfofc' style='margin: 6px 20px 0 0;'>Load CCP4</button>" + me.htmlCls.buttonStr + "reload_mtzfileurlfofc' style='margin: 6px 20px 0 0;'>Load MTZ</button>" + me.htmlCls.buttonStr + "reload_rcsbmtzfileurlfofc' style='margin-top: 6px;'>Load RCSB MTZ</button><br><br><br>";
15150
+ //html += "URL in the same host: " + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6fileurlfofc' size=20><br>" + me.htmlCls.buttonStr + "reload_dsn6fileurlfofc' style='margin: 6px 20px 0 0;'>Load DSN6</button>" + me.htmlCls.buttonStr + "reload_ccp4fileurlfofc' style='margin: 6px 20px 0 0;'>Load CCP4</button>" + me.htmlCls.buttonStr + "reload_mtzfileurlfofc' style='margin: 6px 20px 0 0;'>Load MTZ</button>" + me.htmlCls.buttonStr + "reload_rcsbmtzfileurlfofc' style='margin-top: 6px;'>Load RCSB MTZ</button><br><br><br>";
15151
+
15152
+ html += "URL in the same host: " + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6fileurlfofc' size=20><br>" + me.htmlCls.buttonStr + "reload_ccp4fileurlfofc' style='margin: 6px 20px 0 0;'>Load CCP4</button>" + me.htmlCls.buttonStr + "reload_mtzfileurlfofc' style='margin: 6px 20px 0 0;'>Load MTZ</button>" + me.htmlCls.buttonStr + "reload_rcsbmtzfileurlfofc' style='margin-top: 6px;'>Load RCSB MTZ</button><br><br><br>";
15113
15153
 
15114
15154
  html += me.htmlCls.buttonStr + "elecmapNo5'>Remove Map</button><br>";
15115
15155
 
@@ -15232,6 +15272,8 @@ class SetDialog {
15232
15272
 
15233
15273
  html += "<div style='text-indent:1.1em'>" + me.htmlCls.buttonStr + "hbondScatterplot'>2D Interaction Map</button> " + me.htmlCls.buttonStr + "hbondScatterplot2' style='margin-left:12px'>2D Map with Reference Numbers</button> to show map</div><br>";
15234
15274
 
15275
+ html += "<div style='text-indent:1.1em'>" + me.htmlCls.buttonStr + "hbondLigplot'>2D Interaction for One Ligand/Residue</button> with atom details</div><br>";
15276
+
15235
15277
  tmpStr = ': </td><td><input style="margin-left:-12px" type="text" id="';
15236
15278
 
15237
15279
  html += "<div style='text-indent:1.1em'>" + me.htmlCls.buttonStr + "hbondGraph'>2D Graph(Force-Directed)</button> to show interactions with strength parameters in 0-200:</div>";
@@ -15398,6 +15440,40 @@ class SetDialog {
15398
15440
 
15399
15441
  html += "</div>";
15400
15442
 
15443
+
15444
+ html += me.htmlCls.divStr + "dl_ligplot' sty2D Interaction for One Ligand/Residule='background-color:white' class='" + dialogClass + "'>";
15445
+ html += this.addNotebookTitle('dl_ligplot', 'e with Atom Details');
15446
+
15447
+ html += me.htmlCls.divNowrapStr + "<b>Note</b>: Nodes can be dragged or clicked. Hold Ctrl key to select multiple nodes. " + me.htmlCls.space3;
15448
+
15449
+ html += '<div style="width:20px; margin-top:6px; display:inline-block;"><span id="'
15450
+ + me.pre + 'dl_ligplotcolor_expand" class="ui-icon ui-icon-plus icn3d-expand icn3d-link" style="display:none; width:15px;" title="Expand"></span><span id="'
15451
+ + me.pre + 'dl_ligplotcolor_shrink" class="ui-icon ui-icon-minus icn3d-shrink icn3d-link" style="width:15px;" title="Shrink"></span></div></div>';
15452
+
15453
+ html += me.htmlCls.divStr + "dl_ligplotcolor' style='inline-block;'>";
15454
+
15455
+ // html += "The real interaction distances are not in scale, and are about twice the distances of dashed line segments.<br>Some \"Contact\" lines are only shown partially to simplify the view.<br>";
15456
+ html += "<b>Color Legend</b>: <br>";
15457
+
15458
+ html += me.htmlCls.setHtmlCls.setColorHints();
15459
+
15460
+ html += "<br></div>";
15461
+
15462
+ me.ligplotid = me.pre + 'ligplot';
15463
+ html += me.htmlCls.divNowrapStr + buttonStrTmp + me.ligplotid + '_svg">SVG</button>' + me.htmlCls.space2;
15464
+ html += buttonStrTmp + me.ligplotid + '_png">PNG</button>' + me.htmlCls.space2;
15465
+ // html += buttonStrTmp + me.ligplotid + '_json">JSON</button>' + me.htmlCls.space4;
15466
+ html += "<b>Scale</b>: <select id='" + me.ligplotid + "_scale'>";
15467
+
15468
+ html += me.htmlCls.setHtmlCls.getOptionHtml(optArray4, 5);
15469
+
15470
+ html += "</select></div><br>";
15471
+ html += '<div id="' + me.pre + 'ligplotDiv"></div>';
15472
+
15473
+ html += "</div>";
15474
+
15475
+
15476
+
15401
15477
  html += me.htmlCls.divStr + "dl_contactmap' style='background-color:white' class='" + dialogClass + "'>";
15402
15478
  html += this.addNotebookTitle('dl_contactmap', 'Contact Map');
15403
15479
 
@@ -15658,8 +15734,9 @@ class SetDialog {
15658
15734
  html += "</div>";
15659
15735
 
15660
15736
 
15661
- html += me.htmlCls.divStr + "dl_anglemanysets' class='" + dialogClass + "'>";
15737
+ html += me.htmlCls.divStr + "dl_anglemanysets' class='" + dialogClass + "' style='max-width:500px'>";
15662
15738
  html += this.addNotebookTitle('dl_anglemanysets', 'Measure angles among many sets');
15739
+ html += me.htmlCls.spanNowrapStr + "Note: Each set is represented by a vector, which is the X-axis of the principle axes. The angles between the vectors are then calculated.<br/><br/>";
15663
15740
  html += me.htmlCls.spanNowrapStr + "1. Select sets for pairwise angles</span><br/>";
15664
15741
  html += "<table border=0 width=400 cellspacing=10><tr><td>";
15665
15742
 
@@ -15981,8 +16058,8 @@ class SetDialog {
15981
16058
  html += "Z: " + me.htmlCls.inputTextStr + "id='" + me.pre + "v2Z' value='' size=6><br>";
15982
16059
  html += "<br>";
15983
16060
 
15984
- html += me.htmlCls.buttonStr + "measure_angle'>Measure Angle</button>";
15985
- html += "The angle is: " + me.htmlCls.inputTextStr + "id='" + me.pre + "angle_value' value='' size=6> degree.";
16061
+ html += me.htmlCls.buttonStr + "measure_angle'>Measure Angle</button><br><br>";
16062
+ html += "The angle is: " + me.htmlCls.inputTextStr + "id='" + me.pre + "angle_value' value='' size=6> degree.<br><br>";
15986
16063
  html += "</div>";
15987
16064
 
15988
16065
  html += me.htmlCls.divStr + "dl_matrix' class='" + dialogClass + "'>";
@@ -16451,6 +16528,7 @@ class Events {
16451
16528
 
16452
16529
  ic.diagram2dCls.click2Ddgm();
16453
16530
  ic.cartoon2dCls.click2Dcartoon();
16531
+ ic.ligplotCls.clickLigplot();
16454
16532
  ic.addTrackCls.clickAddTrackButton();
16455
16533
  ic.resizeCanvasCls.windowResize();
16456
16534
  ic.annotationCls.setTabs();
@@ -18072,6 +18150,13 @@ class Events {
18072
18150
  thisClass.setLogCmd("show ref number", true);
18073
18151
  await ic.showInterCls.showInteractions('scatterplot');
18074
18152
  });
18153
+ me.myEventCls.onIds("#" + me.pre + "hbondLigplot", "click", async function(e) { let ic = me.icn3d;
18154
+ e.preventDefault();
18155
+
18156
+ ic.bShownRefnum = false;
18157
+ thisClass.setLogCmd("hide ref number", true);
18158
+ await ic.showInterCls.showInteractions('ligplot');
18159
+ });
18075
18160
  // select residues
18076
18161
  $(document).on("click", "#" + me.svgid + " circle.selected", function(e) { let ic = me.icn3d;
18077
18162
  e.stopImmediatePropagation();
@@ -18182,6 +18267,33 @@ class Events {
18182
18267
  thisClass.setLogCmd("scatterplot scale " + scale, true);
18183
18268
  });
18184
18269
 
18270
+ me.myEventCls.onIds("#" + me.ligplotid + "_svg", "click", function(e) { let ic = me.icn3d;
18271
+ e.preventDefault();
18272
+
18273
+ ic.saveFileCls.saveSvg(me.ligplotid, ic.inputid + "_ligplot.svg", undefined, true);
18274
+ });
18275
+ me.myEventCls.onIds("#" + me.ligplotid + "_png", "click", function(e) { let ic = me.icn3d;
18276
+ e.preventDefault();
18277
+
18278
+ ic.saveFileCls.savePng(me.ligplotid, ic.inputid + "_ligplot.png", undefined, true);
18279
+ });
18280
+ // me.myEventCls.onIds("#" + me.ligplotid + "_json", "click", function(e) { let ic = me.icn3d;
18281
+ // e.preventDefault();
18282
+
18283
+ // let graphStr2 = ic.ligplotStr.substr(0, ic.ligplotStr.lastIndexOf('}'));
18284
+
18285
+ // graphStr2 += me.htmlCls.setHtmlCls.getLinkColor();
18286
+
18287
+ // ic.saveFileCls.saveFile(ic.inputid + "_ligplot.json", "text", [graphStr2]);
18288
+ // });
18289
+ me.myEventCls.onIds("#" + me.ligplotid + "_scale", "change", function(e) { let ic = me.icn3d;
18290
+ e.preventDefault();
18291
+
18292
+ let scale = $("#" + me.ligplotid + "_scale").val();
18293
+ $("#" + me.ligplotid).attr("width",(ic.ligplotWidth * parseFloat(scale)).toString() + "px");
18294
+ thisClass.setLogCmd("ligplot scale " + scale, true);
18295
+ });
18296
+
18185
18297
  me.myEventCls.onIds("#" + me.contactmapid + "_svg", "click", function(e) { let ic = me.icn3d;
18186
18298
  e.preventDefault();
18187
18299
 
@@ -37639,7 +37751,8 @@ class Contact {
37639
37751
  if(oriCalpha === undefined) oriCalpha = oriAtom;
37640
37752
 
37641
37753
  if(bGetPairs) {
37642
- oriResidName = oriAtom.resn + ' $' + oriAtom.structure + '.' + oriAtom.chain + ':' + oriAtom.resi;
37754
+ let serialList = (oriAtom.name.indexOf('pi') == 0 && oriAtom.ring) ? oriAtom.ring.join(',') : oriAtom.serial;
37755
+ oriResidName = oriAtom.resn + ' $' + oriAtom.structure + '.' + oriAtom.chain + ':' + oriAtom.resi + ' ' + serialList;
37643
37756
  if(ic.resid2Residhash[oriResidName] === undefined) ic.resid2Residhash[oriResidName] = {};
37644
37757
  }
37645
37758
 
@@ -37684,13 +37797,14 @@ class Contact {
37684
37797
  if(bGetPairs) {
37685
37798
  let chain_resi2 = atom.structure + '_' + atom.chain + '_' + atom.resi;
37686
37799
 
37687
- residName = atom.resn + ' $' + atom.structure + '.' + atom.chain + ':' + atom.resi;
37800
+ let serialList = (atom.name.indexOf('pi') == 0 && atom.ring) ? atom.ring.join(',') : atom.serial;
37801
+ residName = atom.resn + ' $' + atom.structure + '.' + atom.chain + ':' + atom.resi + ' ' + serialList;
37688
37802
  //var dist = Math.sqrt(atomDistSq).toFixed(1);
37689
37803
  let dist1 = atomDist.toFixed(1);
37690
37804
  let dist2 = calpha.coord.distanceTo(oriCalpha.coord).toFixed(1);
37691
37805
 
37692
37806
  let resids = chain_resi + '_' + oriAtom.resn + ',' + chain_resi2 + '_' + atom.resn;
37693
- let residNames = oriResidName + ',' + residName;
37807
+ let residNames = oriResidName + '|' + residName;
37694
37808
  if(ic.resids2interAll[resids] === undefined
37695
37809
  || ic.resids2interAll[resids]['contact'] === undefined
37696
37810
  || !ic.resids2interAll[resids]['contact'].hasOwnProperty(residNames)
@@ -37707,12 +37821,12 @@ class Contact {
37707
37821
  if(!bInternal) {
37708
37822
  if(ic.resids2inter[resids] === undefined) ic.resids2inter[resids] = {};
37709
37823
  if(ic.resids2inter[resids]['contact'] === undefined) ic.resids2inter[resids]['contact'] = {};
37710
- ic.resids2inter[resids]['contact'][oriResidName + ',' + residName] = dist1 + '_' + dist2 + '_' + oriAtom.name + '_' + atom.name + '_' + cnt;
37824
+ ic.resids2inter[resids]['contact'][oriResidName + '|' + residName] = dist1 + '_' + dist2 + '_' + oriAtom.name + '_' + atom.name + '_' + cnt;
37711
37825
  }
37712
37826
 
37713
37827
  if(ic.resids2interAll[resids] === undefined) ic.resids2interAll[resids] = {};
37714
37828
  if(ic.resids2interAll[resids]['contact'] === undefined) ic.resids2interAll[resids]['contact'] = {};
37715
- ic.resids2interAll[resids]['contact'][oriResidName + ',' + residName] = dist1 + '_' + dist2 + '_' + oriAtom.name + '_' + atom.name + '_' + cnt;
37829
+ ic.resids2interAll[resids]['contact'][oriResidName + '|' + residName] = dist1 + '_' + dist2 + '_' + oriAtom.name + '_' + atom.name + '_' + cnt;
37716
37830
  }
37717
37831
  }
37718
37832
  } // if(bGetPairs) {
@@ -38138,7 +38252,8 @@ class HBond {
38138
38252
  chain_resi_atom = chain_resi + "_" + atom.name;
38139
38253
 
38140
38254
  //var oriResidName = atom.resn + ' ' + chain_resi_atom;
38141
- let oriResidName = atom.resn + ' $' + atom.structure + '.' + atom.chain + ':' + atom.resi + '@' + atom.name;
38255
+ let serialList = (atom.name.indexOf('pi') == 0 && atom.ring) ? atom.ring.join(',') : atom.serial;
38256
+ let oriResidName = atom.resn + ' $' + atom.structure + '.' + atom.chain + ':' + atom.resi + '@' + atom.name + ' ' + serialList;
38142
38257
  if(ic.resid2Residhash[oriResidName] === undefined) ic.resid2Residhash[oriResidName] = {};
38143
38258
 
38144
38259
  for (let j in atomHbond) {
@@ -38263,24 +38378,25 @@ class HBond {
38263
38378
  residueHash[chain_resi2] = 1;
38264
38379
 
38265
38380
  //var residName = atomHbond[j].resn + " " + atomHbond[j].structure + "_" + atomHbond[j].chain + "_" + atomHbond[j].resi + '_' + atomHbond[j].name;
38266
- let residName = atomHbond[j].resn + ' $' + atomHbond[j].structure + '.' + atomHbond[j].chain + ':' + atomHbond[j].resi + '@' + atomHbond[j].name;
38381
+ let serialList = (atomHbond[j].name.indexOf('pi') == 0 && atomHbond[j].ring) ? atomHbond[j].ring.join(',') : atomHbond[j].serial;
38382
+ let residName = atomHbond[j].resn + ' $' + atomHbond[j].structure + '.' + atomHbond[j].chain + ':' + atomHbond[j].resi + '@' + atomHbond[j].name + ' ' + serialList;
38267
38383
 
38268
38384
  let resids = chain_resi + '_' + atom.resn + ',' + chain_resi2 + '_' + atomHbond[j].resn;
38269
38385
 
38270
38386
  if(ic.resids2interAll[resids] === undefined
38271
38387
  || ic.resids2interAll[resids]['ionic'] === undefined
38272
- || !ic.resids2interAll[resids]['ionic'].hasOwnProperty(oriResidName + ',' + residName) ) {
38388
+ || !ic.resids2interAll[resids]['ionic'].hasOwnProperty(oriResidName + '|' + residName) ) {
38273
38389
  ic.resid2Residhash[oriResidName][residName] = dist.toFixed(1);
38274
38390
 
38275
38391
  if(!bInternal) {
38276
38392
  if(ic.resids2inter[resids] === undefined) ic.resids2inter[resids] = {};
38277
38393
  if(ic.resids2inter[resids]['hbond'] === undefined) ic.resids2inter[resids]['hbond'] = {};
38278
- ic.resids2inter[resids]['hbond'][oriResidName + ',' + residName] = dist.toFixed(1);
38394
+ ic.resids2inter[resids]['hbond'][oriResidName + '|' + residName] = dist.toFixed(1);
38279
38395
  }
38280
38396
 
38281
38397
  if(ic.resids2interAll[resids] === undefined) ic.resids2interAll[resids] = {};
38282
38398
  if(ic.resids2interAll[resids]['hbond'] === undefined) ic.resids2interAll[resids]['hbond'] = {};
38283
- ic.resids2interAll[resids]['hbond'][oriResidName + ',' + residName] = dist.toFixed(1);
38399
+ ic.resids2interAll[resids]['hbond'][oriResidName + '|' + residName] = dist.toFixed(1);
38284
38400
  }
38285
38401
  } // end of for (let j in atomHbond) {
38286
38402
  }
@@ -38433,7 +38549,8 @@ class PiHalogen {
38433
38549
 
38434
38550
  for (let i in atoms1a) {
38435
38551
  let atom1 = atoms1a[i];
38436
- let oriResidName = atom1.resn + ' $' + atom1.structure + '.' + atom1.chain + ':' + atom1.resi + '@' + atom1.name;
38552
+ let serialList = (atom1.name.indexOf('pi') == 0 && atom1.ring) ? atom1.ring.join(',') : atom1.serial;
38553
+ let oriResidName = atom1.resn + ' $' + atom1.structure + '.' + atom1.chain + ':' + atom1.resi + '@' + atom1.name + ' ' + serialList;
38437
38554
  if(ic.resid2Residhash[oriResidName] === undefined) ic.resid2Residhash[oriResidName] = {};
38438
38555
 
38439
38556
  for (let j in atoms1b) {
@@ -38477,7 +38594,8 @@ class PiHalogen {
38477
38594
 
38478
38595
  for (let i in atoms2a) {
38479
38596
  let atom1 = atoms2a[i];
38480
- let oriResidName = atom1.resn + ' $' + atom1.structure + '.' + atom1.chain + ':' + atom1.resi + '@' + atom1.name;
38597
+ let serialList = (atom1.name.indexOf('pi') == 0 && atom1.ring) ? atom1.ring.join(',') : atom1.serial;
38598
+ let oriResidName = atom1.resn + ' $' + atom1.structure + '.' + atom1.chain + ':' + atom1.resi + '@' + atom1.name + ' ' + serialList;
38481
38599
  if(ic.resid2Residhash[oriResidName] === undefined) ic.resid2Residhash[oriResidName] = {};
38482
38600
 
38483
38601
  // available in 1b and 2a
@@ -38642,7 +38760,8 @@ class PiHalogen {
38642
38760
  }
38643
38761
  }
38644
38762
 
38645
- let residName = atom2.resn + ' $' + atom2.structure + '.' + atom2.chain + ':' + atom2.resi + '@' + atom2.name;
38763
+ let serialList = (atom2.name.indexOf('pi') == 0 && atom2.ring) ? atom2.ring.join(',') : atom2.serial;
38764
+ let residName = atom2.resn + ' $' + atom2.structure + '.' + atom2.chain + ':' + atom2.resi + '@' + atom2.name + ' ' + serialList;
38646
38765
 
38647
38766
  //if(ic.resid2Residhash[oriResidName][residName] === undefined || ic.resid2Residhash[oriResidName][residName] > dist) {
38648
38767
  ic.resid2Residhash[oriResidName][residName] = dist.toFixed(1);
@@ -38654,12 +38773,12 @@ class PiHalogen {
38654
38773
  if(!bInternal) {
38655
38774
  if(ic.resids2inter[resids] === undefined) ic.resids2inter[resids] = {};
38656
38775
  if(ic.resids2inter[resids][interactionType] === undefined) ic.resids2inter[resids][interactionType] = {};
38657
- ic.resids2inter[resids][interactionType][oriResidName + ',' + residName] = dist.toFixed(1);
38776
+ ic.resids2inter[resids][interactionType][oriResidName + '|' + residName] = dist.toFixed(1);
38658
38777
  }
38659
38778
 
38660
38779
  if(ic.resids2interAll[resids] === undefined) ic.resids2interAll[resids] = {};
38661
38780
  if(ic.resids2interAll[resids][interactionType] === undefined) ic.resids2interAll[resids][interactionType] = {};
38662
- ic.resids2interAll[resids][interactionType][oriResidName + ',' + residName] = dist.toFixed(1);
38781
+ ic.resids2interAll[resids][interactionType][oriResidName + '|' + residName] = dist.toFixed(1);
38663
38782
 
38664
38783
  return true;
38665
38784
  }
@@ -38906,12 +39025,13 @@ class PiHalogen {
38906
39025
  // Print the i-th cycle
38907
39026
  let coord = new THREE.Vector3();
38908
39027
  let cnt = 0, serial;
38909
- let coordArray = [];
39028
+ let coordArray = [], ringArray = [];
38910
39029
  if(cycles.hasOwnProperty(i)) {
38911
39030
  for (let j = 0, jl = cycles[i].length; j < jl; ++j) {
38912
39031
  serial = cycles[i][j];
38913
39032
  coord.add(ic.atoms[serial].coord);
38914
39033
  coordArray.push(ic.atoms[serial].coord);
39034
+ ringArray.push(serial);
38915
39035
  ++cnt;
38916
39036
  }
38917
39037
  }
@@ -38931,7 +39051,7 @@ class PiHalogen {
38931
39051
 
38932
39052
  let atom = ic.atoms[serial];
38933
39053
  name2atom[resid + '_pi' + serial] = {resn: atom.resn, name: 'pi' + serial, coord: coord, serial: atom.serial,
38934
- structure: atom.structure, chain: atom.chain, resi: atom.resi, normal: normal};
39054
+ structure: atom.structure, chain: atom.chain, resi: atom.resi, normal: normal, ring: ringArray};
38935
39055
  }
38936
39056
  }
38937
39057
  }
@@ -39029,7 +39149,8 @@ class Saltbridge {
39029
39149
  chain_resi = atom.structure + "_" + atom.chain + "_" + atom.resi;
39030
39150
  chain_resi_atom = chain_resi + "_" + atom.name;
39031
39151
 
39032
- let oriResidName = atom.resn + ' $' + atom.structure + '.' + atom.chain + ':' + atom.resi + '@' + atom.name;
39152
+ let serialList = (atom.name.indexOf('pi') == 0 && atom.ring) ? atom.ring.join(',') : atom.serial;
39153
+ let oriResidName = atom.resn + ' $' + atom.structure + '.' + atom.chain + ':' + atom.resi + '@' + atom.name + ' ' + serialList;
39033
39154
  if(ic.resid2Residhash[oriResidName] === undefined) ic.resid2Residhash[oriResidName] = {};
39034
39155
 
39035
39156
  let atomHbond = {};
@@ -39094,7 +39215,8 @@ class Saltbridge {
39094
39215
  residueHash[chain_resi] = 1;
39095
39216
  residueHash[chain_resi2] = 1;
39096
39217
 
39097
- let residName = atomHbond[j].resn + ' $' + atomHbond[j].structure + '.' + atomHbond[j].chain + ':' + atomHbond[j].resi + '@' + atomHbond[j].name;
39218
+ let serialList = (atomHbond[j].name.indexOf('pi') == 0 && atomHbond[j].ring) ? atomHbond[j].ring.join(',') : atomHbond[j].serial;
39219
+ let residName = atomHbond[j].resn + ' $' + atomHbond[j].structure + '.' + atomHbond[j].chain + ':' + atomHbond[j].resi + '@' + atomHbond[j].name + ' ' + serialList;
39098
39220
 
39099
39221
  //if(ic.resid2Residhash[oriResidName][residName] === undefined || ic.resid2Residhash[oriResidName][residName] > dist) {
39100
39222
  ic.resid2Residhash[oriResidName][residName] = dist.toFixed(1);
@@ -39105,12 +39227,12 @@ class Saltbridge {
39105
39227
  if(!bInternal) {
39106
39228
  if(ic.resids2inter[resids] === undefined) ic.resids2inter[resids] = {};
39107
39229
  if(ic.resids2inter[resids]['ionic'] === undefined) ic.resids2inter[resids]['ionic'] = {};
39108
- ic.resids2inter[resids]['ionic'][oriResidName + ',' + residName] = dist.toFixed(1);
39230
+ ic.resids2inter[resids]['ionic'][oriResidName + '|' + residName] = dist.toFixed(1);
39109
39231
  }
39110
39232
 
39111
39233
  if(ic.resids2interAll[resids] === undefined) ic.resids2interAll[resids] = {};
39112
39234
  if(ic.resids2interAll[resids]['ionic'] === undefined) ic.resids2interAll[resids]['ionic'] = {};
39113
- ic.resids2interAll[resids]['ionic'][oriResidName + ',' + residName] = dist.toFixed(1);
39235
+ ic.resids2interAll[resids]['ionic'][oriResidName + '|' + residName] = dist.toFixed(1);
39114
39236
 
39115
39237
  } // end of for (let j in atomHbond) {
39116
39238
  }
@@ -45427,7 +45549,7 @@ class AddTrack {
45427
45549
 
45428
45550
  }
45429
45551
 
45430
- showNewTrack(chnid, title, text, cssColorArray, inTarget2queryHash, type, color, bMsa, fromArray, toArray, seqStartLen, exonArray) { let ic = this.icn3d, me = ic.icn3dui;
45552
+ showNewTrack(chnid, title, text, cssColorArray, inTarget2queryHash, type, color, bMsa, fromArray, toArray, seqStartLen, exonArray, offsetArray) { let ic = this.icn3d, me = ic.icn3dui;
45431
45553
  //if(ic.customTracks[chnid] === undefined) {
45432
45554
  // ic.customTracks[chnid] = {}
45433
45555
  //}
@@ -45645,14 +45767,16 @@ class AddTrack {
45645
45767
 
45646
45768
  if(fromArray !== undefined) {
45647
45769
  htmlTmp2 = '';
45648
- let fromArray2 = [], toArray2 = [];
45770
+ let fromArray2 = [], toArray2 = [], offsetArray2 = [];
45649
45771
  for(let i = 0, il = fromArray.length; i < il; ++i) {
45650
45772
  fromArray2.push(fromArray[i]);
45773
+ offsetArray2.push(offsetArray[i]);
45651
45774
 
45652
45775
  for(let j = parseInt(fromArray[i]); j <= parseInt(toArray[i]); ++j) {
45653
45776
  if(ic.targetGapHash !== undefined && ic.targetGapHash.hasOwnProperty(j)) {
45654
45777
  toArray2.push(j - 1);
45655
45778
  fromArray2.push(j);
45779
+ offsetArray2.push(offsetArray[i]);
45656
45780
  }
45657
45781
  }
45658
45782
 
@@ -45686,6 +45810,7 @@ class AddTrack {
45686
45810
  // determine how this range sits in the exon ranges in exonArray
45687
45811
  let startExon, endExon;
45688
45812
 
45813
+ let offset = offsetArray2[i];
45689
45814
  cnt = toArray[i] - fromArray[i] + 1;
45690
45815
  let from = prevCntTotal, to = prevCntTotal + cnt - 1;
45691
45816
 
@@ -45714,26 +45839,26 @@ class AddTrack {
45714
45839
  endColorStr = this.getExonColor(startExon.rangeStart, startExon.rangeEnd, to);
45715
45840
 
45716
45841
  colorGradient = startColorStr + ' 0%, #FFF 50%, ' + endColorStr + ' 100%';
45717
- htmlTmp2 += this.getExonHtml(startExon.exonIndex, colorGradient, startExon.from, endExon.to, startExon.genomeRange, chnid, simpTitle);
45842
+ htmlTmp2 += this.getExonHtml(startExon.exonIndex, colorGradient, startExon.from, endExon.to, startExon.genomeRange, chnid, simpTitle, offset);
45718
45843
  }
45719
45844
  else {
45720
45845
  if(startExon) {
45721
45846
  startColorStr = this.getExonColor(startExon.rangeStart, startExon.rangeEnd, from);
45722
45847
 
45723
45848
  colorGradient = startColorStr + ' 0%, #FFF 50%, #00F 100%';
45724
- htmlTmp2 += this.getExonHtml(startExon.exonIndex, colorGradient, startExon.from, startExon.rangeEnd, startExon.genomeRange, chnid, simpTitle);
45849
+ htmlTmp2 += this.getExonHtml(startExon.exonIndex, colorGradient, startExon.from, startExon.rangeEnd, startExon.genomeRange, chnid, simpTitle, offset);
45725
45850
  }
45726
45851
 
45727
45852
  if(startExon && endExon) {
45728
45853
  for(let j = startExon.exonIndex + 1; j < endExon.exonIndex; ++j) {
45729
45854
  colorGradient = '#F00 0%, #FFF 50%, #00F 100%';
45730
- htmlTmp2 += this.getExonHtml(j, colorGradient, exonArray[j].resStart, exonArray[j].resEnd, exonArray[j].genomeRange, chnid, simpTitle);
45855
+ htmlTmp2 += this.getExonHtml(j, colorGradient, exonArray[j].resStart, exonArray[j].resEnd, exonArray[j].genomeRange, chnid, simpTitle, offset);
45731
45856
  }
45732
45857
 
45733
45858
  endColorStr = this.getExonColor(endExon.rangeStart, endExon.rangeEnd, to);
45734
45859
 
45735
45860
  colorGradient = '#F00 0%, #FFF 50%, ' + endColorStr + ' 100%';
45736
- htmlTmp2 += this.getExonHtml(endExon.exonIndex, colorGradient, endExon.rangeStart, endExon.to, endExon.genomeRange, chnid, simpTitle);
45861
+ htmlTmp2 += this.getExonHtml(endExon.exonIndex, colorGradient, endExon.rangeStart, endExon.to, endExon.genomeRange, chnid, simpTitle, offset);
45737
45862
  }
45738
45863
  }
45739
45864
 
@@ -45767,8 +45892,8 @@ class AddTrack {
45767
45892
  }
45768
45893
  }
45769
45894
 
45770
- getExonHtml(exonIndex, colorGradient, from, to, genomeRange, chainid, simpTitle) { let ic = this.icn3d; ic.icn3dui;
45771
- return '<div style="display:inline-block; color:white!important; width:' + Math.round(ic.seqAnnWidth *(to - from + 1) /(ic.maxAnnoLength + ic.nTotalGap)) + 'px;" class="icn3d-seqTitle icn3d-link icn3d-blue" domain="' + (exonIndex + 1) + '" from="' + from + '" to="' + to + '" setname="' + simpTitle + ', ' + (exonIndex + 1) + '" title="Exon: ' + genomeRange + ' genomic interval" anno="sequence" chain="' + chainid + '"><div style="height: 12px; border: 1px solid #000; background: linear-gradient(to right, ' + colorGradient + ');"></div></div>';
45895
+ getExonHtml(exonIndex, colorGradient, from, to, genomeRange, chainid, simpTitle, offset) { let ic = this.icn3d; ic.icn3dui;
45896
+ return '<div style="display:inline-block; color:white!important; width:' + Math.round(ic.seqAnnWidth *(to - from + 1) /(ic.maxAnnoLength + ic.nTotalGap)) + 'px;" class="icn3d-seqTitle icn3d-link icn3d-blue" domain="' + (exonIndex + 1) + '" from="' + (from + offset) + '" to="' + (to + offset) + '" setname="' + simpTitle + ', ' + (exonIndex + 1) + '" title="Exon: ' + genomeRange + ' genomic interval" anno="sequence" chain="' + chainid + '"><div style="height: 12px; border: 1px solid #000; background: linear-gradient(to right, ' + colorGradient + ');"></div></div>';
45772
45897
  }
45773
45898
 
45774
45899
  getExonColor(start, end, pos) { let ic = this.icn3d; ic.icn3dui;
@@ -46715,6 +46840,7 @@ class AddTrack {
46715
46840
  let fromArray = [], toArray = [];
46716
46841
  let bFound = false;
46717
46842
  let seqStartLen = 0;
46843
+ let offset = 0, offsetArray = [];
46718
46844
  // for(let k = seqStart; k <= seqEnd; ++k) {
46719
46845
  for(let k = 0; k < seqLength; ++k) {
46720
46846
  //if(seqFirst[k] == '-') continue;
@@ -46723,19 +46849,29 @@ class AddTrack {
46723
46849
 
46724
46850
  resn = trackSeqArray[j][k];
46725
46851
 
46852
+ if(resn != '-') {
46853
+ if(!bFound) {
46854
+ seqStartLen = k;
46855
+ bFound = true;
46856
+
46857
+ offset = ic.startposGiSeq - ic.seqStartLen[chainid] + seqStartLen;
46858
+ }
46859
+ }
46860
+
46726
46861
  if(prevResn == '-' && resn != '-') {
46727
46862
  fromArray.push(k);
46863
+ offsetArray.push(offset);
46728
46864
  }
46729
46865
 
46730
46866
  if(prevResn != '-' && resn == '-') {
46731
46867
  toArray.push(k - 1);
46732
46868
  }
46733
46869
 
46734
- if(resn != '-') {
46735
- if(!bFound) {
46736
- seqStartLen = k;
46737
- bFound = true;
46738
- }
46870
+ // use "offset" to adjut the residue numbers, e.g., P20138
46871
+ // some isoforms starts residues before the first residue in the template sequence
46872
+ if(k >= ic.seqStartLen[chainid]) {
46873
+ if(seqFirst[k] == '-') offset--;
46874
+ if(resn == '-') offset++;
46739
46875
  }
46740
46876
 
46741
46877
  text += resn; //ic.giSeq[chainid][i];
@@ -46756,7 +46892,7 @@ class AddTrack {
46756
46892
  let title =(trackTitleArray[j].length < 20) ? trackTitleArray[j] : trackTitleArray[j].substr(0, 20) + '...';
46757
46893
  let bMsa = true;
46758
46894
  let exonArray = (acc2exons) ? acc2exons[trackTitleArray[j]] : undefined;
46759
- this.showNewTrack(chainid, title, text, undefined, undefined, type, undefined, bMsa, fromArray, toArray, seqStartLen, exonArray);
46895
+ this.showNewTrack(chainid, title, text, undefined, undefined, type, undefined, bMsa, fromArray, toArray, seqStartLen, exonArray, offsetArray);
46760
46896
  }
46761
46897
 
46762
46898
  // update exon color
@@ -50481,20 +50617,9 @@ class LineGraph {
50481
50617
  } else {
50482
50618
  linestrokewidth = (link.n == 1) ? 2 : 4;
50483
50619
  }
50484
- let strokecolor;
50485
- if(link.v == me.htmlCls.hbondValue) {
50486
- strokecolor = "#" + me.htmlCls.hbondColor;
50487
- } else if(link.v == me.htmlCls.ionicValue) {
50488
- strokecolor = "#" + me.htmlCls.ionicColor;
50489
- } else if(link.v == me.htmlCls.halogenValue) {
50490
- strokecolor = "#" + me.htmlCls.halogenColor;
50491
- } else if(link.v == me.htmlCls.picationValue) {
50492
- strokecolor = "#" + me.htmlCls.picationColor;
50493
- } else if(link.v == me.htmlCls.pistackingValue) {
50494
- strokecolor = "#" + me.htmlCls.pistackingColor;
50495
- } else if(link.v == me.htmlCls.contactValue) {
50496
- strokecolor = "#" + me.htmlCls.contactColor;
50497
- }
50620
+
50621
+ let strokecolor = this.getStrokecolor(link.v);
50622
+
50498
50623
  html += "<g class='icn3d-interaction' resid1='" + resid1 + "' resid2='" + resid2 + "' >";
50499
50624
  let interactStr = (link.n == 1) ? 'Interaction' : link.n + ' interactions';
50500
50625
  if(link.n > 1) html += "<title>" + interactStr + " of residue " + node1.id + " with residue " + node2.id + "</title>";
@@ -50557,6 +50682,44 @@ class LineGraph {
50557
50682
  return html;
50558
50683
  }
50559
50684
 
50685
+ getStrokecolor(value, type) { let ic = this.icn3d, me = ic.icn3dui;
50686
+ let strokecolor = "#000";
50687
+
50688
+ if(value) {
50689
+ if(value == me.htmlCls.hbondValue) {
50690
+ strokecolor = "#" + me.htmlCls.hbondColor;
50691
+ } else if(value == me.htmlCls.ionicValue) {
50692
+ strokecolor = "#" + me.htmlCls.ionicColor;
50693
+ } else if(value == me.htmlCls.halogenValue) {
50694
+ strokecolor = "#" + me.htmlCls.halogenColor;
50695
+ } else if(value == me.htmlCls.picationValue) {
50696
+ strokecolor = "#" + me.htmlCls.picationColor;
50697
+ } else if(value == me.htmlCls.pistackingValue) {
50698
+ strokecolor = "#" + me.htmlCls.pistackingColor;
50699
+ } else if(value == me.htmlCls.contactValue) {
50700
+ strokecolor = "#" + me.htmlCls.contactColor;
50701
+ }
50702
+ }
50703
+
50704
+ if(type) {
50705
+ if(type == 'hbond') {
50706
+ strokecolor = "#" + me.htmlCls.hbondColor;
50707
+ } else if(type == 'ionic') {
50708
+ strokecolor = "#" + me.htmlCls.ionicColor;
50709
+ } else if(type == 'halogen') {
50710
+ strokecolor = "#" + me.htmlCls.halogenColor;
50711
+ } else if(type == 'pi-cation') {
50712
+ strokecolor = "#" + me.htmlCls.picationColor;
50713
+ } else if(type == 'pi-stacking') {
50714
+ strokecolor = "#" + me.htmlCls.pistackingColor;
50715
+ } else if(type == 'contact') {
50716
+ strokecolor = "#" + me.htmlCls.contactColor;
50717
+ }
50718
+ }
50719
+
50720
+ return strokecolor;
50721
+ }
50722
+
50560
50723
  drawOnePairNode(link, node1, node2, node2posSet1, node2posSet2, bContactMap, bAfMap) { let ic = this.icn3d, me = ic.icn3dui;
50561
50724
  let html = '';
50562
50725
 
@@ -50572,20 +50735,7 @@ class LineGraph {
50572
50735
  let pos2 = node2posSet2[node2.id];
50573
50736
  if(pos1 === undefined || pos2 === undefined) return html;
50574
50737
 
50575
- let strokecolor;
50576
- if(link.v == me.htmlCls.hbondValue) {
50577
- strokecolor = "#" + me.htmlCls.hbondColor;
50578
- } else if(link.v == me.htmlCls.ionicValue) {
50579
- strokecolor = "#" + me.htmlCls.ionicColor;
50580
- } else if(link.v == me.htmlCls.halogenValue) {
50581
- strokecolor = "#" + me.htmlCls.halogenColor;
50582
- } else if(link.v == me.htmlCls.picationValue) {
50583
- strokecolor = "#" + me.htmlCls.picationColor;
50584
- } else if(link.v == me.htmlCls.pistackingValue) {
50585
- strokecolor = "#" + me.htmlCls.pistackingColor;
50586
- } else if(link.v == me.htmlCls.contactValue) {
50587
- strokecolor = "#" + me.htmlCls.contactColor;
50588
- }
50738
+ let strokecolor = this.getStrokecolor(link.v);
50589
50739
 
50590
50740
  if(bContactMap) strokecolor = "#" + link.c;
50591
50741
 
@@ -51165,6 +51315,10 @@ class GetGraph {
51165
51315
  convertLabel2Resid(residLabel) {var ic = this.icn3d; ic.icn3dui;
51166
51316
  //ASN $1KQ2.A:6@ND2
51167
51317
  //or ASN $1KQ2.A:6
51318
+ // or ASN $1KQ2.A:6@ND2 1234
51319
+ let idArray = residLabel.split(' ');
51320
+ residLabel = (idArray.length == 2) ? residLabel : residLabel.substr(0, residLabel.lastIndexOf(' '));
51321
+
51168
51322
  residLabel.indexOf(' ');
51169
51323
  let pos2Tmp = residLabel.indexOf('@');
51170
51324
  let pos2 =(pos2Tmp !== -1) ? pos2Tmp : residLabel.length;
@@ -51199,6 +51353,25 @@ class ShowInter {
51199
51353
  ic.dAtoms = me.hashUtilsCls.unionHash(ic.dAtoms, atoms);
51200
51354
  ic.dAtoms = me.hashUtilsCls.unionHash(ic.dAtoms, atoms2);
51201
51355
 
51356
+ if(type == 'ligplot') {
51357
+ let residueHash1 = ic.firstAtomObjCls.getResiduesFromAtoms(atoms);
51358
+ let residueHash2 = ic.firstAtomObjCls.getResiduesFromAtoms(atoms2);
51359
+
51360
+ if(Object.keys(residueHash1).length > 1 && Object.keys(residueHash2).length > 1) {
51361
+ alert("Please select one ligand or residue as one of the interaction sets...");
51362
+ return;
51363
+ }
51364
+
51365
+ // switch the sets to make the first set as the ligand
51366
+ if(Object.keys(residueHash1).length < Object.keys(residueHash2).length) {
51367
+ nameArray2 = $("#" + ic.pre + "atomsCustomHbond").val();
51368
+ nameArray = $("#" + ic.pre + "atomsCustomHbond2").val();
51369
+
51370
+ atoms = ic.definedSetsCls.getAtomsFromNameArray(nameArray);
51371
+ atoms2 = ic.definedSetsCls.getAtomsFromNameArray(nameArray2);
51372
+ }
51373
+ }
51374
+
51202
51375
  if(nameArray2.length == 0) {
51203
51376
  alert("Please select the first set");
51204
51377
  }
@@ -51242,6 +51415,9 @@ class ShowInter {
51242
51415
  else if(type == 'scatterplot') {
51243
51416
  me.htmlCls.clickMenuCls.setLogCmd("scatterplot interaction pairs | " + tmpStr, true);
51244
51417
  }
51418
+ else if(type == 'ligplot') {
51419
+ me.htmlCls.clickMenuCls.setLogCmd("ligplot interaction pairs | " + tmpStr, true);
51420
+ }
51245
51421
  else if(type == 'graph') { // force-directed graph
51246
51422
  let dist_ss = parseInt($("#" + ic.pre + "dist_ss").val());
51247
51423
  let dist_coil = parseInt($("#" + ic.pre + "dist_coil").val());
@@ -51930,6 +52106,9 @@ class ViewInterPairs {
51930
52106
  let svgHtml = ic.lineGraphCls.drawLineGraph(ic.graphStr, true);
51931
52107
  $("#" + ic.pre + "scatterplotDiv").html(svgHtml);
51932
52108
  }
52109
+ else if(type == 'ligplot') {
52110
+ await ic.ligplotCls.drawLigplot(atomSet1);
52111
+ }
51933
52112
  else if(bContactMapLocal) {
51934
52113
  me.htmlCls.dialogCls.openDlg('dl_contactmap', 'Show contact map');
51935
52114
  let bAnyAtom = true;
@@ -52019,7 +52198,9 @@ class ViewInterPairs {
52019
52198
  }
52020
52199
  }
52021
52200
 
52022
- getAllInteractionTable(type) { let ic = this.icn3d, me = ic.icn3dui;
52201
+ getAllInteractionTable(type, index2xy, xlen, ylen, xcenter, ycenter) { let ic = this.icn3d, me = ic.icn3dui;
52202
+ let svgHtmlNode = '', svgHtmlLine = '';
52203
+
52023
52204
  let bondCnt = [];
52024
52205
 
52025
52206
  let residsArray = Object.keys(ic.resids2inter);
@@ -52058,41 +52239,54 @@ class ViewInterPairs {
52058
52239
  }
52059
52240
  let labels2dist, result;
52060
52241
  labels2dist = ic.resids2inter[resids]['hbond'];
52061
- result = this.getInteractionPairDetails(labels2dist, type, 'hbond');
52242
+ result = this.getInteractionPairDetails(labels2dist, type, 'hbond', index2xy, xlen, ylen, xcenter, ycenter);
52062
52243
  strHbond += result.html;
52063
52244
  cntHbond += result.cnt;
52245
+ svgHtmlNode += result.svgHtmlNode;
52246
+ svgHtmlLine += result.svgHtmlLine;
52064
52247
  if(result.cnt > 0) residname2List += residname2 + ":hbond_" + result.cnt + " ";
52065
52248
 
52066
52249
  labels2dist = ic.resids2inter[resids]['ionic'];
52067
- result = this.getInteractionPairDetails(labels2dist, type, 'ionic');
52250
+ result = this.getInteractionPairDetails(labels2dist, type, 'ionic', index2xy, xlen, ylen, xcenter, ycenter);
52068
52251
  strIonic += result.html;
52069
52252
  cntIonic += result.cnt;
52253
+ svgHtmlNode += result.svgHtmlNode;
52254
+ svgHtmlLine += result.svgHtmlLine;
52070
52255
  if(result.cnt > 0) residname2List += residname2 + ":ionic_" + result.cnt + " ";
52071
52256
 
52072
- labels2dist = ic.resids2inter[resids]['contact'];
52073
- result = this.getContactPairDetails(labels2dist, type, 'contact');
52074
- strContact += result.html;
52075
- cntContact += result.cnt;
52076
- if(result.cnt > 0) residname2List += residname2 + ":contact_" + result.cnt + " ";
52077
-
52078
52257
  labels2dist = ic.resids2inter[resids]['halogen'];
52079
- result = this.getInteractionPairDetails(labels2dist, type, 'halogen');
52258
+ result = this.getInteractionPairDetails(labels2dist, type, 'halogen', index2xy, xlen, ylen, xcenter, ycenter);
52080
52259
  strHalegen += result.html;
52081
52260
  cntHalegen += result.cnt;
52261
+ svgHtmlNode += result.svgHtmlNode;
52262
+ svgHtmlLine += result.svgHtmlLine;
52082
52263
  if(result.cnt > 0) residname2List += residname2 + ":halogen_" + result.cnt + " ";
52083
52264
 
52084
52265
  labels2dist = ic.resids2inter[resids]['pi-cation'];
52085
- result = this.getInteractionPairDetails(labels2dist, type, 'pi-cation');
52266
+ result = this.getInteractionPairDetails(labels2dist, type, 'pi-cation', index2xy, xlen, ylen, xcenter, ycenter);
52086
52267
  strPication += result.html;
52087
52268
  cntPication += result.cnt;
52269
+ svgHtmlNode += result.svgHtmlNode;
52270
+ svgHtmlLine += result.svgHtmlLine;
52088
52271
  if(result.cnt > 0) residname2List += residname2 + ":pi-cation_" + result.cnt + " ";
52089
52272
 
52090
52273
  labels2dist = ic.resids2inter[resids]['pi-stacking'];
52091
- result = this.getInteractionPairDetails(labels2dist, type, 'pi-stacking');
52274
+ result = this.getInteractionPairDetails(labels2dist, type, 'pi-stacking', index2xy, xlen, ylen, xcenter, ycenter);
52092
52275
  strPistacking += result.html;
52093
52276
  cntPistacking += result.cnt;
52277
+ svgHtmlNode += result.svgHtmlNode;
52278
+ svgHtmlLine += result.svgHtmlLine;
52094
52279
  if(result.cnt > 0) residname2List += residname2 + ":pi-stacking_" + result.cnt + " ";
52095
52280
 
52281
+ // put contact as the last one since contact will use the same node as other interactions in ligand-protein interactoin
52282
+ labels2dist = ic.resids2inter[resids]['contact'];
52283
+ result = this.getContactPairDetails(labels2dist, type, 'contact', index2xy, xlen, ylen, xcenter, ycenter);
52284
+ strContact += result.html;
52285
+ cntContact += result.cnt;
52286
+ svgHtmlNode += result.svgHtmlNode;
52287
+ svgHtmlLine += result.svgHtmlLine;
52288
+ if(result.cnt > 0) residname2List += residname2 + ":contact_" + result.cnt + " ";
52289
+
52096
52290
  prevResidname1 = residname1;
52097
52291
  prevIds = ids;
52098
52292
  }
@@ -52120,7 +52314,7 @@ class ViewInterPairs {
52120
52314
  html += tmpText;
52121
52315
  html += '</tbody></table><br/>';
52122
52316
  }
52123
- return {html: html, bondCnt: bondCnt};
52317
+ return {html: html, bondCnt: bondCnt, svgHtmlNode: svgHtmlNode, svgHtmlLine: svgHtmlLine};
52124
52318
  }
52125
52319
  getInteractionPerResidue(prevIds, strHbond, strIonic, strContact, strHalegen, strPication, strPistacking,
52126
52320
  cntHbond, cntIonic, cntContact, cntHalegen, cntPication, cntPistacking) { let ic = this.icn3d; ic.icn3dui;
@@ -52135,15 +52329,24 @@ class ViewInterPairs {
52135
52329
  tmpText += '</tr>';
52136
52330
  return tmpText;
52137
52331
  }
52138
- getInteractionPairDetails(labels2dist, type, interactionType) { let ic = this.icn3d; ic.icn3dui;
52139
- let tmpText = '', cnt = 0;
52332
+ getInteractionPairDetails(labels2dist, type, interactionType, index2xy, xlen, ylen, xcenter, ycenter) { let ic = this.icn3d; ic.icn3dui;
52333
+ let svgHtmlNode = '', svgHtmlLine = '', tmpText = '', cnt = 0;
52140
52334
  let colorText1 = ' <span style="background-color:#';
52141
52335
  let colorText2 = '">&nbsp;&nbsp;&nbsp;</span>';
52142
52336
  if(labels2dist !== undefined) {
52337
+ if(!ic.resid2cnt) ic.resid2cnt = {};
52338
+ if(!ic.resid2ToXy) ic.resid2ToXy = {};
52339
+ if(!ic.nodeid2lineid) ic.nodeid2lineid = {};
52143
52340
  for(let labels in labels2dist) {
52144
- let resid1_resid2 = labels.split(',');
52145
- let resid1 =(type == 'save1') ? resid1_resid2[0] : resid1_resid2[1];
52146
- let resid2 =(type == 'save1') ? resid1_resid2[1] : resid1_resid2[0];
52341
+ let resid1_resid2 = labels.split('|');
52342
+ let resid1Ori =(type == 'save1') ? resid1_resid2[0] : resid1_resid2[1];
52343
+ let resid2Ori =(type == 'save1') ? resid1_resid2[1] : resid1_resid2[0];
52344
+ //resid1: MET $3GVU.A:364@N 1234
52345
+ let pos1 = resid1Ori.lastIndexOf(' ');
52346
+ let pos2 = resid2Ori.lastIndexOf(' ');
52347
+ let resid1 = resid1Ori.substr(0, pos1);
52348
+ let resid2 = resid2Ori.substr(0, pos2);
52349
+
52147
52350
  let resid1Real = ic.getGraphCls.convertLabel2Resid(resid1);
52148
52351
  let atom1 = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid1Real]);
52149
52352
  let color1 = (atom1.color) ? atom1.color.getHexString() : '';
@@ -52155,38 +52358,125 @@ class ViewInterPairs {
52155
52358
  tmpText += '<td align="center"><button class="' + ic.pre + 'selres" resid="' + resid1 + '|' + resid2 + '">Highlight</button></td>';
52156
52359
  tmpText += '</tr>';
52157
52360
  ++cnt;
52361
+
52362
+ if(index2xy) {
52363
+ let serialArray1 = resid1Ori.substr(pos1 + 1).split(',');
52364
+
52365
+ let result = ic.ligplotCls.getSvgPerPair(serialArray1, resid1, resid2, interactionType, index2xy, xlen, ylen, xcenter, ycenter);
52366
+ svgHtmlNode += result.node;
52367
+ svgHtmlLine += result.line;
52368
+ }
52158
52369
  }
52159
52370
  }
52160
- return {html: tmpText, cnt: cnt}
52371
+ return {html: tmpText, cnt: cnt, svgHtmlNode: svgHtmlNode, svgHtmlLine: svgHtmlLine}
52161
52372
  }
52162
- getContactPairDetails(labels2dist, type) { let ic = this.icn3d; ic.icn3dui;
52163
- let tmpText = '', cnt = 0;
52373
+
52374
+ getContactPairDetails(labels2dist, type, interactionType, index2xy, xlen, ylen, xcenter, ycenter) { let ic = this.icn3d; ic.icn3dui;
52375
+ let svgHtmlNode = '', svgHtmlLine = '', tmpText = '', cnt = 0;
52164
52376
  let colorText1 = ' <span style="background-color:#';
52165
52377
  let colorText2 = '">&nbsp;&nbsp;&nbsp;</span>';
52166
52378
  if(labels2dist !== undefined) {
52379
+ let resids2distCnt = {};
52380
+ if(!ic.resid2cnt) ic.resid2cnt = {};
52381
+ if(!ic.resid2ToXy) ic.resid2ToXy = {};
52382
+ if(!ic.nodeid2lineid) ic.nodeid2lineid = {};
52167
52383
  for(let labels in labels2dist) {
52168
- let resid1_resid2 = labels.split(',');
52169
- let resid1 =(type == 'save1') ? resid1_resid2[0] : resid1_resid2[1];
52170
- let resid2 =(type == 'save1') ? resid1_resid2[1] : resid1_resid2[0];
52384
+ let resid1_resid2 = labels.split('|');
52385
+ let resid1Ori =(type == 'save1') ? resid1_resid2[0] : resid1_resid2[1];
52386
+ let resid2Ori =(type == 'save1') ? resid1_resid2[1] : resid1_resid2[0];
52387
+ //resid1: MET $3GVU.A:364 1234
52388
+ let pos1 = resid1Ori.lastIndexOf(' ');
52389
+ let pos2 = resid2Ori.lastIndexOf(' ');
52390
+
52391
+ let serialArray1 = resid1Ori.substr(pos1 + 1).split(',');
52392
+ let resid1 = resid1Ori.substr(0, pos1);
52393
+ if(index2xy) {
52394
+ // add atom name to resid1
52395
+ resid1 += '@' + ic.atoms[serialArray1[0]].name;
52396
+ }
52397
+
52398
+ let resid2 = resid2Ori.substr(0, pos2);
52399
+ let resids = resid1 + '|' + resid2;
52400
+
52401
+ let resid1Real = ic.getGraphCls.convertLabel2Resid(resid1);
52402
+ ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid1Real]);
52403
+ // let color1 = (atom1.color) ? atom1.color.getHexString() : '';
52404
+ let resid2Real = ic.getGraphCls.convertLabel2Resid(resid2);
52405
+ ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid2Real]);
52406
+ // let color2 = (atom2.color) ? atom2.color.getHexString() : '';
52407
+ let dist1_dist2_atom1_atom2 = labels2dist[labels].split('_');
52408
+ let dist1 = parseFloat(dist1_dist2_atom1_atom2[0]);
52409
+ // let dist2 = parseFloat(dist1_dist2_atom1_atom2[1]);
52410
+ // let atom1Name = dist1_dist2_atom1_atom2[2];
52411
+ // let atom2Name = dist1_dist2_atom1_atom2[3];
52412
+ let contactCnt = parseInt(dist1_dist2_atom1_atom2[4]);
52413
+ if(!resids2distCnt.hasOwnProperty(resids)) {
52414
+ resids2distCnt[resids] = {'dist1': dist1, 'dist1_dist2_atom1_atom2': dist1_dist2_atom1_atom2, 'cnt': contactCnt, 'serialArray1': serialArray1};
52415
+ }
52416
+ else {
52417
+ resids2distCnt[resids].cnt += contactCnt;
52418
+ if(dist1 < resids2distCnt[resids].dist1) {
52419
+ resids2distCnt[resids].dist1 = dist1;
52420
+ resids2distCnt[resids].dist1_dist2_atom1_atom2 = dist1_dist2_atom1_atom2;
52421
+ resids2distCnt[resids].serialArray1 = serialArray1;
52422
+ }
52423
+ }
52424
+ }
52425
+
52426
+ let resid2ToResid1 = {};
52427
+ for(let resids in resids2distCnt) {
52428
+ let resid1_resid2 = resids.split('|');
52429
+ let resid1 = resid1_resid2[0];
52430
+ let resid2 = resid1_resid2[1];
52431
+
52432
+ if(!resid2ToResid1.hasOwnProperty(resid2)) {
52433
+ resid2ToResid1[resid2] = [resid1];
52434
+ }
52435
+ else {
52436
+ resid2ToResid1[resid2].push(resid1);
52437
+ }
52438
+
52171
52439
  let resid1Real = ic.getGraphCls.convertLabel2Resid(resid1);
52172
52440
  let atom1 = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid1Real]);
52173
52441
  let color1 = (atom1.color) ? atom1.color.getHexString() : '';
52174
52442
  let resid2Real = ic.getGraphCls.convertLabel2Resid(resid2);
52175
52443
  let atom2 = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid2Real]);
52176
52444
  let color2 = (atom2.color) ? atom2.color.getHexString() : '';
52177
- let dist1_dist2_atom1_atom2 = labels2dist[labels].split('_');
52445
+ let dist1_dist2_atom1_atom2 = resids2distCnt[resids].dist1_dist2_atom1_atom2;
52178
52446
  let dist1 = dist1_dist2_atom1_atom2[0];
52179
52447
  let dist2 = dist1_dist2_atom1_atom2[1];
52180
52448
  let atom1Name = dist1_dist2_atom1_atom2[2];
52181
52449
  let atom2Name = dist1_dist2_atom1_atom2[3];
52182
- let contactCnt = dist1_dist2_atom1_atom2[4];
52450
+ let contactCnt = 1; //resids2distCnt[resids].cnt;
52451
+
52183
52452
  tmpText += '<tr><td><span style="white-space:nowrap"><input type="checkbox" class="' + ic.pre + 'seloneres" id="' + ic.pre + 'inter2_' + cnt + 'a" resid="' + resid1 + '"/> ' + resid1 + '@' + atom1Name + colorText1 + color1 + colorText2 + '</span></td><td><span style="white-space:nowrap"><input type="checkbox" class="' + ic.pre + 'seloneres" id="' + ic.pre + 'inter2_' + cnt + 'b" resid="' + resid2 + '"/> ' + resid2 + '@' + atom2Name + colorText1 + color2 + colorText2 + '</span></td><td align="center">' + contactCnt + '</td><td align="center">' + dist1 + '</td><td align="center">' + dist2 + '</td>';
52184
52453
  tmpText += '<td align="center"><button class="' + ic.pre + 'selres" resid="' + resid1 + '|' + resid2 + '">Highlight</button></td>';
52185
52454
  tmpText += '</tr>';
52186
52455
  cnt += parseInt(contactCnt);
52187
52456
  }
52457
+
52458
+ if(index2xy) {
52459
+ for(let resid2 in resid2ToResid1) {
52460
+ let resid1Array = resid2ToResid1[resid2];
52461
+ let prevX2, prevY2;
52462
+ for(let i = 0, il = resid1Array.length; i < il; ++i) {
52463
+ let resid1 = resid1Array[i];
52464
+ let resids = resid1 + '|' + resid2;
52465
+
52466
+ let serialArray1 = resids2distCnt[resids].serialArray1;
52467
+
52468
+ let bNotDrawNode = (i == 0) ? false : true;
52469
+ let result = ic.ligplotCls.getSvgPerPair(serialArray1, resid1, resid2, interactionType, index2xy, xlen, ylen, xcenter, ycenter, bNotDrawNode, prevX2, prevY2);
52470
+ svgHtmlNode += result.node;
52471
+ svgHtmlLine += result.line;
52472
+ prevX2 = result.x2;
52473
+ prevY2 = result.y2;
52474
+ }
52475
+ }
52476
+ }
52188
52477
  }
52189
- return {html: tmpText, cnt: cnt}
52478
+
52479
+ return {html: tmpText, cnt: cnt, svgHtmlNode: svgHtmlNode, svgHtmlLine: svgHtmlLine};
52190
52480
  }
52191
52481
 
52192
52482
  //Export the list of residues in some chain interacting with residues in another chain.
@@ -53564,8 +53854,10 @@ class ChainalignParser {
53564
53854
  //$.when(ic.pdbParserCls.applyCommandDssp(true)).then(function() {
53565
53855
  await ic.pdbParserCls.applyCommandDssp(true);
53566
53856
 
53857
+ // original version =============
53567
53858
  // align PDB chains
53568
53859
  for(let index in ic.pdbChainIndexHash) {
53860
+ //ic.pdbChainIndexHash[index] = mmdbid_q_tmp + "_" + ic.chain_q + "_" + ic.mmdbid_t + "_" + ic.chain_t;
53569
53861
  let idArray = ic.pdbChainIndexHash[index].split('_');
53570
53862
  mmdbid_q = idArray[0];
53571
53863
  idArray[1];
@@ -53580,25 +53872,49 @@ class ChainalignParser {
53580
53872
  let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
53581
53873
  let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
53582
53874
 
53875
+ let resRangeArray = (me.cfg.resrange) ? me.cfg.resrange.split(' | ') : [];
53876
+
53583
53877
  for(let index in ic.afChainIndexHash) {
53584
53878
  let idArray = ic.afChainIndexHash[index].split('_');
53585
53879
  mmdbid_q = idArray[0];
53586
53880
  let chain_q = idArray[1];
53881
+ let chainid_q = mmdbid_q + '_' + chain_q;
53882
+
53587
53883
  mmdbid_t = idArray[2];
53588
53884
  let chain_t = idArray[3];
53885
+ let chainid_t = mmdbid_t + '_' + chain_t;
53886
+
53887
+ let atomSet_t = (resRangeArray[0]) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[0].split(','), chainid_t).hAtoms : ic.chains[chainid_t];
53888
+ let atomSet_q = (resRangeArray[index]) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[index].split(','), chainid_q).hAtoms : ic.chains[chainid_q];
53889
+ // end of original version =============
53890
+
53891
+ /*
53892
+ // new version to be done for VASTsrv ==============
53893
+ // dynamically align pairs in all chainids
53894
+ let ajaxArray = [], indexArray = [], struArray = [];
53895
+ let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
53896
+ let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
53897
+
53898
+ let resRangeArray = (me.cfg.resrange) ? me.cfg.resrange.split(' | ') : [];
53899
+
53900
+ // dynamically align pairs in all chainids
53901
+ let atomSet_t = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[0].split(','), chainidArray[0]).hAtoms : ic.chains[chainidArray[0]];
53902
+ for(let index = 1, indexl = chainidArray.length; index < indexl; ++index) {
53903
+ let atomSet_q = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[index].split(','), chainidArray[index]).hAtoms : ic.chains[chainidArray[index]];
53904
+ // end of new version to be done for VASTsrv ==============
53905
+ */
53589
53906
 
53590
53907
  let alignAjax;
53591
53908
  if(me.cfg.aligntool != 'tmalign') {
53592
- let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(ic.chains[mmdbid_q + '_' + chain_q]);
53593
- let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(ic.chains[mmdbid_t + '_' + chain_t]);
53909
+ let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(atomSet_q);
53910
+ let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(atomSet_t);
53594
53911
 
53595
53912
  let dataObj = {'domains1': jsonStr_q, 'domains2': jsonStr_t};
53596
53913
  alignAjax = me.getAjaxPostPromise(urlalign, dataObj);
53597
53914
  }
53598
53915
  else {
53599
- let pdb_query = ic.saveFileCls.getAtomPDB(ic.chains[mmdbid_q + '_' + chain_q]);
53600
-
53601
- let pdb_target= ic.saveFileCls.getAtomPDB(ic.chains[mmdbid_t + '_' + chain_t]);
53916
+ let pdb_query = ic.saveFileCls.getAtomPDB(atomSet_q);
53917
+ let pdb_target= ic.saveFileCls.getAtomPDB(atomSet_t);
53602
53918
 
53603
53919
  let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target};
53604
53920
  alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
@@ -54001,7 +54317,7 @@ class ChainalignParser {
54001
54317
  return chainidArray;
54002
54318
  }
54003
54319
 
54004
- async downloadChainalignment(chainalign, resnum, resdef) { let ic = this.icn3d, me = ic.icn3dui;
54320
+ async downloadChainalignment(chainalign) { let ic = this.icn3d, me = ic.icn3dui;
54005
54321
  let thisClass = this;
54006
54322
 
54007
54323
  ic.opts['proteins'] = 'c alpha trace';
@@ -54278,7 +54594,7 @@ class ChainalignParser {
54278
54594
  async loadOpmDataForChainalign(data1, data2, chainidArray, mmdbidArray) { let ic = this.icn3d, me = ic.icn3dui;
54279
54595
  let thisClass = this;
54280
54596
 
54281
- if(me.cfg.resnum || me.cfg.resdef) {
54597
+ if(me.cfg.resnum || me.cfg.resdef || me.cfg.resrange) {
54282
54598
  if(!ic.bCommandLoad) ic.init(); // remove all previously loaded data
54283
54599
  await this.downloadChainalignmentPart2(data1, data2, undefined, chainidArray);
54284
54600
 
@@ -56227,6 +56543,22 @@ class MmdbParser {
56227
56543
  hAtoms = ic.loadAtomDataCls.loadAtomDataIn(data, pdbid, 'mmdbid', undefined, type, chainid, chainIndex, bLastQuery, bNoTransformNoSeqalign);
56228
56544
  }
56229
56545
 
56546
+ // show ligand-protein interaction
56547
+ if(me.cfg.ligand) { // sid123059722
56548
+ for(let chainid in ic.chainid2sid) {
56549
+ if(ic.chainid2sid[chainid] == me.cfg.ligand.substr(3)) {
56550
+ // save a set named me.cfg.ligand
56551
+ let residueHash = ic.firstAtomObjCls.getResiduesFromAtoms(ic.chains[chainid]);
56552
+ let idArray = Object.keys(residueHash)[0].split('_');
56553
+ let select = '.' + idArray[1] + ':' + idArray[2];
56554
+
56555
+ await ic.selByCommCls.selectByCommand(select, me.cfg.ligand, me.cfg.ligand);
56556
+ break;
56557
+ }
56558
+ }
56559
+ }
56560
+ ic.hAtoms = hAtoms;
56561
+
56230
56562
  // set 3d domains
56231
56563
  let structure = data.pdbId;
56232
56564
 
@@ -59155,6 +59487,7 @@ class DensityCifParser {
59155
59487
 
59156
59488
  //https://www.ebi.ac.uk/pdbe/densities/doc.html
59157
59489
  if(type == '2fofc' || type == 'fofc') {
59490
+ detail = 0;
59158
59491
  url = "https://www.ebi.ac.uk/pdbe/densities/x-ray/" + pdbid.toLowerCase() + "/cell?detail=" + detail;
59159
59492
  }
59160
59493
  else if(type == 'em') {
@@ -59195,6 +59528,39 @@ class DensityCifParser {
59195
59528
  }
59196
59529
  }
59197
59530
 
59531
+ async densityCifParserBase(url, type, sigma, location, bInputSigma) { let ic = this.icn3d, me = ic.icn3dui;
59532
+ let thisClass = this;
59533
+
59534
+ //https://stackoverflow.com/questions/33902299/using-jquery-ajax-to-download-a-binary-file
59535
+ if(type == '2fofc' && ic.bAjax2fofc) {
59536
+ ic.mapData.sigma2 = sigma;
59537
+ ic.setOptionCls.setOption('map', type);
59538
+ }
59539
+ else if(type == 'fofc' && ic.bAjaxfofc) {
59540
+ ic.mapData.sigma = sigma;
59541
+ ic.setOptionCls.setOption('map', type);
59542
+ }
59543
+ else {
59544
+ let arrayBuffer = await me.getXMLHttpRqstPromise(url, 'GET', 'arraybuffer', type);
59545
+
59546
+ thisClass.parseChannels(arrayBuffer, type, sigma);
59547
+
59548
+ if(type == '2fofc' || type == 'fofc') {
59549
+ ic.bAjax2fofc = true;
59550
+ ic.bAjaxfofc = true;
59551
+
59552
+ ic.setOptionCls.setOption('map', type);
59553
+ }
59554
+ else if(type == 'em') {
59555
+ ic.bAjaxEm = true;
59556
+
59557
+ ic.setOptionCls.setOption('emmap', type);
59558
+ }
59559
+ }
59560
+
59561
+ // return sigma;
59562
+ }
59563
+
59198
59564
  parseChannels(densitydata, type, sigma) { let ic = this.icn3d; ic.icn3dui;
59199
59565
  let cif = this.BinaryParse(densitydata);
59200
59566
 
@@ -64187,7 +64553,7 @@ class LoadCIF {
64187
64553
 
64188
64554
  let bFirstAtom = true;
64189
64555
 
64190
- let cifArray = bcifData.split('ENDMDL\n');
64556
+ let cifArray = (bText) ? bcifData.split('ENDMDL\n') : [bcifData];
64191
64557
 
64192
64558
  for(let index = 0, indexl = cifArray.length; index < indexl; ++index) {
64193
64559
  ++moleculeNum;
@@ -66780,6 +67146,7 @@ class ApplyCommand {
66780
67146
  || commandOri.indexOf('save2 interaction pairs') == 0
66781
67147
  || commandOri.indexOf('line graph interaction pairs') == 0
66782
67148
  || commandOri.indexOf('scatterplot interaction pairs') == 0
67149
+ || commandOri.indexOf('ligplot interaction pairs') == 0
66783
67150
  ) {
66784
67151
  let paraArray = commandOri.split(' | ');
66785
67152
  if(paraArray.length >= 3) {
@@ -66837,6 +67204,9 @@ class ApplyCommand {
66837
67204
  else if(commandOri.indexOf('scatterplot interaction pairs') == 0) {
66838
67205
  type = 'scatterplot';
66839
67206
  }
67207
+ else if(commandOri.indexOf('ligplot interaction pairs') == 0) {
67208
+ type = 'ligplot';
67209
+ }
66840
67210
 
66841
67211
  await ic.viewInterPairsCls.viewInteractionPairs(nameArray2, nameArray, bHbondCalc, type, bHbond, bSaltbridge, bInteraction, bHalogen, bPication, bPistacking);
66842
67212
  }
@@ -66896,6 +67266,14 @@ class ApplyCommand {
66896
67266
 
66897
67267
  $("#" + me.scatterplotid).attr("width",(ic.scatterplotWidth * parseFloat(scale)).toString() + "px");
66898
67268
  }
67269
+ else if(command.indexOf('ligplot scale') == 0) {
67270
+ let pos = command.lastIndexOf(' ');
67271
+ let scale = command.substr(pos + 1);
67272
+
67273
+ $("#" + me.ligplotid + "_scale").val(scale);
67274
+
67275
+ $("#" + me.ligplotid).attr("width",(ic.ligplotWidth * parseFloat(scale)).toString() + "px");
67276
+ }
66899
67277
  else if(command.indexOf('contactmap scale') == 0) {
66900
67278
  let pos = command.lastIndexOf(' ');
66901
67279
  let scale = command.substr(pos + 1);
@@ -67178,6 +67556,16 @@ class ApplyCommand {
67178
67556
  ic.transformCls.rotateCoord(ic.hAtoms, mArrayFloat);
67179
67557
  ic.drawCls.draw();
67180
67558
  }
67559
+ else if(command.indexOf('set dssp sse') == 0) {
67560
+ await ic.pdbParserCls.applyCommandDssp();
67561
+ ic.bResetAnno = true;
67562
+
67563
+ if(ic.bAnnoShown) {
67564
+ await ic.showAnnoCls.showAnnotations();
67565
+
67566
+ ic.annotationCls.resetAnnoTabAll();
67567
+ }
67568
+ }
67181
67569
 
67182
67570
  // special, select ==========
67183
67571
 
@@ -67539,6 +67927,7 @@ class ApplyCommand {
67539
67927
  else if(cmd.indexOf('save2 interaction pairs') == 0) return hbondIntStr + ': "Set 2" button';
67540
67928
  else if(cmd.indexOf('line graph interaction pairs') == 0) return hbondIntStr + ': "2D Interaction Network" button';
67541
67929
  else if(cmd.indexOf('scatterplot interaction pairs') == 0) return hbondIntStr + ': "2D Interaction Map" button';
67930
+ else if(cmd.indexOf('ligplot interaction pairs') == 0) return hbondIntStr + ': "2D Interaction for One Ligand/Residue" button';
67542
67931
  else if(cmd.indexOf('graph label') == 0) return forceStr + ': "Label Size" menu';
67543
67932
  else if(cmd.indexOf('graph force') == 0) return forceStr + ': "Force on Nodes" menu';
67544
67933
  else if(cmd.indexOf('hide edges') == 0) return forceStr + ': "Internal Edges" menu';
@@ -69160,20 +69549,23 @@ class LoadScript {
69160
69549
  }
69161
69550
  }
69162
69551
  else if(command.indexOf('load chainalignment') !== -1) {
69163
- //load chainalignment [id] | resnum [resnum] | resdef [resnum] | aligntool [aligntool] | parameters [inpara]
69552
+ //load chainalignment [id] | resnum [resnum] | resdef [resdef] | aligntool [aligntool] | parameters [inpara] | resrange [resrange]
69164
69553
  let urlArray = command.split(" | ");
69165
69554
  if(urlArray.length > 1 && urlArray[1].indexOf('resnum') != -1) {
69166
69555
  me.cfg.resnum = urlArray[1].substr(urlArray[1].indexOf('resnum') + 7);
69167
69556
  }
69168
69557
  if(urlArray.length > 2 && urlArray[2].indexOf('resdef') != -1) {
69169
- me.cfg.resdef = urlArray[2].substr(urlArray[1].indexOf('resdef') + 7);
69558
+ me.cfg.resdef = urlArray[2].substr(urlArray[2].indexOf('resdef') + 7);
69170
69559
  }
69171
69560
  if(urlArray.length > 3 && urlArray[3].indexOf('aligntool') != -1) {
69172
- me.cfg.aligntool = urlArray[3].substr(urlArray[1].indexOf('aligntool') + 10);
69561
+ me.cfg.aligntool = urlArray[3].substr(urlArray[3].indexOf('aligntool') + 10);
69562
+ }
69563
+ if(urlArray.length > 5 && urlArray[5].indexOf('resrange') != -1) {
69564
+ me.cfg.resrange = urlArray[5].substr(urlArray[5].indexOf('resrange') + 9);
69173
69565
  }
69174
69566
 
69175
69567
  me.cfg.chainalign = id;
69176
- await ic.chainalignParserCls.downloadChainalignment(id, me.cfg.resnum, me.cfg.resdef);
69568
+ await ic.chainalignParserCls.downloadChainalignment(id);
69177
69569
  }
69178
69570
  else if(command.indexOf('load url') !== -1) {
69179
69571
  let typeStr = load_parameters[1]; // type pdb
@@ -69222,7 +69614,8 @@ class LoadScript {
69222
69614
  if(urlArray.length == 2) {
69223
69615
  let bInputSigma = true;
69224
69616
  if(fileType == 'dsn6') {
69225
- await ic.dsn6ParserCls.dsn6ParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
69617
+ // await ic.dsn6ParserCls.dsn6ParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
69618
+ await ic.densityCifParserCls.densityCifParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
69226
69619
  }
69227
69620
  else if(fileType == 'ccp4') {
69228
69621
  await ic.ccp4ParserCls.ccp4ParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
@@ -69235,7 +69628,8 @@ class LoadScript {
69235
69628
  }
69236
69629
  }
69237
69630
  else {
69238
- await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma);
69631
+ // await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma);
69632
+ await ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma);
69239
69633
  }
69240
69634
  }
69241
69635
  // }); // end of me.deferred = $.Deferred(function() {
@@ -76091,6 +76485,12 @@ class Diagram2d {
76091
76485
  thisClass.clickNode(this);
76092
76486
  });
76093
76487
 
76488
+ $(document).on("click", "#" + ic.pre + "dl_ligplot .icn3d-node", function(e) { thisClass.icn3d;
76489
+ e.stopImmediatePropagation();
76490
+
76491
+ thisClass.clickNode(this);
76492
+ });
76493
+
76094
76494
  //$("#" + ic.pre + "dl_linegraph .icn3d-interaction", "click", function(e) { let ic = this.icn3d, me = ic.icn3dui;
76095
76495
  $(document).on("click", "#" + ic.pre + "dl_linegraph .icn3d-interaction", function(e) { let ic = thisClass.icn3d;
76096
76496
  e.stopImmediatePropagation();
@@ -76173,6 +76573,8 @@ class Diagram2d {
76173
76573
  let strokeWidth = 2;
76174
76574
  $(node).find('circle').attr('stroke', me.htmlCls.ORANGE);
76175
76575
  $(node).find('circle').attr('stroke-width', strokeWidth);
76576
+ $(node).find('rect').attr('stroke', me.htmlCls.ORANGE);
76577
+ $(node).find('rect').attr('stroke-width', strokeWidth);
76176
76578
 
76177
76579
  ic.hAtoms = me.hashUtilsCls.unionHash(ic.hAtoms, ic.residues[resid]);
76178
76580
 
@@ -77290,6 +77692,364 @@ class Cartoon2d {
77290
77692
  }
77291
77693
  }
77292
77694
 
77695
+ /**
77696
+ * @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
77697
+ */
77698
+
77699
+ class Ligplot {
77700
+ constructor(icn3d) {
77701
+ this.icn3d = icn3d;
77702
+ }
77703
+
77704
+ async drawLigplot(atomSet1) { let ic = this.icn3d, me = ic.icn3dui;
77705
+ me.htmlCls.dialogCls.openDlg('dl_ligplot', 'Show ligand interactions with atom details');
77706
+
77707
+ let widthOri, heightOri, width = 100, height = 100;
77708
+ ic.len4ang = 80;
77709
+
77710
+ // get SVG from backend
77711
+ let pdbStr = ic.saveFileCls.getAtomPDB(atomSet1);
77712
+ pdbStr = pdbStr.trim();
77713
+ pdbStr = pdbStr.replace(/\n\n/g, '\n'); // remove empty lines
77714
+
77715
+ let dataObj = {'pdb2svg': pdbStr};
77716
+ let url = me.htmlCls.baseUrl + "openbabel/openbabel.cgi";
77717
+ let dataStr = await me.getAjaxPostPromise(url, dataObj, undefined, undefined, undefined, undefined, 'text');
77718
+
77719
+ let lineArray = dataStr.split('\n');
77720
+ let lineSvg = '', nodeSvg = '', index2xy = {};
77721
+ let xsum = 0, ysum = 0, cnt = 0;
77722
+ ic.svgGridSize = ic.len4ang; // make the scg into many grids to tell whether the grid is empty, 30 is about bond length (1.5 angstrom)
77723
+ ic.gridXY2used = {};
77724
+ for(let i = 0, il = lineArray.length; i < il; ++i) {
77725
+ let line = lineArray[i];
77726
+ if(line.indexOf('<svg width') == 0) {
77727
+ //<svg width="100" height="100" x="0" y="0" viewBox="0 0 634.256 380"
77728
+ // get real width and height
77729
+ let start = line.indexOf('viewBox="') + 9;
77730
+ let linePart = line.substr(start);
77731
+ let viewbox = linePart.substr(0, linePart.indexOf('"'));
77732
+ let viewboxArray = viewbox.split(' ');
77733
+ widthOri = parseFloat(viewboxArray[2]);
77734
+ heightOri = parseFloat(viewboxArray[3]);
77735
+ width = widthOri + 2*ic.len4ang;
77736
+ height = heightOri + 2*ic.len4ang;
77737
+ }
77738
+ else if(line.indexOf('<line') == 0) {
77739
+ lineSvg += line + '\n';
77740
+ }
77741
+ else if(line.indexOf('<text') == 0) {
77742
+ if(line.indexOf('font-size="12"') != -1) {
77743
+ // index node
77744
+ //<text x="40.000000" y="120.000000" fill="rgb(255,0,0)" stroke-width="0" font-weight="bold" font-size="12" >1</text>
77745
+ let start = line.indexOf('>') + 1;
77746
+ let indexPart = line.substr(start);
77747
+ let index = parseInt(indexPart.substr(0, indexPart.indexOf('<')));
77748
+
77749
+ start = line.indexOf('x="') + 3;
77750
+ let xPart = line.substr(start);
77751
+ let x = parseFloat(xPart.substr(0, xPart.indexOf('"')));
77752
+
77753
+ start = line.indexOf('y="') + 3;
77754
+ let yPart = line.substr(start);
77755
+ let y = parseFloat(yPart.substr(0, yPart.indexOf('"')));
77756
+
77757
+ index2xy[index] = {"x": x, "y": y};
77758
+ let xGrid = parseInt(x / ic.svgGridSize);
77759
+ let yGrid = parseInt(y / ic.svgGridSize);
77760
+ ic.gridXY2used[xGrid + '_' + yGrid] = 1;
77761
+
77762
+ xsum += x;
77763
+ ysum += y;
77764
+ ++cnt;
77765
+ }
77766
+ else { // font-size > 12
77767
+ nodeSvg += line + '\n';
77768
+ }
77769
+ }
77770
+ else if(line.indexOf('</svg>') == 0) {
77771
+ break;
77772
+ }
77773
+ }
77774
+
77775
+ let xcenter = xsum / cnt, ycenter = ysum / cnt;
77776
+
77777
+ let id = me.ligplotid;
77778
+ ic.ligplotWidth = width;
77779
+ let graphWidth = ic.ligplotWidth;
77780
+
77781
+ let textHeight = 30;
77782
+ let heightAll = height + textHeight;
77783
+
77784
+ let offset = - ic.len4ang;
77785
+ let svgHtml = "<svg id='" + id + "' viewBox='" + offset + "," + offset + "," + width + "," + heightAll + "' width='" + graphWidth + "px' font-family='sans-serif' stroke='rgb(0,0,0)' stroke-width='2' stroke-linecap='round'>";
77786
+
77787
+ let xlen = parseInt(widthOri / ic.svgGridSize), ylen = parseInt(heightOri / ic.svgGridSize);
77788
+ let result = ic.viewInterPairsCls.getAllInteractionTable("save1", index2xy, xlen, ylen, xcenter, ycenter); // sort on the ligand/set1
77789
+ ic.bLigplot = true;
77790
+
77791
+ svgHtml += lineSvg + result.svgHtmlLine;
77792
+
77793
+ svgHtml += nodeSvg + result.svgHtmlNode;
77794
+
77795
+ svgHtml += "</svg>";
77796
+
77797
+ $("#" + ic.pre + "ligplotDiv").html(svgHtml);
77798
+
77799
+ this.setEventsForLigplot();
77800
+ }
77801
+
77802
+
77803
+ getSvgPerPair(serialArray1, resid1, resid2, interactionType, index2xy, xlen, ylen, xcenter, ycenter, bNotDrawNode, prevX2, prevY2) { let ic = this.icn3d, me = ic.icn3dui;
77804
+ let xOffset = 1, yOffset = -1;
77805
+ let bondLen = (interactionType == 'hbond' || interactionType == 'contact' || interactionType == 'halogen') ? ic.len4ang : ic.len4ang * 1.5; // real distance should be bout 120, not 80
77806
+ let shortBondLen = ic.len4ang / 2;
77807
+ let strokeWidth = (interactionType == 'contact') ? 1 : 2;
77808
+
77809
+ let resid1Real = ic.getGraphCls.convertLabel2Resid(resid1);
77810
+ let atom1 = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid1Real]);
77811
+ let resid2Real = ic.getGraphCls.convertLabel2Resid(resid2);
77812
+ let atom2 = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid2Real]);
77813
+
77814
+ let xSum = 0, ySum = 0, cntPoint = 0;
77815
+ let baseSerial = atom1.serial;
77816
+ for(let i = 0, il = serialArray1.length; i < il; ++i) {
77817
+ let index = serialArray1[i] - baseSerial + 1;
77818
+ xSum += index2xy[index].x;
77819
+ ySum += index2xy[index].y;
77820
+ ++cntPoint;
77821
+ }
77822
+
77823
+ let x1 = xSum / cntPoint - xOffset;
77824
+ let y1 = ySum / cntPoint - yOffset;
77825
+
77826
+ if(!ic.resid2cnt.hasOwnProperty(resid1)) {
77827
+ ic.resid2cnt[resid1] = 0;
77828
+ }
77829
+ else {
77830
+ ++ic.resid2cnt[resid1];
77831
+ }
77832
+
77833
+ let x2, y2, angle;
77834
+ if(!bNotDrawNode && !ic.resid2ToXy.hasOwnProperty(resid2Real)) {
77835
+ // 1st and ideal way to find a position. If failed, use the 2nd way
77836
+ let xGrid = parseInt(x1 / ic.svgGridSize);
77837
+ let yGrid = parseInt(y1 / ic.svgGridSize);
77838
+ let gridArray = [];
77839
+ for(let i = 1; i >= -1; --i) { // try right-bottom first
77840
+ for(let j = 1; j >= -1; --j) {
77841
+ if(!(i == 0 && j == 0)) {
77842
+ if(xGrid + i >= 0 && xGrid + i <= xlen && yGrid + j >= 0 && yGrid + j <= ylen) gridArray.push((xGrid + i) + '_' + (yGrid + j));
77843
+ }
77844
+ }
77845
+ }
77846
+ for(let i = 2; i >= -2; --i) { // try right-bottom first
77847
+ for(let j = 2; j >= -2; --j) {
77848
+ if(!(i >= -1 && i <= 1 && j >= -1 && j <= 1 )) {
77849
+ if(xGrid + i >= 0 && xGrid + i <= xlen && yGrid + j >= 0 && yGrid + j <= ylen) gridArray.push((xGrid + i) + '_' + (yGrid + j));
77850
+ }
77851
+ }
77852
+ }
77853
+
77854
+ let bFound = false, xyGrids;
77855
+ for(let i = 0, il = gridArray.length; i < il; ++i) {
77856
+ if(!ic.gridXY2used[gridArray[i]]) { // found a spot to put the residue
77857
+ xyGrids = gridArray[i].split('_');
77858
+ x2 = (parseInt(xyGrids[0]) + 0.5) * ic.svgGridSize;
77859
+ y2 = (parseInt(xyGrids[1]) + 0.5) * ic.svgGridSize;
77860
+
77861
+ let dist = Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
77862
+ let x2b = bondLen / dist * (x2 - x1) + x1;
77863
+ let y2b = bondLen / dist * (y2 - y1) + y1;
77864
+ x2 = x2b;
77865
+ y2 = y2b;
77866
+
77867
+ ic.gridXY2used[gridArray[i]] = 1;
77868
+ bFound = true;
77869
+ break;
77870
+ }
77871
+ }
77872
+
77873
+ if(!bFound) {
77874
+ // 2nd way to find a position from the center to the outside
77875
+ let dx = x1 - xcenter;
77876
+ let dy = y1 - ycenter;
77877
+
77878
+ let baseAngle = 0;
77879
+ if(Math.abs(dx) > Math.abs(dy)) { // extend along x-axis
77880
+ if(dx > 0) { // +x direction
77881
+ baseAngle = 0;
77882
+ }
77883
+ else { // -x direction
77884
+ baseAngle = 180;
77885
+ }
77886
+ }
77887
+ else { // extend along y-axis
77888
+ if(dy > 0) { // +y direction
77889
+ baseAngle = 90;
77890
+ }
77891
+ else { // -y direction
77892
+ baseAngle = 270;
77893
+ }
77894
+ }
77895
+ angle = baseAngle - 10 + ic.resid2cnt[resid1] * 30;
77896
+
77897
+ x2 = x1 + bondLen * Math.cos(angle * Math.PI/180);
77898
+ y2 = y1 + bondLen * Math.sin(angle * Math.PI/180);
77899
+ }
77900
+ }
77901
+
77902
+ let oneLetterRes = me.utilsCls.residueName2Abbr(atom2.resn.substr(0, 3));
77903
+ let resName2 = oneLetterRes + atom2.resi;
77904
+ let textColor2 = (atom2.color) ? atom2.color.getHexString() : '000';
77905
+ let lineColor = ic.lineGraphCls.getStrokecolor(undefined, interactionType);
77906
+
77907
+ // let node = '<circle cx="' + x2 + '" cy="' + y2 + '" r="8" fill="#' + textColor2 + '" stroke-width="1" stroke="' + textColor2 + '" resid="' + resid2 + '"></circle>\n<text x="' + x2 + '" y="' + y2 + '" stroke="#000" stroke-width="1px" text-anchor="middle" alignment-baseline="central" font-size="8px">' + resName2 + '</text>';
77908
+
77909
+ let node = '', line = '';
77910
+
77911
+ // id can't contain comma and thus use '-'
77912
+ // sometimes the same ligand atom is used in both Hbond and contact. THus we add "interactionType"
77913
+ let idpair = resid2Real + '--' + serialArray1.join('-') + interactionType;
77914
+
77915
+ let id = resid2Real;
77916
+ if(bNotDrawNode || ic.resid2ToXy.hasOwnProperty(id)) {
77917
+ x2 = (ic.resid2ToXy.hasOwnProperty(id)) ? ic.resid2ToXy[id].x2 : prevX2;
77918
+ y2 = (ic.resid2ToXy.hasOwnProperty(id)) ? ic.resid2ToXy[id].y2 : prevY2;
77919
+
77920
+ // draw a short line from x2, y2 to x1, y1 with the distance shortBondLen
77921
+ let x1b = x1, y1b = y1, bShort = 0;
77922
+ if(interactionType == 'contact') {
77923
+ let dist = Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
77924
+ if(shortBondLen < dist) {
77925
+ x1b = shortBondLen / dist * (x1 - x2) + x2;
77926
+ y1b = shortBondLen / dist * (y1 - y2) + y2;
77927
+ bShort = 1;
77928
+ }
77929
+ }
77930
+
77931
+ line += '<line id="' + idpair + '" x1="' + x1b.toFixed(2) + '" y1="' + y1b.toFixed(2) + '" x2="' + x2.toFixed(2) + '" y2="' + y2.toFixed(2) + '" x0="' + x1.toFixed(2) + '" y0="' + y1.toFixed(2) + '" short="' + bShort + '" opacity="1.0" stroke="' + lineColor + '" stroke-width="' + strokeWidth + '" stroke-dasharray="5,5"/>\n';
77932
+ }
77933
+ else {
77934
+ node +='<g>';
77935
+ node += '<title>' + resName2 + '</title>';
77936
+ // node += '<circle class='icn3d-ctnode' cx="' + x2.toFixed(2) + '" cy="' + y2.toFixed(2) + '" r="10" fill="#' + textColor2 + '" stroke-width="1" stroke="' + textColor2 + '" resid="' + resid2Real + '"/>';
77937
+ let boxWidth = 28, boxHeight = 14;
77938
+ node += '<rect id="' + id + '_node" x="' + (x2 - boxWidth*0.5).toFixed(2) + '" y="' + (y2 - boxHeight*0.5).toFixed(2) + '" width="' + boxWidth + '" height="' + boxHeight + '" rx="2" ry="2" fill="#' + textColor2 + '" stroke-width="1" stroke="' + textColor2 + '" resid="' + resid2Real + '"/>';
77939
+
77940
+ node += '<text class="icn3d-ctnode" resid="' + id + '" id="' + id + '" x="' + x2.toFixed(2) + '" y="' + y2.toFixed(2) + '" fill="#000" stroke="none" text-anchor="middle" alignment-baseline="central" style="font-size:10px">' + resName2 + '</text>';
77941
+ node += '</g>\n';
77942
+
77943
+ line += '<line id="' + idpair + '" x1="' + x1.toFixed(2) + '" y1="' + y1.toFixed(2) + '" x2="' + x2.toFixed(2) + '" y2="' + y2.toFixed(2) + '" opacity="1.0" stroke="' + lineColor + '" stroke-width="' + strokeWidth + '" stroke-dasharray="5,5"/>\n';
77944
+
77945
+ if(interactionType != 'contact') {
77946
+ if(!ic.resid2ToXy.hasOwnProperty(resid2Real)) ic.resid2ToXy[resid2Real] = {x2: x2, y2: y2};
77947
+ }
77948
+ }
77949
+
77950
+ if(!ic.nodeid2lineid.hasOwnProperty(id)) ic.nodeid2lineid[id] = [];
77951
+ ic.nodeid2lineid[id].push(idpair);
77952
+
77953
+ return {node: node, line: line, x2: x2, y2: y2};
77954
+ }
77955
+
77956
+ setEventsForLigplot() { let ic = this.icn3d, me = ic.icn3dui;
77957
+ //https://stackoverflow.com/questions/1108480/svg-draggable-using-jquery-and-jquery-svg
77958
+ $("#" + me.ligplotid + " .icn3d-ctnode")
77959
+ .draggable({
77960
+ start: function( e, ui ) {
77961
+ let oriX= parseFloat(e.target.getAttribute('x'));
77962
+ let oriY = parseFloat(e.target.getAttribute('y'));
77963
+
77964
+ e.target.setAttribute('x', oriX);
77965
+ e.target.setAttribute('y', oriY);
77966
+ },
77967
+ drag: function( e, ui ) {
77968
+ let offsetX = $("#" + me.ligplotid).offset().left + ic.len4ang; // ic.len4ang was defined in svg viewbox
77969
+ let offsetY = $("#" + me.ligplotid).offset().top + ic.len4ang;
77970
+
77971
+ let id = e.target.getAttribute('resid');
77972
+ let x = (e.clientX - offsetX);
77973
+ let y = (e.clientY - offsetY);
77974
+
77975
+ let oriX = parseFloat(e.target.getAttribute('x'));
77976
+ let oriY = parseFloat(e.target.getAttribute('y'));
77977
+
77978
+ // change for each step
77979
+ let dx = (x - oriX) / ic.resizeRatioX;
77980
+ let dy = (y - oriY) / ic.resizeRatioY;
77981
+
77982
+ // move the text label
77983
+ oriX = parseFloat($("#" + id + "_node").attr('x'));
77984
+ oriY = parseFloat($("#" + id + "_node").attr('y'));
77985
+
77986
+ $("#" + id + "_node").attr('x', oriX + dx);
77987
+ $("#" + id + "_node").attr('y', oriY + dy);
77988
+
77989
+ // update the center
77990
+ e.target.setAttribute('x', x);
77991
+ e.target.setAttribute('y', y);
77992
+
77993
+ // update the edges
77994
+ if(ic.nodeid2lineid[id]) {
77995
+ for(let i = 0, il = ic.nodeid2lineid[id].length; i < il; ++i) {
77996
+ let idpair = ic.nodeid2lineid[id][i];
77997
+
77998
+ updateEdges(idpair, id);
77999
+ }
78000
+ }
78001
+
78002
+ function updateEdges(idpair, id) {
78003
+ if(idpair && idpair.indexOf(id) != -1) {
78004
+ let idArray = idpair.split('--');
78005
+ if(idArray.length == 2) {
78006
+ let id2;
78007
+ id2 = idArray[0];
78008
+
78009
+ let x2 = parseFloat($("#" + id2).attr('x'));
78010
+ let y2 = parseFloat($("#" + id2).attr('y'));
78011
+
78012
+ $("#" + idpair).attr('x2', x2);
78013
+ $("#" + idpair).attr('y2', y2);
78014
+
78015
+ let x1 = $("#" + idpair).attr('x1');
78016
+ let y1 = $("#" + idpair).attr('y1');
78017
+ let x1b = x1, y1b = y1;
78018
+
78019
+ let bShort = parseInt($("#" + idpair).attr('short'));
78020
+ if(bShort) { // adjust x1,y1
78021
+ x1 = $("#" + idpair).attr('x0');
78022
+ y1 = $("#" + idpair).attr('y0');
78023
+
78024
+ let dist = Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
78025
+ let shortBondLen = ic.len4ang / 2;
78026
+
78027
+ if(shortBondLen < dist) {
78028
+ x1b = shortBondLen / dist * (x1 - x2) + x2;
78029
+ y1b = shortBondLen / dist * (y1 - y2) + y2;
78030
+ }
78031
+ }
78032
+
78033
+ $("#" + idpair).attr('x1', x1b);
78034
+ $("#" + idpair).attr('y1', y1b);
78035
+ }
78036
+ } // if
78037
+ } // function
78038
+ }
78039
+ });
78040
+ }
78041
+
78042
+ clickLigplot() { let ic = this.icn3d; ic.icn3dui;
78043
+ let thisClass = this;
78044
+
78045
+ $(document).on("click", "#" + ic.pre + "dl_ligplot .icn3d-ctnode", function(e) { let ic = thisClass.icn3d;
78046
+ e.stopImmediatePropagation();
78047
+
78048
+ ic.diagram2dCls.clickNode(this);
78049
+ });
78050
+ }
78051
+ }
78052
+
77293
78053
  /**
77294
78054
  * @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
77295
78055
  */
@@ -77973,7 +78733,7 @@ class SaveFile {
77973
78733
  }
77974
78734
  }
77975
78735
 
77976
- saveSvg(id, filename, bContactmap) { let ic = this.icn3d, me = ic.icn3dui;
78736
+ saveSvg(id, filename, bContactmap, bLigplot) { let ic = this.icn3d, me = ic.icn3dui;
77977
78737
  if(me.bNode) return '';
77978
78738
 
77979
78739
  let width = $("#" + id).width();
@@ -77981,19 +78741,26 @@ class SaveFile {
77981
78741
 
77982
78742
  if(bContactmap) height = width;
77983
78743
 
77984
- let svgXml = this.getSvgXml(id, width, height, bContactmap);
78744
+ if(bLigplot) {
78745
+ width += ic.len4ang;
78746
+ height += ic.len4ang;
78747
+ }
78748
+
78749
+ let svgXml = this.getSvgXml(id, width, height, bContactmap, bLigplot);
77985
78750
 
77986
78751
  let blob = new Blob([svgXml], {type: "image/svg+xml"});
77987
78752
  saveAs(blob, filename);
77988
78753
  }
77989
78754
 
77990
- getSvgXml(id, width, height, bContactmap) { let ic = this.icn3d, me = ic.icn3dui;
78755
+ getSvgXml(id, width, height, bContactmap, bLigplot) { let ic = this.icn3d, me = ic.icn3dui;
77991
78756
  if(me.bNode) return '';
77992
78757
 
77993
78758
  // font is not good
77994
78759
  let svg_data = document.getElementById(id).innerHTML; //put id of your svg element here
77995
78760
 
77996
- let viewbox = (width && height) ? "<svg viewBox=\"0 0 " + width + " " + height + "\"" : "<svg";
78761
+ let startX = (bLigplot) ? -30 : 0;
78762
+ let startY = (bLigplot) ? -30 : 0;
78763
+ let viewbox = (width && height) ? "<svg viewBox=\"" + startX + " " + startY + " " + width + " " + height + "\"" : "<svg";
77997
78764
  //let head = viewbox + " title=\"graph\" version=\"1.1\" xmlns:xl=\"http://www.w3.org/1999/xlink\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">";
77998
78765
  let head = viewbox + " title=\"graph\" xmlns:xl=\"http://www.w3.org/1999/xlink\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">";
77999
78766
 
@@ -78005,7 +78772,7 @@ class SaveFile {
78005
78772
  return full_svg;
78006
78773
  }
78007
78774
 
78008
- savePng(id, filename, bContactmap) { let ic = this.icn3d, me = ic.icn3dui;
78775
+ savePng(id, filename, bContactmap, bLigplot) { let ic = this.icn3d, me = ic.icn3dui;
78009
78776
  if(me.bNode) return '';
78010
78777
 
78011
78778
  let width = $("#" + id).width();
@@ -78018,7 +78785,7 @@ class SaveFile {
78018
78785
  let bbox = svg.getBBox();
78019
78786
 
78020
78787
  let copy = svg.cloneNode(true);
78021
- ic.lineGraphCls.copyStylesInline(copy, svg);
78788
+ if(!bLigplot) ic.lineGraphCls.copyStylesInline(copy, svg);
78022
78789
  let canvas = document.createElement("CANVAS");
78023
78790
  canvas.width = width;
78024
78791
  canvas.height = height;
@@ -81811,6 +82578,7 @@ class iCn3D {
81811
82578
  this.shareLinkCls = new ShareLink(this);
81812
82579
  this.diagram2dCls = new Diagram2d(this);
81813
82580
  this.cartoon2dCls = new Cartoon2d(this);
82581
+ this.ligplotCls = new Ligplot(this);
81814
82582
 
81815
82583
  this.rayCls = new Ray(this);
81816
82584
  this.controlCls = new Control(this);
@@ -82037,7 +82805,7 @@ class iCn3DUI {
82037
82805
  //even when multiple iCn3D viewers are shown together.
82038
82806
  this.pre = this.cfg.divid + "_";
82039
82807
 
82040
- this.REVISION = '3.33.2';
82808
+ this.REVISION = '3.34.0';
82041
82809
 
82042
82810
  // In nodejs, iCn3D defines "window = {navigator: {}}"
82043
82811
  this.bNode = (Object.keys(window).length < 2) ? true : false;
@@ -82480,9 +83248,10 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
82480
83248
 
82481
83249
  ic.bChainAlign = true;
82482
83250
  ic.inputid = me.cfg.chainalign;
82483
- ic.loadCmd = 'load chainalignment ' + me.cfg.chainalign + ' | resnum ' + me.cfg.resnum + ' | resdef ' + me.cfg.resdef + ' | aligntool ' + me.cfg.aligntool + ' | parameters ' + me.cfg.inpara;
83251
+ let resrangeStr = (me.cfg.resrange) ? ' | resrange ' + me.cfg.resrange : '';
83252
+ ic.loadCmd = 'load chainalignment ' + me.cfg.chainalign + ' | resnum ' + me.cfg.resnum + ' | resdef ' + me.cfg.resdef + ' | aligntool ' + me.cfg.aligntool + ' | parameters ' + me.cfg.inpara + resrangeStr;
82484
83253
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
82485
- await ic.chainalignParserCls.downloadChainalignment(me.cfg.chainalign, me.cfg.resnum, me.cfg.resdef);
83254
+ await ic.chainalignParserCls.downloadChainalignment(me.cfg.chainalign);
82486
83255
  }
82487
83256
  else if(me.cfg.mmdbafid !== undefined) {
82488
83257
  // ic.bNCBI = true;