icn3d 3.40.0 → 3.40.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/icn3d.js +1183 -1102
- package/icn3d.min.js +4 -4
- package/icn3d.module.js +1183 -1102
- 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
|
|
@@ -14498,7 +14579,7 @@ class Dialog {
|
|
|
14498
14579
|
width='50%';
|
|
14499
14580
|
}
|
|
14500
14581
|
else if(id === me.pre + 'dl_menupref') {
|
|
14501
|
-
width =
|
|
14582
|
+
width = 800;
|
|
14502
14583
|
height = 500;
|
|
14503
14584
|
}
|
|
14504
14585
|
|
|
@@ -15159,6 +15240,10 @@ class SetDialog {
|
|
|
15159
15240
|
html += me.htmlCls.divStr + "dl_collection_file' style=''>";
|
|
15160
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>";
|
|
15161
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/>";
|
|
15162
15247
|
html += me.htmlCls.buttonStr + "reload_collectionfile' style='margin-top: 6px;'>Load</button>";
|
|
15163
15248
|
html += "</div>";
|
|
15164
15249
|
html += "</div>";
|
|
@@ -15166,7 +15251,8 @@ class SetDialog {
|
|
|
15166
15251
|
html += me.htmlCls.divStr + "dl_collection_structures' style='display: none'>";
|
|
15167
15252
|
html += "<select id='" + me.pre + "collections_menu'multiple size='6' style='min-width:300px;'></select>";
|
|
15168
15253
|
html += '<br/>';
|
|
15169
|
-
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>";
|
|
15170
15256
|
html += "</div>";
|
|
15171
15257
|
html += '<br/>';
|
|
15172
15258
|
html += "</div>";
|
|
@@ -15871,13 +15957,15 @@ class SetDialog {
|
|
|
15871
15957
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "apply_menupref'>Apply</button></span>";
|
|
15872
15958
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "reset_menupref' style='margin-left:30px'>Reset to Simple Menus</button></span>";
|
|
15873
15959
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "reset_menupref_all' style='margin-left:30px'>Reset to All Menus</button></span>";
|
|
15874
|
-
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>";
|
|
15875
15962
|
|
|
15876
15963
|
html += "<div id='" + me.pre + "menulist'></div><br><br>";
|
|
15877
15964
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "apply_menupref2'>Apply</button></span>";
|
|
15878
15965
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "reset_menupref2' style='margin-left:30px'>Reset to Simple Menus</button></span>";
|
|
15879
15966
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "reset_menupref_all2' style='margin-left:30px'>Reset to All Menus</button></span>";
|
|
15880
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>";
|
|
15881
15969
|
html += "</div>";
|
|
15882
15970
|
|
|
15883
15971
|
html += me.htmlCls.divStr + "dl_addtrack' class='" + dialogClass + "'>";
|
|
@@ -16653,6 +16741,14 @@ class Events {
|
|
|
16653
16741
|
me.htmlCls.clickMenuCls.clickMenu5();
|
|
16654
16742
|
me.htmlCls.clickMenuCls.clickMenu6();
|
|
16655
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
|
+
|
|
16656
16752
|
// back and forward arrows
|
|
16657
16753
|
me.myEventCls.onIds(["#" + me.pre + "back", "#" + me.pre + "mn6_back"], "click", async function(e) { let ic = me.icn3d;
|
|
16658
16754
|
e.preventDefault();
|
|
@@ -17699,95 +17795,108 @@ class Events {
|
|
|
17699
17795
|
} else {
|
|
17700
17796
|
ic.resizeCanvasCls.closeDialogs();
|
|
17701
17797
|
}
|
|
17702
|
-
|
|
17703
|
-
ic.pdbCollection = [];
|
|
17704
|
-
ic.allData = {};
|
|
17705
|
-
ic.allData['all'] = {
|
|
17706
|
-
'atoms': {},
|
|
17707
|
-
'proteins': {},
|
|
17708
|
-
'nucleotides': {},
|
|
17709
|
-
'chemicals': {},
|
|
17710
|
-
'ions': {},
|
|
17711
|
-
'water': {},
|
|
17712
|
-
'structures': {}, // getSSExpandedAtoms
|
|
17713
|
-
'ssbondpnts': {},
|
|
17714
|
-
'residues': {}, // getSSExpandedAtoms
|
|
17715
|
-
'chains': {},
|
|
17716
|
-
'chainsSeq': {}, //Sequences and Annotation
|
|
17717
|
-
'defNames2Atoms': {},
|
|
17718
|
-
'defNames2Residues': {}
|
|
17719
|
-
};
|
|
17720
|
-
ic.allData['prev'] = {};
|
|
17721
|
-
ic.selectCollectionsCls.reset();
|
|
17722
|
-
|
|
17798
|
+
|
|
17723
17799
|
ic.dAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
|
|
17724
17800
|
ic.hAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
|
|
17725
17801
|
me.htmlCls.setHtmlCls.fileSupport();
|
|
17726
17802
|
|
|
17727
17803
|
let fileName = file.name;
|
|
17728
17804
|
let fileExtension = fileName.split('.').pop().toLowerCase();
|
|
17729
|
-
|
|
17805
|
+
let collection = {};
|
|
17806
|
+
|
|
17730
17807
|
$("#" + ic.pre + "collections_menu").empty();
|
|
17731
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
|
+
}
|
|
17732
17837
|
|
|
17733
17838
|
function parseJsonCollection(data) {
|
|
17734
17839
|
let dataStr = JSON.parse(data);
|
|
17735
|
-
|
|
17840
|
+
let parsedCollection = {};
|
|
17841
|
+
|
|
17842
|
+
dataStr["structures"].map(({ id, title, description, commands }) => {
|
|
17736
17843
|
if (id && id.includes('.pdb')) {
|
|
17737
17844
|
id = id.split('.pdb')[0];
|
|
17738
17845
|
}
|
|
17739
|
-
|
|
17846
|
+
parsedCollection[id] = [id, title, description, commands, false];
|
|
17740
17847
|
});
|
|
17741
|
-
}
|
|
17742
17848
|
|
|
17849
|
+
return parsedCollection;
|
|
17850
|
+
}
|
|
17851
|
+
|
|
17743
17852
|
function parsePdbCollection(data, description = '', commands = []) {
|
|
17744
17853
|
let dataStr = data;
|
|
17745
17854
|
let lines = dataStr.split('\n');
|
|
17746
|
-
|
|
17747
17855
|
let sections = [];
|
|
17748
17856
|
let currentSection = [];
|
|
17749
|
-
|
|
17857
|
+
|
|
17750
17858
|
lines.forEach(line => {
|
|
17751
|
-
|
|
17859
|
+
if (line.startsWith('HEADER')) {
|
|
17752
17860
|
currentSection = [];
|
|
17753
17861
|
sections.push(currentSection);
|
|
17754
|
-
|
|
17755
|
-
|
|
17862
|
+
}
|
|
17863
|
+
currentSection.push(line);
|
|
17756
17864
|
});
|
|
17757
|
-
|
|
17758
|
-
|
|
17759
|
-
let
|
|
17760
|
-
|
|
17865
|
+
|
|
17866
|
+
|
|
17867
|
+
let parsedCollection = {};
|
|
17868
|
+
|
|
17761
17869
|
sections.forEach((section) => {
|
|
17762
|
-
let headerLine = section[0];
|
|
17763
|
-
headerLine = headerLine.replace(/[\n\r]/g, '').trim();
|
|
17870
|
+
let headerLine = section[0].replace(/[\n\r]/g, '').trim();
|
|
17764
17871
|
let header = headerLine.split(' ').filter(Boolean);
|
|
17765
|
-
let
|
|
17766
|
-
|
|
17767
|
-
|
|
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;
|
|
17768
17879
|
});
|
|
17769
|
-
|
|
17770
|
-
if (sections.length > 0) {
|
|
17771
|
-
ic.pdbCollection.push(...sections);
|
|
17772
|
-
}
|
|
17773
17880
|
|
|
17774
|
-
return
|
|
17881
|
+
return parsedCollection;
|
|
17775
17882
|
}
|
|
17776
17883
|
|
|
17777
|
-
let collection = [];
|
|
17778
|
-
|
|
17779
17884
|
if (fileExtension === 'json' || fileExtension === 'pdb') {
|
|
17780
17885
|
let reader = new FileReader();
|
|
17781
17886
|
reader.onload = async function (e) {
|
|
17782
17887
|
if (fileExtension === 'json') {
|
|
17783
|
-
|
|
17888
|
+
let jsonCollection = parseJsonCollection(e.target.result);
|
|
17889
|
+
collection = { ...collection, ...jsonCollection };
|
|
17784
17890
|
} else if (fileExtension === 'pdb') {
|
|
17785
17891
|
ic.bInputfile = true;
|
|
17786
|
-
|
|
17892
|
+
let pdbCollection = parsePdbCollection(e.target.result);
|
|
17893
|
+
collection = { ...collection, ...pdbCollection };
|
|
17787
17894
|
}
|
|
17788
17895
|
|
|
17789
17896
|
let collectionHtml = await ic.selectCollectionsCls.setAtomMenu(collection);
|
|
17790
17897
|
|
|
17898
|
+
ic.collections = collection;
|
|
17899
|
+
|
|
17791
17900
|
$("#" + ic.pre + "collections_menu").html(collectionHtml);
|
|
17792
17901
|
await ic.selectCollectionsCls.clickStructure(collection);
|
|
17793
17902
|
$("#" + ic.pre + "collections_menu").trigger("change");
|
|
@@ -17805,7 +17914,7 @@ class Events {
|
|
|
17805
17914
|
let reader2 = new FileReader();
|
|
17806
17915
|
reader2.onload = async function (e) {
|
|
17807
17916
|
if (fileExtension === 'zip') {
|
|
17808
|
-
let url = './script/jszip.js';
|
|
17917
|
+
let url = './script/jszip.min.js';
|
|
17809
17918
|
await me.getAjaxPromise(url, 'script');
|
|
17810
17919
|
|
|
17811
17920
|
let jszip = new JSZip();
|
|
@@ -17839,7 +17948,8 @@ class Events {
|
|
|
17839
17948
|
let jsonCollection = [];
|
|
17840
17949
|
for (const file of jsonFiles) {
|
|
17841
17950
|
let fileData = await file.async('text');
|
|
17842
|
-
parseJsonCollection(fileData)
|
|
17951
|
+
let parsedJson = Object.values(parseJsonCollection(fileData));
|
|
17952
|
+
parsedJson.forEach(element => {
|
|
17843
17953
|
jsonCollection.push(element);
|
|
17844
17954
|
});
|
|
17845
17955
|
}
|
|
@@ -17849,8 +17959,9 @@ class Events {
|
|
|
17849
17959
|
let matchingPdbFile = pdbFiles.find(file => file.name.toLowerCase().includes(id.toLowerCase()));
|
|
17850
17960
|
if (matchingPdbFile) {
|
|
17851
17961
|
let pdbFileData = await matchingPdbFile.async('text');
|
|
17852
|
-
parsePdbCollection(pdbFileData, description, commands)
|
|
17853
|
-
|
|
17962
|
+
let parsedPdb = Object.values(parsePdbCollection(pdbFileData, description, commands));
|
|
17963
|
+
parsedPdb.forEach(element => {
|
|
17964
|
+
collection[id] = element;
|
|
17854
17965
|
});
|
|
17855
17966
|
}
|
|
17856
17967
|
}
|
|
@@ -17859,27 +17970,30 @@ class Events {
|
|
|
17859
17970
|
// Do something if only JSON files are present
|
|
17860
17971
|
jsonFiles.forEach(async file => {
|
|
17861
17972
|
let fileData = await file.async('text');
|
|
17862
|
-
parseJsonCollection(fileData)
|
|
17863
|
-
|
|
17973
|
+
const parsedJson = Object.values(parseJsonCollection(fileData));
|
|
17974
|
+
parsedJson.forEach(element => {
|
|
17975
|
+
collection[element[0]] = element;
|
|
17864
17976
|
});
|
|
17865
17977
|
});
|
|
17866
17978
|
} else if (hasPdb) {
|
|
17867
17979
|
// Do something if only PDB files are present
|
|
17868
17980
|
pdbFiles.forEach(async file => {
|
|
17869
17981
|
let fileData = await file.async('text');
|
|
17870
|
-
|
|
17871
|
-
|
|
17982
|
+
const parsedPdb = Object.values(parsedPdbCollection(fileData));
|
|
17983
|
+
parsedPdb.forEach(element => {
|
|
17984
|
+
collection[element[0]] = element;
|
|
17872
17985
|
});
|
|
17873
17986
|
});
|
|
17874
17987
|
} else if (hasGz) {
|
|
17875
|
-
let url = './script/pako.js';
|
|
17988
|
+
let url = './script/pako.min.js';
|
|
17876
17989
|
await me.getAjaxPromise(url, 'script');
|
|
17877
17990
|
try {
|
|
17878
17991
|
for (const file of gzFiles) {
|
|
17879
17992
|
let compressed = await file.async('uint8array');
|
|
17880
17993
|
let decompressed = pako.inflate(compressed, { to: 'string' });
|
|
17881
|
-
parsePdbCollection(decompressed)
|
|
17882
|
-
|
|
17994
|
+
const parsedPdb = Object.values(parsePdbCollection(decompressed));
|
|
17995
|
+
parsedPdb.forEach(element => {
|
|
17996
|
+
collection[element[0]] = element;
|
|
17883
17997
|
});
|
|
17884
17998
|
}
|
|
17885
17999
|
} catch (error) {
|
|
@@ -17890,7 +18004,7 @@ class Events {
|
|
|
17890
18004
|
console.error('Error loading ZIP file', error);
|
|
17891
18005
|
}
|
|
17892
18006
|
} else if (fileExtension === 'gz') {
|
|
17893
|
-
let url = './script/pako.js';
|
|
18007
|
+
let url = './script/pako.min.js';
|
|
17894
18008
|
await me.getAjaxPromise(url, 'script');
|
|
17895
18009
|
|
|
17896
18010
|
try {
|
|
@@ -17907,6 +18021,8 @@ class Events {
|
|
|
17907
18021
|
$("#" + ic.pre + "collections_menu").html(collectionHtml);
|
|
17908
18022
|
await ic.selectCollectionsCls.clickStructure(collection);
|
|
17909
18023
|
|
|
18024
|
+
ic.collections = collection;
|
|
18025
|
+
|
|
17910
18026
|
$("#" + ic.pre + "collections_menu").trigger("change");
|
|
17911
18027
|
|
|
17912
18028
|
me.htmlCls.clickMenuCls.setLogCmd(
|
|
@@ -17925,7 +18041,7 @@ class Events {
|
|
|
17925
18041
|
throw new Error('Invalid file type');
|
|
17926
18042
|
}
|
|
17927
18043
|
|
|
17928
|
-
if (Object.keys(
|
|
18044
|
+
if (ic.allData && Object.keys(ic.allData).length > 0) {
|
|
17929
18045
|
$("#" + me.pre + "dl_collection_file").hide();
|
|
17930
18046
|
$("#" + me.pre + "dl_collection_structures").show();
|
|
17931
18047
|
$("#" + me.pre + "dl_collection_file_expand").show();
|
|
@@ -17946,6 +18062,17 @@ class Events {
|
|
|
17946
18062
|
}
|
|
17947
18063
|
});
|
|
17948
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
|
+
|
|
17949
18076
|
me.myEventCls.onIds("#" + me.pre + "opendl_export_collections", "click", function (e) {
|
|
17950
18077
|
me.htmlCls.dialogCls.openDlg("dl_export_collections", "Export Collections");
|
|
17951
18078
|
});
|
|
@@ -20432,9 +20559,9 @@ class SetHtml {
|
|
|
20432
20559
|
|
|
20433
20560
|
let pdbstr = '';
|
|
20434
20561
|
|
|
20435
|
-
let bMergeIntoOne = true;
|
|
20436
|
-
pdbstr += ic.saveFileCls.getAtomPDB(atomHash, undefined, undefined, undefined, undefined, undefined, bMergeIntoOne);
|
|
20437
|
-
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);
|
|
20438
20565
|
|
|
20439
20566
|
let url = me.htmlCls.baseUrl + "delphi/delphi.cgi";
|
|
20440
20567
|
|
|
@@ -29638,698 +29765,244 @@ class Stick {
|
|
|
29638
29765
|
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
29639
29766
|
*/
|
|
29640
29767
|
|
|
29641
|
-
class
|
|
29768
|
+
class FirstAtomObj {
|
|
29642
29769
|
constructor(icn3d) {
|
|
29643
29770
|
this.icn3d = icn3d;
|
|
29644
29771
|
}
|
|
29645
29772
|
|
|
29646
|
-
//
|
|
29647
|
-
|
|
29648
|
-
|
|
29649
|
-
|
|
29650
|
-
|
|
29651
|
-
//"bHighlight" is an option to draw the highlight for these atoms. The highlight could be outlines
|
|
29652
|
-
//with bHighlight=1 and 3D objects with bHighlight=2.
|
|
29653
|
-
createStrand(atoms, num, div, fill, coilWidth, helixSheetWidth, doNotSmoothen, thickness, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
|
|
29654
|
-
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
|
+
}
|
|
29655
29778
|
|
|
29656
|
-
let
|
|
29779
|
+
let atomKeys = Object.keys(atomsHash);
|
|
29780
|
+
let firstIndex = atomKeys[0];
|
|
29657
29781
|
|
|
29658
|
-
|
|
29659
|
-
|
|
29660
|
-
let atomsAdjust = {};
|
|
29782
|
+
return ic.atoms[firstIndex];
|
|
29783
|
+
}
|
|
29661
29784
|
|
|
29662
|
-
|
|
29663
|
-
|
|
29664
|
-
|
|
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;
|
|
29665
29789
|
}
|
|
29666
|
-
|
|
29667
|
-
|
|
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;
|
|
29668
29800
|
}
|
|
29669
29801
|
|
|
29670
|
-
|
|
29671
|
-
|
|
29672
|
-
|
|
29673
|
-
|
|
29674
|
-
|
|
29675
|
-
|
|
29676
|
-
helixSheetWidth = null;
|
|
29677
|
-
thickness = undefined;
|
|
29802
|
+
let firstIndex;
|
|
29803
|
+
|
|
29804
|
+
for(let i in atomsHash) {
|
|
29805
|
+
if(ic.atoms[i].name == 'CA') {
|
|
29806
|
+
firstIndex = i;
|
|
29807
|
+
break;
|
|
29678
29808
|
}
|
|
29679
|
-
|
|
29680
|
-
|
|
29681
|
-
|
|
29682
|
-
|
|
29683
|
-
|
|
29684
|
-
|
|
29685
|
-
|
|
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
|
+
}
|
|
29686
29817
|
}
|
|
29687
29818
|
}
|
|
29688
29819
|
|
|
29689
|
-
|
|
29690
|
-
|
|
29691
|
-
coilWidth = coilWidth || ic.coilWidth;
|
|
29692
|
-
doNotSmoothen = doNotSmoothen || false;
|
|
29693
|
-
helixSheetWidth = helixSheetWidth || ic.helixSheetWidth;
|
|
29694
|
-
let pnts = {}; for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
29695
|
-
let pntsCA = [];
|
|
29696
|
-
let prevCOArray = [];
|
|
29697
|
-
let bShowArray = [];
|
|
29698
|
-
let calphaIdArray = []; // used to store one of the final positions drawn in 3D
|
|
29699
|
-
let colors = [];
|
|
29700
|
-
let currentChain, currentResi, currentCA = null, currentO = null, currentColor = null, prevCoorCA = null, prevCoorO = null, prevColor = null;
|
|
29701
|
-
let prevCO = null, ss = null, ssend = false, atomid = null, prevAtomid = null, prevAtomSelected = null, prevResi = null, calphaid = null, prevCalphaid = null;
|
|
29702
|
-
let strandWidth, bSheetSegment = false, bHelixSegment = false;
|
|
29820
|
+
return (firstIndex !== undefined) ? ic.atoms[firstIndex] : this.getFirstAtomObj(atomsHash);
|
|
29821
|
+
}
|
|
29703
29822
|
|
|
29704
|
-
|
|
29705
|
-
|
|
29706
|
-
|
|
29707
|
-
let atoms = me.hashUtilsCls.hash2Atoms(ic.chains[chainid], ic.atoms);
|
|
29708
|
-
let bCalphaOnly = me.utilsCls.isCalphaPhosOnly(atoms); //, 'CA');
|
|
29709
|
-
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];
|
|
29710
29826
|
}
|
|
29711
29827
|
|
|
29712
|
-
|
|
29713
|
-
let residueHash = {};
|
|
29714
|
-
for(let i in atomsAdjust) {
|
|
29715
|
-
let atom = ic.atoms[i];
|
|
29828
|
+
let firstIndex;
|
|
29716
29829
|
|
|
29717
|
-
|
|
29718
|
-
|
|
29830
|
+
for(let i in atomsHash) {
|
|
29831
|
+
if(ic.atoms[i].name == atomName) {
|
|
29832
|
+
firstIndex = i;
|
|
29833
|
+
break;
|
|
29834
|
+
}
|
|
29719
29835
|
}
|
|
29720
|
-
Object.keys(residueHash).length;
|
|
29721
|
-
|
|
29722
|
-
let bFullAtom = (Object.keys(ic.hAtoms).length == Object.keys(ic.atoms).length) ? true : false;
|
|
29723
29836
|
|
|
29724
|
-
|
|
29837
|
+
return (firstIndex !== undefined) ? ic.atoms[firstIndex] : undefined;
|
|
29838
|
+
}
|
|
29725
29839
|
|
|
29726
|
-
|
|
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
|
+
}
|
|
29727
29845
|
|
|
29728
|
-
|
|
29729
|
-
let
|
|
29730
|
-
let lastAtomSerial = atomArray[atomArray.length - 1];
|
|
29731
|
-
let lastAtom = ic.atoms[lastAtomSerial];
|
|
29732
|
-
let lastResid = lastAtom.structure + '_' + lastAtom.chain + '_' + lastAtom.resi;
|
|
29846
|
+
let atomKeys = Object.keys(atomsHash);
|
|
29847
|
+
let lastIndex = atomKeys[atomKeys.length - 1];
|
|
29733
29848
|
|
|
29734
|
-
|
|
29735
|
-
|
|
29736
|
-
let chainid = atom.structure + '_' + atom.chain;
|
|
29737
|
-
let resid = atom.structure + '_' + atom.chain + '_' + atom.resi;
|
|
29738
|
-
if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
|
|
29739
|
-
// "CA" has to appear before "O"
|
|
29849
|
+
return ic.atoms[lastIndex];
|
|
29850
|
+
}
|
|
29740
29851
|
|
|
29741
|
-
|
|
29742
|
-
|
|
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
|
+
}
|
|
29743
29859
|
|
|
29744
|
-
|
|
29745
|
-
|
|
29746
|
-
calphaid = atom.serial;
|
|
29860
|
+
return residuesHash;
|
|
29861
|
+
}
|
|
29747
29862
|
|
|
29748
|
-
|
|
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;
|
|
29749
29870
|
}
|
|
29871
|
+
}
|
|
29750
29872
|
|
|
29751
|
-
|
|
29752
|
-
|
|
29753
|
-
currentCA = atom.coord;
|
|
29754
|
-
currentColor = atom.color;
|
|
29755
|
-
calphaid = atom.serial;
|
|
29756
|
-
}
|
|
29873
|
+
return residuesHash;
|
|
29874
|
+
}
|
|
29757
29875
|
|
|
29758
|
-
|
|
29759
|
-
|
|
29760
|
-
|
|
29761
|
-
|
|
29762
|
-
|
|
29763
|
-
|
|
29764
|
-
// if (currentChain !== atom.chain) {
|
|
29765
|
-
// //if (currentChain !== atom.chain) {
|
|
29766
|
-
// bSameChain = false;
|
|
29767
|
-
// }
|
|
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;
|
|
29768
29882
|
|
|
29769
|
-
|
|
29770
|
-
|
|
29771
|
-
|
|
29772
|
-
|
|
29773
|
-
|
|
29883
|
+
chainsHash[chainid] = 1;
|
|
29884
|
+
}
|
|
29885
|
+
|
|
29886
|
+
return chainsHash;
|
|
29887
|
+
}
|
|
29888
|
+
|
|
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];
|
|
29774
29894
|
}
|
|
29895
|
+
}
|
|
29896
|
+
}
|
|
29775
29897
|
|
|
29776
|
-
|
|
29777
|
-
|
|
29778
|
-
if(bHighlight === 1 || bHighlight === 2) {
|
|
29779
|
-
colors.push(ic.hColor);
|
|
29780
|
-
}
|
|
29781
|
-
else {
|
|
29782
|
-
colors.push(prevColor);
|
|
29783
|
-
}
|
|
29898
|
+
return undefined;
|
|
29899
|
+
}
|
|
29784
29900
|
|
|
29785
|
-
|
|
29786
|
-
|
|
29787
|
-
|
|
29788
|
-
|
|
29789
|
-
strandWidth = coilWidth;
|
|
29790
|
-
}
|
|
29791
|
-
else {
|
|
29792
|
-
strandWidth = (ss === 'coil') ? coilWidth : helixSheetWidth;
|
|
29793
|
-
}
|
|
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;
|
|
29794
29905
|
|
|
29795
|
-
|
|
29796
|
-
|
|
29797
|
-
O = prevCoorO.clone();
|
|
29798
|
-
if(prevCoorCA !== null && prevCoorCA !== undefined) {
|
|
29799
|
-
O.sub(prevCoorCA);
|
|
29800
|
-
}
|
|
29801
|
-
else {
|
|
29802
|
-
prevCoorCA = prevCoorO.clone();
|
|
29803
|
-
if(caArray.length > resSpan + 1) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
29804
|
-
O = prevCoorCA.clone();
|
|
29805
|
-
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan - 1]].coord.clone();
|
|
29806
|
-
//O.sub(oldCA);
|
|
29807
|
-
oldCA.sub(O);
|
|
29808
|
-
}
|
|
29809
|
-
else {
|
|
29810
|
-
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
29811
|
-
}
|
|
29812
|
-
}
|
|
29813
|
-
}
|
|
29814
|
-
else if(bCalphaOnlyHash[chainid] && atom.name === 'CA') {
|
|
29815
|
-
if(caArray.length > resSpan + 1) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
29816
|
-
O = prevCoorCA.clone();
|
|
29817
|
-
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan - 1]].coord.clone();
|
|
29818
|
-
//O.sub(oldCA);
|
|
29819
|
-
oldCA.sub(O);
|
|
29820
|
-
}
|
|
29821
|
-
else {
|
|
29822
|
-
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
29823
|
-
}
|
|
29824
|
-
}
|
|
29906
|
+
return coord;
|
|
29907
|
+
}
|
|
29825
29908
|
|
|
29826
|
-
|
|
29827
|
-
|
|
29828
|
-
|
|
29829
|
-
prevCO = O;
|
|
29909
|
+
return undefined;
|
|
29910
|
+
}
|
|
29911
|
+
}
|
|
29830
29912
|
|
|
29831
|
-
|
|
29832
|
-
|
|
29833
|
-
|
|
29834
|
-
if (!doNotSmoothen && ss === 'sheet') v.smoothen = true;
|
|
29835
|
-
pnts[j].push(v);
|
|
29836
|
-
}
|
|
29913
|
+
/**
|
|
29914
|
+
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
29915
|
+
*/
|
|
29837
29916
|
|
|
29838
|
-
|
|
29839
|
-
|
|
29917
|
+
class Strip {
|
|
29918
|
+
constructor(icn3d) {
|
|
29919
|
+
this.icn3d = icn3d;
|
|
29920
|
+
}
|
|
29840
29921
|
|
|
29841
|
-
|
|
29842
|
-
|
|
29843
|
-
|
|
29844
|
-
|
|
29845
|
-
else {
|
|
29846
|
-
bShowArray.push(0);
|
|
29847
|
-
calphaIdArray.push(0);
|
|
29848
|
-
}
|
|
29849
|
-
}
|
|
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;
|
|
29850
29926
|
|
|
29851
|
-
|
|
29927
|
+
if (p0.length < 2) return;
|
|
29928
|
+
div = div || ic.axisDIV;
|
|
29852
29929
|
|
|
29853
|
-
|
|
29854
|
-
|
|
29855
|
-
|
|
29856
|
-
|
|
29857
|
-
// check whether the atoms are continuous
|
|
29858
|
-
// atomsAdjusted has all atoms in the secondary structure
|
|
29859
|
-
// atoms has all selected atoms
|
|
29860
|
-
// let bBrokenSs = false;
|
|
29861
|
-
// if(prevAtomSelected && prevAtomid == prevAtomSelected.serial && !atoms.hasOwnProperty(atom.serial)) {
|
|
29862
|
-
// bBrokenSs = true;
|
|
29863
|
-
// }
|
|
29930
|
+
// if(pntsCA && ic.bDoublecolor && !ic.bCalphaOnly) {
|
|
29931
|
+
if(pntsCA && ic.bDoublecolor) {
|
|
29932
|
+
let bExtendLastRes = false; //true;
|
|
29864
29933
|
|
|
29934
|
+
let pnts_clrs = me.subdivideCls.subdivide(pntsCA, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29935
|
+
pntsCA = pnts_clrs[0];
|
|
29865
29936
|
|
|
29866
|
-
|
|
29867
|
-
// 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);
|
|
29937
|
+
this.setCalphaDrawnCoord(pntsCA, div, calphaIdArray);
|
|
29868
29938
|
|
|
29869
|
-
|
|
29870
|
-
|
|
29871
|
-
|
|
29872
|
-
// else if(bBrokenSs && atom.ss === 'helix') {
|
|
29873
|
-
// bHelixSegment = true;
|
|
29874
|
-
// }
|
|
29939
|
+
for(let i = 0, il = prevCOArray.length; i < il; ++i) {
|
|
29940
|
+
prevCOArray[i].normalize();
|
|
29941
|
+
}
|
|
29875
29942
|
|
|
29876
|
-
|
|
29877
|
-
|
|
29943
|
+
let pnts_clrs2 = me.subdivideCls.subdivide(prevCOArray, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29944
|
+
prevCOArray = pnts_clrs2[0];
|
|
29878
29945
|
|
|
29879
|
-
|
|
29880
|
-
|
|
29881
|
-
|
|
29882
|
-
let prevone = [], nexttwo = [];
|
|
29946
|
+
colors = pnts_clrs[2];
|
|
29947
|
+
}
|
|
29948
|
+
else {
|
|
29883
29949
|
|
|
29884
|
-
|
|
29885
|
-
|
|
29886
|
-
|
|
29887
|
-
|
|
29888
|
-
|
|
29889
|
-
|
|
29890
|
-
|
|
29891
|
-
|
|
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;
|
|
29892
29960
|
|
|
29893
|
-
|
|
29894
|
-
|
|
29895
|
-
let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
|
|
29896
|
-
if(nextoneCoord !== undefined) {
|
|
29897
|
-
nexttwo.push(nextoneCoord);
|
|
29898
|
-
}
|
|
29961
|
+
this.setCalphaDrawnCoord(p0, div, calphaIdArray);
|
|
29962
|
+
}
|
|
29899
29963
|
|
|
29900
|
-
|
|
29901
|
-
|
|
29902
|
-
if(nexttwoCoord !== undefined) {
|
|
29903
|
-
nexttwo.push(nexttwoCoord);
|
|
29904
|
-
}
|
|
29905
|
-
}
|
|
29964
|
+
if(bHighlight === 1) {
|
|
29965
|
+
//mesh = new THREE.Mesh(geo, ic.matShader);
|
|
29906
29966
|
|
|
29907
|
-
|
|
29908
|
-
|
|
29909
|
-
|
|
29910
|
-
|
|
29911
|
-
colors.push(ic.hColor);
|
|
29912
|
-
}
|
|
29913
|
-
else {
|
|
29914
|
-
//colors.push(atom.color);
|
|
29915
|
-
colors.push(prevColor);
|
|
29916
|
-
}
|
|
29967
|
+
let radius = ic.coilWidth / 2;
|
|
29968
|
+
//var radiusSegments = 8;
|
|
29969
|
+
let radiusSegments = 4; // save memory
|
|
29970
|
+
let closed = false;
|
|
29917
29971
|
|
|
29918
|
-
|
|
29919
|
-
|
|
29920
|
-
|
|
29921
|
-
else if(ss === 'coil' && atom.ssbegin) {
|
|
29922
|
-
strandWidth = coilWidth;
|
|
29923
|
-
}
|
|
29924
|
-
else if(ssend && atom.ssbegin) { // current residue is the start of ss and the previous residue is the end of ss, then use coil
|
|
29925
|
-
strandWidth = coilWidth;
|
|
29926
|
-
}
|
|
29927
|
-
else { // use the ss from the previous residue
|
|
29928
|
-
strandWidth = (atom.ss === 'coil') ? coilWidth : helixSheetWidth;
|
|
29929
|
-
}
|
|
29972
|
+
if(positions !== undefined) {
|
|
29973
|
+
let currPos, prevPos;
|
|
29974
|
+
let currP0 = [], currP1 = [];
|
|
29930
29975
|
|
|
29931
|
-
|
|
29932
|
-
|
|
29933
|
-
O = currentO.clone();
|
|
29934
|
-
O.sub(currentCA);
|
|
29935
|
-
}
|
|
29936
|
-
else if(bCalphaOnlyHash[chainid] && atom.name === 'CA') {
|
|
29937
|
-
if(caArray.length > resSpan) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
29938
|
-
O = currentCA.clone();
|
|
29939
|
-
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan]].coord.clone();
|
|
29940
|
-
//O.sub(oldCA);
|
|
29941
|
-
oldCA.sub(O);
|
|
29942
|
-
}
|
|
29943
|
-
else {
|
|
29944
|
-
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
29945
|
-
}
|
|
29946
|
-
}
|
|
29976
|
+
for(let i = 0, il = p0.length; i < il; ++i) {
|
|
29977
|
+
currPos = positions[i];
|
|
29947
29978
|
|
|
29948
|
-
|
|
29949
|
-
|
|
29950
|
-
|
|
29951
|
-
|
|
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
|
+
);
|
|
29952
29988
|
|
|
29953
|
-
|
|
29954
|
-
|
|
29955
|
-
|
|
29956
|
-
|
|
29957
|
-
pnts[j].push(v);
|
|
29958
|
-
}
|
|
29989
|
+
let mesh = new THREE.Mesh(geometry0, ic.matShader);
|
|
29990
|
+
mesh.renderOrder = ic.renderOrderPicking;
|
|
29991
|
+
//ic.mdlPicking.add(mesh);
|
|
29992
|
+
ic.mdl.add(mesh);
|
|
29959
29993
|
|
|
29960
|
-
|
|
29994
|
+
ic.prevHighlightObjects.push(mesh);
|
|
29961
29995
|
|
|
29962
|
-
|
|
29963
|
-
prevCOArray.push(prevCO);
|
|
29996
|
+
geometry0 = null;
|
|
29964
29997
|
|
|
29965
|
-
//
|
|
29966
|
-
|
|
29967
|
-
|
|
29968
|
-
|
|
29969
|
-
|
|
29970
|
-
|
|
29971
|
-
|
|
29972
|
-
|
|
29973
|
-
calphaIdArray.push(0);
|
|
29974
|
-
}
|
|
29975
|
-
}
|
|
29976
|
-
|
|
29977
|
-
// draw the current segment
|
|
29978
|
-
for (let j = 0; !fill && j < num; ++j) {
|
|
29979
|
-
if(bSheetSegment) {
|
|
29980
|
-
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
29981
|
-
}
|
|
29982
|
-
else if(bHelixSegment) {
|
|
29983
|
-
if(bFullAtom) {
|
|
29984
|
-
ic.curveCls.createCurveSub(pnts[j], 1, colors, div, bHighlight, bRibbon, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo);
|
|
29985
|
-
}
|
|
29986
|
-
else {
|
|
29987
|
-
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
29988
|
-
}
|
|
29989
|
-
}
|
|
29990
|
-
}
|
|
29991
|
-
if (fill) {
|
|
29992
|
-
if(bSheetSegment) {
|
|
29993
|
-
let start = 0, end = num - 1;
|
|
29994
|
-
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
29995
|
-
}
|
|
29996
|
-
else if(bHelixSegment) {
|
|
29997
|
-
if(bFullAtom) {
|
|
29998
|
-
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
29999
|
-
}
|
|
30000
|
-
else {
|
|
30001
|
-
let start = 0, end = num - 1;
|
|
30002
|
-
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
30003
|
-
}
|
|
30004
|
-
}
|
|
30005
|
-
else {
|
|
30006
|
-
if(bHighlight === 2) { // draw coils only when highlighted. if not highlighted, coils will be drawn as tubes separately
|
|
30007
|
-
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
30008
|
-
}
|
|
30009
|
-
}
|
|
30010
|
-
}
|
|
30011
|
-
for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
30012
|
-
|
|
30013
|
-
colors = [];
|
|
30014
|
-
pntsCA = [];
|
|
30015
|
-
prevCOArray = [];
|
|
30016
|
-
bShowArray = [];
|
|
30017
|
-
calphaIdArray = [];
|
|
30018
|
-
bSheetSegment = false;
|
|
30019
|
-
bHelixSegment = false;
|
|
30020
|
-
} // end if (atom.ssbegin || atom.ssend)
|
|
30021
|
-
|
|
30022
|
-
// end of a chain, or end of selection
|
|
30023
|
-
if ((currentChain !== atom.chain
|
|
30024
|
-
|| ic.ParserUtilsCls.getResiNCBI(atom.structure + '_' + currentChain, currentResi) + 1 !== ic.ParserUtilsCls.getResiNCBI(chainid, atom.resi)
|
|
30025
|
-
// || (drawnResidueCount === totalResidueCount - 1)
|
|
30026
|
-
// || bBrokenSs
|
|
30027
|
-
|| (resid == lastResid && atom.ss != 'coil')
|
|
30028
|
-
) && pnts[0].length > 0) {
|
|
30029
|
-
//if ((currentChain !== atom.chain) && pnts[0].length > 0) {
|
|
30030
|
-
|
|
30031
|
-
let atomName = 'CA';
|
|
30032
|
-
|
|
30033
|
-
let prevone = [], nexttwo = [];
|
|
30034
|
-
if(isNaN(ic.atoms[prevAtomid].resi)) {
|
|
30035
|
-
prevone = [];
|
|
30036
|
-
}
|
|
30037
|
-
else {
|
|
30038
|
-
let prevoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) - 1).toString();
|
|
30039
|
-
ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
|
|
30040
|
-
}
|
|
30041
|
-
|
|
30042
|
-
for (let j = 0; !fill && j < num; ++j) {
|
|
30043
|
-
if(bSheetSegment) {
|
|
30044
|
-
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
30045
|
-
}
|
|
30046
|
-
else if(bHelixSegment) {
|
|
30047
|
-
if(bFullAtom) {
|
|
30048
|
-
ic.curveCls.createCurveSub(pnts[j], 1, colors, div, bHighlight, bRibbon, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo);
|
|
30049
|
-
}
|
|
30050
|
-
else {
|
|
30051
|
-
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
30052
|
-
}
|
|
30053
|
-
}
|
|
30054
|
-
}
|
|
30055
|
-
if (fill) {
|
|
30056
|
-
if(bSheetSegment) {
|
|
30057
|
-
let start = 0, end = num - 1;
|
|
30058
|
-
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
30059
|
-
}
|
|
30060
|
-
else if(bHelixSegment) {
|
|
30061
|
-
if(bFullAtom) {
|
|
30062
|
-
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
30063
|
-
}
|
|
30064
|
-
else {
|
|
30065
|
-
let start = 0, end = num - 1;
|
|
30066
|
-
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
30067
|
-
}
|
|
30068
|
-
}
|
|
30069
|
-
}
|
|
30070
|
-
|
|
30071
|
-
for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
30072
|
-
colors = [];
|
|
30073
|
-
pntsCA = [];
|
|
30074
|
-
prevCOArray = [];
|
|
30075
|
-
bShowArray = [];
|
|
30076
|
-
calphaIdArray = [];
|
|
30077
|
-
bSheetSegment = false;
|
|
30078
|
-
bHelixSegment = false;
|
|
30079
|
-
}
|
|
30080
|
-
|
|
30081
|
-
currentChain = atom.chain;
|
|
30082
|
-
currentResi = atom.resi;
|
|
30083
|
-
ss = atom.ss;
|
|
30084
|
-
ssend = atom.ssend;
|
|
30085
|
-
prevAtomid = atom.serial;
|
|
30086
|
-
if(atoms.hasOwnProperty(atom.serial)) prevAtomSelected = atom;
|
|
30087
|
-
prevResi = atom.resi;
|
|
30088
|
-
|
|
30089
|
-
prevCalphaid = calphaid;
|
|
30090
|
-
|
|
30091
|
-
// only update when atom.name === 'O'
|
|
30092
|
-
prevCoorCA = currentCA;
|
|
30093
|
-
prevCoorO = atom.coord;
|
|
30094
|
-
prevColor = currentColor;
|
|
30095
|
-
} // end if (atom.name === 'O' || (bCalphaOnlyHash[chainid] && atom.name === 'CA') ) {
|
|
30096
|
-
} // end if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
|
|
30097
|
-
} // end for
|
|
30098
|
-
|
|
30099
|
-
caArray = [];
|
|
30100
|
-
|
|
30101
|
-
// ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight);
|
|
30102
|
-
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
30103
|
-
ic.tubeCls.createTube(atomsAdjust, 'CA', coilWidth, bHighlight);
|
|
30104
|
-
pnts = {};
|
|
30105
|
-
}
|
|
30106
|
-
|
|
30107
|
-
getOneExtraResidue(residueHash) { let ic = this.icn3d, me = ic.icn3dui;
|
|
30108
|
-
let atomsAdjust = {};
|
|
30109
|
-
|
|
30110
|
-
for(let resid in residueHash) {
|
|
30111
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, ic.residues[resid]);
|
|
30112
|
-
|
|
30113
|
-
let residNcbi = ic.resid2ncbi[resid];
|
|
30114
|
-
let resiNcbi = residNcbi.substr(residNcbi.lastIndexOf('_') + 1);
|
|
30115
|
-
|
|
30116
|
-
let nextResidNcbi = residNcbi.substr(0, residNcbi.lastIndexOf('_')) + '_' + (parseInt(resiNcbi) + 1);
|
|
30117
|
-
let nextResid = ic.ncbi2resid[nextResidNcbi];
|
|
30118
|
-
|
|
30119
|
-
if(!nextResid) {
|
|
30120
|
-
nextResidNcbi = residNcbi.substr(0, residNcbi.lastIndexOf('_')) + '_' + (parseInt(resiNcbi) - 1);
|
|
30121
|
-
nextResid = ic.ncbi2resid[nextResidNcbi];
|
|
30122
|
-
}
|
|
30123
|
-
|
|
30124
|
-
if(nextResid) atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, ic.residues[nextResid]);
|
|
30125
|
-
}
|
|
30126
|
-
|
|
30127
|
-
return atomsAdjust;
|
|
30128
|
-
}
|
|
30129
|
-
|
|
30130
|
-
/*
|
|
30131
|
-
getSSExpandedAtoms(atoms, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
|
|
30132
|
-
let currChain, currResi, currAtom, prevChain, prevResi, prevAtom;
|
|
30133
|
-
let firstAtom, lastAtom;
|
|
30134
|
-
let index = 0, length = Object.keys(atoms).length;
|
|
30135
|
-
|
|
30136
|
-
let atomsAdjust = me.hashUtilsCls.cloneHash(atoms);
|
|
30137
|
-
for(let serial in atoms) {
|
|
30138
|
-
currChain = atoms[serial].structure + '_' + atoms[serial].chain;
|
|
30139
|
-
currResi = atoms[serial].resi; //parseInt(atoms[serial].resi);
|
|
30140
|
-
currAtom = atoms[serial];
|
|
30141
|
-
|
|
30142
|
-
if(prevChain === undefined) firstAtom = atoms[serial];
|
|
30143
|
-
|
|
30144
|
-
if( (currChain !== prevChain && prevChain !== undefined)
|
|
30145
|
-
|| (currResi !== prevResi && ic.resid2ncbi[currResi] !== ic.resid2ncbi[prevResi] + 1 && prevResi !== undefined) || index === length - 1) {
|
|
30146
|
-
if( (currChain !== prevChain && prevChain !== undefined)
|
|
30147
|
-
|| (currResi !== prevResi && currResi !== ic.resid2ncbi[prevResi] + 1 && prevResi !== undefined) ) {
|
|
30148
|
-
lastAtom = prevAtom;
|
|
30149
|
-
}
|
|
30150
|
-
else if(index === length - 1) {
|
|
30151
|
-
lastAtom = currAtom;
|
|
30152
|
-
}
|
|
30153
|
-
|
|
30154
|
-
// fill the beginning
|
|
30155
|
-
let beginResi = firstAtom.resi;
|
|
30156
|
-
if(!isNaN(firstAtom.resi) && firstAtom.ss !== 'coil' && !(firstAtom.ssbegin) ) {
|
|
30157
|
-
for(let i = parseInt(firstAtom.resi) - 1; i > 0; --i) {
|
|
30158
|
-
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + i;
|
|
30159
|
-
if(!ic.residues.hasOwnProperty(residueid)) break;
|
|
30160
|
-
|
|
30161
|
-
let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[residueid]);
|
|
30162
|
-
|
|
30163
|
-
if(atom.ss === firstAtom.ss && atom.ssbegin) {
|
|
30164
|
-
beginResi = atom.resi;
|
|
30165
|
-
break;
|
|
30166
|
-
}
|
|
30167
|
-
}
|
|
30168
|
-
|
|
30169
|
-
for(let i = beginResi; i < firstAtom.resi; ++i) {
|
|
30170
|
-
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + i;
|
|
30171
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
30172
|
-
ic.atoms));
|
|
30173
|
-
}
|
|
30174
|
-
}
|
|
30175
|
-
|
|
30176
|
-
// add one extra residue for coils between strands/helix
|
|
30177
|
-
if(!isNaN(firstAtom.resi) && ic.pk === 3 && bHighlight === 1 && firstAtom.ss === 'coil') {
|
|
30178
|
-
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
|
|
30179
|
-
if(ic.residues.hasOwnProperty(residueid)) {
|
|
30180
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
30181
|
-
ic.atoms));
|
|
30182
|
-
atoms = me.hashUtilsCls.unionHash(atoms, me.hashUtilsCls.hash2Atoms(ic.residues[residueid], ic.atoms));
|
|
30183
|
-
}
|
|
30184
|
-
}
|
|
30185
|
-
|
|
30186
|
-
// fill the end
|
|
30187
|
-
let endResi = lastAtom.resi;
|
|
30188
|
-
// 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.
|
|
30189
|
-
|
|
30190
|
-
if(lastAtom.ss !== undefined && lastAtom.ss !== 'coil' && !(lastAtom.ssend) && !(lastAtom.notshow)) {
|
|
30191
|
-
|
|
30192
|
-
let endChainResi = ic.firstAtomObjCls.getLastAtomObj(ic.chains[lastAtom.structure + '_' + lastAtom.chain]).resi;
|
|
30193
|
-
for(let i = parseInt(lastAtom.resi) + 1; i <= parseInt(endChainResi); ++i) {
|
|
30194
|
-
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + i;
|
|
30195
|
-
if(!ic.residues.hasOwnProperty(residueid)) break;
|
|
30196
|
-
|
|
30197
|
-
let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[residueid]);
|
|
30198
|
-
|
|
30199
|
-
if(atom.ss === lastAtom.ss && atom.ssend) {
|
|
30200
|
-
endResi = atom.resi;
|
|
30201
|
-
break;
|
|
30202
|
-
}
|
|
30203
|
-
}
|
|
30204
|
-
|
|
30205
|
-
for(let i = parseInt(lastAtom.resi) + 1; i <= parseInt(endResi); ++i) {
|
|
30206
|
-
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + i;
|
|
30207
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
30208
|
-
ic.atoms));
|
|
30209
|
-
}
|
|
30210
|
-
}
|
|
30211
|
-
|
|
30212
|
-
// add one extra residue for coils between strands/helix
|
|
30213
|
-
if(ic.pk === 3 && bHighlight === 1 && lastAtom.ss === 'coil') {
|
|
30214
|
-
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + (parseInt(lastAtom.resi) + 1).toString();
|
|
30215
|
-
if(ic.residues.hasOwnProperty(residueid)) {
|
|
30216
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
30217
|
-
ic.atoms));
|
|
30218
|
-
atoms = me.hashUtilsCls.unionHash(atoms, me.hashUtilsCls.hash2Atoms(ic.residues[residueid], ic.atoms));
|
|
30219
|
-
}
|
|
30220
|
-
}
|
|
30221
|
-
|
|
30222
|
-
// reset notshow
|
|
30223
|
-
if(lastAtom.notshow) lastAtom.notshow = undefined;
|
|
30224
|
-
|
|
30225
|
-
firstAtom = currAtom;
|
|
30226
|
-
}
|
|
30227
|
-
|
|
30228
|
-
prevChain = currChain;
|
|
30229
|
-
prevResi = currResi;
|
|
30230
|
-
prevAtom = currAtom;
|
|
30231
|
-
|
|
30232
|
-
++index;
|
|
30233
|
-
}
|
|
30234
|
-
|
|
30235
|
-
return atomsAdjust;
|
|
30236
|
-
}
|
|
30237
|
-
*/
|
|
30238
|
-
}
|
|
30239
|
-
|
|
30240
|
-
/**
|
|
30241
|
-
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
30242
|
-
*/
|
|
30243
|
-
|
|
30244
|
-
class Strip {
|
|
30245
|
-
constructor(icn3d) {
|
|
30246
|
-
this.icn3d = icn3d;
|
|
30247
|
-
}
|
|
30248
|
-
|
|
30249
|
-
// modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
30250
|
-
createStrip(p0, p1, colors, div, thickness, bHighlight, bNoSmoothen, bShowArray,
|
|
30251
|
-
calphaIdArray, positions, prevone, nexttwo, pntsCA, prevCOArray) { let ic = this.icn3d, me = ic.icn3dui;
|
|
30252
|
-
if(me.bNode) return;
|
|
30253
|
-
|
|
30254
|
-
if (p0.length < 2) return;
|
|
30255
|
-
div = div || ic.axisDIV;
|
|
30256
|
-
|
|
30257
|
-
// if(pntsCA && ic.bDoublecolor && !ic.bCalphaOnly) {
|
|
30258
|
-
if(pntsCA && ic.bDoublecolor) {
|
|
30259
|
-
let bExtendLastRes = false; //true;
|
|
30260
|
-
|
|
30261
|
-
let pnts_clrs = me.subdivideCls.subdivide(pntsCA, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
30262
|
-
pntsCA = pnts_clrs[0];
|
|
30263
|
-
|
|
30264
|
-
this.setCalphaDrawnCoord(pntsCA, div, calphaIdArray);
|
|
30265
|
-
|
|
30266
|
-
for(let i = 0, il = prevCOArray.length; i < il; ++i) {
|
|
30267
|
-
prevCOArray[i].normalize();
|
|
30268
|
-
}
|
|
30269
|
-
|
|
30270
|
-
let pnts_clrs2 = me.subdivideCls.subdivide(prevCOArray, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
30271
|
-
prevCOArray = pnts_clrs2[0];
|
|
30272
|
-
|
|
30273
|
-
colors = pnts_clrs[2];
|
|
30274
|
-
}
|
|
30275
|
-
else {
|
|
30276
|
-
|
|
30277
|
-
if(!bNoSmoothen) {
|
|
30278
|
-
//var bExtendLastRes = true;
|
|
30279
|
-
let bExtendLastRes = false;
|
|
30280
|
-
let pnts_clrs0 = me.subdivideCls.subdivide(p0, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
30281
|
-
let pnts_clrs1 = me.subdivideCls.subdivide(p1, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
30282
|
-
p0 = pnts_clrs0[0];
|
|
30283
|
-
p1 = pnts_clrs1[0];
|
|
30284
|
-
colors = pnts_clrs0[2];
|
|
30285
|
-
}
|
|
30286
|
-
if (p0.length < 2) return;
|
|
30287
|
-
|
|
30288
|
-
this.setCalphaDrawnCoord(p0, div, calphaIdArray);
|
|
30289
|
-
}
|
|
30290
|
-
|
|
30291
|
-
if(bHighlight === 1) {
|
|
30292
|
-
//mesh = new THREE.Mesh(geo, ic.matShader);
|
|
30293
|
-
|
|
30294
|
-
let radius = ic.coilWidth / 2;
|
|
30295
|
-
//var radiusSegments = 8;
|
|
30296
|
-
let radiusSegments = 4; // save memory
|
|
30297
|
-
let closed = false;
|
|
30298
|
-
|
|
30299
|
-
if(positions !== undefined) {
|
|
30300
|
-
let currPos, prevPos;
|
|
30301
|
-
let currP0 = [], currP1 = [];
|
|
30302
|
-
|
|
30303
|
-
for(let i = 0, il = p0.length; i < il; ++i) {
|
|
30304
|
-
currPos = positions[i];
|
|
30305
|
-
|
|
30306
|
-
if((currPos !== prevPos && parseInt(currPos) !== parseInt(prevPos) + 1 && prevPos !== undefined) || (i === il -1) ) {
|
|
30307
|
-
// first tube
|
|
30308
|
-
let geometry0 = new THREE.TubeGeometry(
|
|
30309
|
-
new THREE.CatmullRomCurve3(currP0), // path
|
|
30310
|
-
currP0.length, // segments
|
|
30311
|
-
radius,
|
|
30312
|
-
radiusSegments,
|
|
30313
|
-
closed
|
|
30314
|
-
);
|
|
30315
|
-
|
|
30316
|
-
let mesh = new THREE.Mesh(geometry0, ic.matShader);
|
|
30317
|
-
mesh.renderOrder = ic.renderOrderPicking;
|
|
30318
|
-
//ic.mdlPicking.add(mesh);
|
|
30319
|
-
ic.mdl.add(mesh);
|
|
30320
|
-
|
|
30321
|
-
ic.prevHighlightObjects.push(mesh);
|
|
30322
|
-
|
|
30323
|
-
geometry0 = null;
|
|
30324
|
-
|
|
30325
|
-
// second tube
|
|
30326
|
-
let geometry1 = new THREE.TubeGeometry(
|
|
30327
|
-
new THREE.CatmullRomCurve3(currP1), // path
|
|
30328
|
-
currP1.length, // segments
|
|
30329
|
-
radius,
|
|
30330
|
-
radiusSegments,
|
|
30331
|
-
closed
|
|
30332
|
-
);
|
|
29998
|
+
// second tube
|
|
29999
|
+
let geometry1 = new THREE.TubeGeometry(
|
|
30000
|
+
new THREE.CatmullRomCurve3(currP1), // path
|
|
30001
|
+
currP1.length, // segments
|
|
30002
|
+
radius,
|
|
30003
|
+
radiusSegments,
|
|
30004
|
+
closed
|
|
30005
|
+
);
|
|
30333
30006
|
|
|
30334
30007
|
mesh = new THREE.Mesh(geometry1, ic.matShader);
|
|
30335
30008
|
mesh.renderOrder = ic.renderOrderPicking;
|
|
@@ -30605,6 +30278,7 @@ class Tube {
|
|
|
30605
30278
|
atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) - 1).toString();
|
|
30606
30279
|
|
|
30607
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
|
|
30608
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')
|
|
30609
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))
|
|
30610
30284
|
) ) {
|
|
@@ -30697,7 +30371,7 @@ class Tube {
|
|
|
30697
30371
|
}
|
|
30698
30372
|
|
|
30699
30373
|
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
30700
|
-
if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
|
|
30374
|
+
// if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
|
|
30701
30375
|
|
|
30702
30376
|
//radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
|
|
30703
30377
|
radii.push(radiusFinal);
|
|
@@ -30832,232 +30506,778 @@ class Tube {
|
|
|
30832
30506
|
|
|
30833
30507
|
pnts.push(atom.coord);
|
|
30834
30508
|
|
|
30835
|
-
let radiusFinal;
|
|
30836
|
-
if(bCustom) {
|
|
30837
|
-
radiusFinal = this.getCustomtubesize(atom.structure + '_' + atom.chain + '_' + atom.resi);
|
|
30838
|
-
}
|
|
30839
|
-
else {
|
|
30840
|
-
radiusFinal = this.getRadius(radius, atom);
|
|
30841
|
-
}
|
|
30509
|
+
let radiusFinal;
|
|
30510
|
+
if(bCustom) {
|
|
30511
|
+
radiusFinal = this.getCustomtubesize(atom.structure + '_' + atom.chain + '_' + atom.resi);
|
|
30512
|
+
}
|
|
30513
|
+
else {
|
|
30514
|
+
radiusFinal = this.getRadius(radius, atom);
|
|
30515
|
+
}
|
|
30516
|
+
|
|
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)
|
|
30842
31097
|
|
|
30843
|
-
//
|
|
30844
|
-
|
|
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) {
|
|
30845
31101
|
|
|
30846
|
-
|
|
30847
|
-
radii.push(radiusFinal);
|
|
31102
|
+
let atomName = 'CA';
|
|
30848
31103
|
|
|
30849
|
-
|
|
30850
|
-
|
|
30851
|
-
|
|
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
|
+
}
|
|
30852
31112
|
|
|
30853
|
-
|
|
30854
|
-
|
|
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
|
+
}
|
|
30855
31141
|
|
|
30856
|
-
|
|
30857
|
-
|
|
30858
|
-
|
|
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;
|
|
30859
31150
|
}
|
|
30860
31151
|
|
|
30861
|
-
|
|
31152
|
+
currentChain = atom.chain;
|
|
31153
|
+
ss = atom.ss;
|
|
31154
|
+
ssend = atom.ssend;
|
|
31155
|
+
prevAtomid = atom.serial;
|
|
31156
|
+
prevResi = atom.resi;
|
|
30862
31157
|
|
|
30863
|
-
|
|
30864
|
-
}
|
|
30865
|
-
}
|
|
31158
|
+
prevCalphaid = calphaid;
|
|
30866
31159
|
|
|
30867
|
-
|
|
30868
|
-
|
|
30869
|
-
|
|
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
|
|
30870
31167
|
|
|
30871
|
-
|
|
30872
|
-
let pnts = pnts_colors_radii_prevone_nexttwo[i].pnts;
|
|
30873
|
-
let colors = pnts_colors_radii_prevone_nexttwo[i].colors;
|
|
30874
|
-
let radii = pnts_colors_radii_prevone_nexttwo[i].radii;
|
|
30875
|
-
let prevone = []; // = pnts_colors_radii_prevone_nexttwo[i].prevone;
|
|
30876
|
-
let nexttwo = []; // = pnts_colors_radii_prevone_nexttwo[i].nexttwo;
|
|
31168
|
+
caArray = [];
|
|
30877
31169
|
|
|
30878
|
-
|
|
30879
|
-
}
|
|
31170
|
+
ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight);
|
|
30880
31171
|
|
|
30881
|
-
|
|
31172
|
+
tubeAtoms = {};
|
|
31173
|
+
pnts = {};
|
|
30882
31174
|
}
|
|
30883
|
-
*/
|
|
30884
|
-
|
|
30885
|
-
getCustomtubesize(resid) { let ic = this.icn3d; ic.icn3dui;
|
|
30886
|
-
let pos = resid.lastIndexOf('_');
|
|
30887
|
-
let resi = resid.substr(pos + 1);
|
|
30888
|
-
let chainid = resid.substr(0, pos);
|
|
30889
|
-
|
|
30890
|
-
let radiusFinal = (ic.queryresi2score[chainid] && ic.queryresi2score[chainid].hasOwnProperty(resi)) ? ic.queryresi2score[chainid][resi] * 0.01 : ic.coilWidth;
|
|
30891
|
-
|
|
30892
|
-
return radiusFinal;
|
|
30893
|
-
};
|
|
30894
|
-
|
|
30895
|
-
// modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
30896
|
-
createTubeSub(_pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
|
|
30897
|
-
if(me.bNode) return;
|
|
30898
31175
|
|
|
30899
|
-
|
|
30900
|
-
|
|
30901
|
-
let
|
|
30902
|
-
let
|
|
30903
|
-
//var geo = new THREE.Geometry();
|
|
30904
|
-
let geo = new THREE.BufferGeometry();
|
|
30905
|
-
let verticeArray = [], colorArray = [],indexArray = [], color;
|
|
30906
|
-
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;
|
|
30907
31180
|
|
|
30908
|
-
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];
|
|
30909
31186
|
|
|
30910
|
-
|
|
30911
|
-
colors = pnts_clrs[2];
|
|
31187
|
+
if(prevChain === undefined) firstAtom = atoms[serial];
|
|
30912
31188
|
|
|
30913
|
-
|
|
30914
|
-
|
|
30915
|
-
|
|
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
|
+
}
|
|
30916
31198
|
|
|
30917
|
-
|
|
30918
|
-
|
|
30919
|
-
|
|
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;
|
|
30920
31205
|
|
|
30921
|
-
|
|
30922
|
-
r = radii[0];
|
|
30923
|
-
if(r > 0) constRadiius = r;
|
|
30924
|
-
}
|
|
30925
|
-
else {
|
|
30926
|
-
if (idx % 1 === 0) {
|
|
30927
|
-
r = radii[idx];
|
|
30928
|
-
if(r > 0) constRadiius = r;
|
|
30929
|
-
}
|
|
30930
|
-
else {
|
|
30931
|
-
let floored = Math.floor(idx);
|
|
30932
|
-
let tmp = idx - floored;
|
|
30933
|
-
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
30934
|
-
// r = radii[floored] * tmp + radii[floored + 1] * (1 - tmp);
|
|
30935
|
-
r = radii[floored] * (1 - tmp) + radii[floored + 1] * tmp;
|
|
31206
|
+
let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[residueid]);
|
|
30936
31207
|
|
|
30937
|
-
|
|
30938
|
-
|
|
30939
|
-
|
|
30940
|
-
if(r < thresholdRatio * constRadiius) {
|
|
30941
|
-
r = 0;
|
|
30942
|
-
}
|
|
30943
|
-
// else if(r < constRadiius) {
|
|
30944
|
-
// r *= 0.5; // use small radius for the connection between coild and sheets/helices
|
|
30945
|
-
// }
|
|
31208
|
+
if(atom.ss === firstAtom.ss && atom.ssbegin) {
|
|
31209
|
+
beginResi = atom.resi;
|
|
31210
|
+
break;
|
|
30946
31211
|
}
|
|
30947
31212
|
}
|
|
30948
|
-
|
|
30949
|
-
|
|
30950
|
-
|
|
30951
|
-
|
|
30952
|
-
|
|
30953
|
-
axis2 = delta.clone().cross(axis1).normalize().multiplyScalar(r);
|
|
30954
|
-
// let dir = 1, offset = 0;
|
|
30955
|
-
if (prevAxis1.dot(axis1) < 0) {
|
|
30956
|
-
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));
|
|
30957
31218
|
}
|
|
30958
|
-
prevAxis1 = axis1; prevAxis2 = axis2;
|
|
30959
|
-
} else {
|
|
30960
|
-
axis1 = prevAxis1; axis2 = prevAxis2;
|
|
30961
31219
|
}
|
|
30962
|
-
for (let j = 0; j < circleDiv; ++j) {
|
|
30963
|
-
let angle = 2 * Math.PI * circleDivInv * j; //* dir + offset;
|
|
30964
|
-
let point = pnts[i].clone().add(axis1.clone().multiplyScalar(Math.cos(angle))).add(axis2.clone().multiplyScalar(Math.sin(angle)));
|
|
30965
|
-
verticeArray[offset++] = point.x;
|
|
30966
|
-
verticeArray[offset++] = point.y;
|
|
30967
|
-
verticeArray[offset++] = point.z;
|
|
30968
31220
|
|
|
30969
|
-
|
|
30970
|
-
|
|
30971
|
-
|
|
30972
|
-
|
|
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
|
+
}
|
|
30973
31229
|
}
|
|
30974
|
-
}
|
|
30975
|
-
let offsetTmp = 0, nComp = 3;
|
|
30976
|
-
for (let i = 0, lim = pnts.length - 1; i < lim; ++i) {
|
|
30977
|
-
let reg = 0;
|
|
30978
|
-
//var r1 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv]).lengthSq();
|
|
30979
|
-
//var r2 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv + 1]).lengthSq();
|
|
30980
|
-
let pos = offsetTmp * nComp;
|
|
30981
|
-
let point1 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
30982
|
-
pos = (offsetTmp + circleDiv) * nComp;
|
|
30983
|
-
let point2 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
30984
|
-
pos = (offsetTmp + circleDiv + 1) * nComp;
|
|
30985
|
-
let point3 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
30986
31230
|
|
|
30987
|
-
|
|
30988
|
-
let
|
|
30989
|
-
|
|
30990
|
-
//geo.faces.push(new THREE.Face3(offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv, undefined, c));
|
|
30991
|
-
//geo.faces.push(new THREE.Face3(offset + (j + 1) % circleDiv, offset + (j + reg) % circleDiv + circleDiv, offset + (j + reg + 1) % circleDiv + circleDiv, undefined, c));
|
|
30992
|
-
//indexArray = indexArray.concat([offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv]);
|
|
30993
|
-
indexArray[offset3++] = offsetTmp + j;
|
|
30994
|
-
indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
|
|
30995
|
-
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.
|
|
30996
31234
|
|
|
30997
|
-
|
|
30998
|
-
indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
|
|
30999
|
-
indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
|
|
31000
|
-
indexArray[offset3++] = offsetTmp + (j + reg + 1) % circleDiv + circleDiv;
|
|
31001
|
-
}
|
|
31002
|
-
offsetTmp += circleDiv;
|
|
31003
|
-
}
|
|
31235
|
+
if(lastAtom.ss !== undefined && lastAtom.ss !== 'coil' && !(lastAtom.ssend) && !(lastAtom.notshow)) {
|
|
31004
31236
|
|
|
31005
|
-
|
|
31006
|
-
|
|
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;
|
|
31007
31241
|
|
|
31008
|
-
|
|
31009
|
-
//geo.setIndex(indexArray);
|
|
31242
|
+
let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[residueid]);
|
|
31010
31243
|
|
|
31011
|
-
|
|
31012
|
-
|
|
31013
|
-
|
|
31244
|
+
if(atom.ss === lastAtom.ss && atom.ssend) {
|
|
31245
|
+
endResi = atom.resi;
|
|
31246
|
+
break;
|
|
31247
|
+
}
|
|
31248
|
+
}
|
|
31014
31249
|
|
|
31015
|
-
|
|
31016
|
-
|
|
31017
|
-
|
|
31018
|
-
|
|
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
|
+
}
|
|
31019
31256
|
|
|
31020
|
-
|
|
31021
|
-
|
|
31022
|
-
|
|
31023
|
-
|
|
31024
|
-
|
|
31025
|
-
|
|
31026
|
-
|
|
31027
|
-
|
|
31028
|
-
|
|
31029
|
-
//mesh = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({ specular: ic.frac, shininess: ic.shininess, emissive: ic.emissive, vertexColors: THREE.FaceColors, side: THREE.DoubleSide }));
|
|
31030
|
-
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
|
+
}
|
|
31031
31266
|
|
|
31032
|
-
|
|
31033
|
-
|
|
31267
|
+
// reset notshow
|
|
31268
|
+
if(lastAtom.notshow) lastAtom.notshow = undefined;
|
|
31034
31269
|
|
|
31035
|
-
|
|
31036
|
-
|
|
31037
|
-
}
|
|
31038
|
-
else {
|
|
31039
|
-
ic.objects.push(mesh);
|
|
31040
|
-
}
|
|
31041
|
-
}
|
|
31270
|
+
firstAtom = currAtom;
|
|
31271
|
+
}
|
|
31042
31272
|
|
|
31043
|
-
|
|
31044
|
-
|
|
31045
|
-
|
|
31046
|
-
|
|
31047
|
-
|
|
31048
|
-
else {
|
|
31049
|
-
if(atom.b > 0 && atom.b <= 100) {
|
|
31050
|
-
radiusFinal = atom.b * 0.01;
|
|
31051
|
-
}
|
|
31052
|
-
else if(atom.b > 100) {
|
|
31053
|
-
radiusFinal = 100 * 0.01;
|
|
31054
|
-
}
|
|
31055
|
-
else {
|
|
31056
|
-
radiusFinal = ic.coilWidth;
|
|
31057
|
-
}
|
|
31273
|
+
prevChain = currChain;
|
|
31274
|
+
prevResi = currResi;
|
|
31275
|
+
prevAtom = currAtom;
|
|
31276
|
+
|
|
31277
|
+
++index;
|
|
31058
31278
|
}
|
|
31059
31279
|
|
|
31060
|
-
return
|
|
31280
|
+
return atomsAdjust;
|
|
31061
31281
|
}
|
|
31062
31282
|
}
|
|
31063
31283
|
|
|
@@ -48711,6 +48931,13 @@ class ShowAnno {
|
|
|
48711
48931
|
} // align seq to structure
|
|
48712
48932
|
}
|
|
48713
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
|
+
}
|
|
48714
48941
|
}
|
|
48715
48942
|
|
|
48716
48943
|
async showAnnoSeqData(nucleotide_chainid, chemical_chainid, chemical_set) { let ic = this.icn3d, me = ic.icn3dui;
|
|
@@ -54445,6 +54672,7 @@ class AlignParser {
|
|
|
54445
54672
|
|
|
54446
54673
|
async downloadAlignmentPart2(data, seqalign, chainresiCalphaHash2) { let ic = this.icn3d, me = ic.icn3dui;
|
|
54447
54674
|
//ic.init();
|
|
54675
|
+
|
|
54448
54676
|
ic.loadAtomDataCls.loadAtomDataIn(data, undefined, 'align', seqalign);
|
|
54449
54677
|
|
|
54450
54678
|
if(me.cfg.align === undefined && Object.keys(ic.structures).length == 1) {
|
|
@@ -54488,20 +54716,21 @@ class AlignParser {
|
|
|
54488
54716
|
async loadOpmDataForAlign(data, seqalign, mmdbidArray) { let ic = this.icn3d, me = ic.icn3dui;
|
|
54489
54717
|
let thisClass = this;
|
|
54490
54718
|
|
|
54491
|
-
let url = "https://opm-assets.storage.googleapis.com/pdb/" + mmdbidArray[0].toLowerCase()+ ".pdb";
|
|
54492
|
-
let prms1 = me.getAjaxPromise(url, 'text');
|
|
54493
|
-
let url2 = "https://opm-assets.storage.googleapis.com/pdb/" + mmdbidArray[1].toLowerCase()+ ".pdb";
|
|
54494
|
-
let prms2 = me.getAjaxPromise(url2, 'text');
|
|
54495
|
-
|
|
54496
|
-
let allPromise = Promise.allSettled([prms1, prms2]);
|
|
54497
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
|
+
|
|
54498
54727
|
let dataArray = await allPromise;
|
|
54499
|
-
|
|
54728
|
+
|
|
54500
54729
|
let bFound = false;
|
|
54501
54730
|
for(let i = 0, il = dataArray.length; i < il; ++i) {
|
|
54502
|
-
//
|
|
54503
|
-
let opmdata = dataArray[i].value;
|
|
54731
|
+
// if(dataArray[i].status == 'rejected') continue;
|
|
54504
54732
|
|
|
54733
|
+
let opmdata = dataArray[i].value;
|
|
54505
54734
|
if(!opmdata) continue;
|
|
54506
54735
|
|
|
54507
54736
|
ic.selectedPdbid = mmdbidArray[i];
|
|
@@ -54517,6 +54746,7 @@ class AlignParser {
|
|
|
54517
54746
|
$("#" + ic.pre + "intra_mem_z").val(-ic.halfBilayerSize);
|
|
54518
54747
|
|
|
54519
54748
|
ic.init(); // remove all previously loaded data
|
|
54749
|
+
|
|
54520
54750
|
await thisClass.downloadAlignmentPart2(data, seqalign, chainresiCalphaHash);
|
|
54521
54751
|
|
|
54522
54752
|
bFound = true;
|
|
@@ -59092,7 +59322,7 @@ class SdfParser {
|
|
|
59092
59322
|
let sdfStr = await me.getAjaxPromise(urlSmiles, 'text');
|
|
59093
59323
|
|
|
59094
59324
|
ic.init();
|
|
59095
|
-
ic.bInputfile = true;
|
|
59325
|
+
//ic.bInputfile = true;
|
|
59096
59326
|
ic.InputfileData = (ic.InputfileData) ? ic.InputfileData + '\nENDMDL\n' + sdfStr : sdfStr;
|
|
59097
59327
|
ic.InputfileType = 'sdf';
|
|
59098
59328
|
await ic.sdfParserCls.loadSdfData(sdfStr);
|
|
@@ -61901,6 +62131,7 @@ class ParserUtils {
|
|
|
61901
62131
|
ic.selectionCls.oneStructurePerWindow(); // for alignment
|
|
61902
62132
|
ic.drawCls.draw();
|
|
61903
62133
|
}
|
|
62134
|
+
|
|
61904
62135
|
if(ic.bOpm) {
|
|
61905
62136
|
let axis = new THREE.Vector3(1,0,0);
|
|
61906
62137
|
let angle = -0.5 * Math.PI;
|
|
@@ -64438,7 +64669,8 @@ class LoadPDB {
|
|
|
64438
64669
|
|
|
64439
64670
|
// modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
64440
64671
|
//This PDB parser feeds the viewer with the content of a PDB file, pdbData.
|
|
64441
|
-
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;
|
|
64442
64674
|
let hAtoms = {};
|
|
64443
64675
|
|
|
64444
64676
|
let bNMR = false;
|
|
@@ -69559,17 +69791,15 @@ class SelectCollections {
|
|
|
69559
69791
|
}
|
|
69560
69792
|
|
|
69561
69793
|
//Set the menu of defined sets with an array of defined names "commandnameArray".
|
|
69562
|
-
setAtomMenu(
|
|
69794
|
+
setAtomMenu(collection) {
|
|
69563
69795
|
let ic = this.icn3d;
|
|
69564
69796
|
ic.icn3dui;
|
|
69565
69797
|
let html = "";
|
|
69566
|
-
|
|
69567
|
-
|
|
69568
|
-
let name = nameArray[i][0];
|
|
69569
|
-
let title = nameArray[i][1];
|
|
69570
|
-
let description = nameArray[i][2];
|
|
69571
|
-
|
|
69798
|
+
|
|
69799
|
+
Object.entries(collection).forEach(([name, structure], index) => {
|
|
69572
69800
|
let atomHash;
|
|
69801
|
+
let [id, title, description, commands, pdb] = structure;
|
|
69802
|
+
|
|
69573
69803
|
if (
|
|
69574
69804
|
ic.defNames2Atoms !== undefined &&
|
|
69575
69805
|
ic.defNames2Atoms.hasOwnProperty(name)
|
|
@@ -69590,12 +69820,12 @@ class SelectCollections {
|
|
|
69590
69820
|
}
|
|
69591
69821
|
}
|
|
69592
69822
|
|
|
69593
|
-
if (
|
|
69594
|
-
html += "<option value='" +
|
|
69595
|
-
|
|
69823
|
+
if (index === 0) {
|
|
69824
|
+
html += "<option value='" + name + "' selected='selected' data-description='" + description + "'>" + title + "</option>";
|
|
69825
|
+
} else {
|
|
69596
69826
|
html += "<option value='" + name + "' data-description='" + description + "'>" + title + "</option>";
|
|
69597
|
-
|
|
69598
|
-
}
|
|
69827
|
+
}
|
|
69828
|
+
});
|
|
69599
69829
|
|
|
69600
69830
|
return html;
|
|
69601
69831
|
}
|
|
@@ -69649,7 +69879,7 @@ class SelectCollections {
|
|
|
69649
69879
|
let nameArray = $(this).val();
|
|
69650
69880
|
let nameStructure = $(this).find("option:selected").text();
|
|
69651
69881
|
let selectedIndices = Array.from(this.selectedOptions).map(option => option.index);
|
|
69652
|
-
|
|
69882
|
+
nameArray.reduce((map, name, i) => {
|
|
69653
69883
|
map[name] = selectedIndices[i];
|
|
69654
69884
|
return map;
|
|
69655
69885
|
}, {});
|
|
@@ -69686,13 +69916,13 @@ class SelectCollections {
|
|
|
69686
69916
|
if (Object.keys(ic.structures).length == 0) {
|
|
69687
69917
|
bAppend = false;
|
|
69688
69918
|
}
|
|
69689
|
-
await ic.pdbParserCls.loadPdbData(ic.pdbCollection[
|
|
69919
|
+
await ic.pdbParserCls.loadPdbData(ic.pdbCollection[name].join('\n'), undefined, undefined, bAppend);
|
|
69690
69920
|
} else {
|
|
69691
69921
|
await ic.chainalignParserCls.downloadMmdbAf(name, undefined, undefined, bNoDuplicate);
|
|
69692
69922
|
}
|
|
69693
69923
|
}
|
|
69694
69924
|
|
|
69695
|
-
await loadStructure(collection[
|
|
69925
|
+
await loadStructure(collection[name][4]).then(() => {
|
|
69696
69926
|
ic.allData['all'] = {
|
|
69697
69927
|
'atoms': ic.atoms,
|
|
69698
69928
|
'proteins': ic.proteins,
|
|
@@ -69752,9 +69982,9 @@ class SelectCollections {
|
|
|
69752
69982
|
|
|
69753
69983
|
ic.molTitle = ic.allData[name]['title'];
|
|
69754
69984
|
|
|
69755
|
-
if (collection[
|
|
69985
|
+
if (collection[name][3] !== undefined && collection[name][3].length > 0) {
|
|
69756
69986
|
if (ic.allData[name]['commands'] == undefined) {
|
|
69757
|
-
let commands = collection[
|
|
69987
|
+
let commands = collection[name][3];
|
|
69758
69988
|
ic.allData[name]['commands'] = commands;
|
|
69759
69989
|
}
|
|
69760
69990
|
}
|
|
@@ -72396,155 +72626,6 @@ class Resid2spec {
|
|
|
72396
72626
|
}
|
|
72397
72627
|
}
|
|
72398
72628
|
|
|
72399
|
-
/**
|
|
72400
|
-
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
72401
|
-
*/
|
|
72402
|
-
|
|
72403
|
-
class FirstAtomObj {
|
|
72404
|
-
constructor(icn3d) {
|
|
72405
|
-
this.icn3d = icn3d;
|
|
72406
|
-
}
|
|
72407
|
-
|
|
72408
|
-
//Return the first atom in the atom hash, which has the atom serial number as the key.
|
|
72409
|
-
getFirstAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
72410
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
72411
|
-
return undefined;
|
|
72412
|
-
}
|
|
72413
|
-
|
|
72414
|
-
let atomKeys = Object.keys(atomsHash);
|
|
72415
|
-
let firstIndex = atomKeys[0];
|
|
72416
|
-
|
|
72417
|
-
return ic.atoms[firstIndex];
|
|
72418
|
-
}
|
|
72419
|
-
|
|
72420
|
-
// n is the position of the selected atom
|
|
72421
|
-
getMiddleAtomObj(atomsHash, n) { let ic = this.icn3d; ic.icn3dui;
|
|
72422
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
72423
|
-
return undefined;
|
|
72424
|
-
}
|
|
72425
|
-
|
|
72426
|
-
let atomKeys = Object.keys(atomsHash);
|
|
72427
|
-
let middleIndex = (n && n < atomKeys.length) ? atomKeys[n] : atomKeys[parseInt(atomKeys.length / 2)];
|
|
72428
|
-
|
|
72429
|
-
return ic.atoms[middleIndex];
|
|
72430
|
-
}
|
|
72431
|
-
|
|
72432
|
-
getFirstCalphaAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
72433
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
72434
|
-
return undefined;
|
|
72435
|
-
}
|
|
72436
|
-
|
|
72437
|
-
let firstIndex;
|
|
72438
|
-
|
|
72439
|
-
for(let i in atomsHash) {
|
|
72440
|
-
if(ic.atoms[i].name == 'CA') {
|
|
72441
|
-
firstIndex = i;
|
|
72442
|
-
break;
|
|
72443
|
-
}
|
|
72444
|
-
}
|
|
72445
|
-
|
|
72446
|
-
if(!firstIndex) {
|
|
72447
|
-
for(let i in atomsHash) {
|
|
72448
|
-
if(ic.atoms[i].name == "O3'" || ic.atoms[i].name == "O3*") {
|
|
72449
|
-
firstIndex = i;
|
|
72450
|
-
break;
|
|
72451
|
-
}
|
|
72452
|
-
}
|
|
72453
|
-
}
|
|
72454
|
-
|
|
72455
|
-
return (firstIndex !== undefined) ? ic.atoms[firstIndex] : this.getFirstAtomObj(atomsHash);
|
|
72456
|
-
}
|
|
72457
|
-
|
|
72458
|
-
getFirstAtomObjByName(atomsHash, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
72459
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
72460
|
-
return ic.atoms[0];
|
|
72461
|
-
}
|
|
72462
|
-
|
|
72463
|
-
let firstIndex;
|
|
72464
|
-
|
|
72465
|
-
for(let i in atomsHash) {
|
|
72466
|
-
if(ic.atoms[i].name == atomName) {
|
|
72467
|
-
firstIndex = i;
|
|
72468
|
-
break;
|
|
72469
|
-
}
|
|
72470
|
-
}
|
|
72471
|
-
|
|
72472
|
-
return (firstIndex !== undefined) ? ic.atoms[firstIndex] : undefined;
|
|
72473
|
-
}
|
|
72474
|
-
|
|
72475
|
-
//Return the last atom in the atom hash, which has the atom serial number as the key.
|
|
72476
|
-
getLastAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
72477
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
72478
|
-
return ic.atoms[0];
|
|
72479
|
-
}
|
|
72480
|
-
|
|
72481
|
-
let atomKeys = Object.keys(atomsHash);
|
|
72482
|
-
let lastIndex = atomKeys[atomKeys.length - 1];
|
|
72483
|
-
|
|
72484
|
-
return ic.atoms[lastIndex];
|
|
72485
|
-
}
|
|
72486
|
-
|
|
72487
|
-
//Return the residue hash from the atom hash. The residue hash has the resid as the key and 1 as the value.
|
|
72488
|
-
getResiduesFromAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
72489
|
-
let residuesHash = {};
|
|
72490
|
-
for(let i in atomsHash) {
|
|
72491
|
-
let residueid = ic.atoms[i].structure + '_' + ic.atoms[i].chain + '_' + ic.atoms[i].resi;
|
|
72492
|
-
residuesHash[residueid] = 1;
|
|
72493
|
-
}
|
|
72494
|
-
|
|
72495
|
-
return residuesHash;
|
|
72496
|
-
}
|
|
72497
|
-
|
|
72498
|
-
getResiduesFromCalphaAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
72499
|
-
let residuesHash = {};
|
|
72500
|
-
for(let i in atomsHash) {
|
|
72501
|
-
if((ic.atoms[i].name == 'CA' && ic.proteins.hasOwnProperty(i)) || !ic.proteins.hasOwnProperty(i)) {
|
|
72502
|
-
let residueid = ic.atoms[i].structure + '_' + ic.atoms[i].chain + '_' + ic.atoms[i].resi;
|
|
72503
|
-
//residuesHash[residueid] = 1;
|
|
72504
|
-
residuesHash[residueid] = ic.atoms[i].resn;
|
|
72505
|
-
}
|
|
72506
|
-
}
|
|
72507
|
-
|
|
72508
|
-
return residuesHash;
|
|
72509
|
-
}
|
|
72510
|
-
|
|
72511
|
-
//Return the chain hash from the atom hash. The chain hash has the chainid as the key and 1 as the value.
|
|
72512
|
-
getChainsFromAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
72513
|
-
let chainsHash = {};
|
|
72514
|
-
for(let i in atomsHash) {
|
|
72515
|
-
let atom = ic.atoms[i];
|
|
72516
|
-
let chainid = atom.structure + "_" + atom.chain;
|
|
72517
|
-
|
|
72518
|
-
chainsHash[chainid] = 1;
|
|
72519
|
-
}
|
|
72520
|
-
|
|
72521
|
-
return chainsHash;
|
|
72522
|
-
}
|
|
72523
|
-
|
|
72524
|
-
getAtomFromResi(resid, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
72525
|
-
if(ic.residues.hasOwnProperty(resid)) {
|
|
72526
|
-
for(let i in ic.residues[resid]) {
|
|
72527
|
-
if(ic.atoms[i].name === atomName && !ic.atoms[i].het) {
|
|
72528
|
-
return ic.atoms[i];
|
|
72529
|
-
}
|
|
72530
|
-
}
|
|
72531
|
-
}
|
|
72532
|
-
|
|
72533
|
-
return undefined;
|
|
72534
|
-
}
|
|
72535
|
-
|
|
72536
|
-
getAtomCoordFromResi(resid, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
72537
|
-
let atom = this.getAtomFromResi(resid, atomName);
|
|
72538
|
-
if(atom !== undefined) {
|
|
72539
|
-
let coord = (atom.coord2 !== undefined) ? atom.coord2 : atom.coord;
|
|
72540
|
-
|
|
72541
|
-
return coord;
|
|
72542
|
-
}
|
|
72543
|
-
|
|
72544
|
-
return undefined;
|
|
72545
|
-
}
|
|
72546
|
-
}
|
|
72547
|
-
|
|
72548
72629
|
/**
|
|
72549
72630
|
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
72550
72631
|
*/
|
|
@@ -72605,9 +72686,9 @@ class Delphi {
|
|
|
72605
72686
|
let pdbstr = '';
|
|
72606
72687
|
/// pdbstr += ic.saveFileCls.getPDBHeader();
|
|
72607
72688
|
|
|
72608
|
-
let bMergeIntoOne = true;
|
|
72609
|
-
pdbstr +=(me.cfg.cid) ? ic.saveFileCls.getAtomPDB(atomHash, true, undefined, undefined, undefined, undefined, bMergeIntoOne) : ic.saveFileCls.getAtomPDB(atomHash, undefined, undefined, undefined, undefined, undefined, bMergeIntoOne);
|
|
72610
|
-
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);
|
|
72611
72692
|
|
|
72612
72693
|
return pdbstr;
|
|
72613
72694
|
}
|
|
@@ -79877,7 +79958,7 @@ class SaveFile {
|
|
|
79877
79958
|
}
|
|
79878
79959
|
|
|
79879
79960
|
//getAtomPDB: function(atomHash, bPqr, bPdb, bNoChem) { let ic = this.icn3d, me = ic.icn3dui;
|
|
79880
|
-
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;
|
|
79881
79962
|
let pdbStr = '';
|
|
79882
79963
|
|
|
79883
79964
|
// get all phosphate groups in lipids
|
|
@@ -80152,7 +80233,7 @@ class SaveFile {
|
|
|
80152
80233
|
//line +=(atom.chain.length <= 1) ? atom.chain.padStart(1, ' ') : atom.chain.substr(0, 1);
|
|
80153
80234
|
if(atom.chain.length >= 2) {
|
|
80154
80235
|
let chainTmp = atom.chain.replace(/_/gi, '').substr(0, 2);
|
|
80155
|
-
if(
|
|
80236
|
+
if(bOneLetterChain) chainTmp = ' ' + chainTmp.substr(0,1); // VAST search only support one lettter chain ID
|
|
80156
80237
|
line += chainTmp;
|
|
80157
80238
|
}
|
|
80158
80239
|
else if(atom.chain.length == 1) {
|
|
@@ -80231,8 +80312,8 @@ class SaveFile {
|
|
|
80231
80312
|
}
|
|
80232
80313
|
else {
|
|
80233
80314
|
line += "1.00".padStart(6, ' ');
|
|
80234
|
-
//
|
|
80235
|
-
let defaultBFactor =
|
|
80315
|
+
// let defaultBFactor = (bOneLetterChain) ? "1.0" : " ";
|
|
80316
|
+
let defaultBFactor = " ";
|
|
80236
80317
|
line +=(atom.b) ? parseFloat(atom.b).toFixed(2).toString().padStart(6, ' ') : defaultBFactor.padStart(6, ' ');
|
|
80237
80318
|
line += ' '.padStart(10, ' ');
|
|
80238
80319
|
line += atom.elem.padStart(2, ' ');
|
|
@@ -80280,7 +80361,7 @@ class SaveFile {
|
|
|
80280
80361
|
let resn = me.utilsCls.residueName2Abbr(atom.resn);
|
|
80281
80362
|
let ss = this.secondary2Abbr(atom.ss);
|
|
80282
80363
|
|
|
80283
|
-
if(chainid != prevChainid) {
|
|
80364
|
+
if(chainid != prevChainid && !data[chainid]) {
|
|
80284
80365
|
data[chainid] = {"resi": [], "resn": [], "secondary": []};
|
|
80285
80366
|
}
|
|
80286
80367
|
|
|
@@ -80301,8 +80382,8 @@ class SaveFile {
|
|
|
80301
80382
|
json += '{"chain": "' + chainid + '",\n';
|
|
80302
80383
|
|
|
80303
80384
|
json += '"resi": "' + data[chainid]["resi"].join(',') + '",\n';
|
|
80304
|
-
json += '"resn": "' + data[chainid]["resn"].join('') + '",\n';
|
|
80305
|
-
json += '"secondary": "' + data[chainid]["secondary"].join('') + '"';
|
|
80385
|
+
json += '"resn": "' + data[chainid]["resn"].join(',') + '",\n';
|
|
80386
|
+
json += '"secondary": "' + data[chainid]["secondary"].join(',') + '"';
|
|
80306
80387
|
|
|
80307
80388
|
if(i < cnt - 1) {
|
|
80308
80389
|
json += '},\n';
|
|
@@ -83804,7 +83885,7 @@ class iCn3DUI {
|
|
|
83804
83885
|
//even when multiple iCn3D viewers are shown together.
|
|
83805
83886
|
this.pre = this.cfg.divid + "_";
|
|
83806
83887
|
|
|
83807
|
-
this.REVISION = '3.40.
|
|
83888
|
+
this.REVISION = '3.40.3';
|
|
83808
83889
|
|
|
83809
83890
|
// In nodejs, iCn3D defines "window = {navigator: {}}"
|
|
83810
83891
|
this.bNode = (Object.keys(window).length < 2) ? true : false;
|
|
@@ -83966,7 +84047,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
|
|
|
83966
84047
|
ic.molTitle = '';
|
|
83967
84048
|
ic.loadCmd;
|
|
83968
84049
|
|
|
83969
|
-
// set menus
|
|
84050
|
+
// set menus
|
|
83970
84051
|
me.htmlCls.clickMenuCls.getHiddenMenusFromCache();
|
|
83971
84052
|
me.htmlCls.clickMenuCls.applyShownMenus();
|
|
83972
84053
|
|