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.js CHANGED
@@ -6893,7 +6893,10 @@ class UtilsCls {
6893
6893
  let nOtherAtoms = 0;
6894
6894
  for(let i in atomlist) {
6895
6895
  if(index < testLength) {
6896
- let atomName = atomlist[i].name.trim();
6896
+ let atomName = atomlist[i].name;
6897
+ if(!atomName) continue;
6898
+ atomName = atomName.trim();
6899
+
6897
6900
  if(atomName !== "CA" && atomName !== "P" && atomName !== "O3'" && atomName !== "O3*") {
6898
6901
  //bOtherAtoms = true;
6899
6902
  //break;
@@ -9046,7 +9049,7 @@ class ClickMenu {
9046
9049
  });
9047
9050
 
9048
9051
  me.myEventCls.onIds("#" + me.pre + "mn1_cid", "click", function(e) { me.icn3d; //e.preventDefault();
9049
- me.htmlCls.dialogCls.openDlg('dl_cid', 'Please input PubChem CID');
9052
+ me.htmlCls.dialogCls.openDlg('dl_cid', 'Please input PubChem Compound');
9050
9053
  });
9051
9054
 
9052
9055
  me.myEventCls.onIds("#" + me.pre + "mn1_pngimage", "click", function(e) { me.icn3d; //e.preventDefault();
@@ -10397,8 +10400,8 @@ class ClickMenu {
10397
10400
  //if(!me.cfg.notebook) dialog.dialog( "close" );
10398
10401
  let sigma2fofc = parseFloat($("#" + me.pre + "sigma2fofc" ).val());
10399
10402
  let type = '2fofc';
10400
- await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma2fofc);
10401
- //ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma2fofc);
10403
+ //await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma2fofc);
10404
+ await ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma2fofc);
10402
10405
 
10403
10406
  //ic.setOptionCls.setOption('map', '2fofc');
10404
10407
  thisClass.setLogCmd('set map 2fofc sigma ' + sigma2fofc, true);
@@ -10410,7 +10413,8 @@ class ClickMenu {
10410
10413
  //if(!me.cfg.notebook) dialog.dialog( "close" );
10411
10414
  let sigmafofc = parseFloat($("#" + me.pre + "sigmafofc" ).val());
10412
10415
  let type = 'fofc';
10413
- await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigmafofc);
10416
+ //await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigmafofc);
10417
+ await ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma2fofc);
10414
10418
  //ic.setOptionCls.setOption('map', 'fofc');
10415
10419
  thisClass.setLogCmd('set map fofc sigma ' + sigmafofc, true);
10416
10420
  });
@@ -10670,13 +10674,21 @@ class ClickMenu {
10670
10674
  });
10671
10675
 
10672
10676
  me.myEventCls.onIds("#" + me.pre + "mn6_distManySets", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
10673
- me.htmlCls.dialogCls.openDlg('dl_distmanysets', 'Measure the pairwise distance among many sets');
10677
+ me.htmlCls.dialogCls.openDlg('dl_distmanysets', 'Measure the pairwise distances among many sets');
10674
10678
 
10675
10679
  thisClass.setSetsMenus('atomsCustomDistTable');
10676
10680
 
10677
10681
  ic.bMeasureDistance = true;
10678
10682
  });
10679
10683
 
10684
+ me.myEventCls.onIds("#" + me.pre + "mn6_angleManySets", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
10685
+ me.htmlCls.dialogCls.openDlg('dl_anglemanysets', 'Measure the pairwise angles among many sets');
10686
+
10687
+ thisClass.setSetsMenus('atomsCustomAngleTable');
10688
+
10689
+ ic.bMeasureAngle = true;
10690
+ });
10691
+
10680
10692
  me.myEventCls.onIds("#" + me.pre + "mn6_distanceNo", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
10681
10693
  ic.pickpair = false;
10682
10694
  let select = "set lines off";
@@ -10761,6 +10773,10 @@ class ClickMenu {
10761
10773
  me.htmlCls.dialogCls.openDlg('dl_translate', 'Translate the X,Y,Z coordinates of the structure');
10762
10774
  });
10763
10775
 
10776
+ $(document).on("click", "#" + me.pre + "mn6_angleTwoSets", function(e) { me.icn3d; //e.preventDefault();
10777
+ me.htmlCls.dialogCls.openDlg('dl_angle', 'Measure the angle between two vectors');
10778
+ });
10779
+
10764
10780
  $(document).on("click", "#" + me.pre + "mn2_matrix", function(e) { me.icn3d; //e.preventDefault();
10765
10781
  me.htmlCls.dialogCls.openDlg('dl_matrix', 'Apply matrix to the X,Y,Z coordinates of the structure');
10766
10782
  });
@@ -10947,6 +10963,18 @@ class ClickMenu {
10947
10963
  me.htmlCls.dialogCls.openDlg('dl_contact', 'Set contact map');
10948
10964
  });
10949
10965
 
10966
+ me.myEventCls.onIds(["#" + me.pre + "mn6_DSSP"], "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
10967
+ thisClass.setLogCmd('set dssp sse', true);
10968
+ await ic.pdbParserCls.applyCommandDssp();
10969
+ ic.bResetAnno = true;
10970
+
10971
+ if(ic.bAnnoShown) {
10972
+ await ic.showAnnoCls.showAnnotations();
10973
+
10974
+ ic.annotationCls.resetAnnoTabAll();
10975
+ }
10976
+ });
10977
+
10950
10978
 
