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.js CHANGED
@@ -10400,8 +10400,8 @@ class ClickMenu {
10400
10400
  //if(!me.cfg.notebook) dialog.dialog( "close" );
10401
10401
  let sigma2fofc = parseFloat($("#" + me.pre + "sigma2fofc" ).val());
10402
10402
  let type = '2fofc';
10403
- await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma2fofc);
10404
- //ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma2fofc);
10403
+ //await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma2fofc);
10404
+ await ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma2fofc);
10405
10405
 
10406
10406
  //ic.setOptionCls.setOption('map', '2fofc');
10407
10407
  thisClass.setLogCmd('set map 2fofc sigma ' + sigma2fofc, true);
@@ -10413,7 +10413,8 @@ class ClickMenu {
10413
10413
  //if(!me.cfg.notebook) dialog.dialog( "close" );
10414
10414
  let sigmafofc = parseFloat($("#" + me.pre + "sigmafofc" ).val());
10415
10415
  let type = 'fofc';
10416
- await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigmafofc);
10416
+ //await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigmafofc);
10417
+ await ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma2fofc);
10417
10418
  //ic.setOptionCls.setOption('map', 'fofc');
10418
10419
  thisClass.setLogCmd('set map fofc sigma ' + sigmafofc, true);
10419
10420
  });
@@ -10962,6 +10963,18 @@ class ClickMenu {
10962
10963
  me.htmlCls.dialogCls.openDlg('dl_contact', 'Set contact map');
10963
10964
  });
10964
10965
 
10966
+ me.myEventCls.onIds(["#" + me.pre + "mn6_DSSP"], "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
10967
+ thisClass.setLogCmd('set dssp sse', true);
10968
+ await ic.pdbParserCls.applyCommandDssp();
10969
+ ic.bResetAnno = true;
10970
+
10971
+ if(ic.bAnnoShown) {
10972
+ await ic.showAnnoCls.showAnnotations();
10973
+
10974
+ ic.annotationCls.resetAnnoTabAll();
10975
+ }
10976
+ });
10977
+
10965
10978
 
