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.module.js
CHANGED
|
@@ -9728,25 +9728,42 @@ class ClickMenu {
|
|
|
9728
9728
|
}
|
|
9729
9729
|
|
|
9730
9730
|
getHiddenMenusFromCache() { let me = this.icn3dui; me.icn3d;
|
|
9731
|
-
|
|
9731
|
+
// me.htmlCls.shownMenus = {};
|
|
9732
9732
|
|
|
9733
|
-
|
|
9734
|
-
|
|
9735
|
-
if(idArrayStr && idArrayStr != '[]') {
|
|
9736
|
-
let idArray = JSON.parse(idArrayStr);
|
|
9733
|
+
// let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
|
|
9737
9734
|
|
|
9738
|
-
|
|
9739
|
-
|
|
9740
|
-
|
|
9741
|
-
|
|
9742
|
-
|
|
9743
|
-
|
|
9744
|
-
|
|
9735
|
+
let idArrayStr = (localStorage) ? localStorage.getItem('hiddenmenus') : '';
|
|
9736
|
+
|
|
9737
|
+
if(idArrayStr && idArrayStr != '[]') {
|
|
9738
|
+
me.htmlCls.shownMenus = {};
|
|
9739
|
+
|
|
9740
|
+
let idArray = JSON.parse(idArrayStr);
|
|
9741
|
+
|
|
9742
|
+
// for(let i = 0, il = idArray.length; i < il; ++i) {
|
|
9743
|
+
// me.htmlCls.shownMenus[idArray[i]] = 1;
|
|
9744
|
+
// }
|
|
9745
|
+
for(let menu in me.htmlCls.allMenus) {
|
|
9746
|
+
if(idArray.indexOf(menu) == -1) {
|
|
9747
|
+
me.htmlCls.shownMenus[menu] = 1;
|
|
9745
9748
|
}
|
|
9746
|
-
|
|
9747
|
-
|
|
9748
|
-
|
|
9749
|
-
|
|
9749
|
+
}
|
|
9750
|
+
}
|
|
9751
|
+
//###
|
|
9752
|
+
else {
|
|
9753
|
+
me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
|
|
9754
|
+
}
|
|
9755
|
+
|
|
9756
|
+
// else {
|
|
9757
|
+
// if(mode == 'all') {
|
|
9758
|
+
// me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
|
|
9759
|
+
// }
|
|
9760
|
+
// else if(!mode || mode == 'simple') {
|
|
9761
|
+
// me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
|
|
9762
|
+
// }
|
|
9763
|
+
// else {
|
|
9764
|
+
// me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
|
|
9765
|
+
// }
|
|
9766
|
+
// }
|
|
9750
9767
|
}
|
|
9751
9768
|
|
|
9752
9769
|
displayShownMenus() { let me = this.icn3dui; me.icn3d;
|
|
@@ -10242,11 +10259,14 @@ class ClickMenu {
|
|
|
10242
10259
|
me.htmlCls.shownMenus[checkbox.value] = 1;
|
|
10243
10260
|
}
|
|
10244
10261
|
|
|
10262
|
+
me.htmlCls.setHtmlCls.setCookie('menumode', 'custom');
|
|
10263
|
+
|
|
10245
10264
|
thisClass.applyShownMenus();
|
|
10246
10265
|
});
|
|
10247
10266
|
|
|
10248
10267
|
me.myEventCls.onIds(["#" + me.pre + "reset_menupref", "#" + me.pre + "reset_menupref2"], "click", function(e) { me.icn3d; //e.preventDefault();
|
|
10249
10268
|
me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
|
|
10269
|
+
me.htmlCls.setHtmlCls.setCookie('menumode', 'simple');
|
|
10250
10270
|
|
|
10251
10271
|
thisClass.applyShownMenus();
|
|
10252
10272
|
thisClass.displayShownMenus();
|
|
@@ -10254,6 +10274,7 @@ class ClickMenu {
|
|
|
10254
10274
|
|
|
10255
10275
|
me.myEventCls.onIds(["#" + me.pre + "reset_menupref_all", "#" + me.pre + "reset_menupref_all2"], "click", function(e) { me.icn3d; //e.preventDefault();
|
|
10256
10276
|
me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
|
|
10277
|
+
me.htmlCls.setHtmlCls.setCookie('menumode', 'all');
|
|
10257
10278
|
|
|
10258
10279
|
thisClass.applyShownMenus();
|
|
10259
10280
|
thisClass.displayShownMenus();
|
|
@@ -10303,15 +10324,16 @@ class ClickMenu {
|
|
|
10303
10324
|
|
|
10304
10325
|
thisClass.applyShownMenus();
|
|
10305
10326
|
thisClass.displayShownMenus();
|
|
10327
|
+
|
|
10328
|
+
me.htmlCls.setHtmlCls.setCookie('menumode', 'custom');
|
|
10306
10329
|
};
|
|
10307
10330
|
reader.readAsText(file);
|
|
10308
10331
|
}
|
|
10309
10332
|
});
|
|
10310
10333
|
|
|
10311
|
-
me.myEventCls.onIds("#" + me.pre + "mn1_menuloadpref", "click", function(e) { me.icn3d; //e.preventDefault();
|
|
10334
|
+
me.myEventCls.onIds(["#" + me.pre + "mn1_menuloadpref", "#" + me.pre + "loadpref", "#" + me.pre + "loadpref2"], "click", function(e) { me.icn3d; //e.preventDefault();
|
|
10312
10335
|
me.htmlCls.dialogCls.openDlg('dl_menuloadpref', 'Please input the menu preference file');
|
|
10313
10336
|
});
|
|
10314
|
-
|
|
10315
10337
|
|
|
10316
10338
|
me.myEventCls.onIds("#" + me.pre + "mn1_link_structure", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
|
|
10317
10339
|
let url = ic.saveFileCls.getLinkToStructureSummary(true);
|
|
@@ -12150,6 +12172,51 @@ class SetMenu {
|
|
|
12150
12172
|
return me.htmlCls.setHtmlCls.getRadioColor(radioid, id, text, color, bChecked, bSimpleMenu, selType);
|
|
12151
12173
|
}
|
|
12152
12174
|
|
|
12175
|
+
resetMenu(mode) { let me = this.icn3dui;
|
|
12176
|
+
if(!mode || mode == 'simple') {
|
|
12177
|
+
me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
|
|
12178
|
+
|
|
12179
|
+
me.htmlCls.clickMenuCls.applyShownMenus();
|
|
12180
|
+
}
|
|
12181
|
+
else if(mode == 'all') {
|
|
12182
|
+
me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
|
|
12183
|
+
|
|
12184
|
+
me.htmlCls.clickMenuCls.applyShownMenus();
|
|
12185
|
+
}
|
|
12186
|
+
else if(mode == 'custom') {
|
|
12187
|
+
me.htmlCls.dialogCls.openDlg('dl_menupref', 'Select Menus');
|
|
12188
|
+
|
|
12189
|
+
me.htmlCls.clickMenuCls.getHiddenMenusFromCache();
|
|
12190
|
+
|
|
12191
|
+
me.htmlCls.clickMenuCls.displayShownMenus();
|
|
12192
|
+
}
|
|
12193
|
+
}
|
|
12194
|
+
|
|
12195
|
+
setMenuMode(bMobile) { let me = this.icn3dui;
|
|
12196
|
+
let spaceCss = (bMobile) ? "; padding-left:6px; background-color:#eee" : "; margin:3px; background-color:white";
|
|
12197
|
+
let spaceCss2 = (bMobile) ? "; font-size:14px!important" : "";
|
|
12198
|
+
|
|
12199
|
+
let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
|
|
12200
|
+
|
|
12201
|
+
let html = '<div class="icn3d-text" style="color:#f8b84e; font-weight:bold' + spaceCss + '">';
|
|
12202
|
+
html += '<select name="menumode" id="' + me.pre + 'menumode" class="icn3d-text" style="color:#f8b84e; font-weight:bold; border:0px' + spaceCss2 + '">';
|
|
12203
|
+
html += (mode == 'simple' || !mode) ? '<option value="simple" selected>Simple</option>' : '<option value="simple">Simple</option>';
|
|
12204
|
+
html += (mode == 'all') ? '<option value="all" selected>All</option>' : '<option value="all">All</option>';
|
|
12205
|
+
html += (mode == 'custom') ? '<option value="custom" selected>Custom</option>' : '<option value="custom">Custom</option>';
|
|
12206
|
+
html += '</select>';
|
|
12207
|
+
|
|
12208
|
+
if(bMobile) {
|
|
12209
|
+
html += '<br><span style="font-size:12px"> Menus</span>';
|
|
12210
|
+
}
|
|
12211
|
+
else {
|
|
12212
|
+
html += ' Menus';
|
|
12213
|
+
}
|
|
12214
|
+
|
|
12215
|
+
html += '</div>';
|
|
12216
|
+
|
|
12217
|
+
return html;
|
|
12218
|
+
}
|
|
12219
|
+
|
|
12153
12220
|
//Set the HTML code for the menus shown at the top of the viewer.
|
|
12154
12221
|
setTopMenusHtml(id, str1, str2) { let me = this.icn3dui;
|
|
12155
12222
|
if(me.bNode) return '';
|
|
@@ -12169,6 +12236,9 @@ class SetMenu {
|
|
|
12169
12236
|
html += "<table border='0' cellpadding='0' cellspacing='0' width='100'><tr>";
|
|
12170
12237
|
|
|
12171
12238
|
let tdStr = '<td valign="top">';
|
|
12239
|
+
|
|
12240
|
+
// html += tdStr + this.setMenuMode() + '</td>';
|
|
12241
|
+
|
|
12172
12242
|
html += tdStr + this.setMenu1() + '</td>';
|
|
12173
12243
|
|
|
12174
12244
|
html += tdStr + this.setMenu2() + '</td>';
|
|
@@ -12181,7 +12251,11 @@ class SetMenu {
|
|
|
12181
12251
|
//html += tdStr + this.setMenu5b() + '</td>';
|
|
12182
12252
|
html += tdStr + this.setMenu6() + '</td>';
|
|
12183
12253
|
|
|
12184
|
-
|
|
12254
|
+
// reset the menus at the end of the menus
|
|
12255
|
+
// let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
|
|
12256
|
+
// this.resetMenu(mode);
|
|
12257
|
+
|
|
12258
|
+
// me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
|
|
12185
12259
|
|
|
12186
12260
|
html += tdStr + "<div style='position:relative; margin-left:6px;'>" + str1;
|
|
12187
12261
|
html += "<div class='icn3d-commandTitle' style='min-width:40px; margin-top: 3px; white-space: nowrap;'>" + str2;
|
|
@@ -12277,6 +12351,7 @@ class SetMenu {
|
|
|
12277
12351
|
|
|
12278
12352
|
//html += "<div class='icn3d-menu'>";
|
|
12279
12353
|
html += "<div>";
|
|
12354
|
+
|
|
12280
12355
|
html += "<accordion id='" + me.pre + "accordion0' class='icn3d-accordion'>";
|
|
12281
12356
|
if(me.cfg.notebook) {
|
|
12282
12357
|
html += "<h3 style='width:20px; height:24px; position:relative; padding: 0'><span style='position:absolute; left:3px; top:4px;'>☰</span></h3>";
|
|
@@ -12286,6 +12361,8 @@ class SetMenu {
|
|
|
12286
12361
|
}
|
|
12287
12362
|
html += "<div>";
|
|
12288
12363
|
|
|
12364
|
+
// html += '<li>' + this.setMenuMode(true);
|
|
12365
|
+
|
|
12289
12366
|
let liStr = "<li><span class='icn3d-menu-color'";
|
|
12290
12367
|
|
|
12291
12368
|
html += "<ul class='icn3d-mn-item'>";
|
|
@@ -12304,7 +12381,11 @@ class SetMenu {
|
|
|
12304
12381
|
html += liStr + ">Help</span>";
|
|
12305
12382
|
html += this.setMenu6_base();
|
|
12306
12383
|
|
|
12307
|
-
|
|
12384
|
+
// reset the menus at the end of the menus
|
|
12385
|
+
// let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
|
|
12386
|
+
// this.resetMenu(mode);
|
|
12387
|
+
|
|
12388
|
+
// me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
|
|
12308
12389
|
|
|
12309
12390
|
html += "<li><div style='position:relative; margin-top:-6px;'>" + str1;
|
|
12310
12391
|
html += "<div class='icn3d-commandTitle' style='margin-top: 3px; white-space: nowrap;'>" + str2;
|
|
@@ -12481,7 +12562,7 @@ class SetMenu {
|
|
|
12481
12562
|
// Analysis menu
|
|
12482
12563
|
html += tdStrBorder + this.setIcon(iconType, 'tool_selectannotations', 'Sequences & Annotations', 'grip-lines') + "</td>";
|
|
12483
12564
|
html += tdStr + this.setIcon(iconType, 'hbondsYes', 'Interactions', 'users') + "</td>";
|
|
12484
|
-
html += tdStr + this.setIcon(iconType, 'tool_delphi', '
|
|
12565
|
+
html += tdStr + this.setIcon(iconType, 'tool_delphi', 'DelPhi Potentials', 'cloud-meatball') + "</td>";
|
|
12485
12566
|
html += tdStr + this.setIcon(iconType, 'removeLabels', 'Remove Labels', 'remove-format') + "</td>";
|
|
12486
12567
|
|
|
12487
12568
|
// Help menu
|
|
@@ -13693,6 +13774,10 @@ class SetMenu {
|
|
|
13693
13774
|
|
|
13694
13775
|
html += "<ul class='icn3d-mn-item'>";
|
|
13695
13776
|
|
|
13777
|
+
if(me.cfg.cid !== undefined || me.cfg.smiles !== undefined) {
|
|
13778
|
+
html += this.getLink('mn2_2ddepiction', '2D Depiction ' + me.htmlCls.wifiStr, 1, 1);
|
|
13779
|
+
}
|
|
13780
|
+
|
|
13696
13781
|
if(me.cfg.cid === undefined) {
|
|
13697
13782
|
html += this.getLink('mn6_selectannotations', 'Seq. & Annotations ' + me.htmlCls.wifiStr, 1, 1);
|
|
13698
13783
|
|
|
@@ -14494,7 +14579,7 @@ class Dialog {
|
|
|
14494
14579
|
width='50%';
|
|
14495
14580
|
}
|
|
14496
14581
|
else if(id === me.pre + 'dl_menupref') {
|
|
14497
|
-
width =
|
|
14582
|
+
width = 800;
|
|
14498
14583
|
height = 500;
|
|
14499
14584
|
}
|
|
14500
14585
|
|
|
@@ -15155,6 +15240,10 @@ class SetDialog {
|
|
|
15155
15240
|
html += me.htmlCls.divStr + "dl_collection_file' style=''>";
|
|
15156
15241
|
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>";
|
|
15157
15242
|
html += "Collection file: " + me.htmlCls.inputFileStr + "id='" + me.pre + "collectionfile'><br/>";
|
|
15243
|
+
html += "<input type='radio' id='dl_collectionAppendStructureNone' name='appendStructure' value='none' checked/>";
|
|
15244
|
+
html += "<label for='dl_collectionAppendStructureNone'>Default</label>";
|
|
15245
|
+
html += "<input type='radio' id='dl_collectionAppendStructure' name='appendStructure' value='append' />";
|
|
15246
|
+
html += "<label for='dl_collectionAppendStructure'>Append</label><br/>";
|
|
15158
15247
|
html += me.htmlCls.buttonStr + "reload_collectionfile' style='margin-top: 6px;'>Load</button>";
|
|
15159
15248
|
html += "</div>";
|
|
15160
15249
|
html += "</div>";
|
|
@@ -15162,7 +15251,8 @@ class SetDialog {
|
|
|
15162
15251
|
html += me.htmlCls.divStr + "dl_collection_structures' style='display: none'>";
|
|
15163
15252
|
html += "<select id='" + me.pre + "collections_menu'multiple size='6' style='min-width:300px;'></select>";
|
|
15164
15253
|
html += '<br/>';
|
|
15165
|
-
html += me.htmlCls.buttonStr + "
|
|
15254
|
+
html += me.htmlCls.buttonStr + "collections_clear_commands' style='margin-top: 6px;'>Clear Commands</button>";
|
|
15255
|
+
html += me.htmlCls.buttonStr + "opendl_export_collections'>Export JSON</button>";
|
|
15166
15256
|
html += "</div>";
|
|
15167
15257
|
html += '<br/>';
|
|
15168
15258
|
html += "</div>";
|
|
@@ -15517,24 +15607,30 @@ class SetDialog {
|
|
|
15517
15607
|
html += "</div>";
|
|
15518
15608
|
|
|
15519
15609
|
|
|
15520
|
-
html += me.htmlCls.divStr + "dl_ligplot'
|
|
15521
|
-
|
|
15610
|
+
html += me.htmlCls.divStr + "dl_ligplot' style='background-color:white' class='" + dialogClass + "'>";
|
|
15611
|
+
|
|
15612
|
+
if(me.cfg.cid !== undefined || me.cfg.smiles !== undefined) {
|
|
15613
|
+
html += this.addNotebookTitle('dl_ligplot', '2D Depiction for Chemicals');
|
|
15614
|
+
}
|
|
15615
|
+
else {
|
|
15616
|
+
html += this.addNotebookTitle('dl_ligplot', '2D Interaction for One Ligand/Residue with Atom Details');
|
|
15522
15617
|
|
|
15523
|
-
|
|
15618
|
+
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;
|
|
15524
15619
|
|
|
15525
|
-
|
|
15526
|
-
|
|
15527
|
-
|
|
15620
|
+
html += '<div style="width:20px; margin-top:6px; display:inline-block;"><span id="'
|
|
15621
|
+
+ 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="'
|
|
15622
|
+
+ me.pre + 'dl_ligplotcolor_shrink" class="ui-icon ui-icon-minus icn3d-shrink icn3d-link" style="width:15px;" title="Shrink"></span></div></div>';
|
|
15528
15623
|
|
|
15529
|
-
|
|
15624
|
+
html += me.htmlCls.divStr + "dl_ligplotcolor' style='inline-block;'>";
|
|
15530
15625
|
|
|
15531
|
-
|
|
15532
|
-
|
|
15533
|
-
|
|
15626
|
+
// 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>";
|
|
15627
|
+
// html += "Mouseover the dashed lines to see interaction types and distances.<br>";
|
|
15628
|
+
html += "<b>Color legend</b> for interactions (dashed lines): <br>";
|
|
15534
15629
|
|
|
15535
|
-
|
|
15630
|
+
html += me.htmlCls.setHtmlCls.setColorHints();
|
|
15536
15631
|
|
|
15537
|
-
|
|
15632
|
+
html += "<br></div>";
|
|
15633
|
+
}
|
|
15538
15634
|
|
|
15539
15635
|
me.ligplotid = me.pre + 'ligplot';
|
|
15540
15636
|
html += me.htmlCls.divNowrapStr + buttonStrTmp + me.ligplotid + '_svg">SVG</button>' + me.htmlCls.space2;
|
|
@@ -15861,13 +15957,15 @@ class SetDialog {
|
|
|
15861
15957
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "apply_menupref'>Apply</button></span>";
|
|
15862
15958
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "reset_menupref' style='margin-left:30px'>Reset to Simple Menus</button></span>";
|
|
15863
15959
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "reset_menupref_all' style='margin-left:30px'>Reset to All Menus</button></span>";
|
|
15864
|
-
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "savepref' style='margin-left:30px'>Save Preferences</button></span
|
|
15960
|
+
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "savepref' style='margin-left:30px'>Save Preferences</button></span>";
|
|
15961
|
+
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "loadpref' style='margin-left:30px'>Load Preferences</button></span><br><br>";
|
|
15865
15962
|
|
|
15866
15963
|
html += "<div id='" + me.pre + "menulist'></div><br><br>";
|
|
15867
15964
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "apply_menupref2'>Apply</button></span>";
|
|
15868
15965
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "reset_menupref2' style='margin-left:30px'>Reset to Simple Menus</button></span>";
|
|
15869
15966
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "reset_menupref_all2' style='margin-left:30px'>Reset to All Menus</button></span>";
|
|
15870
15967
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "savepref2' style='margin-left:30px'>Save Preferences</button></span>";
|
|
15968
|
+
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "loadpref2' style='margin-left:30px'>Load Preferences</button></span>";
|
|
15871
15969
|
html += "</div>";
|
|
15872
15970
|
|
|
15873
15971
|
html += me.htmlCls.divStr + "dl_addtrack' class='" + dialogClass + "'>";
|
|
@@ -16643,6 +16741,14 @@ class Events {
|
|
|
16643
16741
|
me.htmlCls.clickMenuCls.clickMenu5();
|
|
16644
16742
|
me.htmlCls.clickMenuCls.clickMenu6();
|
|
16645
16743
|
|
|
16744
|
+
me.myEventCls.onIds("#" + me.pre + "menumode", "change", async function(e) { me.icn3d;
|
|
16745
|
+
e.preventDefault();
|
|
16746
|
+
let mode = $("#" + me.pre + "menumode").val();
|
|
16747
|
+
|
|
16748
|
+
me.htmlCls.setHtmlCls.setCookie('menumode', mode);
|
|
16749
|
+
me.htmlCls.setMenuCls.resetMenu(mode);
|
|
16750
|
+
});
|
|
16751
|
+
|
|
16646
16752
|
// back and forward arrows
|
|
16647
16753
|
me.myEventCls.onIds(["#" + me.pre + "back", "#" + me.pre + "mn6_back"], "click", async function(e) { let ic = me.icn3d;
|
|
16648
16754
|
e.preventDefault();
|
|
@@ -16920,6 +17026,11 @@ class Events {
|
|
|
16920
17026
|
thisClass.setLogCmd("view interactions", true);
|
|
16921
17027
|
});
|
|
16922
17028
|
|
|
17029
|
+
me.myEventCls.onIds("#" + me.pre + "mn2_2ddepiction", "click", async function(e) { let ic = me.icn3d;
|
|
17030
|
+
await ic.ligplotCls.drawLigplot(ic.atoms, true);
|
|
17031
|
+
thisClass.setLogCmd("view 2d depiction", true);
|
|
17032
|
+
});
|
|
17033
|
+
|
|
16923
17034
|
me.myEventCls.onIds("#" + me.pre + "search_seq_button", "click", async function(e) { me.icn3d;
|
|
16924
17035
|
e.stopImmediatePropagation();
|
|
16925
17036
|
await thisClass.searchSeq();
|
|
@@ -17684,95 +17795,108 @@ class Events {
|
|
|
17684
17795
|
} else {
|
|
17685
17796
|
ic.resizeCanvasCls.closeDialogs();
|
|
17686
17797
|
}
|
|
17687
|
-
|
|
17688
|
-
ic.pdbCollection = [];
|
|
17689
|
-
ic.allData = {};
|
|
17690
|
-
ic.allData['all'] = {
|
|
17691
|
-
'atoms': {},
|
|
17692
|
-
'proteins': {},
|
|
17693
|
-
'nucleotides': {},
|
|
17694
|
-
'chemicals': {},
|
|
17695
|
-
'ions': {},
|
|
17696
|
-
'water': {},
|
|
17697
|
-
'structures': {}, // getSSExpandedAtoms
|
|
17698
|
-
'ssbondpnts': {},
|
|
17699
|
-
'residues': {}, // getSSExpandedAtoms
|
|
17700
|
-
'chains': {},
|
|
17701
|
-
'chainsSeq': {}, //Sequences and Annotation
|
|
17702
|
-
'defNames2Atoms': {},
|
|
17703
|
-
'defNames2Residues': {}
|
|
17704
|
-
};
|
|
17705
|
-
ic.allData['prev'] = {};
|
|
17706
|
-
ic.selectCollectionsCls.reset();
|
|
17707
|
-
|
|
17798
|
+
|
|
17708
17799
|
ic.dAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
|
|
17709
17800
|
ic.hAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
|
|
17710
17801
|
me.htmlCls.setHtmlCls.fileSupport();
|
|
17711
17802
|
|
|
17712
17803
|
let fileName = file.name;
|
|
17713
17804
|
let fileExtension = fileName.split('.').pop().toLowerCase();
|
|
17714
|
-
|
|
17805
|
+
let collection = {};
|
|
17806
|
+
|
|
17715
17807
|
$("#" + ic.pre + "collections_menu").empty();
|
|
17716
17808
|
$("#" + ic.pre + "collections_menu").off("change");
|
|
17809
|
+
|
|
17810
|
+
if (dl_collectionAppendStructureNone.checked || ic.allData === undefined) {
|
|
17811
|
+
ic.bInputfile = false;
|
|
17812
|
+
ic.pdbCollection = {};
|
|
17813
|
+
ic.allData = {};
|
|
17814
|
+
ic.allData['all'] = {
|
|
17815
|
+
'atoms': {},
|
|
17816
|
+
'proteins': {},
|
|
17817
|
+
'nucleotides': {},
|
|
17818
|
+
'chemicals': {},
|
|
17819
|
+
'ions': {},
|
|
17820
|
+
'water': {},
|
|
17821
|
+
'structures': {}, // getSSExpandedAtoms
|
|
17822
|
+
'ssbondpnts': {},
|
|
17823
|
+
'residues': {}, // getSSExpandedAtoms
|
|
17824
|
+
'chains': {},
|
|
17825
|
+
'chainsSeq': {}, //Sequences and Annotation
|
|
17826
|
+
'defNames2Atoms': {},
|
|
17827
|
+
'defNames2Residues': {}
|
|
17828
|
+
};
|
|
17829
|
+
ic.allData['prev'] = {};
|
|
17830
|
+
ic.selectCollectionsCls.reset();
|
|
17831
|
+
|
|
17832
|
+
} else {
|
|
17833
|
+
if (ic.collections) {
|
|
17834
|
+
collection = ic.collections;
|
|
17835
|
+
}
|
|
17836
|
+
}
|
|
17717
17837
|
|
|
17718
17838
|
function parseJsonCollection(data) {
|
|
17719
17839
|
let dataStr = JSON.parse(data);
|
|
17720
|
-
|
|
17840
|
+
let parsedCollection = {};
|
|
17841
|
+
|
|
17842
|
+
dataStr["structures"].map(({ id, title, description, commands }) => {
|
|
17721
17843
|
if (id && id.includes('.pdb')) {
|
|
17722
17844
|
id = id.split('.pdb')[0];
|
|
17723
17845
|
}
|
|
17724
|
-
|
|
17846
|
+
parsedCollection[id] = [id, title, description, commands, false];
|
|
17725
17847
|
});
|
|
17726
|
-
}
|
|
17727
17848
|
|
|
17849
|
+
return parsedCollection;
|
|
17850
|
+
}
|
|
17851
|
+
|
|
17728
17852
|
function parsePdbCollection(data, description = '', commands = []) {
|
|
17729
17853
|
let dataStr = data;
|
|
17730
17854
|
let lines = dataStr.split('\n');
|
|
17731
|
-
|
|
17732
17855
|
let sections = [];
|
|
17733
17856
|
let currentSection = [];
|
|
17734
|
-
|
|
17857
|
+
|
|
17735
17858
|
lines.forEach(line => {
|
|
17736
|
-
|
|
17859
|
+
if (line.startsWith('HEADER')) {
|
|
17737
17860
|
currentSection = [];
|
|
17738
17861
|
sections.push(currentSection);
|
|
17739
|
-
|
|
17740
|
-
|
|
17862
|
+
}
|
|
17863
|
+
currentSection.push(line);
|
|
17741
17864
|
});
|
|
17742
|
-
|
|
17743
|
-
|
|
17744
|
-
let
|
|
17745
|
-
|
|
17865
|
+
|
|
17866
|
+
|
|
17867
|
+
let parsedCollection = {};
|
|
17868
|
+
|
|
17746
17869
|
sections.forEach((section) => {
|
|
17747
|
-
let headerLine = section[0];
|
|
17748
|
-
headerLine = headerLine.replace(/[\n\r]/g, '').trim();
|
|
17870
|
+
let headerLine = section[0].replace(/[\n\r]/g, '').trim();
|
|
17749
17871
|
let header = headerLine.split(' ').filter(Boolean);
|
|
17750
|
-
let
|
|
17751
|
-
|
|
17752
|
-
|
|
17872
|
+
let id = header[header.length - 1];
|
|
17873
|
+
let title = section[1].startsWith('TITLE') ? section[1].split('TITLE').pop().trim() : id;
|
|
17874
|
+
|
|
17875
|
+
parsedCollection[id] = [id, title, description, commands, true];
|
|
17876
|
+
|
|
17877
|
+
const sanitizedSection = section.map(line => line.trim());
|
|
17878
|
+
ic.pdbCollection[id] = sanitizedSection;
|
|
17753
17879
|
});
|
|
17754
|
-
|
|
17755
|
-
if (sections.length > 0) {
|
|
17756
|
-
ic.pdbCollection.push(...sections);
|
|
17757
|
-
}
|
|
17758
17880
|
|
|
17759
|
-
return
|
|
17881
|
+
return parsedCollection;
|
|
17760
17882
|
}
|
|
17761
17883
|
|
|
17762
|
-
let collection = [];
|
|
17763
|
-
|
|
17764
17884
|
if (fileExtension === 'json' || fileExtension === 'pdb') {
|
|
17765
17885
|
let reader = new FileReader();
|
|
17766
17886
|
reader.onload = async function (e) {
|
|
17767
17887
|
if (fileExtension === 'json') {
|
|
17768
|
-
|
|
17888
|
+
let jsonCollection = parseJsonCollection(e.target.result);
|
|
17889
|
+
collection = { ...collection, ...jsonCollection };
|
|
17769
17890
|
} else if (fileExtension === 'pdb') {
|
|
17770
17891
|
ic.bInputfile = true;
|
|
17771
|
-
|
|
17892
|
+
let pdbCollection = parsePdbCollection(e.target.result);
|
|
17893
|
+
collection = { ...collection, ...pdbCollection };
|
|
17772
17894
|
}
|
|
17773
17895
|
|
|
17774
17896
|
let collectionHtml = await ic.selectCollectionsCls.setAtomMenu(collection);
|
|
17775
17897
|
|
|
17898
|
+
ic.collections = collection;
|
|
17899
|
+
|
|
17776
17900
|
$("#" + ic.pre + "collections_menu").html(collectionHtml);
|
|
17777
17901
|
await ic.selectCollectionsCls.clickStructure(collection);
|
|
17778
17902
|
$("#" + ic.pre + "collections_menu").trigger("change");
|
|
@@ -17790,7 +17914,7 @@ class Events {
|
|
|
17790
17914
|
let reader2 = new FileReader();
|
|
17791
17915
|
reader2.onload = async function (e) {
|
|
17792
17916
|
if (fileExtension === 'zip') {
|
|
17793
|
-
let url = './script/jszip.js';
|
|
17917
|
+
let url = './script/jszip.min.js';
|
|
17794
17918
|
await me.getAjaxPromise(url, 'script');
|
|
17795
17919
|
|
|
17796
17920
|
let jszip = new JSZip();
|
|
@@ -17824,7 +17948,8 @@ class Events {
|
|
|
17824
17948
|
let jsonCollection = [];
|
|
17825
17949
|
for (const file of jsonFiles) {
|
|
17826
17950
|
let fileData = await file.async('text');
|
|
17827
|
-
parseJsonCollection(fileData)
|
|
17951
|
+
let parsedJson = Object.values(parseJsonCollection(fileData));
|
|
17952
|
+
parsedJson.forEach(element => {
|
|
17828
17953
|
jsonCollection.push(element);
|
|
17829
17954
|
});
|
|
17830
17955
|
}
|
|
@@ -17834,8 +17959,9 @@ class Events {
|
|
|
17834
17959
|
let matchingPdbFile = pdbFiles.find(file => file.name.toLowerCase().includes(id.toLowerCase()));
|
|
17835
17960
|
if (matchingPdbFile) {
|
|
17836
17961
|
let pdbFileData = await matchingPdbFile.async('text');
|
|
17837
|
-
parsePdbCollection(pdbFileData, description, commands)
|
|
17838
|
-
|
|
17962
|
+
let parsedPdb = Object.values(parsePdbCollection(pdbFileData, description, commands));
|
|
17963
|
+
parsedPdb.forEach(element => {
|
|
17964
|
+
collection[id] = element;
|
|
17839
17965
|
});
|
|
17840
17966
|
}
|
|
17841
17967
|
}
|
|
@@ -17844,27 +17970,30 @@ class Events {
|
|
|
17844
17970
|
// Do something if only JSON files are present
|
|
17845
17971
|
jsonFiles.forEach(async file => {
|
|
17846
17972
|
let fileData = await file.async('text');
|
|
17847
|
-
parseJsonCollection(fileData)
|
|
17848
|
-
|
|
17973
|
+
const parsedJson = Object.values(parseJsonCollection(fileData));
|
|
17974
|
+
parsedJson.forEach(element => {
|
|
17975
|
+
collection[element[0]] = element;
|
|
17849
17976
|
});
|
|
17850
17977
|
});
|
|
17851
17978
|
} else if (hasPdb) {
|
|
17852
17979
|
// Do something if only PDB files are present
|
|
17853
17980
|
pdbFiles.forEach(async file => {
|
|
17854
17981
|
let fileData = await file.async('text');
|
|
17855
|
-
|
|
17856
|
-
|
|
17982
|
+
const parsedPdb = Object.values(parsedPdbCollection(fileData));
|
|
17983
|
+
parsedPdb.forEach(element => {
|
|
17984
|
+
collection[element[0]] = element;
|
|
17857
17985
|
});
|
|
17858
17986
|
});
|
|
17859
17987
|
} else if (hasGz) {
|
|
17860
|
-
let url = './script/pako.js';
|
|
17988
|
+
let url = './script/pako.min.js';
|
|
17861
17989
|
await me.getAjaxPromise(url, 'script');
|
|
17862
17990
|
try {
|
|
17863
17991
|
for (const file of gzFiles) {
|
|
17864
17992
|
let compressed = await file.async('uint8array');
|
|
17865
17993
|
let decompressed = pako.inflate(compressed, { to: 'string' });
|
|
17866
|
-
parsePdbCollection(decompressed)
|
|
17867
|
-
|
|
17994
|
+
const parsedPdb = Object.values(parsePdbCollection(decompressed));
|
|
17995
|
+
parsedPdb.forEach(element => {
|
|
17996
|
+
collection[element[0]] = element;
|
|
17868
17997
|
});
|
|
17869
17998
|
}
|
|
17870
17999
|
} catch (error) {
|
|
@@ -17875,7 +18004,7 @@ class Events {
|
|
|
17875
18004
|
console.error('Error loading ZIP file', error);
|
|
17876
18005
|
}
|
|
17877
18006
|
} else if (fileExtension === 'gz') {
|
|
17878
|
-
let url = './script/pako.js';
|
|
18007
|
+
let url = './script/pako.min.js';
|
|
17879
18008
|
await me.getAjaxPromise(url, 'script');
|
|
17880
18009
|
|
|
17881
18010
|
try {
|
|
@@ -17892,6 +18021,8 @@ class Events {
|
|
|
17892
18021
|
$("#" + ic.pre + "collections_menu").html(collectionHtml);
|
|
17893
18022
|
await ic.selectCollectionsCls.clickStructure(collection);
|
|
17894
18023
|
|
|
18024
|
+
ic.collections = collection;
|
|
18025
|
+
|
|
17895
18026
|
$("#" + ic.pre + "collections_menu").trigger("change");
|
|
17896
18027
|
|
|
17897
18028
|
me.htmlCls.clickMenuCls.setLogCmd(
|
|
@@ -17910,7 +18041,7 @@ class Events {
|
|
|
17910
18041
|
throw new Error('Invalid file type');
|
|
17911
18042
|
}
|
|
17912
18043
|
|
|
17913
|
-
if (Object.keys(
|
|
18044
|
+
if (ic.allData && Object.keys(ic.allData).length > 0) {
|
|
17914
18045
|
$("#" + me.pre + "dl_collection_file").hide();
|
|
17915
18046
|
$("#" + me.pre + "dl_collection_structures").show();
|
|
17916
18047
|
$("#" + me.pre + "dl_collection_file_expand").show();
|
|
@@ -17931,6 +18062,17 @@ class Events {
|
|
|
17931
18062
|
}
|
|
17932
18063
|
});
|
|
17933
18064
|
|
|
18065
|
+
me.myEventCls.onIds("#" + me.pre + "collections_clear_commands", "click", function (e) {
|
|
18066
|
+
var selectedValues = $("#" + ic.pre + "collections_menu").val();
|
|
18067
|
+
selectedValues.forEach(function (selectedValue) {
|
|
18068
|
+
if (ic.allData[selectedValue]) {
|
|
18069
|
+
ic.allData[selectedValue]['commands'] = [];
|
|
18070
|
+
} else {
|
|
18071
|
+
console.warn("No data found for selectedValue:", selectedValue);
|
|
18072
|
+
}
|
|
18073
|
+
});
|
|
18074
|
+
});
|
|
18075
|
+
|
|
17934
18076
|
me.myEventCls.onIds("#" + me.pre + "opendl_export_collections", "click", function (e) {
|
|
17935
18077
|
me.htmlCls.dialogCls.openDlg("dl_export_collections", "Export Collections");
|
|
17936
18078
|
});
|
|
@@ -20417,9 +20559,9 @@ class SetHtml {
|
|
|
20417
20559
|
|
|
20418
20560
|
let pdbstr = '';
|
|
20419
20561
|
|
|
20420
|
-
let bMergeIntoOne = true;
|
|
20421
|
-
pdbstr += ic.saveFileCls.getAtomPDB(atomHash, undefined, undefined, undefined, undefined, undefined, bMergeIntoOne);
|
|
20422
|
-
pdbstr += ic.saveFileCls.getAtomPDB(ionHash, true, undefined, true);
|
|
20562
|
+
let bMergeIntoOne = true, bOneLetterChain = true;
|
|
20563
|
+
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);
|
|
20564
|
+
pdbstr += ic.saveFileCls.getAtomPDB(ionHash, true, undefined, true, undefined, undefined, bMergeIntoOne, bOneLetterChain);
|
|
20423
20565
|
|
|
20424
20566
|
let url = me.htmlCls.baseUrl + "delphi/delphi.cgi";
|
|
20425
20567
|
|
|
@@ -28123,6 +28265,8 @@ class Camera {
|
|
|
28123
28265
|
}
|
|
28124
28266
|
}
|
|
28125
28267
|
|
|
28268
|
+
// ic.cam.add(ic.directionalLight);
|
|
28269
|
+
|
|
28126
28270
|
ic.cam.updateProjectionMatrix();
|
|
28127
28271
|
// }
|
|
28128
28272
|
}
|
|
@@ -29621,687 +29765,233 @@ class Stick {
|
|
|
29621
29765
|
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
29622
29766
|
*/
|
|
29623
29767
|
|
|
29624
|
-
class
|
|
29768
|
+
class FirstAtomObj {
|
|
29625
29769
|
constructor(icn3d) {
|
|
29626
29770
|
this.icn3d = icn3d;
|
|
29627
29771
|
}
|
|
29628
29772
|
|
|
29629
|
-
//
|
|
29630
|
-
|
|
29631
|
-
|
|
29632
|
-
|
|
29633
|
-
|
|
29634
|
-
//"bHighlight" is an option to draw the highlight for these atoms. The highlight could be outlines
|
|
29635
|
-
//with bHighlight=1 and 3D objects with bHighlight=2.
|
|
29636
|
-
createStrand(atoms, num, div, fill, coilWidth, helixSheetWidth, doNotSmoothen, thickness, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
|
|
29637
|
-
if(me.bNode) return;
|
|
29773
|
+
//Return the first atom in the atom hash, which has the atom serial number as the key.
|
|
29774
|
+
getFirstAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
29775
|
+
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
29776
|
+
return undefined;
|
|
29777
|
+
}
|
|
29638
29778
|
|
|
29639
|
-
let
|
|
29779
|
+
let atomKeys = Object.keys(atomsHash);
|
|
29780
|
+
let firstIndex = atomKeys[0];
|
|
29640
29781
|
|
|
29641
|
-
|
|
29642
|
-
|
|
29643
|
-
let atomsAdjust = {};
|
|
29782
|
+
return ic.atoms[firstIndex];
|
|
29783
|
+
}
|
|
29644
29784
|
|
|
29645
|
-
|
|
29646
|
-
|
|
29647
|
-
|
|
29785
|
+
// n is the position of the selected atom
|
|
29786
|
+
getMiddleAtomObj(atomsHash, n) { let ic = this.icn3d; ic.icn3dui;
|
|
29787
|
+
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
29788
|
+
return undefined;
|
|
29648
29789
|
}
|
|
29649
|
-
|
|
29650
|
-
|
|
29790
|
+
|
|
29791
|
+
let atomKeys = Object.keys(atomsHash);
|
|
29792
|
+
let middleIndex = (n && n < atomKeys.length) ? atomKeys[n] : atomKeys[parseInt(atomKeys.length / 2)];
|
|
29793
|
+
|
|
29794
|
+
return ic.atoms[middleIndex];
|
|
29795
|
+
}
|
|
29796
|
+
|
|
29797
|
+
getFirstCalphaAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
29798
|
+
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
29799
|
+
return undefined;
|
|
29651
29800
|
}
|
|
29652
29801
|
|
|
29653
|
-
|
|
29654
|
-
|
|
29655
|
-
|
|
29656
|
-
|
|
29657
|
-
|
|
29658
|
-
|
|
29659
|
-
helixSheetWidth = null;
|
|
29660
|
-
thickness = undefined;
|
|
29802
|
+
let firstIndex;
|
|
29803
|
+
|
|
29804
|
+
for(let i in atomsHash) {
|
|
29805
|
+
if(ic.atoms[i].name == 'CA') {
|
|
29806
|
+
firstIndex = i;
|
|
29807
|
+
break;
|
|
29661
29808
|
}
|
|
29662
|
-
|
|
29663
|
-
|
|
29664
|
-
|
|
29665
|
-
|
|
29666
|
-
|
|
29667
|
-
|
|
29668
|
-
|
|
29809
|
+
}
|
|
29810
|
+
|
|
29811
|
+
if(!firstIndex) {
|
|
29812
|
+
for(let i in atomsHash) {
|
|
29813
|
+
if(ic.atoms[i].name == "O3'" || ic.atoms[i].name == "O3*") {
|
|
29814
|
+
firstIndex = i;
|
|
29815
|
+
break;
|
|
29816
|
+
}
|
|
29669
29817
|
}
|
|
29670
29818
|
}
|
|
29671
29819
|
|
|
29672
|
-
|
|
29673
|
-
|
|
29674
|
-
coilWidth = coilWidth || ic.coilWidth;
|
|
29675
|
-
doNotSmoothen = doNotSmoothen || false;
|
|
29676
|
-
helixSheetWidth = helixSheetWidth || ic.helixSheetWidth;
|
|
29677
|
-
let pnts = {}; for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
29678
|
-
let pntsCA = [];
|
|
29679
|
-
let prevCOArray = [];
|
|
29680
|
-
let bShowArray = [];
|
|
29681
|
-
let calphaIdArray = []; // used to store one of the final positions drawn in 3D
|
|
29682
|
-
let colors = [];
|
|
29683
|
-
let currentChain, currentResi, currentCA = null, currentO = null, currentColor = null, prevCoorCA = null, prevCoorO = null, prevColor = null;
|
|
29684
|
-
let prevCO = null, ss = null, ssend = false, atomid = null, prevAtomid = null, prevAtomSelected = null, prevResi = null, calphaid = null, prevCalphaid = null;
|
|
29685
|
-
let strandWidth, bSheetSegment = false, bHelixSegment = false;
|
|
29820
|
+
return (firstIndex !== undefined) ? ic.atoms[firstIndex] : this.getFirstAtomObj(atomsHash);
|
|
29821
|
+
}
|
|
29686
29822
|
|
|
29687
|
-
|
|
29688
|
-
|
|
29689
|
-
|
|
29690
|
-
let atoms = me.hashUtilsCls.hash2Atoms(ic.chains[chainid], ic.atoms);
|
|
29691
|
-
let bCalphaOnly = me.utilsCls.isCalphaPhosOnly(atoms); //, 'CA');
|
|
29692
|
-
bCalphaOnlyHash[chainid] = bCalphaOnly;
|
|
29823
|
+
getFirstAtomObjByName(atomsHash, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
29824
|
+
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
29825
|
+
return ic.atoms[0];
|
|
29693
29826
|
}
|
|
29694
29827
|
|
|
29695
|
-
|
|
29696
|
-
let residueHash = {};
|
|
29697
|
-
for(let i in atomsAdjust) {
|
|
29698
|
-
let atom = ic.atoms[i];
|
|
29828
|
+
let firstIndex;
|
|
29699
29829
|
|
|
29700
|
-
|
|
29701
|
-
|
|
29830
|
+
for(let i in atomsHash) {
|
|
29831
|
+
if(ic.atoms[i].name == atomName) {
|
|
29832
|
+
firstIndex = i;
|
|
29833
|
+
break;
|
|
29834
|
+
}
|
|
29702
29835
|
}
|
|
29703
|
-
Object.keys(residueHash).length;
|
|
29704
|
-
|
|
29705
|
-
let bFullAtom = (Object.keys(ic.hAtoms).length == Object.keys(ic.atoms).length) ? true : false;
|
|
29706
29836
|
|
|
29707
|
-
|
|
29837
|
+
return (firstIndex !== undefined) ? ic.atoms[firstIndex] : undefined;
|
|
29838
|
+
}
|
|
29708
29839
|
|
|
29709
|
-
|
|
29840
|
+
//Return the last atom in the atom hash, which has the atom serial number as the key.
|
|
29841
|
+
getLastAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
29842
|
+
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
29843
|
+
return ic.atoms[0];
|
|
29844
|
+
}
|
|
29710
29845
|
|
|
29711
|
-
|
|
29712
|
-
let
|
|
29713
|
-
let lastAtomSerial = atomArray[atomArray.length - 1];
|
|
29714
|
-
let lastAtom = ic.atoms[lastAtomSerial];
|
|
29715
|
-
let lastResid = lastAtom.structure + '_' + lastAtom.chain + '_' + lastAtom.resi;
|
|
29846
|
+
let atomKeys = Object.keys(atomsHash);
|
|
29847
|
+
let lastIndex = atomKeys[atomKeys.length - 1];
|
|
29716
29848
|
|
|
29717
|
-
|
|
29718
|
-
|
|
29719
|
-
let chainid = atom.structure + '_' + atom.chain;
|
|
29720
|
-
let resid = atom.structure + '_' + atom.chain + '_' + atom.resi;
|
|
29721
|
-
if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
|
|
29722
|
-
// "CA" has to appear before "O"
|
|
29849
|
+
return ic.atoms[lastIndex];
|
|
29850
|
+
}
|
|
29723
29851
|
|
|
29724
|
-
|
|
29725
|
-
|
|
29852
|
+
//Return the residue hash from the atom hash. The residue hash has the resid as the key and 1 as the value.
|
|
29853
|
+
getResiduesFromAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
29854
|
+
let residuesHash = {};
|
|
29855
|
+
for(let i in atomsHash) {
|
|
29856
|
+
let residueid = ic.atoms[i].structure + '_' + ic.atoms[i].chain + '_' + ic.atoms[i].resi;
|
|
29857
|
+
residuesHash[residueid] = 1;
|
|
29858
|
+
}
|
|
29726
29859
|
|
|
29727
|
-
|
|
29728
|
-
|
|
29729
|
-
calphaid = atom.serial;
|
|
29860
|
+
return residuesHash;
|
|
29861
|
+
}
|
|
29730
29862
|
|
|
29731
|
-
|
|
29863
|
+
getResiduesFromCalphaAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
29864
|
+
let residuesHash = {};
|
|
29865
|
+
for(let i in atomsHash) {
|
|
29866
|
+
if((ic.atoms[i].name == 'CA' && ic.proteins.hasOwnProperty(i)) || !ic.proteins.hasOwnProperty(i)) {
|
|
29867
|
+
let residueid = ic.atoms[i].structure + '_' + ic.atoms[i].chain + '_' + ic.atoms[i].resi;
|
|
29868
|
+
//residuesHash[residueid] = 1;
|
|
29869
|
+
residuesHash[residueid] = ic.atoms[i].resn;
|
|
29732
29870
|
}
|
|
29871
|
+
}
|
|
29733
29872
|
|
|
29734
|
-
|
|
29735
|
-
|
|
29736
|
-
currentCA = atom.coord;
|
|
29737
|
-
currentColor = atom.color;
|
|
29738
|
-
calphaid = atom.serial;
|
|
29739
|
-
}
|
|
29873
|
+
return residuesHash;
|
|
29874
|
+
}
|
|
29740
29875
|
|
|
29741
|
-
|
|
29742
|
-
|
|
29743
|
-
|
|
29744
|
-
|
|
29745
|
-
|
|
29746
|
-
|
|
29747
|
-
// if (currentChain !== atom.chain) {
|
|
29748
|
-
// //if (currentChain !== atom.chain) {
|
|
29749
|
-
// bSameChain = false;
|
|
29750
|
-
// }
|
|
29876
|
+
//Return the chain hash from the atom hash. The chain hash has the chainid as the key and 1 as the value.
|
|
29877
|
+
getChainsFromAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
29878
|
+
let chainsHash = {};
|
|
29879
|
+
for(let i in atomsHash) {
|
|
29880
|
+
let atom = ic.atoms[i];
|
|
29881
|
+
let chainid = atom.structure + "_" + atom.chain;
|
|
29751
29882
|
|
|
29752
|
-
|
|
29753
|
-
|
|
29754
|
-
}
|
|
29755
|
-
else if( (atom.ssend && atom.ss === 'helix') || resid == lastResid) { // partial sheet will draw as helix
|
|
29756
|
-
bHelixSegment = true;
|
|
29757
|
-
}
|
|
29883
|
+
chainsHash[chainid] = 1;
|
|
29884
|
+
}
|
|
29758
29885
|
|
|
29759
|
-
|
|
29760
|
-
|
|
29761
|
-
if(bHighlight === 1 || bHighlight === 2) {
|
|
29762
|
-
colors.push(ic.hColor);
|
|
29763
|
-
}
|
|
29764
|
-
else {
|
|
29765
|
-
colors.push(prevColor);
|
|
29766
|
-
}
|
|
29886
|
+
return chainsHash;
|
|
29887
|
+
}
|
|
29767
29888
|
|
|
29768
|
-
|
|
29769
|
-
|
|
29770
|
-
|
|
29771
|
-
|
|
29772
|
-
|
|
29773
|
-
|
|
29774
|
-
|
|
29775
|
-
|
|
29776
|
-
}
|
|
29889
|
+
getAtomFromResi(resid, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
29890
|
+
if(ic.residues.hasOwnProperty(resid)) {
|
|
29891
|
+
for(let i in ic.residues[resid]) {
|
|
29892
|
+
if(ic.atoms[i].name === atomName && !ic.atoms[i].het) {
|
|
29893
|
+
return ic.atoms[i];
|
|
29894
|
+
}
|
|
29895
|
+
}
|
|
29896
|
+
}
|
|
29777
29897
|
|
|
29778
|
-
|
|
29779
|
-
|
|
29780
|
-
O = prevCoorO.clone();
|
|
29781
|
-
if(prevCoorCA !== null && prevCoorCA !== undefined) {
|
|
29782
|
-
O.sub(prevCoorCA);
|
|
29783
|
-
}
|
|
29784
|
-
else {
|
|
29785
|
-
prevCoorCA = prevCoorO.clone();
|
|
29786
|
-
if(caArray.length > resSpan + 1) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
29787
|
-
O = prevCoorCA.clone();
|
|
29788
|
-
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan - 1]].coord.clone();
|
|
29789
|
-
//O.sub(oldCA);
|
|
29790
|
-
oldCA.sub(O);
|
|
29791
|
-
}
|
|
29792
|
-
else {
|
|
29793
|
-
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
29794
|
-
}
|
|
29795
|
-
}
|
|
29796
|
-
}
|
|
29797
|
-
else if(bCalphaOnlyHash[chainid] && atom.name === 'CA') {
|
|
29798
|
-
if(caArray.length > resSpan + 1) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
29799
|
-
O = prevCoorCA.clone();
|
|
29800
|
-
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan - 1]].coord.clone();
|
|
29801
|
-
//O.sub(oldCA);
|
|
29802
|
-
oldCA.sub(O);
|
|
29803
|
-
}
|
|
29804
|
-
else {
|
|
29805
|
-
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
29806
|
-
}
|
|
29807
|
-
}
|
|
29898
|
+
return undefined;
|
|
29899
|
+
}
|
|
29808
29900
|
|
|
29809
|
-
|
|
29810
|
-
|
|
29811
|
-
|
|
29812
|
-
|
|
29901
|
+
getAtomCoordFromResi(resid, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
29902
|
+
let atom = this.getAtomFromResi(resid, atomName);
|
|
29903
|
+
if(atom !== undefined) {
|
|
29904
|
+
let coord = (atom.coord2 !== undefined) ? atom.coord2 : atom.coord;
|
|
29813
29905
|
|
|
29814
|
-
|
|
29815
|
-
|
|
29816
|
-
let v = new THREE.Vector3(prevCoorCA.x + prevCO.x * delta, prevCoorCA.y + prevCO.y * delta, prevCoorCA.z + prevCO.z * delta);
|
|
29817
|
-
if (!doNotSmoothen && ss === 'sheet') v.smoothen = true;
|
|
29818
|
-
pnts[j].push(v);
|
|
29819
|
-
}
|
|
29906
|
+
return coord;
|
|
29907
|
+
}
|
|
29820
29908
|
|
|
29821
|
-
|
|
29822
|
-
|
|
29909
|
+
return undefined;
|
|
29910
|
+
}
|
|
29911
|
+
}
|
|
29823
29912
|
|
|
29824
|
-
|
|
29825
|
-
|
|
29826
|
-
|
|
29827
|
-
}
|
|
29828
|
-
else {
|
|
29829
|
-
bShowArray.push(0);
|
|
29830
|
-
calphaIdArray.push(0);
|
|
29831
|
-
}
|
|
29832
|
-
}
|
|
29913
|
+
/**
|
|
29914
|
+
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
29915
|
+
*/
|
|
29833
29916
|
|
|
29834
|
-
|
|
29917
|
+
class Strip {
|
|
29918
|
+
constructor(icn3d) {
|
|
29919
|
+
this.icn3d = icn3d;
|
|
29920
|
+
}
|
|
29835
29921
|
|
|
29836
|
-
|
|
29837
|
-
|
|
29838
|
-
|
|
29839
|
-
|
|
29840
|
-
// check whether the atoms are continuous
|
|
29841
|
-
// atomsAdjusted has all atoms in the secondary structure
|
|
29842
|
-
// atoms has all selected atoms
|
|
29843
|
-
// let bBrokenSs = false;
|
|
29844
|
-
// if(prevAtomSelected && prevAtomid == prevAtomSelected.serial && !atoms.hasOwnProperty(atom.serial)) {
|
|
29845
|
-
// bBrokenSs = true;
|
|
29846
|
-
// }
|
|
29922
|
+
// modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
29923
|
+
createStrip(p0, p1, colors, div, thickness, bHighlight, bNoSmoothen, bShowArray,
|
|
29924
|
+
calphaIdArray, positions, prevone, nexttwo, pntsCA, prevCOArray) { let ic = this.icn3d, me = ic.icn3dui;
|
|
29925
|
+
if(me.bNode) return;
|
|
29847
29926
|
|
|
29927
|
+
if (p0.length < 2) return;
|
|
29928
|
+
div = div || ic.axisDIV;
|
|
29848
29929
|
|
|
29849
|
-
|
|
29850
|
-
|
|
29930
|
+
// if(pntsCA && ic.bDoublecolor && !ic.bCalphaOnly) {
|
|
29931
|
+
if(pntsCA && ic.bDoublecolor) {
|
|
29932
|
+
let bExtendLastRes = false; //true;
|
|
29851
29933
|
|
|
29852
|
-
|
|
29853
|
-
|
|
29854
|
-
// }
|
|
29855
|
-
// else if(bBrokenSs && atom.ss === 'helix') {
|
|
29856
|
-
// bHelixSegment = true;
|
|
29857
|
-
// }
|
|
29934
|
+
let pnts_clrs = me.subdivideCls.subdivide(pntsCA, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29935
|
+
pntsCA = pnts_clrs[0];
|
|
29858
29936
|
|
|
29859
|
-
|
|
29860
|
-
// 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
|
|
29937
|
+
this.setCalphaDrawnCoord(pntsCA, div, calphaIdArray);
|
|
29861
29938
|
|
|
29862
|
-
|
|
29863
|
-
|
|
29864
|
-
|
|
29865
|
-
let prevone = [], nexttwo = [];
|
|
29939
|
+
for(let i = 0, il = prevCOArray.length; i < il; ++i) {
|
|
29940
|
+
prevCOArray[i].normalize();
|
|
29941
|
+
}
|
|
29866
29942
|
|
|
29867
|
-
|
|
29868
|
-
|
|
29869
|
-
}
|
|
29870
|
-
else {
|
|
29871
|
-
let prevoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) - 1).toString();
|
|
29872
|
-
let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
|
|
29873
|
-
prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
|
|
29874
|
-
}
|
|
29943
|
+
let pnts_clrs2 = me.subdivideCls.subdivide(prevCOArray, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29944
|
+
prevCOArray = pnts_clrs2[0];
|
|
29875
29945
|
|
|
29876
|
-
|
|
29877
|
-
|
|
29878
|
-
|
|
29879
|
-
if(nextoneCoord !== undefined) {
|
|
29880
|
-
nexttwo.push(nextoneCoord);
|
|
29881
|
-
}
|
|
29946
|
+
colors = pnts_clrs[2];
|
|
29947
|
+
}
|
|
29948
|
+
else {
|
|
29882
29949
|
|
|
29883
|
-
|
|
29884
|
-
|
|
29885
|
-
|
|
29886
|
-
|
|
29887
|
-
|
|
29888
|
-
|
|
29950
|
+
if(!bNoSmoothen) {
|
|
29951
|
+
//var bExtendLastRes = true;
|
|
29952
|
+
let bExtendLastRes = false;
|
|
29953
|
+
let pnts_clrs0 = me.subdivideCls.subdivide(p0, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29954
|
+
let pnts_clrs1 = me.subdivideCls.subdivide(p1, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29955
|
+
p0 = pnts_clrs0[0];
|
|
29956
|
+
p1 = pnts_clrs1[0];
|
|
29957
|
+
colors = pnts_clrs0[2];
|
|
29958
|
+
}
|
|
29959
|
+
if (p0.length < 2) return;
|
|
29889
29960
|
|
|
29890
|
-
|
|
29891
|
-
|
|
29892
|
-
// assign the current joint residue to the previous segment
|
|
29893
|
-
if(bHighlight === 1 || bHighlight === 2) {
|
|
29894
|
-
colors.push(ic.hColor);
|
|
29895
|
-
}
|
|
29896
|
-
else {
|
|
29897
|
-
//colors.push(atom.color);
|
|
29898
|
-
colors.push(prevColor);
|
|
29899
|
-
}
|
|
29961
|
+
this.setCalphaDrawnCoord(p0, div, calphaIdArray);
|
|
29962
|
+
}
|
|
29900
29963
|
|
|
29901
|
-
|
|
29902
|
-
|
|
29903
|
-
}
|
|
29904
|
-
else if(ss === 'coil' && atom.ssbegin) {
|
|
29905
|
-
strandWidth = coilWidth;
|
|
29906
|
-
}
|
|
29907
|
-
else if(ssend && atom.ssbegin) { // current residue is the start of ss and the previous residue is the end of ss, then use coil
|
|
29908
|
-
strandWidth = coilWidth;
|
|
29909
|
-
}
|
|
29910
|
-
else { // use the ss from the previous residue
|
|
29911
|
-
strandWidth = (atom.ss === 'coil') ? coilWidth : helixSheetWidth;
|
|
29912
|
-
}
|
|
29964
|
+
if(bHighlight === 1) {
|
|
29965
|
+
//mesh = new THREE.Mesh(geo, ic.matShader);
|
|
29913
29966
|
|
|
29914
|
-
|
|
29915
|
-
|
|
29916
|
-
|
|
29917
|
-
|
|
29918
|
-
}
|
|
29919
|
-
else if(bCalphaOnlyHash[chainid] && atom.name === 'CA') {
|
|
29920
|
-
if(caArray.length > resSpan) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
29921
|
-
O = currentCA.clone();
|
|
29922
|
-
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan]].coord.clone();
|
|
29923
|
-
//O.sub(oldCA);
|
|
29924
|
-
oldCA.sub(O);
|
|
29925
|
-
}
|
|
29926
|
-
else {
|
|
29927
|
-
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
29928
|
-
}
|
|
29929
|
-
}
|
|
29967
|
+
let radius = ic.coilWidth / 2;
|
|
29968
|
+
//var radiusSegments = 8;
|
|
29969
|
+
let radiusSegments = 4; // save memory
|
|
29970
|
+
let closed = false;
|
|
29930
29971
|
|
|
29931
|
-
|
|
29932
|
-
|
|
29933
|
-
|
|
29934
|
-
prevCO = O;
|
|
29972
|
+
if(positions !== undefined) {
|
|
29973
|
+
let currPos, prevPos;
|
|
29974
|
+
let currP0 = [], currP1 = [];
|
|
29935
29975
|
|
|
29936
|
-
|
|
29937
|
-
|
|
29938
|
-
let v = new THREE.Vector3(currentCA.x + prevCO.x * delta, currentCA.y + prevCO.y * delta, currentCA.z + prevCO.z * delta);
|
|
29939
|
-
if (!doNotSmoothen && ss === 'sheet') v.smoothen = true;
|
|
29940
|
-
pnts[j].push(v);
|
|
29941
|
-
}
|
|
29976
|
+
for(let i = 0, il = p0.length; i < il; ++i) {
|
|
29977
|
+
currPos = positions[i];
|
|
29942
29978
|
|
|
29943
|
-
|
|
29979
|
+
if((currPos !== prevPos && parseInt(currPos) !== parseInt(prevPos) + 1 && prevPos !== undefined) || (i === il -1) ) {
|
|
29980
|
+
// first tube
|
|
29981
|
+
let geometry0 = new THREE.TubeGeometry(
|
|
29982
|
+
new THREE.CatmullRomCurve3(currP0), // path
|
|
29983
|
+
currP0.length, // segments
|
|
29984
|
+
radius,
|
|
29985
|
+
radiusSegments,
|
|
29986
|
+
closed
|
|
29987
|
+
);
|
|
29944
29988
|
|
|
29945
|
-
|
|
29946
|
-
|
|
29989
|
+
let mesh = new THREE.Mesh(geometry0, ic.matShader);
|
|
29990
|
+
mesh.renderOrder = ic.renderOrderPicking;
|
|
29991
|
+
//ic.mdlPicking.add(mesh);
|
|
29992
|
+
ic.mdl.add(mesh);
|
|
29947
29993
|
|
|
29948
|
-
|
|
29949
|
-
//if(atoms.hasOwnProperty(atomid) && (bHighlight === 1 && !atom.notshow) ) {
|
|
29950
|
-
if(atoms.hasOwnProperty(atomid)) {
|
|
29951
|
-
bShowArray.push(atom.resi);
|
|
29952
|
-
calphaIdArray.push(calphaid);
|
|
29953
|
-
}
|
|
29954
|
-
else {
|
|
29955
|
-
bShowArray.push(0);
|
|
29956
|
-
calphaIdArray.push(0);
|
|
29957
|
-
}
|
|
29958
|
-
}
|
|
29959
|
-
|
|
29960
|
-
// draw the current segment
|
|
29961
|
-
for (let j = 0; !fill && j < num; ++j) {
|
|
29962
|
-
if(bSheetSegment) {
|
|
29963
|
-
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
29964
|
-
}
|
|
29965
|
-
else if(bHelixSegment) {
|
|
29966
|
-
if(bFullAtom) {
|
|
29967
|
-
ic.curveCls.createCurveSub(pnts[j], 1, colors, div, bHighlight, bRibbon, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo);
|
|
29968
|
-
}
|
|
29969
|
-
else {
|
|
29970
|
-
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
29971
|
-
}
|
|
29972
|
-
}
|
|
29973
|
-
}
|
|
29974
|
-
if (fill) {
|
|
29975
|
-
if(bSheetSegment) {
|
|
29976
|
-
let start = 0, end = num - 1;
|
|
29977
|
-
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
29978
|
-
}
|
|
29979
|
-
else if(bHelixSegment) {
|
|
29980
|
-
if(bFullAtom) {
|
|
29981
|
-
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
29982
|
-
}
|
|
29983
|
-
else {
|
|
29984
|
-
let start = 0, end = num - 1;
|
|
29985
|
-
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
29986
|
-
}
|
|
29987
|
-
}
|
|
29988
|
-
else {
|
|
29989
|
-
if(bHighlight === 2) { // draw coils only when highlighted. if not highlighted, coils will be drawn as tubes separately
|
|
29990
|
-
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
29991
|
-
}
|
|
29992
|
-
}
|
|
29993
|
-
}
|
|
29994
|
-
for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
29995
|
-
|
|
29996
|
-
colors = [];
|
|
29997
|
-
pntsCA = [];
|
|
29998
|
-
prevCOArray = [];
|
|
29999
|
-
bShowArray = [];
|
|
30000
|
-
calphaIdArray = [];
|
|
30001
|
-
bSheetSegment = false;
|
|
30002
|
-
bHelixSegment = false;
|
|
30003
|
-
} // end if (atom.ssbegin || atom.ssend)
|
|
30004
|
-
|
|
30005
|
-
// end of a chain, or end of selection
|
|
30006
|
-
if ((currentChain !== atom.chain
|
|
30007
|
-
|| ic.ParserUtilsCls.getResiNCBI(atom.structure + '_' + currentChain, currentResi) + 1 !== ic.ParserUtilsCls.getResiNCBI(chainid, atom.resi)
|
|
30008
|
-
// || (drawnResidueCount === totalResidueCount - 1)
|
|
30009
|
-
// || bBrokenSs
|
|
30010
|
-
|| (resid == lastResid && atom.ss != 'coil')
|
|
30011
|
-
) && pnts[0].length > 0) {
|
|
30012
|
-
//if ((currentChain !== atom.chain) && pnts[0].length > 0) {
|
|
30013
|
-
|
|
30014
|
-
let atomName = 'CA';
|
|
30015
|
-
|
|
30016
|
-
let prevone = [], nexttwo = [];
|
|
30017
|
-
if(isNaN(ic.atoms[prevAtomid].resi)) {
|
|
30018
|
-
prevone = [];
|
|
30019
|
-
}
|
|
30020
|
-
else {
|
|
30021
|
-
let prevoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) - 1).toString();
|
|
30022
|
-
ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
|
|
30023
|
-
}
|
|
30024
|
-
|
|
30025
|
-
for (let j = 0; !fill && j < num; ++j) {
|
|
30026
|
-
if(bSheetSegment) {
|
|
30027
|
-
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
30028
|
-
}
|
|
30029
|
-
else if(bHelixSegment) {
|
|
30030
|
-
if(bFullAtom) {
|
|
30031
|
-
ic.curveCls.createCurveSub(pnts[j], 1, colors, div, bHighlight, bRibbon, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo);
|
|
30032
|
-
}
|
|
30033
|
-
else {
|
|
30034
|
-
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
30035
|
-
}
|
|
30036
|
-
}
|
|
30037
|
-
}
|
|
30038
|
-
if (fill) {
|
|
30039
|
-
if(bSheetSegment) {
|
|
30040
|
-
let start = 0, end = num - 1;
|
|
30041
|
-
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
30042
|
-
}
|
|
30043
|
-
else if(bHelixSegment) {
|
|
30044
|
-
if(bFullAtom) {
|
|
30045
|
-
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
30046
|
-
}
|
|
30047
|
-
else {
|
|
30048
|
-
let start = 0, end = num - 1;
|
|
30049
|
-
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
30050
|
-
}
|
|
30051
|
-
}
|
|
30052
|
-
}
|
|
30053
|
-
|
|
30054
|
-
for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
30055
|
-
colors = [];
|
|
30056
|
-
pntsCA = [];
|
|
30057
|
-
prevCOArray = [];
|
|
30058
|
-
bShowArray = [];
|
|
30059
|
-
calphaIdArray = [];
|
|
30060
|
-
bSheetSegment = false;
|
|
30061
|
-
bHelixSegment = false;
|
|
30062
|
-
}
|
|
30063
|
-
|
|
30064
|
-
currentChain = atom.chain;
|
|
30065
|
-
currentResi = atom.resi;
|
|
30066
|
-
ss = atom.ss;
|
|
30067
|
-
ssend = atom.ssend;
|
|
30068
|
-
prevAtomid = atom.serial;
|
|
30069
|
-
if(atoms.hasOwnProperty(atom.serial)) prevAtomSelected = atom;
|
|
30070
|
-
prevResi = atom.resi;
|
|
30071
|
-
|
|
30072
|
-
prevCalphaid = calphaid;
|
|
30073
|
-
|
|
30074
|
-
// only update when atom.name === 'O'
|
|
30075
|
-
prevCoorCA = currentCA;
|
|
30076
|
-
prevCoorO = atom.coord;
|
|
30077
|
-
prevColor = currentColor;
|
|
30078
|
-
} // end if (atom.name === 'O' || (bCalphaOnlyHash[chainid] && atom.name === 'CA') ) {
|
|
30079
|
-
} // end if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
|
|
30080
|
-
} // end for
|
|
30081
|
-
|
|
30082
|
-
caArray = [];
|
|
30083
|
-
|
|
30084
|
-
// ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight);
|
|
30085
|
-
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
30086
|
-
ic.tubeCls.createTube(atomsAdjust, 'CA', coilWidth, bHighlight);
|
|
30087
|
-
pnts = {};
|
|
30088
|
-
}
|
|
30089
|
-
|
|
30090
|
-
getOneExtraResidue(residueHash) { let ic = this.icn3d, me = ic.icn3dui;
|
|
30091
|
-
let atomsAdjust = {};
|
|
30092
|
-
|
|
30093
|
-
for(let resid in residueHash) {
|
|
30094
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, ic.residues[resid]);
|
|
30095
|
-
|
|
30096
|
-
let residNcbi = ic.resid2ncbi[resid];
|
|
30097
|
-
let resiNcbi = residNcbi.substr(residNcbi.lastIndexOf('_') + 1);
|
|
30098
|
-
|
|
30099
|
-
let nextResidNcbi = residNcbi.substr(0, residNcbi.lastIndexOf('_')) + '_' + (parseInt(resiNcbi) + 1);
|
|
30100
|
-
let nextResid = ic.ncbi2resid[nextResidNcbi];
|
|
30101
|
-
|
|
30102
|
-
if(!nextResid) {
|
|
30103
|
-
nextResidNcbi = residNcbi.substr(0, residNcbi.lastIndexOf('_')) + '_' + (parseInt(resiNcbi) - 1);
|
|
30104
|
-
nextResid = ic.ncbi2resid[nextResidNcbi];
|
|
30105
|
-
}
|
|
30106
|
-
|
|
30107
|
-
if(nextResid) atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, ic.residues[nextResid]);
|
|
30108
|
-
}
|
|
30109
|
-
|
|
30110
|
-
return atomsAdjust;
|
|
30111
|
-
}
|
|
30112
|
-
|
|
30113
|
-
/*
|
|
30114
|
-
getSSExpandedAtoms(atoms, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
|
|
30115
|
-
let currChain, currResi, currAtom, prevChain, prevResi, prevAtom;
|
|
30116
|
-
let firstAtom, lastAtom;
|
|
30117
|
-
let index = 0, length = Object.keys(atoms).length;
|
|
30118
|
-
|
|
30119
|
-
let atomsAdjust = me.hashUtilsCls.cloneHash(atoms);
|
|
30120
|
-
for(let serial in atoms) {
|
|
30121
|
-
currChain = atoms[serial].structure + '_' + atoms[serial].chain;
|
|
30122
|
-
currResi = atoms[serial].resi; //parseInt(atoms[serial].resi);
|
|
30123
|
-
currAtom = atoms[serial];
|
|
30124
|
-
|
|
30125
|
-
if(prevChain === undefined) firstAtom = atoms[serial];
|
|
30126
|
-
|
|
30127
|
-
if( (currChain !== prevChain && prevChain !== undefined)
|
|
30128
|
-
|| (currResi !== prevResi && ic.resid2ncbi[currResi] !== ic.resid2ncbi[prevResi] + 1 && prevResi !== undefined) || index === length - 1) {
|
|
30129
|
-
if( (currChain !== prevChain && prevChain !== undefined)
|
|
30130
|
-
|| (currResi !== prevResi && currResi !== ic.resid2ncbi[prevResi] + 1 && prevResi !== undefined) ) {
|
|
30131
|
-
lastAtom = prevAtom;
|
|
30132
|
-
}
|
|
30133
|
-
else if(index === length - 1) {
|
|
30134
|
-
lastAtom = currAtom;
|
|
30135
|
-
}
|
|
30136
|
-
|
|
30137
|
-
// fill the beginning
|
|
30138
|
-
let beginResi = firstAtom.resi;
|
|
30139
|
-
if(!isNaN(firstAtom.resi) && firstAtom.ss !== 'coil' && !(firstAtom.ssbegin) ) {
|
|
30140
|
-
for(let i = parseInt(firstAtom.resi) - 1; i > 0; --i) {
|
|
30141
|
-
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + i;
|
|
30142
|
-
if(!ic.residues.hasOwnProperty(residueid)) break;
|
|
30143
|
-
|
|
30144
|
-
let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[residueid]);
|
|
30145
|
-
|
|
30146
|
-
if(atom.ss === firstAtom.ss && atom.ssbegin) {
|
|
30147
|
-
beginResi = atom.resi;
|
|
30148
|
-
break;
|
|
30149
|
-
}
|
|
30150
|
-
}
|
|
30151
|
-
|
|
30152
|
-
for(let i = beginResi; i < firstAtom.resi; ++i) {
|
|
30153
|
-
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + i;
|
|
30154
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
30155
|
-
ic.atoms));
|
|
30156
|
-
}
|
|
30157
|
-
}
|
|
30158
|
-
|
|
30159
|
-
// add one extra residue for coils between strands/helix
|
|
30160
|
-
if(!isNaN(firstAtom.resi) && ic.pk === 3 && bHighlight === 1 && firstAtom.ss === 'coil') {
|
|
30161
|
-
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
|
|
30162
|
-
if(ic.residues.hasOwnProperty(residueid)) {
|
|
30163
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
30164
|
-
ic.atoms));
|
|
30165
|
-
atoms = me.hashUtilsCls.unionHash(atoms, me.hashUtilsCls.hash2Atoms(ic.residues[residueid], ic.atoms));
|
|
30166
|
-
}
|
|
30167
|
-
}
|
|
30168
|
-
|
|
30169
|
-
// fill the end
|
|
30170
|
-
let endResi = lastAtom.resi;
|
|
30171
|
-
// 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.
|
|
30172
|
-
|
|
30173
|
-
if(lastAtom.ss !== undefined && lastAtom.ss !== 'coil' && !(lastAtom.ssend) && !(lastAtom.notshow)) {
|
|
30174
|
-
|
|
30175
|
-
let endChainResi = ic.firstAtomObjCls.getLastAtomObj(ic.chains[lastAtom.structure + '_' + lastAtom.chain]).resi;
|
|
30176
|
-
for(let i = parseInt(lastAtom.resi) + 1; i <= parseInt(endChainResi); ++i) {
|
|
30177
|
-
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + i;
|
|
30178
|
-
if(!ic.residues.hasOwnProperty(residueid)) break;
|
|
30179
|
-
|
|
30180
|
-
let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[residueid]);
|
|
30181
|
-
|
|
30182
|
-
if(atom.ss === lastAtom.ss && atom.ssend) {
|
|
30183
|
-
endResi = atom.resi;
|
|
30184
|
-
break;
|
|
30185
|
-
}
|
|
30186
|
-
}
|
|
30187
|
-
|
|
30188
|
-
for(let i = parseInt(lastAtom.resi) + 1; i <= parseInt(endResi); ++i) {
|
|
30189
|
-
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + i;
|
|
30190
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
30191
|
-
ic.atoms));
|
|
30192
|
-
}
|
|
30193
|
-
}
|
|
30194
|
-
|
|
30195
|
-
// add one extra residue for coils between strands/helix
|
|
30196
|
-
if(ic.pk === 3 && bHighlight === 1 && lastAtom.ss === 'coil') {
|
|
30197
|
-
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + (parseInt(lastAtom.resi) + 1).toString();
|
|
30198
|
-
if(ic.residues.hasOwnProperty(residueid)) {
|
|
30199
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
30200
|
-
ic.atoms));
|
|
30201
|
-
atoms = me.hashUtilsCls.unionHash(atoms, me.hashUtilsCls.hash2Atoms(ic.residues[residueid], ic.atoms));
|
|
30202
|
-
}
|
|
30203
|
-
}
|
|
30204
|
-
|
|
30205
|
-
// reset notshow
|
|
30206
|
-
if(lastAtom.notshow) lastAtom.notshow = undefined;
|
|
30207
|
-
|
|
30208
|
-
firstAtom = currAtom;
|
|
30209
|
-
}
|
|
30210
|
-
|
|
30211
|
-
prevChain = currChain;
|
|
30212
|
-
prevResi = currResi;
|
|
30213
|
-
prevAtom = currAtom;
|
|
30214
|
-
|
|
30215
|
-
++index;
|
|
30216
|
-
}
|
|
30217
|
-
|
|
30218
|
-
return atomsAdjust;
|
|
30219
|
-
}
|
|
30220
|
-
*/
|
|
30221
|
-
}
|
|
30222
|
-
|
|
30223
|
-
/**
|
|
30224
|
-
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
30225
|
-
*/
|
|
30226
|
-
|
|
30227
|
-
class Strip {
|
|
30228
|
-
constructor(icn3d) {
|
|
30229
|
-
this.icn3d = icn3d;
|
|
30230
|
-
}
|
|
30231
|
-
|
|
30232
|
-
// modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
30233
|
-
createStrip(p0, p1, colors, div, thickness, bHighlight, bNoSmoothen, bShowArray,
|
|
30234
|
-
calphaIdArray, positions, prevone, nexttwo, pntsCA, prevCOArray) { let ic = this.icn3d, me = ic.icn3dui;
|
|
30235
|
-
if(me.bNode) return;
|
|
30236
|
-
|
|
30237
|
-
if (p0.length < 2) return;
|
|
30238
|
-
div = div || ic.axisDIV;
|
|
30239
|
-
|
|
30240
|
-
// if(pntsCA && ic.bDoublecolor && !ic.bCalphaOnly) {
|
|
30241
|
-
if(pntsCA && ic.bDoublecolor) {
|
|
30242
|
-
let bExtendLastRes = false; //true;
|
|
30243
|
-
|
|
30244
|
-
let pnts_clrs = me.subdivideCls.subdivide(pntsCA, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
30245
|
-
pntsCA = pnts_clrs[0];
|
|
30246
|
-
|
|
30247
|
-
this.setCalphaDrawnCoord(pntsCA, div, calphaIdArray);
|
|
30248
|
-
|
|
30249
|
-
for(let i = 0, il = prevCOArray.length; i < il; ++i) {
|
|
30250
|
-
prevCOArray[i].normalize();
|
|
30251
|
-
}
|
|
30252
|
-
|
|
30253
|
-
let pnts_clrs2 = me.subdivideCls.subdivide(prevCOArray, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
30254
|
-
prevCOArray = pnts_clrs2[0];
|
|
30255
|
-
|
|
30256
|
-
colors = pnts_clrs[2];
|
|
30257
|
-
}
|
|
30258
|
-
else {
|
|
30259
|
-
|
|
30260
|
-
if(!bNoSmoothen) {
|
|
30261
|
-
//var bExtendLastRes = true;
|
|
30262
|
-
let bExtendLastRes = false;
|
|
30263
|
-
let pnts_clrs0 = me.subdivideCls.subdivide(p0, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
30264
|
-
let pnts_clrs1 = me.subdivideCls.subdivide(p1, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
30265
|
-
p0 = pnts_clrs0[0];
|
|
30266
|
-
p1 = pnts_clrs1[0];
|
|
30267
|
-
colors = pnts_clrs0[2];
|
|
30268
|
-
}
|
|
30269
|
-
if (p0.length < 2) return;
|
|
30270
|
-
|
|
30271
|
-
this.setCalphaDrawnCoord(p0, div, calphaIdArray);
|
|
30272
|
-
}
|
|
30273
|
-
|
|
30274
|
-
if(bHighlight === 1) {
|
|
30275
|
-
//mesh = new THREE.Mesh(geo, ic.matShader);
|
|
30276
|
-
|
|
30277
|
-
let radius = ic.coilWidth / 2;
|
|
30278
|
-
//var radiusSegments = 8;
|
|
30279
|
-
let radiusSegments = 4; // save memory
|
|
30280
|
-
let closed = false;
|
|
30281
|
-
|
|
30282
|
-
if(positions !== undefined) {
|
|
30283
|
-
let currPos, prevPos;
|
|
30284
|
-
let currP0 = [], currP1 = [];
|
|
30285
|
-
|
|
30286
|
-
for(let i = 0, il = p0.length; i < il; ++i) {
|
|
30287
|
-
currPos = positions[i];
|
|
30288
|
-
|
|
30289
|
-
if((currPos !== prevPos && parseInt(currPos) !== parseInt(prevPos) + 1 && prevPos !== undefined) || (i === il -1) ) {
|
|
30290
|
-
// first tube
|
|
30291
|
-
let geometry0 = new THREE.TubeGeometry(
|
|
30292
|
-
new THREE.CatmullRomCurve3(currP0), // path
|
|
30293
|
-
currP0.length, // segments
|
|
30294
|
-
radius,
|
|
30295
|
-
radiusSegments,
|
|
30296
|
-
closed
|
|
30297
|
-
);
|
|
30298
|
-
|
|
30299
|
-
let mesh = new THREE.Mesh(geometry0, ic.matShader);
|
|
30300
|
-
mesh.renderOrder = ic.renderOrderPicking;
|
|
30301
|
-
//ic.mdlPicking.add(mesh);
|
|
30302
|
-
ic.mdl.add(mesh);
|
|
30303
|
-
|
|
30304
|
-
ic.prevHighlightObjects.push(mesh);
|
|
29994
|
+
ic.prevHighlightObjects.push(mesh);
|
|
30305
29995
|
|
|
30306
29996
|
geometry0 = null;
|
|
30307
29997
|
|
|
@@ -30588,6 +30278,7 @@ class Tube {
|
|
|
30588
30278
|
atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) - 1).toString();
|
|
30589
30279
|
|
|
30590
30280
|
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
|
|
30281
|
+
|| (prevAtom.ssbegin) // e.g., https://www.ncbi.nlm.nih.gov/Structure/icn3d/?pdbid=7JO8 where a beta sheet has just two residues
|
|
30591
30282
|
// || (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')
|
|
30592
30283
|
|| (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))
|
|
30593
30284
|
) ) {
|
|
@@ -30680,7 +30371,7 @@ class Tube {
|
|
|
30680
30371
|
}
|
|
30681
30372
|
|
|
30682
30373
|
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
30683
|
-
if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
|
|
30374
|
+
// if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
|
|
30684
30375
|
|
|
30685
30376
|
//radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
|
|
30686
30377
|
radii.push(radiusFinal);
|
|
@@ -30823,224 +30514,770 @@ class Tube {
|
|
|
30823
30514
|
radiusFinal = this.getRadius(radius, atom);
|
|
30824
30515
|
}
|
|
30825
30516
|
|
|
30826
|
-
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
30827
|
-
if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
|
|
30517
|
+
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
30518
|
+
if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
|
|
30519
|
+
|
|
30520
|
+
//radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
|
|
30521
|
+
radii.push(radiusFinal);
|
|
30522
|
+
|
|
30523
|
+
colors.push(atom.color);
|
|
30524
|
+
// the starting residue of a coil uses the color from the next residue to avoid using the color of the last helix/sheet residue
|
|
30525
|
+
if(index === 1) colors[colors.length - 2] = atom.color;
|
|
30526
|
+
|
|
30527
|
+
currentChain = atom.chain;
|
|
30528
|
+
currentResi = atom.resi;
|
|
30529
|
+
|
|
30530
|
+
let scale = 1.2;
|
|
30531
|
+
if(bHighlight === 2 && !atom.ssbegin) {
|
|
30532
|
+
ic.boxCls.createBox(atom, undefined, undefined, scale, undefined, bHighlight);
|
|
30533
|
+
}
|
|
30534
|
+
|
|
30535
|
+
++index;
|
|
30536
|
+
|
|
30537
|
+
prevAtom = atom;
|
|
30538
|
+
}
|
|
30539
|
+
}
|
|
30540
|
+
|
|
30541
|
+
if(bHighlight !== 2) {
|
|
30542
|
+
pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
|
|
30543
|
+
}
|
|
30544
|
+
|
|
30545
|
+
for(let i = 0, il = pnts_colors_radii_prevone_nexttwo.length; i < il; ++i) {
|
|
30546
|
+
let pnts = pnts_colors_radii_prevone_nexttwo[i].pnts;
|
|
30547
|
+
let colors = pnts_colors_radii_prevone_nexttwo[i].colors;
|
|
30548
|
+
let radii = pnts_colors_radii_prevone_nexttwo[i].radii;
|
|
30549
|
+
let prevone = []; // = pnts_colors_radii_prevone_nexttwo[i].prevone;
|
|
30550
|
+
let nexttwo = []; // = pnts_colors_radii_prevone_nexttwo[i].nexttwo;
|
|
30551
|
+
|
|
30552
|
+
this.createTubeSub(pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil);
|
|
30553
|
+
}
|
|
30554
|
+
|
|
30555
|
+
pnts_colors_radii_prevone_nexttwo = [];
|
|
30556
|
+
}
|
|
30557
|
+
*/
|
|
30558
|
+
|
|
30559
|
+
getCustomtubesize(resid) { let ic = this.icn3d; ic.icn3dui;
|
|
30560
|
+
let pos = resid.lastIndexOf('_');
|
|
30561
|
+
let resi = resid.substr(pos + 1);
|
|
30562
|
+
let chainid = resid.substr(0, pos);
|
|
30563
|
+
|
|
30564
|
+
let radiusFinal = (ic.queryresi2score[chainid] && ic.queryresi2score[chainid].hasOwnProperty(resi)) ? ic.queryresi2score[chainid][resi] * 0.01 : ic.coilWidth;
|
|
30565
|
+
|
|
30566
|
+
return radiusFinal;
|
|
30567
|
+
};
|
|
30568
|
+
|
|
30569
|
+
// modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
30570
|
+
createTubeSub(_pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
|
|
30571
|
+
if(me.bNode) return;
|
|
30572
|
+
|
|
30573
|
+
if (_pnts.length < 2) return;
|
|
30574
|
+
|
|
30575
|
+
let circleDiv = ic.tubeDIV, axisDiv = ic.axisDIV;
|
|
30576
|
+
let circleDivInv = 1 / circleDiv, axisDivInv = 1 / axisDiv;
|
|
30577
|
+
//var geo = new THREE.Geometry();
|
|
30578
|
+
let geo = new THREE.BufferGeometry();
|
|
30579
|
+
let verticeArray = [], colorArray = [],indexArray = [], color;
|
|
30580
|
+
let offset = 0, offset2 = 0, offset3 = 0;
|
|
30581
|
+
|
|
30582
|
+
let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv, undefined, undefined, prevone, nexttwo);
|
|
30583
|
+
|
|
30584
|
+
let pnts = pnts_clrs[0];
|
|
30585
|
+
colors = pnts_clrs[2];
|
|
30586
|
+
|
|
30587
|
+
let constRadiius;
|
|
30588
|
+
// a threshold to stop drawing the tube if it's less than this ratio of radius
|
|
30589
|
+
let thresholdRatio = 1; //0.9;
|
|
30590
|
+
|
|
30591
|
+
let prevAxis1 = new THREE.Vector3(), prevAxis2;
|
|
30592
|
+
for (let i = 0, lim = pnts.length; i < lim; ++i) {
|
|
30593
|
+
let r, idx = (i - 1) * axisDivInv;
|
|
30594
|
+
|
|
30595
|
+
if (i === 0) {
|
|
30596
|
+
r = radii[0];
|
|
30597
|
+
if(r > 0) constRadiius = r;
|
|
30598
|
+
}
|
|
30599
|
+
else {
|
|
30600
|
+
if (idx % 1 === 0) {
|
|
30601
|
+
r = radii[idx];
|
|
30602
|
+
if(r > 0) constRadiius = r;
|
|
30603
|
+
}
|
|
30604
|
+
else {
|
|
30605
|
+
let floored = Math.floor(idx);
|
|
30606
|
+
let tmp = idx - floored;
|
|
30607
|
+
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
30608
|
+
// r = radii[floored] * tmp + radii[floored + 1] * (1 - tmp);
|
|
30609
|
+
r = radii[floored] * (1 - tmp) + radii[floored + 1] * tmp;
|
|
30610
|
+
|
|
30611
|
+
// a threshold to stop drawing the tube if it's less than this ratio of radius.
|
|
30612
|
+
// The extra bit of tube connects coil with strands or helices
|
|
30613
|
+
if(!bNonCoil) {
|
|
30614
|
+
if(r < thresholdRatio * constRadiius) {
|
|
30615
|
+
r = 0;
|
|
30616
|
+
}
|
|
30617
|
+
// else if(r < constRadiius) {
|
|
30618
|
+
// r *= 0.5; // use small radius for the connection between coild and sheets/helices
|
|
30619
|
+
// }
|
|
30620
|
+
}
|
|
30621
|
+
}
|
|
30622
|
+
}
|
|
30623
|
+
let delta, axis1, axis2;
|
|
30624
|
+
if (i < lim - 1) {
|
|
30625
|
+
delta = pnts[i].clone().sub(pnts[i + 1]);
|
|
30626
|
+
axis1 = new THREE.Vector3(0, -delta.z, delta.y).normalize().multiplyScalar(r);
|
|
30627
|
+
axis2 = delta.clone().cross(axis1).normalize().multiplyScalar(r);
|
|
30628
|
+
// let dir = 1, offset = 0;
|
|
30629
|
+
if (prevAxis1.dot(axis1) < 0) {
|
|
30630
|
+
axis1.negate(); axis2.negate(); //dir = -1;//offset = 2 * Math.PI / axisDiv;
|
|
30631
|
+
}
|
|
30632
|
+
prevAxis1 = axis1; prevAxis2 = axis2;
|
|
30633
|
+
} else {
|
|
30634
|
+
axis1 = prevAxis1; axis2 = prevAxis2;
|
|
30635
|
+
}
|
|
30636
|
+
for (let j = 0; j < circleDiv; ++j) {
|
|
30637
|
+
let angle = 2 * Math.PI * circleDivInv * j; //* dir + offset;
|
|
30638
|
+
let point = pnts[i].clone().add(axis1.clone().multiplyScalar(Math.cos(angle))).add(axis2.clone().multiplyScalar(Math.sin(angle)));
|
|
30639
|
+
verticeArray[offset++] = point.x;
|
|
30640
|
+
verticeArray[offset++] = point.y;
|
|
30641
|
+
verticeArray[offset++] = point.z;
|
|
30642
|
+
|
|
30643
|
+
color = (i == colors.length - 1 && colors.length > 1) ? me.parasCls.thr(colors[colors.length - 2]) : me.parasCls.thr(colors[i]);
|
|
30644
|
+
colorArray[offset2++] = color.r;
|
|
30645
|
+
colorArray[offset2++] = color.g;
|
|
30646
|
+
colorArray[offset2++] = color.b;
|
|
30647
|
+
}
|
|
30648
|
+
}
|
|
30649
|
+
let offsetTmp = 0, nComp = 3;
|
|
30650
|
+
for (let i = 0, lim = pnts.length - 1; i < lim; ++i) {
|
|
30651
|
+
let reg = 0;
|
|
30652
|
+
//var r1 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv]).lengthSq();
|
|
30653
|
+
//var r2 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv + 1]).lengthSq();
|
|
30654
|
+
let pos = offsetTmp * nComp;
|
|
30655
|
+
let point1 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
30656
|
+
pos = (offsetTmp + circleDiv) * nComp;
|
|
30657
|
+
let point2 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
30658
|
+
pos = (offsetTmp + circleDiv + 1) * nComp;
|
|
30659
|
+
let point3 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
30660
|
+
|
|
30661
|
+
let r1 = point1.clone().sub(point2).lengthSq();
|
|
30662
|
+
let r2 = point1.clone().sub(point3).lengthSq();
|
|
30663
|
+
if (r1 > r2) { r1 = r2; reg = 1; } for (let j = 0; j < circleDiv; ++j) {
|
|
30664
|
+
//geo.faces.push(new THREE.Face3(offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv, undefined, c));
|
|
30665
|
+
//geo.faces.push(new THREE.Face3(offset + (j + 1) % circleDiv, offset + (j + reg) % circleDiv + circleDiv, offset + (j + reg + 1) % circleDiv + circleDiv, undefined, c));
|
|
30666
|
+
//indexArray = indexArray.concat([offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv]);
|
|
30667
|
+
indexArray[offset3++] = offsetTmp + j;
|
|
30668
|
+
indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
|
|
30669
|
+
indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
|
|
30670
|
+
|
|
30671
|
+
//indexArray = indexArray.concat([offset + (j + 1) % circleDiv, offset + (j + reg) % circleDiv + circleDiv, offset + (j + reg + 1) % circleDiv + circleDiv]);
|
|
30672
|
+
indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
|
|
30673
|
+
indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
|
|
30674
|
+
indexArray[offset3++] = offsetTmp + (j + reg + 1) % circleDiv + circleDiv;
|
|
30675
|
+
}
|
|
30676
|
+
offsetTmp += circleDiv;
|
|
30677
|
+
}
|
|
30678
|
+
|
|
30679
|
+
geo.setAttribute('position', new THREE.BufferAttribute(new Float32Array(verticeArray), nComp));
|
|
30680
|
+
geo.setAttribute('color', new THREE.BufferAttribute(new Float32Array(colorArray), nComp));
|
|
30681
|
+
|
|
30682
|
+
geo.setIndex(new THREE.BufferAttribute(new Uint32Array(indexArray), 1));
|
|
30683
|
+
//geo.setIndex(indexArray);
|
|
30684
|
+
|
|
30685
|
+
//geo.computeFaceNormals();
|
|
30686
|
+
//geo.computeVertexNormals(false);
|
|
30687
|
+
geo.computeVertexNormals();
|
|
30688
|
+
|
|
30689
|
+
let mesh;
|
|
30690
|
+
if(bHighlight === 2) {
|
|
30691
|
+
//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 }));
|
|
30692
|
+
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 }));
|
|
30693
|
+
|
|
30694
|
+
if(ic.mdl) ic.mdl.add(mesh);
|
|
30695
|
+
}
|
|
30696
|
+
else if(bHighlight === 1) {
|
|
30697
|
+
mesh = new THREE.Mesh(geo, ic.matShader);
|
|
30698
|
+
mesh.renderOrder = ic.renderOrderPicking;
|
|
30699
|
+
//ic.mdlPicking.add(mesh);
|
|
30700
|
+
if(ic.mdl) ic.mdl.add(mesh);
|
|
30701
|
+
}
|
|
30702
|
+
else {
|
|
30703
|
+
//mesh = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({ specular: ic.frac, shininess: ic.shininess, emissive: ic.emissive, vertexColors: THREE.FaceColors, side: THREE.DoubleSide }));
|
|
30704
|
+
mesh = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({ specular: ic.frac, shininess: ic.shininess, emissive: ic.emissive, vertexColors: true, side: THREE.DoubleSide }));
|
|
30705
|
+
|
|
30706
|
+
if(ic.mdl) ic.mdl.add(mesh);
|
|
30707
|
+
}
|
|
30708
|
+
|
|
30709
|
+
if(bHighlight === 1 || bHighlight === 2) {
|
|
30710
|
+
ic.prevHighlightObjects.push(mesh);
|
|
30711
|
+
}
|
|
30712
|
+
else {
|
|
30713
|
+
ic.objects.push(mesh);
|
|
30714
|
+
}
|
|
30715
|
+
}
|
|
30716
|
+
|
|
30717
|
+
getRadius(radius, atom) { let ic = this.icn3d; ic.icn3dui;
|
|
30718
|
+
let radiusFinal = radius;
|
|
30719
|
+
if(radius) {
|
|
30720
|
+
radiusFinal = radius;
|
|
30721
|
+
}
|
|
30722
|
+
else {
|
|
30723
|
+
if(atom.b > 0 && atom.b <= 100) {
|
|
30724
|
+
radiusFinal = atom.b * 0.01;
|
|
30725
|
+
}
|
|
30726
|
+
else if(atom.b > 100) {
|
|
30727
|
+
radiusFinal = 100 * 0.01;
|
|
30728
|
+
}
|
|
30729
|
+
else {
|
|
30730
|
+
radiusFinal = ic.coilWidth;
|
|
30731
|
+
}
|
|
30732
|
+
}
|
|
30733
|
+
|
|
30734
|
+
return radiusFinal;
|
|
30735
|
+
}
|
|
30736
|
+
}
|
|
30737
|
+
|
|
30738
|
+
/**
|
|
30739
|
+
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
30740
|
+
*/
|
|
30741
|
+
|
|
30742
|
+
class Strand {
|
|
30743
|
+
constructor(icn3d) {
|
|
30744
|
+
this.icn3d = icn3d;
|
|
30745
|
+
}
|
|
30746
|
+
|
|
30747
|
+
// significantly modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
30748
|
+
//Create the style of ribbon or strand for "atoms". "num" means how many lines define the curve.
|
|
30749
|
+
//"num" is 2 for ribbon and 6 for strand. "div" means how many pnts are used to smooth the curve.
|
|
30750
|
+
//It's typically 5. "coilWidth" is the width of curve for coil. "helixSheetWidth" is the width of curve for helix or sheet.
|
|
30751
|
+
//"doNotSmoothen" is a flag to smooth the curve or not. "thickness" is the thickness of the curve.
|
|
30752
|
+
//"bHighlight" is an option to draw the highlight for these atoms. The highlight could be outlines
|
|
30753
|
+
//with bHighlight=1 and 3D objects with bHighlight=2.
|
|
30754
|
+
createStrand(atoms, num, div, fill, coilWidth, helixSheetWidth, doNotSmoothen, thickness, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
|
|
30755
|
+
if(me.bNode) return;
|
|
30756
|
+
|
|
30757
|
+
let bRibbon = fill ? true: false;
|
|
30758
|
+
|
|
30759
|
+
// when highlight, the input atoms may only include part of sheet or helix
|
|
30760
|
+
// include the whole sheet or helix when highlighting
|
|
30761
|
+
let atomsAdjust = {};
|
|
30762
|
+
|
|
30763
|
+
//if( (bHighlight === 1 || bHighlight === 2) && !ic.bAllAtoms) {
|
|
30764
|
+
//if( !ic.bAllAtoms) {
|
|
30765
|
+
if( Object.keys(atoms).length < Object.keys(ic.atoms).length) {
|
|
30766
|
+
atomsAdjust = this.getSSExpandedAtoms(atoms);
|
|
30767
|
+
}
|
|
30768
|
+
else {
|
|
30769
|
+
atomsAdjust = atoms;
|
|
30770
|
+
}
|
|
30771
|
+
|
|
30772
|
+
if(bHighlight === 2) {
|
|
30773
|
+
if(fill) {
|
|
30774
|
+
fill = false;
|
|
30775
|
+
num = null;
|
|
30776
|
+
div = null;
|
|
30777
|
+
coilWidth = null;
|
|
30778
|
+
helixSheetWidth = null;
|
|
30779
|
+
thickness = undefined;
|
|
30780
|
+
}
|
|
30781
|
+
else {
|
|
30782
|
+
fill = true;
|
|
30783
|
+
num = 2;
|
|
30784
|
+
div = undefined;
|
|
30785
|
+
coilWidth = undefined;
|
|
30786
|
+
helixSheetWidth = undefined;
|
|
30787
|
+
thickness = ic.ribbonthickness;
|
|
30788
|
+
}
|
|
30789
|
+
}
|
|
30790
|
+
|
|
30791
|
+
num = num || ic.strandDIV;
|
|
30792
|
+
div = div || ic.axisDIV;
|
|
30793
|
+
coilWidth = coilWidth || ic.coilWidth;
|
|
30794
|
+
doNotSmoothen = doNotSmoothen || false;
|
|
30795
|
+
helixSheetWidth = helixSheetWidth || ic.helixSheetWidth;
|
|
30796
|
+
let pnts = {}; for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
30797
|
+
let pntsCA = [];
|
|
30798
|
+
let prevCOArray = [];
|
|
30799
|
+
let bShowArray = [];
|
|
30800
|
+
let calphaIdArray = []; // used to store one of the final positions drawn in 3D
|
|
30801
|
+
let colors = [];
|
|
30802
|
+
let currentChain, currentCA = null, currentO = null, currentColor = null, prevCoorCA = null, prevCoorO = null, prevColor = null;
|
|
30803
|
+
let prevCO = null, ss = null, ssend = false, atomid = null, prevAtomid = null, prevResi = null, calphaid = null, prevCalphaid = null;
|
|
30804
|
+
let strandWidth, bSheetSegment = false, bHelixSegment = false;
|
|
30805
|
+
let atom, tubeAtoms = {};
|
|
30806
|
+
|
|
30807
|
+
// test the first 30 atoms to see whether only C-alpha is available
|
|
30808
|
+
ic.bCalphaOnly = me.utilsCls.isCalphaPhosOnly(atomsAdjust); //, 'CA');
|
|
30809
|
+
|
|
30810
|
+
// when highlight, draw whole beta sheet and use bShowArray to show the highlight part
|
|
30811
|
+
let residueHash = {};
|
|
30812
|
+
for(let i in atomsAdjust) {
|
|
30813
|
+
let atom = atomsAdjust[i];
|
|
30814
|
+
|
|
30815
|
+
let residueid = atom.structure + '_' + atom.chain + '_' + atom.resi;
|
|
30816
|
+
residueHash[residueid] = 1;
|
|
30817
|
+
}
|
|
30818
|
+
let totalResidueCount = Object.keys(residueHash).length;
|
|
30819
|
+
|
|
30820
|
+
let drawnResidueCount = 0;
|
|
30821
|
+
|
|
30822
|
+
let bFullAtom = (Object.keys(ic.hAtoms).length == Object.keys(ic.atoms).length) ? true : false;
|
|
30823
|
+
|
|
30824
|
+
let caArray = []; // record all C-alpha atoms to predict the helix
|
|
30825
|
+
|
|
30826
|
+
for (let i in atomsAdjust) {
|
|
30827
|
+
atom = atomsAdjust[i];
|
|
30828
|
+
if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
|
|
30829
|
+
// "CA" has to appear before "O"
|
|
30830
|
+
|
|
30831
|
+
if (atom.name === 'CA') {
|
|
30832
|
+
if ( atoms.hasOwnProperty(i) && ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) ) {
|
|
30833
|
+
tubeAtoms[i] = atom;
|
|
30834
|
+
}
|
|
30835
|
+
|
|
30836
|
+
currentCA = atom.coord;
|
|
30837
|
+
currentColor = atom.color;
|
|
30838
|
+
calphaid = atom.serial;
|
|
30839
|
+
|
|
30840
|
+
caArray.push(atom.serial);
|
|
30841
|
+
}
|
|
30842
|
+
|
|
30843
|
+
if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA')) {
|
|
30844
|
+
if(currentCA === null || currentCA === undefined) {
|
|
30845
|
+
currentCA = atom.coord;
|
|
30846
|
+
currentColor = atom.color;
|
|
30847
|
+
calphaid = atom.serial;
|
|
30848
|
+
}
|
|
30849
|
+
|
|
30850
|
+
if(atom.name === 'O') {
|
|
30851
|
+
currentO = atom.coord;
|
|
30852
|
+
}
|
|
30853
|
+
// smoothen each coil, helix and sheet separately. The joint residue has to be included both in the previous and next segment
|
|
30854
|
+
let bSameChain = true;
|
|
30855
|
+
// if (currentChain !== atom.chain || currentResi + 1 !== atom.resi) {
|
|
30856
|
+
if (currentChain !== atom.chain) {
|
|
30857
|
+
bSameChain = false;
|
|
30858
|
+
}
|
|
30859
|
+
|
|
30860
|
+
if(atom.ssend && atom.ss === 'sheet') {
|
|
30861
|
+
bSheetSegment = true;
|
|
30862
|
+
}
|
|
30863
|
+
else if(atom.ssend && atom.ss === 'helix') {
|
|
30864
|
+
bHelixSegment = true;
|
|
30865
|
+
}
|
|
30866
|
+
|
|
30867
|
+
// assign the previous residue
|
|
30868
|
+
if(prevCoorO) {
|
|
30869
|
+
if(bHighlight === 1 || bHighlight === 2) {
|
|
30870
|
+
colors.push(ic.hColor);
|
|
30871
|
+
}
|
|
30872
|
+
else {
|
|
30873
|
+
colors.push(prevColor);
|
|
30874
|
+
}
|
|
30875
|
+
|
|
30876
|
+
if(ss !== 'coil' && atom.ss === 'coil') {
|
|
30877
|
+
strandWidth = coilWidth;
|
|
30878
|
+
}
|
|
30879
|
+
else if(ssend && atom.ssbegin) { // a transition between two ss
|
|
30880
|
+
strandWidth = coilWidth;
|
|
30881
|
+
}
|
|
30882
|
+
else {
|
|
30883
|
+
strandWidth = (ss === 'coil') ? coilWidth : helixSheetWidth;
|
|
30884
|
+
}
|
|
30885
|
+
|
|
30886
|
+
let O, oldCA, resSpan = 4;
|
|
30887
|
+
if(atom.name === 'O') {
|
|
30888
|
+
O = prevCoorO.clone();
|
|
30889
|
+
if(prevCoorCA !== null && prevCoorCA !== undefined) {
|
|
30890
|
+
O.sub(prevCoorCA);
|
|
30891
|
+
}
|
|
30892
|
+
else {
|
|
30893
|
+
prevCoorCA = prevCoorO.clone();
|
|
30894
|
+
if(caArray.length > resSpan + 1) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
30895
|
+
O = prevCoorCA.clone();
|
|
30896
|
+
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan - 1]].coord.clone();
|
|
30897
|
+
//O.sub(oldCA);
|
|
30898
|
+
oldCA.sub(O);
|
|
30899
|
+
}
|
|
30900
|
+
else {
|
|
30901
|
+
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
30902
|
+
}
|
|
30903
|
+
}
|
|
30904
|
+
}
|
|
30905
|
+
else if(ic.bCalphaOnly && atom.name === 'CA') {
|
|
30906
|
+
if(caArray.length > resSpan + 1) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
30907
|
+
O = prevCoorCA.clone();
|
|
30908
|
+
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan - 1]].coord.clone();
|
|
30909
|
+
//O.sub(oldCA);
|
|
30910
|
+
oldCA.sub(O);
|
|
30911
|
+
}
|
|
30912
|
+
else {
|
|
30913
|
+
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
30914
|
+
}
|
|
30915
|
+
}
|
|
30916
|
+
|
|
30917
|
+
O.normalize(); // can be omitted for performance
|
|
30918
|
+
O.multiplyScalar(strandWidth);
|
|
30919
|
+
if (prevCO !== null && O.dot(prevCO) < 0) O.negate();
|
|
30920
|
+
prevCO = O;
|
|
30921
|
+
|
|
30922
|
+
for (let j = 0, numM1Inv2 = 2 / (num - 1); j < num; ++j) {
|
|
30923
|
+
let delta = -1 + numM1Inv2 * j;
|
|
30924
|
+
let v = new THREE.Vector3(prevCoorCA.x + prevCO.x * delta, prevCoorCA.y + prevCO.y * delta, prevCoorCA.z + prevCO.z * delta);
|
|
30925
|
+
if (!doNotSmoothen && ss === 'sheet') v.smoothen = true;
|
|
30926
|
+
pnts[j].push(v);
|
|
30927
|
+
}
|
|
30928
|
+
|
|
30929
|
+
pntsCA.push(prevCoorCA);
|
|
30930
|
+
prevCOArray.push(prevCO);
|
|
30931
|
+
|
|
30932
|
+
if(atoms.hasOwnProperty(prevAtomid)) {
|
|
30933
|
+
bShowArray.push(prevResi);
|
|
30934
|
+
calphaIdArray.push(prevCalphaid);
|
|
30935
|
+
}
|
|
30936
|
+
else {
|
|
30937
|
+
bShowArray.push(0);
|
|
30938
|
+
calphaIdArray.push(0);
|
|
30939
|
+
}
|
|
30940
|
+
|
|
30941
|
+
++drawnResidueCount;
|
|
30942
|
+
}
|
|
30943
|
+
|
|
30944
|
+
let maxDist = 6.0;
|
|
30945
|
+
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);
|
|
30946
|
+
// The following code didn't work to select one residue
|
|
30947
|
+
// 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);
|
|
30948
|
+
|
|
30949
|
+
// if(bBrokenSs && atom.ss === 'sheet') {
|
|
30950
|
+
// bSheetSegment = true;
|
|
30951
|
+
// }
|
|
30952
|
+
// else if(bBrokenSs && atom.ss === 'helix') {
|
|
30953
|
+
// bHelixSegment = true;
|
|
30954
|
+
// }
|
|
30955
|
+
|
|
30956
|
+
if ((atom.ssbegin || atom.ssend || (drawnResidueCount === totalResidueCount - 1) || bBrokenSs) && pnts[0].length > 0 && bSameChain) {
|
|
30957
|
+
let atomName = 'CA';
|
|
30958
|
+
|
|
30959
|
+
let prevone = [], nexttwo = [];
|
|
30960
|
+
|
|
30961
|
+
if(isNaN(ic.atoms[prevAtomid].resi)) {
|
|
30962
|
+
prevone = [];
|
|
30963
|
+
}
|
|
30964
|
+
else {
|
|
30965
|
+
let prevoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) - 1).toString();
|
|
30966
|
+
let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
|
|
30967
|
+
prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
|
|
30968
|
+
}
|
|
30969
|
+
|
|
30970
|
+
if(!isNaN(ic.atoms[prevAtomid].resi)) {
|
|
30971
|
+
let nextoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) + 1).toString();
|
|
30972
|
+
let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
|
|
30973
|
+
if(nextoneCoord !== undefined) {
|
|
30974
|
+
nexttwo.push(nextoneCoord);
|
|
30975
|
+
}
|
|
30976
|
+
|
|
30977
|
+
let nexttwoResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) + 2).toString();
|
|
30978
|
+
let nexttwoCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nexttwoResid, atomName);
|
|
30979
|
+
if(nexttwoCoord !== undefined) {
|
|
30980
|
+
nexttwo.push(nexttwoCoord);
|
|
30981
|
+
}
|
|
30982
|
+
}
|
|
30983
|
+
|
|
30984
|
+
if(!bBrokenSs) { // include the current residue
|
|
30985
|
+
// assign the current joint residue to the previous segment
|
|
30986
|
+
if(bHighlight === 1 || bHighlight === 2) {
|
|
30987
|
+
colors.push(ic.hColor);
|
|
30988
|
+
}
|
|
30989
|
+
else {
|
|
30990
|
+
//colors.push(atom.color);
|
|
30991
|
+
colors.push(prevColor);
|
|
30992
|
+
}
|
|
30993
|
+
|
|
30994
|
+
if(atom.ssend && atom.ss === 'sheet') { // current residue is the end of ss and is the end of arrow
|
|
30995
|
+
strandWidth = 0; // make the arrow end sharp
|
|
30996
|
+
}
|
|
30997
|
+
else if(ss === 'coil' && atom.ssbegin) {
|
|
30998
|
+
strandWidth = coilWidth;
|
|
30999
|
+
}
|
|
31000
|
+
else if(ssend && atom.ssbegin) { // current residue is the start of ss and the previous residue is the end of ss, then use coil
|
|
31001
|
+
strandWidth = coilWidth;
|
|
31002
|
+
}
|
|
31003
|
+
else { // use the ss from the previous residue
|
|
31004
|
+
strandWidth = (atom.ss === 'coil') ? coilWidth : helixSheetWidth;
|
|
31005
|
+
}
|
|
31006
|
+
|
|
31007
|
+
let O, oldCA, resSpan = 4;
|
|
31008
|
+
if(atom.name === 'O') {
|
|
31009
|
+
O = currentO.clone();
|
|
31010
|
+
O.sub(currentCA);
|
|
31011
|
+
}
|
|
31012
|
+
else if(ic.bCalphaOnly && atom.name === 'CA') {
|
|
31013
|
+
if(caArray.length > resSpan) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
31014
|
+
O = currentCA.clone();
|
|
31015
|
+
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan]].coord.clone();
|
|
31016
|
+
//O.sub(oldCA);
|
|
31017
|
+
oldCA.sub(O);
|
|
31018
|
+
}
|
|
31019
|
+
else {
|
|
31020
|
+
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
31021
|
+
}
|
|
31022
|
+
}
|
|
31023
|
+
|
|
31024
|
+
O.normalize(); // can be omitted for performance
|
|
31025
|
+
O.multiplyScalar(strandWidth);
|
|
31026
|
+
if (prevCO !== null && O.dot(prevCO) < 0) O.negate();
|
|
31027
|
+
prevCO = O;
|
|
31028
|
+
|
|
31029
|
+
for (let j = 0, numM1Inv2 = 2 / (num - 1); j < num; ++j) {
|
|
31030
|
+
let delta = -1 + numM1Inv2 * j;
|
|
31031
|
+
let v = new THREE.Vector3(currentCA.x + prevCO.x * delta, currentCA.y + prevCO.y * delta, currentCA.z + prevCO.z * delta);
|
|
31032
|
+
if (!doNotSmoothen && ss === 'sheet') v.smoothen = true;
|
|
31033
|
+
pnts[j].push(v);
|
|
31034
|
+
}
|
|
31035
|
+
|
|
31036
|
+
atomid = atom.serial;
|
|
31037
|
+
|
|
31038
|
+
pntsCA.push(currentCA);
|
|
31039
|
+
prevCOArray.push(prevCO);
|
|
31040
|
+
|
|
31041
|
+
// 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.
|
|
31042
|
+
//if(atoms.hasOwnProperty(atomid) && (bHighlight === 1 && !atom.notshow) ) {
|
|
31043
|
+
if(atoms.hasOwnProperty(atomid)) {
|
|
31044
|
+
bShowArray.push(atom.resi);
|
|
31045
|
+
calphaIdArray.push(calphaid);
|
|
31046
|
+
}
|
|
31047
|
+
else {
|
|
31048
|
+
bShowArray.push(0);
|
|
31049
|
+
calphaIdArray.push(0);
|
|
31050
|
+
}
|
|
31051
|
+
}
|
|
31052
|
+
|
|
31053
|
+
// draw the current segment
|
|
31054
|
+
for (let j = 0; !fill && j < num; ++j) {
|
|
31055
|
+
if(bSheetSegment) {
|
|
31056
|
+
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
31057
|
+
}
|
|
31058
|
+
else if(bHelixSegment) {
|
|
31059
|
+
if(bFullAtom) {
|
|
31060
|
+
ic.curveCls.createCurveSub(pnts[j], 1, colors, div, bHighlight, bRibbon, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo);
|
|
31061
|
+
}
|
|
31062
|
+
else {
|
|
31063
|
+
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
31064
|
+
}
|
|
31065
|
+
}
|
|
31066
|
+
}
|
|
31067
|
+
if (fill) {
|
|
31068
|
+
if(bSheetSegment) {
|
|
31069
|
+
let start = 0, end = num - 1;
|
|
31070
|
+
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
31071
|
+
}
|
|
31072
|
+
else if(bHelixSegment) {
|
|
31073
|
+
if(bFullAtom) {
|
|
31074
|
+
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
31075
|
+
}
|
|
31076
|
+
else {
|
|
31077
|
+
let start = 0, end = num - 1;
|
|
31078
|
+
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
31079
|
+
}
|
|
31080
|
+
}
|
|
31081
|
+
else {
|
|
31082
|
+
if(bHighlight === 2) { // draw coils only when highlighted. if not highlighted, coils will be drawn as tubes separately
|
|
31083
|
+
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
31084
|
+
}
|
|
31085
|
+
}
|
|
31086
|
+
}
|
|
31087
|
+
for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
31088
|
+
|
|
31089
|
+
colors = [];
|
|
31090
|
+
pntsCA = [];
|
|
31091
|
+
prevCOArray = [];
|
|
31092
|
+
bShowArray = [];
|
|
31093
|
+
calphaIdArray = [];
|
|
31094
|
+
bSheetSegment = false;
|
|
31095
|
+
bHelixSegment = false;
|
|
31096
|
+
} // end if (atom.ssbegin || atom.ssend)
|
|
31097
|
+
|
|
31098
|
+
// end of a chain
|
|
31099
|
+
// if ((currentChain !== atom.chain || currentResi + 1 !== atom.resi) && pnts[0].length > 0) {
|
|
31100
|
+
if ((currentChain !== atom.chain) && pnts[0].length > 0) {
|
|
30828
31101
|
|
|
30829
|
-
|
|
30830
|
-
radii.push(radiusFinal);
|
|
31102
|
+
let atomName = 'CA';
|
|
30831
31103
|
|
|
30832
|
-
|
|
30833
|
-
|
|
30834
|
-
|
|
31104
|
+
let prevone = [], nexttwo = [];
|
|
31105
|
+
if(isNaN(ic.atoms[prevAtomid].resi)) {
|
|
31106
|
+
prevone = [];
|
|
31107
|
+
}
|
|
31108
|
+
else {
|
|
31109
|
+
let prevoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) - 1).toString();
|
|
31110
|
+
ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
|
|
31111
|
+
}
|
|
30835
31112
|
|
|
30836
|
-
|
|
30837
|
-
|
|
31113
|
+
for (let j = 0; !fill && j < num; ++j) {
|
|
31114
|
+
if(bSheetSegment) {
|
|
31115
|
+
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
31116
|
+
}
|
|
31117
|
+
else if(bHelixSegment) {
|
|
31118
|
+
if(bFullAtom) {
|
|
31119
|
+
ic.curveCls.createCurveSub(pnts[j], 1, colors, div, bHighlight, bRibbon, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo);
|
|
31120
|
+
}
|
|
31121
|
+
else {
|
|
31122
|
+
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
31123
|
+
}
|
|
31124
|
+
}
|
|
31125
|
+
}
|
|
31126
|
+
if (fill) {
|
|
31127
|
+
if(bSheetSegment) {
|
|
31128
|
+
let start = 0, end = num - 1;
|
|
31129
|
+
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
31130
|
+
}
|
|
31131
|
+
else if(bHelixSegment) {
|
|
31132
|
+
if(bFullAtom) {
|
|
31133
|
+
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
31134
|
+
}
|
|
31135
|
+
else {
|
|
31136
|
+
let start = 0, end = num - 1;
|
|
31137
|
+
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
31138
|
+
}
|
|
31139
|
+
}
|
|
31140
|
+
}
|
|
30838
31141
|
|
|
30839
|
-
|
|
30840
|
-
|
|
30841
|
-
|
|
31142
|
+
for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
31143
|
+
colors = [];
|
|
31144
|
+
pntsCA = [];
|
|
31145
|
+
prevCOArray = [];
|
|
31146
|
+
bShowArray = [];
|
|
31147
|
+
calphaIdArray = [];
|
|
31148
|
+
bSheetSegment = false;
|
|
31149
|
+
bHelixSegment = false;
|
|
30842
31150
|
}
|
|
30843
31151
|
|
|
30844
|
-
|
|
31152
|
+
currentChain = atom.chain;
|
|
31153
|
+
ss = atom.ss;
|
|
31154
|
+
ssend = atom.ssend;
|
|
31155
|
+
prevAtomid = atom.serial;
|
|
31156
|
+
prevResi = atom.resi;
|
|
30845
31157
|
|
|
30846
|
-
|
|
30847
|
-
}
|
|
30848
|
-
}
|
|
31158
|
+
prevCalphaid = calphaid;
|
|
30849
31159
|
|
|
30850
|
-
|
|
30851
|
-
|
|
30852
|
-
|
|
31160
|
+
// only update when atom.name === 'O'
|
|
31161
|
+
prevCoorCA = currentCA;
|
|
31162
|
+
prevCoorO = atom.coord;
|
|
31163
|
+
prevColor = currentColor;
|
|
31164
|
+
} // end if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA') ) {
|
|
31165
|
+
} // end if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
|
|
31166
|
+
} // end for
|
|
30853
31167
|
|
|
30854
|
-
|
|
30855
|
-
let pnts = pnts_colors_radii_prevone_nexttwo[i].pnts;
|
|
30856
|
-
let colors = pnts_colors_radii_prevone_nexttwo[i].colors;
|
|
30857
|
-
let radii = pnts_colors_radii_prevone_nexttwo[i].radii;
|
|
30858
|
-
let prevone = []; // = pnts_colors_radii_prevone_nexttwo[i].prevone;
|
|
30859
|
-
let nexttwo = []; // = pnts_colors_radii_prevone_nexttwo[i].nexttwo;
|
|
31168
|
+
caArray = [];
|
|
30860
31169
|
|
|
30861
|
-
|
|
30862
|
-
}
|
|
31170
|
+
ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight);
|
|
30863
31171
|
|
|
30864
|
-
|
|
31172
|
+
tubeAtoms = {};
|
|
31173
|
+
pnts = {};
|
|
30865
31174
|
}
|
|
30866
|
-
*/
|
|
30867
|
-
|
|
30868
|
-
getCustomtubesize(resid) { let ic = this.icn3d; ic.icn3dui;
|
|
30869
|
-
let pos = resid.lastIndexOf('_');
|
|
30870
|
-
let resi = resid.substr(pos + 1);
|
|
30871
|
-
let chainid = resid.substr(0, pos);
|
|
30872
|
-
|
|
30873
|
-
let radiusFinal = (ic.queryresi2score[chainid] && ic.queryresi2score[chainid].hasOwnProperty(resi)) ? ic.queryresi2score[chainid][resi] * 0.01 : ic.coilWidth;
|
|
30874
|
-
|
|
30875
|
-
return radiusFinal;
|
|
30876
|
-
};
|
|
30877
|
-
|
|
30878
|
-
// modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
30879
|
-
createTubeSub(_pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
|
|
30880
|
-
if(me.bNode) return;
|
|
30881
|
-
|
|
30882
|
-
if (_pnts.length < 2) return;
|
|
30883
31175
|
|
|
30884
|
-
|
|
30885
|
-
let
|
|
30886
|
-
|
|
30887
|
-
let
|
|
30888
|
-
let verticeArray = [], colorArray = [],indexArray = [], color;
|
|
30889
|
-
let offset = 0, offset2 = 0, offset3 = 0;
|
|
31176
|
+
getSSExpandedAtoms(atoms, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
|
|
31177
|
+
let currChain, currResi, currAtom, prevChain, prevResi, prevAtom;
|
|
31178
|
+
let firstAtom, lastAtom;
|
|
31179
|
+
let index = 0, length = Object.keys(atoms).length;
|
|
30890
31180
|
|
|
30891
|
-
let
|
|
31181
|
+
let atomsAdjust = me.hashUtilsCls.cloneHash(atoms);
|
|
31182
|
+
for(let serial in atoms) {
|
|
31183
|
+
currChain = atoms[serial].structure + '_' + atoms[serial].chain;
|
|
31184
|
+
currResi = atoms[serial].resi; //parseInt(atoms[serial].resi);
|
|
31185
|
+
currAtom = atoms[serial];
|
|
30892
31186
|
|
|
30893
|
-
|
|
30894
|
-
colors = pnts_clrs[2];
|
|
31187
|
+
if(prevChain === undefined) firstAtom = atoms[serial];
|
|
30895
31188
|
|
|
30896
|
-
|
|
30897
|
-
|
|
30898
|
-
|
|
31189
|
+
if( (currChain !== prevChain && prevChain !== undefined)
|
|
31190
|
+
|| (currResi !== prevResi && currResi !== parseInt(prevResi) + 1 && prevResi !== undefined) || index === length - 1) {
|
|
31191
|
+
if( (currChain !== prevChain && prevChain !== undefined)
|
|
31192
|
+
|| (currResi !== prevResi && currResi !== parseInt(prevResi) + 1 && prevResi !== undefined) ) {
|
|
31193
|
+
lastAtom = prevAtom;
|
|
31194
|
+
}
|
|
31195
|
+
else if(index === length - 1) {
|
|
31196
|
+
lastAtom = currAtom;
|
|
31197
|
+
}
|
|
30899
31198
|
|
|
30900
|
-
|
|
30901
|
-
|
|
30902
|
-
|
|
31199
|
+
// fill the beginning
|
|
31200
|
+
let beginResi = firstAtom.resi;
|
|
31201
|
+
if(!isNaN(firstAtom.resi) && firstAtom.ss !== 'coil' && !(firstAtom.ssbegin) ) {
|
|
31202
|
+
for(let i = parseInt(firstAtom.resi) - 1; i > 0; --i) {
|
|
31203
|
+
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + i;
|
|
31204
|
+
if(!ic.residues.hasOwnProperty(residueid)) break;
|
|
30903
31205
|
|
|
30904
|
-
|
|
30905
|
-
r = radii[0];
|
|
30906
|
-
if(r > 0) constRadiius = r;
|
|
30907
|
-
}
|
|
30908
|
-
else {
|
|
30909
|
-
if (idx % 1 === 0) {
|
|
30910
|
-
r = radii[idx];
|
|
30911
|
-
if(r > 0) constRadiius = r;
|
|
30912
|
-
}
|
|
30913
|
-
else {
|
|
30914
|
-
let floored = Math.floor(idx);
|
|
30915
|
-
let tmp = idx - floored;
|
|
30916
|
-
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
30917
|
-
// r = radii[floored] * tmp + radii[floored + 1] * (1 - tmp);
|
|
30918
|
-
r = radii[floored] * (1 - tmp) + radii[floored + 1] * tmp;
|
|
31206
|
+
let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[residueid]);
|
|
30919
31207
|
|
|
30920
|
-
|
|
30921
|
-
|
|
30922
|
-
|
|
30923
|
-
if(r < thresholdRatio * constRadiius) {
|
|
30924
|
-
r = 0;
|
|
30925
|
-
}
|
|
30926
|
-
// else if(r < constRadiius) {
|
|
30927
|
-
// r *= 0.5; // use small radius for the connection between coild and sheets/helices
|
|
30928
|
-
// }
|
|
31208
|
+
if(atom.ss === firstAtom.ss && atom.ssbegin) {
|
|
31209
|
+
beginResi = atom.resi;
|
|
31210
|
+
break;
|
|
30929
31211
|
}
|
|
30930
31212
|
}
|
|
30931
|
-
|
|
30932
|
-
|
|
30933
|
-
|
|
30934
|
-
|
|
30935
|
-
|
|
30936
|
-
axis2 = delta.clone().cross(axis1).normalize().multiplyScalar(r);
|
|
30937
|
-
// let dir = 1, offset = 0;
|
|
30938
|
-
if (prevAxis1.dot(axis1) < 0) {
|
|
30939
|
-
axis1.negate(); axis2.negate(); //dir = -1;//offset = 2 * Math.PI / axisDiv;
|
|
31213
|
+
|
|
31214
|
+
for(let i = beginResi; i < firstAtom.resi; ++i) {
|
|
31215
|
+
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + i;
|
|
31216
|
+
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
31217
|
+
ic.atoms));
|
|
30940
31218
|
}
|
|
30941
|
-
prevAxis1 = axis1; prevAxis2 = axis2;
|
|
30942
|
-
} else {
|
|
30943
|
-
axis1 = prevAxis1; axis2 = prevAxis2;
|
|
30944
31219
|
}
|
|
30945
|
-
for (let j = 0; j < circleDiv; ++j) {
|
|
30946
|
-
let angle = 2 * Math.PI * circleDivInv * j; //* dir + offset;
|
|
30947
|
-
let point = pnts[i].clone().add(axis1.clone().multiplyScalar(Math.cos(angle))).add(axis2.clone().multiplyScalar(Math.sin(angle)));
|
|
30948
|
-
verticeArray[offset++] = point.x;
|
|
30949
|
-
verticeArray[offset++] = point.y;
|
|
30950
|
-
verticeArray[offset++] = point.z;
|
|
30951
31220
|
|
|
30952
|
-
|
|
30953
|
-
|
|
30954
|
-
|
|
30955
|
-
|
|
31221
|
+
// add one extra residue for coils between strands/helix
|
|
31222
|
+
if(!isNaN(firstAtom.resi) && ic.pk === 3 && bHighlight === 1 && firstAtom.ss === 'coil') {
|
|
31223
|
+
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
|
|
31224
|
+
if(ic.residues.hasOwnProperty(residueid)) {
|
|
31225
|
+
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
31226
|
+
ic.atoms));
|
|
31227
|
+
atoms = me.hashUtilsCls.unionHash(atoms, me.hashUtilsCls.hash2Atoms(ic.residues[residueid], ic.atoms));
|
|
31228
|
+
}
|
|
30956
31229
|
}
|
|
30957
|
-
}
|
|
30958
|
-
let offsetTmp = 0, nComp = 3;
|
|
30959
|
-
for (let i = 0, lim = pnts.length - 1; i < lim; ++i) {
|
|
30960
|
-
let reg = 0;
|
|
30961
|
-
//var r1 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv]).lengthSq();
|
|
30962
|
-
//var r2 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv + 1]).lengthSq();
|
|
30963
|
-
let pos = offsetTmp * nComp;
|
|
30964
|
-
let point1 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
30965
|
-
pos = (offsetTmp + circleDiv) * nComp;
|
|
30966
|
-
let point2 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
30967
|
-
pos = (offsetTmp + circleDiv + 1) * nComp;
|
|
30968
|
-
let point3 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
30969
31230
|
|
|
30970
|
-
|
|
30971
|
-
let
|
|
30972
|
-
|
|
30973
|
-
//geo.faces.push(new THREE.Face3(offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv, undefined, c));
|
|
30974
|
-
//geo.faces.push(new THREE.Face3(offset + (j + 1) % circleDiv, offset + (j + reg) % circleDiv + circleDiv, offset + (j + reg + 1) % circleDiv + circleDiv, undefined, c));
|
|
30975
|
-
//indexArray = indexArray.concat([offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv]);
|
|
30976
|
-
indexArray[offset3++] = offsetTmp + j;
|
|
30977
|
-
indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
|
|
30978
|
-
indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
|
|
31231
|
+
// fill the end
|
|
31232
|
+
let endResi = lastAtom.resi;
|
|
31233
|
+
// 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.
|
|
30979
31234
|
|
|
30980
|
-
|
|
30981
|
-
indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
|
|
30982
|
-
indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
|
|
30983
|
-
indexArray[offset3++] = offsetTmp + (j + reg + 1) % circleDiv + circleDiv;
|
|
30984
|
-
}
|
|
30985
|
-
offsetTmp += circleDiv;
|
|
30986
|
-
}
|
|
31235
|
+
if(lastAtom.ss !== undefined && lastAtom.ss !== 'coil' && !(lastAtom.ssend) && !(lastAtom.notshow)) {
|
|
30987
31236
|
|
|
30988
|
-
|
|
30989
|
-
|
|
31237
|
+
let endChainResi = ic.firstAtomObjCls.getLastAtomObj(ic.chains[lastAtom.structure + '_' + lastAtom.chain]).resi;
|
|
31238
|
+
for(let i = parseInt(lastAtom.resi) + 1; i <= parseInt(endChainResi); ++i) {
|
|
31239
|
+
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + i;
|
|
31240
|
+
if(!ic.residues.hasOwnProperty(residueid)) break;
|
|
30990
31241
|
|
|
30991
|
-
|
|
30992
|
-
//geo.setIndex(indexArray);
|
|
31242
|
+
let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[residueid]);
|
|
30993
31243
|
|
|
30994
|
-
|
|
30995
|
-
|
|
30996
|
-
|
|
31244
|
+
if(atom.ss === lastAtom.ss && atom.ssend) {
|
|
31245
|
+
endResi = atom.resi;
|
|
31246
|
+
break;
|
|
31247
|
+
}
|
|
31248
|
+
}
|
|
30997
31249
|
|
|
30998
|
-
|
|
30999
|
-
|
|
31000
|
-
|
|
31001
|
-
|
|
31250
|
+
for(let i = parseInt(lastAtom.resi) + 1; i <= parseInt(endResi); ++i) {
|
|
31251
|
+
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + i;
|
|
31252
|
+
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
31253
|
+
ic.atoms));
|
|
31254
|
+
}
|
|
31255
|
+
}
|
|
31002
31256
|
|
|
31003
|
-
|
|
31004
|
-
|
|
31005
|
-
|
|
31006
|
-
|
|
31007
|
-
|
|
31008
|
-
|
|
31009
|
-
|
|
31010
|
-
|
|
31011
|
-
|
|
31012
|
-
//mesh = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({ specular: ic.frac, shininess: ic.shininess, emissive: ic.emissive, vertexColors: THREE.FaceColors, side: THREE.DoubleSide }));
|
|
31013
|
-
mesh = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({ specular: ic.frac, shininess: ic.shininess, emissive: ic.emissive, vertexColors: true, side: THREE.DoubleSide }));
|
|
31257
|
+
// add one extra residue for coils between strands/helix
|
|
31258
|
+
if(ic.pk === 3 && bHighlight === 1 && lastAtom.ss === 'coil') {
|
|
31259
|
+
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + (parseInt(lastAtom.resi) + 1).toString();
|
|
31260
|
+
if(ic.residues.hasOwnProperty(residueid)) {
|
|
31261
|
+
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
31262
|
+
ic.atoms));
|
|
31263
|
+
atoms = me.hashUtilsCls.unionHash(atoms, me.hashUtilsCls.hash2Atoms(ic.residues[residueid], ic.atoms));
|
|
31264
|
+
}
|
|
31265
|
+
}
|
|
31014
31266
|
|
|
31015
|
-
|
|
31016
|
-
|
|
31267
|
+
// reset notshow
|
|
31268
|
+
if(lastAtom.notshow) lastAtom.notshow = undefined;
|
|
31017
31269
|
|
|
31018
|
-
|
|
31019
|
-
|
|
31020
|
-
}
|
|
31021
|
-
else {
|
|
31022
|
-
ic.objects.push(mesh);
|
|
31023
|
-
}
|
|
31024
|
-
}
|
|
31270
|
+
firstAtom = currAtom;
|
|
31271
|
+
}
|
|
31025
31272
|
|
|
31026
|
-
|
|
31027
|
-
|
|
31028
|
-
|
|
31029
|
-
|
|
31030
|
-
|
|
31031
|
-
else {
|
|
31032
|
-
if(atom.b > 0 && atom.b <= 100) {
|
|
31033
|
-
radiusFinal = atom.b * 0.01;
|
|
31034
|
-
}
|
|
31035
|
-
else if(atom.b > 100) {
|
|
31036
|
-
radiusFinal = 100 * 0.01;
|
|
31037
|
-
}
|
|
31038
|
-
else {
|
|
31039
|
-
radiusFinal = ic.coilWidth;
|
|
31040
|
-
}
|
|
31273
|
+
prevChain = currChain;
|
|
31274
|
+
prevResi = currResi;
|
|
31275
|
+
prevAtom = currAtom;
|
|
31276
|
+
|
|
31277
|
+
++index;
|
|
31041
31278
|
}
|
|
31042
31279
|
|
|
31043
|
-
return
|
|
31280
|
+
return atomsAdjust;
|
|
31044
31281
|
}
|
|
31045
31282
|
}
|
|
31046
31283
|
|
|
@@ -38058,6 +38295,11 @@ class Alternate {
|
|
|
38058
38295
|
ic.directionalLight.position.copy(ic.lightPos.clone().applyQuaternion( quaternion ).normalize());
|
|
38059
38296
|
ic.directionalLight2.position.copy(ic.lightPos2.clone().applyQuaternion( quaternion ).normalize());
|
|
38060
38297
|
ic.directionalLight3.position.copy(ic.lightPos3.clone().applyQuaternion( quaternion ).normalize());
|
|
38298
|
+
|
|
38299
|
+
// adjust the light according to the position of camera
|
|
38300
|
+
ic.directionalLight.applyMatrix4(cam.matrixWorld);
|
|
38301
|
+
ic.directionalLight2.applyMatrix4(cam.matrixWorld);
|
|
38302
|
+
ic.directionalLight3.applyMatrix4(cam.matrixWorld);
|
|
38061
38303
|
}
|
|
38062
38304
|
|
|
38063
38305
|
if(!ic.bVr) ic.renderer.setPixelRatio( window.devicePixelRatio ); // r71
|
|
@@ -48689,6 +48931,13 @@ class ShowAnno {
|
|
|
48689
48931
|
} // align seq to structure
|
|
48690
48932
|
}
|
|
48691
48933
|
//ic.bAnnoShown = true;
|
|
48934
|
+
|
|
48935
|
+
if($("#" + ic.pre + "anno_ig").length && $("#" + ic.pre + "anno_ig")[0].checked) {
|
|
48936
|
+
ic.bRunRefnumAgain = true;
|
|
48937
|
+
await ic.annotationCls.setAnnoTabIg();
|
|
48938
|
+
|
|
48939
|
+
ic.bRunRefnumAgain = false;
|
|
48940
|
+
}
|
|
48692
48941
|
}
|
|
48693
48942
|
|
|
48694
48943
|
async showAnnoSeqData(nucleotide_chainid, chemical_chainid, chemical_set) { let ic = this.icn3d, me = ic.icn3dui;
|
|
@@ -54423,6 +54672,7 @@ class AlignParser {
|
|
|
54423
54672
|
|
|
54424
54673
|
async downloadAlignmentPart2(data, seqalign, chainresiCalphaHash2) { let ic = this.icn3d, me = ic.icn3dui;
|
|
54425
54674
|
//ic.init();
|
|
54675
|
+
|
|
54426
54676
|
ic.loadAtomDataCls.loadAtomDataIn(data, undefined, 'align', seqalign);
|
|
54427
54677
|
|
|
54428
54678
|
if(me.cfg.align === undefined && Object.keys(ic.structures).length == 1) {
|
|
@@ -54466,20 +54716,21 @@ class AlignParser {
|
|
|
54466
54716
|
async loadOpmDataForAlign(data, seqalign, mmdbidArray) { let ic = this.icn3d, me = ic.icn3dui;
|
|
54467
54717
|
let thisClass = this;
|
|
54468
54718
|
|
|
54469
|
-
let url = "https://opm-assets.storage.googleapis.com/pdb/" + mmdbidArray[0].toLowerCase()+ ".pdb";
|
|
54470
|
-
let prms1 = me.getAjaxPromise(url, 'text');
|
|
54471
|
-
let url2 = "https://opm-assets.storage.googleapis.com/pdb/" + mmdbidArray[1].toLowerCase()+ ".pdb";
|
|
54472
|
-
let prms2 = me.getAjaxPromise(url2, 'text');
|
|
54473
|
-
|
|
54474
|
-
let allPromise = Promise.allSettled([prms1, prms2]);
|
|
54475
54719
|
try {
|
|
54720
|
+
let url = "https://opm-assets.storage.googleapis.com/pdb/" + mmdbidArray[0].toLowerCase()+ ".pdb";
|
|
54721
|
+
let prms1 = me.getAjaxPromise(url, 'text');
|
|
54722
|
+
let url2 = "https://opm-assets.storage.googleapis.com/pdb/" + mmdbidArray[1].toLowerCase()+ ".pdb";
|
|
54723
|
+
let prms2 = me.getAjaxPromise(url2, 'text');
|
|
54724
|
+
|
|
54725
|
+
let allPromise = Promise.allSettled([prms1, prms2]);
|
|
54726
|
+
|
|
54476
54727
|
let dataArray = await allPromise;
|
|
54477
|
-
|
|
54728
|
+
|
|
54478
54729
|
let bFound = false;
|
|
54479
54730
|
for(let i = 0, il = dataArray.length; i < il; ++i) {
|
|
54480
|
-
//
|
|
54481
|
-
let opmdata = dataArray[i].value;
|
|
54731
|
+
// if(dataArray[i].status == 'rejected') continue;
|
|
54482
54732
|
|
|
54733
|
+
let opmdata = dataArray[i].value;
|
|
54483
54734
|
if(!opmdata) continue;
|
|
54484
54735
|
|
|
54485
54736
|
ic.selectedPdbid = mmdbidArray[i];
|
|
@@ -54495,6 +54746,7 @@ class AlignParser {
|
|
|
54495
54746
|
$("#" + ic.pre + "intra_mem_z").val(-ic.halfBilayerSize);
|
|
54496
54747
|
|
|
54497
54748
|
ic.init(); // remove all previously loaded data
|
|
54749
|
+
|
|
54498
54750
|
await thisClass.downloadAlignmentPart2(data, seqalign, chainresiCalphaHash);
|
|
54499
54751
|
|
|
54500
54752
|
bFound = true;
|
|
@@ -59070,7 +59322,7 @@ class SdfParser {
|
|
|
59070
59322
|
let sdfStr = await me.getAjaxPromise(urlSmiles, 'text');
|
|
59071
59323
|
|
|
59072
59324
|
ic.init();
|
|
59073
|
-
ic.bInputfile = true;
|
|
59325
|
+
//ic.bInputfile = true;
|
|
59074
59326
|
ic.InputfileData = (ic.InputfileData) ? ic.InputfileData + '\nENDMDL\n' + sdfStr : sdfStr;
|
|
59075
59327
|
ic.InputfileType = 'sdf';
|
|
59076
59328
|
await ic.sdfParserCls.loadSdfData(sdfStr);
|
|
@@ -61879,6 +62131,7 @@ class ParserUtils {
|
|
|
61879
62131
|
ic.selectionCls.oneStructurePerWindow(); // for alignment
|
|
61880
62132
|
ic.drawCls.draw();
|
|
61881
62133
|
}
|
|
62134
|
+
|
|
61882
62135
|
if(ic.bOpm) {
|
|
61883
62136
|
let axis = new THREE.Vector3(1,0,0);
|
|
61884
62137
|
let angle = -0.5 * Math.PI;
|
|
@@ -64416,7 +64669,8 @@ class LoadPDB {
|
|
|
64416
64669
|
|
|
64417
64670
|
// modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
64418
64671
|
//This PDB parser feeds the viewer with the content of a PDB file, pdbData.
|
|
64419
|
-
async loadPDB(src, pdbid, bOpm, bVector, bMutation, bAppend, type, bEsmfold) { let ic = this.icn3d, me = ic.icn3dui;
|
|
64672
|
+
// async loadPDB(src, pdbid, bOpm, bVector, bMutation, bAppend, type, bEsmfold) { let ic = this.icn3d, me = ic.icn3dui;
|
|
64673
|
+
loadPDB(src, pdbid, bOpm, bVector, bMutation, bAppend, type, bEsmfold) { let ic = this.icn3d, me = ic.icn3dui;
|
|
64420
64674
|
let hAtoms = {};
|
|
64421
64675
|
|
|
64422
64676
|
let bNMR = false;
|
|
@@ -69537,17 +69791,15 @@ class SelectCollections {
|
|
|
69537
69791
|
}
|
|
69538
69792
|
|
|
69539
69793
|
//Set the menu of defined sets with an array of defined names "commandnameArray".
|
|
69540
|
-
setAtomMenu(
|
|
69794
|
+
setAtomMenu(collection) {
|
|
69541
69795
|
let ic = this.icn3d;
|
|
69542
69796
|
ic.icn3dui;
|
|
69543
69797
|
let html = "";
|
|
69544
|
-
|
|
69545
|
-
|
|
69546
|
-
let name = nameArray[i][0];
|
|
69547
|
-
let title = nameArray[i][1];
|
|
69548
|
-
let description = nameArray[i][2];
|
|
69549
|
-
|
|
69798
|
+
|
|
69799
|
+
Object.entries(collection).forEach(([name, structure], index) => {
|
|
69550
69800
|
let atomHash;
|
|
69801
|
+
let [id, title, description, commands, pdb] = structure;
|
|
69802
|
+
|
|
69551
69803
|
if (
|
|
69552
69804
|
ic.defNames2Atoms !== undefined &&
|
|
69553
69805
|
ic.defNames2Atoms.hasOwnProperty(name)
|
|
@@ -69568,12 +69820,12 @@ class SelectCollections {
|
|
|
69568
69820
|
}
|
|
69569
69821
|
}
|
|
69570
69822
|
|
|
69571
|
-
if (
|
|
69572
|
-
html += "<option value='" +
|
|
69573
|
-
|
|
69823
|
+
if (index === 0) {
|
|
69824
|
+
html += "<option value='" + name + "' selected='selected' data-description='" + description + "'>" + title + "</option>";
|
|
69825
|
+
} else {
|
|
69574
69826
|
html += "<option value='" + name + "' data-description='" + description + "'>" + title + "</option>";
|
|
69575
|
-
|
|
69576
|
-
}
|
|
69827
|
+
}
|
|
69828
|
+
});
|
|
69577
69829
|
|
|
69578
69830
|
return html;
|
|
69579
69831
|
}
|
|
@@ -69627,7 +69879,7 @@ class SelectCollections {
|
|
|
69627
69879
|
let nameArray = $(this).val();
|
|
69628
69880
|
let nameStructure = $(this).find("option:selected").text();
|
|
69629
69881
|
let selectedIndices = Array.from(this.selectedOptions).map(option => option.index);
|
|
69630
|
-
|
|
69882
|
+
nameArray.reduce((map, name, i) => {
|
|
69631
69883
|
map[name] = selectedIndices[i];
|
|
69632
69884
|
return map;
|
|
69633
69885
|
}, {});
|
|
@@ -69664,13 +69916,13 @@ class SelectCollections {
|
|
|
69664
69916
|
if (Object.keys(ic.structures).length == 0) {
|
|
69665
69917
|
bAppend = false;
|
|
69666
69918
|
}
|
|
69667
|
-
await ic.pdbParserCls.loadPdbData(ic.pdbCollection[
|
|
69919
|
+
await ic.pdbParserCls.loadPdbData(ic.pdbCollection[name].join('\n'), undefined, undefined, bAppend);
|
|
69668
69920
|
} else {
|
|
69669
69921
|
await ic.chainalignParserCls.downloadMmdbAf(name, undefined, undefined, bNoDuplicate);
|
|
69670
69922
|
}
|
|
69671
69923
|
}
|
|
69672
69924
|
|
|
69673
|
-
await loadStructure(collection[
|
|
69925
|
+
await loadStructure(collection[name][4]).then(() => {
|
|
69674
69926
|
ic.allData['all'] = {
|
|
69675
69927
|
'atoms': ic.atoms,
|
|
69676
69928
|
'proteins': ic.proteins,
|
|
@@ -69730,9 +69982,9 @@ class SelectCollections {
|
|
|
69730
69982
|
|
|
69731
69983
|
ic.molTitle = ic.allData[name]['title'];
|
|
69732
69984
|
|
|
69733
|
-
if (collection[
|
|
69985
|
+
if (collection[name][3] !== undefined && collection[name][3].length > 0) {
|
|
69734
69986
|
if (ic.allData[name]['commands'] == undefined) {
|
|
69735
|
-
let commands = collection[
|
|
69987
|
+
let commands = collection[name][3];
|
|
69736
69988
|
ic.allData[name]['commands'] = commands;
|
|
69737
69989
|
}
|
|
69738
69990
|
}
|
|
@@ -70001,7 +70253,9 @@ class LoadScript {
|
|
|
70001
70253
|
}
|
|
70002
70254
|
else if(command.indexOf('view interactions') == 0 && me.cfg.align !== undefined) { // the command may have "|||{"factor"...
|
|
70003
70255
|
await thisClass.applyCommandViewinteraction(strArray[0].trim());
|
|
70004
|
-
|
|
70256
|
+
}
|
|
70257
|
+
else if(command.indexOf('view 2d depiction') == 0) { // the command may have "|||{"factor"...
|
|
70258
|
+
await ic.ligplotCls.drawLigplot(ic.atoms, true);
|
|
70005
70259
|
}
|
|
70006
70260
|
else if(command.indexOf('symmetry') == 0) {
|
|
70007
70261
|
ic.bAxisOnly = false;
|
|
@@ -70211,6 +70465,9 @@ class LoadScript {
|
|
|
70211
70465
|
else if(lastCommand.indexOf('view interactions') == 0 && me.cfg.align !== undefined) {
|
|
70212
70466
|
await thisClass.applyCommandViewinteraction(lastCommand);
|
|
70213
70467
|
}
|
|
70468
|
+
else if(lastCommand.indexOf('view 2d depiction') == 0) {
|
|
70469
|
+
await ic.ligplotCls.drawLigplot(ic.atoms, true);
|
|
70470
|
+
}
|
|
70214
70471
|
else if(lastCommand.indexOf('symmetry') == 0) {
|
|
70215
70472
|
let title = lastCommand.substr(lastCommand.indexOf(' ') + 1);
|
|
70216
70473
|
ic.symmetrytitle =(title === 'none') ? undefined : title;
|
|
@@ -72369,155 +72626,6 @@ class Resid2spec {
|
|
|
72369
72626
|
}
|
|
72370
72627
|
}
|
|
72371
72628
|
|
|
72372
|
-
/**
|
|
72373
|
-
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
72374
|
-
*/
|
|
72375
|
-
|
|
72376
|
-
class FirstAtomObj {
|
|
72377
|
-
constructor(icn3d) {
|
|
72378
|
-
this.icn3d = icn3d;
|
|
72379
|
-
}
|
|
72380
|
-
|
|
72381
|
-
//Return the first atom in the atom hash, which has the atom serial number as the key.
|
|
72382
|
-
getFirstAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
72383
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
72384
|
-
return undefined;
|
|
72385
|
-
}
|
|
72386
|
-
|
|
72387
|
-
let atomKeys = Object.keys(atomsHash);
|
|
72388
|
-
let firstIndex = atomKeys[0];
|
|
72389
|
-
|
|
72390
|
-
return ic.atoms[firstIndex];
|
|
72391
|
-
}
|
|
72392
|
-
|
|
72393
|
-
// n is the position of the selected atom
|
|
72394
|
-
getMiddleAtomObj(atomsHash, n) { let ic = this.icn3d; ic.icn3dui;
|
|
72395
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
72396
|
-
return undefined;
|
|
72397
|
-
}
|
|
72398
|
-
|
|
72399
|
-
let atomKeys = Object.keys(atomsHash);
|
|
72400
|
-
let middleIndex = (n && n < atomKeys.length) ? atomKeys[n] : atomKeys[parseInt(atomKeys.length / 2)];
|
|
72401
|
-
|
|
72402
|
-
return ic.atoms[middleIndex];
|
|
72403
|
-
}
|
|
72404
|
-
|
|
72405
|
-
getFirstCalphaAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
72406
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
72407
|
-
return undefined;
|
|
72408
|
-
}
|
|
72409
|
-
|
|
72410
|
-
let firstIndex;
|
|
72411
|
-
|
|
72412
|
-
for(let i in atomsHash) {
|
|
72413
|
-
if(ic.atoms[i].name == 'CA') {
|
|
72414
|
-
firstIndex = i;
|
|
72415
|
-
break;
|
|
72416
|
-
}
|
|
72417
|
-
}
|
|
72418
|
-
|
|
72419
|
-
if(!firstIndex) {
|
|
72420
|
-
for(let i in atomsHash) {
|
|
72421
|
-
if(ic.atoms[i].name == "O3'" || ic.atoms[i].name == "O3*") {
|
|
72422
|
-
firstIndex = i;
|
|
72423
|
-
break;
|
|
72424
|
-
}
|
|
72425
|
-
}
|
|
72426
|
-
}
|
|
72427
|
-
|
|
72428
|
-
return (firstIndex !== undefined) ? ic.atoms[firstIndex] : this.getFirstAtomObj(atomsHash);
|
|
72429
|
-
}
|
|
72430
|
-
|
|
72431
|
-
getFirstAtomObjByName(atomsHash, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
72432
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
72433
|
-
return ic.atoms[0];
|
|
72434
|
-
}
|
|
72435
|
-
|
|
72436
|
-
let firstIndex;
|
|
72437
|
-
|
|
72438
|
-
for(let i in atomsHash) {
|
|
72439
|
-
if(ic.atoms[i].name == atomName) {
|
|
72440
|
-
firstIndex = i;
|
|
72441
|
-
break;
|
|
72442
|
-
}
|
|
72443
|
-
}
|
|
72444
|
-
|
|
72445
|
-
return (firstIndex !== undefined) ? ic.atoms[firstIndex] : undefined;
|
|
72446
|
-
}
|
|
72447
|
-
|
|
72448
|
-
//Return the last atom in the atom hash, which has the atom serial number as the key.
|
|
72449
|
-
getLastAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
72450
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
72451
|
-
return ic.atoms[0];
|
|
72452
|
-
}
|
|
72453
|
-
|
|
72454
|
-
let atomKeys = Object.keys(atomsHash);
|
|
72455
|
-
let lastIndex = atomKeys[atomKeys.length - 1];
|
|
72456
|
-
|
|
72457
|
-
return ic.atoms[lastIndex];
|
|
72458
|
-
}
|
|
72459
|
-
|
|
72460
|
-
//Return the residue hash from the atom hash. The residue hash has the resid as the key and 1 as the value.
|
|
72461
|
-
getResiduesFromAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
72462
|
-
let residuesHash = {};
|
|
72463
|
-
for(let i in atomsHash) {
|
|
72464
|
-
let residueid = ic.atoms[i].structure + '_' + ic.atoms[i].chain + '_' + ic.atoms[i].resi;
|
|
72465
|
-
residuesHash[residueid] = 1;
|
|
72466
|
-
}
|
|
72467
|
-
|
|
72468
|
-
return residuesHash;
|
|
72469
|
-
}
|
|
72470
|
-
|
|
72471
|
-
getResiduesFromCalphaAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
72472
|
-
let residuesHash = {};
|
|
72473
|
-
for(let i in atomsHash) {
|
|
72474
|
-
if((ic.atoms[i].name == 'CA' && ic.proteins.hasOwnProperty(i)) || !ic.proteins.hasOwnProperty(i)) {
|
|
72475
|
-
let residueid = ic.atoms[i].structure + '_' + ic.atoms[i].chain + '_' + ic.atoms[i].resi;
|
|
72476
|
-
//residuesHash[residueid] = 1;
|
|
72477
|
-
residuesHash[residueid] = ic.atoms[i].resn;
|
|
72478
|
-
}
|
|
72479
|
-
}
|
|
72480
|
-
|
|
72481
|
-
return residuesHash;
|
|
72482
|
-
}
|
|
72483
|
-
|
|
72484
|
-
//Return the chain hash from the atom hash. The chain hash has the chainid as the key and 1 as the value.
|
|
72485
|
-
getChainsFromAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
72486
|
-
let chainsHash = {};
|
|
72487
|
-
for(let i in atomsHash) {
|
|
72488
|
-
let atom = ic.atoms[i];
|
|
72489
|
-
let chainid = atom.structure + "_" + atom.chain;
|
|
72490
|
-
|
|
72491
|
-
chainsHash[chainid] = 1;
|
|
72492
|
-
}
|
|
72493
|
-
|
|
72494
|
-
return chainsHash;
|
|
72495
|
-
}
|
|
72496
|
-
|
|
72497
|
-
getAtomFromResi(resid, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
72498
|
-
if(ic.residues.hasOwnProperty(resid)) {
|
|
72499
|
-
for(let i in ic.residues[resid]) {
|
|
72500
|
-
if(ic.atoms[i].name === atomName && !ic.atoms[i].het) {
|
|
72501
|
-
return ic.atoms[i];
|
|
72502
|
-
}
|
|
72503
|
-
}
|
|
72504
|
-
}
|
|
72505
|
-
|
|
72506
|
-
return undefined;
|
|
72507
|
-
}
|
|
72508
|
-
|
|
72509
|
-
getAtomCoordFromResi(resid, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
72510
|
-
let atom = this.getAtomFromResi(resid, atomName);
|
|
72511
|
-
if(atom !== undefined) {
|
|
72512
|
-
let coord = (atom.coord2 !== undefined) ? atom.coord2 : atom.coord;
|
|
72513
|
-
|
|
72514
|
-
return coord;
|
|
72515
|
-
}
|
|
72516
|
-
|
|
72517
|
-
return undefined;
|
|
72518
|
-
}
|
|
72519
|
-
}
|
|
72520
|
-
|
|
72521
72629
|
/**
|
|
72522
72630
|
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
72523
72631
|
*/
|
|
@@ -72578,9 +72686,9 @@ class Delphi {
|
|
|
72578
72686
|
let pdbstr = '';
|
|
72579
72687
|
/// pdbstr += ic.saveFileCls.getPDBHeader();
|
|
72580
72688
|
|
|
72581
|
-
let bMergeIntoOne = true;
|
|
72582
|
-
pdbstr +=(me.cfg.cid) ? ic.saveFileCls.getAtomPDB(atomHash, true, undefined, undefined, undefined, undefined, bMergeIntoOne) : ic.saveFileCls.getAtomPDB(atomHash, undefined, undefined, undefined, undefined, undefined, bMergeIntoOne);
|
|
72583
|
-
pdbstr += ic.saveFileCls.getAtomPDB(ionHash, true, undefined, true);
|
|
72689
|
+
let bMergeIntoOne = true, bOneLetterChain = true;
|
|
72690
|
+
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);
|
|
72691
|
+
pdbstr += ic.saveFileCls.getAtomPDB(ionHash, true, undefined, true, undefined, undefined, bMergeIntoOne, bOneLetterChain);
|
|
72584
72692
|
|
|
72585
72693
|
return pdbstr;
|
|
72586
72694
|
}
|
|
@@ -78594,8 +78702,13 @@ class Ligplot {
|
|
|
78594
78702
|
this.icn3d = icn3d;
|
|
78595
78703
|
}
|
|
78596
78704
|
|
|
78597
|
-
async drawLigplot(atomSet1) { let ic = this.icn3d, me = ic.icn3dui;
|
|
78598
|
-
|
|
78705
|
+
async drawLigplot(atomSet1, bDepiction) { let ic = this.icn3d, me = ic.icn3dui;
|
|
78706
|
+
if(bDepiction) {
|
|
78707
|
+
me.htmlCls.dialogCls.openDlg('dl_ligplot', '2D Depiction');
|
|
78708
|
+
}
|
|
78709
|
+
else {
|
|
78710
|
+
me.htmlCls.dialogCls.openDlg('dl_ligplot', 'Show ligand interactions with atom details');
|
|
78711
|
+
}
|
|
78599
78712
|
|
|
78600
78713
|
let widthOri, heightOri, width = 100, height = 100;
|
|
78601
78714
|
ic.len4ang = 80;
|
|
@@ -78677,19 +78790,28 @@ class Ligplot {
|
|
|
78677
78790
|
let offset = - ic.len4ang;
|
|
78678
78791
|
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'>";
|
|
78679
78792
|
|
|
78680
|
-
|
|
78681
|
-
|
|
78682
|
-
|
|
78793
|
+
if(bDepiction) {
|
|
78794
|
+
svgHtml += lineSvg + nodeSvg;
|
|
78795
|
+
}
|
|
78796
|
+
else {
|
|
78797
|
+
let xlen = parseInt(widthOri / ic.svgGridSize), ylen = parseInt(heightOri / ic.svgGridSize);
|
|
78798
|
+
let result = ic.viewInterPairsCls.getAllInteractionTable("save1", index2xy, xlen, ylen, xcenter, ycenter); // sort on the ligand/set1
|
|
78799
|
+
// ic.bLigplot = true;
|
|
78683
78800
|
|
|
78684
|
-
|
|
78801
|
+
svgHtml += lineSvg + result.svgHtmlLine;
|
|
78685
78802
|
|
|
78686
|
-
|
|
78803
|
+
svgHtml += nodeSvg + result.svgHtmlNode;
|
|
78804
|
+
}
|
|
78687
78805
|
|
|
78688
78806
|
svgHtml += "</svg>";
|
|
78689
78807
|
|
|
78690
|
-
|
|
78691
|
-
|
|
78692
|
-
|
|
78808
|
+
if(bDepiction) {
|
|
78809
|
+
$("#" + ic.pre + "ligplotDiv").html(svgHtml);
|
|
78810
|
+
}
|
|
78811
|
+
else {
|
|
78812
|
+
$("#" + ic.pre + "ligplotDiv").html(svgHtml);
|
|
78813
|
+
this.setEventsForLigplot();
|
|
78814
|
+
}
|
|
78693
78815
|
}
|
|
78694
78816
|
|
|
78695
78817
|
|
|
@@ -79836,7 +79958,7 @@ class SaveFile {
|
|
|
79836
79958
|
}
|
|
79837
79959
|
|
|
79838
79960
|
//getAtomPDB: function(atomHash, bPqr, bPdb, bNoChem) { let ic = this.icn3d, me = ic.icn3dui;
|
|
79839
|
-
getAtomPDB(atomHash, bPqr, bNoChem, bNoHeader, chainResi2pdb, pdbid, bMergeIntoOne,
|
|
79961
|
+
getAtomPDB(atomHash, bPqr, bNoChem, bNoHeader, chainResi2pdb, pdbid, bMergeIntoOne, bOneLetterChain) { let ic = this.icn3d, me = ic.icn3dui;
|
|
79840
79962
|
let pdbStr = '';
|
|
79841
79963
|
|
|
79842
79964
|
// get all phosphate groups in lipids
|
|
@@ -80111,7 +80233,7 @@ class SaveFile {
|
|
|
80111
80233
|
//line +=(atom.chain.length <= 1) ? atom.chain.padStart(1, ' ') : atom.chain.substr(0, 1);
|
|
80112
80234
|
if(atom.chain.length >= 2) {
|
|
80113
80235
|
let chainTmp = atom.chain.replace(/_/gi, '').substr(0, 2);
|
|
80114
|
-
if(
|
|
80236
|
+
if(bOneLetterChain) chainTmp = ' ' + chainTmp.substr(0,1); // VAST search only support one lettter chain ID
|
|
80115
80237
|
line += chainTmp;
|
|
80116
80238
|
}
|
|
80117
80239
|
else if(atom.chain.length == 1) {
|
|
@@ -80190,8 +80312,8 @@ class SaveFile {
|
|
|
80190
80312
|
}
|
|
80191
80313
|
else {
|
|
80192
80314
|
line += "1.00".padStart(6, ' ');
|
|
80193
|
-
//
|
|
80194
|
-
let defaultBFactor =
|
|
80315
|
+
// let defaultBFactor = (bOneLetterChain) ? "1.0" : " ";
|
|
80316
|
+
let defaultBFactor = " ";
|
|
80195
80317
|
line +=(atom.b) ? parseFloat(atom.b).toFixed(2).toString().padStart(6, ' ') : defaultBFactor.padStart(6, ' ');
|
|
80196
80318
|
line += ' '.padStart(10, ' ');
|
|
80197
80319
|
line += atom.elem.padStart(2, ' ');
|
|
@@ -80239,7 +80361,7 @@ class SaveFile {
|
|
|
80239
80361
|
let resn = me.utilsCls.residueName2Abbr(atom.resn);
|
|
80240
80362
|
let ss = this.secondary2Abbr(atom.ss);
|
|
80241
80363
|
|
|
80242
|
-
if(chainid != prevChainid) {
|
|
80364
|
+
if(chainid != prevChainid && !data[chainid]) {
|
|
80243
80365
|
data[chainid] = {"resi": [], "resn": [], "secondary": []};
|
|
80244
80366
|
}
|
|
80245
80367
|
|
|
@@ -83763,7 +83885,7 @@ class iCn3DUI {
|
|
|
83763
83885
|
//even when multiple iCn3D viewers are shown together.
|
|
83764
83886
|
this.pre = this.cfg.divid + "_";
|
|
83765
83887
|
|
|
83766
|
-
this.REVISION = '3.
|
|
83888
|
+
this.REVISION = '3.40.3';
|
|
83767
83889
|
|
|
83768
83890
|
// In nodejs, iCn3D defines "window = {navigator: {}}"
|
|
83769
83891
|
this.bNode = (Object.keys(window).length < 2) ? true : false;
|
|
@@ -83925,7 +84047,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
|
|
|
83925
84047
|
ic.molTitle = '';
|
|
83926
84048
|
ic.loadCmd;
|
|
83927
84049
|
|
|
83928
|
-
// set menus
|
|
84050
|
+
// set menus
|
|
83929
84051
|
me.htmlCls.clickMenuCls.getHiddenMenusFromCache();
|
|
83930
84052
|
me.htmlCls.clickMenuCls.applyShownMenus();
|
|
83931
84053
|
|