10951
10979
  me.myEventCls.onIds("#" + me.pre + "mn6_hbondsNo", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
10952
10980
  ic.showInterCls.hideHbondsContacts();
@@ -11681,7 +11709,7 @@ class SetMenu {
11681
11709
  html += this.getLink('mn1_mmcifid', 'RCSB mmCIF ID ' + me.htmlCls.wifiStr, undefined, 2);
11682
11710
  //html += this.getLink('mn1_gi', 'NCBI gi ' + me.htmlCls.wifiStr, undefined, 2);
11683
11711
 
11684
- html += this.getLink('mn1_cid', 'PubChem CID ' + me.htmlCls.wifiStr, 1, 2);
11712
+ html += this.getLink('mn1_cid', 'PubChem CID/Name/InchI ' + me.htmlCls.wifiStr, 1, 2);
11685
11713
 
11686
11714
  html += "</ul>";
11687
11715
  html += "</li>";
@@ -12782,11 +12810,18 @@ class SetMenu {
12782
12810
  html += "<ul>";
12783
12811
  html += this.getRadio('mn6_distance', 'mn6_distanceYes', 'between Two Atoms', undefined, 1, 2);
12784
12812
  html += this.getRadio('mn6_distance', 'mn6_distTwoSets', 'between Two Sets', undefined, undefined, 2);
12785
- html += this.getRadio('mn6_distance', 'mn6_distManySets', 'Among Many Sets', undefined, undefined, 2);
12813
+ html += this.getRadio('mn6_distance', 'mn6_distManySets', 'among Many Sets', undefined, undefined, 2);
12786
12814
  html += this.getRadio('mn6_distance', 'mn6_distanceNo', 'Hide', true, 1, 2);
12787
12815
  html += "</ul>";
12788
12816
  html += "</li>";
12789
12817
 
12818
+ html += this.getMenuText('mn6_anglewrap', 'Angle', undefined, 1, 1);
12819
+ html += "<ul>";
12820
+ html += this.getRadio('mn6_angle', 'mn6_angleManySets', 'among Many Sets', undefined, 1, 2);
12821
+ html += this.getRadio('mn6_angle', 'mn6_angleTwoSets', 'b/w Two Vectors', undefined, undefined, 2);
12822
+ html += "</ul>";
12823
+ html += "</li>";
12824
+
12790
12825
  html += this.getLink('mn6_area', 'Surface Area', 1, 1);
12791
12826
 
12792
12827
  html += this.getMenuText('mn6_addlabelwrap', 'Label', undefined, 1, 1);
@@ -12860,6 +12895,8 @@ class SetMenu {
12860
12895
  html += "</ul>";
12861
12896
  html += "</li>";
12862
12897
 
12898
+ html += this.getLink('mn6_DSSP', 'DSSP Secondary', undefined, 1);
12899
+
12863
12900
  let bOnePdb = me.cfg.mmtfid !== undefined || me.cfg.pdbid !== undefined || me.cfg.opmid !== undefined || me.cfg.mmcifid !== undefined || me.cfg.mmdbid !== undefined || me.cfg.mmdbafid !== undefined || me.cfg.gi !== undefined || me.cfg.blast_rep_id !== undefined;
12864
12901
 
12865
12902
  if(bOnePdb) {
@@ -14102,8 +14139,8 @@ class SetDialog {
14102
14139
  html += "</div>";
14103
14140
 
14104
14141
  html += me.htmlCls.divStr + "dl_cid' class='" + dialogClass + "'>";
14105
- html += this.addNotebookTitle('dl_cid', 'Please input a PubChem CID');
14106
- html += "PubChem CID: " + me.htmlCls.inputTextStr + "id='" + me.pre + "cid' value='2244' size=8> ";
14142
+ html += this.addNotebookTitle('dl_cid', 'Please input a PubChem Compound');
14143
+ html += "PubChem CID/Name/InchI: " + me.htmlCls.inputTextStr + "id='" + me.pre + "cid' value='2244' size=8> ";
14107
14144
  html += me.htmlCls.buttonStr + "reload_cid'>Load</button>";
14108
14145
  html += "</div>";
14109
14146
 
@@ -14160,14 +14197,14 @@ class SetDialog {
14160
14197
 
14161
14198
  html += "<span style='white-space:nowrap;font-weight:bold;'>2fofc contour at default threshold or at: "
14162
14199
  + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigma2fofc' value='' size=8> &sigma;</span><br/>";
14163
- //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/>";
14164
- 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/>";
14200
+ //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/>";
14201
+ 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/>";
14165
14202
 
14166
14203
  html += "<span style='white-space:nowrap;font-weight:bold;'>fofc contour at default threshold or at: "
14167
14204
  + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigmafofc' value='' size=8> &sigma;</span><br/>";
14168
14205
 
14169
- //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>";
14170
- 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>";
14206
+ //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>";
14207
+ 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>";
14171
14208
 
14172
14209
 
14173
14210
  html += me.htmlCls.buttonStr + "elecmapNo4'>Remove Map</button><br>";
@@ -14181,12 +14218,16 @@ class SetDialog {
14181
14218
  html += "<span style='white-space:nowrap;font-weight:bold;'>2fofc contour at default threshold or at: "
14182
14219
  + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigmaurl2fofc' value='' size=8> &sigma;</span><br/>";
14183
14220
 
14184
- 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/>";
14221
+ //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/>";
14222
+
14223
+ 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/>";
14185
14224
 
14186
14225
  html += "<span style='white-space:nowrap;font-weight:bold;'>fofc contour at default threshold or at: "
14187
14226
  + me.htmlCls.inputTextStr + "id='" + me.pre + "dsn6sigmaurlfofc' value='' size=8> &sigma;</span><br/>";
14188
14227
 
14189
- 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>";
14228
+ //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>";
14229
+
14230
+ 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>";
14190
14231
 
14191
14232
  html += me.htmlCls.buttonStr + "elecmapNo5'>Remove Map</button><br>";
14192
14233
 
@@ -14734,6 +14775,29 @@ class SetDialog {
14734
14775
  html += me.htmlCls.spanNowrapStr + "2. " + me.htmlCls.buttonStr + "applydisttable'>Distances in Table</button></span>";
14735
14776
  html += "</div>";
14736
14777
 
14778
+
14779
+ html += me.htmlCls.divStr + "dl_anglemanysets' class='" + dialogClass + "' style='max-width:500px'>";
14780
+ html += this.addNotebookTitle('dl_anglemanysets', 'Measure angles among many sets');
14781
+ 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/>";
14782
+ html += me.htmlCls.spanNowrapStr + "1. Select sets for pairwise angles</span><br/>";
14783
+ html += "<table border=0 width=400 cellspacing=10><tr><td>";
14784
+
14785
+ html += me.htmlCls.divNowrapStr + "First sets:</div>";
14786
+ html += "<div style='text-indent:1.1em'><select style='max-width:200px' id='" + me.pre + "atomsCustomAngleTable2' multiple size='5' style='min-width:130px;'>";
14787
+ html += "</select></div>";
14788
+
14789
+ html += "</td><td>";
14790
+
14791
+ html += me.htmlCls.divNowrapStr + "Second sets:</div>";
14792
+ html += "<div style='text-indent:1.1em'><select style='max-width:200px' id='" + me.pre + "atomsCustomAngleTable' multiple size='5' style='min-width:130px;'>";
14793
+ html += "</select></div>";
14794
+
14795
+ html += "</td></tr></table>";
14796
+
14797
+ html += me.htmlCls.spanNowrapStr + "2. " + me.htmlCls.buttonStr + "applyangletable'>Angles in Table</button></span>";
14798
+ html += "</div>";
14799
+
14800
+
14737
14801
  html += me.htmlCls.divStr + "dl_stabilizer_rm' class='" + dialogClass + "'>";
14738
14802
  html += this.addNotebookTitle('dl_stabilizer_rm', 'Remove a stabilizer');
14739
14803
  if(me.utilsCls.isMobile()) {
@@ -15013,6 +15077,11 @@ class SetDialog {
15013
15077
  html += this.addNotebookTitle('dl_disttable', 'Distance Table', true);
15014
15078
  html += "</div>";
15015
15079
 
15080
+
15081
+ html += me.htmlCls.divStr + "dl_angletable' class='" + dialogClass + "'>";
15082
+ html += this.addNotebookTitle('dl_angletable', 'Angle Table', true);
15083
+ html += "</div>";
15084
+
15016
15085
  html += me.htmlCls.divStr + "dl_translate' class='" + dialogClass + "'>";
15017
15086
  html += this.addNotebookTitle('dl_translate', 'Translate the X,Y,Z coordinates of the structure');
15018
15087
  html += "X: " + me.htmlCls.inputTextStr + "id='" + me.pre + "translateX' value='' size=4> ";
@@ -15021,6 +15090,20 @@ class SetDialog {
15021
15090
  html += me.htmlCls.buttonStr + "translate_pdb'>Translate</button>";
15022
15091
  html += "</div>";
15023
15092
 
15093
+ html += me.htmlCls.divStr + "dl_angle' class='" + dialogClass + "'>";
15094
+ html += this.addNotebookTitle('dl_angle', 'Measure the angle between two vectors');
15095
+ html += "<b>Vector 1</b>, X: " + me.htmlCls.inputTextStr + "id='" + me.pre + "v1X' value='' size=6> ";
15096
+ html += "Y: " + me.htmlCls.inputTextStr + "id='" + me.pre + "v1Y' value='' size=6> ";
15097
+ html += "Z: " + me.htmlCls.inputTextStr + "id='" + me.pre + "v1Z' value='' size=6><br>";
15098
+ html += "<b>Vector 2</b>, X: " + me.htmlCls.inputTextStr + "id='" + me.pre + "v2X' value='' size=6> ";
15099
+ html += "Y: " + me.htmlCls.inputTextStr + "id='" + me.pre + "v2Y' value='' size=6> ";
15100
+ html += "Z: " + me.htmlCls.inputTextStr + "id='" + me.pre + "v2Z' value='' size=6><br>";
15101
+ html += "<br>";
15102
+
15103
+ html += me.htmlCls.buttonStr + "measure_angle'>Measure Angle</button><br><br>";
15104
+ html += "The angle is: " + me.htmlCls.inputTextStr + "id='" + me.pre + "angle_value' value='' size=6> degree.<br><br>";
15105
+ html += "</div>";
15106
+
15024
15107
  html += me.htmlCls.divStr + "dl_matrix' class='" + dialogClass + "'>";
15025
15108
  html += this.addNotebookTitle('dl_matrix', 'Apply matrix to the X,Y,Z coordinates of the structure');
15026
15109
  html += "0: " + me.htmlCls.inputTextStr + "id='" + me.pre + "matrix0' value='1' size=2> ";
@@ -15864,6 +15947,27 @@ class Events {
15864
15947
  thisClass.setLogCmd("translate pdb " + dx + " " + dy + " " + dz, true);
15865
15948
  });
15866
15949
 
15950
+ me.myEventCls.onIds("#" + me.pre + "measure_angle", "click", function(e) { me.icn3d;
15951
+ e.preventDefault();
15952
+ if(!me.cfg.notebook) dialog.dialog( "close" );
15953
+ let v1X = $("#" + me.pre + "v1X").val();
15954
+ let v1Y = $("#" + me.pre + "v1Y").val();
15955
+ let v1Z= $("#" + me.pre + "v1Z").val();
15956
+
15957
+ let v2X = $("#" + me.pre + "v2X").val();
15958
+ let v2Y = $("#" + me.pre + "v2Y").val();
15959
+ let v2Z = $("#" + me.pre + "v2Z").val();
15960
+
15961
+ let angleRad = new THREE.Vector3(parseFloat(v1X), parseFloat(v1Y), parseFloat(v1Z)).angleTo(new THREE.Vector3(parseFloat(v2X), parseFloat(v2Y), parseFloat(v2Z)));
15962
+ let angle = angleRad / 3.1416 * 180;
15963
+ angle = Math.abs(angle).toFixed(0);
15964
+ if(angle > 180) angle -= 180;
15965
+ if(angle > 90) angle = 180 - angle;
15966
+
15967
+ thisClass.setLogCmd("The angle is " + angle + " degree", false);
15968
+ $("#" + me.pre + "angle_value").val(angle);
15969
+ });
15970
+
15867
15971
  me.myEventCls.onIds("#" + me.pre + "matrix_pdb", "click", function(e) { let ic = me.icn3d;
15868
15972
  e.preventDefault();
15869
15973
  if(!me.cfg.notebook) dialog.dialog( "close" );
@@ -17520,6 +17624,20 @@ class Events {
17520
17624
  thisClass.setLogCmd("disttable | " + nameArray2 + " " + nameArray, true);
17521
17625
  });
17522
17626
 
17627
+ me.myEventCls.onIds("#" + me.pre + "applyangletable", "click", function(e) { let ic = me.icn3d;
17628
+ e.preventDefault();
17629
+ if(!me.cfg.notebook) dialog.dialog( "close" );
17630
+ ic.bMeasureAngle = false;
17631
+
17632
+ let nameArray = $("#" + me.pre + "atomsCustomAngleTable").val();
17633
+ let nameArray2 = $("#" + me.pre + "atomsCustomAngleTable2").val();
17634
+
17635
+ ic.analysisCls.measureAngleManySets(nameArray, nameArray2);
17636
+ me.htmlCls.dialogCls.openDlg('dl_angletable', 'Angles among the sets');
17637
+
17638
+ thisClass.setLogCmd("angletable | " + nameArray2 + " " + nameArray, true);
17639
+ });
17640
+
17523
17641
  me.myEventCls.onIds("#" + me.pre + "applylinebtwsets", "click", function(e) { let ic = me.icn3d;
17524
17642
  e.preventDefault();
17525
17643
 
@@ -28109,18 +28227,17 @@ class Strand {
28109
28227
 
28110
28228
  let bRibbon = fill ? true: false;
28111
28229
 
28112
- // when highlight, the input atoms may only include part of sheet or helix
28113
- // include the whole sheet or helix when highlighting
28230
+ // when highlight, the input atoms may only include one rediue.
28231
+ // add one extra residue to show the strand
28114
28232
  let atomsAdjust = {};
28115
28233
 
28116
- // if( Object.keys(atoms).length < Object.keys(ic.atoms).length) {
28117
- // atomsAdjust = this.getSSExpandedAtoms(atoms);
28118
- // }
28119
- // else {
28120
- // atomsAdjust = atoms;
28121
- // }
28122
-
28123
- atomsAdjust = atoms;
28234
+ let residueHashTmp = ic.firstAtomObjCls.getResiduesFromAtoms(atoms);
28235
+ if( Object.keys(residueHashTmp).length == 1) {
28236
+ atomsAdjust = this.getOneExtraResidue(residueHashTmp);
28237
+ }
28238
+ else {
28239
+ atomsAdjust = atoms;
28240
+ }
28124
28241
 
28125
28242
  if(bHighlight === 2) {
28126
28243
  if(fill) {
@@ -28155,22 +28272,24 @@ class Strand {
28155
28272
  let currentChain, currentResi, currentCA = null, currentO = null, currentColor = null, prevCoorCA = null, prevCoorO = null, prevColor = null;
28156
28273
  let prevCO = null, ss = null, ssend = false, atomid = null, prevAtomid = null, prevAtomSelected = null, prevResi = null, calphaid = null, prevCalphaid = null;
28157
28274
  let strandWidth, bSheetSegment = false, bHelixSegment = false;
28158
- let atom, tubeAtoms = {};
28159
28275
 
28160
- // test the first 30 atoms to see whether only C-alpha is available
28161
- ic.bCalphaOnly = me.utilsCls.isCalphaPhosOnly(atomsAdjust); //, 'CA');
28276
+ // For each chain, test the first 30 atoms to see whether only C-alpha is available
28277
+ let bCalphaOnlyHash = {};
28278
+ for(let chainid in ic.chains) {
28279
+ let atoms = me.hashUtilsCls.hash2Atoms(ic.chains[chainid], ic.atoms);
28280
+ let bCalphaOnly = me.utilsCls.isCalphaPhosOnly(atoms); //, 'CA');
28281
+ bCalphaOnlyHash[chainid] = bCalphaOnly;
28282
+ }
28162
28283
 
28163
28284
  // when highlight, draw whole beta sheet and use bShowArray to show the highlight part
28164
28285
  let residueHash = {};
28165
28286
  for(let i in atomsAdjust) {
28166
- let atom = atomsAdjust[i];
28287
+ let atom = ic.atoms[i];
28167
28288
 
28168
28289
  let residueid = atom.structure + '_' + atom.chain + '_' + atom.resi;
28169
28290
  residueHash[residueid] = 1;
28170
28291
  }
28171
- let totalResidueCount = Object.keys(residueHash).length;
28172
-
28173
- let drawnResidueCount = 0;
28292
+ Object.keys(residueHash).length;
28174
28293
 
28175
28294
  let bFullAtom = (Object.keys(ic.hAtoms).length == Object.keys(ic.atoms).length) ? true : false;
28176
28295
 
@@ -28179,22 +28298,20 @@ class Strand {
28179
28298
  let maxDist = 6.0;
28180
28299
 
28181
28300
  //get the last residue
28182
- let atomArray = Object.keys(atoms);
28301
+ let atomArray = Object.keys(atomsAdjust);
28183
28302
  let lastAtomSerial = atomArray[atomArray.length - 1];
28184
- let lastAtom = atoms[lastAtomSerial];
28303
+ let lastAtom = ic.atoms[lastAtomSerial];
28185
28304
  let lastResid = lastAtom.structure + '_' + lastAtom.chain + '_' + lastAtom.resi;
28186
28305
 
28187
28306
  for (let i in atomsAdjust) {
28188
- atom = atomsAdjust[i];
28307
+ let atom = ic.atoms[i];
28189
28308
  let chainid = atom.structure + '_' + atom.chain;
28190
28309
  let resid = atom.structure + '_' + atom.chain + '_' + atom.resi;
28191
28310
  if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
28192
28311
  // "CA" has to appear before "O"
28193
28312
 
28194
28313
  if (atom.name === 'CA') {
28195
- if ( atoms.hasOwnProperty(i) && ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) ) {
28196
- tubeAtoms[i] = atom;
28197
- }
28314
+ if ( atoms.hasOwnProperty(i) && ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) ) ;
28198
28315
 
28199
28316
  currentCA = atom.coord;
28200
28317
  currentColor = atom.color;
@@ -28203,7 +28320,7 @@ class Strand {
28203
28320
  caArray.push(atom.serial);
28204
28321
  }
28205
28322
 
28206
- if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA')) {
28323
+ if (atom.name === 'O' || (bCalphaOnlyHash[chainid] && atom.name === 'CA')) {
28207
28324
  if(currentCA === null || currentCA === undefined) {
28208
28325
  currentCA = atom.coord;
28209
28326
  currentColor = atom.color;
@@ -28266,7 +28383,7 @@ class Strand {
28266
28383
  }
28267
28384
  }
28268
28385
  }
28269
- else if(ic.bCalphaOnly && atom.name === 'CA') {
28386
+ else if(bCalphaOnlyHash[chainid] && atom.name === 'CA') {
28270
28387
  if(caArray.length > resSpan + 1) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
28271
28388
  O = prevCoorCA.clone();
28272
28389
  oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan - 1]].coord.clone();
@@ -28301,8 +28418,6 @@ class Strand {
28301
28418
  bShowArray.push(0);
28302
28419
  calphaIdArray.push(0);
28303
28420
  }
28304
-
28305
- ++drawnResidueCount;
28306
28421
  }
28307
28422
 
28308
28423
  //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);
@@ -28331,7 +28446,9 @@ class Strand {
28331
28446
  // }
28332
28447
 
28333
28448
  //if ((atom.ssbegin || atom.ssend || (drawnResidueCount === totalResidueCount - 1) || bBrokenSs) && pnts[0].length > 0 && bSameChain) {
28334
- if ((currentChain !== atom.chain || atom.ssbegin || atom.ssend || (drawnResidueCount === totalResidueCount - 1) || bBrokenSs || resid == lastResid) && pnts[0].length > 0) {
28449
+ // 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
28450
+
28451
+ if ((currentChain !== atom.chain || atom.ssbegin || atom.ssend || bBrokenSs || (resid == lastResid && atom.ss != 'coil')) && pnts[0].length > 0) {
28335
28452
  let atomName = 'CA';
28336
28453
 
28337
28454
  let prevone = [], nexttwo = [];
@@ -28388,7 +28505,7 @@ class Strand {
28388
28505
  O = currentO.clone();
28389
28506
  O.sub(currentCA);
28390
28507
  }
28391
- else if(ic.bCalphaOnly && atom.name === 'CA') {
28508
+ else if(bCalphaOnlyHash[chainid] && atom.name === 'CA') {
28392
28509
  if(caArray.length > resSpan) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
28393
28510
  O = currentCA.clone();
28394
28511
  oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan]].coord.clone();
@@ -28477,7 +28594,9 @@ class Strand {
28477
28594
  // end of a chain, or end of selection
28478
28595
  if ((currentChain !== atom.chain
28479
28596
  || ic.ParserUtilsCls.getResiNCBI(atom.structure + '_' + currentChain, currentResi) + 1 !== ic.ParserUtilsCls.getResiNCBI(chainid, atom.resi)
28480
- || resid == lastResid
28597
+ // || (drawnResidueCount === totalResidueCount - 1)
28598
+ // || bBrokenSs
28599
+ || (resid == lastResid && atom.ss != 'coil')
28481
28600
  ) && pnts[0].length > 0) {
28482
28601
  //if ((currentChain !== atom.chain) && pnts[0].length > 0) {
28483
28602
 
@@ -28545,18 +28664,42 @@ class Strand {
28545
28664
  prevCoorCA = currentCA;
28546
28665
  prevCoorO = atom.coord;
28547
28666
  prevColor = currentColor;
28548
- } // end if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA') ) {
28667
+ } // end if (atom.name === 'O' || (bCalphaOnlyHash[chainid] && atom.name === 'CA') ) {
28549
28668
  } // end if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
28550
28669
  } // end for
28551
28670
 
28552
28671
  caArray = [];
28553
28672
 
28554
- ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight);
28555
-
28556
- tubeAtoms = {};
28673
+ // ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight);
28674
+ // draw all atoms in tubes and assign zero radius when the residue is not coil
28675
+ ic.tubeCls.createTube(atomsAdjust, 'CA', coilWidth, bHighlight);
28557
28676
  pnts = {};
28558
28677
  }
28559
28678
 
28679
+ getOneExtraResidue(residueHash) { let ic = this.icn3d, me = ic.icn3dui;
28680
+ let atomsAdjust = {};
28681
+
28682
+ for(let resid in residueHash) {
28683
+ atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, ic.residues[resid]);
28684
+
28685
+ let residNcbi = ic.resid2ncbi[resid];
28686
+ let resiNcbi = residNcbi.substr(residNcbi.lastIndexOf('_') + 1);
28687
+
28688
+ let nextResidNcbi = residNcbi.substr(0, residNcbi.lastIndexOf('_')) + '_' + (parseInt(resiNcbi) + 1);
28689
+ let nextResid = ic.ncbi2resid[nextResidNcbi];
28690
+
28691
+ if(!nextResid) {
28692
+ nextResidNcbi = residNcbi.substr(0, residNcbi.lastIndexOf('_')) + '_' + (parseInt(resiNcbi) - 1);
28693
+ nextResid = ic.ncbi2resid[nextResidNcbi];
28694
+ }
28695
+
28696
+ if(nextResid) atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, ic.residues[nextResid]);
28697
+ }
28698
+
28699
+ return atomsAdjust;
28700
+ }
28701
+
28702
+ /*
28560
28703
  getSSExpandedAtoms(atoms, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
28561
28704
  let currChain, currResi, currAtom, prevChain, prevResi, prevAtom;
28562
28705
  let firstAtom, lastAtom;
@@ -28663,6 +28806,7 @@ class Strand {
28663
28806
 
28664
28807
  return atomsAdjust;
28665
28808
  }
28809
+ */
28666
28810
  }
28667
28811
 
28668
28812
  /**
@@ -28682,7 +28826,8 @@ class Strip {
28682
28826
  if (p0.length < 2) return;
28683
28827
  div = div || ic.axisDIV;
28684
28828
 
28685
- if(pntsCA && ic.bDoublecolor && !ic.bCalphaOnly) {
28829
+ // if(pntsCA && ic.bDoublecolor && !ic.bCalphaOnly) {
28830
+ if(pntsCA && ic.bDoublecolor) {
28686
28831
  let bExtendLastRes = false; //true;
28687
28832
 
28688
28833
  let pnts_clrs = me.subdivideCls.subdivide(pntsCA, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
@@ -29010,7 +29155,7 @@ class Tube {
29010
29155
  //Create tubes for "atoms" with certain "atomName". "radius" is the radius of the tubes.
29011
29156
  //"bHighlight" is an option to draw the highlight for these atoms. The highlight could be
29012
29157
  //outlines with bHighlight=1 and 3D objects with bHighlight=2.
29013
- createTube(atoms, atomName, radius, bHighlight, bCustom, bRadiusArray) { let ic = this.icn3d, me = ic.icn3dui;
29158
+ createTube(atoms, atomName, radius, bHighlight, bCustom, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
29014
29159
  if(me.bNode) return;
29015
29160
 
29016
29161
  let pnts = [], colors = [], radii = [], prevone = [], nexttwo = [];
@@ -29122,6 +29267,9 @@ class Tube {
29122
29267
  else {
29123
29268
  radiusFinal = this.getRadius(radius, atom);
29124
29269
  }
29270
+
29271
+ // draw all atoms in tubes and assign zero radius when the residue is not coil
29272
+ if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
29125
29273
 
29126
29274
  //radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
29127
29275
  radii.push(radiusFinal);
@@ -29195,183 +29343,247 @@ class Tube {
29195
29343
  let prevone = pnts_colors_radii_prevone_nexttwo[i].prevone;
29196
29344
  let nexttwo = pnts_colors_radii_prevone_nexttwo[i].nexttwo;
29197
29345
 
29198
- this.createTubeSub(pnts, colors, radii, bHighlight, prevone, nexttwo, bRadiusArray);
29346
+ this.createTubeSub(pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil);
29199
29347
  }
29200
29348
 
29201
- pnts_colors_radii_prevone_nexttwo = [];
29349
+ pnts_colors_radii_prevone_nexttwo = [];
29202
29350
  }
29203
29351
 
29204
- getCustomtubesize(resid) { let ic = this.icn3d; ic.icn3dui;
29205
- let pos = resid.lastIndexOf('_');
29206
- let resi = resid.substr(pos + 1);
29207
- let chainid = resid.substr(0, pos);
29352
+ /*
29353
+ createTube(atoms, atomName, radius, bHighlight, bCustom, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
29354
+ if(me.bNode) return;
29208
29355
 
29209
- let radiusFinal = (ic.queryresi2score[chainid] && ic.queryresi2score[chainid].hasOwnProperty(resi)) ? ic.queryresi2score[chainid][resi] * 0.01 : ic.coilWidth;
29356
+ let pnts = [], colors = [], radii = [], prevone = [], nexttwo = [];
29357
+ let currentChain, currentResi;
29358
+ let index = 0;
29359
+ let maxDist = 6.0;
29360
+ let maxDist2 = 3.0; // avoid tube between the residues in 3 residue helix
29210
29361
 
29211
- return radiusFinal;
29212
- };
29362
+ let pnts_colors_radii_prevone_nexttwo = [];
29363
+ let firstAtom, atom, prevAtom;
29213
29364
 
29214
- // modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
29215
- createTubeSub(_pnts, colors, radii, bHighlight, prevone, nexttwo, bRadiusArray) { let ic = this.icn3d, me = ic.icn3dui;
29216
- if(me.bNode) return;
29365
+ for (let i in atoms) {
29366
+ atom = atoms[i];
29367
+ if ((atom.name === atomName) && !atom.het) {
29368
+ if(index == 0) {
29369
+ firstAtom = atom;
29370
+ }
29217
29371
 
29218
- if (_pnts.length < 2) return;
29372
+ 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
29373
+ || (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))
29374
+ ) ) {
29375
+ if(bHighlight !== 2) {
29376
+ if(!isNaN(firstAtom.resi) && !isNaN(prevAtom.resi)) {
29377
+ let prevoneResid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
29378
+ let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
29379
+ prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
29219
29380
 
29220
- // if(bRadiusArray) {
29221
- let circleDiv = ic.tubeDIV, axisDiv = ic.axisDIV;
29222
- let circleDivInv = 1 / circleDiv, axisDivInv = 1 / axisDiv;
29223
- //var geo = new THREE.Geometry();
29224
- let geo = new THREE.BufferGeometry();
29225
- let verticeArray = [], colorArray = [],indexArray = [], color;
29226
- let offset = 0, offset2 = 0, offset3 = 0;
29381
+ let nextoneResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 1).toString();
29382
+
29383
+ // add one more residue if only one residue is available
29384
+ if(pnts.length == 1 && ic.residues.hasOwnProperty(nextoneResid)) {
29385
+ let nextAtom = ic.firstAtomObjCls.getAtomFromResi(nextoneResid, atomName);
29227
29386
 
29228
- let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv, undefined, undefined, prevone, nexttwo);
29387
+ if(nextAtom) {
29388
+ pnts.push(nextAtom.coord);
29389
+ colors.push(nextAtom.color);
29229
29390
 
29230
- let pnts = pnts_clrs[0];
29231
- colors = pnts_clrs[2];
29391
+ let radiusFinal = this.getRadius(radius, atom);
29392
+ radii.push(radiusFinal);
29393
+ }
29394
+ }
29395
+
29396
+ }
29232
29397
 
29233
- let prevAxis1 = new THREE.Vector3(), prevAxis2;
29234
- for (let i = 0, lim = pnts.length; i < lim; ++i) {
29235
- let r, idx = (i - 1) * axisDivInv;
29236
- if (i === 0) r = radii[0];
29237
- else {
29238
- if (idx % 1 === 0) r = radii[idx];
29239
- else {
29240
- let floored = Math.floor(idx);
29241
- let tmp = idx - floored;
29242
- r = radii[floored] * tmp + radii[floored + 1] * (1 - tmp);
29398
+ pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
29243
29399
  }
29400
+ pnts = []; colors = []; radii = []; prevone = []; nexttwo = [];
29401
+ firstAtom = atom;
29402
+ index = 0;
29244
29403
  }
29245
- let delta, axis1, axis2;
29246
- if (i < lim - 1) {
29247
- delta = pnts[i].clone().sub(pnts[i + 1]);
29248
- axis1 = new THREE.Vector3(0, -delta.z, delta.y).normalize().multiplyScalar(r);
29249
- axis2 = delta.clone().cross(axis1).normalize().multiplyScalar(r);
29250
- // let dir = 1, offset = 0;
29251
- if (prevAxis1.dot(axis1) < 0) {
29252
- axis1.negate(); axis2.negate(); //dir = -1;//offset = 2 * Math.PI / axisDiv;
29253
- }
29254
- prevAxis1 = axis1; prevAxis2 = axis2;
29255
- } else {
29256
- axis1 = prevAxis1; axis2 = prevAxis2;
29404
+
29405
+ pnts.push(atom.coord);
29406
+
29407
+ let radiusFinal;
29408
+ if(bCustom) {
29409
+ radiusFinal = this.getCustomtubesize(atom.structure + '_' + atom.chain + '_' + atom.resi);
29410
+ }
29411
+ else {
29412
+ radiusFinal = this.getRadius(radius, atom);
29257
29413
  }
29258
- for (let j = 0; j < circleDiv; ++j) {
29259
- let angle = 2 * Math.PI * circleDivInv * j; //* dir + offset;
29260
- let point = pnts[i].clone().add(axis1.clone().multiplyScalar(Math.cos(angle))).add(axis2.clone().multiplyScalar(Math.sin(angle)));
29261
- verticeArray[offset++] = point.x;
29262
- verticeArray[offset++] = point.y;
29263
- verticeArray[offset++] = point.z;
29264
29414
 
29265
- color = (i == colors.length - 1 && colors.length > 1) ? me.parasCls.thr(colors[colors.length - 2]) : me.parasCls.thr(colors[i]);
29266
- colorArray[offset2++] = color.r;
29267
- colorArray[offset2++] = color.g;
29268
- colorArray[offset2++] = color.b;
29415
+ // draw all atoms in tubes and assign zero radius when the residue is not coil
29416
+ if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
29417
+
29418
+ //radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
29419
+ radii.push(radiusFinal);
29420
+
29421
+ colors.push(atom.color);
29422
+ // the starting residue of a coil uses the color from the next residue to avoid using the color of the last helix/sheet residue
29423
+ if(index === 1) colors[colors.length - 2] = atom.color;
29424
+
29425
+ currentChain = atom.chain;
29426
+ currentResi = atom.resi;
29427
+
29428
+ let scale = 1.2;
29429
+ if(bHighlight === 2 && !atom.ssbegin) {
29430
+ ic.boxCls.createBox(atom, undefined, undefined, scale, undefined, bHighlight);
29269
29431
  }
29432
+
29433
+ ++index;
29434
+
29435
+ prevAtom = atom;
29270
29436
  }
29271
- let offsetTmp = 0, nComp = 3;
29272
- for (let i = 0, lim = pnts.length - 1; i < lim; ++i) {
29273
- let reg = 0;
29274
- //var r1 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv]).lengthSq();
29275
- //var r2 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv + 1]).lengthSq();
29276
- let pos = offsetTmp * nComp;
29277
- let point1 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
29278
- pos = (offsetTmp + circleDiv) * nComp;
29279
- let point2 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
29280
- pos = (offsetTmp + circleDiv + 1) * nComp;
29281
- let point3 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
29282
-
29283
- let r1 = point1.clone().sub(point2).lengthSq();
29284
- let r2 = point1.clone().sub(point3).lengthSq();
29285
- if (r1 > r2) { r1 = r2; reg = 1; } for (let j = 0; j < circleDiv; ++j) {
29286
- //geo.faces.push(new THREE.Face3(offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv, undefined, c));
29287
- //geo.faces.push(new THREE.Face3(offset + (j + 1) % circleDiv, offset + (j + reg) % circleDiv + circleDiv, offset + (j + reg + 1) % circleDiv + circleDiv, undefined, c));
29288
- //indexArray = indexArray.concat([offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv]);
29289
- indexArray[offset3++] = offsetTmp + j;
29290
- indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
29291
- indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
29292
-
29293
- //indexArray = indexArray.concat([offset + (j + 1) % circleDiv, offset + (j + reg) % circleDiv + circleDiv, offset + (j + reg + 1) % circleDiv + circleDiv]);
29294
- indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
29295
- indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
29296
- indexArray[offset3++] = offsetTmp + (j + reg + 1) % circleDiv + circleDiv;
29297
- }
29298
- offsetTmp += circleDiv;
29299
- }
29437
+ }
29300
29438
 
29301
- geo.setAttribute('position', new THREE.BufferAttribute(new Float32Array(verticeArray), nComp));
29302
- geo.setAttribute('color', new THREE.BufferAttribute(new Float32Array(colorArray), nComp));
29439
+ if(bHighlight !== 2) {
29440
+ pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
29441
+ }
29303
29442
 
29304
- geo.setIndex(new THREE.BufferAttribute(new Uint32Array(indexArray), 1));
29305
- //geo.setIndex(indexArray);
29443
+ for(let i = 0, il = pnts_colors_radii_prevone_nexttwo.length; i < il; ++i) {
29444
+ let pnts = pnts_colors_radii_prevone_nexttwo[i].pnts;
29445
+ let colors = pnts_colors_radii_prevone_nexttwo[i].colors;
29446
+ let radii = pnts_colors_radii_prevone_nexttwo[i].radii;
29447
+ let prevone = []; // = pnts_colors_radii_prevone_nexttwo[i].prevone;
29448
+ let nexttwo = []; // = pnts_colors_radii_prevone_nexttwo[i].nexttwo;
29306
29449
 
29307
- //geo.computeFaceNormals();
29308
- //geo.computeVertexNormals(false);
29309
- geo.computeVertexNormals();
29310
- /*
29450
+ this.createTubeSub(pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil);
29311
29451
  }
29312
- else {
29313
- let axisDiv = ic.axisDIV;
29314
29452
 
29315
- let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv, undefined, undefined, prevone, nexttwo);
29316
- // extend one residue
29317
- //var pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv, undefined, undefined, prevone, nexttwo, true);
29453
+ pnts_colors_radii_prevone_nexttwo = [];
29454
+ }
29455
+ */
29318
29456
 
29319
- _pnts = pnts_clrs[0];
29320
- colors = pnts_clrs[2];
29457
+ getCustomtubesize(resid) { let ic = this.icn3d; ic.icn3dui;
29458
+ let pos = resid.lastIndexOf('_');
29459
+ let resi = resid.substr(pos + 1);
29460
+ let chainid = resid.substr(0, pos);
29321
29461
 
29322
- let radius = ic.coilWidth;
29323
- segments = _pnts.length;
29324
- //radiusSegments = 8;
29325
- radiusSegments = 4; // save memory
29326
- let closed = false;
29462
+ let radiusFinal = (ic.queryresi2score[chainid] && ic.queryresi2score[chainid].hasOwnProperty(resi)) ? ic.queryresi2score[chainid][resi] * 0.01 : ic.coilWidth;
29327
29463
 
29328
- // when using radiusArray with modified three.js, the tube didn't work in picking
29329
- let geo = new THREE.TubeGeometry(
29330
- new THREE.CatmullRomCurve3(_pnts), // path
29331
- segments,
29332
- radius, //radiusArray, //radius,
29333
- radiusSegments,
29334
- closed
29335
- );
29464
+ return radiusFinal;
29465
+ };
29336
29466
 
29337
- //https://stemkoski.github.io/Three.js/Graphulus-Curve.html
29338
- let color, face, numberOfSides, vertexIndex;
29339
- // faces are indexed using characters
29340
- let faceIndices = [ 'a', 'b', 'c', 'd' ];
29467
+ // modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
29468
+ createTubeSub(_pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
29469
+ if(me.bNode) return;
29341
29470
 
29342
- // first, assign colors to vertices as desired
29343
- let prevColor, geoColors = {};
29344
- for ( let s = 0; s <= segments; s++ ) {
29345
- for ( let r = 0; r < radiusSegments; r++ )
29346
- {
29347
- vertexIndex = r + s * radiusSegments;
29348
- color = colors[s];
29349
- if(!color) color = prevColor;
29471
+ if (_pnts.length < 2) return;
29350
29472
 
29351
- geoColors[vertexIndex] = color; // use this array for convenience
29473
+ let circleDiv = ic.tubeDIV, axisDiv = ic.axisDIV;
29474
+ let circleDivInv = 1 / circleDiv, axisDivInv = 1 / axisDiv;
29475
+ //var geo = new THREE.Geometry();
29476
+ let geo = new THREE.BufferGeometry();
29477
+ let verticeArray = [], colorArray = [],indexArray = [], color;
29478
+ let offset = 0, offset2 = 0, offset3 = 0;
29352
29479
 
29353
- prevColor = color;
29354
- }
29355
- }
29480
+ let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv, undefined, undefined, prevone, nexttwo);
29356
29481
 
29357
- // copy the colors as necessary to the face's vertexColors array.
29358
- // after version r125, geo.faces is undefined for TubeGeometry
29359
- for ( let i = 0; geo.faces && i < geo.faces.length; i++ )
29360
- {
29361
- face = geo.faces[ i ];
29482
+ let pnts = pnts_clrs[0];
29483
+ colors = pnts_clrs[2];
29484
+
29485
+ let constRadiius;
29486
+ // a threshold to stop drawing the tube if it's less than this ratio of radius
29487
+ let thresholdRatio = 1; //0.9;
29488
+
29489
+ let prevAxis1 = new THREE.Vector3(), prevAxis2;
29490
+ for (let i = 0, lim = pnts.length; i < lim; ++i) {
29491
+ let r, idx = (i - 1) * axisDivInv;
29362
29492
 
29363
- numberOfSides = ( face instanceof THREE.Face3 ) ? 3 : 4;
29364
- for( let j = 0; j < numberOfSides; j++ )
29365
- {
29366
- vertexIndex = face[ faceIndices[ j ] ];
29367
- face.vertexColors[ j ] = geoColors[ vertexIndex ];
29493
+ if (i === 0) {
29494
+ r = radii[0];
29495
+ if(r > 0) constRadiius = r;
29496
+ }
29497
+ else {
29498
+ if (idx % 1 === 0) {
29499
+ r = radii[idx];
29500
+ if(r > 0) constRadiius = r;
29501
+ }
29502
+ else {
29503
+ let floored = Math.floor(idx);
29504
+ let tmp = idx - floored;
29505
+ // draw all atoms in tubes and assign zero radius when the residue is not coil
29506
+ // r = radii[floored] * tmp + radii[floored + 1] * (1 - tmp);
29507
+ r = radii[floored] * (1 - tmp) + radii[floored + 1] * tmp;
29508
+
29509
+ // a threshold to stop drawing the tube if it's less than this ratio of radius.
29510
+ // The extra bit of tube connects coil with strands or helices
29511
+ if(!bNonCoil) {
29512
+ if(r < thresholdRatio * constRadiius) {
29513
+ r = 0;
29514
+ }
29515
+ // else if(r < constRadiius) {
29516
+ // r *= 0.5; // use small radius for the connection between coild and sheets/helices
29517
+ // }
29518
+ }
29368
29519
  }
29369
29520
  }
29370
-
29371
- geo.computeFaceNormals();
29372
- geo.computeVertexNormals(false);
29521
+ let delta, axis1, axis2;
29522
+ if (i < lim - 1) {
29523
+ delta = pnts[i].clone().sub(pnts[i + 1]);
29524
+ axis1 = new THREE.Vector3(0, -delta.z, delta.y).normalize().multiplyScalar(r);
29525
+ axis2 = delta.clone().cross(axis1).normalize().multiplyScalar(r);
29526
+ // let dir = 1, offset = 0;
29527
+ if (prevAxis1.dot(axis1) < 0) {
29528
+ axis1.negate(); axis2.negate(); //dir = -1;//offset = 2 * Math.PI / axisDiv;
29529
+ }
29530
+ prevAxis1 = axis1; prevAxis2 = axis2;
29531
+ } else {
29532
+ axis1 = prevAxis1; axis2 = prevAxis2;
29533
+ }
29534
+ for (let j = 0; j < circleDiv; ++j) {
29535
+ let angle = 2 * Math.PI * circleDivInv * j; //* dir + offset;
29536
+ let point = pnts[i].clone().add(axis1.clone().multiplyScalar(Math.cos(angle))).add(axis2.clone().multiplyScalar(Math.sin(angle)));
29537
+ verticeArray[offset++] = point.x;
29538
+ verticeArray[offset++] = point.y;
29539
+ verticeArray[offset++] = point.z;
29540
+
29541
+ color = (i == colors.length - 1 && colors.length > 1) ? me.parasCls.thr(colors[colors.length - 2]) : me.parasCls.thr(colors[i]);
29542
+ colorArray[offset2++] = color.r;
29543
+ colorArray[offset2++] = color.g;
29544
+ colorArray[offset2++] = color.b;
29545
+ }
29546
+ }
29547
+ let offsetTmp = 0, nComp = 3;
29548
+ for (let i = 0, lim = pnts.length - 1; i < lim; ++i) {
29549
+ let reg = 0;
29550
+ //var r1 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv]).lengthSq();
29551
+ //var r2 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv + 1]).lengthSq();
29552
+ let pos = offsetTmp * nComp;
29553
+ let point1 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
29554
+ pos = (offsetTmp + circleDiv) * nComp;
29555
+ let point2 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
29556
+ pos = (offsetTmp + circleDiv + 1) * nComp;
29557
+ let point3 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
29558
+
29559
+ let r1 = point1.clone().sub(point2).lengthSq();
29560
+ let r2 = point1.clone().sub(point3).lengthSq();
29561
+ if (r1 > r2) { r1 = r2; reg = 1; } for (let j = 0; j < circleDiv; ++j) {
29562
+ //geo.faces.push(new THREE.Face3(offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv, undefined, c));
29563
+ //geo.faces.push(new THREE.Face3(offset + (j + 1) % circleDiv, offset + (j + reg) % circleDiv + circleDiv, offset + (j + reg + 1) % circleDiv + circleDiv, undefined, c));
29564
+ //indexArray = indexArray.concat([offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv]);
29565
+ indexArray[offset3++] = offsetTmp + j;
29566
+ indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
29567
+ indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
29568
+
29569
+ //indexArray = indexArray.concat([offset + (j + 1) % circleDiv, offset + (j + reg) % circleDiv + circleDiv, offset + (j + reg + 1) % circleDiv + circleDiv]);
29570
+ indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
29571
+ indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
29572
+ indexArray[offset3++] = offsetTmp + (j + reg + 1) % circleDiv + circleDiv;
29573
+ }
29574
+ offsetTmp += circleDiv;
29373
29575
  }
29374
- */
29576
+
29577
+ geo.setAttribute('position', new THREE.BufferAttribute(new Float32Array(verticeArray), nComp));
29578
+ geo.setAttribute('color', new THREE.BufferAttribute(new Float32Array(colorArray), nComp));
29579
+
29580
+ geo.setIndex(new THREE.BufferAttribute(new Uint32Array(indexArray), 1));
29581
+ //geo.setIndex(indexArray);
29582
+
29583
+ //geo.computeFaceNormals();
29584
+ //geo.computeVertexNormals(false);
29585
+ geo.computeVertexNormals();
29586
+
29375
29587
  let mesh;
29376
29588
  if(bHighlight === 2) {
29377
29589
  //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 }));
@@ -29954,7 +30166,7 @@ class Axes {
29954
30166
  return cone;
29955
30167
  }
29956
30168
 
29957
- setPc1Axes() { let ic = this.icn3d, me = ic.icn3dui;
30169
+ setPc1Axes(bXAxis) { let ic = this.icn3d, me = ic.icn3dui;
29958
30170
  if(me.bNode) return;
29959
30171
 
29960
30172
  let atomHash = me.hashUtilsCls.intHash(ic.hAtoms, ic.dAtoms);
@@ -30035,6 +30247,11 @@ class Axes {
30035
30247
 
30036
30248
  let positionX = center.clone().add(vecX.normalize().multiplyScalar(maxD * 0.4));
30037
30249
 
30250
+ let prinXaxis = vecX.normalize();
30251
+ me.htmlCls.clickMenuCls.setLogCmd('Principle X-Axis: ' + prinXaxis.x.toFixed(3) + " " + prinXaxis.y.toFixed(3) + " " + prinXaxis.z.toFixed(3), false);
30252
+
30253
+ if(bXAxis) return prinXaxis;
30254
+
30038
30255
  let vecY = new THREE.Vector3(eigenRet.h2[0], eigenRet.h2[1], eigenRet.h2[2]);
30039
30256
  let positionY = center.clone().add(vecY.normalize().multiplyScalar(maxD * 0.3));
30040
30257
 
@@ -34253,6 +34470,9 @@ class ApplySymd {
34253
34470
 
34254
34471
  ic.cylinderCls.createCylinder(start, end, axisRadius, colorAxis, 0);
34255
34472
 
34473
+ let SymAxis = end.clone().sub(start).normalize();
34474
+ me.htmlCls.clickMenuCls.setLogCmd('Symmetry Axis: ' + SymAxis.x.toFixed(3) + " " + SymAxis.y.toFixed(3) + " " + SymAxis.z.toFixed(3), false);
34475
+
34256
34476
  if(ic.bAxisOnly) continue;
34257
34477
 
34258
34478
  if(symmetryType == 'C' || (symmetryType == 'D' && order == nSide) ) {
@@ -34409,87 +34629,87 @@ class ApplySymd {
34409
34629
  pointArray.push(end);
34410
34630
  }
34411
34631
  else ;
34412
- }
34413
34632
 
34414
- if(symmetryType == 'T') {
34415
- let pos1 = pointArray[0]; // pointArray: start, end, start, end, ...
34416
- ic.sphereCls.createSphereBase(pos1, colorPolygon, polygonRadius, 1.0, 0);
34633
+ if(symmetryType == 'T') {
34634
+ let pos1 = pointArray[0]; // pointArray: start, end, start, end, ...
34635
+ ic.sphereCls.createSphereBase(pos1, colorPolygon, polygonRadius, 1.0, 0);
34417
34636
 
34418
- let dist2 = pos1.distanceTo(pointArray[2]);
34419
- let dist3 = pos1.distanceTo(pointArray[3]);
34637
+ let dist2 = pos1.distanceTo(pointArray[2]);
34638
+ let dist3 = pos1.distanceTo(pointArray[3]);
34420
34639
 
34421
- let distSmall, posSel;
34422
- if(dist2 < dist3) {
34423
- distSmall = dist2;
34424
- posSel = pointArray[3];
34425
- }
34426
- else {
34427
- distSmall = dist3;
34428
- posSel = pointArray[2];
34429
- }
34640
+ let distSmall, posSel;
34641
+ if(dist2 < dist3) {
34642
+ distSmall = dist2;
34643
+ posSel = pointArray[3];
34644
+ }
34645
+ else {
34646
+ distSmall = dist3;
34647
+ posSel = pointArray[2];
34648
+ }
34430
34649
 
34431
- ic.sphereCls.createSphereBase(posSel, colorPolygon, polygonRadius, 1.0, 0);
34432
- ic.cylinderCls.createCylinder(pos1, posSel, polygonRadius, colorPolygon, 0);
34650
+ ic.sphereCls.createSphereBase(posSel, colorPolygon, polygonRadius, 1.0, 0);
34651
+ ic.cylinderCls.createCylinder(pos1, posSel, polygonRadius, colorPolygon, 0);
34433
34652
 
34434
- let iPrev;
34435
- for(let i = 4, il = pointArray.length; i < il; ++i) {
34436
- let pos2 = pointArray[i];
34653
+ let iPrev;
34654
+ for(let i = 4, il = pointArray.length; i < il; ++i) {
34655
+ let pos2 = pointArray[i];
34437
34656
 
34438
- let dist = pos1.distanceTo(pos2);
34439
- if(dist > distSmall) {
34440
- ic.sphereCls.createSphereBase(pos2, colorPolygon, polygonRadius, 1.0, 0);
34441
- ic.cylinderCls.createCylinder(pos1, pos2, polygonRadius, colorPolygon, 0);
34657
+ let dist = pos1.distanceTo(pos2);
34658
+ if(dist > distSmall) {
34659
+ ic.sphereCls.createSphereBase(pos2, colorPolygon, polygonRadius, 1.0, 0);
34660
+ ic.cylinderCls.createCylinder(pos1, pos2, polygonRadius, colorPolygon, 0);
34442
34661
 
34443
- ic.cylinderCls.createCylinder(posSel, pos2, polygonRadius, colorPolygon, 0);
34444
- if(iPrev !== undefined) {
34445
- ic.cylinderCls.createCylinder(pointArray[iPrev], pos2, polygonRadius, colorPolygon, 0);
34446
- }
34662
+ ic.cylinderCls.createCylinder(posSel, pos2, polygonRadius, colorPolygon, 0);
34663
+ if(iPrev !== undefined) {
34664
+ ic.cylinderCls.createCylinder(pointArray[iPrev], pos2, polygonRadius, colorPolygon, 0);
34665
+ }
34447
34666
 
34448
- iPrev = i;
34667
+ iPrev = i;
34668
+ }
34449
34669
  }
34450
34670
  }
34451
- }
34452
- else if(symmetryType == 'O') {
34453
- for(let i = 0, il = pointArray.length; i < il; i += 2) {
34454
- let pos1 = pointArray[i];
34455
- let pos2 = pointArray[i+1];
34456
- ic.sphereCls.createSphereBase(pos1, colorPolygon, polygonRadius, 1.0, 0);
34457
- ic.sphereCls.createSphereBase(pos2, colorPolygon, polygonRadius, 1.0, 0);
34458
- for(let j = i + 2, jl = pointArray.length; j < jl; ++j) {
34459
- let pos3 = pointArray[j];
34460
- ic.sphereCls.createSphereBase(pos3, colorPolygon, polygonRadius, 1.0, 0);
34461
- ic.cylinderCls.createCylinder(pos1, pos3, polygonRadius, colorPolygon, 0);
34462
- ic.cylinderCls.createCylinder(pos2, pos3, polygonRadius, colorPolygon, 0);
34671
+ else if(symmetryType == 'O') {
34672
+ for(let i = 0, il = pointArray.length; i < il; i += 2) {
34673
+ let pos1 = pointArray[i];
34674
+ let pos2 = pointArray[i+1];
34675
+ ic.sphereCls.createSphereBase(pos1, colorPolygon, polygonRadius, 1.0, 0);
34676
+ ic.sphereCls.createSphereBase(pos2, colorPolygon, polygonRadius, 1.0, 0);
34677
+ for(let j = i + 2, jl = pointArray.length; j < jl; ++j) {
34678
+ let pos3 = pointArray[j];
34679
+ ic.sphereCls.createSphereBase(pos3, colorPolygon, polygonRadius, 1.0, 0);
34680
+ ic.cylinderCls.createCylinder(pos1, pos3, polygonRadius, colorPolygon, 0);
34681
+ ic.cylinderCls.createCylinder(pos2, pos3, polygonRadius, colorPolygon, 0);
34682
+ }
34463
34683
  }
34464
34684
  }
34465
- }
34466
- else if(symmetryType == 'I') {
34467
- for(let i = 0, il = pointArray.length; i < il; i += 2) {
34468
- let pos1 = pointArray[i];
34469
- let pos2 = pointArray[i+1];
34470
- ic.sphereCls.createSphereBase(pos1, colorPolygon, polygonRadius, 1.0, 0);
34471
- ic.sphereCls.createSphereBase(pos2, colorPolygon, polygonRadius, 1.0, 0);
34472
- for(let j = i + 2, jl = pointArray.length; j < jl; j += 2) {
34473
- let pos3 = pointArray[j];
34474
- let pos4 = pointArray[j+1];
34685
+ else if(symmetryType == 'I') {
34686
+ for(let i = 0, il = pointArray.length; i < il; i += 2) {
34687
+ let pos1 = pointArray[i];
34688
+ let pos2 = pointArray[i+1];
34689
+ ic.sphereCls.createSphereBase(pos1, colorPolygon, polygonRadius, 1.0, 0);
34690
+ ic.sphereCls.createSphereBase(pos2, colorPolygon, polygonRadius, 1.0, 0);
34691
+ for(let j = i + 2, jl = pointArray.length; j < jl; j += 2) {
34692
+ let pos3 = pointArray[j];
34693
+ let pos4 = pointArray[j+1];
34475
34694
 
34476
- let dist3 = pos1.distanceTo(pos3);
34477
- let dist4 = pos1.distanceTo(pos4);
34695
+ let dist3 = pos1.distanceTo(pos3);
34696
+ let dist4 = pos1.distanceTo(pos4);
34478
34697
 
34479
- let pos1Sel, pos2Sel;
34480
- if(dist3 < dist4) {
34481
- pos1Sel = pos3;
34482
- pos2Sel = pos4;
34483
- }
34484
- else {
34485
- pos1Sel = pos4;
34486
- pos2Sel = pos3;
34487
- }
34698
+ let pos1Sel, pos2Sel;
34699
+ if(dist3 < dist4) {
34700
+ pos1Sel = pos3;
34701
+ pos2Sel = pos4;
34702
+ }
34703
+ else {
34704
+ pos1Sel = pos4;
34705
+ pos2Sel = pos3;
34706
+ }
34488
34707
 
34489
- ic.sphereCls.createSphereBase(pos1Sel, colorPolygon, polygonRadius, 1.0, 0);
34490
- ic.sphereCls.createSphereBase(pos2Sel, colorPolygon, polygonRadius, 1.0, 0);
34491
- ic.cylinderCls.createCylinder(pos1, pos1Sel, polygonRadius, colorPolygon, 0);
34492
- ic.cylinderCls.createCylinder(pos2, pos2Sel, polygonRadius, colorPolygon, 0);
34708
+ ic.sphereCls.createSphereBase(pos1Sel, colorPolygon, polygonRadius, 1.0, 0);
34709
+ ic.sphereCls.createSphereBase(pos2Sel, colorPolygon, polygonRadius, 1.0, 0);
34710
+ ic.cylinderCls.createCylinder(pos1, pos1Sel, polygonRadius, colorPolygon, 0);
34711
+ ic.cylinderCls.createCylinder(pos2, pos2Sel, polygonRadius, colorPolygon, 0);
34712
+ }
34493
34713
  }
34494
34714
  }
34495
34715
  }
@@ -44326,7 +44546,7 @@ class AddTrack {
44326
44546
 
44327
44547
  }
44328
44548
 
44329
- showNewTrack(chnid, title, text, cssColorArray, inTarget2queryHash, type, color, bMsa, fromArray, toArray, seqStartLen, exonArray) { let ic = this.icn3d, me = ic.icn3dui;
44549
+ showNewTrack(chnid, title, text, cssColorArray, inTarget2queryHash, type, color, bMsa, fromArray, toArray, seqStartLen, exonArray, offsetArray) { let ic = this.icn3d, me = ic.icn3dui;
44330
44550
  //if(ic.customTracks[chnid] === undefined) {
44331
44551
  // ic.customTracks[chnid] = {}
44332
44552
  //}
@@ -44544,14 +44764,16 @@ class AddTrack {
44544
44764
 
44545
44765
  if(fromArray !== undefined) {
44546
44766
  htmlTmp2 = '';
44547
- let fromArray2 = [], toArray2 = [];
44767
+ let fromArray2 = [], toArray2 = [], offsetArray2 = [];
44548
44768
  for(let i = 0, il = fromArray.length; i < il; ++i) {
44549
44769
  fromArray2.push(fromArray[i]);
44770
+ offsetArray2.push(offsetArray[i]);
44550
44771
 
44551
44772
  for(let j = parseInt(fromArray[i]); j <= parseInt(toArray[i]); ++j) {
44552
44773
  if(ic.targetGapHash !== undefined && ic.targetGapHash.hasOwnProperty(j)) {
44553
44774
  toArray2.push(j - 1);
44554
44775
  fromArray2.push(j);
44776
+ offsetArray2.push(offsetArray[i]);
44555
44777
  }
44556
44778
  }
44557
44779
 
@@ -44585,6 +44807,7 @@ class AddTrack {
44585
44807
  // determine how this range sits in the exon ranges in exonArray
44586
44808
  let startExon, endExon;
44587
44809
 
44810
+ let offset = offsetArray2[i];
44588
44811
  cnt = toArray[i] - fromArray[i] + 1;
44589
44812
  let from = prevCntTotal, to = prevCntTotal + cnt - 1;
44590
44813
 
@@ -44613,26 +44836,26 @@ class AddTrack {
44613
44836
  endColorStr = this.getExonColor(startExon.rangeStart, startExon.rangeEnd, to);
44614
44837
 
44615
44838
  colorGradient = startColorStr + ' 0%, #FFF 50%, ' + endColorStr + ' 100%';
44616
- htmlTmp2 += this.getExonHtml(startExon.exonIndex, colorGradient, startExon.from, endExon.to, startExon.genomeRange, chnid, simpTitle);
44839
+ htmlTmp2 += this.getExonHtml(startExon.exonIndex, colorGradient, startExon.from, endExon.to, startExon.genomeRange, chnid, simpTitle, offset);
44617
44840
  }
44618
44841
  else {
44619
44842
  if(startExon) {
44620
44843
  startColorStr = this.getExonColor(startExon.rangeStart, startExon.rangeEnd, from);
44621
44844
 
44622
44845
  colorGradient = startColorStr + ' 0%, #FFF 50%, #00F 100%';
44623
- htmlTmp2 += this.getExonHtml(startExon.exonIndex, colorGradient, startExon.from, startExon.rangeEnd, startExon.genomeRange, chnid, simpTitle);
44846
+ htmlTmp2 += this.getExonHtml(startExon.exonIndex, colorGradient, startExon.from, startExon.rangeEnd, startExon.genomeRange, chnid, simpTitle, offset);
44624
44847
  }
44625
44848
 
44626
44849
  if(startExon && endExon) {
44627
44850
  for(let j = startExon.exonIndex + 1; j < endExon.exonIndex; ++j) {
44628
44851
  colorGradient = '#F00 0%, #FFF 50%, #00F 100%';
44629
- htmlTmp2 += this.getExonHtml(j, colorGradient, exonArray[j].resStart, exonArray[j].resEnd, exonArray[j].genomeRange, chnid, simpTitle);
44852
+ htmlTmp2 += this.getExonHtml(j, colorGradient, exonArray[j].resStart, exonArray[j].resEnd, exonArray[j].genomeRange, chnid, simpTitle, offset);
44630
44853
  }
44631
44854
 
44632
44855
  endColorStr = this.getExonColor(endExon.rangeStart, endExon.rangeEnd, to);
44633
44856
 
44634
44857
  colorGradient = '#F00 0%, #FFF 50%, ' + endColorStr + ' 100%';
44635
- htmlTmp2 += this.getExonHtml(endExon.exonIndex, colorGradient, endExon.rangeStart, endExon.to, endExon.genomeRange, chnid, simpTitle);
44858
+ htmlTmp2 += this.getExonHtml(endExon.exonIndex, colorGradient, endExon.rangeStart, endExon.to, endExon.genomeRange, chnid, simpTitle, offset);
44636
44859
  }
44637
44860
  }
44638
44861
 
@@ -44666,9 +44889,8 @@ class AddTrack {
44666
44889
  }
44667
44890
  }
44668
44891
 
44669
- getExonHtml(exonIndex, colorGradient, from, to, genomeRange, chainid, simpTitle) { let ic = this.icn3d; ic.icn3dui;
44670
- // 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>';
44671
- 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>';
44892
+ getExonHtml(exonIndex, colorGradient, from, to, genomeRange, chainid, simpTitle, offset) { let ic = this.icn3d; ic.icn3dui;
44893
+ 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>';
44672
44894
  }
44673
44895
 
44674
44896
  getExonColor(start, end, pos) { let ic = this.icn3d; ic.icn3dui;
@@ -45409,7 +45631,7 @@ class AddTrack {
45409
45631
  let targetId = 'genomeRes';
45410
45632
 
45411
45633
  let acc2index = {};
45412
-
45634
+
45413
45635
  for(let index = 0, indexl = accArray.length; index < indexl; ++index) {
45414
45636
  let acc = accArray[index];
45415
45637
 
@@ -45494,22 +45716,24 @@ class AddTrack {
45494
45716
  trackSeqArrayFinal[i] = '';
45495
45717
  }
45496
45718
 
45497
- for(let j = 0, jl = trackSeqArray[maxIndex].length; j < jl; ++j) {
45498
- let seq = trackSeqArray[maxIndex][j];
45719
+ if(trackSeqArray[maxIndex]) {
45720
+ for(let j = 0, jl = trackSeqArray[maxIndex].length; j < jl; ++j) {
45721
+ let seq = trackSeqArray[maxIndex][j];
45499
45722
 
45500
- let bExon = (seq != '-') ? true : false;
45501
- if(!bExon) {
45502
- for(let i = 0, il = trackSeqArray.length; i < il; ++i) {
45503
- if(trackSeqArray[i][j] != '-') {
45504
- bExon = true;
45505
- break;
45723
+ let bExon = (seq != '-') ? true : false;
45724
+ if(!bExon) {
45725
+ for(let i = 0, il = trackSeqArray.length; i < il; ++i) {
45726
+ if(trackSeqArray[i][j] != '-') {
45727
+ bExon = true;
45728
+ break;
45729
+ }
45506
45730
  }
45507
45731
  }
45508
- }
45509
-
45510
- if(bExon) {
45511
- for(let i = 0, il = trackSeqArray.length; i < il; ++i) {
45512
- trackSeqArrayFinal[i] += trackSeqArray[i][j];
45732
+
45733
+ if(bExon) {
45734
+ for(let i = 0, il = trackSeqArray.length; i < il; ++i) {
45735
+ trackSeqArrayFinal[i] += trackSeqArray[i][j];
45736
+ }
45513
45737
  }
45514
45738
  }
45515
45739
  }
@@ -45580,7 +45804,9 @@ class AddTrack {
45580
45804
  ic.maxAnnoLength = ic.maxAnnoLengthOri + ic.seqStartLen[chainid] + ic.seqEndLen[chainid];
45581
45805
  }
45582
45806
 
45583
- await ic.annotationCls.resetAnnoAll();
45807
+ // do not remove other tracks
45808
+ // await ic.annotationCls.resetAnnoAll();
45809
+ await ic.showAnnoCls.processSeqData(ic.chainid_seq);
45584
45810
 
45585
45811
  let targetGapHashStr = '';
45586
45812
  let cntTmp = 0;
@@ -45611,6 +45837,7 @@ class AddTrack {
45611
45837
  let fromArray = [], toArray = [];
45612
45838
  let bFound = false;
45613
45839
  let seqStartLen = 0;
45840
+ let offset = 0, offsetArray = [];
45614
45841
  // for(let k = seqStart; k <= seqEnd; ++k) {
45615
45842
  for(let k = 0; k < seqLength; ++k) {
45616
45843
  //if(seqFirst[k] == '-') continue;
@@ -45619,19 +45846,29 @@ class AddTrack {
45619
45846
 
45620
45847
  resn = trackSeqArray[j][k];
45621
45848
 
45849
+ if(resn != '-') {
45850
+ if(!bFound) {
45851
+ seqStartLen = k;
45852
+ bFound = true;
45853
+
45854
+ offset = ic.startposGiSeq - ic.seqStartLen[chainid] + seqStartLen;
45855
+ }
45856
+ }
45857
+
45622
45858
  if(prevResn == '-' && resn != '-') {
45623
45859
  fromArray.push(k);
45860
+ offsetArray.push(offset);
45624
45861
  }
45625
45862
 
45626
45863
  if(prevResn != '-' && resn == '-') {
45627
45864
  toArray.push(k - 1);
45628
45865
  }
45629
45866
 
45630
- if(resn != '-') {
45631
- if(!bFound) {
45632
- seqStartLen = k;
45633
- bFound = true;
45634
- }
45867
+ // use "offset" to adjut the residue numbers, e.g., P20138
45868
+ // some isoforms starts residues before the first residue in the template sequence
45869
+ if(k >= ic.seqStartLen[chainid]) {
45870
+ if(seqFirst[k] == '-') offset--;
45871
+ if(resn == '-') offset++;
45635
45872
  }
45636
45873
 
45637
45874
  text += resn; //ic.giSeq[chainid][i];
@@ -45652,7 +45889,7 @@ class AddTrack {
45652
45889
  let title =(trackTitleArray[j].length < 20) ? trackTitleArray[j] : trackTitleArray[j].substr(0, 20) + '...';
45653
45890
  let bMsa = true;
45654
45891
  let exonArray = (acc2exons) ? acc2exons[trackTitleArray[j]] : undefined;
45655
- this.showNewTrack(chainid, title, text, undefined, undefined, type, undefined, bMsa, fromArray, toArray, seqStartLen, exonArray);
45892
+ this.showNewTrack(chainid, title, text, undefined, undefined, type, undefined, bMsa, fromArray, toArray, seqStartLen, exonArray, offsetArray);
45656
45893
  }
45657
45894
 
45658
45895
  // update exon color
@@ -45747,7 +45984,7 @@ class AddTrack {
45747
45984
 
45748
45985
  let type = 'identity';
45749
45986
 
45750
- await thisClass.addExonTracks(chainid, geneid, startpos, type);
45987
+ await this.addExonTracks(chainid, geneid, startpos, type);
45751
45988
  }
45752
45989
 
45753
45990
  async addExonTracks(chainid, geneid, startpos, type) { let ic = this.icn3d, me = ic.icn3dui;
@@ -45782,13 +46019,12 @@ class AddTrack {
45782
46019
  let cnt = (j == jl - 1) ? itemArray[2] - 3 : itemArray[2]; // The last one is stop codeon
45783
46020
  cntTotal += cnt;
45784
46021
 
45785
- let resStart = parseInt(prevCntTotal/3.0 + 0.5); // 0-based
45786
- let resEnd = parseInt(cntTotal/3.0 + 0.5) - 1; // 0-based
46022
+ let resStart = parseInt((prevCntTotal+2)/3.0); // 0-based
46023
+ let resEnd = parseInt((cntTotal+2)/3.0) - 1; // 0-based
45787
46024
 
45788
- let genResStart = parseInt(itemArray[0] / 3.0 + 0.5);
45789
-
45790
- //let genResEnd = parseInt(itemArray[1] / 3.0 + 0.5); // some difference due to round
45791
- let genResEnd = genResStart + ic.exonOrder * (resEnd - resStart);
46025
+ let genResEnd = parseInt((itemArray[1]+2) / 3.0);
46026
+ // let genResStart = parseInt((itemArray[0]+2) / 3.0); // some difference due to round
46027
+ let genResStart = genResEnd - ic.exonOrder * (resEnd - resStart);
45792
46028
 
45793
46029
  rangeArray.push({genomeRange: genomeRange, genResStart: genResStart, genResEnd: genResEnd, resStart: resStart, resEnd: resEnd});
45794
46030
 
@@ -45842,7 +46078,7 @@ class AddTrack {
45842
46078
 
45843
46079
  let ALen = trackSeqArray.length;
45844
46080
 
45845
- while (i < A.length && j < B.length) {
46081
+ while (A && B && i < A.length && j < B.length) {
45846
46082
  if(A[i] != B[j]) {
45847
46083
  if(A[i] == '-') {
45848
46084
  // insert "-" in B
@@ -52461,8 +52697,10 @@ class ChainalignParser {
52461
52697
  //$.when(ic.pdbParserCls.applyCommandDssp(true)).then(function() {
52462
52698
  await ic.pdbParserCls.applyCommandDssp(true);
52463
52699
 
52700
+ // original version =============
52464
52701
  // align PDB chains
52465
52702
  for(let index in ic.pdbChainIndexHash) {
52703
+ //ic.pdbChainIndexHash[index] = mmdbid_q_tmp + "_" + ic.chain_q + "_" + ic.mmdbid_t + "_" + ic.chain_t;
52466
52704
  let idArray = ic.pdbChainIndexHash[index].split('_');
52467
52705
  mmdbid_q = idArray[0];
52468
52706
  idArray[1];
@@ -52477,25 +52715,49 @@ class ChainalignParser {
52477
52715
  let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
52478
52716
  let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
52479
52717
 
52718
+ let resRangeArray = (me.cfg.resrange) ? me.cfg.resrange.split(' | ') : [];
52719
+
52480
52720
  for(let index in ic.afChainIndexHash) {
52481
52721
  let idArray = ic.afChainIndexHash[index].split('_');
52482
52722
  mmdbid_q = idArray[0];
52483
52723
  let chain_q = idArray[1];
52724
+ let chainid_q = mmdbid_q + '_' + chain_q;
52725
+
52484
52726
  mmdbid_t = idArray[2];
52485
52727
  let chain_t = idArray[3];
52728
+ let chainid_t = mmdbid_t + '_' + chain_t;
52729
+
52730
+ let atomSet_t = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[0].split(','), chainid_t).hAtoms : ic.chains[chainid_t];
52731
+ let atomSet_q = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[index].split(','), chainid_q).hAtoms : ic.chains[chainid_q];
52732
+ // end of original version =============
52733
+
52734
+ /*
52735
+ // new version to be done for VASTsrv ==============
52736
+ // dynamically align pairs in all chainids
52737
+ let ajaxArray = [], indexArray = [], struArray = [];
52738
+ let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi";
52739
+ let urltmalign = me.htmlCls.baseUrl + "tmalign/tmalign.cgi";
52740
+
52741
+ let resRangeArray = (me.cfg.resrange) ? me.cfg.resrange.split(' | ') : [];
52742
+
52743
+ // dynamically align pairs in all chainids
52744
+ let atomSet_t = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[0].split(','), chainidArray[0]).hAtoms : ic.chains[chainidArray[0]];
52745
+ for(let index = 1, indexl = chainidArray.length; index < indexl; ++index) {
52746
+ let atomSet_q = (me.cfg.resrange) ? ic.realignParserCls.getSeqCoorResid(resRangeArray[index].split(','), chainidArray[index]).hAtoms : ic.chains[chainidArray[index]];
52747
+ // end of new version to be done for VASTsrv ==============
52748
+ */
52486
52749
 
52487
52750
  let alignAjax;
52488
52751
  if(me.cfg.aligntool != 'tmalign') {
52489
- let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(ic.chains[mmdbid_q + '_' + chain_q]);
52490
- let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(ic.chains[mmdbid_t + '_' + chain_t]);
52752
+ let jsonStr_q = ic.domain3dCls.getDomainJsonForAlign(atomSet_q);
52753
+ let jsonStr_t = ic.domain3dCls.getDomainJsonForAlign(atomSet_t);
52491
52754
 
52492
52755
  let dataObj = {'domains1': jsonStr_q, 'domains2': jsonStr_t};
52493
52756
  alignAjax = me.getAjaxPostPromise(urlalign, dataObj);
52494
52757
  }
52495
52758
  else {
52496
- let pdb_query = ic.saveFileCls.getAtomPDB(ic.chains[mmdbid_q + '_' + chain_q]);
52497
-
52498
- let pdb_target= ic.saveFileCls.getAtomPDB(ic.chains[mmdbid_t + '_' + chain_t]);
52759
+ let pdb_query = ic.saveFileCls.getAtomPDB(atomSet_q);
52760
+ let pdb_target= ic.saveFileCls.getAtomPDB(atomSet_t);
52499
52761
 
52500
52762
  let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target};
52501
52763
  alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
@@ -52898,7 +53160,7 @@ class ChainalignParser {
52898
53160
  return chainidArray;
52899
53161
  }
52900
53162
 
52901
- async downloadChainalignment(chainalign, resnum, resdef) { let ic = this.icn3d, me = ic.icn3dui;
53163
+ async downloadChainalignment(chainalign) { let ic = this.icn3d, me = ic.icn3dui;
52902
53164
  let thisClass = this;
52903
53165
 
52904
53166
  ic.opts['proteins'] = 'c alpha trace';
@@ -53175,7 +53437,7 @@ class ChainalignParser {
53175
53437
  async loadOpmDataForChainalign(data1, data2, chainidArray, mmdbidArray) { let ic = this.icn3d, me = ic.icn3dui;
53176
53438
  let thisClass = this;
53177
53439
 
53178
- if(me.cfg.resnum || me.cfg.resdef) {
53440
+ if(me.cfg.resnum || me.cfg.resdef || me.cfg.resrange) {
53179
53441
  if(!ic.bCommandLoad) ic.init(); // remove all previously loaded data
53180
53442
  await this.downloadChainalignmentPart2(data1, data2, undefined, chainidArray);
53181
53443
 
@@ -57651,13 +57913,7 @@ class RealignParser {
57651
57913
 
57652
57914
  let allPromise = Promise.allSettled(ajaxArray);
57653
57915
  // try {
57654
- // let dataArray = await allPromise;
57655
-
57656
- let startDate = new Date();
57657
57916
  let dataArray = await allPromise;
57658
- let endDate = new Date();
57659
- let miliseconds = (endDate.getTime() - startDate.getTime());
57660
- console.log("vastdyn time: " + miliseconds + " miliseconds");
57661
57917
 
57662
57918
  ic.qt_start_end = []; // reset the alignment
57663
57919
  await ic.chainalignParserCls.downloadChainalignmentPart2bRealign(dataArray, chainidPairArray, bReverse);
@@ -57749,6 +58005,8 @@ class RealignParser {
57749
58005
  async realignChainOnSeqAlign(chainresiCalphaHash2, chainidArray, bRealign, bPredefined) { let ic = this.icn3d, me = ic.icn3dui;
57750
58006
  let thisClass = this;
57751
58007
 
58008
+ me.cfg.aligntool = 'seqalign';
58009
+
57752
58010
  //bRealign: realign based on seq alignment
57753
58011
  //bPredefined: chain alignment with predefined matching residues
57754
58012
 
@@ -58056,6 +58314,7 @@ class DensityCifParser {
58056
58314
 
58057
58315
  //https://www.ebi.ac.uk/pdbe/densities/doc.html
58058
58316
  if(type == '2fofc' || type == 'fofc') {
58317
+ detail = 0;
58059
58318
  url = "https://www.ebi.ac.uk/pdbe/densities/x-ray/" + pdbid.toLowerCase() + "/cell?detail=" + detail;
58060
58319
  }
58061
58320
  else if(type == 'em') {
@@ -58096,6 +58355,39 @@ class DensityCifParser {
58096
58355
  }
58097
58356
  }
58098
58357
 
58358
+ async densityCifParserBase(url, type, sigma, location, bInputSigma) { let ic = this.icn3d, me = ic.icn3dui;
58359
+ let thisClass = this;
58360
+
58361
+ //https://stackoverflow.com/questions/33902299/using-jquery-ajax-to-download-a-binary-file
58362
+ if(type == '2fofc' && ic.bAjax2fofc) {
58363
+ ic.mapData.sigma2 = sigma;
58364
+ ic.setOptionCls.setOption('map', type);
58365
+ }
58366
+ else if(type == 'fofc' && ic.bAjaxfofc) {
58367
+ ic.mapData.sigma = sigma;
58368
+ ic.setOptionCls.setOption('map', type);
58369
+ }
58370
+ else {
58371
+ let arrayBuffer = await me.getXMLHttpRqstPromise(url, 'GET', 'arraybuffer', type);
58372
+
58373
+ thisClass.parseChannels(arrayBuffer, type, sigma);
58374
+
58375
+ if(type == '2fofc' || type == 'fofc') {
58376
+ ic.bAjax2fofc = true;
58377
+ ic.bAjaxfofc = true;
58378
+
58379
+ ic.setOptionCls.setOption('map', type);
58380
+ }
58381
+ else if(type == 'em') {
58382
+ ic.bAjaxEm = true;
58383
+
58384
+ ic.setOptionCls.setOption('emmap', type);
58385
+ }
58386
+ }
58387
+
58388
+ // return sigma;
58389
+ }
58390
+
58099
58391
  parseChannels(densitydata, type, sigma) { let ic = this.icn3d; ic.icn3dui;
58100
58392
  let cif = this.BinaryParse(densitydata);
58101
58393
 
@@ -59946,9 +60238,11 @@ class LoadAtomData {
59946
60238
  serial2structure[j] = pdbidTmp.toString();
59947
60239
  mmdbid2pdbid[mmdbidTmp] = pdbidTmp;
59948
60240
  }
59949
-
60241
+
59950
60242
  for(let j = 0, jl = structure.molecules.length; j < jl; ++j) {
59951
60243
  let chain = structure.molecules[j].chain;
60244
+ chain = chain.replace(/_/g, ''); // change "A_1" to "A1"
60245
+
59952
60246
  let kind = structure.molecules[j].kind;
59953
60247
  let title = structure.molecules[j].name;
59954
60248
  //var seq = structure.molecules[j].sequence;
@@ -60941,7 +61235,9 @@ class SetSeqAlign {
60941
61235
 
60942
61236
  let resid = chainid + '_' + resi;
60943
61237
  let resn = ic.residueId2Name[resid];
60944
- if(!resn) resn = '?';
61238
+ if(!resn) {
61239
+ resn = '?';
61240
+ }
60945
61241
 
60946
61242
  return resn;
60947
61243
  }
@@ -63084,7 +63380,7 @@ class LoadCIF {
63084
63380
 
63085
63381
  let bFirstAtom = true;
63086
63382
 
63087
- let cifArray = bcifData.split('ENDMDL\n');
63383
+ let cifArray = (bText) ? bcifData.split('ENDMDL\n') : [bcifData];
63088
63384
 
63089
63385
  for(let index = 0, indexl = cifArray.length; index < indexl; ++index) {
63090
63386
  ++moleculeNum;
@@ -65653,7 +65949,21 @@ class ApplyCommand {
65653
65949
  let nameArray2 = setNameArray[1].split(',');
65654
65950
 
65655
65951
  ic.analysisCls.measureDistManySets(nameArray, nameArray2);
65656
- me.htmlCls.dialogCls.openDlg('dl_disttable', 'Distance among the sets');
65952
+ me.htmlCls.dialogCls.openDlg('dl_disttable', 'Distances among the sets');
65953
+ }
65954
+ }
65955
+ }
65956
+ else if(commandOri.indexOf('angletable') == 0) {
65957
+ let paraArray = commandOri.split(' | ');
65958
+ if(paraArray.length == 2) {
65959
+ let setNameArray = paraArray[1].split(' ');
65960
+
65961
+ if(setNameArray.length == 2) {
65962
+ let nameArray = setNameArray[0].split(',');
65963
+ let nameArray2 = setNameArray[1].split(',');
65964
+
65965
+ ic.analysisCls.measureAngleManySets(nameArray, nameArray2);
65966
+ me.htmlCls.dialogCls.openDlg('dl_angletable', 'Angles among the sets');
65657
65967
  }
65658
65968
  }
65659
65969
  }
@@ -66061,6 +66371,16 @@ class ApplyCommand {
66061
66371
  ic.transformCls.rotateCoord(ic.hAtoms, mArrayFloat);
66062
66372
  ic.drawCls.draw();
66063
66373
  }
66374
+ else if(command.indexOf('set dssp sse') == 0) {
66375
+ await ic.pdbParserCls.applyCommandDssp();
66376
+ ic.bResetAnno = true;
66377
+
66378
+ if(ic.bAnnoShown) {
66379
+ await ic.showAnnoCls.showAnnotations();
66380
+
66381
+ ic.annotationCls.resetAnnoTabAll();
66382
+ }
66383
+ }
66064
66384
 
66065
66385
  // special, select ==========
66066
66386
 
@@ -67261,9 +67581,9 @@ class SelectCollections {
67261
67581
  'chemicals': {},
67262
67582
  'ions': {},
67263
67583
  'water': {},
67264
- 'structures': {}, // getSSExpandedAtoms
67584
+ 'structures': {},
67265
67585
  'ssbondpnts': {},
67266
- 'residues': {}, // getSSExpandedAtoms
67586
+ 'residues': {},
67267
67587
  'chains': {},
67268
67588
  'chainsSeq': {}, //Sequences and Annotation
67269
67589
  'defNames2Atoms': {},
@@ -67312,9 +67632,9 @@ class SelectCollections {
67312
67632
  'chemicals': ic.chemicals,
67313
67633
  'ions': ic.ions,
67314
67634
  'water': ic.water,
67315
- 'structures': ic.structures, // getSSExpandedAtoms
67635
+ 'structures': ic.structures,
67316
67636
  'ssbondpnts': ic.ssbondpnts,
67317
- 'residues': ic.residues, // getSSExpandedAtoms
67637
+ 'residues': ic.residues,
67318
67638
  'chains': ic.chains,
67319
67639
  'chainsSeq': ic.chainsSeq, //Sequences and Annotation
67320
67640
  'defNames2Atoms': ic.defNames2Atoms,
@@ -67328,9 +67648,9 @@ class SelectCollections {
67328
67648
  'chemicals': thisClass.dictionaryDifference(ic.allData['prev']['chemicals'], ic.chemicals),
67329
67649
  'ions': thisClass.dictionaryDifference(ic.allData['prev']['ions'], ic.ions),
67330
67650
  'water': thisClass.dictionaryDifference(ic.allData['prev']['water'], ic.water),
67331
- 'structures': thisClass.dictionaryDifference(ic.allData['prev']['structures'], ic.structures), // getSSExpandedAtoms
67651
+ 'structures': thisClass.dictionaryDifference(ic.allData['prev']['structures'], ic.structures),
67332
67652
  'ssbondpnts': thisClass.dictionaryDifference(ic.allData['prev']['ssbondpnts'], ic.ssbondpnts),
67333
- 'residues': thisClass.dictionaryDifference(ic.allData['prev']['residues'], ic.residues), // getSSExpandedAtoms
67653
+ 'residues': thisClass.dictionaryDifference(ic.allData['prev']['residues'], ic.residues),
67334
67654
  'chains': thisClass.dictionaryDifference(ic.allData['prev']['chains'], ic.chains),
67335
67655
  'chainsSeq': thisClass.dictionaryDifference(ic.allData['prev']['chainsSeq'], ic.chainsSeq), //Sequences and Annotation
67336
67656
  'defNames2Atoms': thisClass.dictionaryDifference(ic.allData['prev']['defNames2Atoms'], ic.defNames2Atoms),
@@ -68043,20 +68363,23 @@ class LoadScript {
68043
68363
  }
68044
68364
  }
68045
68365
  else if(command.indexOf('load chainalignment') !== -1) {
68046
- //load chainalignment [id] | resnum [resnum] | resdef [resnum] | aligntool [aligntool] | parameters [inpara]
68366
+ //load chainalignment [id] | resnum [resnum] | resdef [resdef] | aligntool [aligntool] | parameters [inpara] | resrange [resrange]
68047
68367
  let urlArray = command.split(" | ");
68048
68368
  if(urlArray.length > 1 && urlArray[1].indexOf('resnum') != -1) {
68049
68369
  me.cfg.resnum = urlArray[1].substr(urlArray[1].indexOf('resnum') + 7);
68050
68370
  }
68051
68371
  if(urlArray.length > 2 && urlArray[2].indexOf('resdef') != -1) {
68052
- me.cfg.resdef = urlArray[2].substr(urlArray[1].indexOf('resdef') + 7);
68372
+ me.cfg.resdef = urlArray[2].substr(urlArray[2].indexOf('resdef') + 7);
68053
68373
  }
68054
68374
  if(urlArray.length > 3 && urlArray[3].indexOf('aligntool') != -1) {
68055
- me.cfg.aligntool = urlArray[3].substr(urlArray[1].indexOf('aligntool') + 10);
68375
+ me.cfg.aligntool = urlArray[3].substr(urlArray[3].indexOf('aligntool') + 10);
68376
+ }
68377
+ if(urlArray.length > 5 && urlArray[5].indexOf('resrange') != -1) {
68378
+ me.cfg.resrange = urlArray[5].substr(urlArray[5].indexOf('resrange') + 9);
68056
68379
  }
68057
68380
 
68058
68381
  me.cfg.chainalign = id;
68059
- await ic.chainalignParserCls.downloadChainalignment(id, me.cfg.resnum, me.cfg.resdef);
68382
+ await ic.chainalignParserCls.downloadChainalignment(id);
68060
68383
  }
68061
68384
  else if(command.indexOf('load url') !== -1) {
68062
68385
  let typeStr = load_parameters[1]; // type pdb
@@ -68105,7 +68428,8 @@ class LoadScript {
68105
68428
  if(urlArray.length == 2) {
68106
68429
  let bInputSigma = true;
68107
68430
  if(fileType == 'dsn6') {
68108
- await ic.dsn6ParserCls.dsn6ParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
68431
+ // await ic.dsn6ParserCls.dsn6ParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
68432
+ await ic.densityCifParserCls.densityCifParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
68109
68433
  }
68110
68434
  else if(fileType == 'ccp4') {
68111
68435
  await ic.ccp4ParserCls.ccp4ParserBase(urlArray[1], type, sigma, 'url', bInputSigma);
@@ -68118,7 +68442,8 @@ class LoadScript {
68118
68442
  }
68119
68443
  }
68120
68444
  else {
68121
- await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma);
68445
+ // await ic.dsn6ParserCls.dsn6Parser(ic.inputid, type, sigma);
68446
+ await ic.densityCifParserCls.densityCifParser(ic.inputid, type, sigma);
68122
68447
  }
68123
68448
  }
68124
68449
  // }); // end of me.deferred = $.Deferred(function() {
@@ -74145,7 +74470,73 @@ class Analysis {
74145
74470
 
74146
74471
  $("#" + me.pre + "dl_disttable_html").html(tableHtml);
74147
74472
  }
74148
- }
74473
+ }
74474
+
74475
+ measureAngleManySets(nameArray, nameArray2) {var ic = this.icn3d, me = ic.icn3dui;
74476
+ if(nameArray.length == 0 || nameArray2.length == 0) {
74477
+ var aaa = 1; //alert("Please select sets for angleance calculation...");
74478
+ }
74479
+ else {
74480
+ let angleHash = {};
74481
+
74482
+ for(let i = 0, il = nameArray.length; i < il; ++i) {
74483
+ let set1 = nameArray[i];
74484
+ let array1 = [set1];
74485
+ angleHash[set1] = {};
74486
+
74487
+ ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(array1);
74488
+ let axis1 = ic.axesCls.setPc1Axes(true);
74489
+
74490
+ for(let j = 0, jl = nameArray2.length; j < jl; ++j) {
74491
+ let set2 = nameArray2[j];
74492
+ let array2 = [set2];
74493
+
74494
+ if(set1 == set2) continue;
74495
+
74496
+ ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(array2);
74497
+ let axis2 = ic.axesCls.setPc1Axes(true);
74498
+
74499
+ 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)));
74500
+
74501
+ let angle = angleRad / 3.1416 * 180;
74502
+ angle = Math.abs(angle).toFixed(0);
74503
+ if(angle > 180) angle -= 180;
74504
+ if(angle > 90) angle = 180 - angle;
74505
+
74506
+ angleHash[set1][set2] = angle;
74507
+ }
74508
+ }
74509
+
74510
+ let tableHtml = '<table align=center border=1 cellpadding=10 cellspacing=0><tr><th></th>';
74511
+ for(let j = 0, jl = nameArray2.length; j < jl; ++j) {
74512
+ let set2 = nameArray2[j];
74513
+ tableHtml += '<th><b>' + set2 + '</b> (&deg;)</th>';
74514
+ }
74515
+ tableHtml += '</tr>';
74516
+
74517
+ for(let i = 0, il = nameArray.length; i < il; ++i) {
74518
+ let set1 = nameArray[i];
74519
+ tableHtml += '<tr><th><b>' + set1 + '</b> (&deg;)</th>';
74520
+
74521
+ for(let j = 0, jl = nameArray2.length; j < jl; ++j) {
74522
+ let set2 = nameArray2[j];
74523
+
74524
+ if(angleHash[set1] && angleHash[set1][set2]) {
74525
+ tableHtml += '<td><span>' + angleHash[set1][set2] + '</span></td>';
74526
+ }
74527
+ else {
74528
+ tableHtml += '<td>0</td>';
74529
+ }
74530
+ }
74531
+
74532
+ tableHtml += '</tr>';
74533
+ }
74534
+
74535
+ tableHtml += '</table><br><br>';
74536
+
74537
+ $("#" + me.pre + "dl_angletable_html").html(tableHtml);
74538
+ }
74539
+ }
74149
74540
 
74150
74541
  //Add a line between the position (x1, y1, z1) and the position (x2, y2, z2) with the input "color".
74151
74542
  //The line can be dashed if "dashed" is set true.
@@ -77988,7 +78379,8 @@ class ShareLink {
77988
78379
  }
77989
78380
  else {
77990
78381
  text += "\nStart of type file======\n";
77991
- text += ic.InputfileType + "\n";
78382
+ // text += ic.InputfileType + "\n";
78383
+ text += "pdb\n";
77992
78384
  text += "End of type file======\n";
77993
78385
 
77994
78386
  text += "Start of data file======\n";
@@ -80853,7 +81245,7 @@ class iCn3DUI {
80853
81245
  //even when multiple iCn3D viewers are shown together.
80854
81246
  this.pre = this.cfg.divid + "_";
80855
81247
 
80856
- this.REVISION = '3.33.0';
81248
+ this.REVISION = '3.33.3';
80857
81249
 
80858
81250
  // In nodejs, iCn3D defines "window = {navigator: {}}"
80859
81251
  this.bNode = (Object.keys(window).length < 2) ? true : false;
@@ -80997,7 +81389,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
80997
81389
  ic.setStyleCls.handleContextLost();
80998
81390
  ic.applyCenterCls.setWidthHeight(width, height);
80999
81391
  ic.ori_chemicalbinding = ic.opts['chemicalbinding'];
81000
- if(me.cfg.bCalphaOnly !== undefined) ic.bCalphaOnly = me.cfg.bCalphaOnly;
81392
+ // if(me.cfg.bCalphaOnly !== undefined) ic.bCalphaOnly = me.cfg.bCalphaOnly;
81001
81393
  ic.opts = me.hashUtilsCls.cloneHash(ic.opts);
81002
81394
  ic.STATENUMBER = ic.commands.length;
81003
81395
  // If previously crashed, recover it
@@ -81025,7 +81417,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81025
81417
  ic.bInputfile = true;
81026
81418
  ic.InputfileType = 'pdb';
81027
81419
  ic.InputfileData = (ic.InputfileData) ? ic.InputfileData + '\nENDMDL\n' + pdbStr : pdbStr;
81028
-
81420
+
81029
81421
  await ic.pdbParserCls.loadPdbData(pdbStr);
81030
81422
 
81031
81423
  if(me.cfg.resdef !== undefined && me.cfg.chains !== undefined) {
@@ -81036,9 +81428,9 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81036
81428
  for(let i = 0, il = structureArray.length; i < il; ++i) {
81037
81429
  chainidArray.push(structureArray[i] + '_' + chainArray[i]);
81038
81430
  }
81039
-
81431
+
81040
81432
  chainidArray = ic.chainalignParserCls.addPostfixForChainids(chainidArray);
81041
-
81433
+
81042
81434
  let bRealign = true, bPredefined = true;
81043
81435
  await ic.realignParserCls.realignChainOnSeqAlign(undefined, chainidArray, bRealign, bPredefined);
81044
81436
  }
@@ -81059,7 +81451,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81059
81451
  chainidArray.push(domainidArray[i]);
81060
81452
  }
81061
81453
  }
81062
-
81454
+
81063
81455
  // get the matched structures, do not include the template
81064
81456
  let mmdbafid = '';
81065
81457
  for(let i = 0, il = chainidArray.length; i < il; ++i) {
@@ -81070,7 +81462,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81070
81462
  // realign, include the template
81071
81463
  ic.chainidArray = [chain_t].concat(chainidArray);
81072
81464
  ic.chainidArray = ic.chainalignParserCls.addPostfixForChainids(ic.chainidArray);
81073
-
81465
+
81074
81466
  me.htmlCls.clickMenuCls.setLogCmd('resdef ' + me.cfg.resdef, true);
81075
81467
 
81076
81468
  ic.loadCmd = 'vast_search_chainid ' + ic.chainidArray;
@@ -81147,7 +81539,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81147
81539
  }
81148
81540
  else if(me.cfg.refseqid !== undefined) {
81149
81541
  ic.inputid = me.cfg.refseqid;
81150
-
81542
+
81151
81543
  // ic.bNCBI = true;
81152
81544
  ic.loadCmd = 'load refseq ' + me.cfg.refseqid;
81153
81545
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
@@ -81155,7 +81547,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81155
81547
  }
81156
81548
  else if(me.cfg.protein !== undefined) {
81157
81549
  ic.inputid = me.cfg.protein;
81158
-
81550
+
81159
81551
  // ic.bNCBI = true;
81160
81552
  ic.loadCmd = 'load protein ' + me.cfg.protein;
81161
81553
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
@@ -81164,7 +81556,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81164
81556
  else if(me.cfg.blast_rep_id !== undefined) {
81165
81557
  // ic.bNCBI = true;
81166
81558
  ic.inputid = me.cfg.query_id + ',' + me.cfg.blast_rep_id;
81167
-
81559
+
81168
81560
  me.cfg.oriQuery_id = me.cfg.query_id;
81169
81561
  me.cfg.oriBlast_rep_id = me.cfg.blast_rep_id;
81170
81562
 
@@ -81188,7 +81580,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81188
81580
  ic.bSmithwm = false;
81189
81581
  ic.bLocalSmithwm = false;
81190
81582
  }
81191
-
81583
+
81192
81584
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
81193
81585
  await ic.mmdbParserCls.downloadBlast_rep_id(me.cfg.query_id + ',' + me.cfg.blast_rep_id);
81194
81586
  }
@@ -81197,7 +81589,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81197
81589
  let data = await me.getAjaxPromise(url, 'json', false, 'The RID ' + me.cfg.rid + ' may have expired...');
81198
81590
 
81199
81591
  for(let q = 0, ql = data.BlastOutput2.length; q < ql; ++q) {
81200
-
81592
+
81201
81593
  let hitArray;
81202
81594
  if(data.BlastOutput2[q].report.results.iterations) { // psi-blast may have "iterations". Use the last iteration.
81203
81595
  let nIterations = data.BlastOutput2[q].report.results.iterations.length;
@@ -81208,7 +81600,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81208
81600
  if(data.BlastOutput2[q].report.results.search.query_id != me.cfg.query_id) continue;
81209
81601
  hitArray = data.BlastOutput2[q].report.results.search.hits;
81210
81602
  }
81211
-
81603
+
81212
81604
  let qseq = undefined;
81213
81605
  for(let i = 0, il = hitArray.length; i < il; ++i) {
81214
81606
  let hit = hitArray[i];
@@ -81240,6 +81632,18 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81240
81632
  }
81241
81633
  }
81242
81634
  else if(me.cfg.cid !== undefined) {
81635
+ if(isNaN(me.cfg.cid)) {
81636
+ let urlCid = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi?compound2cid=" + me.cfg.cid;
81637
+ let cidJson = await me.getAjaxPromise(urlCid, 'jsonp');
81638
+ if(cidJson.cid && cidJson.cid[0]) {
81639
+ me.cfg.cid = cidJson.cid[0];
81640
+ }
81641
+ else {
81642
+ var aaa = 1; //alert("Please input an valid PubChem CID...");
81643
+ return;
81644
+ }
81645
+ }
81646
+
81243
81647
  ic.inputid = me.cfg.cid;
81244
81648
 
81245
81649
  let url = "https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/" + ic.inputid + "/description/jsonp";
@@ -81284,9 +81688,9 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81284
81688
 
81285
81689
  ic.bChainAlign = true;
81286
81690
  ic.inputid = me.cfg.chainalign;
81287
- ic.loadCmd = 'load chainalignment ' + me.cfg.chainalign + ' | resnum ' + me.cfg.resnum + ' | resdef ' + me.cfg.resdef + ' | aligntool ' + me.cfg.aligntool + ' | parameters ' + me.cfg.inpara;
81691
+ 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;
81288
81692
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
81289
- await ic.chainalignParserCls.downloadChainalignment(me.cfg.chainalign, me.cfg.resnum, me.cfg.resdef);
81693
+ await ic.chainalignParserCls.downloadChainalignment(me.cfg.chainalign);
81290
81694
  }
81291
81695
  else if(me.cfg.mmdbafid !== undefined) {
81292
81696
  // ic.bNCBI = true;
@@ -81304,7 +81708,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81304
81708
  }
81305
81709
  me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
81306
81710
 
81307
- await ic.chainalignParserCls.downloadMmdbAf(me.cfg.mmdbafid);
81711
+ await ic.chainalignParserCls.downloadMmdbAf(me.cfg.mmdbafid);
81308
81712
  //await ic.loadScriptCls.loadScript(me.cfg.command, undefined, true);
81309
81713
  }
81310
81714
  else if(me.cfg.command !== undefined && me.cfg.command !== '') {
@@ -81318,7 +81722,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
81318
81722
 
81319
81723
  return;
81320
81724
  }
81321
-
81725
+
81322
81726
  await ic.loadScriptCls.loadScript(me.cfg.command, undefined, true);
81323
81727
  // });
81324
81728
  // return me.deferred.promise();
@@ -81386,7 +81790,7 @@ iCn3DUI.prototype.getXMLHttpRqstPromise = function(url, dataType, responseType,
81386
81790
  let oReq = new XMLHttpRequest();
81387
81791
  oReq.open(dataType, url, true);
81388
81792
  oReq.responseType = responseType;
81389
-
81793
+
81390
81794
  oReq.onreadystatechange = function() {
81391
81795
  if (this.readyState == 4) {
81392
81796
  if(this.status == 200) {
@@ -81438,7 +81842,7 @@ iCn3DUI.prototype.getAjaxPromise = function(url, dataType, beforeSend, alertMess
81438
81842
  error : function() {
81439
81843
  if(alertMess) var aaa = 1; //alert(alertMess);
81440
81844
  if(logMess) console.log(logMess);
81441
-
81845
+
81442
81846
  reject('error');
81443
81847
  }
81444
81848
  });
@@ -81481,7 +81885,7 @@ iCn3DUI.prototype.getAjaxPostPromise = async function(url, data, beforeSend, ale
81481
81885
  //if(alertMess) var aaa = 1; //alert(alertMess);
81482
81886
  if(!me.bNode && alertMess) console.log(alertMess);
81483
81887
  if(!me.bNode && logMess) console.log(logMess);
81484
-
81888
+
81485
81889
  // reject('error');
81486
81890
  // keep running the program
81487
81891
  resolve('error');