icn3d 3.39.1 → 3.40.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/icn3d.js +1228 -1106
- package/icn3d.min.js +4 -4
- package/icn3d.module.js +1228 -1106
- package/package.json +1 -1
package/icn3d.js
CHANGED
|
@@ -8827,25 +8827,42 @@ class ClickMenu {
|
|
|
8827
8827
|
}
|
|
8828
8828
|
|
|
8829
8829
|
getHiddenMenusFromCache() { let me = this.icn3dui; me.icn3d;
|
|
8830
|
-
|
|
8830
|
+
// me.htmlCls.shownMenus = {};
|
|
8831
8831
|
|
|
8832
|
-
|
|
8833
|
-
|
|
8834
|
-
if(idArrayStr && idArrayStr != '[]') {
|
|
8835
|
-
let idArray = JSON.parse(idArrayStr);
|
|
8832
|
+
// let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
|
|
8836
8833
|
|
|
8837
|
-
|
|
8838
|
-
|
|
8839
|
-
|
|
8840
|
-
|
|
8841
|
-
|
|
8842
|
-
|
|
8843
|
-
|
|
8834
|
+
let idArrayStr = (localStorage) ? localStorage.getItem('hiddenmenus') : '';
|
|
8835
|
+
|
|
8836
|
+
if(idArrayStr && idArrayStr != '[]') {
|
|
8837
|
+
me.htmlCls.shownMenus = {};
|
|
8838
|
+
|
|
8839
|
+
let idArray = JSON.parse(idArrayStr);
|
|
8840
|
+
|
|
8841
|
+
// for(let i = 0, il = idArray.length; i < il; ++i) {
|
|
8842
|
+
// me.htmlCls.shownMenus[idArray[i]] = 1;
|
|
8843
|
+
// }
|
|
8844
|
+
for(let menu in me.htmlCls.allMenus) {
|
|
8845
|
+
if(idArray.indexOf(menu) == -1) {
|
|
8846
|
+
me.htmlCls.shownMenus[menu] = 1;
|
|
8844
8847
|
}
|
|
8845
|
-
|
|
8846
|
-
|
|
8847
|
-
|
|
8848
|
-
|
|
8848
|
+
}
|
|
8849
|
+
}
|
|
8850
|
+
//###
|
|
8851
|
+
else {
|
|
8852
|
+
me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
|
|
8853
|
+
}
|
|
8854
|
+
|
|
8855
|
+
// else {
|
|
8856
|
+
// if(mode == 'all') {
|
|
8857
|
+
// me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
|
|
8858
|
+
// }
|
|
8859
|
+
// else if(!mode || mode == 'simple') {
|
|
8860
|
+
// me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
|
|
8861
|
+
// }
|
|
8862
|
+
// else {
|
|
8863
|
+
// me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
|
|
8864
|
+
// }
|
|
8865
|
+
// }
|
|
8849
8866
|
}
|
|
8850
8867
|
|
|
8851
8868
|
displayShownMenus() { let me = this.icn3dui; me.icn3d;
|
|
@@ -9341,11 +9358,14 @@ class ClickMenu {
|
|
|
9341
9358
|
me.htmlCls.shownMenus[checkbox.value] = 1;
|
|
9342
9359
|
}
|
|
9343
9360
|
|
|
9361
|
+
me.htmlCls.setHtmlCls.setCookie('menumode', 'custom');
|
|
9362
|
+
|
|
9344
9363
|
thisClass.applyShownMenus();
|
|
9345
9364
|
});
|
|
9346
9365
|
|
|
9347
9366
|
me.myEventCls.onIds(["#" + me.pre + "reset_menupref", "#" + me.pre + "reset_menupref2"], "click", function(e) { me.icn3d; //e.preventDefault();
|
|
9348
9367
|
me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
|
|
9368
|
+
me.htmlCls.setHtmlCls.setCookie('menumode', 'simple');
|
|
9349
9369
|
|
|
9350
9370
|
thisClass.applyShownMenus();
|
|
9351
9371
|
thisClass.displayShownMenus();
|
|
@@ -9353,6 +9373,7 @@ class ClickMenu {
|
|
|
9353
9373
|
|
|
9354
9374
|
me.myEventCls.onIds(["#" + me.pre + "reset_menupref_all", "#" + me.pre + "reset_menupref_all2"], "click", function(e) { me.icn3d; //e.preventDefault();
|
|
9355
9375
|
me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
|
|
9376
|
+
me.htmlCls.setHtmlCls.setCookie('menumode', 'all');
|
|
9356
9377
|
|
|
9357
9378
|
thisClass.applyShownMenus();
|
|
9358
9379
|
thisClass.displayShownMenus();
|
|
@@ -9402,15 +9423,16 @@ class ClickMenu {
|
|
|
9402
9423
|
|
|
9403
9424
|
thisClass.applyShownMenus();
|
|
9404
9425
|
thisClass.displayShownMenus();
|
|
9426
|
+
|
|
9427
|
+
me.htmlCls.setHtmlCls.setCookie('menumode', 'custom');
|
|
9405
9428
|
};
|
|
9406
9429
|
reader.readAsText(file);
|
|
9407
9430
|
}
|
|
9408
9431
|
});
|
|
9409
9432
|
|
|
9410
|
-
me.myEventCls.onIds("#" + me.pre + "mn1_menuloadpref", "click", function(e) { me.icn3d; //e.preventDefault();
|
|
9433
|
+
me.myEventCls.onIds(["#" + me.pre + "mn1_menuloadpref", "#" + me.pre + "loadpref", "#" + me.pre + "loadpref2"], "click", function(e) { me.icn3d; //e.preventDefault();
|
|
9411
9434
|
me.htmlCls.dialogCls.openDlg('dl_menuloadpref', 'Please input the menu preference file');
|
|
9412
9435
|
});
|
|
9413
|
-
|
|
9414
9436
|
|
|
9415
9437
|
me.myEventCls.onIds("#" + me.pre + "mn1_link_structure", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
|
|
9416
9438
|
let url = ic.saveFileCls.getLinkToStructureSummary(true);
|
|
@@ -11249,6 +11271,51 @@ class SetMenu {
|
|
|
11249
11271
|
return me.htmlCls.setHtmlCls.getRadioColor(radioid, id, text, color, bChecked, bSimpleMenu, selType);
|
|
11250
11272
|
}
|
|
11251
11273
|
|
|
11274
|
+
resetMenu(mode) { let me = this.icn3dui;
|
|
11275
|
+
if(!mode || mode == 'simple') {
|
|
11276
|
+
me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
|
|
11277
|
+
|
|
11278
|
+
me.htmlCls.clickMenuCls.applyShownMenus();
|
|
11279
|
+
}
|
|
11280
|
+
else if(mode == 'all') {
|
|
11281
|
+
me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
|
|
11282
|
+
|
|
11283
|
+
me.htmlCls.clickMenuCls.applyShownMenus();
|
|
11284
|
+
}
|
|
11285
|
+
else if(mode == 'custom') {
|
|
11286
|
+
me.htmlCls.dialogCls.openDlg('dl_menupref', 'Select Menus');
|
|
11287
|
+
|
|
11288
|
+
me.htmlCls.clickMenuCls.getHiddenMenusFromCache();
|
|
11289
|
+
|
|
11290
|
+
me.htmlCls.clickMenuCls.displayShownMenus();
|
|
11291
|
+
}
|
|
11292
|
+
}
|
|
11293
|
+
|
|
11294
|
+
setMenuMode(bMobile) { let me = this.icn3dui;
|
|
11295
|
+
let spaceCss = (bMobile) ? "; padding-left:6px; background-color:#eee" : "; margin:3px; background-color:white";
|
|
11296
|
+
let spaceCss2 = (bMobile) ? "; font-size:14px!important" : "";
|
|
11297
|
+
|
|
11298
|
+
let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
|
|
11299
|
+
|
|
11300
|
+
let html = '<div class="icn3d-text" style="color:#f8b84e; font-weight:bold' + spaceCss + '">';
|
|
11301
|
+
html += '<select name="menumode" id="' + me.pre + 'menumode" class="icn3d-text" style="color:#f8b84e; font-weight:bold; border:0px' + spaceCss2 + '">';
|
|
11302
|
+
html += (mode == 'simple' || !mode) ? '<option value="simple" selected>Simple</option>' : '<option value="simple">Simple</option>';
|
|
11303
|
+
html += (mode == 'all') ? '<option value="all" selected>All</option>' : '<option value="all">All</option>';
|
|
11304
|
+
html += (mode == 'custom') ? '<option value="custom" selected>Custom</option>' : '<option value="custom">Custom</option>';
|
|
11305
|
+
html += '</select>';
|
|
11306
|
+
|
|
11307
|
+
if(bMobile) {
|
|
11308
|
+
html += '<br><span style="font-size:12px"> Menus</span>';
|
|
11309
|
+
}
|
|
11310
|
+
else {
|
|
11311
|
+
html += ' Menus';
|
|
11312
|
+
}
|
|
11313
|
+
|
|
11314
|
+
html += '</div>';
|
|
11315
|
+
|
|
11316
|
+
return html;
|
|
11317
|
+
}
|
|
11318
|
+
|
|
11252
11319
|
//Set the HTML code for the menus shown at the top of the viewer.
|
|
11253
11320
|
setTopMenusHtml(id, str1, str2) { let me = this.icn3dui;
|
|
11254
11321
|
if(me.bNode) return '';
|
|
@@ -11268,6 +11335,9 @@ class SetMenu {
|
|
|
11268
11335
|
html += "<table border='0' cellpadding='0' cellspacing='0' width='100'><tr>";
|
|
11269
11336
|
|
|
11270
11337
|
let tdStr = '<td valign="top">';
|
|
11338
|
+
|
|
11339
|
+
// html += tdStr + this.setMenuMode() + '</td>';
|
|
11340
|
+
|
|
11271
11341
|
html += tdStr + this.setMenu1() + '</td>';
|
|
11272
11342
|
|
|
11273
11343
|
html += tdStr + this.setMenu2() + '</td>';
|
|
@@ -11280,7 +11350,11 @@ class SetMenu {
|
|
|
11280
11350
|
//html += tdStr + this.setMenu5b() + '</td>';
|
|
11281
11351
|
html += tdStr + this.setMenu6() + '</td>';
|
|
11282
11352
|
|
|
11283
|
-
|
|
11353
|
+
// reset the menus at the end of the menus
|
|
11354
|
+
// let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
|
|
11355
|
+
// this.resetMenu(mode);
|
|
11356
|
+
|
|
11357
|
+
// me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
|
|
11284
11358
|
|
|
11285
11359
|
html += tdStr + "<div style='position:relative; margin-left:6px;'>" + str1;
|
|
11286
11360
|
html += "<div class='icn3d-commandTitle' style='min-width:40px; margin-top: 3px; white-space: nowrap;'>" + str2;
|
|
@@ -11376,6 +11450,7 @@ class SetMenu {
|
|
|
11376
11450
|
|
|
11377
11451
|
//html += "<div class='icn3d-menu'>";
|
|
11378
11452
|
html += "<div>";
|
|
11453
|
+
|
|
11379
11454
|
html += "<accordion id='" + me.pre + "accordion0' class='icn3d-accordion'>";
|
|
11380
11455
|
if(me.cfg.notebook) {
|
|
11381
11456
|
html += "<h3 style='width:20px; height:24px; position:relative; padding: 0'><span style='position:absolute; left:3px; top:4px;'>☰</span></h3>";
|
|
@@ -11385,6 +11460,8 @@ class SetMenu {
|
|
|
11385
11460
|
}
|
|
11386
11461
|
html += "<div>";
|
|
11387
11462
|
|
|
11463
|
+
// html += '<li>' + this.setMenuMode(true);
|
|
11464
|
+
|
|
11388
11465
|
let liStr = "<li><span class='icn3d-menu-color'";
|
|
11389
11466
|
|
|
11390
11467
|
html += "<ul class='icn3d-mn-item'>";
|
|
@@ -11403,7 +11480,11 @@ class SetMenu {
|
|
|
11403
11480
|
html += liStr + ">Help</span>";
|
|
11404
11481
|
html += this.setMenu6_base();
|
|
11405
11482
|
|
|
11406
|
-
|
|
11483
|
+
// reset the menus at the end of the menus
|
|
11484
|
+
// let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
|
|
11485
|
+
// this.resetMenu(mode);
|
|
11486
|
+
|
|
11487
|
+
// me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
|
|
11407
11488
|
|
|
11408
11489
|
html += "<li><div style='position:relative; margin-top:-6px;'>" + str1;
|
|
11409
11490
|
html += "<div class='icn3d-commandTitle' style='margin-top: 3px; white-space: nowrap;'>" + str2;
|
|
@@ -11580,7 +11661,7 @@ class SetMenu {
|
|
|
11580
11661
|
// Analysis menu
|
|
11581
11662
|
html += tdStrBorder + this.setIcon(iconType, 'tool_selectannotations', 'Sequences & Annotations', 'grip-lines') + "</td>";
|
|
11582
11663
|
html += tdStr + this.setIcon(iconType, 'hbondsYes', 'Interactions', 'users') + "</td>";
|
|
11583
|
-
html += tdStr + this.setIcon(iconType, 'tool_delphi', '
|
|
11664
|
+
html += tdStr + this.setIcon(iconType, 'tool_delphi', 'DelPhi Potentials', 'cloud-meatball') + "</td>";
|
|
11584
11665
|
html += tdStr + this.setIcon(iconType, 'removeLabels', 'Remove Labels', 'remove-format') + "</td>";
|
|
11585
11666
|
|
|
11586
11667
|
// Help menu
|
|
@@ -12792,6 +12873,10 @@ class SetMenu {
|
|
|
12792
12873
|
|
|
12793
12874
|
html += "<ul class='icn3d-mn-item'>";
|
|
12794
12875
|
|
|
12876
|
+
if(me.cfg.cid !== undefined || me.cfg.smiles !== undefined) {
|
|
12877
|
+
html += this.getLink('mn2_2ddepiction', '2D Depiction ' + me.htmlCls.wifiStr, 1, 1);
|
|
12878
|
+
}
|
|
12879
|
+
|
|
12795
12880
|
if(me.cfg.cid === undefined) {
|
|
12796
12881
|
html += this.getLink('mn6_selectannotations', 'Seq. & Annotations ' + me.htmlCls.wifiStr, 1, 1);
|
|
12797
12882
|
|
|
@@ -13593,7 +13678,7 @@ class Dialog {
|
|
|
13593
13678
|
width='50%';
|
|
13594
13679
|
}
|
|
13595
13680
|
else if(id === me.pre + 'dl_menupref') {
|
|
13596
|
-
width =
|
|
13681
|
+
width = 800;
|
|
13597
13682
|
height = 500;
|
|
13598
13683
|
}
|
|
13599
13684
|
|
|
@@ -14254,6 +14339,10 @@ class SetDialog {
|
|
|
14254
14339
|
html += me.htmlCls.divStr + "dl_collection_file' style=''>";
|
|
14255
14340
|
html += "You can load a collection of structures via a file. Here are <a href='https://github.com/ncbi/icn3d/blob/master/example/collection/' target='_blank'>some example files</a><br><br>";
|
|
14256
14341
|
html += "Collection file: " + me.htmlCls.inputFileStr + "id='" + me.pre + "collectionfile'><br/>";
|
|
14342
|
+
html += "<input type='radio' id='dl_collectionAppendStructureNone' name='appendStructure' value='none' checked/>";
|
|
14343
|
+
html += "<label for='dl_collectionAppendStructureNone'>Default</label>";
|
|
14344
|
+
html += "<input type='radio' id='dl_collectionAppendStructure' name='appendStructure' value='append' />";
|
|
14345
|
+
html += "<label for='dl_collectionAppendStructure'>Append</label><br/>";
|
|
14257
14346
|
html += me.htmlCls.buttonStr + "reload_collectionfile' style='margin-top: 6px;'>Load</button>";
|
|
14258
14347
|
html += "</div>";
|
|
14259
14348
|
html += "</div>";
|
|
@@ -14261,7 +14350,8 @@ class SetDialog {
|
|
|
14261
14350
|
html += me.htmlCls.divStr + "dl_collection_structures' style='display: none'>";
|
|
14262
14351
|
html += "<select id='" + me.pre + "collections_menu'multiple size='6' style='min-width:300px;'></select>";
|
|
14263
14352
|
html += '<br/>';
|
|
14264
|
-
html += me.htmlCls.buttonStr + "
|
|
14353
|
+
html += me.htmlCls.buttonStr + "collections_clear_commands' style='margin-top: 6px;'>Clear Commands</button>";
|
|
14354
|
+
html += me.htmlCls.buttonStr + "opendl_export_collections'>Export JSON</button>";
|
|
14265
14355
|
html += "</div>";
|
|
14266
14356
|
html += '<br/>';
|
|
14267
14357
|
html += "</div>";
|
|
@@ -14616,24 +14706,30 @@ class SetDialog {
|
|
|
14616
14706
|
html += "</div>";
|
|
14617
14707
|
|
|
14618
14708
|
|
|
14619
|
-
html += me.htmlCls.divStr + "dl_ligplot'
|
|
14620
|
-
|
|
14709
|
+
html += me.htmlCls.divStr + "dl_ligplot' style='background-color:white' class='" + dialogClass + "'>";
|
|
14710
|
+
|
|
14711
|
+
if(me.cfg.cid !== undefined || me.cfg.smiles !== undefined) {
|
|
14712
|
+
html += this.addNotebookTitle('dl_ligplot', '2D Depiction for Chemicals');
|
|
14713
|
+
}
|
|
14714
|
+
else {
|
|
14715
|
+
html += this.addNotebookTitle('dl_ligplot', '2D Interaction for One Ligand/Residue with Atom Details');
|
|
14621
14716
|
|
|
14622
|
-
|
|
14717
|
+
html += me.htmlCls.divNowrapStr + "<b>Note</b>: Nodes/Residues can be dragged. Both nodes and dashed lines/interactions can be clicked to select residues. " + me.htmlCls.space3;
|
|
14623
14718
|
|
|
14624
|
-
|
|
14625
|
-
|
|
14626
|
-
|
|
14719
|
+
html += '<div style="width:20px; margin-top:6px; display:inline-block;"><span id="'
|
|
14720
|
+
+ me.pre + 'dl_ligplotcolor_expand" class="ui-icon ui-icon-plus icn3d-expand icn3d-link" style="display:none; width:15px;" title="Expand"></span><span id="'
|
|
14721
|
+
+ me.pre + 'dl_ligplotcolor_shrink" class="ui-icon ui-icon-minus icn3d-shrink icn3d-link" style="width:15px;" title="Shrink"></span></div></div>';
|
|
14627
14722
|
|
|
14628
|
-
|
|
14723
|
+
html += me.htmlCls.divStr + "dl_ligplotcolor' style='inline-block;'>";
|
|
14629
14724
|
|
|
14630
|
-
|
|
14631
|
-
|
|
14632
|
-
|
|
14725
|
+
// html += "The real interaction distances are not in scale, and are about twice the distances of dashed line segments.<br>Some \"Contact\" lines are only shown partially to simplify the view.<br>";
|
|
14726
|
+
// html += "Mouseover the dashed lines to see interaction types and distances.<br>";
|
|
14727
|
+
html += "<b>Color legend</b> for interactions (dashed lines): <br>";
|
|
14633
14728
|
|
|
14634
|
-
|
|
14729
|
+
html += me.htmlCls.setHtmlCls.setColorHints();
|
|
14635
14730
|
|
|
14636
|
-
|
|
14731
|
+
html += "<br></div>";
|
|
14732
|
+
}
|
|
14637
14733
|
|
|
14638
14734
|
me.ligplotid = me.pre + 'ligplot';
|
|
14639
14735
|
html += me.htmlCls.divNowrapStr + buttonStrTmp + me.ligplotid + '_svg">SVG</button>' + me.htmlCls.space2;
|
|
@@ -14960,13 +15056,15 @@ class SetDialog {
|
|
|
14960
15056
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "apply_menupref'>Apply</button></span>";
|
|
14961
15057
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "reset_menupref' style='margin-left:30px'>Reset to Simple Menus</button></span>";
|
|
14962
15058
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "reset_menupref_all' style='margin-left:30px'>Reset to All Menus</button></span>";
|
|
14963
|
-
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "savepref' style='margin-left:30px'>Save Preferences</button></span
|
|
15059
|
+
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "savepref' style='margin-left:30px'>Save Preferences</button></span>";
|
|
15060
|
+
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "loadpref' style='margin-left:30px'>Load Preferences</button></span><br><br>";
|
|
14964
15061
|
|
|
14965
15062
|
html += "<div id='" + me.pre + "menulist'></div><br><br>";
|
|
14966
15063
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "apply_menupref2'>Apply</button></span>";
|
|
14967
15064
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "reset_menupref2' style='margin-left:30px'>Reset to Simple Menus</button></span>";
|
|
14968
15065
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "reset_menupref_all2' style='margin-left:30px'>Reset to All Menus</button></span>";
|
|
14969
15066
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "savepref2' style='margin-left:30px'>Save Preferences</button></span>";
|
|
15067
|
+
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "loadpref2' style='margin-left:30px'>Load Preferences</button></span>";
|
|
14970
15068
|
html += "</div>";
|
|
14971
15069
|
|
|
14972
15070
|
html += me.htmlCls.divStr + "dl_addtrack' class='" + dialogClass + "'>";
|
|
@@ -15742,6 +15840,14 @@ class Events {
|
|
|
15742
15840
|
me.htmlCls.clickMenuCls.clickMenu5();
|
|
15743
15841
|
me.htmlCls.clickMenuCls.clickMenu6();
|
|
15744
15842
|
|
|
15843
|
+
me.myEventCls.onIds("#" + me.pre + "menumode", "change", async function(e) { me.icn3d;
|
|
15844
|
+
e.preventDefault();
|
|
15845
|
+
let mode = $("#" + me.pre + "menumode").val();
|
|
15846
|
+
|
|
15847
|
+
me.htmlCls.setHtmlCls.setCookie('menumode', mode);
|
|
15848
|
+
me.htmlCls.setMenuCls.resetMenu(mode);
|
|
15849
|
+
});
|
|
15850
|
+
|
|
15745
15851
|
// back and forward arrows
|
|
15746
15852
|
me.myEventCls.onIds(["#" + me.pre + "back", "#" + me.pre + "mn6_back"], "click", async function(e) { let ic = me.icn3d;
|
|
15747
15853
|
e.preventDefault();
|
|
@@ -16019,6 +16125,11 @@ class Events {
|
|
|
16019
16125
|
thisClass.setLogCmd("view interactions", true);
|
|
16020
16126
|
});
|
|
16021
16127
|
|
|
16128
|
+
me.myEventCls.onIds("#" + me.pre + "mn2_2ddepiction", "click", async function(e) { let ic = me.icn3d;
|
|
16129
|
+
await ic.ligplotCls.drawLigplot(ic.atoms, true);
|
|
16130
|
+
thisClass.setLogCmd("view 2d depiction", true);
|
|
16131
|
+
});
|
|
16132
|
+
|
|
16022
16133
|
me.myEventCls.onIds("#" + me.pre + "search_seq_button", "click", async function(e) { me.icn3d;
|
|
16023
16134
|
e.stopImmediatePropagation();
|
|
16024
16135
|
await thisClass.searchSeq();
|
|
@@ -16783,95 +16894,108 @@ class Events {
|
|
|
16783
16894
|
} else {
|
|
16784
16895
|
ic.resizeCanvasCls.closeDialogs();
|
|
16785
16896
|
}
|
|
16786
|
-
|
|
16787
|
-
ic.pdbCollection = [];
|
|
16788
|
-
ic.allData = {};
|
|
16789
|
-
ic.allData['all'] = {
|
|
16790
|
-
'atoms': {},
|
|
16791
|
-
'proteins': {},
|
|
16792
|
-
'nucleotides': {},
|
|
16793
|
-
'chemicals': {},
|
|
16794
|
-
'ions': {},
|
|
16795
|
-
'water': {},
|
|
16796
|
-
'structures': {}, // getSSExpandedAtoms
|
|
16797
|
-
'ssbondpnts': {},
|
|
16798
|
-
'residues': {}, // getSSExpandedAtoms
|
|
16799
|
-
'chains': {},
|
|
16800
|
-
'chainsSeq': {}, //Sequences and Annotation
|
|
16801
|
-
'defNames2Atoms': {},
|
|
16802
|
-
'defNames2Residues': {}
|
|
16803
|
-
};
|
|
16804
|
-
ic.allData['prev'] = {};
|
|
16805
|
-
ic.selectCollectionsCls.reset();
|
|
16806
|
-
|
|
16897
|
+
|
|
16807
16898
|
ic.dAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
|
|
16808
16899
|
ic.hAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
|
|
16809
16900
|
me.htmlCls.setHtmlCls.fileSupport();
|
|
16810
16901
|
|
|
16811
16902
|
let fileName = file.name;
|
|
16812
16903
|
let fileExtension = fileName.split('.').pop().toLowerCase();
|
|
16813
|
-
|
|
16904
|
+
let collection = {};
|
|
16905
|
+
|
|
16814
16906
|
$("#" + ic.pre + "collections_menu").empty();
|
|
16815
16907
|
$("#" + ic.pre + "collections_menu").off("change");
|
|
16908
|
+
|
|
16909
|
+
if (dl_collectionAppendStructureNone.checked || ic.allData === undefined) {
|
|
16910
|
+
ic.bInputfile = false;
|
|
16911
|
+
ic.pdbCollection = {};
|
|
16912
|
+
ic.allData = {};
|
|
16913
|
+
ic.allData['all'] = {
|
|
16914
|
+
'atoms': {},
|
|
16915
|
+
'proteins': {},
|
|
16916
|
+
'nucleotides': {},
|
|
16917
|
+
'chemicals': {},
|
|
16918
|
+
'ions': {},
|
|
16919
|
+
'water': {},
|
|
16920
|
+
'structures': {}, // getSSExpandedAtoms
|
|
16921
|
+
'ssbondpnts': {},
|
|
16922
|
+
'residues': {}, // getSSExpandedAtoms
|
|
16923
|
+
'chains': {},
|
|
16924
|
+
'chainsSeq': {}, //Sequences and Annotation
|
|
16925
|
+
'defNames2Atoms': {},
|
|
16926
|
+
'defNames2Residues': {}
|
|
16927
|
+
};
|
|
16928
|
+
ic.allData['prev'] = {};
|
|
16929
|
+
ic.selectCollectionsCls.reset();
|
|
16930
|
+
|
|
16931
|
+
} else {
|
|
16932
|
+
if (ic.collections) {
|
|
16933
|
+
collection = ic.collections;
|
|
16934
|
+
}
|
|
16935
|
+
}
|
|
16816
16936
|
|
|
16817
16937
|
function parseJsonCollection(data) {
|
|
16818
16938
|
let dataStr = JSON.parse(data);
|
|
16819
|
-
|
|
16939
|
+
let parsedCollection = {};
|
|
16940
|
+
|
|
16941
|
+
dataStr["structures"].map(({ id, title, description, commands }) => {
|
|
16820
16942
|
if (id && id.includes('.pdb')) {
|
|
16821
16943
|
id = id.split('.pdb')[0];
|
|
16822
16944
|
}
|
|
16823
|
-
|
|
16945
|
+
parsedCollection[id] = [id, title, description, commands, false];
|
|
16824
16946
|
});
|
|
16825
|
-
}
|
|
16826
16947
|
|
|
16948
|
+
return parsedCollection;
|
|
16949
|
+
}
|
|
16950
|
+
|
|
16827
16951
|
function parsePdbCollection(data, description = '', commands = []) {
|
|
16828
16952
|
let dataStr = data;
|
|
16829
16953
|
let lines = dataStr.split('\n');
|
|
16830
|
-
|
|
16831
16954
|
let sections = [];
|
|
16832
16955
|
let currentSection = [];
|
|
16833
|
-
|
|
16956
|
+
|
|
16834
16957
|
lines.forEach(line => {
|
|
16835
|
-
|
|
16958
|
+
if (line.startsWith('HEADER')) {
|
|
16836
16959
|
currentSection = [];
|
|
16837
16960
|
sections.push(currentSection);
|
|
16838
|
-
|
|
16839
|
-
|
|
16961
|
+
}
|
|
16962
|
+
currentSection.push(line);
|
|
16840
16963
|
});
|
|
16841
|
-
|
|
16842
|
-
|
|
16843
|
-
let
|
|
16844
|
-
|
|
16964
|
+
|
|
16965
|
+
|
|
16966
|
+
let parsedCollection = {};
|
|
16967
|
+
|
|
16845
16968
|
sections.forEach((section) => {
|
|
16846
|
-
let headerLine = section[0];
|
|
16847
|
-
headerLine = headerLine.replace(/[\n\r]/g, '').trim();
|
|
16969
|
+
let headerLine = section[0].replace(/[\n\r]/g, '').trim();
|
|
16848
16970
|
let header = headerLine.split(' ').filter(Boolean);
|
|
16849
|
-
let
|
|
16850
|
-
|
|
16851
|
-
|
|
16971
|
+
let id = header[header.length - 1];
|
|
16972
|
+
let title = section[1].startsWith('TITLE') ? section[1].split('TITLE').pop().trim() : id;
|
|
16973
|
+
|
|
16974
|
+
parsedCollection[id] = [id, title, description, commands, true];
|
|
16975
|
+
|
|
16976
|
+
const sanitizedSection = section.map(line => line.trim());
|
|
16977
|
+
ic.pdbCollection[id] = sanitizedSection;
|
|
16852
16978
|
});
|
|
16853
|
-
|
|
16854
|
-
if (sections.length > 0) {
|
|
16855
|
-
ic.pdbCollection.push(...sections);
|
|
16856
|
-
}
|
|
16857
16979
|
|
|
16858
|
-
return
|
|
16980
|
+
return parsedCollection;
|
|
16859
16981
|
}
|
|
16860
16982
|
|
|
16861
|
-
let collection = [];
|
|
16862
|
-
|
|
16863
16983
|
if (fileExtension === 'json' || fileExtension === 'pdb') {
|
|
16864
16984
|
let reader = new FileReader();
|
|
16865
16985
|
reader.onload = async function (e) {
|
|
16866
16986
|
if (fileExtension === 'json') {
|
|
16867
|
-
|
|
16987
|
+
let jsonCollection = parseJsonCollection(e.target.result);
|
|
16988
|
+
collection = { ...collection, ...jsonCollection };
|
|
16868
16989
|
} else if (fileExtension === 'pdb') {
|
|
16869
16990
|
ic.bInputfile = true;
|
|
16870
|
-
|
|
16991
|
+
let pdbCollection = parsePdbCollection(e.target.result);
|
|
16992
|
+
collection = { ...collection, ...pdbCollection };
|
|
16871
16993
|
}
|
|
16872
16994
|
|
|
16873
16995
|
let collectionHtml = await ic.selectCollectionsCls.setAtomMenu(collection);
|
|
16874
16996
|
|
|
16997
|
+
ic.collections = collection;
|
|
16998
|
+
|
|
16875
16999
|
$("#" + ic.pre + "collections_menu").html(collectionHtml);
|
|
16876
17000
|
await ic.selectCollectionsCls.clickStructure(collection);
|
|
16877
17001
|
$("#" + ic.pre + "collections_menu").trigger("change");
|
|
@@ -16889,7 +17013,7 @@ class Events {
|
|
|
16889
17013
|
let reader2 = new FileReader();
|
|
16890
17014
|
reader2.onload = async function (e) {
|
|
16891
17015
|
if (fileExtension === 'zip') {
|
|
16892
|
-
let url = './script/jszip.js';
|
|
17016
|
+
let url = './script/jszip.min.js';
|
|
16893
17017
|
await me.getAjaxPromise(url, 'script');
|
|
16894
17018
|
|
|
16895
17019
|
let jszip = new JSZip();
|
|
@@ -16923,7 +17047,8 @@ class Events {
|
|
|
16923
17047
|
let jsonCollection = [];
|
|
16924
17048
|
for (const file of jsonFiles) {
|
|
16925
17049
|
let fileData = await file.async('text');
|
|
16926
|
-
parseJsonCollection(fileData)
|
|
17050
|
+
let parsedJson = Object.values(parseJsonCollection(fileData));
|
|
17051
|
+
parsedJson.forEach(element => {
|
|
16927
17052
|
jsonCollection.push(element);
|
|
16928
17053
|
});
|
|
16929
17054
|
}
|
|
@@ -16933,8 +17058,9 @@ class Events {
|
|
|
16933
17058
|
let matchingPdbFile = pdbFiles.find(file => file.name.toLowerCase().includes(id.toLowerCase()));
|
|
16934
17059
|
if (matchingPdbFile) {
|
|
16935
17060
|
let pdbFileData = await matchingPdbFile.async('text');
|
|
16936
|
-
parsePdbCollection(pdbFileData, description, commands)
|
|
16937
|
-
|
|
17061
|
+
let parsedPdb = Object.values(parsePdbCollection(pdbFileData, description, commands));
|
|
17062
|
+
parsedPdb.forEach(element => {
|
|
17063
|
+
collection[id] = element;
|
|
16938
17064
|
});
|
|
16939
17065
|
}
|
|
16940
17066
|
}
|
|
@@ -16943,27 +17069,30 @@ class Events {
|
|
|
16943
17069
|
// Do something if only JSON files are present
|
|
16944
17070
|
jsonFiles.forEach(async file => {
|
|
16945
17071
|
let fileData = await file.async('text');
|
|
16946
|
-
parseJsonCollection(fileData)
|
|
16947
|
-
|
|
17072
|
+
const parsedJson = Object.values(parseJsonCollection(fileData));
|
|
17073
|
+
parsedJson.forEach(element => {
|
|
17074
|
+
collection[element[0]] = element;
|
|
16948
17075
|
});
|
|
16949
17076
|
});
|
|
16950
17077
|
} else if (hasPdb) {
|
|
16951
17078
|
// Do something if only PDB files are present
|
|
16952
17079
|
pdbFiles.forEach(async file => {
|
|
16953
17080
|
let fileData = await file.async('text');
|
|
16954
|
-
|
|
16955
|
-
|
|
17081
|
+
const parsedPdb = Object.values(parsedPdbCollection(fileData));
|
|
17082
|
+
parsedPdb.forEach(element => {
|
|
17083
|
+
collection[element[0]] = element;
|
|
16956
17084
|
});
|
|
16957
17085
|
});
|
|
16958
17086
|
} else if (hasGz) {
|
|
16959
|
-
let url = './script/pako.js';
|
|
17087
|
+
let url = './script/pako.min.js';
|
|
16960
17088
|
await me.getAjaxPromise(url, 'script');
|
|
16961
17089
|
try {
|
|
16962
17090
|
for (const file of gzFiles) {
|
|
16963
17091
|
let compressed = await file.async('uint8array');
|
|
16964
17092
|
let decompressed = pako.inflate(compressed, { to: 'string' });
|
|
16965
|
-
parsePdbCollection(decompressed)
|
|
16966
|
-
|
|
17093
|
+
const parsedPdb = Object.values(parsePdbCollection(decompressed));
|
|
17094
|
+
parsedPdb.forEach(element => {
|
|
17095
|
+
collection[element[0]] = element;
|
|
16967
17096
|
});
|
|
16968
17097
|
}
|
|
16969
17098
|
} catch (error) {
|
|
@@ -16974,7 +17103,7 @@ class Events {
|
|
|
16974
17103
|
console.error('Error loading ZIP file', error);
|
|
16975
17104
|
}
|
|
16976
17105
|
} else if (fileExtension === 'gz') {
|
|
16977
|
-
let url = './script/pako.js';
|
|
17106
|
+
let url = './script/pako.min.js';
|
|
16978
17107
|
await me.getAjaxPromise(url, 'script');
|
|
16979
17108
|
|
|
16980
17109
|
try {
|
|
@@ -16991,6 +17120,8 @@ class Events {
|
|
|
16991
17120
|
$("#" + ic.pre + "collections_menu").html(collectionHtml);
|
|
16992
17121
|
await ic.selectCollectionsCls.clickStructure(collection);
|
|
16993
17122
|
|
|
17123
|
+
ic.collections = collection;
|
|
17124
|
+
|
|
16994
17125
|
$("#" + ic.pre + "collections_menu").trigger("change");
|
|
16995
17126
|
|
|
16996
17127
|
me.htmlCls.clickMenuCls.setLogCmd(
|
|
@@ -17009,7 +17140,7 @@ class Events {
|
|
|
17009
17140
|
throw new Error('Invalid file type');
|
|
17010
17141
|
}
|
|
17011
17142
|
|
|
17012
|
-
if (Object.keys(
|
|
17143
|
+
if (ic.allData && Object.keys(ic.allData).length > 0) {
|
|
17013
17144
|
$("#" + me.pre + "dl_collection_file").hide();
|
|
17014
17145
|
$("#" + me.pre + "dl_collection_structures").show();
|
|
17015
17146
|
$("#" + me.pre + "dl_collection_file_expand").show();
|
|
@@ -17030,6 +17161,17 @@ class Events {
|
|
|
17030
17161
|
}
|
|
17031
17162
|
});
|
|
17032
17163
|
|
|
17164
|
+
me.myEventCls.onIds("#" + me.pre + "collections_clear_commands", "click", function (e) {
|
|
17165
|
+
var selectedValues = $("#" + ic.pre + "collections_menu").val();
|
|
17166
|
+
selectedValues.forEach(function (selectedValue) {
|
|
17167
|
+
if (ic.allData[selectedValue]) {
|
|
17168
|
+
ic.allData[selectedValue]['commands'] = [];
|
|
17169
|
+
} else {
|
|
17170
|
+
console.warn("No data found for selectedValue:", selectedValue);
|
|
17171
|
+
}
|
|
17172
|
+
});
|
|
17173
|
+
});
|
|
17174
|
+
|
|
17033
17175
|
me.myEventCls.onIds("#" + me.pre + "opendl_export_collections", "click", function (e) {
|
|
17034
17176
|
me.htmlCls.dialogCls.openDlg("dl_export_collections", "Export Collections");
|
|
17035
17177
|
});
|
|
@@ -19516,9 +19658,9 @@ class SetHtml {
|
|
|
19516
19658
|
|
|
19517
19659
|
let pdbstr = '';
|
|
19518
19660
|
|
|
19519
|
-
let bMergeIntoOne = true;
|
|
19520
|
-
pdbstr += ic.saveFileCls.getAtomPDB(atomHash, undefined, undefined, undefined, undefined, undefined, bMergeIntoOne);
|
|
19521
|
-
pdbstr += ic.saveFileCls.getAtomPDB(ionHash, true, undefined, true);
|
|
19661
|
+
let bMergeIntoOne = true, bOneLetterChain = true;
|
|
19662
|
+
pdbstr +=(me.cfg.cid) ? ic.saveFileCls.getAtomPDB(atomHash, true, undefined, undefined, undefined, undefined, bMergeIntoOne, bOneLetterChain) : ic.saveFileCls.getAtomPDB(atomHash, undefined, undefined, undefined, undefined, undefined, bMergeIntoOne, bOneLetterChain);
|
|
19663
|
+
pdbstr += ic.saveFileCls.getAtomPDB(ionHash, true, undefined, true, undefined, undefined, bMergeIntoOne, bOneLetterChain);
|
|
19522
19664
|
|
|
19523
19665
|
let url = me.htmlCls.baseUrl + "delphi/delphi.cgi";
|
|
19524
19666
|
|
|
@@ -27222,6 +27364,8 @@ class Camera {
|
|
|
27222
27364
|
}
|
|
27223
27365
|
}
|
|
27224
27366
|
|
|
27367
|
+
// ic.cam.add(ic.directionalLight);
|
|
27368
|
+
|
|
27225
27369
|
ic.cam.updateProjectionMatrix();
|
|
27226
27370
|
// }
|
|
27227
27371
|
}
|
|
@@ -28720,687 +28864,233 @@ class Stick {
|
|
|
28720
28864
|
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
28721
28865
|
*/
|
|
28722
28866
|
|
|
28723
|
-
class
|
|
28867
|
+
class FirstAtomObj {
|
|
28724
28868
|
constructor(icn3d) {
|
|
28725
28869
|
this.icn3d = icn3d;
|
|
28726
28870
|
}
|
|
28727
28871
|
|
|
28728
|
-
//
|
|
28729
|
-
|
|
28730
|
-
|
|
28731
|
-
|
|
28732
|
-
|
|
28733
|
-
//"bHighlight" is an option to draw the highlight for these atoms. The highlight could be outlines
|
|
28734
|
-
//with bHighlight=1 and 3D objects with bHighlight=2.
|
|
28735
|
-
createStrand(atoms, num, div, fill, coilWidth, helixSheetWidth, doNotSmoothen, thickness, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
|
|
28736
|
-
if(me.bNode) return;
|
|
28872
|
+
//Return the first atom in the atom hash, which has the atom serial number as the key.
|
|
28873
|
+
getFirstAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
28874
|
+
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
28875
|
+
return undefined;
|
|
28876
|
+
}
|
|
28737
28877
|
|
|
28738
|
-
let
|
|
28878
|
+
let atomKeys = Object.keys(atomsHash);
|
|
28879
|
+
let firstIndex = atomKeys[0];
|
|
28739
28880
|
|
|
28740
|
-
|
|
28741
|
-
|
|
28742
|
-
let atomsAdjust = {};
|
|
28881
|
+
return ic.atoms[firstIndex];
|
|
28882
|
+
}
|
|
28743
28883
|
|
|
28744
|
-
|
|
28745
|
-
|
|
28746
|
-
|
|
28884
|
+
// n is the position of the selected atom
|
|
28885
|
+
getMiddleAtomObj(atomsHash, n) { let ic = this.icn3d; ic.icn3dui;
|
|
28886
|
+
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
28887
|
+
return undefined;
|
|
28747
28888
|
}
|
|
28748
|
-
|
|
28749
|
-
|
|
28889
|
+
|
|
28890
|
+
let atomKeys = Object.keys(atomsHash);
|
|
28891
|
+
let middleIndex = (n && n < atomKeys.length) ? atomKeys[n] : atomKeys[parseInt(atomKeys.length / 2)];
|
|
28892
|
+
|
|
28893
|
+
return ic.atoms[middleIndex];
|
|
28894
|
+
}
|
|
28895
|
+
|
|
28896
|
+
getFirstCalphaAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
28897
|
+
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
28898
|
+
return undefined;
|
|
28750
28899
|
}
|
|
28751
28900
|
|
|
28752
|
-
|
|
28753
|
-
|
|
28754
|
-
|
|
28755
|
-
|
|
28756
|
-
|
|
28757
|
-
|
|
28758
|
-
helixSheetWidth = null;
|
|
28759
|
-
thickness = undefined;
|
|
28901
|
+
let firstIndex;
|
|
28902
|
+
|
|
28903
|
+
for(let i in atomsHash) {
|
|
28904
|
+
if(ic.atoms[i].name == 'CA') {
|
|
28905
|
+
firstIndex = i;
|
|
28906
|
+
break;
|
|
28760
28907
|
}
|
|
28761
|
-
|
|
28762
|
-
|
|
28763
|
-
|
|
28764
|
-
|
|
28765
|
-
|
|
28766
|
-
|
|
28767
|
-
|
|
28908
|
+
}
|
|
28909
|
+
|
|
28910
|
+
if(!firstIndex) {
|
|
28911
|
+
for(let i in atomsHash) {
|
|
28912
|
+
if(ic.atoms[i].name == "O3'" || ic.atoms[i].name == "O3*") {
|
|
28913
|
+
firstIndex = i;
|
|
28914
|
+
break;
|
|
28915
|
+
}
|
|
28768
28916
|
}
|
|
28769
28917
|
}
|
|
28770
28918
|
|
|
28771
|
-
|
|
28772
|
-
|
|
28773
|
-
coilWidth = coilWidth || ic.coilWidth;
|
|
28774
|
-
doNotSmoothen = doNotSmoothen || false;
|
|
28775
|
-
helixSheetWidth = helixSheetWidth || ic.helixSheetWidth;
|
|
28776
|
-
let pnts = {}; for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
28777
|
-
let pntsCA = [];
|
|
28778
|
-
let prevCOArray = [];
|
|
28779
|
-
let bShowArray = [];
|
|
28780
|
-
let calphaIdArray = []; // used to store one of the final positions drawn in 3D
|
|
28781
|
-
let colors = [];
|
|
28782
|
-
let currentChain, currentResi, currentCA = null, currentO = null, currentColor = null, prevCoorCA = null, prevCoorO = null, prevColor = null;
|
|
28783
|
-
let prevCO = null, ss = null, ssend = false, atomid = null, prevAtomid = null, prevAtomSelected = null, prevResi = null, calphaid = null, prevCalphaid = null;
|
|
28784
|
-
let strandWidth, bSheetSegment = false, bHelixSegment = false;
|
|
28919
|
+
return (firstIndex !== undefined) ? ic.atoms[firstIndex] : this.getFirstAtomObj(atomsHash);
|
|
28920
|
+
}
|
|
28785
28921
|
|
|
28786
|
-
|
|
28787
|
-
|
|
28788
|
-
|
|
28789
|
-
let atoms = me.hashUtilsCls.hash2Atoms(ic.chains[chainid], ic.atoms);
|
|
28790
|
-
let bCalphaOnly = me.utilsCls.isCalphaPhosOnly(atoms); //, 'CA');
|
|
28791
|
-
bCalphaOnlyHash[chainid] = bCalphaOnly;
|
|
28922
|
+
getFirstAtomObjByName(atomsHash, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
28923
|
+
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
28924
|
+
return ic.atoms[0];
|
|
28792
28925
|
}
|
|
28793
28926
|
|
|
28794
|
-
|
|
28795
|
-
let residueHash = {};
|
|
28796
|
-
for(let i in atomsAdjust) {
|
|
28797
|
-
let atom = ic.atoms[i];
|
|
28927
|
+
let firstIndex;
|
|
28798
28928
|
|
|
28799
|
-
|
|
28800
|
-
|
|
28929
|
+
for(let i in atomsHash) {
|
|
28930
|
+
if(ic.atoms[i].name == atomName) {
|
|
28931
|
+
firstIndex = i;
|
|
28932
|
+
break;
|
|
28933
|
+
}
|
|
28801
28934
|
}
|
|
28802
|
-
Object.keys(residueHash).length;
|
|
28803
|
-
|
|
28804
|
-
let bFullAtom = (Object.keys(ic.hAtoms).length == Object.keys(ic.atoms).length) ? true : false;
|
|
28805
28935
|
|
|
28806
|
-
|
|
28936
|
+
return (firstIndex !== undefined) ? ic.atoms[firstIndex] : undefined;
|
|
28937
|
+
}
|
|
28807
28938
|
|
|
28808
|
-
|
|
28939
|
+
//Return the last atom in the atom hash, which has the atom serial number as the key.
|
|
28940
|
+
getLastAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
28941
|
+
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
28942
|
+
return ic.atoms[0];
|
|
28943
|
+
}
|
|
28809
28944
|
|
|
28810
|
-
|
|
28811
|
-
let
|
|
28812
|
-
let lastAtomSerial = atomArray[atomArray.length - 1];
|
|
28813
|
-
let lastAtom = ic.atoms[lastAtomSerial];
|
|
28814
|
-
let lastResid = lastAtom.structure + '_' + lastAtom.chain + '_' + lastAtom.resi;
|
|
28945
|
+
let atomKeys = Object.keys(atomsHash);
|
|
28946
|
+
let lastIndex = atomKeys[atomKeys.length - 1];
|
|
28815
28947
|
|
|
28816
|
-
|
|
28817
|
-
|
|
28818
|
-
let chainid = atom.structure + '_' + atom.chain;
|
|
28819
|
-
let resid = atom.structure + '_' + atom.chain + '_' + atom.resi;
|
|
28820
|
-
if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
|
|
28821
|
-
// "CA" has to appear before "O"
|
|
28948
|
+
return ic.atoms[lastIndex];
|
|
28949
|
+
}
|
|
28822
28950
|
|
|
28823
|
-
|
|
28824
|
-
|
|
28951
|
+
//Return the residue hash from the atom hash. The residue hash has the resid as the key and 1 as the value.
|
|
28952
|
+
getResiduesFromAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
28953
|
+
let residuesHash = {};
|
|
28954
|
+
for(let i in atomsHash) {
|
|
28955
|
+
let residueid = ic.atoms[i].structure + '_' + ic.atoms[i].chain + '_' + ic.atoms[i].resi;
|
|
28956
|
+
residuesHash[residueid] = 1;
|
|
28957
|
+
}
|
|
28825
28958
|
|
|
28826
|
-
|
|
28827
|
-
|
|
28828
|
-
calphaid = atom.serial;
|
|
28959
|
+
return residuesHash;
|
|
28960
|
+
}
|
|
28829
28961
|
|
|
28830
|
-
|
|
28962
|
+
getResiduesFromCalphaAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
28963
|
+
let residuesHash = {};
|
|
28964
|
+
for(let i in atomsHash) {
|
|
28965
|
+
if((ic.atoms[i].name == 'CA' && ic.proteins.hasOwnProperty(i)) || !ic.proteins.hasOwnProperty(i)) {
|
|
28966
|
+
let residueid = ic.atoms[i].structure + '_' + ic.atoms[i].chain + '_' + ic.atoms[i].resi;
|
|
28967
|
+
//residuesHash[residueid] = 1;
|
|
28968
|
+
residuesHash[residueid] = ic.atoms[i].resn;
|
|
28831
28969
|
}
|
|
28970
|
+
}
|
|
28832
28971
|
|
|
28833
|
-
|
|
28834
|
-
|
|
28835
|
-
currentCA = atom.coord;
|
|
28836
|
-
currentColor = atom.color;
|
|
28837
|
-
calphaid = atom.serial;
|
|
28838
|
-
}
|
|
28972
|
+
return residuesHash;
|
|
28973
|
+
}
|
|
28839
28974
|
|
|
28840
|
-
|
|
28841
|
-
|
|
28842
|
-
|
|
28843
|
-
|
|
28844
|
-
|
|
28845
|
-
|
|
28846
|
-
// if (currentChain !== atom.chain) {
|
|
28847
|
-
// //if (currentChain !== atom.chain) {
|
|
28848
|
-
// bSameChain = false;
|
|
28849
|
-
// }
|
|
28975
|
+
//Return the chain hash from the atom hash. The chain hash has the chainid as the key and 1 as the value.
|
|
28976
|
+
getChainsFromAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
28977
|
+
let chainsHash = {};
|
|
28978
|
+
for(let i in atomsHash) {
|
|
28979
|
+
let atom = ic.atoms[i];
|
|
28980
|
+
let chainid = atom.structure + "_" + atom.chain;
|
|
28850
28981
|
|
|
28851
|
-
|
|
28852
|
-
|
|
28853
|
-
}
|
|
28854
|
-
else if( (atom.ssend && atom.ss === 'helix') || resid == lastResid) { // partial sheet will draw as helix
|
|
28855
|
-
bHelixSegment = true;
|
|
28856
|
-
}
|
|
28982
|
+
chainsHash[chainid] = 1;
|
|
28983
|
+
}
|
|
28857
28984
|
|
|
28858
|
-
|
|
28859
|
-
|
|
28860
|
-
if(bHighlight === 1 || bHighlight === 2) {
|
|
28861
|
-
colors.push(ic.hColor);
|
|
28862
|
-
}
|
|
28863
|
-
else {
|
|
28864
|
-
colors.push(prevColor);
|
|
28865
|
-
}
|
|
28985
|
+
return chainsHash;
|
|
28986
|
+
}
|
|
28866
28987
|
|
|
28867
|
-
|
|
28868
|
-
|
|
28869
|
-
|
|
28870
|
-
|
|
28871
|
-
|
|
28872
|
-
|
|
28873
|
-
|
|
28874
|
-
|
|
28875
|
-
}
|
|
28988
|
+
getAtomFromResi(resid, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
28989
|
+
if(ic.residues.hasOwnProperty(resid)) {
|
|
28990
|
+
for(let i in ic.residues[resid]) {
|
|
28991
|
+
if(ic.atoms[i].name === atomName && !ic.atoms[i].het) {
|
|
28992
|
+
return ic.atoms[i];
|
|
28993
|
+
}
|
|
28994
|
+
}
|
|
28995
|
+
}
|
|
28876
28996
|
|
|
28877
|
-
|
|
28878
|
-
|
|
28879
|
-
O = prevCoorO.clone();
|
|
28880
|
-
if(prevCoorCA !== null && prevCoorCA !== undefined) {
|
|
28881
|
-
O.sub(prevCoorCA);
|
|
28882
|
-
}
|
|
28883
|
-
else {
|
|
28884
|
-
prevCoorCA = prevCoorO.clone();
|
|
28885
|
-
if(caArray.length > resSpan + 1) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
28886
|
-
O = prevCoorCA.clone();
|
|
28887
|
-
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan - 1]].coord.clone();
|
|
28888
|
-
//O.sub(oldCA);
|
|
28889
|
-
oldCA.sub(O);
|
|
28890
|
-
}
|
|
28891
|
-
else {
|
|
28892
|
-
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
28893
|
-
}
|
|
28894
|
-
}
|
|
28895
|
-
}
|
|
28896
|
-
else if(bCalphaOnlyHash[chainid] && atom.name === 'CA') {
|
|
28897
|
-
if(caArray.length > resSpan + 1) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
28898
|
-
O = prevCoorCA.clone();
|
|
28899
|
-
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan - 1]].coord.clone();
|
|
28900
|
-
//O.sub(oldCA);
|
|
28901
|
-
oldCA.sub(O);
|
|
28902
|
-
}
|
|
28903
|
-
else {
|
|
28904
|
-
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
28905
|
-
}
|
|
28906
|
-
}
|
|
28997
|
+
return undefined;
|
|
28998
|
+
}
|
|
28907
28999
|
|
|
28908
|
-
|
|
28909
|
-
|
|
28910
|
-
|
|
28911
|
-
|
|
29000
|
+
getAtomCoordFromResi(resid, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
29001
|
+
let atom = this.getAtomFromResi(resid, atomName);
|
|
29002
|
+
if(atom !== undefined) {
|
|
29003
|
+
let coord = (atom.coord2 !== undefined) ? atom.coord2 : atom.coord;
|
|
28912
29004
|
|
|
28913
|
-
|
|
28914
|
-
|
|
28915
|
-
let v = new THREE.Vector3(prevCoorCA.x + prevCO.x * delta, prevCoorCA.y + prevCO.y * delta, prevCoorCA.z + prevCO.z * delta);
|
|
28916
|
-
if (!doNotSmoothen && ss === 'sheet') v.smoothen = true;
|
|
28917
|
-
pnts[j].push(v);
|
|
28918
|
-
}
|
|
29005
|
+
return coord;
|
|
29006
|
+
}
|
|
28919
29007
|
|
|
28920
|
-
|
|
28921
|
-
|
|
29008
|
+
return undefined;
|
|
29009
|
+
}
|
|
29010
|
+
}
|
|
28922
29011
|
|
|
28923
|
-
|
|
28924
|
-
|
|
28925
|
-
|
|
28926
|
-
}
|
|
28927
|
-
else {
|
|
28928
|
-
bShowArray.push(0);
|
|
28929
|
-
calphaIdArray.push(0);
|
|
28930
|
-
}
|
|
28931
|
-
}
|
|
29012
|
+
/**
|
|
29013
|
+
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
29014
|
+
*/
|
|
28932
29015
|
|
|
28933
|
-
|
|
29016
|
+
class Strip {
|
|
29017
|
+
constructor(icn3d) {
|
|
29018
|
+
this.icn3d = icn3d;
|
|
29019
|
+
}
|
|
28934
29020
|
|
|
28935
|
-
|
|
28936
|
-
|
|
28937
|
-
|
|
28938
|
-
|
|
28939
|
-
// check whether the atoms are continuous
|
|
28940
|
-
// atomsAdjusted has all atoms in the secondary structure
|
|
28941
|
-
// atoms has all selected atoms
|
|
28942
|
-
// let bBrokenSs = false;
|
|
28943
|
-
// if(prevAtomSelected && prevAtomid == prevAtomSelected.serial && !atoms.hasOwnProperty(atom.serial)) {
|
|
28944
|
-
// bBrokenSs = true;
|
|
28945
|
-
// }
|
|
29021
|
+
// modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
29022
|
+
createStrip(p0, p1, colors, div, thickness, bHighlight, bNoSmoothen, bShowArray,
|
|
29023
|
+
calphaIdArray, positions, prevone, nexttwo, pntsCA, prevCOArray) { let ic = this.icn3d, me = ic.icn3dui;
|
|
29024
|
+
if(me.bNode) return;
|
|
28946
29025
|
|
|
29026
|
+
if (p0.length < 2) return;
|
|
29027
|
+
div = div || ic.axisDIV;
|
|
28947
29028
|
|
|
28948
|
-
|
|
28949
|
-
|
|
29029
|
+
// if(pntsCA && ic.bDoublecolor && !ic.bCalphaOnly) {
|
|
29030
|
+
if(pntsCA && ic.bDoublecolor) {
|
|
29031
|
+
let bExtendLastRes = false; //true;
|
|
28950
29032
|
|
|
28951
|
-
|
|
28952
|
-
|
|
28953
|
-
// }
|
|
28954
|
-
// else if(bBrokenSs && atom.ss === 'helix') {
|
|
28955
|
-
// bHelixSegment = true;
|
|
28956
|
-
// }
|
|
29033
|
+
let pnts_clrs = me.subdivideCls.subdivide(pntsCA, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29034
|
+
pntsCA = pnts_clrs[0];
|
|
28957
29035
|
|
|
28958
|
-
|
|
28959
|
-
// 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
|
|
29036
|
+
this.setCalphaDrawnCoord(pntsCA, div, calphaIdArray);
|
|
28960
29037
|
|
|
28961
|
-
|
|
28962
|
-
|
|
28963
|
-
|
|
28964
|
-
let prevone = [], nexttwo = [];
|
|
29038
|
+
for(let i = 0, il = prevCOArray.length; i < il; ++i) {
|
|
29039
|
+
prevCOArray[i].normalize();
|
|
29040
|
+
}
|
|
28965
29041
|
|
|
28966
|
-
|
|
28967
|
-
|
|
28968
|
-
}
|
|
28969
|
-
else {
|
|
28970
|
-
let prevoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) - 1).toString();
|
|
28971
|
-
let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
|
|
28972
|
-
prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
|
|
28973
|
-
}
|
|
29042
|
+
let pnts_clrs2 = me.subdivideCls.subdivide(prevCOArray, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29043
|
+
prevCOArray = pnts_clrs2[0];
|
|
28974
29044
|
|
|
28975
|
-
|
|
28976
|
-
|
|
28977
|
-
|
|
28978
|
-
if(nextoneCoord !== undefined) {
|
|
28979
|
-
nexttwo.push(nextoneCoord);
|
|
28980
|
-
}
|
|
29045
|
+
colors = pnts_clrs[2];
|
|
29046
|
+
}
|
|
29047
|
+
else {
|
|
28981
29048
|
|
|
28982
|
-
|
|
28983
|
-
|
|
28984
|
-
|
|
28985
|
-
|
|
28986
|
-
|
|
28987
|
-
|
|
29049
|
+
if(!bNoSmoothen) {
|
|
29050
|
+
//var bExtendLastRes = true;
|
|
29051
|
+
let bExtendLastRes = false;
|
|
29052
|
+
let pnts_clrs0 = me.subdivideCls.subdivide(p0, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29053
|
+
let pnts_clrs1 = me.subdivideCls.subdivide(p1, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29054
|
+
p0 = pnts_clrs0[0];
|
|
29055
|
+
p1 = pnts_clrs1[0];
|
|
29056
|
+
colors = pnts_clrs0[2];
|
|
29057
|
+
}
|
|
29058
|
+
if (p0.length < 2) return;
|
|
28988
29059
|
|
|
28989
|
-
|
|
28990
|
-
|
|
28991
|
-
// assign the current joint residue to the previous segment
|
|
28992
|
-
if(bHighlight === 1 || bHighlight === 2) {
|
|
28993
|
-
colors.push(ic.hColor);
|
|
28994
|
-
}
|
|
28995
|
-
else {
|
|
28996
|
-
//colors.push(atom.color);
|
|
28997
|
-
colors.push(prevColor);
|
|
28998
|
-
}
|
|
29060
|
+
this.setCalphaDrawnCoord(p0, div, calphaIdArray);
|
|
29061
|
+
}
|
|
28999
29062
|
|
|
29000
|
-
|
|
29001
|
-
|
|
29002
|
-
}
|
|
29003
|
-
else if(ss === 'coil' && atom.ssbegin) {
|
|
29004
|
-
strandWidth = coilWidth;
|
|
29005
|
-
}
|
|
29006
|
-
else if(ssend && atom.ssbegin) { // current residue is the start of ss and the previous residue is the end of ss, then use coil
|
|
29007
|
-
strandWidth = coilWidth;
|
|
29008
|
-
}
|
|
29009
|
-
else { // use the ss from the previous residue
|
|
29010
|
-
strandWidth = (atom.ss === 'coil') ? coilWidth : helixSheetWidth;
|
|
29011
|
-
}
|
|
29063
|
+
if(bHighlight === 1) {
|
|
29064
|
+
//mesh = new THREE.Mesh(geo, ic.matShader);
|
|
29012
29065
|
|
|
29013
|
-
|
|
29014
|
-
|
|
29015
|
-
|
|
29016
|
-
|
|
29017
|
-
}
|
|
29018
|
-
else if(bCalphaOnlyHash[chainid] && atom.name === 'CA') {
|
|
29019
|
-
if(caArray.length > resSpan) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
29020
|
-
O = currentCA.clone();
|
|
29021
|
-
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan]].coord.clone();
|
|
29022
|
-
//O.sub(oldCA);
|
|
29023
|
-
oldCA.sub(O);
|
|
29024
|
-
}
|
|
29025
|
-
else {
|
|
29026
|
-
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
29027
|
-
}
|
|
29028
|
-
}
|
|
29066
|
+
let radius = ic.coilWidth / 2;
|
|
29067
|
+
//var radiusSegments = 8;
|
|
29068
|
+
let radiusSegments = 4; // save memory
|
|
29069
|
+
let closed = false;
|
|
29029
29070
|
|
|
29030
|
-
|
|
29031
|
-
|
|
29032
|
-
|
|
29033
|
-
prevCO = O;
|
|
29071
|
+
if(positions !== undefined) {
|
|
29072
|
+
let currPos, prevPos;
|
|
29073
|
+
let currP0 = [], currP1 = [];
|
|
29034
29074
|
|
|
29035
|
-
|
|
29036
|
-
|
|
29037
|
-
let v = new THREE.Vector3(currentCA.x + prevCO.x * delta, currentCA.y + prevCO.y * delta, currentCA.z + prevCO.z * delta);
|
|
29038
|
-
if (!doNotSmoothen && ss === 'sheet') v.smoothen = true;
|
|
29039
|
-
pnts[j].push(v);
|
|
29040
|
-
}
|
|
29075
|
+
for(let i = 0, il = p0.length; i < il; ++i) {
|
|
29076
|
+
currPos = positions[i];
|
|
29041
29077
|
|
|
29042
|
-
|
|
29078
|
+
if((currPos !== prevPos && parseInt(currPos) !== parseInt(prevPos) + 1 && prevPos !== undefined) || (i === il -1) ) {
|
|
29079
|
+
// first tube
|
|
29080
|
+
let geometry0 = new THREE.TubeGeometry(
|
|
29081
|
+
new THREE.CatmullRomCurve3(currP0), // path
|
|
29082
|
+
currP0.length, // segments
|
|
29083
|
+
radius,
|
|
29084
|
+
radiusSegments,
|
|
29085
|
+
closed
|
|
29086
|
+
);
|
|
29043
29087
|
|
|
29044
|
-
|
|
29045
|
-
|
|
29088
|
+
let mesh = new THREE.Mesh(geometry0, ic.matShader);
|
|
29089
|
+
mesh.renderOrder = ic.renderOrderPicking;
|
|
29090
|
+
//ic.mdlPicking.add(mesh);
|
|
29091
|
+
ic.mdl.add(mesh);
|
|
29046
29092
|
|
|
29047
|
-
|
|
29048
|
-
//if(atoms.hasOwnProperty(atomid) && (bHighlight === 1 && !atom.notshow) ) {
|
|
29049
|
-
if(atoms.hasOwnProperty(atomid)) {
|
|
29050
|
-
bShowArray.push(atom.resi);
|
|
29051
|
-
calphaIdArray.push(calphaid);
|
|
29052
|
-
}
|
|
29053
|
-
else {
|
|
29054
|
-
bShowArray.push(0);
|
|
29055
|
-
calphaIdArray.push(0);
|
|
29056
|
-
}
|
|
29057
|
-
}
|
|
29058
|
-
|
|
29059
|
-
// draw the current segment
|
|
29060
|
-
for (let j = 0; !fill && j < num; ++j) {
|
|
29061
|
-
if(bSheetSegment) {
|
|
29062
|
-
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
29063
|
-
}
|
|
29064
|
-
else if(bHelixSegment) {
|
|
29065
|
-
if(bFullAtom) {
|
|
29066
|
-
ic.curveCls.createCurveSub(pnts[j], 1, colors, div, bHighlight, bRibbon, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo);
|
|
29067
|
-
}
|
|
29068
|
-
else {
|
|
29069
|
-
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
29070
|
-
}
|
|
29071
|
-
}
|
|
29072
|
-
}
|
|
29073
|
-
if (fill) {
|
|
29074
|
-
if(bSheetSegment) {
|
|
29075
|
-
let start = 0, end = num - 1;
|
|
29076
|
-
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
29077
|
-
}
|
|
29078
|
-
else if(bHelixSegment) {
|
|
29079
|
-
if(bFullAtom) {
|
|
29080
|
-
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
29081
|
-
}
|
|
29082
|
-
else {
|
|
29083
|
-
let start = 0, end = num - 1;
|
|
29084
|
-
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
29085
|
-
}
|
|
29086
|
-
}
|
|
29087
|
-
else {
|
|
29088
|
-
if(bHighlight === 2) { // draw coils only when highlighted. if not highlighted, coils will be drawn as tubes separately
|
|
29089
|
-
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
29090
|
-
}
|
|
29091
|
-
}
|
|
29092
|
-
}
|
|
29093
|
-
for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
29094
|
-
|
|
29095
|
-
colors = [];
|
|
29096
|
-
pntsCA = [];
|
|
29097
|
-
prevCOArray = [];
|
|
29098
|
-
bShowArray = [];
|
|
29099
|
-
calphaIdArray = [];
|
|
29100
|
-
bSheetSegment = false;
|
|
29101
|
-
bHelixSegment = false;
|
|
29102
|
-
} // end if (atom.ssbegin || atom.ssend)
|
|
29103
|
-
|
|
29104
|
-
// end of a chain, or end of selection
|
|
29105
|
-
if ((currentChain !== atom.chain
|
|
29106
|
-
|| ic.ParserUtilsCls.getResiNCBI(atom.structure + '_' + currentChain, currentResi) + 1 !== ic.ParserUtilsCls.getResiNCBI(chainid, atom.resi)
|
|
29107
|
-
// || (drawnResidueCount === totalResidueCount - 1)
|
|
29108
|
-
// || bBrokenSs
|
|
29109
|
-
|| (resid == lastResid && atom.ss != 'coil')
|
|
29110
|
-
) && pnts[0].length > 0) {
|
|
29111
|
-
//if ((currentChain !== atom.chain) && pnts[0].length > 0) {
|
|
29112
|
-
|
|
29113
|
-
let atomName = 'CA';
|
|
29114
|
-
|
|
29115
|
-
let prevone = [], nexttwo = [];
|
|
29116
|
-
if(isNaN(ic.atoms[prevAtomid].resi)) {
|
|
29117
|
-
prevone = [];
|
|
29118
|
-
}
|
|
29119
|
-
else {
|
|
29120
|
-
let prevoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) - 1).toString();
|
|
29121
|
-
ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
|
|
29122
|
-
}
|
|
29123
|
-
|
|
29124
|
-
for (let j = 0; !fill && j < num; ++j) {
|
|
29125
|
-
if(bSheetSegment) {
|
|
29126
|
-
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
29127
|
-
}
|
|
29128
|
-
else if(bHelixSegment) {
|
|
29129
|
-
if(bFullAtom) {
|
|
29130
|
-
ic.curveCls.createCurveSub(pnts[j], 1, colors, div, bHighlight, bRibbon, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo);
|
|
29131
|
-
}
|
|
29132
|
-
else {
|
|
29133
|
-
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
29134
|
-
}
|
|
29135
|
-
}
|
|
29136
|
-
}
|
|
29137
|
-
if (fill) {
|
|
29138
|
-
if(bSheetSegment) {
|
|
29139
|
-
let start = 0, end = num - 1;
|
|
29140
|
-
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
29141
|
-
}
|
|
29142
|
-
else if(bHelixSegment) {
|
|
29143
|
-
if(bFullAtom) {
|
|
29144
|
-
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
29145
|
-
}
|
|
29146
|
-
else {
|
|
29147
|
-
let start = 0, end = num - 1;
|
|
29148
|
-
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
29149
|
-
}
|
|
29150
|
-
}
|
|
29151
|
-
}
|
|
29152
|
-
|
|
29153
|
-
for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
29154
|
-
colors = [];
|
|
29155
|
-
pntsCA = [];
|
|
29156
|
-
prevCOArray = [];
|
|
29157
|
-
bShowArray = [];
|
|
29158
|
-
calphaIdArray = [];
|
|
29159
|
-
bSheetSegment = false;
|
|
29160
|
-
bHelixSegment = false;
|
|
29161
|
-
}
|
|
29162
|
-
|
|
29163
|
-
currentChain = atom.chain;
|
|
29164
|
-
currentResi = atom.resi;
|
|
29165
|
-
ss = atom.ss;
|
|
29166
|
-
ssend = atom.ssend;
|
|
29167
|
-
prevAtomid = atom.serial;
|
|
29168
|
-
if(atoms.hasOwnProperty(atom.serial)) prevAtomSelected = atom;
|
|
29169
|
-
prevResi = atom.resi;
|
|
29170
|
-
|
|
29171
|
-
prevCalphaid = calphaid;
|
|
29172
|
-
|
|
29173
|
-
// only update when atom.name === 'O'
|
|
29174
|
-
prevCoorCA = currentCA;
|
|
29175
|
-
prevCoorO = atom.coord;
|
|
29176
|
-
prevColor = currentColor;
|
|
29177
|
-
} // end if (atom.name === 'O' || (bCalphaOnlyHash[chainid] && atom.name === 'CA') ) {
|
|
29178
|
-
} // end if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
|
|
29179
|
-
} // end for
|
|
29180
|
-
|
|
29181
|
-
caArray = [];
|
|
29182
|
-
|
|
29183
|
-
// ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight);
|
|
29184
|
-
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
29185
|
-
ic.tubeCls.createTube(atomsAdjust, 'CA', coilWidth, bHighlight);
|
|
29186
|
-
pnts = {};
|
|
29187
|
-
}
|
|
29188
|
-
|
|
29189
|
-
getOneExtraResidue(residueHash) { let ic = this.icn3d, me = ic.icn3dui;
|
|
29190
|
-
let atomsAdjust = {};
|
|
29191
|
-
|
|
29192
|
-
for(let resid in residueHash) {
|
|
29193
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, ic.residues[resid]);
|
|
29194
|
-
|
|
29195
|
-
let residNcbi = ic.resid2ncbi[resid];
|
|
29196
|
-
let resiNcbi = residNcbi.substr(residNcbi.lastIndexOf('_') + 1);
|
|
29197
|
-
|
|
29198
|
-
let nextResidNcbi = residNcbi.substr(0, residNcbi.lastIndexOf('_')) + '_' + (parseInt(resiNcbi) + 1);
|
|
29199
|
-
let nextResid = ic.ncbi2resid[nextResidNcbi];
|
|
29200
|
-
|
|
29201
|
-
if(!nextResid) {
|
|
29202
|
-
nextResidNcbi = residNcbi.substr(0, residNcbi.lastIndexOf('_')) + '_' + (parseInt(resiNcbi) - 1);
|
|
29203
|
-
nextResid = ic.ncbi2resid[nextResidNcbi];
|
|
29204
|
-
}
|
|
29205
|
-
|
|
29206
|
-
if(nextResid) atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, ic.residues[nextResid]);
|
|
29207
|
-
}
|
|
29208
|
-
|
|
29209
|
-
return atomsAdjust;
|
|
29210
|
-
}
|
|
29211
|
-
|
|
29212
|
-
/*
|
|
29213
|
-
getSSExpandedAtoms(atoms, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
|
|
29214
|
-
let currChain, currResi, currAtom, prevChain, prevResi, prevAtom;
|
|
29215
|
-
let firstAtom, lastAtom;
|
|
29216
|
-
let index = 0, length = Object.keys(atoms).length;
|
|
29217
|
-
|
|
29218
|
-
let atomsAdjust = me.hashUtilsCls.cloneHash(atoms);
|
|
29219
|
-
for(let serial in atoms) {
|
|
29220
|
-
currChain = atoms[serial].structure + '_' + atoms[serial].chain;
|
|
29221
|
-
currResi = atoms[serial].resi; //parseInt(atoms[serial].resi);
|
|
29222
|
-
currAtom = atoms[serial];
|
|
29223
|
-
|
|
29224
|
-
if(prevChain === undefined) firstAtom = atoms[serial];
|
|
29225
|
-
|
|
29226
|
-
if( (currChain !== prevChain && prevChain !== undefined)
|
|
29227
|
-
|| (currResi !== prevResi && ic.resid2ncbi[currResi] !== ic.resid2ncbi[prevResi] + 1 && prevResi !== undefined) || index === length - 1) {
|
|
29228
|
-
if( (currChain !== prevChain && prevChain !== undefined)
|
|
29229
|
-
|| (currResi !== prevResi && currResi !== ic.resid2ncbi[prevResi] + 1 && prevResi !== undefined) ) {
|
|
29230
|
-
lastAtom = prevAtom;
|
|
29231
|
-
}
|
|
29232
|
-
else if(index === length - 1) {
|
|
29233
|
-
lastAtom = currAtom;
|
|
29234
|
-
}
|
|
29235
|
-
|
|
29236
|
-
// fill the beginning
|
|
29237
|
-
let beginResi = firstAtom.resi;
|
|
29238
|
-
if(!isNaN(firstAtom.resi) && firstAtom.ss !== 'coil' && !(firstAtom.ssbegin) ) {
|
|
29239
|
-
for(let i = parseInt(firstAtom.resi) - 1; i > 0; --i) {
|
|
29240
|
-
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + i;
|
|
29241
|
-
if(!ic.residues.hasOwnProperty(residueid)) break;
|
|
29242
|
-
|
|
29243
|
-
let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[residueid]);
|
|
29244
|
-
|
|
29245
|
-
if(atom.ss === firstAtom.ss && atom.ssbegin) {
|
|
29246
|
-
beginResi = atom.resi;
|
|
29247
|
-
break;
|
|
29248
|
-
}
|
|
29249
|
-
}
|
|
29250
|
-
|
|
29251
|
-
for(let i = beginResi; i < firstAtom.resi; ++i) {
|
|
29252
|
-
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + i;
|
|
29253
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
29254
|
-
ic.atoms));
|
|
29255
|
-
}
|
|
29256
|
-
}
|
|
29257
|
-
|
|
29258
|
-
// add one extra residue for coils between strands/helix
|
|
29259
|
-
if(!isNaN(firstAtom.resi) && ic.pk === 3 && bHighlight === 1 && firstAtom.ss === 'coil') {
|
|
29260
|
-
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
|
|
29261
|
-
if(ic.residues.hasOwnProperty(residueid)) {
|
|
29262
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
29263
|
-
ic.atoms));
|
|
29264
|
-
atoms = me.hashUtilsCls.unionHash(atoms, me.hashUtilsCls.hash2Atoms(ic.residues[residueid], ic.atoms));
|
|
29265
|
-
}
|
|
29266
|
-
}
|
|
29267
|
-
|
|
29268
|
-
// fill the end
|
|
29269
|
-
let endResi = lastAtom.resi;
|
|
29270
|
-
// when a coil connects to a sheet and the last residue of coil is highlighted, the first sheet residue is set as atom.notshow. This residue should not be shown.
|
|
29271
|
-
|
|
29272
|
-
if(lastAtom.ss !== undefined && lastAtom.ss !== 'coil' && !(lastAtom.ssend) && !(lastAtom.notshow)) {
|
|
29273
|
-
|
|
29274
|
-
let endChainResi = ic.firstAtomObjCls.getLastAtomObj(ic.chains[lastAtom.structure + '_' + lastAtom.chain]).resi;
|
|
29275
|
-
for(let i = parseInt(lastAtom.resi) + 1; i <= parseInt(endChainResi); ++i) {
|
|
29276
|
-
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + i;
|
|
29277
|
-
if(!ic.residues.hasOwnProperty(residueid)) break;
|
|
29278
|
-
|
|
29279
|
-
let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[residueid]);
|
|
29280
|
-
|
|
29281
|
-
if(atom.ss === lastAtom.ss && atom.ssend) {
|
|
29282
|
-
endResi = atom.resi;
|
|
29283
|
-
break;
|
|
29284
|
-
}
|
|
29285
|
-
}
|
|
29286
|
-
|
|
29287
|
-
for(let i = parseInt(lastAtom.resi) + 1; i <= parseInt(endResi); ++i) {
|
|
29288
|
-
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + i;
|
|
29289
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
29290
|
-
ic.atoms));
|
|
29291
|
-
}
|
|
29292
|
-
}
|
|
29293
|
-
|
|
29294
|
-
// add one extra residue for coils between strands/helix
|
|
29295
|
-
if(ic.pk === 3 && bHighlight === 1 && lastAtom.ss === 'coil') {
|
|
29296
|
-
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + (parseInt(lastAtom.resi) + 1).toString();
|
|
29297
|
-
if(ic.residues.hasOwnProperty(residueid)) {
|
|
29298
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
29299
|
-
ic.atoms));
|
|
29300
|
-
atoms = me.hashUtilsCls.unionHash(atoms, me.hashUtilsCls.hash2Atoms(ic.residues[residueid], ic.atoms));
|
|
29301
|
-
}
|
|
29302
|
-
}
|
|
29303
|
-
|
|
29304
|
-
// reset notshow
|
|
29305
|
-
if(lastAtom.notshow) lastAtom.notshow = undefined;
|
|
29306
|
-
|
|
29307
|
-
firstAtom = currAtom;
|
|
29308
|
-
}
|
|
29309
|
-
|
|
29310
|
-
prevChain = currChain;
|
|
29311
|
-
prevResi = currResi;
|
|
29312
|
-
prevAtom = currAtom;
|
|
29313
|
-
|
|
29314
|
-
++index;
|
|
29315
|
-
}
|
|
29316
|
-
|
|
29317
|
-
return atomsAdjust;
|
|
29318
|
-
}
|
|
29319
|
-
*/
|
|
29320
|
-
}
|
|
29321
|
-
|
|
29322
|
-
/**
|
|
29323
|
-
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
29324
|
-
*/
|
|
29325
|
-
|
|
29326
|
-
class Strip {
|
|
29327
|
-
constructor(icn3d) {
|
|
29328
|
-
this.icn3d = icn3d;
|
|
29329
|
-
}
|
|
29330
|
-
|
|
29331
|
-
// modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
29332
|
-
createStrip(p0, p1, colors, div, thickness, bHighlight, bNoSmoothen, bShowArray,
|
|
29333
|
-
calphaIdArray, positions, prevone, nexttwo, pntsCA, prevCOArray) { let ic = this.icn3d, me = ic.icn3dui;
|
|
29334
|
-
if(me.bNode) return;
|
|
29335
|
-
|
|
29336
|
-
if (p0.length < 2) return;
|
|
29337
|
-
div = div || ic.axisDIV;
|
|
29338
|
-
|
|
29339
|
-
// if(pntsCA && ic.bDoublecolor && !ic.bCalphaOnly) {
|
|
29340
|
-
if(pntsCA && ic.bDoublecolor) {
|
|
29341
|
-
let bExtendLastRes = false; //true;
|
|
29342
|
-
|
|
29343
|
-
let pnts_clrs = me.subdivideCls.subdivide(pntsCA, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29344
|
-
pntsCA = pnts_clrs[0];
|
|
29345
|
-
|
|
29346
|
-
this.setCalphaDrawnCoord(pntsCA, div, calphaIdArray);
|
|
29347
|
-
|
|
29348
|
-
for(let i = 0, il = prevCOArray.length; i < il; ++i) {
|
|
29349
|
-
prevCOArray[i].normalize();
|
|
29350
|
-
}
|
|
29351
|
-
|
|
29352
|
-
let pnts_clrs2 = me.subdivideCls.subdivide(prevCOArray, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29353
|
-
prevCOArray = pnts_clrs2[0];
|
|
29354
|
-
|
|
29355
|
-
colors = pnts_clrs[2];
|
|
29356
|
-
}
|
|
29357
|
-
else {
|
|
29358
|
-
|
|
29359
|
-
if(!bNoSmoothen) {
|
|
29360
|
-
//var bExtendLastRes = true;
|
|
29361
|
-
let bExtendLastRes = false;
|
|
29362
|
-
let pnts_clrs0 = me.subdivideCls.subdivide(p0, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29363
|
-
let pnts_clrs1 = me.subdivideCls.subdivide(p1, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29364
|
-
p0 = pnts_clrs0[0];
|
|
29365
|
-
p1 = pnts_clrs1[0];
|
|
29366
|
-
colors = pnts_clrs0[2];
|
|
29367
|
-
}
|
|
29368
|
-
if (p0.length < 2) return;
|
|
29369
|
-
|
|
29370
|
-
this.setCalphaDrawnCoord(p0, div, calphaIdArray);
|
|
29371
|
-
}
|
|
29372
|
-
|
|
29373
|
-
if(bHighlight === 1) {
|
|
29374
|
-
//mesh = new THREE.Mesh(geo, ic.matShader);
|
|
29375
|
-
|
|
29376
|
-
let radius = ic.coilWidth / 2;
|
|
29377
|
-
//var radiusSegments = 8;
|
|
29378
|
-
let radiusSegments = 4; // save memory
|
|
29379
|
-
let closed = false;
|
|
29380
|
-
|
|
29381
|
-
if(positions !== undefined) {
|
|
29382
|
-
let currPos, prevPos;
|
|
29383
|
-
let currP0 = [], currP1 = [];
|
|
29384
|
-
|
|
29385
|
-
for(let i = 0, il = p0.length; i < il; ++i) {
|
|
29386
|
-
currPos = positions[i];
|
|
29387
|
-
|
|
29388
|
-
if((currPos !== prevPos && parseInt(currPos) !== parseInt(prevPos) + 1 && prevPos !== undefined) || (i === il -1) ) {
|
|
29389
|
-
// first tube
|
|
29390
|
-
let geometry0 = new THREE.TubeGeometry(
|
|
29391
|
-
new THREE.CatmullRomCurve3(currP0), // path
|
|
29392
|
-
currP0.length, // segments
|
|
29393
|
-
radius,
|
|
29394
|
-
radiusSegments,
|
|
29395
|
-
closed
|
|
29396
|
-
);
|
|
29397
|
-
|
|
29398
|
-
let mesh = new THREE.Mesh(geometry0, ic.matShader);
|
|
29399
|
-
mesh.renderOrder = ic.renderOrderPicking;
|
|
29400
|
-
//ic.mdlPicking.add(mesh);
|
|
29401
|
-
ic.mdl.add(mesh);
|
|
29402
|
-
|
|
29403
|
-
ic.prevHighlightObjects.push(mesh);
|
|
29093
|
+
ic.prevHighlightObjects.push(mesh);
|
|
29404
29094
|
|
|
29405
29095
|
geometry0 = null;
|
|
29406
29096
|
|
|
@@ -29687,6 +29377,7 @@ class Tube {
|
|
|
29687
29377
|
atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) - 1).toString();
|
|
29688
29378
|
|
|
29689
29379
|
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
|
|
29380
|
+
|| (prevAtom.ssbegin) // e.g., https://www.ncbi.nlm.nih.gov/Structure/icn3d/?pdbid=7JO8 where a beta sheet has just two residues
|
|
29690
29381
|
// || (parseInt(currentResi) + 1 < parseInt(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) && ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[resid]) && ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[resid]).ss == 'helix')
|
|
29691
29382
|
|| (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))
|
|
29692
29383
|
) ) {
|
|
@@ -29779,7 +29470,7 @@ class Tube {
|
|
|
29779
29470
|
}
|
|
29780
29471
|
|
|
29781
29472
|
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
29782
|
-
if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
|
|
29473
|
+
// if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
|
|
29783
29474
|
|
|
29784
29475
|
//radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
|
|
29785
29476
|
radii.push(radiusFinal);
|
|
@@ -29922,224 +29613,770 @@ class Tube {
|
|
|
29922
29613
|
radiusFinal = this.getRadius(radius, atom);
|
|
29923
29614
|
}
|
|
29924
29615
|
|
|
29925
|
-
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
29926
|
-
if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
|
|
29616
|
+
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
29617
|
+
if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
|
|
29618
|
+
|
|
29619
|
+
//radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
|
|
29620
|
+
radii.push(radiusFinal);
|
|
29621
|
+
|
|
29622
|
+
colors.push(atom.color);
|
|
29623
|
+
// the starting residue of a coil uses the color from the next residue to avoid using the color of the last helix/sheet residue
|
|
29624
|
+
if(index === 1) colors[colors.length - 2] = atom.color;
|
|
29625
|
+
|
|
29626
|
+
currentChain = atom.chain;
|
|
29627
|
+
currentResi = atom.resi;
|
|
29628
|
+
|
|
29629
|
+
let scale = 1.2;
|
|
29630
|
+
if(bHighlight === 2 && !atom.ssbegin) {
|
|
29631
|
+
ic.boxCls.createBox(atom, undefined, undefined, scale, undefined, bHighlight);
|
|
29632
|
+
}
|
|
29633
|
+
|
|
29634
|
+
++index;
|
|
29635
|
+
|
|
29636
|
+
prevAtom = atom;
|
|
29637
|
+
}
|
|
29638
|
+
}
|
|
29639
|
+
|
|
29640
|
+
if(bHighlight !== 2) {
|
|
29641
|
+
pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
|
|
29642
|
+
}
|
|
29643
|
+
|
|
29644
|
+
for(let i = 0, il = pnts_colors_radii_prevone_nexttwo.length; i < il; ++i) {
|
|
29645
|
+
let pnts = pnts_colors_radii_prevone_nexttwo[i].pnts;
|
|
29646
|
+
let colors = pnts_colors_radii_prevone_nexttwo[i].colors;
|
|
29647
|
+
let radii = pnts_colors_radii_prevone_nexttwo[i].radii;
|
|
29648
|
+
let prevone = []; // = pnts_colors_radii_prevone_nexttwo[i].prevone;
|
|
29649
|
+
let nexttwo = []; // = pnts_colors_radii_prevone_nexttwo[i].nexttwo;
|
|
29650
|
+
|
|
29651
|
+
this.createTubeSub(pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil);
|
|
29652
|
+
}
|
|
29653
|
+
|
|
29654
|
+
pnts_colors_radii_prevone_nexttwo = [];
|
|
29655
|
+
}
|
|
29656
|
+
*/
|
|
29657
|
+
|
|
29658
|
+
getCustomtubesize(resid) { let ic = this.icn3d; ic.icn3dui;
|
|
29659
|
+
let pos = resid.lastIndexOf('_');
|
|
29660
|
+
let resi = resid.substr(pos + 1);
|
|
29661
|
+
let chainid = resid.substr(0, pos);
|
|
29662
|
+
|
|
29663
|
+
let radiusFinal = (ic.queryresi2score[chainid] && ic.queryresi2score[chainid].hasOwnProperty(resi)) ? ic.queryresi2score[chainid][resi] * 0.01 : ic.coilWidth;
|
|
29664
|
+
|
|
29665
|
+
return radiusFinal;
|
|
29666
|
+
};
|
|
29667
|
+
|
|
29668
|
+
// modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
29669
|
+
createTubeSub(_pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
|
|
29670
|
+
if(me.bNode) return;
|
|
29671
|
+
|
|
29672
|
+
if (_pnts.length < 2) return;
|
|
29673
|
+
|
|
29674
|
+
let circleDiv = ic.tubeDIV, axisDiv = ic.axisDIV;
|
|
29675
|
+
let circleDivInv = 1 / circleDiv, axisDivInv = 1 / axisDiv;
|
|
29676
|
+
//var geo = new THREE.Geometry();
|
|
29677
|
+
let geo = new THREE.BufferGeometry();
|
|
29678
|
+
let verticeArray = [], colorArray = [],indexArray = [], color;
|
|
29679
|
+
let offset = 0, offset2 = 0, offset3 = 0;
|
|
29680
|
+
|
|
29681
|
+
let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv, undefined, undefined, prevone, nexttwo);
|
|
29682
|
+
|
|
29683
|
+
let pnts = pnts_clrs[0];
|
|
29684
|
+
colors = pnts_clrs[2];
|
|
29685
|
+
|
|
29686
|
+
let constRadiius;
|
|
29687
|
+
// a threshold to stop drawing the tube if it's less than this ratio of radius
|
|
29688
|
+
let thresholdRatio = 1; //0.9;
|
|
29689
|
+
|
|
29690
|
+
let prevAxis1 = new THREE.Vector3(), prevAxis2;
|
|
29691
|
+
for (let i = 0, lim = pnts.length; i < lim; ++i) {
|
|
29692
|
+
let r, idx = (i - 1) * axisDivInv;
|
|
29693
|
+
|
|
29694
|
+
if (i === 0) {
|
|
29695
|
+
r = radii[0];
|
|
29696
|
+
if(r > 0) constRadiius = r;
|
|
29697
|
+
}
|
|
29698
|
+
else {
|
|
29699
|
+
if (idx % 1 === 0) {
|
|
29700
|
+
r = radii[idx];
|
|
29701
|
+
if(r > 0) constRadiius = r;
|
|
29702
|
+
}
|
|
29703
|
+
else {
|
|
29704
|
+
let floored = Math.floor(idx);
|
|
29705
|
+
let tmp = idx - floored;
|
|
29706
|
+
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
29707
|
+
// r = radii[floored] * tmp + radii[floored + 1] * (1 - tmp);
|
|
29708
|
+
r = radii[floored] * (1 - tmp) + radii[floored + 1] * tmp;
|
|
29709
|
+
|
|
29710
|
+
// a threshold to stop drawing the tube if it's less than this ratio of radius.
|
|
29711
|
+
// The extra bit of tube connects coil with strands or helices
|
|
29712
|
+
if(!bNonCoil) {
|
|
29713
|
+
if(r < thresholdRatio * constRadiius) {
|
|
29714
|
+
r = 0;
|
|
29715
|
+
}
|
|
29716
|
+
// else if(r < constRadiius) {
|
|
29717
|
+
// r *= 0.5; // use small radius for the connection between coild and sheets/helices
|
|
29718
|
+
// }
|
|
29719
|
+
}
|
|
29720
|
+
}
|
|
29721
|
+
}
|
|
29722
|
+
let delta, axis1, axis2;
|
|
29723
|
+
if (i < lim - 1) {
|
|
29724
|
+
delta = pnts[i].clone().sub(pnts[i + 1]);
|
|
29725
|
+
axis1 = new THREE.Vector3(0, -delta.z, delta.y).normalize().multiplyScalar(r);
|
|
29726
|
+
axis2 = delta.clone().cross(axis1).normalize().multiplyScalar(r);
|
|
29727
|
+
// let dir = 1, offset = 0;
|
|
29728
|
+
if (prevAxis1.dot(axis1) < 0) {
|
|
29729
|
+
axis1.negate(); axis2.negate(); //dir = -1;//offset = 2 * Math.PI / axisDiv;
|
|
29730
|
+
}
|
|
29731
|
+
prevAxis1 = axis1; prevAxis2 = axis2;
|
|
29732
|
+
} else {
|
|
29733
|
+
axis1 = prevAxis1; axis2 = prevAxis2;
|
|
29734
|
+
}
|
|
29735
|
+
for (let j = 0; j < circleDiv; ++j) {
|
|
29736
|
+
let angle = 2 * Math.PI * circleDivInv * j; //* dir + offset;
|
|
29737
|
+
let point = pnts[i].clone().add(axis1.clone().multiplyScalar(Math.cos(angle))).add(axis2.clone().multiplyScalar(Math.sin(angle)));
|
|
29738
|
+
verticeArray[offset++] = point.x;
|
|
29739
|
+
verticeArray[offset++] = point.y;
|
|
29740
|
+
verticeArray[offset++] = point.z;
|
|
29741
|
+
|
|
29742
|
+
color = (i == colors.length - 1 && colors.length > 1) ? me.parasCls.thr(colors[colors.length - 2]) : me.parasCls.thr(colors[i]);
|
|
29743
|
+
colorArray[offset2++] = color.r;
|
|
29744
|
+
colorArray[offset2++] = color.g;
|
|
29745
|
+
colorArray[offset2++] = color.b;
|
|
29746
|
+
}
|
|
29747
|
+
}
|
|
29748
|
+
let offsetTmp = 0, nComp = 3;
|
|
29749
|
+
for (let i = 0, lim = pnts.length - 1; i < lim; ++i) {
|
|
29750
|
+
let reg = 0;
|
|
29751
|
+
//var r1 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv]).lengthSq();
|
|
29752
|
+
//var r2 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv + 1]).lengthSq();
|
|
29753
|
+
let pos = offsetTmp * nComp;
|
|
29754
|
+
let point1 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
29755
|
+
pos = (offsetTmp + circleDiv) * nComp;
|
|
29756
|
+
let point2 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
29757
|
+
pos = (offsetTmp + circleDiv + 1) * nComp;
|
|
29758
|
+
let point3 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
29759
|
+
|
|
29760
|
+
let r1 = point1.clone().sub(point2).lengthSq();
|
|
29761
|
+
let r2 = point1.clone().sub(point3).lengthSq();
|
|
29762
|
+
if (r1 > r2) { r1 = r2; reg = 1; } for (let j = 0; j < circleDiv; ++j) {
|
|
29763
|
+
//geo.faces.push(new THREE.Face3(offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv, undefined, c));
|
|
29764
|
+
//geo.faces.push(new THREE.Face3(offset + (j + 1) % circleDiv, offset + (j + reg) % circleDiv + circleDiv, offset + (j + reg + 1) % circleDiv + circleDiv, undefined, c));
|
|
29765
|
+
//indexArray = indexArray.concat([offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv]);
|
|
29766
|
+
indexArray[offset3++] = offsetTmp + j;
|
|
29767
|
+
indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
|
|
29768
|
+
indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
|
|
29769
|
+
|
|
29770
|
+
//indexArray = indexArray.concat([offset + (j + 1) % circleDiv, offset + (j + reg) % circleDiv + circleDiv, offset + (j + reg + 1) % circleDiv + circleDiv]);
|
|
29771
|
+
indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
|
|
29772
|
+
indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
|
|
29773
|
+
indexArray[offset3++] = offsetTmp + (j + reg + 1) % circleDiv + circleDiv;
|
|
29774
|
+
}
|
|
29775
|
+
offsetTmp += circleDiv;
|
|
29776
|
+
}
|
|
29777
|
+
|
|
29778
|
+
geo.setAttribute('position', new THREE.BufferAttribute(new Float32Array(verticeArray), nComp));
|
|
29779
|
+
geo.setAttribute('color', new THREE.BufferAttribute(new Float32Array(colorArray), nComp));
|
|
29780
|
+
|
|
29781
|
+
geo.setIndex(new THREE.BufferAttribute(new Uint32Array(indexArray), 1));
|
|
29782
|
+
//geo.setIndex(indexArray);
|
|
29783
|
+
|
|
29784
|
+
//geo.computeFaceNormals();
|
|
29785
|
+
//geo.computeVertexNormals(false);
|
|
29786
|
+
geo.computeVertexNormals();
|
|
29787
|
+
|
|
29788
|
+
let mesh;
|
|
29789
|
+
if(bHighlight === 2) {
|
|
29790
|
+
//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 }));
|
|
29791
|
+
mesh = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({ transparent: true, opacity: 0.5, specular: ic.frac, shininess: ic.shininess, emissive: ic.emissive, vertexColors: true, side: THREE.DoubleSide }));
|
|
29792
|
+
|
|
29793
|
+
if(ic.mdl) ic.mdl.add(mesh);
|
|
29794
|
+
}
|
|
29795
|
+
else if(bHighlight === 1) {
|
|
29796
|
+
mesh = new THREE.Mesh(geo, ic.matShader);
|
|
29797
|
+
mesh.renderOrder = ic.renderOrderPicking;
|
|
29798
|
+
//ic.mdlPicking.add(mesh);
|
|
29799
|
+
if(ic.mdl) ic.mdl.add(mesh);
|
|
29800
|
+
}
|
|
29801
|
+
else {
|
|
29802
|
+
//mesh = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({ specular: ic.frac, shininess: ic.shininess, emissive: ic.emissive, vertexColors: THREE.FaceColors, side: THREE.DoubleSide }));
|
|
29803
|
+
mesh = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({ specular: ic.frac, shininess: ic.shininess, emissive: ic.emissive, vertexColors: true, side: THREE.DoubleSide }));
|
|
29804
|
+
|
|
29805
|
+
if(ic.mdl) ic.mdl.add(mesh);
|
|
29806
|
+
}
|
|
29807
|
+
|
|
29808
|
+
if(bHighlight === 1 || bHighlight === 2) {
|
|
29809
|
+
ic.prevHighlightObjects.push(mesh);
|
|
29810
|
+
}
|
|
29811
|
+
else {
|
|
29812
|
+
ic.objects.push(mesh);
|
|
29813
|
+
}
|
|
29814
|
+
}
|
|
29815
|
+
|
|
29816
|
+
getRadius(radius, atom) { let ic = this.icn3d; ic.icn3dui;
|
|
29817
|
+
let radiusFinal = radius;
|
|
29818
|
+
if(radius) {
|
|
29819
|
+
radiusFinal = radius;
|
|
29820
|
+
}
|
|
29821
|
+
else {
|
|
29822
|
+
if(atom.b > 0 && atom.b <= 100) {
|
|
29823
|
+
radiusFinal = atom.b * 0.01;
|
|
29824
|
+
}
|
|
29825
|
+
else if(atom.b > 100) {
|
|
29826
|
+
radiusFinal = 100 * 0.01;
|
|
29827
|
+
}
|
|
29828
|
+
else {
|
|
29829
|
+
radiusFinal = ic.coilWidth;
|
|
29830
|
+
}
|
|
29831
|
+
}
|
|
29832
|
+
|
|
29833
|
+
return radiusFinal;
|
|
29834
|
+
}
|
|
29835
|
+
}
|
|
29836
|
+
|
|
29837
|
+
/**
|
|
29838
|
+
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
29839
|
+
*/
|
|
29840
|
+
|
|
29841
|
+
class Strand {
|
|
29842
|
+
constructor(icn3d) {
|
|
29843
|
+
this.icn3d = icn3d;
|
|
29844
|
+
}
|
|
29845
|
+
|
|
29846
|
+
// significantly modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
29847
|
+
//Create the style of ribbon or strand for "atoms". "num" means how many lines define the curve.
|
|
29848
|
+
//"num" is 2 for ribbon and 6 for strand. "div" means how many pnts are used to smooth the curve.
|
|
29849
|
+
//It's typically 5. "coilWidth" is the width of curve for coil. "helixSheetWidth" is the width of curve for helix or sheet.
|
|
29850
|
+
//"doNotSmoothen" is a flag to smooth the curve or not. "thickness" is the thickness of the curve.
|
|
29851
|
+
//"bHighlight" is an option to draw the highlight for these atoms. The highlight could be outlines
|
|
29852
|
+
//with bHighlight=1 and 3D objects with bHighlight=2.
|
|
29853
|
+
createStrand(atoms, num, div, fill, coilWidth, helixSheetWidth, doNotSmoothen, thickness, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
|
|
29854
|
+
if(me.bNode) return;
|
|
29855
|
+
|
|
29856
|
+
let bRibbon = fill ? true: false;
|
|
29857
|
+
|
|
29858
|
+
// when highlight, the input atoms may only include part of sheet or helix
|
|
29859
|
+
// include the whole sheet or helix when highlighting
|
|
29860
|
+
let atomsAdjust = {};
|
|
29861
|
+
|
|
29862
|
+
//if( (bHighlight === 1 || bHighlight === 2) && !ic.bAllAtoms) {
|
|
29863
|
+
//if( !ic.bAllAtoms) {
|
|
29864
|
+
if( Object.keys(atoms).length < Object.keys(ic.atoms).length) {
|
|
29865
|
+
atomsAdjust = this.getSSExpandedAtoms(atoms);
|
|
29866
|
+
}
|
|
29867
|
+
else {
|
|
29868
|
+
atomsAdjust = atoms;
|
|
29869
|
+
}
|
|
29870
|
+
|
|
29871
|
+
if(bHighlight === 2) {
|
|
29872
|
+
if(fill) {
|
|
29873
|
+
fill = false;
|
|
29874
|
+
num = null;
|
|
29875
|
+
div = null;
|
|
29876
|
+
coilWidth = null;
|
|
29877
|
+
helixSheetWidth = null;
|
|
29878
|
+
thickness = undefined;
|
|
29879
|
+
}
|
|
29880
|
+
else {
|
|
29881
|
+
fill = true;
|
|
29882
|
+
num = 2;
|
|
29883
|
+
div = undefined;
|
|
29884
|
+
coilWidth = undefined;
|
|
29885
|
+
helixSheetWidth = undefined;
|
|
29886
|
+
thickness = ic.ribbonthickness;
|
|
29887
|
+
}
|
|
29888
|
+
}
|
|
29889
|
+
|
|
29890
|
+
num = num || ic.strandDIV;
|
|
29891
|
+
div = div || ic.axisDIV;
|
|
29892
|
+
coilWidth = coilWidth || ic.coilWidth;
|
|
29893
|
+
doNotSmoothen = doNotSmoothen || false;
|
|
29894
|
+
helixSheetWidth = helixSheetWidth || ic.helixSheetWidth;
|
|
29895
|
+
let pnts = {}; for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
29896
|
+
let pntsCA = [];
|
|
29897
|
+
let prevCOArray = [];
|
|
29898
|
+
let bShowArray = [];
|
|
29899
|
+
let calphaIdArray = []; // used to store one of the final positions drawn in 3D
|
|
29900
|
+
let colors = [];
|
|
29901
|
+
let currentChain, currentCA = null, currentO = null, currentColor = null, prevCoorCA = null, prevCoorO = null, prevColor = null;
|
|
29902
|
+
let prevCO = null, ss = null, ssend = false, atomid = null, prevAtomid = null, prevResi = null, calphaid = null, prevCalphaid = null;
|
|
29903
|
+
let strandWidth, bSheetSegment = false, bHelixSegment = false;
|
|
29904
|
+
let atom, tubeAtoms = {};
|
|
29905
|
+
|
|
29906
|
+
// test the first 30 atoms to see whether only C-alpha is available
|
|
29907
|
+
ic.bCalphaOnly = me.utilsCls.isCalphaPhosOnly(atomsAdjust); //, 'CA');
|
|
29908
|
+
|
|
29909
|
+
// when highlight, draw whole beta sheet and use bShowArray to show the highlight part
|
|
29910
|
+
let residueHash = {};
|
|
29911
|
+
for(let i in atomsAdjust) {
|
|
29912
|
+
let atom = atomsAdjust[i];
|
|
29913
|
+
|
|
29914
|
+
let residueid = atom.structure + '_' + atom.chain + '_' + atom.resi;
|
|
29915
|
+
residueHash[residueid] = 1;
|
|
29916
|
+
}
|
|
29917
|
+
let totalResidueCount = Object.keys(residueHash).length;
|
|
29918
|
+
|
|
29919
|
+
let drawnResidueCount = 0;
|
|
29920
|
+
|
|
29921
|
+
let bFullAtom = (Object.keys(ic.hAtoms).length == Object.keys(ic.atoms).length) ? true : false;
|
|
29922
|
+
|
|
29923
|
+
let caArray = []; // record all C-alpha atoms to predict the helix
|
|
29924
|
+
|
|
29925
|
+
for (let i in atomsAdjust) {
|
|
29926
|
+
atom = atomsAdjust[i];
|
|
29927
|
+
if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
|
|
29928
|
+
// "CA" has to appear before "O"
|
|
29929
|
+
|
|
29930
|
+
if (atom.name === 'CA') {
|
|
29931
|
+
if ( atoms.hasOwnProperty(i) && ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) ) {
|
|
29932
|
+
tubeAtoms[i] = atom;
|
|
29933
|
+
}
|
|
29934
|
+
|
|
29935
|
+
currentCA = atom.coord;
|
|
29936
|
+
currentColor = atom.color;
|
|
29937
|
+
calphaid = atom.serial;
|
|
29938
|
+
|
|
29939
|
+
caArray.push(atom.serial);
|
|
29940
|
+
}
|
|
29941
|
+
|
|
29942
|
+
if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA')) {
|
|
29943
|
+
if(currentCA === null || currentCA === undefined) {
|
|
29944
|
+
currentCA = atom.coord;
|
|
29945
|
+
currentColor = atom.color;
|
|
29946
|
+
calphaid = atom.serial;
|
|
29947
|
+
}
|
|
29948
|
+
|
|
29949
|
+
if(atom.name === 'O') {
|
|
29950
|
+
currentO = atom.coord;
|
|
29951
|
+
}
|
|
29952
|
+
// smoothen each coil, helix and sheet separately. The joint residue has to be included both in the previous and next segment
|
|
29953
|
+
let bSameChain = true;
|
|
29954
|
+
// if (currentChain !== atom.chain || currentResi + 1 !== atom.resi) {
|
|
29955
|
+
if (currentChain !== atom.chain) {
|
|
29956
|
+
bSameChain = false;
|
|
29957
|
+
}
|
|
29958
|
+
|
|
29959
|
+
if(atom.ssend && atom.ss === 'sheet') {
|
|
29960
|
+
bSheetSegment = true;
|
|
29961
|
+
}
|
|
29962
|
+
else if(atom.ssend && atom.ss === 'helix') {
|
|
29963
|
+
bHelixSegment = true;
|
|
29964
|
+
}
|
|
29965
|
+
|
|
29966
|
+
// assign the previous residue
|
|
29967
|
+
if(prevCoorO) {
|
|
29968
|
+
if(bHighlight === 1 || bHighlight === 2) {
|
|
29969
|
+
colors.push(ic.hColor);
|
|
29970
|
+
}
|
|
29971
|
+
else {
|
|
29972
|
+
colors.push(prevColor);
|
|
29973
|
+
}
|
|
29974
|
+
|
|
29975
|
+
if(ss !== 'coil' && atom.ss === 'coil') {
|
|
29976
|
+
strandWidth = coilWidth;
|
|
29977
|
+
}
|
|
29978
|
+
else if(ssend && atom.ssbegin) { // a transition between two ss
|
|
29979
|
+
strandWidth = coilWidth;
|
|
29980
|
+
}
|
|
29981
|
+
else {
|
|
29982
|
+
strandWidth = (ss === 'coil') ? coilWidth : helixSheetWidth;
|
|
29983
|
+
}
|
|
29984
|
+
|
|
29985
|
+
let O, oldCA, resSpan = 4;
|
|
29986
|
+
if(atom.name === 'O') {
|
|
29987
|
+
O = prevCoorO.clone();
|
|
29988
|
+
if(prevCoorCA !== null && prevCoorCA !== undefined) {
|
|
29989
|
+
O.sub(prevCoorCA);
|
|
29990
|
+
}
|
|
29991
|
+
else {
|
|
29992
|
+
prevCoorCA = prevCoorO.clone();
|
|
29993
|
+
if(caArray.length > resSpan + 1) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
29994
|
+
O = prevCoorCA.clone();
|
|
29995
|
+
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan - 1]].coord.clone();
|
|
29996
|
+
//O.sub(oldCA);
|
|
29997
|
+
oldCA.sub(O);
|
|
29998
|
+
}
|
|
29999
|
+
else {
|
|
30000
|
+
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
30001
|
+
}
|
|
30002
|
+
}
|
|
30003
|
+
}
|
|
30004
|
+
else if(ic.bCalphaOnly && atom.name === 'CA') {
|
|
30005
|
+
if(caArray.length > resSpan + 1) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
30006
|
+
O = prevCoorCA.clone();
|
|
30007
|
+
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan - 1]].coord.clone();
|
|
30008
|
+
//O.sub(oldCA);
|
|
30009
|
+
oldCA.sub(O);
|
|
30010
|
+
}
|
|
30011
|
+
else {
|
|
30012
|
+
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
30013
|
+
}
|
|
30014
|
+
}
|
|
30015
|
+
|
|
30016
|
+
O.normalize(); // can be omitted for performance
|
|
30017
|
+
O.multiplyScalar(strandWidth);
|
|
30018
|
+
if (prevCO !== null && O.dot(prevCO) < 0) O.negate();
|
|
30019
|
+
prevCO = O;
|
|
30020
|
+
|
|
30021
|
+
for (let j = 0, numM1Inv2 = 2 / (num - 1); j < num; ++j) {
|
|
30022
|
+
let delta = -1 + numM1Inv2 * j;
|
|
30023
|
+
let v = new THREE.Vector3(prevCoorCA.x + prevCO.x * delta, prevCoorCA.y + prevCO.y * delta, prevCoorCA.z + prevCO.z * delta);
|
|
30024
|
+
if (!doNotSmoothen && ss === 'sheet') v.smoothen = true;
|
|
30025
|
+
pnts[j].push(v);
|
|
30026
|
+
}
|
|
30027
|
+
|
|
30028
|
+
pntsCA.push(prevCoorCA);
|
|
30029
|
+
prevCOArray.push(prevCO);
|
|
30030
|
+
|
|
30031
|
+
if(atoms.hasOwnProperty(prevAtomid)) {
|
|
30032
|
+
bShowArray.push(prevResi);
|
|
30033
|
+
calphaIdArray.push(prevCalphaid);
|
|
30034
|
+
}
|
|
30035
|
+
else {
|
|
30036
|
+
bShowArray.push(0);
|
|
30037
|
+
calphaIdArray.push(0);
|
|
30038
|
+
}
|
|
30039
|
+
|
|
30040
|
+
++drawnResidueCount;
|
|
30041
|
+
}
|
|
30042
|
+
|
|
30043
|
+
let maxDist = 6.0;
|
|
30044
|
+
let bBrokenSs = (prevCoorCA && Math.abs(currentCA.x - prevCoorCA.x) > maxDist) || (prevCoorCA && Math.abs(currentCA.y - prevCoorCA.y) > maxDist) || (prevCoorCA && Math.abs(currentCA.z - prevCoorCA.z) > maxDist);
|
|
30045
|
+
// The following code didn't work to select one residue
|
|
30046
|
+
// let bBrokenSs = !atoms.hasOwnProperty(atom.serial) || (prevCoorCA && Math.abs(currentCA.x - prevCoorCA.x) > maxDist) || (prevCoorCA && Math.abs(currentCA.y - prevCoorCA.y) > maxDist) || (prevCoorCA && Math.abs(currentCA.z - prevCoorCA.z) > maxDist);
|
|
30047
|
+
|
|
30048
|
+
// if(bBrokenSs && atom.ss === 'sheet') {
|
|
30049
|
+
// bSheetSegment = true;
|
|
30050
|
+
// }
|
|
30051
|
+
// else if(bBrokenSs && atom.ss === 'helix') {
|
|
30052
|
+
// bHelixSegment = true;
|
|
30053
|
+
// }
|
|
30054
|
+
|
|
30055
|
+
if ((atom.ssbegin || atom.ssend || (drawnResidueCount === totalResidueCount - 1) || bBrokenSs) && pnts[0].length > 0 && bSameChain) {
|
|
30056
|
+
let atomName = 'CA';
|
|
30057
|
+
|
|
30058
|
+
let prevone = [], nexttwo = [];
|
|
30059
|
+
|
|
30060
|
+
if(isNaN(ic.atoms[prevAtomid].resi)) {
|
|
30061
|
+
prevone = [];
|
|
30062
|
+
}
|
|
30063
|
+
else {
|
|
30064
|
+
let prevoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) - 1).toString();
|
|
30065
|
+
let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
|
|
30066
|
+
prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
|
|
30067
|
+
}
|
|
30068
|
+
|
|
30069
|
+
if(!isNaN(ic.atoms[prevAtomid].resi)) {
|
|
30070
|
+
let nextoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) + 1).toString();
|
|
30071
|
+
let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
|
|
30072
|
+
if(nextoneCoord !== undefined) {
|
|
30073
|
+
nexttwo.push(nextoneCoord);
|
|
30074
|
+
}
|
|
30075
|
+
|
|
30076
|
+
let nexttwoResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) + 2).toString();
|
|
30077
|
+
let nexttwoCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nexttwoResid, atomName);
|
|
30078
|
+
if(nexttwoCoord !== undefined) {
|
|
30079
|
+
nexttwo.push(nexttwoCoord);
|
|
30080
|
+
}
|
|
30081
|
+
}
|
|
30082
|
+
|
|
30083
|
+
if(!bBrokenSs) { // include the current residue
|
|
30084
|
+
// assign the current joint residue to the previous segment
|
|
30085
|
+
if(bHighlight === 1 || bHighlight === 2) {
|
|
30086
|
+
colors.push(ic.hColor);
|
|
30087
|
+
}
|
|
30088
|
+
else {
|
|
30089
|
+
//colors.push(atom.color);
|
|
30090
|
+
colors.push(prevColor);
|
|
30091
|
+
}
|
|
30092
|
+
|
|
30093
|
+
if(atom.ssend && atom.ss === 'sheet') { // current residue is the end of ss and is the end of arrow
|
|
30094
|
+
strandWidth = 0; // make the arrow end sharp
|
|
30095
|
+
}
|
|
30096
|
+
else if(ss === 'coil' && atom.ssbegin) {
|
|
30097
|
+
strandWidth = coilWidth;
|
|
30098
|
+
}
|
|
30099
|
+
else if(ssend && atom.ssbegin) { // current residue is the start of ss and the previous residue is the end of ss, then use coil
|
|
30100
|
+
strandWidth = coilWidth;
|
|
30101
|
+
}
|
|
30102
|
+
else { // use the ss from the previous residue
|
|
30103
|
+
strandWidth = (atom.ss === 'coil') ? coilWidth : helixSheetWidth;
|
|
30104
|
+
}
|
|
30105
|
+
|
|
30106
|
+
let O, oldCA, resSpan = 4;
|
|
30107
|
+
if(atom.name === 'O') {
|
|
30108
|
+
O = currentO.clone();
|
|
30109
|
+
O.sub(currentCA);
|
|
30110
|
+
}
|
|
30111
|
+
else if(ic.bCalphaOnly && atom.name === 'CA') {
|
|
30112
|
+
if(caArray.length > resSpan) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
30113
|
+
O = currentCA.clone();
|
|
30114
|
+
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan]].coord.clone();
|
|
30115
|
+
//O.sub(oldCA);
|
|
30116
|
+
oldCA.sub(O);
|
|
30117
|
+
}
|
|
30118
|
+
else {
|
|
30119
|
+
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
30120
|
+
}
|
|
30121
|
+
}
|
|
30122
|
+
|
|
30123
|
+
O.normalize(); // can be omitted for performance
|
|
30124
|
+
O.multiplyScalar(strandWidth);
|
|
30125
|
+
if (prevCO !== null && O.dot(prevCO) < 0) O.negate();
|
|
30126
|
+
prevCO = O;
|
|
30127
|
+
|
|
30128
|
+
for (let j = 0, numM1Inv2 = 2 / (num - 1); j < num; ++j) {
|
|
30129
|
+
let delta = -1 + numM1Inv2 * j;
|
|
30130
|
+
let v = new THREE.Vector3(currentCA.x + prevCO.x * delta, currentCA.y + prevCO.y * delta, currentCA.z + prevCO.z * delta);
|
|
30131
|
+
if (!doNotSmoothen && ss === 'sheet') v.smoothen = true;
|
|
30132
|
+
pnts[j].push(v);
|
|
30133
|
+
}
|
|
30134
|
+
|
|
30135
|
+
atomid = atom.serial;
|
|
30136
|
+
|
|
30137
|
+
pntsCA.push(currentCA);
|
|
30138
|
+
prevCOArray.push(prevCO);
|
|
30139
|
+
|
|
30140
|
+
// when a coil connects to a sheet and the last residue of coild is highlighted, the first sheet residue is set as atom.highlightStyle. This residue should not be shown.
|
|
30141
|
+
//if(atoms.hasOwnProperty(atomid) && (bHighlight === 1 && !atom.notshow) ) {
|
|
30142
|
+
if(atoms.hasOwnProperty(atomid)) {
|
|
30143
|
+
bShowArray.push(atom.resi);
|
|
30144
|
+
calphaIdArray.push(calphaid);
|
|
30145
|
+
}
|
|
30146
|
+
else {
|
|
30147
|
+
bShowArray.push(0);
|
|
30148
|
+
calphaIdArray.push(0);
|
|
30149
|
+
}
|
|
30150
|
+
}
|
|
30151
|
+
|
|
30152
|
+
// draw the current segment
|
|
30153
|
+
for (let j = 0; !fill && j < num; ++j) {
|
|
30154
|
+
if(bSheetSegment) {
|
|
30155
|
+
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
30156
|
+
}
|
|
30157
|
+
else if(bHelixSegment) {
|
|
30158
|
+
if(bFullAtom) {
|
|
30159
|
+
ic.curveCls.createCurveSub(pnts[j], 1, colors, div, bHighlight, bRibbon, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo);
|
|
30160
|
+
}
|
|
30161
|
+
else {
|
|
30162
|
+
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
30163
|
+
}
|
|
30164
|
+
}
|
|
30165
|
+
}
|
|
30166
|
+
if (fill) {
|
|
30167
|
+
if(bSheetSegment) {
|
|
30168
|
+
let start = 0, end = num - 1;
|
|
30169
|
+
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
30170
|
+
}
|
|
30171
|
+
else if(bHelixSegment) {
|
|
30172
|
+
if(bFullAtom) {
|
|
30173
|
+
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
30174
|
+
}
|
|
30175
|
+
else {
|
|
30176
|
+
let start = 0, end = num - 1;
|
|
30177
|
+
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
30178
|
+
}
|
|
30179
|
+
}
|
|
30180
|
+
else {
|
|
30181
|
+
if(bHighlight === 2) { // draw coils only when highlighted. if not highlighted, coils will be drawn as tubes separately
|
|
30182
|
+
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
30183
|
+
}
|
|
30184
|
+
}
|
|
30185
|
+
}
|
|
30186
|
+
for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
30187
|
+
|
|
30188
|
+
colors = [];
|
|
30189
|
+
pntsCA = [];
|
|
30190
|
+
prevCOArray = [];
|
|
30191
|
+
bShowArray = [];
|
|
30192
|
+
calphaIdArray = [];
|
|
30193
|
+
bSheetSegment = false;
|
|
30194
|
+
bHelixSegment = false;
|
|
30195
|
+
} // end if (atom.ssbegin || atom.ssend)
|
|
30196
|
+
|
|
30197
|
+
// end of a chain
|
|
30198
|
+
// if ((currentChain !== atom.chain || currentResi + 1 !== atom.resi) && pnts[0].length > 0) {
|
|
30199
|
+
if ((currentChain !== atom.chain) && pnts[0].length > 0) {
|
|
29927
30200
|
|
|
29928
|
-
|
|
29929
|
-
radii.push(radiusFinal);
|
|
30201
|
+
let atomName = 'CA';
|
|
29930
30202
|
|
|
29931
|
-
|
|
29932
|
-
|
|
29933
|
-
|
|
30203
|
+
let prevone = [], nexttwo = [];
|
|
30204
|
+
if(isNaN(ic.atoms[prevAtomid].resi)) {
|
|
30205
|
+
prevone = [];
|
|
30206
|
+
}
|
|
30207
|
+
else {
|
|
30208
|
+
let prevoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) - 1).toString();
|
|
30209
|
+
ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
|
|
30210
|
+
}
|
|
29934
30211
|
|
|
29935
|
-
|
|
29936
|
-
|
|
30212
|
+
for (let j = 0; !fill && j < num; ++j) {
|
|
30213
|
+
if(bSheetSegment) {
|
|
30214
|
+
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
30215
|
+
}
|
|
30216
|
+
else if(bHelixSegment) {
|
|
30217
|
+
if(bFullAtom) {
|
|
30218
|
+
ic.curveCls.createCurveSub(pnts[j], 1, colors, div, bHighlight, bRibbon, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo);
|
|
30219
|
+
}
|
|
30220
|
+
else {
|
|
30221
|
+
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
30222
|
+
}
|
|
30223
|
+
}
|
|
30224
|
+
}
|
|
30225
|
+
if (fill) {
|
|
30226
|
+
if(bSheetSegment) {
|
|
30227
|
+
let start = 0, end = num - 1;
|
|
30228
|
+
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
30229
|
+
}
|
|
30230
|
+
else if(bHelixSegment) {
|
|
30231
|
+
if(bFullAtom) {
|
|
30232
|
+
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
30233
|
+
}
|
|
30234
|
+
else {
|
|
30235
|
+
let start = 0, end = num - 1;
|
|
30236
|
+
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
30237
|
+
}
|
|
30238
|
+
}
|
|
30239
|
+
}
|
|
29937
30240
|
|
|
29938
|
-
|
|
29939
|
-
|
|
29940
|
-
|
|
30241
|
+
for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
30242
|
+
colors = [];
|
|
30243
|
+
pntsCA = [];
|
|
30244
|
+
prevCOArray = [];
|
|
30245
|
+
bShowArray = [];
|
|
30246
|
+
calphaIdArray = [];
|
|
30247
|
+
bSheetSegment = false;
|
|
30248
|
+
bHelixSegment = false;
|
|
29941
30249
|
}
|
|
29942
30250
|
|
|
29943
|
-
|
|
30251
|
+
currentChain = atom.chain;
|
|
30252
|
+
ss = atom.ss;
|
|
30253
|
+
ssend = atom.ssend;
|
|
30254
|
+
prevAtomid = atom.serial;
|
|
30255
|
+
prevResi = atom.resi;
|
|
29944
30256
|
|
|
29945
|
-
|
|
29946
|
-
}
|
|
29947
|
-
}
|
|
30257
|
+
prevCalphaid = calphaid;
|
|
29948
30258
|
|
|
29949
|
-
|
|
29950
|
-
|
|
29951
|
-
|
|
30259
|
+
// only update when atom.name === 'O'
|
|
30260
|
+
prevCoorCA = currentCA;
|
|
30261
|
+
prevCoorO = atom.coord;
|
|
30262
|
+
prevColor = currentColor;
|
|
30263
|
+
} // end if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA') ) {
|
|
30264
|
+
} // end if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
|
|
30265
|
+
} // end for
|
|
29952
30266
|
|
|
29953
|
-
|
|
29954
|
-
let pnts = pnts_colors_radii_prevone_nexttwo[i].pnts;
|
|
29955
|
-
let colors = pnts_colors_radii_prevone_nexttwo[i].colors;
|
|
29956
|
-
let radii = pnts_colors_radii_prevone_nexttwo[i].radii;
|
|
29957
|
-
let prevone = []; // = pnts_colors_radii_prevone_nexttwo[i].prevone;
|
|
29958
|
-
let nexttwo = []; // = pnts_colors_radii_prevone_nexttwo[i].nexttwo;
|
|
30267
|
+
caArray = [];
|
|
29959
30268
|
|
|
29960
|
-
|
|
29961
|
-
}
|
|
30269
|
+
ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight);
|
|
29962
30270
|
|
|
29963
|
-
|
|
30271
|
+
tubeAtoms = {};
|
|
30272
|
+
pnts = {};
|
|
29964
30273
|
}
|
|
29965
|
-
*/
|
|
29966
|
-
|
|
29967
|
-
getCustomtubesize(resid) { let ic = this.icn3d; ic.icn3dui;
|
|
29968
|
-
let pos = resid.lastIndexOf('_');
|
|
29969
|
-
let resi = resid.substr(pos + 1);
|
|
29970
|
-
let chainid = resid.substr(0, pos);
|
|
29971
|
-
|
|
29972
|
-
let radiusFinal = (ic.queryresi2score[chainid] && ic.queryresi2score[chainid].hasOwnProperty(resi)) ? ic.queryresi2score[chainid][resi] * 0.01 : ic.coilWidth;
|
|
29973
|
-
|
|
29974
|
-
return radiusFinal;
|
|
29975
|
-
};
|
|
29976
|
-
|
|
29977
|
-
// modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
29978
|
-
createTubeSub(_pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
|
|
29979
|
-
if(me.bNode) return;
|
|
29980
|
-
|
|
29981
|
-
if (_pnts.length < 2) return;
|
|
29982
30274
|
|
|
29983
|
-
|
|
29984
|
-
let
|
|
29985
|
-
|
|
29986
|
-
let
|
|
29987
|
-
let verticeArray = [], colorArray = [],indexArray = [], color;
|
|
29988
|
-
let offset = 0, offset2 = 0, offset3 = 0;
|
|
30275
|
+
getSSExpandedAtoms(atoms, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
|
|
30276
|
+
let currChain, currResi, currAtom, prevChain, prevResi, prevAtom;
|
|
30277
|
+
let firstAtom, lastAtom;
|
|
30278
|
+
let index = 0, length = Object.keys(atoms).length;
|
|
29989
30279
|
|
|
29990
|
-
let
|
|
30280
|
+
let atomsAdjust = me.hashUtilsCls.cloneHash(atoms);
|
|
30281
|
+
for(let serial in atoms) {
|
|
30282
|
+
currChain = atoms[serial].structure + '_' + atoms[serial].chain;
|
|
30283
|
+
currResi = atoms[serial].resi; //parseInt(atoms[serial].resi);
|
|
30284
|
+
currAtom = atoms[serial];
|
|
29991
30285
|
|
|
29992
|
-
|
|
29993
|
-
colors = pnts_clrs[2];
|
|
30286
|
+
if(prevChain === undefined) firstAtom = atoms[serial];
|
|
29994
30287
|
|
|
29995
|
-
|
|
29996
|
-
|
|
29997
|
-
|
|
30288
|
+
if( (currChain !== prevChain && prevChain !== undefined)
|
|
30289
|
+
|| (currResi !== prevResi && currResi !== parseInt(prevResi) + 1 && prevResi !== undefined) || index === length - 1) {
|
|
30290
|
+
if( (currChain !== prevChain && prevChain !== undefined)
|
|
30291
|
+
|| (currResi !== prevResi && currResi !== parseInt(prevResi) + 1 && prevResi !== undefined) ) {
|
|
30292
|
+
lastAtom = prevAtom;
|
|
30293
|
+
}
|
|
30294
|
+
else if(index === length - 1) {
|
|
30295
|
+
lastAtom = currAtom;
|
|
30296
|
+
}
|
|
29998
30297
|
|
|
29999
|
-
|
|
30000
|
-
|
|
30001
|
-
|
|
30298
|
+
// fill the beginning
|
|
30299
|
+
let beginResi = firstAtom.resi;
|
|
30300
|
+
if(!isNaN(firstAtom.resi) && firstAtom.ss !== 'coil' && !(firstAtom.ssbegin) ) {
|
|
30301
|
+
for(let i = parseInt(firstAtom.resi) - 1; i > 0; --i) {
|
|
30302
|
+
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + i;
|
|
30303
|
+
if(!ic.residues.hasOwnProperty(residueid)) break;
|
|
30002
30304
|
|
|
30003
|
-
|
|
30004
|
-
r = radii[0];
|
|
30005
|
-
if(r > 0) constRadiius = r;
|
|
30006
|
-
}
|
|
30007
|
-
else {
|
|
30008
|
-
if (idx % 1 === 0) {
|
|
30009
|
-
r = radii[idx];
|
|
30010
|
-
if(r > 0) constRadiius = r;
|
|
30011
|
-
}
|
|
30012
|
-
else {
|
|
30013
|
-
let floored = Math.floor(idx);
|
|
30014
|
-
let tmp = idx - floored;
|
|
30015
|
-
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
30016
|
-
// r = radii[floored] * tmp + radii[floored + 1] * (1 - tmp);
|
|
30017
|
-
r = radii[floored] * (1 - tmp) + radii[floored + 1] * tmp;
|
|
30305
|
+
let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[residueid]);
|
|
30018
30306
|
|
|
30019
|
-
|
|
30020
|
-
|
|
30021
|
-
|
|
30022
|
-
if(r < thresholdRatio * constRadiius) {
|
|
30023
|
-
r = 0;
|
|
30024
|
-
}
|
|
30025
|
-
// else if(r < constRadiius) {
|
|
30026
|
-
// r *= 0.5; // use small radius for the connection between coild and sheets/helices
|
|
30027
|
-
// }
|
|
30307
|
+
if(atom.ss === firstAtom.ss && atom.ssbegin) {
|
|
30308
|
+
beginResi = atom.resi;
|
|
30309
|
+
break;
|
|
30028
30310
|
}
|
|
30029
30311
|
}
|
|
30030
|
-
|
|
30031
|
-
|
|
30032
|
-
|
|
30033
|
-
|
|
30034
|
-
|
|
30035
|
-
axis2 = delta.clone().cross(axis1).normalize().multiplyScalar(r);
|
|
30036
|
-
// let dir = 1, offset = 0;
|
|
30037
|
-
if (prevAxis1.dot(axis1) < 0) {
|
|
30038
|
-
axis1.negate(); axis2.negate(); //dir = -1;//offset = 2 * Math.PI / axisDiv;
|
|
30312
|
+
|
|
30313
|
+
for(let i = beginResi; i < firstAtom.resi; ++i) {
|
|
30314
|
+
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + i;
|
|
30315
|
+
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
30316
|
+
ic.atoms));
|
|
30039
30317
|
}
|
|
30040
|
-
prevAxis1 = axis1; prevAxis2 = axis2;
|
|
30041
|
-
} else {
|
|
30042
|
-
axis1 = prevAxis1; axis2 = prevAxis2;
|
|
30043
30318
|
}
|
|
30044
|
-
for (let j = 0; j < circleDiv; ++j) {
|
|
30045
|
-
let angle = 2 * Math.PI * circleDivInv * j; //* dir + offset;
|
|
30046
|
-
let point = pnts[i].clone().add(axis1.clone().multiplyScalar(Math.cos(angle))).add(axis2.clone().multiplyScalar(Math.sin(angle)));
|
|
30047
|
-
verticeArray[offset++] = point.x;
|
|
30048
|
-
verticeArray[offset++] = point.y;
|
|
30049
|
-
verticeArray[offset++] = point.z;
|
|
30050
30319
|
|
|
30051
|
-
|
|
30052
|
-
|
|
30053
|
-
|
|
30054
|
-
|
|
30320
|
+
// add one extra residue for coils between strands/helix
|
|
30321
|
+
if(!isNaN(firstAtom.resi) && ic.pk === 3 && bHighlight === 1 && firstAtom.ss === 'coil') {
|
|
30322
|
+
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
|
|
30323
|
+
if(ic.residues.hasOwnProperty(residueid)) {
|
|
30324
|
+
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
30325
|
+
ic.atoms));
|
|
30326
|
+
atoms = me.hashUtilsCls.unionHash(atoms, me.hashUtilsCls.hash2Atoms(ic.residues[residueid], ic.atoms));
|
|
30327
|
+
}
|
|
30055
30328
|
}
|
|
30056
|
-
}
|
|
30057
|
-
let offsetTmp = 0, nComp = 3;
|
|
30058
|
-
for (let i = 0, lim = pnts.length - 1; i < lim; ++i) {
|
|
30059
|
-
let reg = 0;
|
|
30060
|
-
//var r1 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv]).lengthSq();
|
|
30061
|
-
//var r2 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv + 1]).lengthSq();
|
|
30062
|
-
let pos = offsetTmp * nComp;
|
|
30063
|
-
let point1 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
30064
|
-
pos = (offsetTmp + circleDiv) * nComp;
|
|
30065
|
-
let point2 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
30066
|
-
pos = (offsetTmp + circleDiv + 1) * nComp;
|
|
30067
|
-
let point3 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
30068
30329
|
|
|
30069
|
-
|
|
30070
|
-
let
|
|
30071
|
-
|
|
30072
|
-
//geo.faces.push(new THREE.Face3(offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv, undefined, c));
|
|
30073
|
-
//geo.faces.push(new THREE.Face3(offset + (j + 1) % circleDiv, offset + (j + reg) % circleDiv + circleDiv, offset + (j + reg + 1) % circleDiv + circleDiv, undefined, c));
|
|
30074
|
-
//indexArray = indexArray.concat([offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv]);
|
|
30075
|
-
indexArray[offset3++] = offsetTmp + j;
|
|
30076
|
-
indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
|
|
30077
|
-
indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
|
|
30330
|
+
// fill the end
|
|
30331
|
+
let endResi = lastAtom.resi;
|
|
30332
|
+
// when a coil connects to a sheet and the last residue of coil is highlighted, the first sheet residue is set as atom.notshow. This residue should not be shown.
|
|
30078
30333
|
|
|
30079
|
-
|
|
30080
|
-
indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
|
|
30081
|
-
indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
|
|
30082
|
-
indexArray[offset3++] = offsetTmp + (j + reg + 1) % circleDiv + circleDiv;
|
|
30083
|
-
}
|
|
30084
|
-
offsetTmp += circleDiv;
|
|
30085
|
-
}
|
|
30334
|
+
if(lastAtom.ss !== undefined && lastAtom.ss !== 'coil' && !(lastAtom.ssend) && !(lastAtom.notshow)) {
|
|
30086
30335
|
|
|
30087
|
-
|
|
30088
|
-
|
|
30336
|
+
let endChainResi = ic.firstAtomObjCls.getLastAtomObj(ic.chains[lastAtom.structure + '_' + lastAtom.chain]).resi;
|
|
30337
|
+
for(let i = parseInt(lastAtom.resi) + 1; i <= parseInt(endChainResi); ++i) {
|
|
30338
|
+
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + i;
|
|
30339
|
+
if(!ic.residues.hasOwnProperty(residueid)) break;
|
|
30089
30340
|
|
|
30090
|
-
|
|
30091
|
-
//geo.setIndex(indexArray);
|
|
30341
|
+
let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[residueid]);
|
|
30092
30342
|
|
|
30093
|
-
|
|
30094
|
-
|
|
30095
|
-
|
|
30343
|
+
if(atom.ss === lastAtom.ss && atom.ssend) {
|
|
30344
|
+
endResi = atom.resi;
|
|
30345
|
+
break;
|
|
30346
|
+
}
|
|
30347
|
+
}
|
|
30096
30348
|
|
|
30097
|
-
|
|
30098
|
-
|
|
30099
|
-
|
|
30100
|
-
|
|
30349
|
+
for(let i = parseInt(lastAtom.resi) + 1; i <= parseInt(endResi); ++i) {
|
|
30350
|
+
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + i;
|
|
30351
|
+
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
30352
|
+
ic.atoms));
|
|
30353
|
+
}
|
|
30354
|
+
}
|
|
30101
30355
|
|
|
30102
|
-
|
|
30103
|
-
|
|
30104
|
-
|
|
30105
|
-
|
|
30106
|
-
|
|
30107
|
-
|
|
30108
|
-
|
|
30109
|
-
|
|
30110
|
-
|
|
30111
|
-
//mesh = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({ specular: ic.frac, shininess: ic.shininess, emissive: ic.emissive, vertexColors: THREE.FaceColors, side: THREE.DoubleSide }));
|
|
30112
|
-
mesh = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({ specular: ic.frac, shininess: ic.shininess, emissive: ic.emissive, vertexColors: true, side: THREE.DoubleSide }));
|
|
30356
|
+
// add one extra residue for coils between strands/helix
|
|
30357
|
+
if(ic.pk === 3 && bHighlight === 1 && lastAtom.ss === 'coil') {
|
|
30358
|
+
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + (parseInt(lastAtom.resi) + 1).toString();
|
|
30359
|
+
if(ic.residues.hasOwnProperty(residueid)) {
|
|
30360
|
+
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
30361
|
+
ic.atoms));
|
|
30362
|
+
atoms = me.hashUtilsCls.unionHash(atoms, me.hashUtilsCls.hash2Atoms(ic.residues[residueid], ic.atoms));
|
|
30363
|
+
}
|
|
30364
|
+
}
|
|
30113
30365
|
|
|
30114
|
-
|
|
30115
|
-
|
|
30366
|
+
// reset notshow
|
|
30367
|
+
if(lastAtom.notshow) lastAtom.notshow = undefined;
|
|
30116
30368
|
|
|
30117
|
-
|
|
30118
|
-
|
|
30119
|
-
}
|
|
30120
|
-
else {
|
|
30121
|
-
ic.objects.push(mesh);
|
|
30122
|
-
}
|
|
30123
|
-
}
|
|
30369
|
+
firstAtom = currAtom;
|
|
30370
|
+
}
|
|
30124
30371
|
|
|
30125
|
-
|
|
30126
|
-
|
|
30127
|
-
|
|
30128
|
-
|
|
30129
|
-
|
|
30130
|
-
else {
|
|
30131
|
-
if(atom.b > 0 && atom.b <= 100) {
|
|
30132
|
-
radiusFinal = atom.b * 0.01;
|
|
30133
|
-
}
|
|
30134
|
-
else if(atom.b > 100) {
|
|
30135
|
-
radiusFinal = 100 * 0.01;
|
|
30136
|
-
}
|
|
30137
|
-
else {
|
|
30138
|
-
radiusFinal = ic.coilWidth;
|
|
30139
|
-
}
|
|
30372
|
+
prevChain = currChain;
|
|
30373
|
+
prevResi = currResi;
|
|
30374
|
+
prevAtom = currAtom;
|
|
30375
|
+
|
|
30376
|
+
++index;
|
|
30140
30377
|
}
|
|
30141
30378
|
|
|
30142
|
-
return
|
|
30379
|
+
return atomsAdjust;
|
|
30143
30380
|
}
|
|
30144
30381
|
}
|
|
30145
30382
|
|
|
@@ -37157,6 +37394,11 @@ class Alternate {
|
|
|
37157
37394
|
ic.directionalLight.position.copy(ic.lightPos.clone().applyQuaternion( quaternion ).normalize());
|
|
37158
37395
|
ic.directionalLight2.position.copy(ic.lightPos2.clone().applyQuaternion( quaternion ).normalize());
|
|
37159
37396
|
ic.directionalLight3.position.copy(ic.lightPos3.clone().applyQuaternion( quaternion ).normalize());
|
|
37397
|
+
|
|
37398
|
+
// adjust the light according to the position of camera
|
|
37399
|
+
ic.directionalLight.applyMatrix4(cam.matrixWorld);
|
|
37400
|
+
ic.directionalLight2.applyMatrix4(cam.matrixWorld);
|
|
37401
|
+
ic.directionalLight3.applyMatrix4(cam.matrixWorld);
|
|
37160
37402
|
}
|
|
37161
37403
|
|
|
37162
37404
|
if(!ic.bVr) ic.renderer.setPixelRatio( window.devicePixelRatio ); // r71
|
|
@@ -47788,6 +48030,13 @@ class ShowAnno {
|
|
|
47788
48030
|
} // align seq to structure
|
|
47789
48031
|
}
|
|
47790
48032
|
//ic.bAnnoShown = true;
|
|
48033
|
+
|
|
48034
|
+
if($("#" + ic.pre + "anno_ig").length && $("#" + ic.pre + "anno_ig")[0].checked) {
|
|
48035
|
+
ic.bRunRefnumAgain = true;
|
|
48036
|
+
await ic.annotationCls.setAnnoTabIg();
|
|
48037
|
+
|
|
48038
|
+
ic.bRunRefnumAgain = false;
|
|
48039
|
+
}
|
|
47791
48040
|
}
|
|
47792
48041
|
|
|
47793
48042
|
async showAnnoSeqData(nucleotide_chainid, chemical_chainid, chemical_set) { let ic = this.icn3d, me = ic.icn3dui;
|
|
@@ -53522,6 +53771,7 @@ class AlignParser {
|
|
|
53522
53771
|
|
|
53523
53772
|
async downloadAlignmentPart2(data, seqalign, chainresiCalphaHash2) { let ic = this.icn3d, me = ic.icn3dui;
|
|
53524
53773
|
//ic.init();
|
|
53774
|
+
|
|
53525
53775
|
ic.loadAtomDataCls.loadAtomDataIn(data, undefined, 'align', seqalign);
|
|
53526
53776
|
|
|
53527
53777
|
if(me.cfg.align === undefined && Object.keys(ic.structures).length == 1) {
|
|
@@ -53565,20 +53815,21 @@ class AlignParser {
|
|
|
53565
53815
|
async loadOpmDataForAlign(data, seqalign, mmdbidArray) { let ic = this.icn3d, me = ic.icn3dui;
|
|
53566
53816
|
let thisClass = this;
|
|
53567
53817
|
|
|
53568
|
-
let url = "https://opm-assets.storage.googleapis.com/pdb/" + mmdbidArray[0].toLowerCase()+ ".pdb";
|
|
53569
|
-
let prms1 = me.getAjaxPromise(url, 'text');
|
|
53570
|
-
let url2 = "https://opm-assets.storage.googleapis.com/pdb/" + mmdbidArray[1].toLowerCase()+ ".pdb";
|
|
53571
|
-
let prms2 = me.getAjaxPromise(url2, 'text');
|
|
53572
|
-
|
|
53573
|
-
let allPromise = Promise.allSettled([prms1, prms2]);
|
|
53574
53818
|
try {
|
|
53819
|
+
let url = "https://opm-assets.storage.googleapis.com/pdb/" + mmdbidArray[0].toLowerCase()+ ".pdb";
|
|
53820
|
+
let prms1 = me.getAjaxPromise(url, 'text');
|
|
53821
|
+
let url2 = "https://opm-assets.storage.googleapis.com/pdb/" + mmdbidArray[1].toLowerCase()+ ".pdb";
|
|
53822
|
+
let prms2 = me.getAjaxPromise(url2, 'text');
|
|
53823
|
+
|
|
53824
|
+
let allPromise = Promise.allSettled([prms1, prms2]);
|
|
53825
|
+
|
|
53575
53826
|
let dataArray = await allPromise;
|
|
53576
|
-
|
|
53827
|
+
|
|
53577
53828
|
let bFound = false;
|
|
53578
53829
|
for(let i = 0, il = dataArray.length; i < il; ++i) {
|
|
53579
|
-
//
|
|
53580
|
-
let opmdata = dataArray[i].value;
|
|
53830
|
+
// if(dataArray[i].status == 'rejected') continue;
|
|
53581
53831
|
|
|
53832
|
+
let opmdata = dataArray[i].value;
|
|
53582
53833
|
if(!opmdata) continue;
|
|
53583
53834
|
|
|
53584
53835
|
ic.selectedPdbid = mmdbidArray[i];
|
|
@@ -53594,6 +53845,7 @@ class AlignParser {
|
|
|
53594
53845
|
$("#" + ic.pre + "intra_mem_z").val(-ic.halfBilayerSize);
|
|
53595
53846
|
|
|
53596
53847
|
ic.init(); // remove all previously loaded data
|
|
53848
|
+
|
|
53597
53849
|
await thisClass.downloadAlignmentPart2(data, seqalign, chainresiCalphaHash);
|
|
53598
53850
|
|
|
53599
53851
|
bFound = true;
|
|
@@ -58169,7 +58421,7 @@ class SdfParser {
|
|
|
58169
58421
|
let sdfStr = await me.getAjaxPromise(urlSmiles, 'text');
|
|
58170
58422
|
|
|
58171
58423
|
ic.init();
|
|
58172
|
-
ic.bInputfile = true;
|
|
58424
|
+
//ic.bInputfile = true;
|
|
58173
58425
|
ic.InputfileData = (ic.InputfileData) ? ic.InputfileData + '\nENDMDL\n' + sdfStr : sdfStr;
|
|
58174
58426
|
ic.InputfileType = 'sdf';
|
|
58175
58427
|
await ic.sdfParserCls.loadSdfData(sdfStr);
|
|
@@ -60978,6 +61230,7 @@ class ParserUtils {
|
|
|
60978
61230
|
ic.selectionCls.oneStructurePerWindow(); // for alignment
|
|
60979
61231
|
ic.drawCls.draw();
|
|
60980
61232
|
}
|
|
61233
|
+
|
|
60981
61234
|
if(ic.bOpm) {
|
|
60982
61235
|
let axis = new THREE.Vector3(1,0,0);
|
|
60983
61236
|
let angle = -0.5 * Math.PI;
|
|
@@ -63515,7 +63768,8 @@ class LoadPDB {
|
|
|
63515
63768
|
|
|
63516
63769
|
// modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
63517
63770
|
//This PDB parser feeds the viewer with the content of a PDB file, pdbData.
|
|
63518
|
-
async loadPDB(src, pdbid, bOpm, bVector, bMutation, bAppend, type, bEsmfold) { let ic = this.icn3d, me = ic.icn3dui;
|
|
63771
|
+
// async loadPDB(src, pdbid, bOpm, bVector, bMutation, bAppend, type, bEsmfold) { let ic = this.icn3d, me = ic.icn3dui;
|
|
63772
|
+
loadPDB(src, pdbid, bOpm, bVector, bMutation, bAppend, type, bEsmfold) { let ic = this.icn3d, me = ic.icn3dui;
|
|
63519
63773
|
let hAtoms = {};
|
|
63520
63774
|
|
|
63521
63775
|
let bNMR = false;
|
|
@@ -68636,17 +68890,15 @@ class SelectCollections {
|
|
|
68636
68890
|
}
|
|
68637
68891
|
|
|
68638
68892
|
//Set the menu of defined sets with an array of defined names "commandnameArray".
|
|
68639
|
-
setAtomMenu(
|
|
68893
|
+
setAtomMenu(collection) {
|
|
68640
68894
|
let ic = this.icn3d;
|
|
68641
68895
|
ic.icn3dui;
|
|
68642
68896
|
let html = "";
|
|
68643
|
-
|
|
68644
|
-
|
|
68645
|
-
let name = nameArray[i][0];
|
|
68646
|
-
let title = nameArray[i][1];
|
|
68647
|
-
let description = nameArray[i][2];
|
|
68648
|
-
|
|
68897
|
+
|
|
68898
|
+
Object.entries(collection).forEach(([name, structure], index) => {
|
|
68649
68899
|
let atomHash;
|
|
68900
|
+
let [id, title, description, commands, pdb] = structure;
|
|
68901
|
+
|
|
68650
68902
|
if (
|
|
68651
68903
|
ic.defNames2Atoms !== undefined &&
|
|
68652
68904
|
ic.defNames2Atoms.hasOwnProperty(name)
|
|
@@ -68667,12 +68919,12 @@ class SelectCollections {
|
|
|
68667
68919
|
}
|
|
68668
68920
|
}
|
|
68669
68921
|
|
|
68670
|
-
if (
|
|
68671
|
-
html += "<option value='" +
|
|
68672
|
-
|
|
68922
|
+
if (index === 0) {
|
|
68923
|
+
html += "<option value='" + name + "' selected='selected' data-description='" + description + "'>" + title + "</option>";
|
|
68924
|
+
} else {
|
|
68673
68925
|
html += "<option value='" + name + "' data-description='" + description + "'>" + title + "</option>";
|
|
68674
|
-
|
|
68675
|
-
}
|
|
68926
|
+
}
|
|
68927
|
+
});
|
|
68676
68928
|
|
|
68677
68929
|
return html;
|
|
68678
68930
|
}
|
|
@@ -68726,7 +68978,7 @@ class SelectCollections {
|
|
|
68726
68978
|
let nameArray = $(this).val();
|
|
68727
68979
|
let nameStructure = $(this).find("option:selected").text();
|
|
68728
68980
|
let selectedIndices = Array.from(this.selectedOptions).map(option => option.index);
|
|
68729
|
-
|
|
68981
|
+
nameArray.reduce((map, name, i) => {
|
|
68730
68982
|
map[name] = selectedIndices[i];
|
|
68731
68983
|
return map;
|
|
68732
68984
|
}, {});
|
|
@@ -68763,13 +69015,13 @@ class SelectCollections {
|
|
|
68763
69015
|
if (Object.keys(ic.structures).length == 0) {
|
|
68764
69016
|
bAppend = false;
|
|
68765
69017
|
}
|
|
68766
|
-
await ic.pdbParserCls.loadPdbData(ic.pdbCollection[
|
|
69018
|
+
await ic.pdbParserCls.loadPdbData(ic.pdbCollection[name].join('\n'), undefined, undefined, bAppend);
|
|
68767
69019
|
} else {
|
|
68768
69020
|
await ic.chainalignParserCls.downloadMmdbAf(name, undefined, undefined, bNoDuplicate);
|
|
68769
69021
|
}
|
|
68770
69022
|
}
|
|
68771
69023
|
|
|
68772
|
-
await loadStructure(collection[
|
|
69024
|
+
await loadStructure(collection[name][4]).then(() => {
|
|
68773
69025
|
ic.allData['all'] = {
|
|
68774
69026
|
'atoms': ic.atoms,
|
|
68775
69027
|
'proteins': ic.proteins,
|
|
@@ -68829,9 +69081,9 @@ class SelectCollections {
|
|
|
68829
69081
|
|
|
68830
69082
|
ic.molTitle = ic.allData[name]['title'];
|
|
68831
69083
|
|
|
68832
|
-
if (collection[
|
|
69084
|
+
if (collection[name][3] !== undefined && collection[name][3].length > 0) {
|
|
68833
69085
|
if (ic.allData[name]['commands'] == undefined) {
|
|
68834
|
-
let commands = collection[
|
|
69086
|
+
let commands = collection[name][3];
|
|
68835
69087
|
ic.allData[name]['commands'] = commands;
|
|
68836
69088
|
}
|
|
68837
69089
|
}
|
|
@@ -69100,7 +69352,9 @@ class LoadScript {
|
|
|
69100
69352
|
}
|
|
69101
69353
|
else if(command.indexOf('view interactions') == 0 && me.cfg.align !== undefined) { // the command may have "|||{"factor"...
|
|
69102
69354
|
await thisClass.applyCommandViewinteraction(strArray[0].trim());
|
|
69103
|
-
|
|
69355
|
+
}
|
|
69356
|
+
else if(command.indexOf('view 2d depiction') == 0) { // the command may have "|||{"factor"...
|
|
69357
|
+
await ic.ligplotCls.drawLigplot(ic.atoms, true);
|
|
69104
69358
|
}
|
|
69105
69359
|
else if(command.indexOf('symmetry') == 0) {
|
|
69106
69360
|
ic.bAxisOnly = false;
|
|
@@ -69310,6 +69564,9 @@ class LoadScript {
|
|
|
69310
69564
|
else if(lastCommand.indexOf('view interactions') == 0 && me.cfg.align !== undefined) {
|
|
69311
69565
|
await thisClass.applyCommandViewinteraction(lastCommand);
|
|
69312
69566
|
}
|
|
69567
|
+
else if(lastCommand.indexOf('view 2d depiction') == 0) {
|
|
69568
|
+
await ic.ligplotCls.drawLigplot(ic.atoms, true);
|
|
69569
|
+
}
|
|
69313
69570
|
else if(lastCommand.indexOf('symmetry') == 0) {
|
|
69314
69571
|
let title = lastCommand.substr(lastCommand.indexOf(' ') + 1);
|
|
69315
69572
|
ic.symmetrytitle =(title === 'none') ? undefined : title;
|
|
@@ -71468,155 +71725,6 @@ class Resid2spec {
|
|
|
71468
71725
|
}
|
|
71469
71726
|
}
|
|
71470
71727
|
|
|
71471
|
-
/**
|
|
71472
|
-
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
71473
|
-
*/
|
|
71474
|
-
|
|
71475
|
-
class FirstAtomObj {
|
|
71476
|
-
constructor(icn3d) {
|
|
71477
|
-
this.icn3d = icn3d;
|
|
71478
|
-
}
|
|
71479
|
-
|
|
71480
|
-
//Return the first atom in the atom hash, which has the atom serial number as the key.
|
|
71481
|
-
getFirstAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
71482
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
71483
|
-
return undefined;
|
|
71484
|
-
}
|
|
71485
|
-
|
|
71486
|
-
let atomKeys = Object.keys(atomsHash);
|
|
71487
|
-
let firstIndex = atomKeys[0];
|
|
71488
|
-
|
|
71489
|
-
return ic.atoms[firstIndex];
|
|
71490
|
-
}
|
|
71491
|
-
|
|
71492
|
-
// n is the position of the selected atom
|
|
71493
|
-
getMiddleAtomObj(atomsHash, n) { let ic = this.icn3d; ic.icn3dui;
|
|
71494
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
71495
|
-
return undefined;
|
|
71496
|
-
}
|
|
71497
|
-
|
|
71498
|
-
let atomKeys = Object.keys(atomsHash);
|
|
71499
|
-
let middleIndex = (n && n < atomKeys.length) ? atomKeys[n] : atomKeys[parseInt(atomKeys.length / 2)];
|
|
71500
|
-
|
|
71501
|
-
return ic.atoms[middleIndex];
|
|
71502
|
-
}
|
|
71503
|
-
|
|
71504
|
-
getFirstCalphaAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
71505
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
71506
|
-
return undefined;
|
|
71507
|
-
}
|
|
71508
|
-
|
|
71509
|
-
let firstIndex;
|
|
71510
|
-
|
|
71511
|
-
for(let i in atomsHash) {
|
|
71512
|
-
if(ic.atoms[i].name == 'CA') {
|
|
71513
|
-
firstIndex = i;
|
|
71514
|
-
break;
|
|
71515
|
-
}
|
|
71516
|
-
}
|
|
71517
|
-
|
|
71518
|
-
if(!firstIndex) {
|
|
71519
|
-
for(let i in atomsHash) {
|
|
71520
|
-
if(ic.atoms[i].name == "O3'" || ic.atoms[i].name == "O3*") {
|
|
71521
|
-
firstIndex = i;
|
|
71522
|
-
break;
|
|
71523
|
-
}
|
|
71524
|
-
}
|
|
71525
|
-
}
|
|
71526
|
-
|
|
71527
|
-
return (firstIndex !== undefined) ? ic.atoms[firstIndex] : this.getFirstAtomObj(atomsHash);
|
|
71528
|
-
}
|
|
71529
|
-
|
|
71530
|
-
getFirstAtomObjByName(atomsHash, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
71531
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
71532
|
-
return ic.atoms[0];
|
|
71533
|
-
}
|
|
71534
|
-
|
|
71535
|
-
let firstIndex;
|
|
71536
|
-
|
|
71537
|
-
for(let i in atomsHash) {
|
|
71538
|
-
if(ic.atoms[i].name == atomName) {
|
|
71539
|
-
firstIndex = i;
|
|
71540
|
-
break;
|
|
71541
|
-
}
|
|
71542
|
-
}
|
|
71543
|
-
|
|
71544
|
-
return (firstIndex !== undefined) ? ic.atoms[firstIndex] : undefined;
|
|
71545
|
-
}
|
|
71546
|
-
|
|
71547
|
-
//Return the last atom in the atom hash, which has the atom serial number as the key.
|
|
71548
|
-
getLastAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
71549
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
71550
|
-
return ic.atoms[0];
|
|
71551
|
-
}
|
|
71552
|
-
|
|
71553
|
-
let atomKeys = Object.keys(atomsHash);
|
|
71554
|
-
let lastIndex = atomKeys[atomKeys.length - 1];
|
|
71555
|
-
|
|
71556
|
-
return ic.atoms[lastIndex];
|
|
71557
|
-
}
|
|
71558
|
-
|
|
71559
|
-
//Return the residue hash from the atom hash. The residue hash has the resid as the key and 1 as the value.
|
|
71560
|
-
getResiduesFromAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
71561
|
-
let residuesHash = {};
|
|
71562
|
-
for(let i in atomsHash) {
|
|
71563
|
-
let residueid = ic.atoms[i].structure + '_' + ic.atoms[i].chain + '_' + ic.atoms[i].resi;
|
|
71564
|
-
residuesHash[residueid] = 1;
|
|
71565
|
-
}
|
|
71566
|
-
|
|
71567
|
-
return residuesHash;
|
|
71568
|
-
}
|
|
71569
|
-
|
|
71570
|
-
getResiduesFromCalphaAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
71571
|
-
let residuesHash = {};
|
|
71572
|
-
for(let i in atomsHash) {
|
|
71573
|
-
if((ic.atoms[i].name == 'CA' && ic.proteins.hasOwnProperty(i)) || !ic.proteins.hasOwnProperty(i)) {
|
|
71574
|
-
let residueid = ic.atoms[i].structure + '_' + ic.atoms[i].chain + '_' + ic.atoms[i].resi;
|
|
71575
|
-
//residuesHash[residueid] = 1;
|
|
71576
|
-
residuesHash[residueid] = ic.atoms[i].resn;
|
|
71577
|
-
}
|
|
71578
|
-
}
|
|
71579
|
-
|
|
71580
|
-
return residuesHash;
|
|
71581
|
-
}
|
|
71582
|
-
|
|
71583
|
-
//Return the chain hash from the atom hash. The chain hash has the chainid as the key and 1 as the value.
|
|
71584
|
-
getChainsFromAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
71585
|
-
let chainsHash = {};
|
|
71586
|
-
for(let i in atomsHash) {
|
|
71587
|
-
let atom = ic.atoms[i];
|
|
71588
|
-
let chainid = atom.structure + "_" + atom.chain;
|
|
71589
|
-
|
|
71590
|
-
chainsHash[chainid] = 1;
|
|
71591
|
-
}
|
|
71592
|
-
|
|
71593
|
-
return chainsHash;
|
|
71594
|
-
}
|
|
71595
|
-
|
|
71596
|
-
getAtomFromResi(resid, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
71597
|
-
if(ic.residues.hasOwnProperty(resid)) {
|
|
71598
|
-
for(let i in ic.residues[resid]) {
|
|
71599
|
-
if(ic.atoms[i].name === atomName && !ic.atoms[i].het) {
|
|
71600
|
-
return ic.atoms[i];
|
|
71601
|
-
}
|
|
71602
|
-
}
|
|
71603
|
-
}
|
|
71604
|
-
|
|
71605
|
-
return undefined;
|
|
71606
|
-
}
|
|
71607
|
-
|
|
71608
|
-
getAtomCoordFromResi(resid, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
71609
|
-
let atom = this.getAtomFromResi(resid, atomName);
|
|
71610
|
-
if(atom !== undefined) {
|
|
71611
|
-
let coord = (atom.coord2 !== undefined) ? atom.coord2 : atom.coord;
|
|
71612
|
-
|
|
71613
|
-
return coord;
|
|
71614
|
-
}
|
|
71615
|
-
|
|
71616
|
-
return undefined;
|
|
71617
|
-
}
|
|
71618
|
-
}
|
|
71619
|
-
|
|
71620
71728
|
/**
|
|
71621
71729
|
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
71622
71730
|
*/
|
|
@@ -71677,9 +71785,9 @@ class Delphi {
|
|
|
71677
71785
|
let pdbstr = '';
|
|
71678
71786
|
/// pdbstr += ic.saveFileCls.getPDBHeader();
|
|
71679
71787
|
|
|
71680
|
-
let bMergeIntoOne = true;
|
|
71681
|
-
pdbstr +=(me.cfg.cid) ? ic.saveFileCls.getAtomPDB(atomHash, true, undefined, undefined, undefined, undefined, bMergeIntoOne) : ic.saveFileCls.getAtomPDB(atomHash, undefined, undefined, undefined, undefined, undefined, bMergeIntoOne);
|
|
71682
|
-
pdbstr += ic.saveFileCls.getAtomPDB(ionHash, true, undefined, true);
|
|
71788
|
+
let bMergeIntoOne = true, bOneLetterChain = true;
|
|
71789
|
+
pdbstr +=(me.cfg.cid) ? ic.saveFileCls.getAtomPDB(atomHash, true, undefined, undefined, undefined, undefined, bMergeIntoOne, bOneLetterChain) : ic.saveFileCls.getAtomPDB(atomHash, undefined, undefined, undefined, undefined, undefined, bMergeIntoOne, bOneLetterChain);
|
|
71790
|
+
pdbstr += ic.saveFileCls.getAtomPDB(ionHash, true, undefined, true, undefined, undefined, bMergeIntoOne, bOneLetterChain);
|
|
71683
71791
|
|
|
71684
71792
|
return pdbstr;
|
|
71685
71793
|
}
|
|
@@ -77693,8 +77801,13 @@ class Ligplot {
|
|
|
77693
77801
|
this.icn3d = icn3d;
|
|
77694
77802
|
}
|
|
77695
77803
|
|
|
77696
|
-
async drawLigplot(atomSet1) { let ic = this.icn3d, me = ic.icn3dui;
|
|
77697
|
-
|
|
77804
|
+
async drawLigplot(atomSet1, bDepiction) { let ic = this.icn3d, me = ic.icn3dui;
|
|
77805
|
+
if(bDepiction) {
|
|
77806
|
+
me.htmlCls.dialogCls.openDlg('dl_ligplot', '2D Depiction');
|
|
77807
|
+
}
|
|
77808
|
+
else {
|
|
77809
|
+
me.htmlCls.dialogCls.openDlg('dl_ligplot', 'Show ligand interactions with atom details');
|
|
77810
|
+
}
|
|
77698
77811
|
|
|
77699
77812
|
let widthOri, heightOri, width = 100, height = 100;
|
|
77700
77813
|
ic.len4ang = 80;
|
|
@@ -77776,19 +77889,28 @@ class Ligplot {
|
|
|
77776
77889
|
let offset = - ic.len4ang;
|
|
77777
77890
|
let svgHtml = "<svg id='" + id + "' viewBox='" + offset + "," + offset + "," + width + "," + heightAll + "' width='" + graphWidth + "px' font-family='sans-serif' stroke='rgb(0,0,0)' stroke-width='2' stroke-linecap='round'>";
|
|
77778
77891
|
|
|
77779
|
-
|
|
77780
|
-
|
|
77781
|
-
|
|
77892
|
+
if(bDepiction) {
|
|
77893
|
+
svgHtml += lineSvg + nodeSvg;
|
|
77894
|
+
}
|
|
77895
|
+
else {
|
|
77896
|
+
let xlen = parseInt(widthOri / ic.svgGridSize), ylen = parseInt(heightOri / ic.svgGridSize);
|
|
77897
|
+
let result = ic.viewInterPairsCls.getAllInteractionTable("save1", index2xy, xlen, ylen, xcenter, ycenter); // sort on the ligand/set1
|
|
77898
|
+
// ic.bLigplot = true;
|
|
77782
77899
|
|
|
77783
|
-
|
|
77900
|
+
svgHtml += lineSvg + result.svgHtmlLine;
|
|
77784
77901
|
|
|
77785
|
-
|
|
77902
|
+
svgHtml += nodeSvg + result.svgHtmlNode;
|
|
77903
|
+
}
|
|
77786
77904
|
|
|
77787
77905
|
svgHtml += "</svg>";
|
|
77788
77906
|
|
|
77789
|
-
|
|
77790
|
-
|
|
77791
|
-
|
|
77907
|
+
if(bDepiction) {
|
|
77908
|
+
$("#" + ic.pre + "ligplotDiv").html(svgHtml);
|
|
77909
|
+
}
|
|
77910
|
+
else {
|
|
77911
|
+
$("#" + ic.pre + "ligplotDiv").html(svgHtml);
|
|
77912
|
+
this.setEventsForLigplot();
|
|
77913
|
+
}
|
|
77792
77914
|
}
|
|
77793
77915
|
|
|
77794
77916
|
|
|
@@ -78935,7 +79057,7 @@ class SaveFile {
|
|
|
78935
79057
|
}
|
|
78936
79058
|
|
|
78937
79059
|
//getAtomPDB: function(atomHash, bPqr, bPdb, bNoChem) { let ic = this.icn3d, me = ic.icn3dui;
|
|
78938
|
-
getAtomPDB(atomHash, bPqr, bNoChem, bNoHeader, chainResi2pdb, pdbid, bMergeIntoOne,
|
|
79060
|
+
getAtomPDB(atomHash, bPqr, bNoChem, bNoHeader, chainResi2pdb, pdbid, bMergeIntoOne, bOneLetterChain) { let ic = this.icn3d, me = ic.icn3dui;
|
|
78939
79061
|
let pdbStr = '';
|
|
78940
79062
|
|
|
78941
79063
|
// get all phosphate groups in lipids
|
|
@@ -79210,7 +79332,7 @@ class SaveFile {
|
|
|
79210
79332
|
//line +=(atom.chain.length <= 1) ? atom.chain.padStart(1, ' ') : atom.chain.substr(0, 1);
|
|
79211
79333
|
if(atom.chain.length >= 2) {
|
|
79212
79334
|
let chainTmp = atom.chain.replace(/_/gi, '').substr(0, 2);
|
|
79213
|
-
if(
|
|
79335
|
+
if(bOneLetterChain) chainTmp = ' ' + chainTmp.substr(0,1); // VAST search only support one lettter chain ID
|
|
79214
79336
|
line += chainTmp;
|
|
79215
79337
|
}
|
|
79216
79338
|
else if(atom.chain.length == 1) {
|
|
@@ -79289,8 +79411,8 @@ class SaveFile {
|
|
|
79289
79411
|
}
|
|
79290
79412
|
else {
|
|
79291
79413
|
line += "1.00".padStart(6, ' ');
|
|
79292
|
-
//
|
|
79293
|
-
let defaultBFactor =
|
|
79414
|
+
// let defaultBFactor = (bOneLetterChain) ? "1.0" : " ";
|
|
79415
|
+
let defaultBFactor = " ";
|
|
79294
79416
|
line +=(atom.b) ? parseFloat(atom.b).toFixed(2).toString().padStart(6, ' ') : defaultBFactor.padStart(6, ' ');
|
|
79295
79417
|
line += ' '.padStart(10, ' ');
|
|
79296
79418
|
line += atom.elem.padStart(2, ' ');
|
|
@@ -79338,7 +79460,7 @@ class SaveFile {
|
|
|
79338
79460
|
let resn = me.utilsCls.residueName2Abbr(atom.resn);
|
|
79339
79461
|
let ss = this.secondary2Abbr(atom.ss);
|
|
79340
79462
|
|
|
79341
|
-
if(chainid != prevChainid) {
|
|
79463
|
+
if(chainid != prevChainid && !data[chainid]) {
|
|
79342
79464
|
data[chainid] = {"resi": [], "resn": [], "secondary": []};
|
|
79343
79465
|
}
|
|
79344
79466
|
|
|
@@ -82862,7 +82984,7 @@ class iCn3DUI {
|
|
|
82862
82984
|
//even when multiple iCn3D viewers are shown together.
|
|
82863
82985
|
this.pre = this.cfg.divid + "_";
|
|
82864
82986
|
|
|
82865
|
-
this.REVISION = '3.
|
|
82987
|
+
this.REVISION = '3.40.3';
|
|
82866
82988
|
|
|
82867
82989
|
// In nodejs, iCn3D defines "window = {navigator: {}}"
|
|
82868
82990
|
this.bNode = (Object.keys(window).length < 2) ? true : false;
|
|
@@ -83024,7 +83146,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
|
|
|
83024
83146
|
ic.molTitle = '';
|
|
83025
83147
|
ic.loadCmd;
|
|
83026
83148
|
|
|
83027
|
-
// set menus
|
|
83149
|
+
// set menus
|
|
83028
83150
|
me.htmlCls.clickMenuCls.getHiddenMenusFromCache();
|
|
83029
83151
|
me.htmlCls.clickMenuCls.applyShownMenus();
|
|
83030
83152
|
|