icn3d 3.33.0 → 3.33.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/icn3d.module.js CHANGED
@@ -7794,7 +7794,10 @@ class UtilsCls {
7794
7794
  let nOtherAtoms = 0;
7795
7795
  for(let i in atomlist) {
7796
7796
  if(index < testLength) {
7797
- let atomName = atomlist[i].name.trim();
7797
+ let atomName = atomlist[i].name;
7798
+ if(!atomName) continue;
7799
+ atomName = atomName.trim();
7800
+
7798
7801
  if(atomName !== "CA" && atomName !== "P" && atomName !== "O3'" && atomName !== "O3*") {
7799
7802
  //bOtherAtoms = true;
7800
7803
  //break;
@@ -9947,7 +9950,7 @@ class ClickMenu {
9947
9950
  });
9948
9951
 
9949
9952
  me.myEventCls.onIds("#" + me.pre + "mn1_cid", "click", function(e) { me.icn3d; //e.preventDefault();
9950
- me.htmlCls.dialogCls.openDlg('dl_cid', 'Please input PubChem CID');
9953
+ me.htmlCls.dialogCls.openDlg('dl_cid', 'Please input PubChem Compound');
9951
9954
  });
9952
9955
 
9953
9956
  me.myEventCls.onIds("#" + me.pre + "mn1_pngimage", "click", function(e) { me.icn3d; //e.preventDefault();
@@ -11298,8 +11301,8 @@ class ClickMenu {
11298
11301
  //if(!me.cfg.notebook) dialog.dialog( "close" );
11299
11302
  let sigma2fofc = parseFloat($("#" + me.pre + "sigma2fofc" ).val());
11300
11303
  let type = '2fofc';
11301
- await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma2fofc);
11302
- //ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma2fofc);
11304
+ //await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma2fofc);
11305
+ await ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma2fofc);
11303
11306
 
11304
11307
  //ic.setOptionCls.setOption('map', '2fofc');
11305
11308
  thisClass.setLogCmd('set map 2fofc sigma ' + sigma2fofc, true);
@@ -11311,7 +11314,8 @@ class ClickMenu {
11311
11314
  //if(!me.cfg.notebook) dialog.dialog( "close" );
11312
11315
  let sigmafofc = parseFloat($("#" + me.pre + "sigmafofc" ).val());
11313
11316
  let type = 'fofc';
11314
- await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigmafofc);
11317
+ //await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigmafofc);
11318
+ await ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma2fofc);
11315
11319
  //ic.setOptionCls.setOption('map', 'fofc');
11316
11320
  thisClass.setLogCmd('set map fofc sigma ' + sigmafofc, true);
11317
11321
  });
@@ -11571,13 +11575,21 @@ class ClickMenu {
11571
11575
  });
11572
11576
 
11573
11577
  me.myEventCls.onIds("#" + me.pre + "mn6_distManySets", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
11574
- me.htmlCls.dialogCls.openDlg('dl_distmanysets', 'Measure the pairwise distance among many sets');
11578
+ me.htmlCls.dialogCls.openDlg('dl_distmanysets', 'Measure the pairwise distances among many sets');
11575
11579
 
11576
11580
  thisClass.setSetsMenus('atomsCustomDistTable');
11577
11581
 
11578
11582
  ic.bMeasureDistance = true;
11579
11583
  });
11580
11584
 
11585
+ me.myEventCls.onIds("#" + me.pre + "mn6_angleManySets", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
11586
+ me.htmlCls.dialogCls.openDlg('dl_anglemanysets', 'Measure the pairwise angles among many sets');
11587
+
11588
+ thisClass.setSetsMenus('atomsCustomAngleTable');
11589
+
11590
+ ic.bMeasureAngle = true;
11591
+ });
11592
+
11581
11593
  me.myEventCls.onIds("#" + me.pre + "mn6_distanceNo", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
11582
11594
  ic.pickpair = false;
11583
11595
  let select = "set lines off";
@@ -11662,6 +11674,10 @@ class ClickMenu {
11662
11674
  me.htmlCls.dialogCls.openDlg('dl_translate', 'Translate the X,Y,Z coordinates of the structure');
11663
11675
  });
11664
11676
 
11677
+ $(document).on("click", "#" + me.pre + "mn6_angleTwoSets", function(e) { me.icn3d; //e.preventDefault();
11678
+ me.htmlCls.dialogCls.openDlg('dl_angle', 'Measure the angle between two vectors');
11679
+ });
11680
+
11665
11681
  $(document).on("click", "#" + me.pre + "mn2_matrix", function(e) { me.icn3d; //e.preventDefault();
11666
11682
  me.htmlCls.dialogCls.openDlg('dl_matrix', 'Apply matrix to the X,Y,Z coordinates of the structure');
11667
11683
  });
@@ -11848,6 +11864,18 @@ class ClickMenu {
11848
11864
  me.htmlCls.dialogCls.openDlg('dl_contact', 'Set contact map');
11849
11865
  });
11850
11866
 
11867
+ me.myEventCls.onIds(["#" + me.pre + "mn6_DSSP"], "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
11868
+ thisClass.setLogCmd('set dssp sse', true);
11869
+ await ic.pdbParserCls.applyCommandDssp();
11870
+ ic.bResetAnno = true;
11871
+
11872
+ if(ic.bAnnoShown) {
11873
+ await ic.showAnnoCls.showAnnotations();
11874
+
11875
+ ic.annotationCls.resetAnnoTabAll();
11876
+ }
11877
+ });
11878
+
11851
11879
 