10966
10979
  me.myEventCls.onIds("#" + me.pre + "mn6_hbondsNo", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
10967
10980
  ic.showInterCls.hideHbondsContacts();
@@ -12882,6 +12895,8 @@ class SetMenu {
12882
12895
  html += "</ul>";
12883
12896
  html += "</li>";
12884
12897
 
12898
+ html += this.getLink('mn6_DSSP', 'DSSP Secondary', undefined, 1);
12899
+
12885
12900
  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;
12886
12901
 
12887
12902
  if(bOnePdb) {
@@ -13173,6 +13188,7 @@ class Dialog {
13173
13188
  let bGraph = $('#' + me.pre + 'dl_graph').hasClass('ui-dialog-content'); // initialized
13174
13189
  let bLineGraph = $('#' + me.pre + 'dl_linegraph').hasClass('ui-dialog-content'); // initialized
13175
13190
  let bScatterplot = $('#' + me.pre + 'dl_scatterplot').hasClass('ui-dialog-content'); // initialized
13191
+ let bLigplot = $('#' + me.pre + 'dl_ligplot').hasClass('ui-dialog-content'); // initialized
13176
13192
  let bContactmap = $('#' + me.pre + 'dl_contactmap').hasClass('ui-dialog-content'); // initialized
13177
13193
  let bAlignerrormap = $('#' + me.pre + 'dl_alignerrormap').hasClass('ui-dialog-content'); // initialized
13178
13194
  let bTable = $('#' + me.pre + 'dl_interactionsorted').hasClass('ui-dialog-content'); // initialized
@@ -13182,13 +13198,14 @@ class Dialog {
13182
13198
  let bSetsInit = $('#' + me.pre + 'dl_definedsets').hasClass('ui-dialog-content'); // initialized
13183
13199
 
13184
13200
  status.bSelectannotationsInit2 = false, status.bGraph2 = false, status.bLineGraph2 = false;
13185
- status.bScatterplot2 = false, status.bTable2 = false, status.bAlignmentInit2 = false;
13201
+ status.bScatterplot2 = false, status.bLigplot2 = false, status.bTable2 = false, status.bAlignmentInit2 = false;
13186
13202
  status.bTwoddgmInit2 = false, status.bTwodctnInit2 = false, status.bSetsInit2 = false;
13187
13203
 
13188
13204
  id2flag.dl_selectannotations = 'bSelectannotationsInit2';
13189
13205
  id2flag.dl_graph = 'bGraph2';
13190
13206
  id2flag.dl_linegraph = 'bLineGraph2';
13191
- id2flag.dl_scatterplot = 'bScatterplot2';
13207
+ id2flag.dl_scatterplot = 'bScatterplot2';
13208
+ id2flag.dl_ligplot = 'bLigplot2';
13192
13209
  id2flag.dl_contactmap = 'bContactmap2';
13193
13210
  id2flag.dl_alignerrormap = 'bAlignerrormap2';
13194
13211
  id2flag.dl_interactionsorted = 'bTable2';
@@ -13201,6 +13218,7 @@ class Dialog {
13201
13218
  if(bGraph) status.bGraph2 = $('#' + me.pre + 'dl_graph').dialog( 'isOpen' );
13202
13219
  if(bLineGraph) status.bLineGraph2 = $('#' + me.pre + 'dl_linegraph').dialog( 'isOpen' );
13203
13220
  if(bScatterplot) status.bScatterplot2 = $('#' + me.pre + 'dl_scatterplot').dialog( 'isOpen' );
13221
+ if(bLigplot) status.bLigplot2 = $('#' + me.pre + 'dl_ligplot').dialog( 'isOpen' );
13204
13222
  if(bContactmap) status.bContactmap2 = $('#' + me.pre + 'dl_contactmap').dialog( 'isOpen' );
13205
13223
  if(bAlignerrormap) status.bAlignerror2 = $('#' + me.pre + 'dl_alignerrormap').dialog( 'isOpen' );
13206
13224
  if(bTable) status.bTable2 = $('#' + me.pre + 'dl_interactionsorted').dialog( 'isOpen' );
@@ -13287,7 +13305,7 @@ class Dialog {
13287
13305
 
13288
13306
  d3.select("#" + me.svgid).attr("width", width).attr("height", height);
13289
13307
  }
13290
- else if(id == me.pre + 'dl_linegraph' || id == me.pre + 'dl_scatterplot' || id == me.pre + 'dl_contactmap' || id == me.pre + 'dl_alignerrormap') {
13308
+ 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') {
13291
13309
  let oriWidth =(status.bTwoddgmInit2 || status.bSetsInit2) ?(me.htmlCls.WIDTH - twoddgmWidth)/2 : me.htmlCls.WIDTH / 2;
13292
13310
  let ratio = $("#" + id).width() / oriWidth;
13293
13311
 
@@ -13299,6 +13317,14 @@ class Dialog {
13299
13317
  let width = ic.scatterplotWidth * ratio;
13300
13318
  $("#" + me.scatterplotid).attr("width", width);
13301
13319
  }
13320
+ else if(id == me.pre + 'dl_ligplot') {
13321
+ let width = ic.ligplotWidth * ratio;
13322
+ $("#" + me.ligplotid).attr("width", width);
13323
+ }
13324
+ else if(id == me.pre + 'dl_ligplot') {
13325
+ let width = ic.ligplotWidth * ratio;
13326
+ $("#" + me.ligplotid).attr("width", width);
13327
+ }
13302
13328
  else if(id == me.pre + 'dl_contactmap') {
13303
13329
  let width = ic.contactmapWidth * ratio;
13304
13330
  $("#" + me.contactmapid).attr("width", width);
@@ -13352,7 +13378,7 @@ class Dialog {
13352
13378
  close: function(e) {
13353
13379
  let status = thisClass.getDialogStatus().status;
13354
13380
 
13355
- if((!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bTable2) &&(!status.bAlignmentInit2) ) {
13381
+ if((!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bTable2) &&(!status.bAlignmentInit2) ) {
13356
13382
  //ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH, me.htmlCls.HEIGHT - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT, true);
13357
13383
  ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH, me.htmlCls.HEIGHT, true);
13358
13384
  }
@@ -13381,7 +13407,7 @@ class Dialog {
13381
13407
 
13382
13408
  let status = this.getDialogStatus().status;
13383
13409
 
13384
- 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') {
13410
+ 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') {
13385
13411
  //var dialogWidth = 0.5 *(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH) - twoddgmWidth * 0.5;
13386
13412
  let dialogWidth = 0.5 *(me.htmlCls.WIDTH) - twoddgmWidth * 0.5;
13387
13413
 
@@ -13417,14 +13443,15 @@ class Dialog {
13417
13443
  modal: false,
13418
13444
  position: position,
13419
13445
  close: function(e) {
13420
- if((id === me.pre + 'dl_selectannotations' &&(!status.bAlignmentInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
13421
- ||(id === me.pre + 'dl_graph' &&(!status.bSelectannotationsInit2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
13422
- ||(id === me.pre + 'dl_alignment' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
13423
- ||(id === me.pre + 'dl_interactionsorted' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
13424
- ||(id === me.pre + 'dl_linegraph' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
13425
- ||(id === me.pre + 'dl_scatterplot' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
13426
- ||(id === me.pre + 'dl_contactmap' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bAlignerrormap2))
13427
- ||(id === me.pre + 'dl_alignerrormap' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2))
13446
+ if((id === me.pre + 'dl_selectannotations' &&(!status.bAlignmentInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
13447
+ ||(id === me.pre + 'dl_graph' &&(!status.bSelectannotationsInit2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
13448
+ ||(id === me.pre + 'dl_alignment' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
13449
+ ||(id === me.pre + 'dl_interactionsorted' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
13450
+ ||(id === me.pre + 'dl_linegraph' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
13451
+ ||(id === me.pre + 'dl_scatterplot' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bLigplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
13452
+ ||(id === me.pre + 'dl_ligplot' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
13453
+ ||(id === me.pre + 'dl_contactmap' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bAlignerrormap2))
13454
+ ||(id === me.pre + 'dl_alignerrormap' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bLigplot2) &&(!status.bContactmap2))
13428
13455
  ) {
13429
13456
  if(status.bTwoddgmInit2 || status.bTwodctnInit2 || status.bSetsInit2) {
13430
13457
  let canvasWidth = me.utilsCls.isMobile() ? me.htmlCls.WIDTH : me.htmlCls.WIDTH - twoddgmWidth;
@@ -13450,7 +13477,7 @@ class Dialog {
13450
13477
 
13451
13478
  d3.select("#" + me.svgid).attr("width", width).attr("height", height);
13452
13479
  }
13453
- else if(id == me.pre + 'dl_linegraph' || id == me.pre + 'dl_scatterplot' || id == me.pre + 'dl_contactmap' || id == me.pre + 'dl_alignerrormap') {
13480
+ 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') {
13454
13481
  let oriWidth =(status.bTwoddgmInit2 || status.bSetsInit2) ?(me.htmlCls.WIDTH - twoddgmWidth)/2 : me.htmlCls.WIDTH / 2;
13455
13482
  let ratio = $("#" + id).width() / oriWidth;
13456
13483
 
@@ -13462,6 +13489,10 @@ class Dialog {
13462
13489
  let width = ic.scatterplotWidth * ratio;
13463
13490
  $("#" + me.scatterplotid).attr("width", width);
13464
13491
  }
13492
+ else if(id == me.pre + 'dl_ligplot') {
13493
+ let width = ic.ligplotWidth * ratio;
13494
+ $("#" + me.ligplotid).attr("width", width);
13495
+ }
13465
13496
  else if(id == me.pre + 'dl_contactmap') {
13466
13497
  let width = ic.contactmapWidth * ratio;
13467
13498
  $("#" + me.contactmapid).attr("width", width);
@@ -13483,7 +13514,7 @@ class Dialog {
13483
13514
 
13484
13515
  //if(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH >= me.htmlCls.HEIGHT - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT) {
13485
13516
  if(me.htmlCls.WIDTH >= me.htmlCls.HEIGHT) {
13486
- if(status.bSelectannotationsInit2 || status.bGraph2 || status.bLineGraph2 || status.bScatterplot2 || status.bTable2 || status.bAlignmentInit2) {
13517
+ if(status.bSelectannotationsInit2 || status.bGraph2 || status.bLineGraph2 || status.bScatterplot2 || status.bLigplot2 || status.bTable2 || status.bAlignmentInit2) {
13487
13518
  //tmpWidth = 0.5 *(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH) - twoddgmWidth * 0.5;
13488
13519
  tmpWidth = 0.5 *(me.htmlCls.WIDTH) - twoddgmWidth * 0.5;
13489
13520
  }
@@ -13522,7 +13553,7 @@ class Dialog {
13522
13553
 
13523
13554
  //if(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH >= me.htmlCls.HEIGHT - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT) {
13524
13555
  if(me.htmlCls.WIDTH >= me.htmlCls.HEIGHT) {
13525
- if(status.bSelectannotationsInit2 || status.bGraph2 || status.bLineGraph2 || status.bScatterplot2 || status.bTable2 || status.bAlignmentInit2) {
13556
+ if(status.bSelectannotationsInit2 || status.bGraph2 || status.bLineGraph2 || status.bScatterplot2 || status.bLigplot2 || status.bTable2 || status.bAlignmentInit2) {
13526
13557
  //tmpWidth = 0.5 *(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH) - twoddgmWidth * 0.5;
13527
13558
  tmpWidth = 0.5 *(me.htmlCls.WIDTH) - twoddgmWidth * 0.5;
13528
13559
  }
@@ -13602,7 +13633,7 @@ class Dialog {
13602
13633
  let width = 400, height = 150;
13603
13634
  let twoddgmWidth = me.htmlCls.width2d + 20;
13604
13635
 
13605
- 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') {
13636
+ 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') {
13606
13637
  $( "#" + id ).show();
13607
13638
  $( "#" + id + "_nb").show();
13608
13639
  $( "#" + id + "_title").html(title);
@@ -13637,6 +13668,11 @@ class Dialog {
13637
13668
 
13638
13669
  $("#" + me.scatterplotid).attr("width", width);
13639
13670
  }
13671
+ else if(id == me.pre + 'dl_ligplot') {
13672
+ let width = ic.ligplotWidth * ratio;
13673
+
13674
+ $("#" + me.ligplotid).attr("width", width);
13675
+ }
13640
13676
  else if(id == me.pre + 'dl_contactmap') {
13641
13677
  let width = ic.contactmapWidth * ratio;
13642
13678
 
@@ -14182,14 +14218,14 @@ class SetDialog {
14182
14218
 
14183
14219
  html += "<span style='white-space:nowrap;font-weight:bold;'>2fofc contour at default threshold or at: "
14184
14220
  + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigma2fofc' value='' size=8> &sigma;</span><br/>";
14185
- //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/>";
14186
- 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/>";
14221
+ //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/>";
14222
+ 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/>";
14187
14223
 
14188
14224
  html += "<span style='white-space:nowrap;font-weight:bold;'>fofc contour at default threshold or at: "
14189
14225
  + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigmafofc' value='' size=8> &sigma;</span><br/>";
14190
14226
 
14191
- //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>";
14192
- 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>";
14227
+ //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>";
14228
+ 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>";
14193
14229
 
14194
14230
 
14195
14231
  html += me.htmlCls.buttonStr + "elecmapNo4'>Remove Map</button><br>";
@@ -14203,12 +14239,16 @@ class SetDialog {
14203
14239
  html += "<span style='white-space:nowrap;font-weight:bold;'>2fofc contour at default threshold or at: "
14204
14240
  + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigmaurl2fofc' value='' size=8> &sigma;</span><br/>";
14205
14241
 
14206
- 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/>";
14242
+ //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/>";
14243
+
14244
+ 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/>";
14207
14245
 
14208
14246
  html += "<span style='white-space:nowrap;font-weight:bold;'>fofc contour at default threshold or at: "
14209
14247
  + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigmaurlfofc' value='' size=8> &sigma;</span><br/>";
14210
14248
 
14211
- 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>";
14249
+ //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>";
14250
+
14251
+ 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>";
14212
14252
 
14213
14253
  html += me.htmlCls.buttonStr + "elecmapNo5'>Remove Map</button><br>";
14214
14254
 
@@ -14331,6 +14371,8 @@ class SetDialog {
14331
14371
 
14332
14372
  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>";
14333
14373
 
14374
+ html += "<div style='text-indent:1.1em'>" + me.htmlCls.buttonStr + "hbondLigplot'>2D Interaction for One Ligand/Residue</button> with atom details</div><br>";
14375
+
14334
14376
  tmpStr = ': </td><td><input style="margin-left:-12px" type="text" id="';
14335
14377
 
14336
14378
  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>";
@@ -14497,6 +14539,40 @@ class SetDialog {
14497
14539
 
14498
14540
  html += "</div>";
14499
14541
 
14542
+
14543
+ html += me.htmlCls.divStr + "dl_ligplot' sty2D Interaction for One Ligand/Residule='background-color:white' class='" + dialogClass + "'>";
14544
+ html += this.addNotebookTitle('dl_ligplot', 'e with Atom Details');
14545
+
14546
+ html += me.htmlCls.divNowrapStr + "<b>Note</b>: Nodes can be dragged or clicked. Hold Ctrl key to select multiple nodes. " + me.htmlCls.space3;
14547
+
14548
+ html += '<div style="width:20px; margin-top:6px; display:inline-block;"><span id="'
14549
+ + 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="'
14550
+ + me.pre + 'dl_ligplotcolor_shrink" class="ui-icon ui-icon-minus icn3d-shrink icn3d-link" style="width:15px;" title="Shrink"></span></div></div>';
14551
+
14552
+ html += me.htmlCls.divStr + "dl_ligplotcolor' style='inline-block;'>";
14553
+
14554
+ // 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>";
14555
+ html += "<b>Color Legend</b>: <br>";
14556
+
14557
+ html += me.htmlCls.setHtmlCls.setColorHints();
14558
+
14559
+ html += "<br></div>";
14560
+
14561
+ me.ligplotid = me.pre + 'ligplot';
14562
+ html += me.htmlCls.divNowrapStr + buttonStrTmp + me.ligplotid + '_svg">SVG</button>' + me.htmlCls.space2;
14563
+ html += buttonStrTmp + me.ligplotid + '_png">PNG</button>' + me.htmlCls.space2;
14564
+ // html += buttonStrTmp + me.ligplotid + '_json">JSON</button>' + me.htmlCls.space4;
14565
+ html += "<b>Scale</b>: <select id='" + me.ligplotid + "_scale'>";
14566
+
14567
+ html += me.htmlCls.setHtmlCls.getOptionHtml(optArray4, 5);
14568
+
14569
+ html += "</select></div><br>";
14570
+ html += '<div id="' + me.pre + 'ligplotDiv"></div>';
14571
+
14572
+ html += "</div>";
14573
+
14574
+
14575
+
14500
14576
  html += me.htmlCls.divStr + "dl_contactmap' style='background-color:white' class='" + dialogClass + "'>";
14501
14577
  html += this.addNotebookTitle('dl_contactmap', 'Contact Map');
14502
14578
 
@@ -14757,8 +14833,9 @@ class SetDialog {
14757
14833
  html += "</div>";
14758
14834
 
14759
14835
 
14760
- html += me.htmlCls.divStr + "dl_anglemanysets' class='" + dialogClass + "'>";
14836
+ html += me.htmlCls.divStr + "dl_anglemanysets' class='" + dialogClass + "' style='max-width:500px'>";
14761
14837
  html += this.addNotebookTitle('dl_anglemanysets', 'Measure angles among many sets');
14838
+ 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/>";
14762
14839
  html += me.htmlCls.spanNowrapStr + "1. Select sets for pairwise angles</span><br/>";
14763
14840
  html += "<table border=0 width=400 cellspacing=10><tr><td>";
14764
14841
 
@@ -15080,8 +15157,8 @@ class SetDialog {
15080
15157
  html += "Z: " + me.htmlCls.inputTextStr + "id='" + me.pre + "v2Z' value='' size=6><br>";
15081
15158
  html += "<br>";
15082
15159
 
15083
- html += me.htmlCls.buttonStr + "measure_angle'>Measure Angle</button>";
15084
- html += "The angle is: " + me.htmlCls.inputTextStr + "id='" + me.pre + "angle_value' value='' size=6> degree.";
15160
+ html += me.htmlCls.buttonStr + "measure_angle'>Measure Angle</button><br><br>";
15161
+ html += "The angle is: " + me.htmlCls.inputTextStr + "id='" + me.pre + "angle_value' value='' size=6> degree.<br><br>";
15085
15162
  html += "</div>";
15086
15163
 
15087
15164
  html += me.htmlCls.divStr + "dl_matrix' class='" + dialogClass + "'>";
@@ -15550,6 +15627,7 @@ class Events {
15550
15627
 
15551
15628
  ic.diagram2dCls.click2Ddgm();
15552
15629
  ic.cartoon2dCls.click2Dcartoon();
15630
+ ic.ligplotCls.clickLigplot();
15553
15631
  ic.addTrackCls.clickAddTrackButton();
15554
15632
  ic.resizeCanvasCls.windowResize();
15555
15633
  ic.annotationCls.setTabs();
@@ -17171,6 +17249,13 @@ class Events {
17171
17249
  thisClass.setLogCmd("show ref number", true);
17172
17250
  await ic.showInterCls.showInteractions('scatterplot');
17173
17251
  });
17252
+ me.myEventCls.onIds("#" + me.pre + "hbondLigplot", "click", async function(e) { let ic = me.icn3d;
17253
+ e.preventDefault();
17254
+
17255
+ ic.bShownRefnum = false;
17256
+ thisClass.setLogCmd("hide ref number", true);
17257
+ await ic.showInterCls.showInteractions('ligplot');
17258
+ });
17174
17259
  // select residues
17175
17260
  $(document).on("click", "#" + me.svgid + " circle.selected", function(e) { let ic = me.icn3d;
17176
17261
  e.stopImmediatePropagation();
@@ -17281,6 +17366,33 @@ class Events {
17281
17366
  thisClass.setLogCmd("scatterplot scale " + scale, true);
17282
17367
  });
17283
17368
 
17369
+ me.myEventCls.onIds("#" + me.ligplotid + "_svg", "click", function(e) { let ic = me.icn3d;
17370
+ e.preventDefault();
17371
+
17372
+ ic.saveFileCls.saveSvg(me.ligplotid, ic.inputid + "_ligplot.svg", undefined, true);
17373
+ });
17374
+ me.myEventCls.onIds("#" + me.ligplotid + "_png", "click", function(e) { let ic = me.icn3d;
17375
+ e.preventDefault();
17376
+
17377
+ ic.saveFileCls.savePng(me.ligplotid, ic.inputid + "_ligplot.png", undefined, true);
17378
+ });
17379
+ // me.myEventCls.onIds("#" + me.ligplotid + "_json", "click", function(e) { let ic = me.icn3d;
17380
+ // e.preventDefault();
17381
+
17382
+ // let graphStr2 = ic.ligplotStr.substr(0, ic.ligplotStr.lastIndexOf('}'));
17383
+
17384
+ // graphStr2 += me.htmlCls.setHtmlCls.getLinkColor();
17385
+
17386
+ // ic.saveFileCls.saveFile(ic.inputid + "_ligplot.json", "text", [graphStr2]);
17387
+ // });
17388
+ me.myEventCls.onIds("#" + me.ligplotid + "_scale", "change", function(e) { let ic = me.icn3d;
17389
+ e.preventDefault();
17390
+
17391
+ let scale = $("#" + me.ligplotid + "_scale").val();
17392
+ $("#" + me.ligplotid).attr("width",(ic.ligplotWidth * parseFloat(scale)).toString() + "px");
17393
+ thisClass.setLogCmd("ligplot scale " + scale, true);
17394
+ });
17395
+
17284
17396
  me.myEventCls.onIds("#" + me.contactmapid + "_svg", "click", function(e) { let ic = me.icn3d;
17285
17397
  e.preventDefault();
17286
17398
 
@@ -36738,7 +36850,8 @@ class Contact {
36738
36850
  if(oriCalpha === undefined) oriCalpha = oriAtom;
36739
36851
 
36740
36852
  if(bGetPairs) {
36741
- oriResidName = oriAtom.resn + ' $' + oriAtom.structure + '.' + oriAtom.chain + ':' + oriAtom.resi;
36853
+ let serialList = (oriAtom.name.indexOf('pi') == 0 && oriAtom.ring) ? oriAtom.ring.join(',') : oriAtom.serial;
36854
+ oriResidName = oriAtom.resn + ' $' + oriAtom.structure + '.' + oriAtom.chain + ':' + oriAtom.resi + ' ' + serialList;
36742
36855
  if(ic.resid2Residhash[oriResidName] === undefined) ic.resid2Residhash[oriResidName] = {};
36743
36856
  }
36744
36857
 
@@ -36783,13 +36896,14 @@ class Contact {
36783
36896
  if(bGetPairs) {
36784
36897
  let chain_resi2 = atom.structure + '_' + atom.chain + '_' + atom.resi;
36785
36898
 
36786
- residName = atom.resn + ' $' + atom.structure + '.' + atom.chain + ':' + atom.resi;
36899
+ let serialList = (atom.name.indexOf('pi') == 0 && atom.ring) ? atom.ring.join(',') : atom.serial;
36900
+ residName = atom.resn + ' $' + atom.structure + '.' + atom.chain + ':' + atom.resi + ' ' + serialList;
36787
36901
  //var dist = Math.sqrt(atomDistSq).toFixed(1);
36788
36902
  let dist1 = atomDist.toFixed(1);
36789
36903
  let dist2 = calpha.coord.distanceTo(oriCalpha.coord).toFixed(1);
36790
36904
 
36791
36905
  let resids = chain_resi + '_' + oriAtom.resn + ',' + chain_resi2 + '_' + atom.resn;
36792
- let residNames = oriResidName + ',' + residName;
36906
+ let residNames = oriResidName + '|' + residName;
36793
36907
  if(ic.resids2interAll[resids] === undefined
36794
36908
  || ic.resids2interAll[resids]['contact'] === undefined
36795
36909
  || !ic.resids2interAll[resids]['contact'].hasOwnProperty(residNames)
@@ -36806,12 +36920,12 @@ class Contact {
36806
36920
  if(!bInternal) {
36807
36921
  if(ic.resids2inter[resids] === undefined) ic.resids2inter[resids] = {};
36808
36922
  if(ic.resids2inter[resids]['contact'] === undefined) ic.resids2inter[resids]['contact'] = {};
36809
- ic.resids2inter[resids]['contact'][oriResidName + ',' + residName] = dist1 + '_' + dist2 + '_' + oriAtom.name + '_' + atom.name + '_' + cnt;
36923
+ ic.resids2inter[resids]['contact'][oriResidName + '|' + residName] = dist1 + '_' + dist2 + '_' + oriAtom.name + '_' + atom.name + '_' + cnt;
36810
36924
  }
36811
36925
 
36812
36926
  if(ic.resids2interAll[resids] === undefined) ic.resids2interAll[resids] = {};
36813
36927
  if(ic.resids2interAll[resids]['contact'] === undefined) ic.resids2interAll[resids]['contact'] = {};
36814
- ic.resids2interAll[resids]['contact'][oriResidName + ',' + residName] = dist1 + '_' + dist2 + '_' + oriAtom.name + '_' + atom.name + '_' + cnt;
36928
+ ic.resids2interAll[resids]['contact'][oriResidName + '|' + residName] = dist1 + '_' + dist2 + '_' + oriAtom.name + '_' + atom.name + '_' + cnt;
36815
36929
  }
36816
36930
  }
36817
36931
  } // if(bGetPairs) {
@@ -37237,7 +37351,8 @@ class HBond {
37237
37351
  chain_resi_atom = chain_resi + "_" + atom.name;
37238
37352
 
37239
37353
  //var oriResidName = atom.resn + ' ' + chain_resi_atom;
37240
- let oriResidName = atom.resn + ' $' + atom.structure + '.' + atom.chain + ':' + atom.resi + '@' + atom.name;
37354
+ let serialList = (atom.name.indexOf('pi') == 0 && atom.ring) ? atom.ring.join(',') : atom.serial;
37355
+ let oriResidName = atom.resn + ' $' + atom.structure + '.' + atom.chain + ':' + atom.resi + '@' + atom.name + ' ' + serialList;
37241
37356
  if(ic.resid2Residhash[oriResidName] === undefined) ic.resid2Residhash[oriResidName] = {};
37242
37357
 
37243
37358
  for (let j in atomHbond) {
@@ -37362,24 +37477,25 @@ class HBond {
37362
37477
  residueHash[chain_resi2] = 1;
37363
37478
 
37364
37479
  //var residName = atomHbond[j].resn + " " + atomHbond[j].structure + "_" + atomHbond[j].chain + "_" + atomHbond[j].resi + '_' + atomHbond[j].name;
37365
- let residName = atomHbond[j].resn + ' $' + atomHbond[j].structure + '.' + atomHbond[j].chain + ':' + atomHbond[j].resi + '@' + atomHbond[j].name;
37480
+ let serialList = (atomHbond[j].name.indexOf('pi') == 0 && atomHbond[j].ring) ? atomHbond[j].ring.join(',') : atomHbond[j].serial;
37481
+ let residName = atomHbond[j].resn + ' $' + atomHbond[j].structure + '.' + atomHbond[j].chain + ':' + atomHbond[j].resi + '@' + atomHbond[j].name + ' ' + serialList;
37366
37482
 
37367
37483
  let resids = chain_resi + '_' + atom.resn + ',' + chain_resi2 + '_' + atomHbond[j].resn;
37368
37484
 
37369
37485
  if(ic.resids2interAll[resids] === undefined
37370
37486
  || ic.resids2interAll[resids]['ionic'] === undefined
37371
- || !ic.resids2interAll[resids]['ionic'].hasOwnProperty(oriResidName + ',' + residName) ) {
37487
+ || !ic.resids2interAll[resids]['ionic'].hasOwnProperty(oriResidName + '|' + residName) ) {
37372
37488
  ic.resid2Residhash[oriResidName][residName] = dist.toFixed(1);
37373
37489
 
37374
37490
  if(!bInternal) {
37375
37491
  if(ic.resids2inter[resids] === undefined) ic.resids2inter[resids] = {};
37376
37492
  if(ic.resids2inter[resids]['hbond'] === undefined) ic.resids2inter[resids]['hbond'] = {};
37377
- ic.resids2inter[resids]['hbond'][oriResidName + ',' + residName] = dist.toFixed(1);
37493
+ ic.resids2inter[resids]['hbond'][oriResidName + '|' + residName] = dist.toFixed(1);
37378
37494
  }
37379
37495
 
37380
37496
  if(ic.resids2interAll[resids] === undefined) ic.resids2interAll[resids] = {};
37381
37497
  if(ic.resids2interAll[resids]['hbond'] === undefined) ic.resids2interAll[resids]['hbond'] = {};
37382
- ic.resids2interAll[resids]['hbond'][oriResidName + ',' + residName] = dist.toFixed(1);
37498
+ ic.resids2interAll[resids]['hbond'][oriResidName + '|' + residName] = dist.toFixed(1);
37383
37499
  }
37384
37500
  } // end of for (let j in atomHbond) {
37385
37501
  }
@@ -37532,7 +37648,8 @@ class PiHalogen {
37532
37648
 
37533
37649
  for (let i in atoms1a) {
37534
37650
  let atom1 = atoms1a[i];
37535
- let oriResidName = atom1.resn + ' $' + atom1.structure + '.' + atom1.chain + ':' + atom1.resi + '@' + atom1.name;
37651
+ let serialList = (atom1.name.indexOf('pi') == 0 && atom1.ring) ? atom1.ring.join(',') : atom1.serial;
37652
+ let oriResidName = atom1.resn + ' $' + atom1.structure + '.' + atom1.chain + ':' + atom1.resi + '@' + atom1.name + ' ' + serialList;
37536
37653
  if(ic.resid2Residhash[oriResidName] === undefined) ic.resid2Residhash[oriResidName] = {};
37537
37654
 
37538
37655
  for (let j in atoms1b) {
@@ -37576,7 +37693,8 @@ class PiHalogen {
37576
37693
 
37577
37694
  for (let i in atoms2a) {
37578
37695
  let atom1 = atoms2a[i];
37579
- let oriResidName = atom1.resn + ' $' + atom1.structure + '.' + atom1.chain + ':' + atom1.resi + '@' + atom1.name;
37696
+ let serialList = (atom1.name.indexOf('pi') == 0 && atom1.ring) ? atom1.ring.join(',') : atom1.serial;
37697
+ let oriResidName = atom1.resn + ' $' + atom1.structure + '.' + atom1.chain + ':' + atom1.resi + '@' + atom1.name + ' ' + serialList;
37580
37698
  if(ic.resid2Residhash[oriResidName] === undefined) ic.resid2Residhash[oriResidName] = {};
37581
37699
 
37582
37700
  // available in 1b and 2a
@@ -37741,7 +37859,8 @@ class PiHalogen {
37741
37859
  }
37742
37860
  }
37743
37861
 
37744
- let residName = atom2.resn + ' $' + atom2.structure + '.' + atom2.chain + ':' + atom2.resi + '@' + atom2.name;
37862
+ let serialList = (atom2.name.indexOf('pi') == 0 && atom2.ring) ? atom2.ring.join(',') : atom2.serial;
37863
+ let residName = atom2.resn + ' $' + atom2.structure + '.' + atom2.chain + ':' + atom2.resi + '@' + atom2.name + ' ' + serialList;
37745
37864
 
37746
37865
  //if(ic.resid2Residhash[oriResidName][residName] === undefined || ic.resid2Residhash[oriResidName][residName] > dist) {
37747
37866
  ic.resid2Residhash[oriResidName][residName] = dist.toFixed(1);
@@ -37753,12 +37872,12 @@ class PiHalogen {
37753
37872
  if(!bInternal) {
37754
37873
  if(ic.resids2inter[resids] === undefined) ic.resids2inter[resids] = {};
37755
37874
  if(ic.resids2inter[resids][interactionType] === undefined) ic.resids2inter[resids][interactionType] = {};
37756
- ic.resids2inter[resids][interactionType][oriResidName + ',' + residName] = dist.toFixed(1);
37875
+ ic.resids2inter[resids][interactionType][oriResidName + '|' + residName] = dist.toFixed(1);
37757
37876
  }
37758
37877
 
37759
37878
  if(ic.resids2interAll[resids] === undefined) ic.resids2interAll[resids] = {};
37760
37879
  if(ic.resids2interAll[resids][interactionType] === undefined) ic.resids2interAll[resids][interactionType] = {};
37761
- ic.resids2interAll[resids][interactionType][oriResidName + ',' + residName] = dist.toFixed(1);
37880
+ ic.resids2interAll[resids][interactionType][oriResidName + '|' + residName] = dist.toFixed(1);
37762
37881
 
37763
37882
  return true;
37764
37883
  }
@@ -38005,12 +38124,13 @@ class PiHalogen {
38005
38124
  // Print the i-th cycle
38006
38125
  let coord = new THREE.Vector3();
38007
38126
  let cnt = 0, serial;
38008
- let coordArray = [];
38127
+ let coordArray = [], ringArray = [];
38009
38128
  if(cycles.hasOwnProperty(i)) {
38010
38129
  for (let j = 0, jl = cycles[i].length; j < jl; ++j) {
38011
38130
  serial = cycles[i][j];
38012
38131
  coord.add(ic.atoms[serial].coord);
38013
38132
  coordArray.push(ic.atoms[serial].coord);
38133
+ ringArray.push(serial);
38014
38134
  ++cnt;
38015
38135
  }
38016
38136
  }
@@ -38030,7 +38150,7 @@ class PiHalogen {
38030
38150
 
38031
38151
  let atom = ic.atoms[serial];
38032
38152
  name2atom[resid + '_pi' + serial] = {resn: atom.resn, name: 'pi' + serial, coord: coord, serial: atom.serial,
38033
- structure: atom.structure, chain: atom.chain, resi: atom.resi, normal: normal};
38153
+ structure: atom.structure, chain: atom.chain, resi: atom.resi, normal: normal, ring: ringArray};
38034
38154
  }
38035
38155
  }
38036
38156
  }
@@ -38128,7 +38248,8 @@ class Saltbridge {
38128
38248
  chain_resi = atom.structure + "_" + atom.chain + "_" + atom.resi;
38129
38249
  chain_resi_atom = chain_resi + "_" + atom.name;
38130
38250
 
38131
- let oriResidName = atom.resn + ' $' + atom.structure + '.' + atom.chain + ':' + atom.resi + '@' + atom.name;
38251
+ let serialList = (atom.name.indexOf('pi') == 0 && atom.ring) ? atom.ring.join(',') : atom.serial;
38252
+ let oriResidName = atom.resn + ' $' + atom.structure + '.' + atom.chain + ':' + atom.resi + '@' + atom.name + ' ' + serialList;
38132
38253
  if(ic.resid2Residhash[oriResidName] === undefined) ic.resid2Residhash[oriResidName] = {};
38133
38254
 
38134
38255
  let atomHbond = {};
@@ -38193,7 +38314,8 @@ class Saltbridge {
38193
38314
  residueHash[chain_resi] = 1;
38194
38315
  residueHash[chain_resi2] = 1;
38195
38316
 
38196
- let residName = atomHbond[j].resn + ' $' + atomHbond[j].structure + '.' + atomHbond[j].chain + ':' + atomHbond[j].resi + '@' + atomHbond[j].name;
38317
+ let serialList = (atomHbond[j].name.indexOf('pi') == 0 && atomHbond[j].ring) ? atomHbond[j].ring.join(',') : atomHbond[j].serial;
38318
+ let residName = atomHbond[j].resn + ' $' + atomHbond[j].structure + '.' + atomHbond[j].chain + ':' + atomHbond[j].resi + '@' + atomHbond[j].name + ' ' + serialList;
38197
38319
 
38198
38320
  //if(ic.resid2Residhash[oriResidName][residName] === undefined || ic.resid2Residhash[oriResidName][residName] > dist) {
38199
38321
  ic.resid2Residhash[oriResidName][residName] = dist.toFixed(1);
@@ -38204,12 +38326,12 @@ class Saltbridge {
38204
38326
  if(!bInternal) {
38205
38327
  if(ic.resids2inter[resids] === undefined) ic.resids2inter[resids] = {};
38206
38328
  if(ic.resids2inter[resids]['ionic'] === undefined) ic.resids2inter[resids]['ionic'] = {};
38207
- ic.resids2inter[resids]['ionic'][oriResidName + ',' + residName] = dist.toFixed(1);
38329
+ ic.resids2inter[resids]['ionic'][oriResidName + '|' + residName] = dist.toFixed(1);
38208
38330
  }
38209
38331
 
38210
38332
  if(ic.resids2interAll[resids] === undefined) ic.resids2interAll[resids] = {};
38211
38333
  if(ic.resids2interAll[resids]['ionic'] === undefined) ic.resids2interAll[resids]['ionic'] = {};
38212
- ic.resids2interAll[resids]['ionic'][oriResidName + ',' + residName] = dist.toFixed(1);
38334
+ ic.resids2interAll[resids]['ionic'][oriResidName + '|' + residName] = dist.toFixed(1);
38213
38335
 
38214
38336
  } // end of for (let j in atomHbond) {
38215
38337
  }
@@ -44526,7 +44648,7 @@ class AddTrack {
44526
44648
 
44527
44649
  }
44528
44650
 
44529
- showNewTrack(chnid, title, text, cssColorArray, inTarget2queryHash, type, color, bMsa, fromArray, toArray, seqStartLen, exonArray) { let ic = this.icn3d, me = ic.icn3dui;
44651
+ showNewTrack(chnid, title, text, cssColorArray, inTarget2queryHash, type, color, bMsa, fromArray, toArray, seqStartLen, exonArray, offsetArray) { let ic = this.icn3d, me = ic.icn3dui;
44530
44652
  //if(ic.customTracks[chnid] === undefined) {
44531
44653
  // ic.customTracks[chnid] = {}
44532
44654
  //}
@@ -44744,14 +44866,16 @@ class AddTrack {
44744
44866
 
44745
44867
  if(fromArray !== undefined) {
44746
44868
  htmlTmp2 = '';
44747
- let fromArray2 = [], toArray2 = [];
44869
+ let fromArray2 = [], toArray2 = [], offsetArray2 = [];
44748
44870
  for(let i = 0, il = fromArray.length; i < il; ++i) {
44749
44871
  fromArray2.push(fromArray[i]);
44872
+ offsetArray2.push(offsetArray[i]);
44750
44873
 
44751
44874
  for(let j = parseInt(fromArray[i]); j <= parseInt(toArray[i]); ++j) {
44752
44875
  if(ic.targetGapHash !== undefined && ic.targetGapHash.hasOwnProperty(j)) {
44753
44876
  toArray2.push(j - 1);
44754
44877
  fromArray2.push(j);
44878
+ offsetArray2.push(offsetArray[i]);
44755
44879
  }
44756
44880
  }
44757
44881
 
@@ -44785,6 +44909,7 @@ class AddTrack {
44785
44909
  // determine how this range sits in the exon ranges in exonArray
44786
44910
  let startExon, endExon;
44787
44911
 
44912
+ let offset = offsetArray2[i];
44788
44913
  cnt = toArray[i] - fromArray[i] + 1;
44789
44914
  let from = prevCntTotal, to = prevCntTotal + cnt - 1;
44790
44915
 
@@ -44813,26 +44938,26 @@ class AddTrack {
44813
44938
  endColorStr = this.getExonColor(startExon.rangeStart, startExon.rangeEnd, to);
44814
44939
 
44815
44940
  colorGradient = startColorStr + ' 0%, #FFF 50%, ' + endColorStr + ' 100%';
44816
- htmlTmp2 += this.getExonHtml(startExon.exonIndex, colorGradient, startExon.from, endExon.to, startExon.genomeRange, chnid, simpTitle);
44941
+ htmlTmp2 += this.getExonHtml(startExon.exonIndex, colorGradient, startExon.from, endExon.to, startExon.genomeRange, chnid, simpTitle, offset);
44817
44942
  }
44818
44943
  else {
44819
44944
  if(startExon) {
44820
44945
  startColorStr = this.getExonColor(startExon.rangeStart, startExon.rangeEnd, from);
44821
44946
 
44822
44947
  colorGradient = startColorStr + ' 0%, #FFF 50%, #00F 100%';
44823
- htmlTmp2 += this.getExonHtml(startExon.exonIndex, colorGradient, startExon.from, startExon.rangeEnd, startExon.genomeRange, chnid, simpTitle);
44948
+ htmlTmp2 += this.getExonHtml(startExon.exonIndex, colorGradient, startExon.from, startExon.rangeEnd, startExon.genomeRange, chnid, simpTitle, offset);
44824
44949
  }
44825
44950
 
44826
44951
  if(startExon && endExon) {
44827
44952
  for(let j = startExon.exonIndex + 1; j < endExon.exonIndex; ++j) {
44828
44953
  colorGradient = '#F00 0%, #FFF 50%, #00F 100%';
44829
- htmlTmp2 += this.getExonHtml(j, colorGradient, exonArray[j].resStart, exonArray[j].resEnd, exonArray[j].genomeRange, chnid, simpTitle);
44954
+ htmlTmp2 += this.getExonHtml(j, colorGradient, exonArray[j].resStart, exonArray[j].resEnd, exonArray[j].genomeRange, chnid, simpTitle, offset);
44830
44955
  }
44831
44956
 
44832
44957
  endColorStr = this.getExonColor(endExon.rangeStart, endExon.rangeEnd, to);
44833
44958
 
44834
44959
  colorGradient = '#F00 0%, #FFF 50%, ' + endColorStr + ' 100%';
44835
- htmlTmp2 += this.getExonHtml(endExon.exonIndex, colorGradient, endExon.rangeStart, endExon.to, endExon.genomeRange, chnid, simpTitle);
44960
+ htmlTmp2 += this.getExonHtml(endExon.exonIndex, colorGradient, endExon.rangeStart, endExon.to, endExon.genomeRange, chnid, simpTitle, offset);
44836
44961
  }
44837
44962
  }
44838
44963
 
@@ -44866,8 +44991,8 @@ class AddTrack {
44866
44991
  }
44867
44992
  }
44868
44993
 
44869
- getExonHtml(exonIndex, colorGradient, from, to, genomeRange, chainid, simpTitle) { let ic = this.icn3d; ic.icn3dui;
44870
- 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>';
44994
+ getExonHtml(exonIndex, colorGradient, from, to, genomeRange, chainid, simpTitle, offset) { let ic = this.icn3d; ic.icn3dui;
44995
+ 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>';
44871
44996
  }
44872
44997
 
44873
44998
  getExonColor(start, end, pos) { let ic = this.icn3d; ic.icn3dui;
@@ -45814,6 +45939,7 @@ class AddTrack {
45814
45939
  let fromArray = [], toArray = [];
45815
45940
  let bFound = false;
45816
45941
  let seqStartLen = 0;
45942
+ let offset = 0, offsetArray = [];
45817
45943
  // for(let k = seqStart; k <= seqEnd; ++k) {
45818
45944
  for(let k = 0; k < seqLength; ++k) {
45819
45945
  //if(seqFirst[k] == '-') continue;
@@ -45822,19 +45948,29 @@ class AddTrack {
45822
45948
 
45823
45949
  resn = trackSeqArray[j][k];
45824
45950
 
45951
+ if(resn != '-') {
45952
+ if(!bFound) {
45953
+ seqStartLen = k;
45954
+ bFound = true;
45955
+
45956
+ offset = ic.startposGiSeq - ic.seqStartLen[chainid] + seqStartLen;
45957
+ }
45958
+ }
45959
+
45825
45960
  if(prevResn == '-' && resn != '-') {
45826
45961
  fromArray.push(k);
45962
+ offsetArray.push(offset);
45827
45963
  }
45828
45964
 
45829
45965
  if(prevResn != '-' && resn == '-') {
45830
45966
  toArray.push(k - 1);
45831
45967
  }
45832
45968
 
45833
- if(resn != '-') {
45834
- if(!bFound) {
45835
- seqStartLen = k;
45836
- bFound = true;
45837
- }
45969
+ // use "offset" to adjut the residue numbers, e.g., P20138
45970
+ // some isoforms starts residues before the first residue in the template sequence
45971
+ if(k >= ic.seqStartLen[chainid]) {
45972
+ if(seqFirst[k] == '-') offset--;
45973
+ if(resn == '-') offset++;
45838
45974
  }
45839
45975
 
45840
45976
  text += resn; //ic.giSeq[chainid][i];
@@ -45855,7 +45991,7 @@ class AddTrack {
45855
45991
  let title =(trackTitleArray[j].length < 20) ? trackTitleArray[j] : trackTitleArray[j].substr(0, 20) + '...';
45856
45992
  let bMsa = true;
45857
45993
  let exonArray = (acc2exons) ? acc2exons[trackTitleArray[j]] : undefined;
45858
- this.showNewTrack(chainid, title, text, undefined, undefined, type, undefined, bMsa, fromArray, toArray, seqStartLen, exonArray);
45994
+ this.showNewTrack(chainid, title, text, undefined, undefined, type, undefined, bMsa, fromArray, toArray, seqStartLen, exonArray, offsetArray);
45859
45995
  }
45860
45996
 
45861
45997
  // update exon color
@@ -49580,20 +49716,9 @@ class LineGraph {
49580
49716
  } else {
49581
49717
  linestrokewidth = (link.n == 1) ? 2 : 4;
49582
49718
  }
49583
- let strokecolor;
49584
- if(link.v == me.htmlCls.hbondValue) {
49585
- strokecolor = "#" + me.htmlCls.hbondColor;
49586
- } else if(link.v == me.htmlCls.ionicValue) {
49587
- strokecolor = "#" + me.htmlCls.ionicColor;
49588
- } else if(link.v == me.htmlCls.halogenValue) {
49589
- strokecolor = "#" + me.htmlCls.halogenColor;
49590
- } else if(link.v == me.htmlCls.picationValue) {
49591
- strokecolor = "#" + me.htmlCls.picationColor;
49592
- } else if(link.v == me.htmlCls.pistackingValue) {
49593
- strokecolor = "#" + me.htmlCls.pistackingColor;
49594
- } else if(link.v == me.htmlCls.contactValue) {
49595
- strokecolor = "#" + me.htmlCls.contactColor;
49596
- }
49719
+
49720
+ let strokecolor = this.getStrokecolor(link.v);
49721
+
49597
49722
  html += "<g class='icn3d-interaction' resid1='" + resid1 + "' resid2='" + resid2 + "' >";
49598
49723
  let interactStr = (link.n == 1) ? 'Interaction' : link.n + ' interactions';
49599
49724
  if(link.n > 1) html += "<title>" + interactStr + " of residue " + node1.id + " with residue " + node2.id + "</title>";
@@ -49656,6 +49781,44 @@ class LineGraph {
49656
49781
  return html;
49657
49782
  }
49658
49783
 
49784
+ getStrokecolor(value, type) { let ic = this.icn3d, me = ic.icn3dui;
49785
+ let strokecolor = "#000";
49786
+
49787
+ if(value) {
49788
+ if(value == me.htmlCls.hbondValue) {
49789
+ strokecolor = "#" + me.htmlCls.hbondColor;
49790
+ } else if(value == me.htmlCls.ionicValue) {
49791
+ strokecolor = "#" + me.htmlCls.ionicColor;
49792
+ } else if(value == me.htmlCls.halogenValue) {
49793
+ strokecolor = "#" + me.htmlCls.halogenColor;
49794
+ } else if(value == me.htmlCls.picationValue) {
49795
+ strokecolor = "#" + me.htmlCls.picationColor;
49796
+ } else if(value == me.htmlCls.pistackingValue) {
49797
+ strokecolor = "#" + me.htmlCls.pistackingColor;
49798
+ } else if(value == me.htmlCls.contactValue) {
49799
+ strokecolor = "#" + me.htmlCls.contactColor;
49800
+ }
49801
+ }
49802
+
49803
+ if(type) {
49804
+ if(type == 'hbond') {
49805
+ strokecolor = "#" + me.htmlCls.hbondColor;
49806
+ } else if(type == 'ionic') {
49807
+ strokecolor = "#" + me.htmlCls.ionicColor;
49808
+ } else if(type == 'halogen') {
49809
+ strokecolor = "#" + me.htmlCls.halogenColor;
49810
+ } else if(type == 'pi-cation') {
49811
+ strokecolor = "#" + me.htmlCls.picationColor;
49812
+ } else if(type == 'pi-stacking') {
49813
+ strokecolor = "#" + me.htmlCls.pistackingColor;
49814
+ } else if(type == 'contact') {
49815
+ strokecolor = "#" + me.htmlCls.contactColor;
49816
+ }
49817
+ }
49818
+
49819
+ return strokecolor;
49820
+ }
49821
+
49659
49822
  drawOnePairNode(link, node1, node2, node2posSet1, node2posSet2, bContactMap, bAfMap) { let ic = this.icn3d, me = ic.icn3dui;
49660
49823
  let html = '';
49661
49824
 
@@ -49671,20 +49834,7 @@ class LineGraph {
49671
49834
  let pos2 = node2posSet2[node2.id];
49672
49835
  if(pos1 === undefined || pos2 === undefined) return html;
49673
49836
 
49674
- let strokecolor;
49675
- if(link.v == me.htmlCls.hbondValue) {
49676
- strokecolor = "#" + me.htmlCls.hbondColor;
49677
- } else if(link.v == me.htmlCls.ionicValue) {
49678
- strokecolor = "#" + me.htmlCls.ionicColor;
49679
- } else if(link.v == me.htmlCls.halogenValue) {
49680
- strokecolor = "#" + me.htmlCls.halogenColor;
49681
- } else if(link.v == me.htmlCls.picationValue) {
49682
- strokecolor = "#" + me.htmlCls.picationColor;
49683
- } else if(link.v == me.htmlCls.pistackingValue) {
49684
- strokecolor = "#" + me.htmlCls.pistackingColor;
49685
- } else if(link.v == me.htmlCls.contactValue) {
49686
- strokecolor = "#" + me.htmlCls.contactColor;
49687
- }
49837
+ let strokecolor = this.getStrokecolor(link.v);
49688
49838
 
49689
49839
  if(bContactMap) strokecolor = "#" + link.c;
49690
49840
 
@@ -50264,6 +50414,10 @@ class GetGraph {
50264
50414
  convertLabel2Resid(residLabel) {var ic = this.icn3d; ic.icn3dui;
50265
50415
  //ASN $1KQ2.A:6@ND2
50266
50416
  //or ASN $1KQ2.A:6
50417
+ // or ASN $1KQ2.A:6@ND2 1234
50418
+ let idArray = residLabel.split(' ');
50419
+ residLabel = (idArray.length == 2) ? residLabel : residLabel.substr(0, residLabel.lastIndexOf(' '));
50420
+
50267
50421
  residLabel.indexOf(' ');
50268
50422
  let pos2Tmp = residLabel.indexOf('@');
50269
50423
  let pos2 =(pos2Tmp !== -1) ? pos2Tmp : residLabel.length;
@@ -50298,6 +50452,25 @@ class ShowInter {
50298
50452
  ic.dAtoms = me.hashUtilsCls.unionHash(ic.dAtoms, atoms);
50299
50453
  ic.dAtoms = me.hashUtilsCls.unionHash(ic.dAtoms, atoms2);
50300
50454
 
50455
+ if(type == 'ligplot') {
50456
+ let residueHash1 = ic.firstAtomObjCls.getResiduesFromAtoms(atoms);
50457
+ let residueHash2 = ic.firstAtomObjCls.getResiduesFromAtoms(atoms2);
50458
+
50459
+ if(Object.keys(residueHash1).length > 1 && Object.keys(residueHash2).length > 1) {
50460
+ var aaa = 1; //alert("Please select one ligand or residue as one of the interaction sets...");
50461
+ return;
50462
+ }
50463
+
50464
+ // switch the sets to make the first set as the ligand
50465
+ if(Object.keys(residueHash1).length < Object.keys(residueHash2).length) {
50466
+ nameArray2 = $("#" + ic.pre + "atomsCustomHbond").val();
50467
+ nameArray = $("#" + ic.pre + "atomsCustomHbond2").val();
50468
+
50469
+ atoms = ic.definedSetsCls.getAtomsFromNameArray(nameArray);
50470
+ atoms2 = ic.definedSetsCls.getAtomsFromNameArray(nameArray2);
50471
+ }
50472
+ }
50473
+
50301
50474
  if(nameArray2.length == 0) {
50302
50475
  var aaa = 1; //alert("Please select the first set");
50303
50476
  }
@@ -50341,6 +50514,9 @@ class ShowInter {
50341
50514
  else if(type == 'scatterplot') {
50342
50515
  me.htmlCls.clickMenuCls.setLogCmd("scatterplot interaction pairs | " + tmpStr, true);
50343
50516
  }
50517
+ else if(type == 'ligplot') {
50518
+ me.htmlCls.clickMenuCls.setLogCmd("ligplot interaction pairs | " + tmpStr, true);
50519
+ }
50344
50520
  else if(type == 'graph') { // force-directed graph
50345
50521
  let dist_ss = parseInt($("#" + ic.pre + "dist_ss").val());
50346
50522
  let dist_coil = parseInt($("#" + ic.pre + "dist_coil").val());
@@ -51029,6 +51205,9 @@ class ViewInterPairs {
51029
51205
  let svgHtml = ic.lineGraphCls.drawLineGraph(ic.graphStr, true);
51030
51206
  $("#" + ic.pre + "scatterplotDiv").html(svgHtml);
51031
51207
  }
51208
+ else if(type == 'ligplot') {
51209
+ await ic.ligplotCls.drawLigplot(atomSet1);
51210
+ }
51032
51211
  else if(bContactMapLocal) {
51033
51212
  me.htmlCls.dialogCls.openDlg('dl_contactmap', 'Show contact map');
51034
51213
  let bAnyAtom = true;
@@ -51118,7 +51297,9 @@ class ViewInterPairs {
51118
51297
  }
51119
51298
  }
51120
51299
 
51121
- getAllInteractionTable(type) { let ic = this.icn3d, me = ic.icn3dui;
51300
+ getAllInteractionTable(type, index2xy, xlen, ylen, xcenter, ycenter) { let ic = this.icn3d, me = ic.icn3dui;
51301
+ let svgHtmlNode = '', svgHtmlLine = '';
51302
+
51122
51303
  let bondCnt = [];
51123
51304
 
51124
51305
  let residsArray = Object.keys(ic.resids2inter);
@@ -51157,41 +51338,54 @@ class ViewInterPairs {
51157
51338
  }
51158
51339
  let labels2dist, result;
51159
51340
  labels2dist = ic.resids2inter[resids]['hbond'];
51160
- result = this.getInteractionPairDetails(labels2dist, type, 'hbond');
51341
+ result = this.getInteractionPairDetails(labels2dist, type, 'hbond', index2xy, xlen, ylen, xcenter, ycenter);
51161
51342
  strHbond += result.html;
51162
51343
  cntHbond += result.cnt;
51344
+ svgHtmlNode += result.svgHtmlNode;
51345
+ svgHtmlLine += result.svgHtmlLine;
51163
51346
  if(result.cnt > 0) residname2List += residname2 + ":hbond_" + result.cnt + " ";
51164
51347
 
51165
51348
  labels2dist = ic.resids2inter[resids]['ionic'];
51166
- result = this.getInteractionPairDetails(labels2dist, type, 'ionic');
51349
+ result = this.getInteractionPairDetails(labels2dist, type, 'ionic', index2xy, xlen, ylen, xcenter, ycenter);
51167
51350
  strIonic += result.html;
51168
51351
  cntIonic += result.cnt;
51352
+ svgHtmlNode += result.svgHtmlNode;
51353
+ svgHtmlLine += result.svgHtmlLine;
51169
51354
  if(result.cnt > 0) residname2List += residname2 + ":ionic_" + result.cnt + " ";
51170
51355
 
51171
- labels2dist = ic.resids2inter[resids]['contact'];
51172
- result = this.getContactPairDetails(labels2dist, type, 'contact');
51173
- strContact += result.html;
51174
- cntContact += result.cnt;
51175
- if(result.cnt > 0) residname2List += residname2 + ":contact_" + result.cnt + " ";
51176
-
51177
51356
  labels2dist = ic.resids2inter[resids]['halogen'];
51178
- result = this.getInteractionPairDetails(labels2dist, type, 'halogen');
51357
+ result = this.getInteractionPairDetails(labels2dist, type, 'halogen', index2xy, xlen, ylen, xcenter, ycenter);
51179
51358
  strHalegen += result.html;
51180
51359
  cntHalegen += result.cnt;
51360
+ svgHtmlNode += result.svgHtmlNode;
51361
+ svgHtmlLine += result.svgHtmlLine;
51181
51362
  if(result.cnt > 0) residname2List += residname2 + ":halogen_" + result.cnt + " ";
51182
51363
 
51183
51364
  labels2dist = ic.resids2inter[resids]['pi-cation'];
51184
- result = this.getInteractionPairDetails(labels2dist, type, 'pi-cation');
51365
+ result = this.getInteractionPairDetails(labels2dist, type, 'pi-cation', index2xy, xlen, ylen, xcenter, ycenter);
51185
51366
  strPication += result.html;
51186
51367
  cntPication += result.cnt;
51368
+ svgHtmlNode += result.svgHtmlNode;
51369
+ svgHtmlLine += result.svgHtmlLine;
51187
51370
  if(result.cnt > 0) residname2List += residname2 + ":pi-cation_" + result.cnt + " ";
51188
51371
 
51189
51372
  labels2dist = ic.resids2inter[resids]['pi-stacking'];
51190
- result = this.getInteractionPairDetails(labels2dist, type, 'pi-stacking');
51373
+ result = this.getInteractionPairDetails(labels2dist, type, 'pi-stacking', index2xy, xlen, ylen, xcenter, ycenter);
51191
51374
  strPistacking += result.html;
51192
51375
  cntPistacking += result.cnt;
51376
+ svgHtmlNode += result.svgHtmlNode;
51377
+ svgHtmlLine += result.svgHtmlLine;
51193
51378
  if(result.cnt > 0) residname2List += residname2 + ":pi-stacking_" + result.cnt + " ";
51194
51379
 
51380
+ // put contact as the last one since contact will use the same node as other interactions in ligand-protein interactoin
51381
+ labels2dist = ic.resids2inter[resids]['contact'];
51382
+ result = this.getContactPairDetails(labels2dist, type, 'contact', index2xy, xlen, ylen, xcenter, ycenter);
51383
+ strContact += result.html;
51384
+ cntContact += result.cnt;
51385
+ svgHtmlNode += result.svgHtmlNode;
51386
+ svgHtmlLine += result.svgHtmlLine;
51387
+ if(result.cnt > 0) residname2List += residname2 + ":contact_" + result.cnt + " ";
51388
+
51195
51389
  prevResidname1 = residname1;
51196
51390
  prevIds = ids;
51197
51391
  }
@@ -51219,7 +51413,7 @@ class ViewInterPairs {
51219
51413
  html += tmpText;
51220
51414
  html += '</tbody></table><br/>';
51221
51415
  }
51222
- return {html: html, bondCnt: bondCnt};
51416
+ return {html: html, bondCnt: bondCnt, svgHtmlNode: svgHtmlNode, svgHtmlLine: svgHtmlLine};
51223
51417
  }
51224
51418
  getInteractionPerResidue(prevIds, strHbond, strIonic, strContact, strHalegen, strPication, strPistacking,
51225
51419
  cntHbond, cntIonic, cntContact, cntHalegen, cntPication, cntPistacking) { let ic = this.icn3d; ic.icn3dui;
@@ -51234,15 +51428,24 @@ class ViewInterPairs {
51234
51428
  tmpText += '</tr>';
51235
51429
  return tmpText;
51236
51430
  }
51237
- getInteractionPairDetails(labels2dist, type, interactionType) { let ic = this.icn3d; ic.icn3dui;
51238
- let tmpText = '', cnt = 0;
51431
+ getInteractionPairDetails(labels2dist, type, interactionType, index2xy, xlen, ylen, xcenter, ycenter) { let ic = this.icn3d; ic.icn3dui;
51432
+ let svgHtmlNode = '', svgHtmlLine = '', tmpText = '', cnt = 0;
51239
51433
  let colorText1 = ' <span style="background-color:#';
51240
51434
  let colorText2 = '">&nbsp;&nbsp;&nbsp;</span>';
51241
51435
  if(labels2dist !== undefined) {
51436
+ if(!ic.resid2cnt) ic.resid2cnt = {};
51437
+ if(!ic.resid2ToXy) ic.resid2ToXy = {};
51438
+ if(!ic.nodeid2lineid) ic.nodeid2lineid = {};
51242
51439
  for(let labels in labels2dist) {
51243
- let resid1_resid2 = labels.split(',');
51244
- let resid1 =(type == 'save1') ? resid1_resid2[0] : resid1_resid2[1];
51245
- let resid2 =(type == 'save1') ? resid1_resid2[1] : resid1_resid2[0];
51440
+ let resid1_resid2 = labels.split('|');
51441
+ let resid1Ori =(type == 'save1') ? resid1_resid2[0] : resid1_resid2[1];
51442
+ let resid2Ori =(type == 'save1') ? resid1_resid2[1] : resid1_resid2[0];
51443
+ //resid1: MET $3GVU.A:364@N 1234
51444
+ let pos1 = resid1Ori.lastIndexOf(' ');
51445
+ let pos2 = resid2Ori.lastIndexOf(' ');
51446
+ let resid1 = resid1Ori.substr(0, pos1);
51447
+ let resid2 = resid2Ori.substr(0, pos2);
51448
+
51246
51449
  let resid1Real = ic.getGraphCls.convertLabel2Resid(resid1);
51247
51450
  let atom1 = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid1Real]);
51248
51451
  let color1 = (atom1.color) ? atom1.color.getHexString() : '';
@@ -51254,38 +51457,125 @@ class ViewInterPairs {
51254
51457
  tmpText += '<td align="center"><button class="' + ic.pre + 'selres" resid="' + resid1 + '|' + resid2 + '">Highlight</button></td>';
51255
51458
  tmpText += '</tr>';
51256
51459
  ++cnt;
51460
+
51461
+ if(index2xy) {
51462
+ let serialArray1 = resid1Ori.substr(pos1 + 1).split(',');
51463
+
51464
+ let result = ic.ligplotCls.getSvgPerPair(serialArray1, resid1, resid2, interactionType, index2xy, xlen, ylen, xcenter, ycenter);
51465
+ svgHtmlNode += result.node;
51466
+ svgHtmlLine += result.line;
51467
+ }
51257
51468
  }
51258
51469
  }
51259
- return {html: tmpText, cnt: cnt}
51470
+ return {html: tmpText, cnt: cnt, svgHtmlNode: svgHtmlNode, svgHtmlLine: svgHtmlLine}
51260
51471
  }
51261
- getContactPairDetails(labels2dist, type) { let ic = this.icn3d; ic.icn3dui;
51262
- let tmpText = '', cnt = 0;
51472
+
51473
+ getContactPairDetails(labels2dist, type, interactionType, index2xy, xlen, ylen, xcenter, ycenter) { let ic = this.icn3d; ic.icn3dui;
51474
+ let svgHtmlNode = '', svgHtmlLine = '', tmpText = '', cnt = 0;
51263
51475
  let colorText1 = ' <span style="background-color:#';
51264
51476
  let colorText2 = '">&nbsp;&nbsp;&nbsp;</span>';
51265
51477
  if(labels2dist !== undefined) {
51478
+ let resids2distCnt = {};
51479
+ if(!ic.resid2cnt) ic.resid2cnt = {};
51480
+ if(!ic.resid2ToXy) ic.resid2ToXy = {};
51481
+ if(!ic.nodeid2lineid) ic.nodeid2lineid = {};
51266
51482
  for(let labels in labels2dist) {
51267
- let resid1_resid2 = labels.split(',');
51268
- let resid1 =(type == 'save1') ? resid1_resid2[0] : resid1_resid2[1];
51269
- let resid2 =(type == 'save1') ? resid1_resid2[1] : resid1_resid2[0];
51483
+ let resid1_resid2 = labels.split('|');
51484
+ let resid1Ori =(type == 'save1') ? resid1_resid2[0] : resid1_resid2[1];
51485
+ let resid2Ori =(type == 'save1') ? resid1_resid2[1] : resid1_resid2[0];
51486
+ //resid1: MET $3GVU.A:364 1234
51487
+ let pos1 = resid1Ori.lastIndexOf(' ');
51488
+ let pos2 = resid2Ori.lastIndexOf(' ');
51489
+
51490
+ let serialArray1 = resid1Ori.substr(pos1 + 1).split(',');
51491
+ let resid1 = resid1Ori.substr(0, pos1);
51492
+ if(index2xy) {
51493
+ // add atom name to resid1
51494
+ resid1 += '@' + ic.atoms[serialArray1[0]].name;
51495
+ }
51496
+
51497
+ let resid2 = resid2Ori.substr(0, pos2);
51498
+ let resids = resid1 + '|' + resid2;
51499
+
51500
+ let resid1Real = ic.getGraphCls.convertLabel2Resid(resid1);
51501
+ ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid1Real]);
51502
+ // let color1 = (atom1.color) ? atom1.color.getHexString() : '';
51503
+ let resid2Real = ic.getGraphCls.convertLabel2Resid(resid2);
51504
+ ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid2Real]);
51505
+ // let color2 = (atom2.color) ? atom2.color.getHexString() : '';
51506
+ let dist1_dist2_atom1_atom2 = labels2dist[labels].split('_');
51507
+ let dist1 = parseFloat(dist1_dist2_atom1_atom2[0]);
51508
+ // let dist2 = parseFloat(dist1_dist2_atom1_atom2[1]);
51509
+ // let atom1Name = dist1_dist2_atom1_atom2[2];
51510
+ // let atom2Name = dist1_dist2_atom1_atom2[3];
51511
+ let contactCnt = parseInt(dist1_dist2_atom1_atom2[4]);
51512
+ if(!resids2distCnt.hasOwnProperty(resids)) {
51513
+ resids2distCnt[resids] = {'dist1': dist1, 'dist1_dist2_atom1_atom2': dist1_dist2_atom1_atom2, 'cnt': contactCnt, 'serialArray1': serialArray1};
51514
+ }
51515
+ else {
51516
+ resids2distCnt[resids].cnt += contactCnt;
51517
+ if(dist1 < resids2distCnt[resids].dist1) {
51518
+ resids2distCnt[resids].dist1 = dist1;
51519
+ resids2distCnt[resids].dist1_dist2_atom1_atom2 = dist1_dist2_atom1_atom2;
51520
+ resids2distCnt[resids].serialArray1 = serialArray1;
51521
+ }
51522
+ }
51523
+ }
51524
+
51525
+ let resid2ToResid1 = {};
51526
+ for(let resids in resids2distCnt) {
51527
+ let resid1_resid2 = resids.split('|');
51528
+ let resid1 = resid1_resid2[0];
51529
+ let resid2 = resid1_resid2[1];
51530
+
51531
+ if(!resid2ToResid1.hasOwnProperty(resid2)) {
51532
+ resid2ToResid1[resid2] = [resid1];
51533
+ }
51534
+ else {
51535
+ resid2ToResid1[resid2].push(resid1);
51536
+ }
51537
+
51270
51538
  let resid1Real = ic.getGraphCls.convertLabel2Resid(resid1);
51271
51539
  let atom1 = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid1Real]);
51272
51540
  let color1 = (atom1.color) ? atom1.color.getHexString() : '';
51273
51541
  let resid2Real = ic.getGraphCls.convertLabel2Resid(resid2);
51274
51542
  let atom2 = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid2Real]);
51275
51543
  let color2 = (atom2.color) ? atom2.color.getHexString() : '';
51276
- let dist1_dist2_atom1_atom2 = labels2dist[labels].split('_');
51544
+ let dist1_dist2_atom1_atom2 = resids2distCnt[resids].dist1_dist2_atom1_atom2;
51277
51545
  let dist1 = dist1_dist2_atom1_atom2[0];
51278
51546
  let dist2 = dist1_dist2_atom1_atom2[1];
51279
51547
  let atom1Name = dist1_dist2_atom1_atom2[2];
51280
51548
  let atom2Name = dist1_dist2_atom1_atom2[3];
51281
- let contactCnt = dist1_dist2_atom1_atom2[4];
51549
+ let contactCnt = 1; //resids2distCnt[resids].cnt;
51550
+
51282
51551
  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>';
51283
51552
  tmpText += '<td align="center"><button class="' + ic.pre + 'selres" resid="' + resid1 + '|' + resid2 + '">Highlight</button></td>';
51284
51553
  tmpText += '</tr>';
51285
51554
  cnt += parseInt(contactCnt);
51286
51555
  }
51556
+
51557
+ if(index2xy) {
51558
+ for(let resid2 in resid2ToResid1) {
51559
+ let resid1Array = resid2ToResid1[resid2];
51560
+ let prevX2, prevY2;
51561
+ for(let i = 0, il = resid1Array.length; i < il; ++i) {
51562
+ let resid1 = resid1Array[i];
51563
+ let resids = resid1 + '|' + resid2;
51564
+
51565
+ let serialArray1 = resids2distCnt[resids].serialArray1;
51566
+
51567
+ let bNotDrawNode = (i == 0) ? false : true;
51568
+ let result = ic.ligplotCls.getSvgPerPair(serialArray1, resid1, resid2, interactionType, index2xy, xlen, ylen, xcenter, ycenter, bNotDrawNode, prevX2, prevY2);
51569
+ svgHtmlNode += result.node;
51570
+ svgHtmlLine += result.line;
51571
+ prevX2 = result.x2;
51572
+ prevY2 = result.y2;
51573
+ }
51574
+ }
51575
+ }
51287
51576
  }
51288
- return {html: tmpText, cnt: cnt}
51577
+
51578
+ return {html: tmpText, cnt: cnt, svgHtmlNode: svgHtmlNode, svgHtmlLine: svgHtmlLine};
51289
51579
  }
51290
51580
 
51291
51581
  //Export the list of residues in some chain interacting with residues in another chain.
@@ -52663,8 +52953,10 @@ class ChainalignParser {
52663
52953
  //$.when(ic.pdbParserCls.applyCommandDssp(true)).then(function() {
52664
52954
  await ic.pdbParserCls.applyCommandDssp(true);
52665
52955
 
52956
+ // original version =============
52666
52957
  // align PDB chains
52667
52958
  for(let index in ic.pdbChainIndexHash) {
52959
+ //ic.pdbChainIndexHash[index] = mmdbid_q_tmp + "_" + ic.chain_q + "_" + ic.mmdbid_t + "_" + ic.chain_t;
52668
52960
  let idArray = ic.pdbChainIndexHash[index].split('_');
52669
52961
  mmdbid_q = idArray[0];
52670
52962
  idArray[1];
@@ -52679,25 +52971,49 @@ class ChainalignParser {
52679
52971
  let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
52680
52972
  let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
52681
52973
 
52974
+ let resRangeArray = (me.cfg.resrange) ? me.cfg.resrange.split(' | ') : [];
52975
+
52682
52976
  for(let index in ic.afChainIndexHash) {
52683
52977
  let idArray = ic.afChainIndexHash[index].split('_');
52684
52978
  mmdbid_q = idArray[0];
52685
52979
  let chain_q = idArray[1];
52980
+ let chainid_q = mmdbid_q + '_' + chain_q;
52981
+
52686
52982
  mmdbid_t = idArray[2];
52687
52983
  let chain_t = idArray[3];
52984
+ let chainid_t = mmdbid_t + '_' + chain_t;
52985
+
52986
+ let atomSet_t = (resRangeArray[0]) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[0].split(','), chainid_t).hAtoms : ic.chains[chainid_t];
52987
+ let atomSet_q = (resRangeArray[index]) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[index].split(','), chainid_q).hAtoms : ic.chains[chainid_q];
52988
+ // end of original version =============
52989
+
52990
+ /*
52991
+ // new version to be done for VASTsrv ==============
52992
+ // dynamically align pairs in all chainids
52993
+ let ajaxArray = [], indexArray = [], struArray = [];
52994
+ let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
52995
+ let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
52996
+
52997
+ let resRangeArray = (me.cfg.resrange) ? me.cfg.resrange.split(' | ') : [];
52998
+
52999
+ // dynamically align pairs in all chainids
53000
+ let atomSet_t = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[0].split(','), chainidArray[0]).hAtoms : ic.chains[chainidArray[0]];
53001
+ for(let index = 1, indexl = chainidArray.length; index < indexl; ++index) {
53002
+ let atomSet_q = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[index].split(','), chainidArray[index]).hAtoms : ic.chains[chainidArray[index]];
53003
+ // end of new version to be done for VASTsrv ==============
53004
+ */
52688
53005
 
52689
53006
  let alignAjax;
52690
53007
  if(me.cfg.aligntool != 'tmalign') {
52691
- let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(ic.chains[mmdbid_q + '_' + chain_q]);
52692
- let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(ic.chains[mmdbid_t + '_' + chain_t]);
53008
+ let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(atomSet_q);
53009
+ let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(atomSet_t);
52693
53010
 
52694
53011
  let dataObj = {'domains1': jsonStr_q, 'domains2': jsonStr_t};
52695
53012
  alignAjax = me.getAjaxPostPromise(urlalign, dataObj);
52696
53013
  }
52697
53014
  else {
52698
- let pdb_query = ic.saveFileCls.getAtomPDB(ic.chains[mmdbid_q + '_' + chain_q]);
52699
-
52700
- let pdb_target= ic.saveFileCls.getAtomPDB(ic.chains[mmdbid_t + '_' + chain_t]);
53015
+ let pdb_query = ic.saveFileCls.getAtomPDB(atomSet_q);
53016
+ let pdb_target= ic.saveFileCls.getAtomPDB(atomSet_t);
52701
53017
 
52702
53018
  let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target};
52703
53019
  alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
@@ -53100,7 +53416,7 @@ class ChainalignParser {
53100
53416
  return chainidArray;
53101
53417
  }
53102
53418
 
53103
- async downloadChainalignment(chainalign, resnum, resdef) { let ic = this.icn3d, me = ic.icn3dui;
53419
+ async downloadChainalignment(chainalign) { let ic = this.icn3d, me = ic.icn3dui;
53104
53420
  let thisClass = this;
53105
53421
 
53106
53422
  ic.opts['proteins'] = 'c alpha trace';
@@ -53377,7 +53693,7 @@ class ChainalignParser {
53377
53693
  async loadOpmDataForChainalign(data1, data2, chainidArray, mmdbidArray) { let ic = this.icn3d, me = ic.icn3dui;
53378
53694
  let thisClass = this;
53379
53695
 
53380
- if(me.cfg.resnum || me.cfg.resdef) {
53696
+ if(me.cfg.resnum || me.cfg.resdef || me.cfg.resrange) {
53381
53697
  if(!ic.bCommandLoad) ic.init(); // remove all previously loaded data
53382
53698
  await this.downloadChainalignmentPart2(data1, data2, undefined, chainidArray);
53383
53699
 
@@ -55326,6 +55642,22 @@ class MmdbParser {
55326
55642
  hAtoms = ic.loadAtomDataCls.loadAtomDataIn(data, pdbid, 'mmdbid', undefined, type, chainid, chainIndex, bLastQuery, bNoTransformNoSeqalign);
55327
55643
  }
55328
55644
 
55645
+ // show ligand-protein interaction
55646
+ if(me.cfg.ligand) { // sid123059722
55647
+ for(let chainid in ic.chainid2sid) {
55648
+ if(ic.chainid2sid[chainid] == me.cfg.ligand.substr(3)) {
55649
+ // save a set named me.cfg.ligand
55650
+ let residueHash = ic.firstAtomObjCls.getResiduesFromAtoms(ic.chains[chainid]);
55651
+ let idArray = Object.keys(residueHash)[0].split('_');
55652
+ let select = '.' + idArray[1] + ':' + idArray[2];
55653
+
55654
+ await ic.selByCommCls.selectByCommand(select, me.cfg.ligand, me.cfg.ligand);
55655
+ break;
55656
+ }
55657
+ }
55658
+ }
55659
+ ic.hAtoms = hAtoms;
55660
+
55329
55661
  // set 3d domains
55330
55662
  let structure = data.pdbId;
55331
55663
 
@@ -58254,6 +58586,7 @@ class DensityCifParser {
58254
58586
 
58255
58587
  //https://www.ebi.ac.uk/pdbe/densities/doc.html
58256
58588
  if(type == '2fofc' || type == 'fofc') {
58589
+ detail = 0;
58257
58590
  url = "https://www.ebi.ac.uk/pdbe/densities/x-ray/" + pdbid.toLowerCase() + "/cell?detail=" + detail;
58258
58591
  }
58259
58592
  else if(type == 'em') {
@@ -58294,6 +58627,39 @@ class DensityCifParser {
58294
58627
  }
58295
58628
  }
58296
58629
 
58630
+ async densityCifParserBase(url, type, sigma, location, bInputSigma) { let ic = this.icn3d, me = ic.icn3dui;
58631
+ let thisClass = this;
58632
+
58633
+ //https://stackoverflow.com/questions/33902299/using-jquery-ajax-to-download-a-binary-file
58634
+ if(type == '2fofc' && ic.bAjax2fofc) {
58635
+ ic.mapData.sigma2 = sigma;
58636
+ ic.setOptionCls.setOption('map', type);
58637
+ }
58638
+ else if(type == 'fofc' && ic.bAjaxfofc) {
58639
+ ic.mapData.sigma = sigma;
58640
+ ic.setOptionCls.setOption('map', type);
58641
+ }
58642
+ else {
58643
+ let arrayBuffer = await me.getXMLHttpRqstPromise(url, 'GET', 'arraybuffer', type);
58644
+
58645
+ thisClass.parseChannels(arrayBuffer, type, sigma);
58646
+
58647
+ if(type == '2fofc' || type == 'fofc') {
58648
+ ic.bAjax2fofc = true;
58649
+ ic.bAjaxfofc = true;
58650
+
58651
+ ic.setOptionCls.setOption('map', type);
58652
+ }
58653
+ else if(type == 'em') {
58654
+ ic.bAjaxEm = true;
58655
+
58656
+ ic.setOptionCls.setOption('emmap', type);
58657
+ }
58658
+ }
58659
+
58660
+ // return sigma;
58661
+ }
58662
+
58297
58663
  parseChannels(densitydata, type, sigma) { let ic = this.icn3d; ic.icn3dui;
58298
58664
  let cif = this.BinaryParse(densitydata);
58299
58665
 
@@ -63286,7 +63652,7 @@ class LoadCIF {
63286
63652
 
63287
63653
  let bFirstAtom = true;
63288
63654
 
63289
- let cifArray = bcifData.split('ENDMDL\n');
63655
+ let cifArray = (bText) ? bcifData.split('ENDMDL\n') : [bcifData];
63290
63656
 
63291
63657
  for(let index = 0, indexl = cifArray.length; index < indexl; ++index) {
63292
63658
  ++moleculeNum;
@@ -65879,6 +66245,7 @@ class ApplyCommand {
65879
66245
  || commandOri.indexOf('save2 interaction pairs') == 0
65880
66246
  || commandOri.indexOf('line graph interaction pairs') == 0
65881
66247
  || commandOri.indexOf('scatterplot interaction pairs') == 0
66248
+ || commandOri.indexOf('ligplot interaction pairs') == 0
65882
66249
  ) {
65883
66250
  let paraArray = commandOri.split(' | ');
65884
66251
  if(paraArray.length >= 3) {
@@ -65936,6 +66303,9 @@ class ApplyCommand {
65936
66303
  else if(commandOri.indexOf('scatterplot interaction pairs') == 0) {
65937
66304
  type = 'scatterplot';
65938
66305
  }
66306
+ else if(commandOri.indexOf('ligplot interaction pairs') == 0) {
66307
+ type = 'ligplot';
66308
+ }
65939
66309
 
65940
66310
  await ic.viewInterPairsCls.viewInteractionPairs(nameArray2, nameArray, bHbondCalc, type, bHbond, bSaltbridge, bInteraction, bHalogen, bPication, bPistacking);
65941
66311
  }
@@ -65995,6 +66365,14 @@ class ApplyCommand {
65995
66365
 
65996
66366
  $("#" + me.scatterplotid).attr("width",(ic.scatterplotWidth * parseFloat(scale)).toString() + "px");
65997
66367
  }
66368
+ else if(command.indexOf('ligplot scale') == 0) {
66369
+ let pos = command.lastIndexOf(' ');
66370
+ let scale = command.substr(pos + 1);
66371
+
66372
+ $("#" + me.ligplotid + "_scale").val(scale);
66373
+
66374
+ $("#" + me.ligplotid).attr("width",(ic.ligplotWidth * parseFloat(scale)).toString() + "px");
66375
+ }
65998
66376
  else if(command.indexOf('contactmap scale') == 0) {
65999
66377
  let pos = command.lastIndexOf(' ');
66000
66378
  let scale = command.substr(pos + 1);
@@ -66277,6 +66655,16 @@ class ApplyCommand {
66277
66655
  ic.transformCls.rotateCoord(ic.hAtoms, mArrayFloat);
66278
66656
  ic.drawCls.draw();
66279
66657
  }
66658
+ else if(command.indexOf('set dssp sse') == 0) {
66659
+ await ic.pdbParserCls.applyCommandDssp();
66660
+ ic.bResetAnno = true;
66661
+
66662
+ if(ic.bAnnoShown) {
66663
+ await ic.showAnnoCls.showAnnotations();
66664
+
66665
+ ic.annotationCls.resetAnnoTabAll();
66666
+ }
66667
+ }
66280
66668
 
66281
66669
  // special, select ==========
66282
66670
 
@@ -66638,6 +67026,7 @@ class ApplyCommand {
66638
67026
  else if(cmd.indexOf('save2 interaction pairs') == 0) return hbondIntStr + ': "Set 2" button';
66639
67027
  else if(cmd.indexOf('line graph interaction pairs') == 0) return hbondIntStr + ': "2D Interaction Network" button';
66640
67028
  else if(cmd.indexOf('scatterplot interaction pairs') == 0) return hbondIntStr + ': "2D Interaction Map" button';
67029
+ else if(cmd.indexOf('ligplot interaction pairs') == 0) return hbondIntStr + ': "2D Interaction for One Ligand/Residue" button';
66641
67030
  else if(cmd.indexOf('graph label') == 0) return forceStr + ': "Label Size" menu';
66642
67031
  else if(cmd.indexOf('graph force') == 0) return forceStr + ': "Force on Nodes" menu';
66643
67032
  else if(cmd.indexOf('hide edges') == 0) return forceStr + ': "Internal Edges" menu';
@@ -68259,20 +68648,23 @@ class LoadScript {
68259
68648
  }
68260
68649
  }
68261
68650
  else if(command.indexOf('load chainalignment') !== -1) {
68262
- //load chainalignment [id] | resnum [resnum] | resdef [resnum] | aligntool [aligntool] | parameters [inpara]
68651
+ //load chainalignment [id] | resnum [resnum] | resdef [resdef] | aligntool [aligntool] | parameters [inpara] | resrange [resrange]
68263
68652
  let urlArray = command.split(" | ");
68264
68653
  if(urlArray.length > 1 && urlArray[1].indexOf('resnum') != -1) {
68265
68654
  me.cfg.resnum = urlArray[1].substr(urlArray[1].indexOf('resnum') + 7);
68266
68655
  }
68267
68656
  if(urlArray.length > 2 && urlArray[2].indexOf('resdef') != -1) {
68268
- me.cfg.resdef = urlArray[2].substr(urlArray[1].indexOf('resdef') + 7);
68657
+ me.cfg.resdef = urlArray[2].substr(urlArray[2].indexOf('resdef') + 7);
68269
68658
  }
68270
68659
  if(urlArray.length > 3 && urlArray[3].indexOf('aligntool') != -1) {
68271
- me.cfg.aligntool = urlArray[3].substr(urlArray[1].indexOf('aligntool') + 10);
68660
+ me.cfg.aligntool = urlArray[3].substr(urlArray[3].indexOf('aligntool') + 10);
68661
+ }
68662
+ if(urlArray.length > 5 && urlArray[5].indexOf('resrange') != -1) {
68663
+ me.cfg.resrange = urlArray[5].substr(urlArray[5].indexOf('resrange') + 9);
68272
68664
  }
68273
68665
 
68274
68666
  me.cfg.chainalign = id;
68275
- await ic.chainalignParserCls.downloadChainalignment(id, me.cfg.resnum, me.cfg.resdef);
68667
+ await ic.chainalignParserCls.downloadChainalignment(id);
68276
68668
  }
68277
68669
  else if(command.indexOf('load url') !== -1) {
68278
68670
  let typeStr = load_parameters[1]; // type pdb
@@ -68321,7 +68713,8 @@ class LoadScript {
68321
68713
  if(urlArray.length == 2) {
68322
68714
  let bInputSigma = true;
68323
68715
  if(fileType == 'dsn6') {
68324
- await ic.dsn6ParserCls.dsn6ParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
68716
+ // await ic.dsn6ParserCls.dsn6ParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
68717
+ await ic.densityCifParserCls.densityCifParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
68325
68718
  }
68326
68719
  else if(fileType == 'ccp4') {
68327
68720
  await ic.ccp4ParserCls.ccp4ParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
@@ -68334,7 +68727,8 @@ class LoadScript {
68334
68727
  }
68335
68728
  }
68336
68729
  else {
68337
- await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma);
68730
+ // await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma);
68731
+ await ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma);
68338
68732
  }
68339
68733
  }
68340
68734
  // }); // end of me.deferred = $.Deferred(function() {
@@ -75190,6 +75584,12 @@ class Diagram2d {
75190
75584
  thisClass.clickNode(this);
75191
75585
  });
75192
75586
 
75587
+ $(document).on("click", "#" + ic.pre + "dl_ligplot .icn3d-node", function(e) { thisClass.icn3d;
75588
+ e.stopImmediatePropagation();
75589
+
75590
+ thisClass.clickNode(this);
75591
+ });
75592
+
75193
75593
  //$("#" + ic.pre + "dl_linegraph .icn3d-interaction", "click", function(e) { let ic = this.icn3d, me = ic.icn3dui;
75194
75594
  $(document).on("click", "#" + ic.pre + "dl_linegraph .icn3d-interaction", function(e) { let ic = thisClass.icn3d;
75195
75595
  e.stopImmediatePropagation();
@@ -75272,6 +75672,8 @@ class Diagram2d {
75272
75672
  let strokeWidth = 2;
75273
75673
  $(node).find('circle').attr('stroke', me.htmlCls.ORANGE);
75274
75674
  $(node).find('circle').attr('stroke-width', strokeWidth);
75675
+ $(node).find('rect').attr('stroke', me.htmlCls.ORANGE);
75676
+ $(node).find('rect').attr('stroke-width', strokeWidth);
75275
75677
 
75276
75678
  ic.hAtoms = me.hashUtilsCls.unionHash(ic.hAtoms, ic.residues[resid]);
75277
75679
 
@@ -76389,6 +76791,364 @@ class Cartoon2d {
76389
76791
  }
76390
76792
  }
76391
76793
 
76794
+ /**
76795
+ * @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
76796
+ */
76797
+
76798
+ class Ligplot {
76799
+ constructor(icn3d) {
76800
+ this.icn3d = icn3d;
76801
+ }
76802
+
76803
+ async drawLigplot(atomSet1) { let ic = this.icn3d, me = ic.icn3dui;
76804
+ me.htmlCls.dialogCls.openDlg('dl_ligplot', 'Show ligand interactions with atom details');
76805
+
76806
+ let widthOri, heightOri, width = 100, height = 100;
76807
+ ic.len4ang = 80;
76808
+
76809
+ // get SVG from backend
76810
+ let pdbStr = ic.saveFileCls.getAtomPDB(atomSet1);
76811
+ pdbStr = pdbStr.trim();
76812
+ pdbStr = pdbStr.replace(/\n\n/g, '\n'); // remove empty lines
76813
+
76814
+ let dataObj = {'pdb2svg': pdbStr};
76815
+ let url = me.htmlCls.baseUrl + "openbabel/openbabel.cgi";
76816
+ let dataStr = await me.getAjaxPostPromise(url, dataObj, undefined, undefined, undefined, undefined, 'text');
76817
+
76818
+ let lineArray = dataStr.split('\n');
76819
+ let lineSvg = '', nodeSvg = '', index2xy = {};
76820
+ let xsum = 0, ysum = 0, cnt = 0;
76821
+ 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)
76822
+ ic.gridXY2used = {};
76823
+ for(let i = 0, il = lineArray.length; i < il; ++i) {
76824
+ let line = lineArray[i];
76825
+ if(line.indexOf('<svg width') == 0) {
76826
+ //<svg width="100" height="100" x="0" y="0" viewBox="0 0 634.256 380"
76827
+ // get real width and height
76828
+ let start = line.indexOf('viewBox="') + 9;
76829
+ let linePart = line.substr(start);
76830
+ let viewbox = linePart.substr(0, linePart.indexOf('"'));
76831
+ let viewboxArray = viewbox.split(' ');
76832
+ widthOri = parseFloat(viewboxArray[2]);
76833
+ heightOri = parseFloat(viewboxArray[3]);
76834
+ width = widthOri + 2*ic.len4ang;
76835
+ height = heightOri + 2*ic.len4ang;
76836
+ }
76837
+ else if(line.indexOf('<line') == 0) {
76838
+ lineSvg += line + '\n';
76839
+ }
76840
+ else if(line.indexOf('<text') == 0) {
76841
+ if(line.indexOf('font-size="12"') != -1) {
76842
+ // index node
76843
+ //<text x="40.000000" y="120.000000" fill="rgb(255,0,0)" stroke-width="0" font-weight="bold" font-size="12" >1</text>
76844
+ let start = line.indexOf('>') + 1;
76845
+ let indexPart = line.substr(start);
76846
+ let index = parseInt(indexPart.substr(0, indexPart.indexOf('<')));
76847
+
76848
+ start = line.indexOf('x="') + 3;
76849
+ let xPart = line.substr(start);
76850
+ let x = parseFloat(xPart.substr(0, xPart.indexOf('"')));
76851
+
76852
+ start = line.indexOf('y="') + 3;
76853
+ let yPart = line.substr(start);
76854
+ let y = parseFloat(yPart.substr(0, yPart.indexOf('"')));
76855
+
76856
+ index2xy[index] = {"x": x, "y": y};
76857
+ let xGrid = parseInt(x / ic.svgGridSize);
76858
+ let yGrid = parseInt(y / ic.svgGridSize);
76859
+ ic.gridXY2used[xGrid + '_' + yGrid] = 1;
76860
+
76861
+ xsum += x;
76862
+ ysum += y;
76863
+ ++cnt;
76864
+ }
76865
+ else { // font-size > 12
76866
+ nodeSvg += line + '\n';
76867
+ }
76868
+ }
76869
+ else if(line.indexOf('</svg>') == 0) {
76870
+ break;
76871
+ }
76872
+ }
76873
+
76874
+ let xcenter = xsum / cnt, ycenter = ysum / cnt;
76875
+
76876
+ let id = me.ligplotid;
76877
+ ic.ligplotWidth = width;
76878
+ let graphWidth = ic.ligplotWidth;
76879
+
76880
+ let textHeight = 30;
76881
+ let heightAll = height + textHeight;
76882
+
76883
+ let offset = - ic.len4ang;
76884
+ 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'>";
76885
+
76886
+ let xlen = parseInt(widthOri / ic.svgGridSize), ylen = parseInt(heightOri / ic.svgGridSize);
76887
+ let result = ic.viewInterPairsCls.getAllInteractionTable("save1", index2xy, xlen, ylen, xcenter, ycenter); // sort on the ligand/set1
76888
+ ic.bLigplot = true;
76889
+
76890
+ svgHtml += lineSvg + result.svgHtmlLine;
76891
+
76892
+ svgHtml += nodeSvg + result.svgHtmlNode;
76893
+
76894
+ svgHtml += "</svg>";
76895
+
76896
+ $("#" + ic.pre + "ligplotDiv").html(svgHtml);
76897
+
76898
+ this.setEventsForLigplot();
76899
+ }
76900
+
76901
+
76902
+ getSvgPerPair(serialArray1, resid1, resid2, interactionType, index2xy, xlen, ylen, xcenter, ycenter, bNotDrawNode, prevX2, prevY2) { let ic = this.icn3d, me = ic.icn3dui;
76903
+ let xOffset = 1, yOffset = -1;
76904
+ let bondLen = (interactionType == 'hbond' || interactionType == 'contact' || interactionType == 'halogen') ? ic.len4ang : ic.len4ang * 1.5; // real distance should be bout 120, not 80
76905
+ let shortBondLen = ic.len4ang / 2;
76906
+ let strokeWidth = (interactionType == 'contact') ? 1 : 2;
76907
+
76908
+ let resid1Real = ic.getGraphCls.convertLabel2Resid(resid1);
76909
+ let atom1 = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid1Real]);
76910
+ let resid2Real = ic.getGraphCls.convertLabel2Resid(resid2);
76911
+ let atom2 = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid2Real]);
76912
+
76913
+ let xSum = 0, ySum = 0, cntPoint = 0;
76914
+ let baseSerial = atom1.serial;
76915
+ for(let i = 0, il = serialArray1.length; i < il; ++i) {
76916
+ let index = serialArray1[i] - baseSerial + 1;
76917
+ xSum += index2xy[index].x;
76918
+ ySum += index2xy[index].y;
76919
+ ++cntPoint;
76920
+ }
76921
+
76922
+ let x1 = xSum / cntPoint - xOffset;
76923
+ let y1 = ySum / cntPoint - yOffset;
76924
+
76925
+ if(!ic.resid2cnt.hasOwnProperty(resid1)) {
76926
+ ic.resid2cnt[resid1] = 0;
76927
+ }
76928
+ else {
76929
+ ++ic.resid2cnt[resid1];
76930
+ }
76931
+
76932
+ let x2, y2, angle;
76933
+ if(!bNotDrawNode && !ic.resid2ToXy.hasOwnProperty(resid2Real)) {
76934
+ // 1st and ideal way to find a position. If failed, use the 2nd way
76935
+ let xGrid = parseInt(x1 / ic.svgGridSize);
76936
+ let yGrid = parseInt(y1 / ic.svgGridSize);
76937
+ let gridArray = [];
76938
+ for(let i = 1; i >= -1; --i) { // try right-bottom first
76939
+ for(let j = 1; j >= -1; --j) {
76940
+ if(!(i == 0 && j == 0)) {
76941
+ if(xGrid + i >= 0 && xGrid + i <= xlen && yGrid + j >= 0 && yGrid + j <= ylen) gridArray.push((xGrid + i) + '_' + (yGrid + j));
76942
+ }
76943
+ }
76944
+ }
76945
+ for(let i = 2; i >= -2; --i) { // try right-bottom first
76946
+ for(let j = 2; j >= -2; --j) {
76947
+ if(!(i >= -1 && i <= 1 && j >= -1 && j <= 1 )) {
76948
+ if(xGrid + i >= 0 && xGrid + i <= xlen && yGrid + j >= 0 && yGrid + j <= ylen) gridArray.push((xGrid + i) + '_' + (yGrid + j));
76949
+ }
76950
+ }
76951
+ }
76952
+
76953
+ let bFound = false, xyGrids;
76954
+ for(let i = 0, il = gridArray.length; i < il; ++i) {
76955
+ if(!ic.gridXY2used[gridArray[i]]) { // found a spot to put the residue
76956
+ xyGrids = gridArray[i].split('_');
76957
+ x2 = (parseInt(xyGrids[0]) + 0.5) * ic.svgGridSize;
76958
+ y2 = (parseInt(xyGrids[1]) + 0.5) * ic.svgGridSize;
76959
+
76960
+ let dist = Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
76961
+ let x2b = bondLen / dist * (x2 - x1) + x1;
76962
+ let y2b = bondLen / dist * (y2 - y1) + y1;
76963
+ x2 = x2b;
76964
+ y2 = y2b;
76965
+
76966
+ ic.gridXY2used[gridArray[i]] = 1;
76967
+ bFound = true;
76968
+ break;
76969
+ }
76970
+ }
76971
+
76972
+ if(!bFound) {
76973
+ // 2nd way to find a position from the center to the outside
76974
+ let dx = x1 - xcenter;
76975
+ let dy = y1 - ycenter;
76976
+
76977
+ let baseAngle = 0;
76978
+ if(Math.abs(dx) > Math.abs(dy)) { // extend along x-axis
76979
+ if(dx > 0) { // +x direction
76980
+ baseAngle = 0;
76981
+ }
76982
+ else { // -x direction
76983
+ baseAngle = 180;
76984
+ }
76985
+ }
76986
+ else { // extend along y-axis
76987
+ if(dy > 0) { // +y direction
76988
+ baseAngle = 90;
76989
+ }
76990
+ else { // -y direction
76991
+ baseAngle = 270;
76992
+ }
76993
+ }
76994
+ angle = baseAngle - 10 + ic.resid2cnt[resid1] * 30;
76995
+
76996
+ x2 = x1 + bondLen * Math.cos(angle * Math.PI/180);
76997
+ y2 = y1 + bondLen * Math.sin(angle * Math.PI/180);
76998
+ }
76999
+ }
77000
+
77001
+ let oneLetterRes = me.utilsCls.residueName2Abbr(atom2.resn.substr(0, 3));
77002
+ let resName2 = oneLetterRes + atom2.resi;
77003
+ let textColor2 = (atom2.color) ? atom2.color.getHexString() : '000';
77004
+ let lineColor = ic.lineGraphCls.getStrokecolor(undefined, interactionType);
77005
+
77006
+ // 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>';
77007
+
77008
+ let node = '', line = '';
77009
+
77010
+ // id can't contain comma and thus use '-'
77011
+ // sometimes the same ligand atom is used in both Hbond and contact. THus we add "interactionType"
77012
+ let idpair = resid2Real + '--' + serialArray1.join('-') + interactionType;
77013
+
77014
+ let id = resid2Real;
77015
+ if(bNotDrawNode || ic.resid2ToXy.hasOwnProperty(id)) {
77016
+ x2 = (ic.resid2ToXy.hasOwnProperty(id)) ? ic.resid2ToXy[id].x2 : prevX2;
77017
+ y2 = (ic.resid2ToXy.hasOwnProperty(id)) ? ic.resid2ToXy[id].y2 : prevY2;
77018
+
77019
+ // draw a short line from x2, y2 to x1, y1 with the distance shortBondLen
77020
+ let x1b = x1, y1b = y1, bShort = 0;
77021
+ if(interactionType == 'contact') {
77022
+ let dist = Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
77023
+ if(shortBondLen < dist) {
77024
+ x1b = shortBondLen / dist * (x1 - x2) + x2;
77025
+ y1b = shortBondLen / dist * (y1 - y2) + y2;
77026
+ bShort = 1;
77027
+ }
77028
+ }
77029
+
77030
+ 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';
77031
+ }
77032
+ else {
77033
+ node +='<g>';
77034
+ node += '<title>' + resName2 + '</title>';
77035
+ // node += '<circle class='icn3d-ctnode' cx="' + x2.toFixed(2) + '" cy="' + y2.toFixed(2) + '" r="10" fill="#' + textColor2 + '" stroke-width="1" stroke="' + textColor2 + '" resid="' + resid2Real + '"/>';
77036
+ let boxWidth = 28, boxHeight = 14;
77037
+ 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 + '"/>';
77038
+
77039
+ 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>';
77040
+ node += '</g>\n';
77041
+
77042
+ 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';
77043
+
77044
+ if(interactionType != 'contact') {
77045
+ if(!ic.resid2ToXy.hasOwnProperty(resid2Real)) ic.resid2ToXy[resid2Real] = {x2: x2, y2: y2};
77046
+ }
77047
+ }
77048
+
77049
+ if(!ic.nodeid2lineid.hasOwnProperty(id)) ic.nodeid2lineid[id] = [];
77050
+ ic.nodeid2lineid[id].push(idpair);
77051
+
77052
+ return {node: node, line: line, x2: x2, y2: y2};
77053
+ }
77054
+
77055
+ setEventsForLigplot() { let ic = this.icn3d, me = ic.icn3dui;
77056
+ //https://stackoverflow.com/questions/1108480/svg-draggable-using-jquery-and-jquery-svg
77057
+ $("#" + me.ligplotid + " .icn3d-ctnode")
77058
+ .draggable({
77059
+ start: function( e, ui ) {
77060
+ let oriX= parseFloat(e.target.getAttribute('x'));
77061
+ let oriY = parseFloat(e.target.getAttribute('y'));
77062
+
77063
+ e.target.setAttribute('x', oriX);
77064
+ e.target.setAttribute('y', oriY);
77065
+ },
77066
+ drag: function( e, ui ) {
77067
+ let offsetX = $("#" + me.ligplotid).offset().left + ic.len4ang; // ic.len4ang was defined in svg viewbox
77068
+ let offsetY = $("#" + me.ligplotid).offset().top + ic.len4ang;
77069
+
77070
+ let id = e.target.getAttribute('resid');
77071
+ let x = (e.clientX - offsetX);
77072
+ let y = (e.clientY - offsetY);
77073
+
77074
+ let oriX = parseFloat(e.target.getAttribute('x'));
77075
+ let oriY = parseFloat(e.target.getAttribute('y'));
77076
+
77077
+ // change for each step
77078
+ let dx = (x - oriX) / ic.resizeRatioX;
77079
+ let dy = (y - oriY) / ic.resizeRatioY;
77080
+
77081
+ // move the text label
77082
+ oriX = parseFloat($("#" + id + "_node").attr('x'));
77083
+ oriY = parseFloat($("#" + id + "_node").attr('y'));
77084
+
77085
+ $("#" + id + "_node").attr('x', oriX + dx);
77086
+ $("#" + id + "_node").attr('y', oriY + dy);
77087
+
77088
+ // update the center
77089
+ e.target.setAttribute('x', x);
77090
+ e.target.setAttribute('y', y);
77091
+
77092
+ // update the edges
77093
+ if(ic.nodeid2lineid[id]) {
77094
+ for(let i = 0, il = ic.nodeid2lineid[id].length; i < il; ++i) {
77095
+ let idpair = ic.nodeid2lineid[id][i];
77096
+
77097
+ updateEdges(idpair, id);
77098
+ }
77099
+ }
77100
+
77101
+ function updateEdges(idpair, id) {
77102
+ if(idpair && idpair.indexOf(id) != -1) {
77103
+ let idArray = idpair.split('--');
77104
+ if(idArray.length == 2) {
77105
+ let id2;
77106
+ id2 = idArray[0];
77107
+
77108
+ let x2 = parseFloat($("#" + id2).attr('x'));
77109
+ let y2 = parseFloat($("#" + id2).attr('y'));
77110
+
77111
+ $("#" + idpair).attr('x2', x2);
77112
+ $("#" + idpair).attr('y2', y2);
77113
+
77114
+ let x1 = $("#" + idpair).attr('x1');
77115
+ let y1 = $("#" + idpair).attr('y1');
77116
+ let x1b = x1, y1b = y1;
77117
+
77118
+ let bShort = parseInt($("#" + idpair).attr('short'));
77119
+ if(bShort) { // adjust x1,y1
77120
+ x1 = $("#" + idpair).attr('x0');
77121
+ y1 = $("#" + idpair).attr('y0');
77122
+
77123
+ let dist = Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
77124
+ let shortBondLen = ic.len4ang / 2;
77125
+
77126
+ if(shortBondLen < dist) {
77127
+ x1b = shortBondLen / dist * (x1 - x2) + x2;
77128
+ y1b = shortBondLen / dist * (y1 - y2) + y2;
77129
+ }
77130
+ }
77131
+
77132
+ $("#" + idpair).attr('x1', x1b);
77133
+ $("#" + idpair).attr('y1', y1b);
77134
+ }
77135
+ } // if
77136
+ } // function
77137
+ }
77138
+ });
77139
+ }
77140
+
77141
+ clickLigplot() { let ic = this.icn3d; ic.icn3dui;
77142
+ let thisClass = this;
77143
+
77144
+ $(document).on("click", "#" + ic.pre + "dl_ligplot .icn3d-ctnode", function(e) { let ic = thisClass.icn3d;
77145
+ e.stopImmediatePropagation();
77146
+
77147
+ ic.diagram2dCls.clickNode(this);
77148
+ });
77149
+ }
77150
+ }
77151
+
76392
77152
  /**
76393
77153
  * @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
76394
77154
  */
@@ -77072,7 +77832,7 @@ class SaveFile {
77072
77832
  }
77073
77833
  }
77074
77834
 
77075
- saveSvg(id, filename, bContactmap) { let ic = this.icn3d, me = ic.icn3dui;
77835
+ saveSvg(id, filename, bContactmap, bLigplot) { let ic = this.icn3d, me = ic.icn3dui;
77076
77836
  if(me.bNode) return '';
77077
77837
 
77078
77838
  let width = $("#" + id).width();
@@ -77080,19 +77840,26 @@ class SaveFile {
77080
77840
 
77081
77841
  if(bContactmap) height = width;
77082
77842
 
77083
- let svgXml = this.getSvgXml(id, width, height, bContactmap);
77843
+ if(bLigplot) {
77844
+ width += ic.len4ang;
77845
+ height += ic.len4ang;
77846
+ }
77847
+
77848
+ let svgXml = this.getSvgXml(id, width, height, bContactmap, bLigplot);
77084
77849
 
77085
77850
  let blob = new Blob([svgXml], {type: "image/svg+xml"});
77086
77851
  saveAs(blob, filename);
77087
77852
  }
77088
77853
 
77089
- getSvgXml(id, width, height, bContactmap) { let ic = this.icn3d, me = ic.icn3dui;
77854
+ getSvgXml(id, width, height, bContactmap, bLigplot) { let ic = this.icn3d, me = ic.icn3dui;
77090
77855
  if(me.bNode) return '';
77091
77856
 
77092
77857
  // font is not good
77093
77858
  let svg_data = document.getElementById(id).innerHTML; //put id of your svg element here
77094
77859
 
77095
- let viewbox = (width && height) ? "<svg viewBox=\"0 0 " + width + " " + height + "\"" : "<svg";
77860
+ let startX = (bLigplot) ? -30 : 0;
77861
+ let startY = (bLigplot) ? -30 : 0;
77862
+ let viewbox = (width && height) ? "<svg viewBox=\"" + startX + " " + startY + " " + width + " " + height + "\"" : "<svg";
77096
77863
  //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/\">";
77097
77864
  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/\">";
77098
77865
 
@@ -77104,7 +77871,7 @@ class SaveFile {
77104
77871
  return full_svg;
77105
77872
  }
77106
77873
 
77107
- savePng(id, filename, bContactmap) { let ic = this.icn3d, me = ic.icn3dui;
77874
+ savePng(id, filename, bContactmap, bLigplot) { let ic = this.icn3d, me = ic.icn3dui;
77108
77875
  if(me.bNode) return '';
77109
77876
 
77110
77877
  let width = $("#" + id).width();
@@ -77117,7 +77884,7 @@ class SaveFile {
77117
77884
  let bbox = svg.getBBox();
77118
77885
 
77119
77886
  let copy = svg.cloneNode(true);
77120
- ic.lineGraphCls.copyStylesInline(copy, svg);
77887
+ if(!bLigplot) ic.lineGraphCls.copyStylesInline(copy, svg);
77121
77888
  let canvas = document.createElement("CANVAS");
77122
77889
  canvas.width = width;
77123
77890
  canvas.height = height;
@@ -80910,6 +81677,7 @@ class iCn3D {
80910
81677
  this.shareLinkCls = new ShareLink(this);
80911
81678
  this.diagram2dCls = new Diagram2d(this);
80912
81679
  this.cartoon2dCls = new Cartoon2d(this);
81680
+ this.ligplotCls = new Ligplot(this);
80913
81681
 
80914
81682
  this.rayCls = new Ray(this);
80915
81683
  this.controlCls = new Control(this);
@@ -81136,7 +81904,7 @@ class iCn3DUI {
81136
81904
  //even when multiple iCn3D viewers are shown together.
81137
81905
  this.pre = this.cfg.divid + "_";
81138
81906
 
81139
- this.REVISION = '3.33.2';
81907
+ this.REVISION = '3.34.0';
81140
81908
 
81141
81909
  // In nodejs, iCn3D defines "window = {navigator: {}}"
81142
81910
  this.bNode = (Object.keys(window).length < 2) ? true : false;
@@ -81579,9 +82347,10 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81579
82347
 
81580
82348
  ic.bChainAlign = true;
81581
82349
  ic.inputid = me.cfg.chainalign;
81582
- ic.loadCmd = 'load chainalignment ' + me.cfg.chainalign + ' | resnum ' + me.cfg.resnum + ' | resdef ' + me.cfg.resdef + ' | aligntool ' + me.cfg.aligntool + ' | parameters ' + me.cfg.inpara;
82350
+ let resrangeStr = (me.cfg.resrange) ? ' | resrange ' + me.cfg.resrange : '';
82351
+ ic.loadCmd = 'load chainalignment ' + me.cfg.chainalign + ' | resnum ' + me.cfg.resnum + ' | resdef ' + me.cfg.resdef + ' | aligntool ' + me.cfg.aligntool + ' | parameters ' + me.cfg.inpara + resrangeStr;
81583
82352
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
81584
- await ic.chainalignParserCls.downloadChainalignment(me.cfg.chainalign, me.cfg.resnum, me.cfg.resdef);
82353
+ await ic.chainalignParserCls.downloadChainalignment(me.cfg.chainalign);
81585
82354
  }
81586
82355
  else if(me.cfg.mmdbafid !== undefined) {
81587
82356
  // ic.bNCBI = true;