11852
11880
  me.myEventCls.onIds("#" + me.pre + "mn6_hbondsNo", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
11853
11881
  ic.showInterCls.hideHbondsContacts();
@@ -12582,7 +12610,7 @@ class SetMenu {
12582
12610
  html += this.getLink('mn1_mmcifid', 'RCSB mmCIF ID ' + me.htmlCls.wifiStr, undefined, 2);
12583
12611
  //html += this.getLink('mn1_gi', 'NCBI gi ' + me.htmlCls.wifiStr, undefined, 2);
12584
12612
 
12585
- html += this.getLink('mn1_cid', 'PubChem CID ' + me.htmlCls.wifiStr, 1, 2);
12613
+ html += this.getLink('mn1_cid', 'PubChem CID/Name/InchI ' + me.htmlCls.wifiStr, 1, 2);
12586
12614
 
12587
12615
  html += "</ul>";
12588
12616
  html += "</li>";
@@ -13683,11 +13711,18 @@ class SetMenu {
13683
13711
  html += "<ul>";
13684
13712
  html += this.getRadio('mn6_distance', 'mn6_distanceYes', 'between Two Atoms', undefined, 1, 2);
13685
13713
  html += this.getRadio('mn6_distance', 'mn6_distTwoSets', 'between Two Sets', undefined, undefined, 2);
13686
- html += this.getRadio('mn6_distance', 'mn6_distManySets', 'Among Many Sets', undefined, undefined, 2);
13714
+ html += this.getRadio('mn6_distance', 'mn6_distManySets', 'among Many Sets', undefined, undefined, 2);
13687
13715
  html += this.getRadio('mn6_distance', 'mn6_distanceNo', 'Hide', true, 1, 2);
13688
13716
  html += "</ul>";
13689
13717
  html += "</li>";
13690
13718
 
13719
+ html += this.getMenuText('mn6_anglewrap', 'Angle', undefined, 1, 1);
13720
+ html += "<ul>";
13721
+ html += this.getRadio('mn6_angle', 'mn6_angleManySets', 'among Many Sets', undefined, 1, 2);
13722
+ html += this.getRadio('mn6_angle', 'mn6_angleTwoSets', 'b/w Two Vectors', undefined, undefined, 2);
13723
+ html += "</ul>";
13724
+ html += "</li>";
13725
+
13691
13726
  html += this.getLink('mn6_area', 'Surface Area', 1, 1);
13692
13727
 
13693
13728
  html += this.getMenuText('mn6_addlabelwrap', 'Label', undefined, 1, 1);
@@ -13761,6 +13796,8 @@ class SetMenu {
13761
13796
  html += "</ul>";
13762
13797
  html += "</li>";
13763
13798
 
13799
+ html += this.getLink('mn6_DSSP', 'DSSP Secondary', undefined, 1);
13800
+
13764
13801
  let bOnePdb = me.cfg.mmtfid !== undefined || me.cfg.pdbid !== undefined || me.cfg.opmid !== undefined || me.cfg.mmcifid !== undefined || me.cfg.mmdbid !== undefined || me.cfg.mmdbafid !== undefined || me.cfg.gi !== undefined || me.cfg.blast_rep_id !== undefined;
13765
13802
 
13766
13803
  if(bOnePdb) {
@@ -15003,8 +15040,8 @@ class SetDialog {
15003
15040
  html += "</div>";
15004
15041
 
15005
15042
  html += me.htmlCls.divStr + "dl_cid' class='" + dialogClass + "'>";
15006
- html += this.addNotebookTitle('dl_cid', 'Please input a PubChem CID');
15007
- html += "PubChem CID: " + me.htmlCls.inputTextStr + "id='" + me.pre + "cid' value='2244' size=8> ";
15043
+ html += this.addNotebookTitle('dl_cid', 'Please input a PubChem Compound');
15044
+ html += "PubChem CID/Name/InchI: " + me.htmlCls.inputTextStr + "id='" + me.pre + "cid' value='2244' size=8> ";
15008
15045
  html += me.htmlCls.buttonStr + "reload_cid'>Load</button>";
15009
15046
  html += "</div>";
15010
15047
 
@@ -15061,14 +15098,14 @@ class SetDialog {
15061
15098
 
15062
15099
  html += "<span style='white-space:nowrap;font-weight:bold;'>2fofc contour at default threshold or at: "
15063
15100
  + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigma2fofc' value='' size=8> &sigma;</span><br/>";
15064
- //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/>";
15065
- 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/>";
15101
+ //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/>";
15102
+ 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/>";
15066
15103
 
15067
15104
  html += "<span style='white-space:nowrap;font-weight:bold;'>fofc contour at default threshold or at: "
15068
15105
  + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigmafofc' value='' size=8> &sigma;</span><br/>";
15069
15106
 
15070
- //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>";
15071
- 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>";
15107
+ //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>";
15108
+ 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>";
15072
15109
 
15073
15110
 
15074
15111
  html += me.htmlCls.buttonStr + "elecmapNo4'>Remove Map</button><br>";
@@ -15082,12 +15119,16 @@ class SetDialog {
15082
15119
  html += "<span style='white-space:nowrap;font-weight:bold;'>2fofc contour at default threshold or at: "
15083
15120
  + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigmaurl2fofc' value='' size=8> &sigma;</span><br/>";
15084
15121
 
15085
- 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/>";
15122
+ //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/>";
15123
+
15124
+ 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/>";
15086
15125
 
15087
15126
  html += "<span style='white-space:nowrap;font-weight:bold;'>fofc contour at default threshold or at: "
15088
15127
  + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigmaurlfofc' value='' size=8> &sigma;</span><br/>";
15089
15128
 
15090
- 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>";
15129
+ //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>";
15130
+
15131
+ 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>";
15091
15132
 
15092
15133
  html += me.htmlCls.buttonStr + "elecmapNo5'>Remove Map</button><br>";
15093
15134
 
@@ -15635,6 +15676,29 @@ class SetDialog {
15635
15676
  html += me.htmlCls.spanNowrapStr + "2. " + me.htmlCls.buttonStr + "applydisttable'>Distances in Table</button></span>";
15636
15677
  html += "</div>";
15637
15678
 
15679
+
15680
+ html += me.htmlCls.divStr + "dl_anglemanysets' class='" + dialogClass + "' style='max-width:500px'>";
15681
+ html += this.addNotebookTitle('dl_anglemanysets', 'Measure angles among many sets');
15682
+ 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/>";
15683
+ html += me.htmlCls.spanNowrapStr + "1. Select sets for pairwise angles</span><br/>";
15684
+ html += "<table border=0 width=400 cellspacing=10><tr><td>";
15685
+
15686
+ html += me.htmlCls.divNowrapStr + "First sets:</div>";
15687
+ html += "<div style='text-indent:1.1em'><select style='max-width:200px' id='" + me.pre + "atomsCustomAngleTable2' multiple size='5' style='min-width:130px;'>";
15688
+ html += "</select></div>";
15689
+
15690
+ html += "</td><td>";
15691
+
15692
+ html += me.htmlCls.divNowrapStr + "Second sets:</div>";
15693
+ html += "<div style='text-indent:1.1em'><select style='max-width:200px' id='" + me.pre + "atomsCustomAngleTable' multiple size='5' style='min-width:130px;'>";
15694
+ html += "</select></div>";
15695
+
15696
+ html += "</td></tr></table>";
15697
+
15698
+ html += me.htmlCls.spanNowrapStr + "2. " + me.htmlCls.buttonStr + "applyangletable'>Angles in Table</button></span>";
15699
+ html += "</div>";
15700
+
15701
+
15638
15702
  html += me.htmlCls.divStr + "dl_stabilizer_rm' class='" + dialogClass + "'>";
15639
15703
  html += this.addNotebookTitle('dl_stabilizer_rm', 'Remove a stabilizer');
15640
15704
  if(me.utilsCls.isMobile()) {
@@ -15914,6 +15978,11 @@ class SetDialog {
15914
15978
  html += this.addNotebookTitle('dl_disttable', 'Distance Table', true);
15915
15979
  html += "</div>";
15916
15980
 
15981
+
15982
+ html += me.htmlCls.divStr + "dl_angletable' class='" + dialogClass + "'>";
15983
+ html += this.addNotebookTitle('dl_angletable', 'Angle Table', true);
15984
+ html += "</div>";
15985
+
15917
15986
  html += me.htmlCls.divStr + "dl_translate' class='" + dialogClass + "'>";
15918
15987
  html += this.addNotebookTitle('dl_translate', 'Translate the X,Y,Z coordinates of the structure');
15919
15988
  html += "X: " + me.htmlCls.inputTextStr + "id='" + me.pre + "translateX' value='' size=4> ";
@@ -15922,6 +15991,20 @@ class SetDialog {
15922
15991
  html += me.htmlCls.buttonStr + "translate_pdb'>Translate</button>";
15923
15992
  html += "</div>";
15924
15993
 
15994
+ html += me.htmlCls.divStr + "dl_angle' class='" + dialogClass + "'>";
15995
+ html += this.addNotebookTitle('dl_angle', 'Measure the angle between two vectors');
15996
+ html += "<b>Vector 1</b>, X: " + me.htmlCls.inputTextStr + "id='" + me.pre + "v1X' value='' size=6> ";
15997
+ html += "Y: " + me.htmlCls.inputTextStr + "id='" + me.pre + "v1Y' value='' size=6> ";
15998
+ html += "Z: " + me.htmlCls.inputTextStr + "id='" + me.pre + "v1Z' value='' size=6><br>";
15999
+ html += "<b>Vector 2</b>, X: " + me.htmlCls.inputTextStr + "id='" + me.pre + "v2X' value='' size=6> ";
16000
+ html += "Y: " + me.htmlCls.inputTextStr + "id='" + me.pre + "v2Y' value='' size=6> ";
16001
+ html += "Z: " + me.htmlCls.inputTextStr + "id='" + me.pre + "v2Z' value='' size=6><br>";
16002
+ html += "<br>";
16003
+
16004
+ html += me.htmlCls.buttonStr + "measure_angle'>Measure Angle</button><br><br>";
16005
+ html += "The angle is: " + me.htmlCls.inputTextStr + "id='" + me.pre + "angle_value' value='' size=6> degree.<br><br>";
16006
+ html += "</div>";
16007
+
15925
16008
  html += me.htmlCls.divStr + "dl_matrix' class='" + dialogClass + "'>";
15926
16009
  html += this.addNotebookTitle('dl_matrix', 'Apply matrix to the X,Y,Z coordinates of the structure');
15927
16010
  html += "0: " + me.htmlCls.inputTextStr + "id='" + me.pre + "matrix0' value='1' size=2> ";
@@ -16765,6 +16848,27 @@ class Events {
16765
16848
  thisClass.setLogCmd("translate pdb " + dx + " " + dy + " " + dz, true);
16766
16849
  });
16767
16850
 
16851
+ me.myEventCls.onIds("#" + me.pre + "measure_angle", "click", function(e) { me.icn3d;
16852
+ e.preventDefault();
16853
+ if(!me.cfg.notebook) dialog.dialog( "close" );
16854
+ let v1X = $("#" + me.pre + "v1X").val();
16855
+ let v1Y = $("#" + me.pre + "v1Y").val();
16856
+ let v1Z= $("#" + me.pre + "v1Z").val();
16857
+
16858
+ let v2X = $("#" + me.pre + "v2X").val();
16859
+ let v2Y = $("#" + me.pre + "v2Y").val();
16860
+ let v2Z = $("#" + me.pre + "v2Z").val();
16861
+
16862
+ let angleRad = new THREE.Vector3(parseFloat(v1X), parseFloat(v1Y), parseFloat(v1Z)).angleTo(new THREE.Vector3(parseFloat(v2X), parseFloat(v2Y), parseFloat(v2Z)));
16863
+ let angle = angleRad / 3.1416 * 180;
16864
+ angle = Math.abs(angle).toFixed(0);
16865
+ if(angle > 180) angle -= 180;
16866
+ if(angle > 90) angle = 180 - angle;
16867
+
16868
+ thisClass.setLogCmd("The angle is " + angle + " degree", false);
16869
+ $("#" + me.pre + "angle_value").val(angle);
16870
+ });
16871
+
16768
16872
  me.myEventCls.onIds("#" + me.pre + "matrix_pdb", "click", function(e) { let ic = me.icn3d;
16769
16873
  e.preventDefault();
16770
16874
  if(!me.cfg.notebook) dialog.dialog( "close" );
@@ -18421,6 +18525,20 @@ class Events {
18421
18525
  thisClass.setLogCmd("disttable | " + nameArray2 + " " + nameArray, true);
18422
18526
  });
18423
18527
 
18528
+ me.myEventCls.onIds("#" + me.pre + "applyangletable", "click", function(e) { let ic = me.icn3d;
18529
+ e.preventDefault();
18530
+ if(!me.cfg.notebook) dialog.dialog( "close" );
18531
+ ic.bMeasureAngle = false;
18532
+
18533
+ let nameArray = $("#" + me.pre + "atomsCustomAngleTable").val();
18534
+ let nameArray2 = $("#" + me.pre + "atomsCustomAngleTable2").val();
18535
+
18536
+ ic.analysisCls.measureAngleManySets(nameArray, nameArray2);
18537
+ me.htmlCls.dialogCls.openDlg('dl_angletable', 'Angles among the sets');
18538
+
18539
+ thisClass.setLogCmd("angletable | " + nameArray2 + " " + nameArray, true);
18540
+ });
18541
+
18424
18542
  me.myEventCls.onIds("#" + me.pre + "applylinebtwsets", "click", function(e) { let ic = me.icn3d;
18425
18543
  e.preventDefault();
18426
18544
 
@@ -29010,18 +29128,17 @@ class Strand {
29010
29128
 
29011
29129
  let bRibbon = fill ? true: false;
29012
29130
 
29013
- // when highlight, the input atoms may only include part of sheet or helix
29014
- // include the whole sheet or helix when highlighting
29131
+ // when highlight, the input atoms may only include one rediue.
29132
+ // add one extra residue to show the strand
29015
29133
  let atomsAdjust = {};
29016
29134
 
29017
- // if( Object.keys(atoms).length < Object.keys(ic.atoms).length) {
29018
- // atomsAdjust = this.getSSExpandedAtoms(atoms);
29019
- // }
29020
- // else {
29021
- // atomsAdjust = atoms;
29022
- // }
29023
-
29024
- atomsAdjust = atoms;
29135
+ let residueHashTmp = ic.firstAtomObjCls.getResiduesFromAtoms(atoms);
29136
+ if( Object.keys(residueHashTmp).length == 1) {
29137
+ atomsAdjust = this.getOneExtraResidue(residueHashTmp);
29138
+ }
29139
+ else {
29140
+ atomsAdjust = atoms;
29141
+ }
29025
29142
 
29026
29143
  if(bHighlight === 2) {
29027
29144
  if(fill) {
@@ -29056,22 +29173,24 @@ class Strand {
29056
29173
  let currentChain, currentResi, currentCA = null, currentO = null, currentColor = null, prevCoorCA = null, prevCoorO = null, prevColor = null;
29057
29174
  let prevCO = null, ss = null, ssend = false, atomid = null, prevAtomid = null, prevAtomSelected = null, prevResi = null, calphaid = null, prevCalphaid = null;
29058
29175
  let strandWidth, bSheetSegment = false, bHelixSegment = false;
29059
- let atom, tubeAtoms = {};
29060
29176
 
29061
- // test the first 30 atoms to see whether only C-alpha is available
29062
- ic.bCalphaOnly = me.utilsCls.isCalphaPhosOnly(atomsAdjust); //, 'CA');
29177
+ // For each chain, test the first 30 atoms to see whether only C-alpha is available
29178
+ let bCalphaOnlyHash = {};
29179
+ for(let chainid in ic.chains) {
29180
+ let atoms = me.hashUtilsCls.hash2Atoms(ic.chains[chainid], ic.atoms);
29181
+ let bCalphaOnly = me.utilsCls.isCalphaPhosOnly(atoms); //, 'CA');
29182
+ bCalphaOnlyHash[chainid] = bCalphaOnly;
29183
+ }
29063
29184
 
29064
29185
  // when highlight, draw whole beta sheet and use bShowArray to show the highlight part
29065
29186
  let residueHash = {};
29066
29187
  for(let i in atomsAdjust) {
29067
- let atom = atomsAdjust[i];
29188
+ let atom = ic.atoms[i];
29068
29189
 
29069
29190
  let residueid = atom.structure + '_' + atom.chain + '_' + atom.resi;
29070
29191
  residueHash[residueid] = 1;
29071
29192
  }
29072
- let totalResidueCount = Object.keys(residueHash).length;
29073
-
29074
- let drawnResidueCount = 0;
29193
+ Object.keys(residueHash).length;
29075
29194
 
29076
29195
  let bFullAtom = (Object.keys(ic.hAtoms).length == Object.keys(ic.atoms).length) ? true : false;
29077
29196
 
@@ -29080,22 +29199,20 @@ class Strand {
29080
29199
  let maxDist = 6.0;
29081
29200
 
29082
29201
  //get the last residue
29083
- let atomArray = Object.keys(atoms);
29202
+ let atomArray = Object.keys(atomsAdjust);
29084
29203
  let lastAtomSerial = atomArray[atomArray.length - 1];
29085
- let lastAtom = atoms[lastAtomSerial];
29204
+ let lastAtom = ic.atoms[lastAtomSerial];
29086
29205
  let lastResid = lastAtom.structure + '_' + lastAtom.chain + '_' + lastAtom.resi;
29087
29206
 
29088
29207
  for (let i in atomsAdjust) {
29089
- atom = atomsAdjust[i];
29208
+ let atom = ic.atoms[i];
29090
29209
  let chainid = atom.structure + '_' + atom.chain;
29091
29210
  let resid = atom.structure + '_' + atom.chain + '_' + atom.resi;
29092
29211
  if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
29093
29212
  // "CA" has to appear before "O"
29094
29213
 
29095
29214
  if (atom.name === 'CA') {
29096
- if ( atoms.hasOwnProperty(i) && ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) ) {
29097
- tubeAtoms[i] = atom;
29098
- }
29215
+ if ( atoms.hasOwnProperty(i) && ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) ) ;
29099
29216
 
29100
29217
  currentCA = atom.coord;
29101
29218
  currentColor = atom.color;
@@ -29104,7 +29221,7 @@ class Strand {
29104
29221
  caArray.push(atom.serial);
29105
29222
  }
29106
29223
 
29107
- if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA')) {
29224
+ if (atom.name === 'O' || (bCalphaOnlyHash[chainid] && atom.name === 'CA')) {
29108
29225
  if(currentCA === null || currentCA === undefined) {
29109
29226
  currentCA = atom.coord;
29110
29227
  currentColor = atom.color;
@@ -29167,7 +29284,7 @@ class Strand {
29167
29284
  }
29168
29285
  }
29169
29286
  }
29170
- else if(ic.bCalphaOnly && atom.name === 'CA') {
29287
+ else if(bCalphaOnlyHash[chainid] && atom.name === 'CA') {
29171
29288
  if(caArray.length > resSpan + 1) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
29172
29289
  O = prevCoorCA.clone();
29173
29290
  oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan - 1]].coord.clone();
@@ -29202,8 +29319,6 @@ class Strand {
29202
29319
  bShowArray.push(0);
29203
29320
  calphaIdArray.push(0);
29204
29321
  }
29205
-
29206
- ++drawnResidueCount;
29207
29322
  }
29208
29323
 
29209
29324
  //let bBrokenSs = ic.ParserUtilsCls.getResiNCBI(atom.structure + '_' + currentChain, currentResi) + 1 !== ic.ParserUtilsCls.getResiNCBI(chainid, atom.resi) || (prevCoorCA && Math.abs(currentCA.x - prevCoorCA.x) > maxDist) || (prevCoorCA && Math.abs(currentCA.y - prevCoorCA.y) > maxDist) || (prevCoorCA && Math.abs(currentCA.z - prevCoorCA.z) > maxDist);
@@ -29232,7 +29347,9 @@ class Strand {
29232
29347
  // }
29233
29348
 
29234
29349
  //if ((atom.ssbegin || atom.ssend || (drawnResidueCount === totalResidueCount - 1) || bBrokenSs) && pnts[0].length > 0 && bSameChain) {
29235
- if ((currentChain !== atom.chain || atom.ssbegin || atom.ssend || (drawnResidueCount === totalResidueCount - 1) || bBrokenSs || resid == lastResid) && pnts[0].length > 0) {
29350
+ // if ((currentChain !== atom.chain || atom.ssbegin || atom.ssend || (drawnResidueCount === totalResidueCount - 1) || bBrokenSs || resid == lastResid) && pnts[0].length > 0) { // last coil was not drawn correctly, e.g., in 1TOP
29351
+
29352
+ if ((currentChain !== atom.chain || atom.ssbegin || atom.ssend || bBrokenSs || (resid == lastResid && atom.ss != 'coil')) && pnts[0].length > 0) {
29236
29353
  let atomName = 'CA';
29237
29354
 
29238
29355
  let prevone = [], nexttwo = [];
@@ -29289,7 +29406,7 @@ class Strand {
29289
29406
  O = currentO.clone();
29290
29407
  O.sub(currentCA);
29291
29408
  }
29292
- else if(ic.bCalphaOnly && atom.name === 'CA') {
29409
+ else if(bCalphaOnlyHash[chainid] && atom.name === 'CA') {
29293
29410
  if(caArray.length > resSpan) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
29294
29411
  O = currentCA.clone();
29295
29412
  oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan]].coord.clone();
@@ -29378,7 +29495,9 @@ class Strand {
29378
29495
  // end of a chain, or end of selection
29379
29496
  if ((currentChain !== atom.chain
29380
29497
  || ic.ParserUtilsCls.getResiNCBI(atom.structure + '_' + currentChain, currentResi) + 1 !== ic.ParserUtilsCls.getResiNCBI(chainid, atom.resi)
29381
- || resid == lastResid
29498
+ // || (drawnResidueCount === totalResidueCount - 1)
29499
+ // || bBrokenSs
29500
+ || (resid == lastResid && atom.ss != 'coil')
29382
29501
  ) && pnts[0].length > 0) {
29383
29502
  //if ((currentChain !== atom.chain) && pnts[0].length > 0) {
29384
29503
 
@@ -29446,18 +29565,42 @@ class Strand {
29446
29565
  prevCoorCA = currentCA;
29447
29566
  prevCoorO = atom.coord;
29448
29567
  prevColor = currentColor;
29449
- } // end if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA') ) {
29568
+ } // end if (atom.name === 'O' || (bCalphaOnlyHash[chainid] && atom.name === 'CA') ) {
29450
29569
  } // end if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
29451
29570
  } // end for
29452
29571
 
29453
29572
  caArray = [];
29454
29573
 
29455
- ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight);
29456
-
29457
- tubeAtoms = {};
29574
+ // ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight);
29575
+ // draw all atoms in tubes and assign zero radius when the residue is not coil
29576
+ ic.tubeCls.createTube(atomsAdjust, 'CA', coilWidth, bHighlight);
29458
29577
  pnts = {};
29459
29578
  }
29460
29579
 
29580
+ getOneExtraResidue(residueHash) { let ic = this.icn3d, me = ic.icn3dui;
29581
+ let atomsAdjust = {};
29582
+
29583
+ for(let resid in residueHash) {
29584
+ atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, ic.residues[resid]);
29585
+
29586
+ let residNcbi = ic.resid2ncbi[resid];
29587
+ let resiNcbi = residNcbi.substr(residNcbi.lastIndexOf('_') + 1);
29588
+
29589
+ let nextResidNcbi = residNcbi.substr(0, residNcbi.lastIndexOf('_')) + '_' + (parseInt(resiNcbi) + 1);
29590
+ let nextResid = ic.ncbi2resid[nextResidNcbi];
29591
+
29592
+ if(!nextResid) {
29593
+ nextResidNcbi = residNcbi.substr(0, residNcbi.lastIndexOf('_')) + '_' + (parseInt(resiNcbi) - 1);
29594
+ nextResid = ic.ncbi2resid[nextResidNcbi];
29595
+ }
29596
+
29597
+ if(nextResid) atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, ic.residues[nextResid]);
29598
+ }
29599
+
29600
+ return atomsAdjust;
29601
+ }
29602
+
29603
+ /*
29461
29604
  getSSExpandedAtoms(atoms, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
29462
29605
  let currChain, currResi, currAtom, prevChain, prevResi, prevAtom;
29463
29606
  let firstAtom, lastAtom;
@@ -29564,6 +29707,7 @@ class Strand {
29564
29707
 
29565
29708
  return atomsAdjust;
29566
29709
  }
29710
+ */
29567
29711
  }
29568
29712
 
29569
29713
  /**
@@ -29583,7 +29727,8 @@ class Strip {
29583
29727
  if (p0.length < 2) return;
29584
29728
  div = div || ic.axisDIV;
29585
29729
 
29586
- if(pntsCA && ic.bDoublecolor && !ic.bCalphaOnly) {
29730
+ // if(pntsCA && ic.bDoublecolor && !ic.bCalphaOnly) {
29731
+ if(pntsCA && ic.bDoublecolor) {
29587
29732
  let bExtendLastRes = false; //true;
29588
29733
 
29589
29734
  let pnts_clrs = me.subdivideCls.subdivide(pntsCA, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
@@ -29911,7 +30056,7 @@ class Tube {
29911
30056
  //Create tubes for "atoms" with certain "atomName". "radius" is the radius of the tubes.
29912
30057
  //"bHighlight" is an option to draw the highlight for these atoms. The highlight could be
29913
30058
  //outlines with bHighlight=1 and 3D objects with bHighlight=2.
29914
- createTube(atoms, atomName, radius, bHighlight, bCustom, bRadiusArray) { let ic = this.icn3d, me = ic.icn3dui;
30059
+ createTube(atoms, atomName, radius, bHighlight, bCustom, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
29915
30060
  if(me.bNode) return;
29916
30061
 
29917
30062
  let pnts = [], colors = [], radii = [], prevone = [], nexttwo = [];
@@ -30023,6 +30168,9 @@ class Tube {
30023
30168
  else {
30024
30169
  radiusFinal = this.getRadius(radius, atom);
30025
30170
  }
30171
+
30172
+ // draw all atoms in tubes and assign zero radius when the residue is not coil
30173
+ if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
30026
30174
 
30027
30175
  //radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
30028
30176
  radii.push(radiusFinal);
@@ -30096,183 +30244,247 @@ class Tube {
30096
30244
  let prevone = pnts_colors_radii_prevone_nexttwo[i].prevone;
30097
30245
  let nexttwo = pnts_colors_radii_prevone_nexttwo[i].nexttwo;
30098
30246
 
30099
- this.createTubeSub(pnts, colors, radii, bHighlight, prevone, nexttwo, bRadiusArray);
30247
+ this.createTubeSub(pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil);
30100
30248
  }
30101
30249
 
30102
- pnts_colors_radii_prevone_nexttwo = [];
30250
+ pnts_colors_radii_prevone_nexttwo = [];
30103
30251
  }
30104
30252
 
30105
- getCustomtubesize(resid) { let ic = this.icn3d; ic.icn3dui;
30106
- let pos = resid.lastIndexOf('_');
30107
- let resi = resid.substr(pos + 1);
30108
- let chainid = resid.substr(0, pos);
30253
+ /*
30254
+ createTube(atoms, atomName, radius, bHighlight, bCustom, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
30255
+ if(me.bNode) return;
30109
30256
 
30110
- let radiusFinal = (ic.queryresi2score[chainid] && ic.queryresi2score[chainid].hasOwnProperty(resi)) ? ic.queryresi2score[chainid][resi] * 0.01 : ic.coilWidth;
30257
+ let pnts = [], colors = [], radii = [], prevone = [], nexttwo = [];
30258
+ let currentChain, currentResi;
30259
+ let index = 0;
30260
+ let maxDist = 6.0;
30261
+ let maxDist2 = 3.0; // avoid tube between the residues in 3 residue helix
30111
30262
 
30112
- return radiusFinal;
30113
- };
30263
+ let pnts_colors_radii_prevone_nexttwo = [];
30264
+ let firstAtom, atom, prevAtom;
30114
30265
 
30115
- // modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
30116
- createTubeSub(_pnts, colors, radii, bHighlight, prevone, nexttwo, bRadiusArray) { let ic = this.icn3d, me = ic.icn3dui;
30117
- if(me.bNode) return;
30266
+ for (let i in atoms) {
30267
+ atom = atoms[i];
30268
+ if ((atom.name === atomName) && !atom.het) {
30269
+ if(index == 0) {
30270
+ firstAtom = atom;
30271
+ }
30118
30272
 
30119
- if (_pnts.length < 2) return;
30273
+ if (index > 0 && (currentChain !== atom.chain || Math.abs(atom.coord.x - prevAtom.coord.x) > maxDist || Math.abs(atom.coord.y - prevAtom.coord.y) > maxDist || Math.abs(atom.coord.z - prevAtom.coord.z) > maxDist
30274
+ || (ic.ParserUtilsCls.getResiNCBI(atom.structure + '_' + currentChain, currentResi) + 1 < ic.ParserUtilsCls.getResiNCBI(atom.structure + '_' + atom.chain, atom.resi) && (Math.abs(atom.coord.x - prevAtom.coord.x) > maxDist2 || Math.abs(atom.coord.y - prevAtom.coord.y) > maxDist2 || Math.abs(atom.coord.z - prevAtom.coord.z) > maxDist2))
30275
+ ) ) {
30276
+ if(bHighlight !== 2) {
30277
+ if(!isNaN(firstAtom.resi) && !isNaN(prevAtom.resi)) {
30278
+ let prevoneResid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
30279
+ let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
30280
+ prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
30120
30281
 
30121
- // if(bRadiusArray) {
30122
- let circleDiv = ic.tubeDIV, axisDiv = ic.axisDIV;
30123
- let circleDivInv = 1 / circleDiv, axisDivInv = 1 / axisDiv;
30124
- //var geo = new THREE.Geometry();
30125
- let geo = new THREE.BufferGeometry();
30126
- let verticeArray = [], colorArray = [],indexArray = [], color;
30127
- let offset = 0, offset2 = 0, offset3 = 0;
30282
+ let nextoneResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 1).toString();
30283
+
30284
+ // add one more residue if only one residue is available
30285
+ if(pnts.length == 1 && ic.residues.hasOwnProperty(nextoneResid)) {
30286
+ let nextAtom = ic.firstAtomObjCls.getAtomFromResi(nextoneResid, atomName);
30128
30287
 
30129
- let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv, undefined, undefined, prevone, nexttwo);
30288
+ if(nextAtom) {
30289
+ pnts.push(nextAtom.coord);
30290
+ colors.push(nextAtom.color);
30130
30291
 
30131
- let pnts = pnts_clrs[0];
30132
- colors = pnts_clrs[2];
30292
+ let radiusFinal = this.getRadius(radius, atom);
30293
+ radii.push(radiusFinal);
30294
+ }
30295
+ }
30296
+
30297
+ }
30133
30298
 
30134
- let prevAxis1 = new THREE.Vector3(), prevAxis2;
30135
- for (let i = 0, lim = pnts.length; i < lim; ++i) {
30136
- let r, idx = (i - 1) * axisDivInv;
30137
- if (i === 0) r = radii[0];
30138
- else {
30139
- if (idx % 1 === 0) r = radii[idx];
30140
- else {
30141
- let floored = Math.floor(idx);
30142
- let tmp = idx - floored;
30143
- r = radii[floored] * tmp + radii[floored + 1] * (1 - tmp);
30299
+ pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
30144
30300
  }
30301
+ pnts = []; colors = []; radii = []; prevone = []; nexttwo = [];
30302
+ firstAtom = atom;
30303
+ index = 0;
30145
30304
  }
30146
- let delta, axis1, axis2;
30147
- if (i < lim - 1) {
30148
- delta = pnts[i].clone().sub(pnts[i + 1]);
30149
- axis1 = new THREE.Vector3(0, -delta.z, delta.y).normalize().multiplyScalar(r);
30150
- axis2 = delta.clone().cross(axis1).normalize().multiplyScalar(r);
30151
- // let dir = 1, offset = 0;
30152
- if (prevAxis1.dot(axis1) < 0) {
30153
- axis1.negate(); axis2.negate(); //dir = -1;//offset = 2 * Math.PI / axisDiv;
30154
- }
30155
- prevAxis1 = axis1; prevAxis2 = axis2;
30156
- } else {
30157
- axis1 = prevAxis1; axis2 = prevAxis2;
30305
+
30306
+ pnts.push(atom.coord);
30307
+
30308
+ let radiusFinal;
30309
+ if(bCustom) {
30310
+ radiusFinal = this.getCustomtubesize(atom.structure + '_' + atom.chain + '_' + atom.resi);
30311
+ }
30312
+ else {
30313
+ radiusFinal = this.getRadius(radius, atom);
30158
30314
  }
30159
- for (let j = 0; j < circleDiv; ++j) {
30160
- let angle = 2 * Math.PI * circleDivInv * j; //* dir + offset;
30161
- let point = pnts[i].clone().add(axis1.clone().multiplyScalar(Math.cos(angle))).add(axis2.clone().multiplyScalar(Math.sin(angle)));
30162
- verticeArray[offset++] = point.x;
30163
- verticeArray[offset++] = point.y;
30164
- verticeArray[offset++] = point.z;
30165
30315
 
30166
- color = (i == colors.length - 1 && colors.length > 1) ? me.parasCls.thr(colors[colors.length - 2]) : me.parasCls.thr(colors[i]);
30167
- colorArray[offset2++] = color.r;
30168
- colorArray[offset2++] = color.g;
30169
- colorArray[offset2++] = color.b;
30316
+ // draw all atoms in tubes and assign zero radius when the residue is not coil
30317
+ if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
30318
+
30319
+ //radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
30320
+ radii.push(radiusFinal);
30321
+
30322
+ colors.push(atom.color);
30323
+ // the starting residue of a coil uses the color from the next residue to avoid using the color of the last helix/sheet residue
30324
+ if(index === 1) colors[colors.length - 2] = atom.color;
30325
+
30326
+ currentChain = atom.chain;
30327
+ currentResi = atom.resi;
30328
+
30329
+ let scale = 1.2;
30330
+ if(bHighlight === 2 && !atom.ssbegin) {
30331
+ ic.boxCls.createBox(atom, undefined, undefined, scale, undefined, bHighlight);
30170
30332
  }
30333
+
30334
+ ++index;
30335
+
30336
+ prevAtom = atom;
30171
30337
  }
30172
- let offsetTmp = 0, nComp = 3;
30173
- for (let i = 0, lim = pnts.length - 1; i < lim; ++i) {
30174
- let reg = 0;
30175
- //var r1 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv]).lengthSq();
30176
- //var r2 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv + 1]).lengthSq();
30177
- let pos = offsetTmp * nComp;
30178
- let point1 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
30179
- pos = (offsetTmp + circleDiv) * nComp;
30180
- let point2 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
30181
- pos = (offsetTmp + circleDiv + 1) * nComp;
30182
- let point3 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
30183
-
30184
- let r1 = point1.clone().sub(point2).lengthSq();
30185
- let r2 = point1.clone().sub(point3).lengthSq();
30186
- if (r1 > r2) { r1 = r2; reg = 1; } for (let j = 0; j < circleDiv; ++j) {
30187
- //geo.faces.push(new THREE.Face3(offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv, undefined, c));
30188
- //geo.faces.push(new THREE.Face3(offset + (j + 1) % circleDiv, offset + (j + reg) % circleDiv + circleDiv, offset + (j + reg + 1) % circleDiv + circleDiv, undefined, c));
30189
- //indexArray = indexArray.concat([offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv]);
30190
- indexArray[offset3++] = offsetTmp + j;
30191
- indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
30192
- indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
30193
-
30194
- //indexArray = indexArray.concat([offset + (j + 1) % circleDiv, offset + (j + reg) % circleDiv + circleDiv, offset + (j + reg + 1) % circleDiv + circleDiv]);
30195
- indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
30196
- indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
30197
- indexArray[offset3++] = offsetTmp + (j + reg + 1) % circleDiv + circleDiv;
30198
- }
30199
- offsetTmp += circleDiv;
30200
- }
30338
+ }
30201
30339
 
30202
- geo.setAttribute('position', new THREE.BufferAttribute(new Float32Array(verticeArray), nComp));
30203
- geo.setAttribute('color', new THREE.BufferAttribute(new Float32Array(colorArray), nComp));
30340
+ if(bHighlight !== 2) {
30341
+ pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
30342
+ }
30204
30343
 
30205
- geo.setIndex(new THREE.BufferAttribute(new Uint32Array(indexArray), 1));
30206
- //geo.setIndex(indexArray);
30344
+ for(let i = 0, il = pnts_colors_radii_prevone_nexttwo.length; i < il; ++i) {
30345
+ let pnts = pnts_colors_radii_prevone_nexttwo[i].pnts;
30346
+ let colors = pnts_colors_radii_prevone_nexttwo[i].colors;
30347
+ let radii = pnts_colors_radii_prevone_nexttwo[i].radii;
30348
+ let prevone = []; // = pnts_colors_radii_prevone_nexttwo[i].prevone;
30349
+ let nexttwo = []; // = pnts_colors_radii_prevone_nexttwo[i].nexttwo;
30207
30350
 
30208
- //geo.computeFaceNormals();
30209
- //geo.computeVertexNormals(false);
30210
- geo.computeVertexNormals();
30211
- /*
30351
+ this.createTubeSub(pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil);
30212
30352
  }
30213
- else {
30214
- let axisDiv = ic.axisDIV;
30215
30353
 
30216
- let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv, undefined, undefined, prevone, nexttwo);
30217
- // extend one residue
30218
- //var pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv, undefined, undefined, prevone, nexttwo, true);
30354
+ pnts_colors_radii_prevone_nexttwo = [];
30355
+ }
30356
+ */
30219
30357
 
30220
- _pnts = pnts_clrs[0];
30221
- colors = pnts_clrs[2];
30358
+ getCustomtubesize(resid) { let ic = this.icn3d; ic.icn3dui;
30359
+ let pos = resid.lastIndexOf('_');
30360
+ let resi = resid.substr(pos + 1);
30361
+ let chainid = resid.substr(0, pos);
30222
30362
 
30223
- let radius = ic.coilWidth;
30224
- segments = _pnts.length;
30225
- //radiusSegments = 8;
30226
- radiusSegments = 4; // save memory
30227
- let closed = false;
30363
+ let radiusFinal = (ic.queryresi2score[chainid] && ic.queryresi2score[chainid].hasOwnProperty(resi)) ? ic.queryresi2score[chainid][resi] * 0.01 : ic.coilWidth;
30228
30364
 
30229
- // when using radiusArray with modified three.js, the tube didn't work in picking
30230
- let geo = new THREE.TubeGeometry(
30231
- new THREE.CatmullRomCurve3(_pnts), // path
30232
- segments,
30233
- radius, //radiusArray, //radius,
30234
- radiusSegments,
30235
- closed
30236
- );
30365
+ return radiusFinal;
30366
+ };
30237
30367
 
30238
- //https://stemkoski.github.io/Three.js/Graphulus-Curve.html
30239
- let color, face, numberOfSides, vertexIndex;
30240
- // faces are indexed using characters
30241
- let faceIndices = [ 'a', 'b', 'c', 'd' ];
30368
+ // modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
30369
+ createTubeSub(_pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
30370
+ if(me.bNode) return;
30242
30371
 
30243
- // first, assign colors to vertices as desired
30244
- let prevColor, geoColors = {};
30245
- for ( let s = 0; s <= segments; s++ ) {
30246
- for ( let r = 0; r < radiusSegments; r++ )
30247
- {
30248
- vertexIndex = r + s * radiusSegments;
30249
- color = colors[s];
30250
- if(!color) color = prevColor;
30372
+ if (_pnts.length < 2) return;
30251
30373
 
30252
- geoColors[vertexIndex] = color; // use this array for convenience
30374
+ let circleDiv = ic.tubeDIV, axisDiv = ic.axisDIV;
30375
+ let circleDivInv = 1 / circleDiv, axisDivInv = 1 / axisDiv;
30376
+ //var geo = new THREE.Geometry();
30377
+ let geo = new THREE.BufferGeometry();
30378
+ let verticeArray = [], colorArray = [],indexArray = [], color;
30379
+ let offset = 0, offset2 = 0, offset3 = 0;
30253
30380
 
30254
- prevColor = color;
30255
- }
30256
- }
30381
+ let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv, undefined, undefined, prevone, nexttwo);
30257
30382
 
30258
- // copy the colors as necessary to the face's vertexColors array.
30259
- // after version r125, geo.faces is undefined for TubeGeometry
30260
- for ( let i = 0; geo.faces && i < geo.faces.length; i++ )
30261
- {
30262
- face = geo.faces[ i ];
30383
+ let pnts = pnts_clrs[0];
30384
+ colors = pnts_clrs[2];
30385
+
30386
+ let constRadiius;
30387
+ // a threshold to stop drawing the tube if it's less than this ratio of radius
30388
+ let thresholdRatio = 1; //0.9;
30389
+
30390
+ let prevAxis1 = new THREE.Vector3(), prevAxis2;
30391
+ for (let i = 0, lim = pnts.length; i < lim; ++i) {
30392
+ let r, idx = (i - 1) * axisDivInv;
30263
30393
 
30264
- numberOfSides = ( face instanceof THREE.Face3 ) ? 3 : 4;
30265
- for( let j = 0; j < numberOfSides; j++ )
30266
- {
30267
- vertexIndex = face[ faceIndices[ j ] ];
30268
- face.vertexColors[ j ] = geoColors[ vertexIndex ];
30394
+ if (i === 0) {
30395
+ r = radii[0];
30396
+ if(r > 0) constRadiius = r;
30397
+ }
30398
+ else {
30399
+ if (idx % 1 === 0) {
30400
+ r = radii[idx];
30401
+ if(r > 0) constRadiius = r;
30402
+ }
30403
+ else {
30404
+ let floored = Math.floor(idx);
30405
+ let tmp = idx - floored;
30406
+ // draw all atoms in tubes and assign zero radius when the residue is not coil
30407
+ // r = radii[floored] * tmp + radii[floored + 1] * (1 - tmp);
30408
+ r = radii[floored] * (1 - tmp) + radii[floored + 1] * tmp;
30409
+
30410
+ // a threshold to stop drawing the tube if it's less than this ratio of radius.
30411
+ // The extra bit of tube connects coil with strands or helices
30412
+ if(!bNonCoil) {
30413
+ if(r < thresholdRatio * constRadiius) {
30414
+ r = 0;
30415
+ }
30416
+ // else if(r < constRadiius) {
30417
+ // r *= 0.5; // use small radius for the connection between coild and sheets/helices
30418
+ // }
30419
+ }
30269
30420
  }
30270
30421
  }
30271
-
30272
- geo.computeFaceNormals();
30273
- geo.computeVertexNormals(false);
30422
+ let delta, axis1, axis2;
30423
+ if (i < lim - 1) {
30424
+ delta = pnts[i].clone().sub(pnts[i + 1]);
30425
+ axis1 = new THREE.Vector3(0, -delta.z, delta.y).normalize().multiplyScalar(r);
30426
+ axis2 = delta.clone().cross(axis1).normalize().multiplyScalar(r);
30427
+ // let dir = 1, offset = 0;
30428
+ if (prevAxis1.dot(axis1) < 0) {
30429
+ axis1.negate(); axis2.negate(); //dir = -1;//offset = 2 * Math.PI / axisDiv;
30430
+ }
30431
+ prevAxis1 = axis1; prevAxis2 = axis2;
30432
+ } else {
30433
+ axis1 = prevAxis1; axis2 = prevAxis2;
30434
+ }
30435
+ for (let j = 0; j < circleDiv; ++j) {
30436
+ let angle = 2 * Math.PI * circleDivInv * j; //* dir + offset;
30437
+ let point = pnts[i].clone().add(axis1.clone().multiplyScalar(Math.cos(angle))).add(axis2.clone().multiplyScalar(Math.sin(angle)));
30438
+ verticeArray[offset++] = point.x;
30439
+ verticeArray[offset++] = point.y;
30440
+ verticeArray[offset++] = point.z;
30441
+
30442
+ color = (i == colors.length - 1 && colors.length > 1) ? me.parasCls.thr(colors[colors.length - 2]) : me.parasCls.thr(colors[i]);
30443
+ colorArray[offset2++] = color.r;
30444
+ colorArray[offset2++] = color.g;
30445
+ colorArray[offset2++] = color.b;
30446
+ }
30447
+ }
30448
+ let offsetTmp = 0, nComp = 3;
30449
+ for (let i = 0, lim = pnts.length - 1; i < lim; ++i) {
30450
+ let reg = 0;
30451
+ //var r1 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv]).lengthSq();
30452
+ //var r2 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv + 1]).lengthSq();
30453
+ let pos = offsetTmp * nComp;
30454
+ let point1 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
30455
+ pos = (offsetTmp + circleDiv) * nComp;
30456
+ let point2 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
30457
+ pos = (offsetTmp + circleDiv + 1) * nComp;
30458
+ let point3 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
30459
+
30460
+ let r1 = point1.clone().sub(point2).lengthSq();
30461
+ let r2 = point1.clone().sub(point3).lengthSq();
30462
+ if (r1 > r2) { r1 = r2; reg = 1; } for (let j = 0; j < circleDiv; ++j) {
30463
+ //geo.faces.push(new THREE.Face3(offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv, undefined, c));
30464
+ //geo.faces.push(new THREE.Face3(offset + (j + 1) % circleDiv, offset + (j + reg) % circleDiv + circleDiv, offset + (j + reg + 1) % circleDiv + circleDiv, undefined, c));
30465
+ //indexArray = indexArray.concat([offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv]);
30466
+ indexArray[offset3++] = offsetTmp + j;
30467
+ indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
30468
+ indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
30469
+
30470
+ //indexArray = indexArray.concat([offset + (j + 1) % circleDiv, offset + (j + reg) % circleDiv + circleDiv, offset + (j + reg + 1) % circleDiv + circleDiv]);
30471
+ indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
30472
+ indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
30473
+ indexArray[offset3++] = offsetTmp + (j + reg + 1) % circleDiv + circleDiv;
30474
+ }
30475
+ offsetTmp += circleDiv;
30274
30476
  }
30275
- */
30477
+
30478
+ geo.setAttribute('position', new THREE.BufferAttribute(new Float32Array(verticeArray), nComp));
30479
+ geo.setAttribute('color', new THREE.BufferAttribute(new Float32Array(colorArray), nComp));
30480
+
30481
+ geo.setIndex(new THREE.BufferAttribute(new Uint32Array(indexArray), 1));
30482
+ //geo.setIndex(indexArray);
30483
+
30484
+ //geo.computeFaceNormals();
30485
+ //geo.computeVertexNormals(false);
30486
+ geo.computeVertexNormals();
30487
+
30276
30488
  let mesh;
30277
30489
  if(bHighlight === 2) {
30278
30490
  //mesh = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({ transparent: true, opacity: 0.5, specular: ic.frac, shininess: ic.shininess, emissive: ic.emissive, vertexColors: THREE.FaceColors, side: THREE.DoubleSide }));
@@ -30855,7 +31067,7 @@ class Axes {
30855
31067
  return cone;
30856
31068
  }
30857
31069
 
30858
- setPc1Axes() { let ic = this.icn3d, me = ic.icn3dui;
31070
+ setPc1Axes(bXAxis) { let ic = this.icn3d, me = ic.icn3dui;
30859
31071
  if(me.bNode) return;
30860
31072
 
30861
31073
  let atomHash = me.hashUtilsCls.intHash(ic.hAtoms, ic.dAtoms);
@@ -30936,6 +31148,11 @@ class Axes {
30936
31148
 
30937
31149
  let positionX = center.clone().add(vecX.normalize().multiplyScalar(maxD * 0.4));
30938
31150
 
31151
+ let prinXaxis = vecX.normalize();
31152
+ me.htmlCls.clickMenuCls.setLogCmd('Principle X-Axis: ' + prinXaxis.x.toFixed(3) + " " + prinXaxis.y.toFixed(3) + " " + prinXaxis.z.toFixed(3), false);
31153
+
31154
+ if(bXAxis) return prinXaxis;
31155
+
30939
31156
  let vecY = new THREE.Vector3(eigenRet.h2[0], eigenRet.h2[1], eigenRet.h2[2]);
30940
31157
  let positionY = center.clone().add(vecY.normalize().multiplyScalar(maxD * 0.3));
30941
31158
 
@@ -35154,6 +35371,9 @@ class ApplySymd {
35154
35371
 
35155
35372
  ic.cylinderCls.createCylinder(start, end, axisRadius, colorAxis, 0);
35156
35373
 
35374
+ let SymAxis = end.clone().sub(start).normalize();
35375
+ me.htmlCls.clickMenuCls.setLogCmd('Symmetry Axis: ' + SymAxis.x.toFixed(3) + " " + SymAxis.y.toFixed(3) + " " + SymAxis.z.toFixed(3), false);
35376
+
35157
35377
  if(ic.bAxisOnly) continue;
35158
35378
 
35159
35379
  if(symmetryType == 'C' || (symmetryType == 'D' && order == nSide) ) {
@@ -35310,87 +35530,87 @@ class ApplySymd {
35310
35530
  pointArray.push(end);
35311
35531
  }
35312
35532
  else ;
35313
- }
35314
35533
 
35315
- if(symmetryType == 'T') {
35316
- let pos1 = pointArray[0]; // pointArray: start, end, start, end, ...
35317
- ic.sphereCls.createSphereBase(pos1, colorPolygon, polygonRadius, 1.0, 0);
35534
+ if(symmetryType == 'T') {
35535
+ let pos1 = pointArray[0]; // pointArray: start, end, start, end, ...
35536
+ ic.sphereCls.createSphereBase(pos1, colorPolygon, polygonRadius, 1.0, 0);
35318
35537
 
35319
- let dist2 = pos1.distanceTo(pointArray[2]);
35320
- let dist3 = pos1.distanceTo(pointArray[3]);
35538
+ let dist2 = pos1.distanceTo(pointArray[2]);
35539
+ let dist3 = pos1.distanceTo(pointArray[3]);
35321
35540
 
35322
- let distSmall, posSel;
35323
- if(dist2 < dist3) {
35324
- distSmall = dist2;
35325
- posSel = pointArray[3];
35326
- }
35327
- else {
35328
- distSmall = dist3;
35329
- posSel = pointArray[2];
35330
- }
35541
+ let distSmall, posSel;
35542
+ if(dist2 < dist3) {
35543
+ distSmall = dist2;
35544
+ posSel = pointArray[3];
35545
+ }
35546
+ else {
35547
+ distSmall = dist3;
35548
+ posSel = pointArray[2];
35549
+ }
35331
35550
 
35332
- ic.sphereCls.createSphereBase(posSel, colorPolygon, polygonRadius, 1.0, 0);
35333
- ic.cylinderCls.createCylinder(pos1, posSel, polygonRadius, colorPolygon, 0);
35551
+ ic.sphereCls.createSphereBase(posSel, colorPolygon, polygonRadius, 1.0, 0);
35552
+ ic.cylinderCls.createCylinder(pos1, posSel, polygonRadius, colorPolygon, 0);
35334
35553
 
35335
- let iPrev;
35336
- for(let i = 4, il = pointArray.length; i < il; ++i) {
35337
- let pos2 = pointArray[i];
35554
+ let iPrev;
35555
+ for(let i = 4, il = pointArray.length; i < il; ++i) {
35556
+ let pos2 = pointArray[i];
35338
35557
 
35339
- let dist = pos1.distanceTo(pos2);
35340
- if(dist > distSmall) {
35341
- ic.sphereCls.createSphereBase(pos2, colorPolygon, polygonRadius, 1.0, 0);
35342
- ic.cylinderCls.createCylinder(pos1, pos2, polygonRadius, colorPolygon, 0);
35558
+ let dist = pos1.distanceTo(pos2);
35559
+ if(dist > distSmall) {
35560
+ ic.sphereCls.createSphereBase(pos2, colorPolygon, polygonRadius, 1.0, 0);
35561
+ ic.cylinderCls.createCylinder(pos1, pos2, polygonRadius, colorPolygon, 0);
35343
35562
 
35344
- ic.cylinderCls.createCylinder(posSel, pos2, polygonRadius, colorPolygon, 0);
35345
- if(iPrev !== undefined) {
35346
- ic.cylinderCls.createCylinder(pointArray[iPrev], pos2, polygonRadius, colorPolygon, 0);
35347
- }
35563
+ ic.cylinderCls.createCylinder(posSel, pos2, polygonRadius, colorPolygon, 0);
35564
+ if(iPrev !== undefined) {
35565
+ ic.cylinderCls.createCylinder(pointArray[iPrev], pos2, polygonRadius, colorPolygon, 0);
35566
+ }
35348
35567
 
35349
- iPrev = i;
35568
+ iPrev = i;
35569
+ }
35350
35570
  }
35351
35571
  }
35352
- }
35353
- else if(symmetryType == 'O') {
35354
- for(let i = 0, il = pointArray.length; i < il; i += 2) {
35355
- let pos1 = pointArray[i];
35356
- let pos2 = pointArray[i+1];
35357
- ic.sphereCls.createSphereBase(pos1, colorPolygon, polygonRadius, 1.0, 0);
35358
- ic.sphereCls.createSphereBase(pos2, colorPolygon, polygonRadius, 1.0, 0);
35359
- for(let j = i + 2, jl = pointArray.length; j < jl; ++j) {
35360
- let pos3 = pointArray[j];
35361
- ic.sphereCls.createSphereBase(pos3, colorPolygon, polygonRadius, 1.0, 0);
35362
- ic.cylinderCls.createCylinder(pos1, pos3, polygonRadius, colorPolygon, 0);
35363
- ic.cylinderCls.createCylinder(pos2, pos3, polygonRadius, colorPolygon, 0);
35572
+ else if(symmetryType == 'O') {
35573
+ for(let i = 0, il = pointArray.length; i < il; i += 2) {
35574
+ let pos1 = pointArray[i];
35575
+ let pos2 = pointArray[i+1];
35576
+ ic.sphereCls.createSphereBase(pos1, colorPolygon, polygonRadius, 1.0, 0);
35577
+ ic.sphereCls.createSphereBase(pos2, colorPolygon, polygonRadius, 1.0, 0);
35578
+ for(let j = i + 2, jl = pointArray.length; j < jl; ++j) {
35579
+ let pos3 = pointArray[j];
35580
+ ic.sphereCls.createSphereBase(pos3, colorPolygon, polygonRadius, 1.0, 0);
35581
+ ic.cylinderCls.createCylinder(pos1, pos3, polygonRadius, colorPolygon, 0);
35582
+ ic.cylinderCls.createCylinder(pos2, pos3, polygonRadius, colorPolygon, 0);
35583
+ }
35364
35584
  }
35365
35585
  }
35366
- }
35367
- else if(symmetryType == 'I') {
35368
- for(let i = 0, il = pointArray.length; i < il; i += 2) {
35369
- let pos1 = pointArray[i];
35370
- let pos2 = pointArray[i+1];
35371
- ic.sphereCls.createSphereBase(pos1, colorPolygon, polygonRadius, 1.0, 0);
35372
- ic.sphereCls.createSphereBase(pos2, colorPolygon, polygonRadius, 1.0, 0);
35373
- for(let j = i + 2, jl = pointArray.length; j < jl; j += 2) {
35374
- let pos3 = pointArray[j];
35375
- let pos4 = pointArray[j+1];
35586
+ else if(symmetryType == 'I') {
35587
+ for(let i = 0, il = pointArray.length; i < il; i += 2) {
35588
+ let pos1 = pointArray[i];
35589
+ let pos2 = pointArray[i+1];
35590
+ ic.sphereCls.createSphereBase(pos1, colorPolygon, polygonRadius, 1.0, 0);
35591
+ ic.sphereCls.createSphereBase(pos2, colorPolygon, polygonRadius, 1.0, 0);
35592
+ for(let j = i + 2, jl = pointArray.length; j < jl; j += 2) {
35593
+ let pos3 = pointArray[j];
35594
+ let pos4 = pointArray[j+1];
35376
35595
 
35377
- let dist3 = pos1.distanceTo(pos3);
35378
- let dist4 = pos1.distanceTo(pos4);
35596
+ let dist3 = pos1.distanceTo(pos3);
35597
+ let dist4 = pos1.distanceTo(pos4);
35379
35598
 
35380
- let pos1Sel, pos2Sel;
35381
- if(dist3 < dist4) {
35382
- pos1Sel = pos3;
35383
- pos2Sel = pos4;
35384
- }
35385
- else {
35386
- pos1Sel = pos4;
35387
- pos2Sel = pos3;
35388
- }
35599
+ let pos1Sel, pos2Sel;
35600
+ if(dist3 < dist4) {
35601
+ pos1Sel = pos3;
35602
+ pos2Sel = pos4;
35603
+ }
35604
+ else {
35605
+ pos1Sel = pos4;
35606
+ pos2Sel = pos3;
35607
+ }
35389
35608
 
35390
- ic.sphereCls.createSphereBase(pos1Sel, colorPolygon, polygonRadius, 1.0, 0);
35391
- ic.sphereCls.createSphereBase(pos2Sel, colorPolygon, polygonRadius, 1.0, 0);
35392
- ic.cylinderCls.createCylinder(pos1, pos1Sel, polygonRadius, colorPolygon, 0);
35393
- ic.cylinderCls.createCylinder(pos2, pos2Sel, polygonRadius, colorPolygon, 0);
35609
+ ic.sphereCls.createSphereBase(pos1Sel, colorPolygon, polygonRadius, 1.0, 0);
35610
+ ic.sphereCls.createSphereBase(pos2Sel, colorPolygon, polygonRadius, 1.0, 0);
35611
+ ic.cylinderCls.createCylinder(pos1, pos1Sel, polygonRadius, colorPolygon, 0);
35612
+ ic.cylinderCls.createCylinder(pos2, pos2Sel, polygonRadius, colorPolygon, 0);
35613
+ }
35394
35614
  }
35395
35615
  }
35396
35616
  }
@@ -45227,7 +45447,7 @@ class AddTrack {
45227
45447
 
45228
45448
  }
45229
45449
 
45230
- showNewTrack(chnid, title, text, cssColorArray, inTarget2queryHash, type, color, bMsa, fromArray, toArray, seqStartLen, exonArray) { let ic = this.icn3d, me = ic.icn3dui;
45450
+ showNewTrack(chnid, title, text, cssColorArray, inTarget2queryHash, type, color, bMsa, fromArray, toArray, seqStartLen, exonArray, offsetArray) { let ic = this.icn3d, me = ic.icn3dui;
45231
45451
  //if(ic.customTracks[chnid] === undefined) {
45232
45452
  // ic.customTracks[chnid] = {}
45233
45453
  //}
@@ -45445,14 +45665,16 @@ class AddTrack {
45445
45665
 
45446
45666
  if(fromArray !== undefined) {
45447
45667
  htmlTmp2 = '';
45448
- let fromArray2 = [], toArray2 = [];
45668
+ let fromArray2 = [], toArray2 = [], offsetArray2 = [];
45449
45669
  for(let i = 0, il = fromArray.length; i < il; ++i) {
45450
45670
  fromArray2.push(fromArray[i]);
45671
+ offsetArray2.push(offsetArray[i]);
45451
45672
 
45452
45673
  for(let j = parseInt(fromArray[i]); j <= parseInt(toArray[i]); ++j) {
45453
45674
  if(ic.targetGapHash !== undefined && ic.targetGapHash.hasOwnProperty(j)) {
45454
45675
  toArray2.push(j - 1);
45455
45676
  fromArray2.push(j);
45677
+ offsetArray2.push(offsetArray[i]);
45456
45678
  }
45457
45679
  }
45458
45680
 
@@ -45486,6 +45708,7 @@ class AddTrack {
45486
45708
  // determine how this range sits in the exon ranges in exonArray
45487
45709
  let startExon, endExon;
45488
45710
 
45711
+ let offset = offsetArray2[i];
45489
45712
  cnt = toArray[i] - fromArray[i] + 1;
45490
45713
  let from = prevCntTotal, to = prevCntTotal + cnt - 1;
45491
45714
 
@@ -45514,26 +45737,26 @@ class AddTrack {
45514
45737
  endColorStr = this.getExonColor(startExon.rangeStart, startExon.rangeEnd, to);
45515
45738
 
45516
45739
  colorGradient = startColorStr + ' 0%, #FFF 50%, ' + endColorStr + ' 100%';
45517
- htmlTmp2 += this.getExonHtml(startExon.exonIndex, colorGradient, startExon.from, endExon.to, startExon.genomeRange, chnid, simpTitle);
45740
+ htmlTmp2 += this.getExonHtml(startExon.exonIndex, colorGradient, startExon.from, endExon.to, startExon.genomeRange, chnid, simpTitle, offset);
45518
45741
  }
45519
45742
  else {
45520
45743
  if(startExon) {
45521
45744
  startColorStr = this.getExonColor(startExon.rangeStart, startExon.rangeEnd, from);
45522
45745
 
45523
45746
  colorGradient = startColorStr + ' 0%, #FFF 50%, #00F 100%';
45524
- htmlTmp2 += this.getExonHtml(startExon.exonIndex, colorGradient, startExon.from, startExon.rangeEnd, startExon.genomeRange, chnid, simpTitle);
45747
+ htmlTmp2 += this.getExonHtml(startExon.exonIndex, colorGradient, startExon.from, startExon.rangeEnd, startExon.genomeRange, chnid, simpTitle, offset);
45525
45748
  }
45526
45749
 
45527
45750
  if(startExon && endExon) {
45528
45751
  for(let j = startExon.exonIndex + 1; j < endExon.exonIndex; ++j) {
45529
45752
  colorGradient = '#F00 0%, #FFF 50%, #00F 100%';
45530
- htmlTmp2 += this.getExonHtml(j, colorGradient, exonArray[j].resStart, exonArray[j].resEnd, exonArray[j].genomeRange, chnid, simpTitle);
45753
+ htmlTmp2 += this.getExonHtml(j, colorGradient, exonArray[j].resStart, exonArray[j].resEnd, exonArray[j].genomeRange, chnid, simpTitle, offset);
45531
45754
  }
45532
45755
 
45533
45756
  endColorStr = this.getExonColor(endExon.rangeStart, endExon.rangeEnd, to);
45534
45757
 
45535
45758
  colorGradient = '#F00 0%, #FFF 50%, ' + endColorStr + ' 100%';
45536
- htmlTmp2 += this.getExonHtml(endExon.exonIndex, colorGradient, endExon.rangeStart, endExon.to, endExon.genomeRange, chnid, simpTitle);
45759
+ htmlTmp2 += this.getExonHtml(endExon.exonIndex, colorGradient, endExon.rangeStart, endExon.to, endExon.genomeRange, chnid, simpTitle, offset);
45537
45760
  }
45538
45761
  }
45539
45762
 
@@ -45567,9 +45790,8 @@ class AddTrack {
45567
45790
  }
45568
45791
  }
45569
45792
 
45570
- getExonHtml(exonIndex, colorGradient, from, to, genomeRange, chainid, simpTitle) { let ic = this.icn3d; ic.icn3dui;
45571
- // 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 + ', Exon ' + (exonIndex + 1) + '" title="Exon ' + (exonIndex + 1) + ': ' + genomeRange + ' genomic interval" anno="sequence" chain="' + chainid + '"><div style="height: 12px; border: 1px solid #000; background: linear-gradient(to right, ' + colorGradient + ');"></div></div>';
45572
- 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>';
45793
+ getExonHtml(exonIndex, colorGradient, from, to, genomeRange, chainid, simpTitle, offset) { let ic = this.icn3d; ic.icn3dui;
45794
+ 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>';
45573
45795
  }
45574
45796
 
45575
45797
  getExonColor(start, end, pos) { let ic = this.icn3d; ic.icn3dui;
@@ -46310,7 +46532,7 @@ class AddTrack {
46310
46532
  let targetId = 'genomeRes';
46311
46533
 
46312
46534
  let acc2index = {};
46313
-
46535
+
46314
46536
  for(let index = 0, indexl = accArray.length; index < indexl; ++index) {
46315
46537
  let acc = accArray[index];
46316
46538
 
@@ -46395,22 +46617,24 @@ class AddTrack {
46395
46617
  trackSeqArrayFinal[i] = '';
46396
46618
  }
46397
46619
 
46398
- for(let j = 0, jl = trackSeqArray[maxIndex].length; j < jl; ++j) {
46399
- let seq = trackSeqArray[maxIndex][j];
46620
+ if(trackSeqArray[maxIndex]) {
46621
+ for(let j = 0, jl = trackSeqArray[maxIndex].length; j < jl; ++j) {
46622
+ let seq = trackSeqArray[maxIndex][j];
46400
46623
 
46401
- let bExon = (seq != '-') ? true : false;
46402
- if(!bExon) {
46403
- for(let i = 0, il = trackSeqArray.length; i < il; ++i) {
46404
- if(trackSeqArray[i][j] != '-') {
46405
- bExon = true;
46406
- break;
46624
+ let bExon = (seq != '-') ? true : false;
46625
+ if(!bExon) {
46626
+ for(let i = 0, il = trackSeqArray.length; i < il; ++i) {
46627
+ if(trackSeqArray[i][j] != '-') {
46628
+ bExon = true;
46629
+ break;
46630
+ }
46407
46631
  }
46408
46632
  }
46409
- }
46410
-
46411
- if(bExon) {
46412
- for(let i = 0, il = trackSeqArray.length; i < il; ++i) {
46413
- trackSeqArrayFinal[i] += trackSeqArray[i][j];
46633
+
46634
+ if(bExon) {
46635
+ for(let i = 0, il = trackSeqArray.length; i < il; ++i) {
46636
+ trackSeqArrayFinal[i] += trackSeqArray[i][j];
46637
+ }
46414
46638
  }
46415
46639
  }
46416
46640
  }
@@ -46481,7 +46705,9 @@ class AddTrack {
46481
46705
  ic.maxAnnoLength = ic.maxAnnoLengthOri + ic.seqStartLen[chainid] + ic.seqEndLen[chainid];
46482
46706
  }
46483
46707
 
46484
- await ic.annotationCls.resetAnnoAll();
46708
+ // do not remove other tracks
46709
+ // await ic.annotationCls.resetAnnoAll();
46710
+ await ic.showAnnoCls.processSeqData(ic.chainid_seq);
46485
46711
 
46486
46712
  let targetGapHashStr = '';
46487
46713
  let cntTmp = 0;
@@ -46512,6 +46738,7 @@ class AddTrack {
46512
46738
  let fromArray = [], toArray = [];
46513
46739
  let bFound = false;
46514
46740
  let seqStartLen = 0;
46741
+ let offset = 0, offsetArray = [];
46515
46742
  // for(let k = seqStart; k <= seqEnd; ++k) {
46516
46743
  for(let k = 0; k < seqLength; ++k) {
46517
46744
  //if(seqFirst[k] == '-') continue;
@@ -46520,19 +46747,29 @@ class AddTrack {
46520
46747
 
46521
46748
  resn = trackSeqArray[j][k];
46522
46749
 
46750
+ if(resn != '-') {
46751
+ if(!bFound) {
46752
+ seqStartLen = k;
46753
+ bFound = true;
46754
+
46755
+ offset = ic.startposGiSeq - ic.seqStartLen[chainid] + seqStartLen;
46756
+ }
46757
+ }
46758
+
46523
46759
  if(prevResn == '-' && resn != '-') {
46524
46760
  fromArray.push(k);
46761
+ offsetArray.push(offset);
46525
46762
  }
46526
46763
 
46527
46764
  if(prevResn != '-' && resn == '-') {
46528
46765
  toArray.push(k - 1);
46529
46766
  }
46530
46767
 
46531
- if(resn != '-') {
46532
- if(!bFound) {
46533
- seqStartLen = k;
46534
- bFound = true;
46535
- }
46768
+ // use "offset" to adjut the residue numbers, e.g., P20138
46769
+ // some isoforms starts residues before the first residue in the template sequence
46770
+ if(k >= ic.seqStartLen[chainid]) {
46771
+ if(seqFirst[k] == '-') offset--;
46772
+ if(resn == '-') offset++;
46536
46773
  }
46537
46774
 
46538
46775
  text += resn; //ic.giSeq[chainid][i];
@@ -46553,7 +46790,7 @@ class AddTrack {
46553
46790
  let title =(trackTitleArray[j].length < 20) ? trackTitleArray[j] : trackTitleArray[j].substr(0, 20) + '...';
46554
46791
  let bMsa = true;
46555
46792
  let exonArray = (acc2exons) ? acc2exons[trackTitleArray[j]] : undefined;
46556
- this.showNewTrack(chainid, title, text, undefined, undefined, type, undefined, bMsa, fromArray, toArray, seqStartLen, exonArray);
46793
+ this.showNewTrack(chainid, title, text, undefined, undefined, type, undefined, bMsa, fromArray, toArray, seqStartLen, exonArray, offsetArray);
46557
46794
  }
46558
46795
 
46559
46796
  // update exon color
@@ -46648,7 +46885,7 @@ class AddTrack {
46648
46885
 
46649
46886
  let type = 'identity';
46650
46887
 
46651
- await thisClass.addExonTracks(chainid, geneid, startpos, type);
46888
+ await this.addExonTracks(chainid, geneid, startpos, type);
46652
46889
  }
46653
46890
 
46654
46891
  async addExonTracks(chainid, geneid, startpos, type) { let ic = this.icn3d, me = ic.icn3dui;
@@ -46683,13 +46920,12 @@ class AddTrack {
46683
46920
  let cnt = (j == jl - 1) ? itemArray[2] - 3 : itemArray[2]; // The last one is stop codeon
46684
46921
  cntTotal += cnt;
46685
46922
 
46686
- let resStart = parseInt(prevCntTotal/3.0 + 0.5); // 0-based
46687
- let resEnd = parseInt(cntTotal/3.0 + 0.5) - 1; // 0-based
46923
+ let resStart = parseInt((prevCntTotal+2)/3.0); // 0-based
46924
+ let resEnd = parseInt((cntTotal+2)/3.0) - 1; // 0-based
46688
46925
 
46689
- let genResStart = parseInt(itemArray[0] / 3.0 + 0.5);
46690
-
46691
- //let genResEnd = parseInt(itemArray[1] / 3.0 + 0.5); // some difference due to round
46692
- let genResEnd = genResStart + ic.exonOrder * (resEnd - resStart);
46926
+ let genResEnd = parseInt((itemArray[1]+2) / 3.0);
46927
+ // let genResStart = parseInt((itemArray[0]+2) / 3.0); // some difference due to round
46928
+ let genResStart = genResEnd - ic.exonOrder * (resEnd - resStart);
46693
46929
 
46694
46930
  rangeArray.push({genomeRange: genomeRange, genResStart: genResStart, genResEnd: genResEnd, resStart: resStart, resEnd: resEnd});
46695
46931
 
@@ -46743,7 +46979,7 @@ class AddTrack {
46743
46979
 
46744
46980
  let ALen = trackSeqArray.length;
46745
46981
 
46746
- while (i < A.length && j < B.length) {
46982
+ while (A && B && i < A.length && j < B.length) {
46747
46983
  if(A[i] != B[j]) {
46748
46984
  if(A[i] == '-') {
46749
46985
  // insert "-" in B
@@ -53362,8 +53598,10 @@ class ChainalignParser {
53362
53598
  //$.when(ic.pdbParserCls.applyCommandDssp(true)).then(function() {
53363
53599
  await ic.pdbParserCls.applyCommandDssp(true);
53364
53600
 
53601
+ // original version =============
53365
53602
  // align PDB chains
53366
53603
  for(let index in ic.pdbChainIndexHash) {
53604
+ //ic.pdbChainIndexHash[index] = mmdbid_q_tmp + "_" + ic.chain_q + "_" + ic.mmdbid_t + "_" + ic.chain_t;
53367
53605
  let idArray = ic.pdbChainIndexHash[index].split('_');
53368
53606
  mmdbid_q = idArray[0];
53369
53607
  idArray[1];
@@ -53378,25 +53616,49 @@ class ChainalignParser {
53378
53616
  let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
53379
53617
  let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
53380
53618
 
53619
+ let resRangeArray = (me.cfg.resrange) ? me.cfg.resrange.split(' | ') : [];
53620
+
53381
53621
  for(let index in ic.afChainIndexHash) {
53382
53622
  let idArray = ic.afChainIndexHash[index].split('_');
53383
53623
  mmdbid_q = idArray[0];
53384
53624
  let chain_q = idArray[1];
53625
+ let chainid_q = mmdbid_q + '_' + chain_q;
53626
+
53385
53627
  mmdbid_t = idArray[2];
53386
53628
  let chain_t = idArray[3];
53629
+ let chainid_t = mmdbid_t + '_' + chain_t;
53630
+
53631
+ let atomSet_t = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[0].split(','), chainid_t).hAtoms : ic.chains[chainid_t];
53632
+ let atomSet_q = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[index].split(','), chainid_q).hAtoms : ic.chains[chainid_q];
53633
+ // end of original version =============
53634
+
53635
+ /*
53636
+ // new version to be done for VASTsrv ==============
53637
+ // dynamically align pairs in all chainids
53638
+ let ajaxArray = [], indexArray = [], struArray = [];
53639
+ let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
53640
+ let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
53641
+
53642
+ let resRangeArray = (me.cfg.resrange) ? me.cfg.resrange.split(' | ') : [];
53643
+
53644
+ // dynamically align pairs in all chainids
53645
+ let atomSet_t = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[0].split(','), chainidArray[0]).hAtoms : ic.chains[chainidArray[0]];
53646
+ for(let index = 1, indexl = chainidArray.length; index < indexl; ++index) {
53647
+ let atomSet_q = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[index].split(','), chainidArray[index]).hAtoms : ic.chains[chainidArray[index]];
53648
+ // end of new version to be done for VASTsrv ==============
53649
+ */
53387
53650
 
53388
53651
  let alignAjax;
53389
53652
  if(me.cfg.aligntool != 'tmalign') {
53390
- let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(ic.chains[mmdbid_q + '_' + chain_q]);
53391
- let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(ic.chains[mmdbid_t + '_' + chain_t]);
53653
+ let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(atomSet_q);
53654
+ let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(atomSet_t);
53392
53655
 
53393
53656
  let dataObj = {'domains1': jsonStr_q, 'domains2': jsonStr_t};
53394
53657
  alignAjax = me.getAjaxPostPromise(urlalign, dataObj);
53395
53658
  }
53396
53659
  else {
53397
- let pdb_query = ic.saveFileCls.getAtomPDB(ic.chains[mmdbid_q + '_' + chain_q]);
53398
-
53399
- let pdb_target= ic.saveFileCls.getAtomPDB(ic.chains[mmdbid_t + '_' + chain_t]);
53660
+ let pdb_query = ic.saveFileCls.getAtomPDB(atomSet_q);
53661
+ let pdb_target= ic.saveFileCls.getAtomPDB(atomSet_t);
53400
53662
 
53401
53663
  let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target};
53402
53664
  alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
@@ -53799,7 +54061,7 @@ class ChainalignParser {
53799
54061
  return chainidArray;
53800
54062
  }
53801
54063
 
53802
- async downloadChainalignment(chainalign, resnum, resdef) { let ic = this.icn3d, me = ic.icn3dui;
54064
+ async downloadChainalignment(chainalign) { let ic = this.icn3d, me = ic.icn3dui;
53803
54065
  let thisClass = this;
53804
54066
 
53805
54067
  ic.opts['proteins'] = 'c alpha trace';
@@ -54076,7 +54338,7 @@ class ChainalignParser {
54076
54338
  async loadOpmDataForChainalign(data1, data2, chainidArray, mmdbidArray) { let ic = this.icn3d, me = ic.icn3dui;
54077
54339
  let thisClass = this;
54078
54340
 
54079
- if(me.cfg.resnum || me.cfg.resdef) {
54341
+ if(me.cfg.resnum || me.cfg.resdef || me.cfg.resrange) {
54080
54342
  if(!ic.bCommandLoad) ic.init(); // remove all previously loaded data
54081
54343
  await this.downloadChainalignmentPart2(data1, data2, undefined, chainidArray);
54082
54344
 
@@ -58552,13 +58814,7 @@ class RealignParser {
58552
58814
 
58553
58815
  let allPromise = Promise.allSettled(ajaxArray);
58554
58816
  // try {
58555
- // let dataArray = await allPromise;
58556
-
58557
- let startDate = new Date();
58558
58817
  let dataArray = await allPromise;
58559
- let endDate = new Date();
58560
- let miliseconds = (endDate.getTime() - startDate.getTime());
58561
- console.log("vastdyn time: " + miliseconds + " miliseconds");
58562
58818
 
58563
58819
  ic.qt_start_end = []; // reset the alignment
58564
58820
  await ic.chainalignParserCls.downloadChainalignmentPart2bRealign(dataArray, chainidPairArray, bReverse);
@@ -58650,6 +58906,8 @@ class RealignParser {
58650
58906
  async realignChainOnSeqAlign(chainresiCalphaHash2, chainidArray, bRealign, bPredefined) { let ic = this.icn3d, me = ic.icn3dui;
58651
58907
  let thisClass = this;
58652
58908
 
58909
+ me.cfg.aligntool = 'seqalign';
58910
+
58653
58911
  //bRealign: realign based on seq alignment
58654
58912
  //bPredefined: chain alignment with predefined matching residues
58655
58913
 
@@ -58957,6 +59215,7 @@ class DensityCifParser {
58957
59215
 
58958
59216
  //https://www.ebi.ac.uk/pdbe/densities/doc.html
58959
59217
  if(type == '2fofc' || type == 'fofc') {
59218
+ detail = 0;
58960
59219
  url = "https://www.ebi.ac.uk/pdbe/densities/x-ray/" + pdbid.toLowerCase() + "/cell?detail=" + detail;
58961
59220
  }
58962
59221
  else if(type == 'em') {
@@ -58997,6 +59256,39 @@ class DensityCifParser {
58997
59256
  }
58998
59257
  }
58999
59258
 
59259
+ async densityCifParserBase(url, type, sigma, location, bInputSigma) { let ic = this.icn3d, me = ic.icn3dui;
59260
+ let thisClass = this;
59261
+
59262
+ //https://stackoverflow.com/questions/33902299/using-jquery-ajax-to-download-a-binary-file
59263
+ if(type == '2fofc' && ic.bAjax2fofc) {
59264
+ ic.mapData.sigma2 = sigma;
59265
+ ic.setOptionCls.setOption('map', type);
59266
+ }
59267
+ else if(type == 'fofc' && ic.bAjaxfofc) {
59268
+ ic.mapData.sigma = sigma;
59269
+ ic.setOptionCls.setOption('map', type);
59270
+ }
59271
+ else {
59272
+ let arrayBuffer = await me.getXMLHttpRqstPromise(url, 'GET', 'arraybuffer', type);
59273
+
59274
+ thisClass.parseChannels(arrayBuffer, type, sigma);
59275
+
59276
+ if(type == '2fofc' || type == 'fofc') {
59277
+ ic.bAjax2fofc = true;
59278
+ ic.bAjaxfofc = true;
59279
+
59280
+ ic.setOptionCls.setOption('map', type);
59281
+ }
59282
+ else if(type == 'em') {
59283
+ ic.bAjaxEm = true;
59284
+
59285
+ ic.setOptionCls.setOption('emmap', type);
59286
+ }
59287
+ }
59288
+
59289
+ // return sigma;
59290
+ }
59291
+
59000
59292
  parseChannels(densitydata, type, sigma) { let ic = this.icn3d; ic.icn3dui;
59001
59293
  let cif = this.BinaryParse(densitydata);
59002
59294
 
@@ -60847,9 +61139,11 @@ class LoadAtomData {
60847
61139
  serial2structure[j] = pdbidTmp.toString();
60848
61140
  mmdbid2pdbid[mmdbidTmp] = pdbidTmp;
60849
61141
  }
60850
-
61142
+
60851
61143
  for(let j = 0, jl = structure.molecules.length; j < jl; ++j) {
60852
61144
  let chain = structure.molecules[j].chain;
61145
+ chain = chain.replace(/_/g, ''); // change "A_1" to "A1"
61146
+
60853
61147
  let kind = structure.molecules[j].kind;
60854
61148
  let title = structure.molecules[j].name;
60855
61149
  //var seq = structure.molecules[j].sequence;
@@ -61842,7 +62136,9 @@ class SetSeqAlign {
61842
62136
 
61843
62137
  let resid = chainid + '_' + resi;
61844
62138
  let resn = ic.residueId2Name[resid];
61845
- if(!resn) resn = '?';
62139
+ if(!resn) {
62140
+ resn = '?';
62141
+ }
61846
62142
 
61847
62143
  return resn;
61848
62144
  }
@@ -63985,7 +64281,7 @@ class LoadCIF {
63985
64281
 
63986
64282
  let bFirstAtom = true;
63987
64283
 
63988
- let cifArray = bcifData.split('ENDMDL\n');
64284
+ let cifArray = (bText) ? bcifData.split('ENDMDL\n') : [bcifData];
63989
64285
 
63990
64286
  for(let index = 0, indexl = cifArray.length; index < indexl; ++index) {
63991
64287
  ++moleculeNum;
@@ -66554,7 +66850,21 @@ class ApplyCommand {
66554
66850
  let nameArray2 = setNameArray[1].split(',');
66555
66851
 
66556
66852
  ic.analysisCls.measureDistManySets(nameArray, nameArray2);
66557
- me.htmlCls.dialogCls.openDlg('dl_disttable', 'Distance among the sets');
66853
+ me.htmlCls.dialogCls.openDlg('dl_disttable', 'Distances among the sets');
66854
+ }
66855
+ }
66856
+ }
66857
+ else if(commandOri.indexOf('angletable') == 0) {
66858
+ let paraArray = commandOri.split(' | ');
66859
+ if(paraArray.length == 2) {
66860
+ let setNameArray = paraArray[1].split(' ');
66861
+
66862
+ if(setNameArray.length == 2) {
66863
+ let nameArray = setNameArray[0].split(',');
66864
+ let nameArray2 = setNameArray[1].split(',');
66865
+
66866
+ ic.analysisCls.measureAngleManySets(nameArray, nameArray2);
66867
+ me.htmlCls.dialogCls.openDlg('dl_angletable', 'Angles among the sets');
66558
66868
  }
66559
66869
  }
66560
66870
  }
@@ -66962,6 +67272,16 @@ class ApplyCommand {
66962
67272
  ic.transformCls.rotateCoord(ic.hAtoms, mArrayFloat);
66963
67273
  ic.drawCls.draw();
66964
67274
  }
67275
+ else if(command.indexOf('set dssp sse') == 0) {
67276
+ await ic.pdbParserCls.applyCommandDssp();
67277
+ ic.bResetAnno = true;
67278
+
67279
+ if(ic.bAnnoShown) {
67280
+ await ic.showAnnoCls.showAnnotations();
67281
+
67282
+ ic.annotationCls.resetAnnoTabAll();
67283
+ }
67284
+ }
66965
67285
 
66966
67286
  // special, select ==========
66967
67287
 
@@ -68162,9 +68482,9 @@ class SelectCollections {
68162
68482
  'chemicals': {},
68163
68483
  'ions': {},
68164
68484
  'water': {},
68165
- 'structures': {}, // getSSExpandedAtoms
68485
+ 'structures': {},
68166
68486
  'ssbondpnts': {},
68167
- 'residues': {}, // getSSExpandedAtoms
68487
+ 'residues': {},
68168
68488
  'chains': {},
68169
68489
  'chainsSeq': {}, //Sequences and Annotation
68170
68490
  'defNames2Atoms': {},
@@ -68213,9 +68533,9 @@ class SelectCollections {
68213
68533
  'chemicals': ic.chemicals,
68214
68534
  'ions': ic.ions,
68215
68535
  'water': ic.water,
68216
- 'structures': ic.structures, // getSSExpandedAtoms
68536
+ 'structures': ic.structures,
68217
68537
  'ssbondpnts': ic.ssbondpnts,
68218
- 'residues': ic.residues, // getSSExpandedAtoms
68538
+ 'residues': ic.residues,
68219
68539
  'chains': ic.chains,
68220
68540
  'chainsSeq': ic.chainsSeq, //Sequences and Annotation
68221
68541
  'defNames2Atoms': ic.defNames2Atoms,
@@ -68229,9 +68549,9 @@ class SelectCollections {
68229
68549
  'chemicals': thisClass.dictionaryDifference(ic.allData['prev']['chemicals'], ic.chemicals),
68230
68550
  'ions': thisClass.dictionaryDifference(ic.allData['prev']['ions'], ic.ions),
68231
68551
  'water': thisClass.dictionaryDifference(ic.allData['prev']['water'], ic.water),
68232
- 'structures': thisClass.dictionaryDifference(ic.allData['prev']['structures'], ic.structures), // getSSExpandedAtoms
68552
+ 'structures': thisClass.dictionaryDifference(ic.allData['prev']['structures'], ic.structures),
68233
68553
  'ssbondpnts': thisClass.dictionaryDifference(ic.allData['prev']['ssbondpnts'], ic.ssbondpnts),
68234
- 'residues': thisClass.dictionaryDifference(ic.allData['prev']['residues'], ic.residues), // getSSExpandedAtoms
68554
+ 'residues': thisClass.dictionaryDifference(ic.allData['prev']['residues'], ic.residues),
68235
68555
  'chains': thisClass.dictionaryDifference(ic.allData['prev']['chains'], ic.chains),
68236
68556
  'chainsSeq': thisClass.dictionaryDifference(ic.allData['prev']['chainsSeq'], ic.chainsSeq), //Sequences and Annotation
68237
68557
  'defNames2Atoms': thisClass.dictionaryDifference(ic.allData['prev']['defNames2Atoms'], ic.defNames2Atoms),
@@ -68944,20 +69264,23 @@ class LoadScript {
68944
69264
  }
68945
69265
  }
68946
69266
  else if(command.indexOf('load chainalignment') !== -1) {
68947
- //load chainalignment [id] | resnum [resnum] | resdef [resnum] | aligntool [aligntool] | parameters [inpara]
69267
+ //load chainalignment [id] | resnum [resnum] | resdef [resdef] | aligntool [aligntool] | parameters [inpara] | resrange [resrange]
68948
69268
  let urlArray = command.split(" | ");
68949
69269
  if(urlArray.length > 1 && urlArray[1].indexOf('resnum') != -1) {
68950
69270
  me.cfg.resnum = urlArray[1].substr(urlArray[1].indexOf('resnum') + 7);
68951
69271
  }
68952
69272
  if(urlArray.length > 2 && urlArray[2].indexOf('resdef') != -1) {
68953
- me.cfg.resdef = urlArray[2].substr(urlArray[1].indexOf('resdef') + 7);
69273
+ me.cfg.resdef = urlArray[2].substr(urlArray[2].indexOf('resdef') + 7);
68954
69274
  }
68955
69275
  if(urlArray.length > 3 && urlArray[3].indexOf('aligntool') != -1) {
68956
- me.cfg.aligntool = urlArray[3].substr(urlArray[1].indexOf('aligntool') + 10);
69276
+ me.cfg.aligntool = urlArray[3].substr(urlArray[3].indexOf('aligntool') + 10);
69277
+ }
69278
+ if(urlArray.length > 5 && urlArray[5].indexOf('resrange') != -1) {
69279
+ me.cfg.resrange = urlArray[5].substr(urlArray[5].indexOf('resrange') + 9);
68957
69280
  }
68958
69281
 
68959
69282
  me.cfg.chainalign = id;
68960
- await ic.chainalignParserCls.downloadChainalignment(id, me.cfg.resnum, me.cfg.resdef);
69283
+ await ic.chainalignParserCls.downloadChainalignment(id);
68961
69284
  }
68962
69285
  else if(command.indexOf('load url') !== -1) {
68963
69286
  let typeStr = load_parameters[1]; // type pdb
@@ -69006,7 +69329,8 @@ class LoadScript {
69006
69329
  if(urlArray.length == 2) {
69007
69330
  let bInputSigma = true;
69008
69331
  if(fileType == 'dsn6') {
69009
- await ic.dsn6ParserCls.dsn6ParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
69332
+ // await ic.dsn6ParserCls.dsn6ParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
69333
+ await ic.densityCifParserCls.densityCifParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
69010
69334
  }
69011
69335
  else if(fileType == 'ccp4') {
69012
69336
  await ic.ccp4ParserCls.ccp4ParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
@@ -69019,7 +69343,8 @@ class LoadScript {
69019
69343
  }
69020
69344
  }
69021
69345
  else {
69022
- await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma);
69346
+ // await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma);
69347
+ await ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma);
69023
69348
  }
69024
69349
  }
69025
69350
  // }); // end of me.deferred = $.Deferred(function() {
@@ -75046,7 +75371,73 @@ class Analysis {
75046
75371
 
75047
75372
  $("#" + me.pre + "dl_disttable_html").html(tableHtml);
75048
75373
  }
75049
- }
75374
+ }
75375
+
75376
+ measureAngleManySets(nameArray, nameArray2) {var ic = this.icn3d, me = ic.icn3dui;
75377
+ if(nameArray.length == 0 || nameArray2.length == 0) {
75378
+ alert("Please select sets for angleance calculation...");
75379
+ }
75380
+ else {
75381
+ let angleHash = {};
75382
+
75383
+ for(let i = 0, il = nameArray.length; i < il; ++i) {
75384
+ let set1 = nameArray[i];
75385
+ let array1 = [set1];
75386
+ angleHash[set1] = {};
75387
+
75388
+ ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(array1);
75389
+ let axis1 = ic.axesCls.setPc1Axes(true);
75390
+
75391
+ for(let j = 0, jl = nameArray2.length; j < jl; ++j) {
75392
+ let set2 = nameArray2[j];
75393
+ let array2 = [set2];
75394
+
75395
+ if(set1 == set2) continue;
75396
+
75397
+ ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(array2);
75398
+ let axis2 = ic.axesCls.setPc1Axes(true);
75399
+
75400
+ let angleRad = new THREE.Vector3(parseFloat(axis1.x), parseFloat(axis1.y), parseFloat(axis1.z)).angleTo(new THREE.Vector3(parseFloat(axis2.x), parseFloat(axis2.y), parseFloat(axis2.z)));
75401
+
75402
+ let angle = angleRad / 3.1416 * 180;
75403
+ angle = Math.abs(angle).toFixed(0);
75404
+ if(angle > 180) angle -= 180;
75405
+ if(angle > 90) angle = 180 - angle;
75406
+
75407
+ angleHash[set1][set2] = angle;
75408
+ }
75409
+ }
75410
+
75411
+ let tableHtml = '<table align=center border=1 cellpadding=10 cellspacing=0><tr><th></th>';
75412
+ for(let j = 0, jl = nameArray2.length; j < jl; ++j) {
75413
+ let set2 = nameArray2[j];
75414
+ tableHtml += '<th><b>' + set2 + '</b> (&deg;)</th>';
75415
+ }
75416
+ tableHtml += '</tr>';
75417
+
75418
+ for(let i = 0, il = nameArray.length; i < il; ++i) {
75419
+ let set1 = nameArray[i];
75420
+ tableHtml += '<tr><th><b>' + set1 + '</b> (&deg;)</th>';
75421
+
75422
+ for(let j = 0, jl = nameArray2.length; j < jl; ++j) {
75423
+ let set2 = nameArray2[j];
75424
+
75425
+ if(angleHash[set1] && angleHash[set1][set2]) {
75426
+ tableHtml += '<td><span>' + angleHash[set1][set2] + '</span></td>';
75427
+ }
75428
+ else {
75429
+ tableHtml += '<td>0</td>';
75430
+ }
75431
+ }
75432
+
75433
+ tableHtml += '</tr>';
75434
+ }
75435
+
75436
+ tableHtml += '</table><br><br>';
75437
+
75438
+ $("#" + me.pre + "dl_angletable_html").html(tableHtml);
75439
+ }
75440
+ }
75050
75441
 
75051
75442
  //Add a line between the position (x1, y1, z1) and the position (x2, y2, z2) with the input "color".
75052
75443
  //The line can be dashed if "dashed" is set true.
@@ -78889,7 +79280,8 @@ class ShareLink {
78889
79280
  }
78890
79281
  else {
78891
79282
  text += "\nStart of type file======\n";
78892
- text += ic.InputfileType + "\n";
79283
+ // text += ic.InputfileType + "\n";
79284
+ text += "pdb\n";
78893
79285
  text += "End of type file======\n";
78894
79286
 
78895
79287
  text += "Start of data file======\n";
@@ -81754,7 +82146,7 @@ class iCn3DUI {
81754
82146
  //even when multiple iCn3D viewers are shown together.
81755
82147
  this.pre = this.cfg.divid + "_";
81756
82148
 
81757
- this.REVISION = '3.33.0';
82149
+ this.REVISION = '3.33.3';
81758
82150
 
81759
82151
  // In nodejs, iCn3D defines "window = {navigator: {}}"
81760
82152
  this.bNode = (Object.keys(window).length < 2) ? true : false;
@@ -81898,7 +82290,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81898
82290
  ic.setStyleCls.handleContextLost();
81899
82291
  ic.applyCenterCls.setWidthHeight(width, height);
81900
82292
  ic.ori_chemicalbinding = ic.opts['chemicalbinding'];
81901
- if(me.cfg.bCalphaOnly !== undefined) ic.bCalphaOnly = me.cfg.bCalphaOnly;
82293
+ // if(me.cfg.bCalphaOnly !== undefined) ic.bCalphaOnly = me.cfg.bCalphaOnly;
81902
82294
  ic.opts = me.hashUtilsCls.cloneHash(ic.opts);
81903
82295
  ic.STATENUMBER = ic.commands.length;
81904
82296
  // If previously crashed, recover it
@@ -81926,7 +82318,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81926
82318
  ic.bInputfile = true;
81927
82319
  ic.InputfileType = 'pdb';
81928
82320
  ic.InputfileData = (ic.InputfileData) ? ic.InputfileData + '\nENDMDL\n' + pdbStr : pdbStr;
81929
-
82321
+
81930
82322
  await ic.pdbParserCls.loadPdbData(pdbStr);
81931
82323
 
81932
82324
  if(me.cfg.resdef !== undefined && me.cfg.chains !== undefined) {
@@ -81937,9 +82329,9 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81937
82329
  for(let i = 0, il = structureArray.length; i < il; ++i) {
81938
82330
  chainidArray.push(structureArray[i] + '_' + chainArray[i]);
81939
82331
  }
81940
-
82332
+
81941
82333
  chainidArray = ic.chainalignParserCls.addPostfixForChainids(chainidArray);
81942
-
82334
+
81943
82335
  let bRealign = true, bPredefined = true;
81944
82336
  await ic.realignParserCls.realignChainOnSeqAlign(undefined, chainidArray, bRealign, bPredefined);
81945
82337
  }
@@ -81960,7 +82352,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81960
82352
  chainidArray.push(domainidArray[i]);
81961
82353
  }
81962
82354
  }
81963
-
82355
+
81964
82356
  // get the matched structures, do not include the template
81965
82357
  let mmdbafid = '';
81966
82358
  for(let i = 0, il = chainidArray.length; i < il; ++i) {
@@ -81971,7 +82363,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81971
82363
  // realign, include the template
81972
82364
  ic.chainidArray = [chain_t].concat(chainidArray);
81973
82365
  ic.chainidArray = ic.chainalignParserCls.addPostfixForChainids(ic.chainidArray);
81974
-
82366
+
81975
82367
  me.htmlCls.clickMenuCls.setLogCmd('resdef ' + me.cfg.resdef, true);
81976
82368
 
81977
82369
  ic.loadCmd = 'vast_search_chainid ' + ic.chainidArray;
@@ -82048,7 +82440,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
82048
82440
  }
82049
82441
  else if(me.cfg.refseqid !== undefined) {
82050
82442
  ic.inputid = me.cfg.refseqid;
82051
-
82443
+
82052
82444
  // ic.bNCBI = true;
82053
82445
  ic.loadCmd = 'load refseq ' + me.cfg.refseqid;
82054
82446
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
@@ -82056,7 +82448,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
82056
82448
  }
82057
82449
  else if(me.cfg.protein !== undefined) {
82058
82450
  ic.inputid = me.cfg.protein;
82059
-
82451
+
82060
82452
  // ic.bNCBI = true;
82061
82453
  ic.loadCmd = 'load protein ' + me.cfg.protein;
82062
82454
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
@@ -82065,7 +82457,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
82065
82457
  else if(me.cfg.blast_rep_id !== undefined) {
82066
82458
  // ic.bNCBI = true;
82067
82459
  ic.inputid = me.cfg.query_id + ',' + me.cfg.blast_rep_id;
82068
-
82460
+
82069
82461
  me.cfg.oriQuery_id = me.cfg.query_id;
82070
82462
  me.cfg.oriBlast_rep_id = me.cfg.blast_rep_id;
82071
82463
 
@@ -82089,7 +82481,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
82089
82481
  ic.bSmithwm = false;
82090
82482
  ic.bLocalSmithwm = false;
82091
82483
  }
82092
-
82484
+
82093
82485
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
82094
82486
  await ic.mmdbParserCls.downloadBlast_rep_id(me.cfg.query_id + ',' + me.cfg.blast_rep_id);
82095
82487
  }
@@ -82098,7 +82490,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
82098
82490
  let data = await me.getAjaxPromise(url, 'json', false, 'The RID ' + me.cfg.rid + ' may have expired...');
82099
82491
 
82100
82492
  for(let q = 0, ql = data.BlastOutput2.length; q < ql; ++q) {
82101
-
82493
+
82102
82494
  let hitArray;
82103
82495
  if(data.BlastOutput2[q].report.results.iterations) { // psi-blast may have "iterations". Use the last iteration.
82104
82496
  let nIterations = data.BlastOutput2[q].report.results.iterations.length;
@@ -82109,7 +82501,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
82109
82501
  if(data.BlastOutput2[q].report.results.search.query_id != me.cfg.query_id) continue;
82110
82502
  hitArray = data.BlastOutput2[q].report.results.search.hits;
82111
82503
  }
82112
-
82504
+
82113
82505
  let qseq = undefined;
82114
82506
  for(let i = 0, il = hitArray.length; i < il; ++i) {
82115
82507
  let hit = hitArray[i];
@@ -82141,6 +82533,18 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
82141
82533
  }
82142
82534
  }
82143
82535
  else if(me.cfg.cid !== undefined) {
82536
+ if(isNaN(me.cfg.cid)) {
82537
+ let urlCid = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi?compound2cid=" + me.cfg.cid;
82538
+ let cidJson = await me.getAjaxPromise(urlCid, 'jsonp');
82539
+ if(cidJson.cid && cidJson.cid[0]) {
82540
+ me.cfg.cid = cidJson.cid[0];
82541
+ }
82542
+ else {
82543
+ alert("Please input an valid PubChem CID...");
82544
+ return;
82545
+ }
82546
+ }
82547
+
82144
82548
  ic.inputid = me.cfg.cid;
82145
82549
 
82146
82550
  let url = "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/" + ic.inputid + "/description/jsonp";
@@ -82185,9 +82589,9 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
82185
82589
 
82186
82590
  ic.bChainAlign = true;
82187
82591
  ic.inputid = me.cfg.chainalign;
82188
- ic.loadCmd = 'load chainalignment ' + me.cfg.chainalign + ' | resnum ' + me.cfg.resnum + ' | resdef ' + me.cfg.resdef + ' | aligntool ' + me.cfg.aligntool + ' | parameters ' + me.cfg.inpara;
82592
+ ic.loadCmd = 'load chainalignment ' + me.cfg.chainalign + ' | resnum ' + me.cfg.resnum + ' | resdef ' + me.cfg.resdef + ' | aligntool ' + me.cfg.aligntool + ' | parameters ' + me.cfg.inpara + ' | resrange ' + me.cfg.resrange;
82189
82593
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
82190
- await ic.chainalignParserCls.downloadChainalignment(me.cfg.chainalign, me.cfg.resnum, me.cfg.resdef);
82594
+ await ic.chainalignParserCls.downloadChainalignment(me.cfg.chainalign);
82191
82595
  }
82192
82596
  else if(me.cfg.mmdbafid !== undefined) {
82193
82597
  // ic.bNCBI = true;
@@ -82205,7 +82609,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
82205
82609
  }
82206
82610
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
82207
82611
 
82208
- await ic.chainalignParserCls.downloadMmdbAf(me.cfg.mmdbafid);
82612
+ await ic.chainalignParserCls.downloadMmdbAf(me.cfg.mmdbafid);
82209
82613
  //await ic.loadScriptCls.loadScript(me.cfg.command, undefined, true);
82210
82614
  }
82211
82615
  else if(me.cfg.command !== undefined && me.cfg.command !== '') {
@@ -82219,7 +82623,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
82219
82623
 
82220
82624
  return;
82221
82625
  }
82222
-
82626
+
82223
82627
  await ic.loadScriptCls.loadScript(me.cfg.command, undefined, true);
82224
82628
  // });
82225
82629
  // return me.deferred.promise();
@@ -82287,7 +82691,7 @@ iCn3DUI.prototype.getXMLHttpRqstPromise = function(url, dataType, responseType,
82287
82691
  let oReq = new XMLHttpRequest();
82288
82692
  oReq.open(dataType, url, true);
82289
82693
  oReq.responseType = responseType;
82290
-
82694
+
82291
82695
  oReq.onreadystatechange = function() {
82292
82696
  if (this.readyState == 4) {
82293
82697
  if(this.status == 200) {
@@ -82339,7 +82743,7 @@ iCn3DUI.prototype.getAjaxPromise = function(url, dataType, beforeSend, alertMess
82339
82743
  error : function() {
82340
82744
  if(alertMess) alert(alertMess);
82341
82745
  if(logMess) console.log(logMess);
82342
-
82746
+
82343
82747
  reject('error');
82344
82748
  }
82345
82749
  });
@@ -82382,7 +82786,7 @@ iCn3DUI.prototype.getAjaxPostPromise = async function(url, data, beforeSend, ale
82382
82786
  //if(alertMess) alert(alertMess);
82383
82787
  if(!me.bNode && alertMess) console.log(alertMess);
82384
82788
  if(!me.bNode && logMess) console.log(logMess);
82385
-
82789
+
82386
82790
  // reject('error');
82387
82791
  // keep running the program
82388
82792
  resolve('error');