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.js
CHANGED
|
@@ -8827,25 +8827,42 @@ class ClickMenu {
|
|
|
8827
8827
|
}
|
|
8828
8828
|
|
|
8829
8829
|
getHiddenMenusFromCache() { let me = this.icn3dui; me.icn3d;
|
|
8830
|
-
|
|
8830
|
+
// me.htmlCls.shownMenus = {};
|
|
8831
8831
|
|
|
8832
|
-
|
|
8833
|
-
|
|
8834
|
-
if(idArrayStr && idArrayStr != '[]') {
|
|
8835
|
-
let idArray = JSON.parse(idArrayStr);
|
|
8832
|
+
// let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
|
|
8836
8833
|
|
|
8837
|
-
|
|
8838
|
-
|
|
8839
|
-
|
|
8840
|
-
|
|
8841
|
-
|
|
8842
|
-
|
|
8843
|
-
|
|
8834
|
+
let idArrayStr = (localStorage) ? localStorage.getItem('hiddenmenus') : '';
|
|
8835
|
+
|
|
8836
|
+
if(idArrayStr && idArrayStr != '[]') {
|
|
8837
|
+
me.htmlCls.shownMenus = {};
|
|
8838
|
+
|
|
8839
|
+
let idArray = JSON.parse(idArrayStr);
|
|
8840
|
+
|
|
8841
|
+
// for(let i = 0, il = idArray.length; i < il; ++i) {
|
|
8842
|
+
// me.htmlCls.shownMenus[idArray[i]] = 1;
|
|
8843
|
+
// }
|
|
8844
|
+
for(let menu in me.htmlCls.allMenus) {
|
|
8845
|
+
if(idArray.indexOf(menu) == -1) {
|
|
8846
|
+
me.htmlCls.shownMenus[menu] = 1;
|
|
8844
8847
|
}
|
|
8845
|
-
|
|
8846
|
-
|
|
8847
|
-
|
|
8848
|
-
|
|
8848
|
+
}
|
|
8849
|
+
}
|
|
8850
|
+
//###
|
|
8851
|
+
else {
|
|
8852
|
+
me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
|
|
8853
|
+
}
|
|
8854
|
+
|
|
8855
|
+
// else {
|
|
8856
|
+
// if(mode == 'all') {
|
|
8857
|
+
// me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
|
|
8858
|
+
// }
|
|
8859
|
+
// else if(!mode || mode == 'simple') {
|
|
8860
|
+
// me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
|
|
8861
|
+
// }
|
|
8862
|
+
// else {
|
|
8863
|
+
// me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
|
|
8864
|
+
// }
|
|
8865
|
+
// }
|
|
8849
8866
|
}
|
|
8850
8867
|
|
|
8851
8868
|
displayShownMenus() { let me = this.icn3dui; me.icn3d;
|
|
@@ -9341,11 +9358,14 @@ class ClickMenu {
|
|
|
9341
9358
|
me.htmlCls.shownMenus[checkbox.value] = 1;
|
|
9342
9359
|
}
|
|
9343
9360
|
|
|
9361
|
+
me.htmlCls.setHtmlCls.setCookie('menumode', 'custom');
|
|
9362
|
+
|
|
9344
9363
|
thisClass.applyShownMenus();
|
|
9345
9364
|
});
|
|
9346
9365
|
|
|
9347
9366
|
me.myEventCls.onIds(["#" + me.pre + "reset_menupref", "#" + me.pre + "reset_menupref2"], "click", function(e) { me.icn3d; //e.preventDefault();
|
|
9348
9367
|
me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
|
|
9368
|
+
me.htmlCls.setHtmlCls.setCookie('menumode', 'simple');
|
|
9349
9369
|
|
|
9350
9370
|
thisClass.applyShownMenus();
|
|
9351
9371
|
thisClass.displayShownMenus();
|
|
@@ -9353,6 +9373,7 @@ class ClickMenu {
|
|
|
9353
9373
|
|
|
9354
9374
|
me.myEventCls.onIds(["#" + me.pre + "reset_menupref_all", "#" + me.pre + "reset_menupref_all2"], "click", function(e) { me.icn3d; //e.preventDefault();
|
|
9355
9375
|
me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
|
|
9376
|
+
me.htmlCls.setHtmlCls.setCookie('menumode', 'all');
|
|
9356
9377
|
|
|
9357
9378
|
thisClass.applyShownMenus();
|
|
9358
9379
|
thisClass.displayShownMenus();
|
|
@@ -9402,15 +9423,16 @@ class ClickMenu {
|
|
|
9402
9423
|
|
|
9403
9424
|
thisClass.applyShownMenus();
|
|
9404
9425
|
thisClass.displayShownMenus();
|
|
9426
|
+
|
|
9427
|
+
me.htmlCls.setHtmlCls.setCookie('menumode', 'custom');
|
|
9405
9428
|
};
|
|
9406
9429
|
reader.readAsText(file);
|
|
9407
9430
|
}
|
|
9408
9431
|
});
|
|
9409
9432
|
|
|
9410
|
-
me.myEventCls.onIds("#" + me.pre + "mn1_menuloadpref", "click", function(e) { me.icn3d; //e.preventDefault();
|
|
9433
|
+
me.myEventCls.onIds(["#" + me.pre + "mn1_menuloadpref", "#" + me.pre + "loadpref", "#" + me.pre + "loadpref2"], "click", function(e) { me.icn3d; //e.preventDefault();
|
|
9411
9434
|
me.htmlCls.dialogCls.openDlg('dl_menuloadpref', 'Please input the menu preference file');
|
|
9412
9435
|
});
|
|
9413
|
-
|
|
9414
9436
|
|
|
9415
9437
|
me.myEventCls.onIds("#" + me.pre + "mn1_link_structure", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
|
|
9416
9438
|
let url = ic.saveFileCls.getLinkToStructureSummary(true);
|
|
@@ -11249,6 +11271,51 @@ class SetMenu {
|
|
|
11249
11271
|
return me.htmlCls.setHtmlCls.getRadioColor(radioid, id, text, color, bChecked, bSimpleMenu, selType);
|
|
11250
11272
|
}
|
|
11251
11273
|
|
|
11274
|
+
resetMenu(mode) { let me = this.icn3dui;
|
|
11275
|
+
if(!mode || mode == 'simple') {
|
|
11276
|
+
me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
|
|
11277
|
+
|
|
11278
|
+
me.htmlCls.clickMenuCls.applyShownMenus();
|
|
11279
|
+
}
|
|
11280
|
+
else if(mode == 'all') {
|
|
11281
|
+
me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
|
|
11282
|
+
|
|
11283
|
+
me.htmlCls.clickMenuCls.applyShownMenus();
|
|
11284
|
+
}
|
|
11285
|
+
else if(mode == 'custom') {
|
|
11286
|
+
me.htmlCls.dialogCls.openDlg('dl_menupref', 'Select Menus');
|
|
11287
|
+
|
|
11288
|
+
me.htmlCls.clickMenuCls.getHiddenMenusFromCache();
|
|
11289
|
+
|
|
11290
|
+
me.htmlCls.clickMenuCls.displayShownMenus();
|
|
11291
|
+
}
|
|
11292
|
+
}
|
|
11293
|
+
|
|
11294
|
+
setMenuMode(bMobile) { let me = this.icn3dui;
|
|
11295
|
+
let spaceCss = (bMobile) ? "; padding-left:6px; background-color:#eee" : "; margin:3px; background-color:white";
|
|
11296
|
+
let spaceCss2 = (bMobile) ? "; font-size:14px!important" : "";
|
|
11297
|
+
|
|
11298
|
+
let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
|
|
11299
|
+
|
|
11300
|
+
let html = '<div class="icn3d-text" style="color:#f8b84e; font-weight:bold' + spaceCss + '">';
|
|
11301
|
+
html += '<select name="menumode" id="' + me.pre + 'menumode" class="icn3d-text" style="color:#f8b84e; font-weight:bold; border:0px' + spaceCss2 + '">';
|
|
11302
|
+
html += (mode == 'simple' || !mode) ? '<option value="simple" selected>Simple</option>' : '<option value="simple">Simple</option>';
|
|
11303
|
+
html += (mode == 'all') ? '<option value="all" selected>All</option>' : '<option value="all">All</option>';
|
|
11304
|
+
html += (mode == 'custom') ? '<option value="custom" selected>Custom</option>' : '<option value="custom">Custom</option>';
|
|
11305
|
+
html += '</select>';
|
|
11306
|
+
|
|
11307
|
+
if(bMobile) {
|
|
11308
|
+
html += '<br><span style="font-size:12px"> Menus</span>';
|
|
11309
|
+
}
|
|
11310
|
+
else {
|
|
11311
|
+
html += ' Menus';
|
|
11312
|
+
}
|
|
11313
|
+
|
|
11314
|
+
html += '</div>';
|
|
11315
|
+
|
|
11316
|
+
return html;
|
|
11317
|
+
}
|
|
11318
|
+
|
|
11252
11319
|
//Set the HTML code for the menus shown at the top of the viewer.
|
|
11253
11320
|
setTopMenusHtml(id, str1, str2) { let me = this.icn3dui;
|
|
11254
11321
|
if(me.bNode) return '';
|
|
@@ -11268,6 +11335,9 @@ class SetMenu {
|
|
|
11268
11335
|
html += "<table border='0' cellpadding='0' cellspacing='0' width='100'><tr>";
|
|
11269
11336
|
|
|
11270
11337
|
let tdStr = '<td valign="top">';
|
|
11338
|
+
|
|
11339
|
+
// html += tdStr + this.setMenuMode() + '</td>';
|
|
11340
|
+
|
|
11271
11341
|
html += tdStr + this.setMenu1() + '</td>';
|
|
11272
11342
|
|
|
11273
11343
|
html += tdStr + this.setMenu2() + '</td>';
|
|
@@ -11280,7 +11350,11 @@ class SetMenu {
|
|
|
11280
11350
|
//html += tdStr + this.setMenu5b() + '</td>';
|
|
11281
11351
|
html += tdStr + this.setMenu6() + '</td>';
|
|
11282
11352
|
|
|
11283
|
-
|
|
11353
|
+
// reset the menus at the end of the menus
|
|
11354
|
+
// let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
|
|
11355
|
+
// this.resetMenu(mode);
|
|
11356
|
+
|
|
11357
|
+
// me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
|
|
11284
11358
|
|
|
11285
11359
|
html += tdStr + "<div style='position:relative; margin-left:6px;'>" + str1;
|
|
11286
11360
|
html += "<div class='icn3d-commandTitle' style='min-width:40px; margin-top: 3px; white-space: nowrap;'>" + str2;
|
|
@@ -11376,6 +11450,7 @@ class SetMenu {
|
|
|
11376
11450
|
|
|
11377
11451
|
//html += "<div class='icn3d-menu'>";
|
|
11378
11452
|
html += "<div>";
|
|
11453
|
+
|
|
11379
11454
|
html += "<accordion id='" + me.pre + "accordion0' class='icn3d-accordion'>";
|
|
11380
11455
|
if(me.cfg.notebook) {
|
|
11381
11456
|
html += "<h3 style='width:20px; height:24px; position:relative; padding: 0'><span style='position:absolute; left:3px; top:4px;'>☰</span></h3>";
|
|
@@ -11385,6 +11460,8 @@ class SetMenu {
|
|
|
11385
11460
|
}
|
|
11386
11461
|
html += "<div>";
|
|
11387
11462
|
|
|
11463
|
+
// html += '<li>' + this.setMenuMode(true);
|
|
11464
|
+
|
|
11388
11465
|
let liStr = "<li><span class='icn3d-menu-color'";
|
|
11389
11466
|
|
|
11390
11467
|
html += "<ul class='icn3d-mn-item'>";
|
|
@@ -11403,7 +11480,11 @@ class SetMenu {
|
|
|
11403
11480
|
html += liStr + ">Help</span>";
|
|
11404
11481
|
html += this.setMenu6_base();
|
|
11405
11482
|
|
|
11406
|
-
|
|
11483
|
+
// reset the menus at the end of the menus
|
|
11484
|
+
// let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
|
|
11485
|
+
// this.resetMenu(mode);
|
|
11486
|
+
|
|
11487
|
+
// me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
|
|
11407
11488
|
|
|
11408
11489
|
html += "<li><div style='position:relative; margin-top:-6px;'>" + str1;
|
|
11409
11490
|
html += "<div class='icn3d-commandTitle' style='margin-top: 3px; white-space: nowrap;'>" + str2;
|
|
@@ -11580,7 +11661,7 @@ class SetMenu {
|
|
|
11580
11661
|
// Analysis menu
|
|
11581
11662
|
html += tdStrBorder + this.setIcon(iconType, 'tool_selectannotations', 'Sequences & Annotations', 'grip-lines') + "</td>";
|
|
11582
11663
|
html += tdStr + this.setIcon(iconType, 'hbondsYes', 'Interactions', 'users') + "</td>";
|
|
11583
|
-
html += tdStr + this.setIcon(iconType, 'tool_delphi', '
|
|
11664
|
+
html += tdStr + this.setIcon(iconType, 'tool_delphi', 'DelPhi Potentials', 'cloud-meatball') + "</td>";
|
|
11584
11665
|
html += tdStr + this.setIcon(iconType, 'removeLabels', 'Remove Labels', 'remove-format') + "</td>";
|
|
11585
11666
|
|
|
11586
11667
|
// Help menu
|
|
@@ -13597,7 +13678,7 @@ class Dialog {
|
|
|
13597
13678
|
width='50%';
|
|
13598
13679
|
}
|
|
13599
13680
|
else if(id === me.pre + 'dl_menupref') {
|
|
13600
|
-
width =
|
|
13681
|
+
width = 800;
|
|
13601
13682
|
height = 500;
|
|
13602
13683
|
}
|
|
13603
13684
|
|
|
@@ -14258,6 +14339,10 @@ class SetDialog {
|
|
|
14258
14339
|
html += me.htmlCls.divStr + "dl_collection_file' style=''>";
|
|
14259
14340
|
html += "You can load a collection of structures via a file. Here are <a href='https://github.com/ncbi/icn3d/blob/master/example/collection/' target='_blank'>some example files</a><br><br>";
|
|
14260
14341
|
html += "Collection file: " + me.htmlCls.inputFileStr + "id='" + me.pre + "collectionfile'><br/>";
|
|
14342
|
+
html += "<input type='radio' id='dl_collectionAppendStructureNone' name='appendStructure' value='none' checked/>";
|
|
14343
|
+
html += "<label for='dl_collectionAppendStructureNone'>Default</label>";
|
|
14344
|
+
html += "<input type='radio' id='dl_collectionAppendStructure' name='appendStructure' value='append' />";
|
|
14345
|
+
html += "<label for='dl_collectionAppendStructure'>Append</label><br/>";
|
|
14261
14346
|
html += me.htmlCls.buttonStr + "reload_collectionfile' style='margin-top: 6px;'>Load</button>";
|
|
14262
14347
|
html += "</div>";
|
|
14263
14348
|
html += "</div>";
|
|
@@ -14265,7 +14350,8 @@ class SetDialog {
|
|
|
14265
14350
|
html += me.htmlCls.divStr + "dl_collection_structures' style='display: none'>";
|
|
14266
14351
|
html += "<select id='" + me.pre + "collections_menu'multiple size='6' style='min-width:300px;'></select>";
|
|
14267
14352
|
html += '<br/>';
|
|
14268
|
-
html += me.htmlCls.buttonStr + "
|
|
14353
|
+
html += me.htmlCls.buttonStr + "collections_clear_commands' style='margin-top: 6px;'>Clear Commands</button>";
|
|
14354
|
+
html += me.htmlCls.buttonStr + "opendl_export_collections'>Export JSON</button>";
|
|
14269
14355
|
html += "</div>";
|
|
14270
14356
|
html += '<br/>';
|
|
14271
14357
|
html += "</div>";
|
|
@@ -14970,13 +15056,15 @@ class SetDialog {
|
|
|
14970
15056
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "apply_menupref'>Apply</button></span>";
|
|
14971
15057
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "reset_menupref' style='margin-left:30px'>Reset to Simple Menus</button></span>";
|
|
14972
15058
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "reset_menupref_all' style='margin-left:30px'>Reset to All Menus</button></span>";
|
|
14973
|
-
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "savepref' style='margin-left:30px'>Save Preferences</button></span
|
|
15059
|
+
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "savepref' style='margin-left:30px'>Save Preferences</button></span>";
|
|
15060
|
+
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "loadpref' style='margin-left:30px'>Load Preferences</button></span><br><br>";
|
|
14974
15061
|
|
|
14975
15062
|
html += "<div id='" + me.pre + "menulist'></div><br><br>";
|
|
14976
15063
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "apply_menupref2'>Apply</button></span>";
|
|
14977
15064
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "reset_menupref2' style='margin-left:30px'>Reset to Simple Menus</button></span>";
|
|
14978
15065
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "reset_menupref_all2' style='margin-left:30px'>Reset to All Menus</button></span>";
|
|
14979
15066
|
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "savepref2' style='margin-left:30px'>Save Preferences</button></span>";
|
|
15067
|
+
html += me.htmlCls.spanNowrapStr + "" + me.htmlCls.buttonStr + "loadpref2' style='margin-left:30px'>Load Preferences</button></span>";
|
|
14980
15068
|
html += "</div>";
|
|
14981
15069
|
|
|
14982
15070
|
html += me.htmlCls.divStr + "dl_addtrack' class='" + dialogClass + "'>";
|
|
@@ -15752,6 +15840,14 @@ class Events {
|
|
|
15752
15840
|
me.htmlCls.clickMenuCls.clickMenu5();
|
|
15753
15841
|
me.htmlCls.clickMenuCls.clickMenu6();
|
|
15754
15842
|
|
|
15843
|
+
me.myEventCls.onIds("#" + me.pre + "menumode", "change", async function(e) { me.icn3d;
|
|
15844
|
+
e.preventDefault();
|
|
15845
|
+
let mode = $("#" + me.pre + "menumode").val();
|
|
15846
|
+
|
|
15847
|
+
me.htmlCls.setHtmlCls.setCookie('menumode', mode);
|
|
15848
|
+
me.htmlCls.setMenuCls.resetMenu(mode);
|
|
15849
|
+
});
|
|
15850
|
+
|
|
15755
15851
|
// back and forward arrows
|
|
15756
15852
|
me.myEventCls.onIds(["#" + me.pre + "back", "#" + me.pre + "mn6_back"], "click", async function(e) { let ic = me.icn3d;
|
|
15757
15853
|
e.preventDefault();
|
|
@@ -16798,95 +16894,108 @@ class Events {
|
|
|
16798
16894
|
} else {
|
|
16799
16895
|
ic.resizeCanvasCls.closeDialogs();
|
|
16800
16896
|
}
|
|
16801
|
-
|
|
16802
|
-
ic.pdbCollection = [];
|
|
16803
|
-
ic.allData = {};
|
|
16804
|
-
ic.allData['all'] = {
|
|
16805
|
-
'atoms': {},
|
|
16806
|
-
'proteins': {},
|
|
16807
|
-
'nucleotides': {},
|
|
16808
|
-
'chemicals': {},
|
|
16809
|
-
'ions': {},
|
|
16810
|
-
'water': {},
|
|
16811
|
-
'structures': {}, // getSSExpandedAtoms
|
|
16812
|
-
'ssbondpnts': {},
|
|
16813
|
-
'residues': {}, // getSSExpandedAtoms
|
|
16814
|
-
'chains': {},
|
|
16815
|
-
'chainsSeq': {}, //Sequences and Annotation
|
|
16816
|
-
'defNames2Atoms': {},
|
|
16817
|
-
'defNames2Residues': {}
|
|
16818
|
-
};
|
|
16819
|
-
ic.allData['prev'] = {};
|
|
16820
|
-
ic.selectCollectionsCls.reset();
|
|
16821
|
-
|
|
16897
|
+
|
|
16822
16898
|
ic.dAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
|
|
16823
16899
|
ic.hAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
|
|
16824
16900
|
me.htmlCls.setHtmlCls.fileSupport();
|
|
16825
16901
|
|
|
16826
16902
|
let fileName = file.name;
|
|
16827
16903
|
let fileExtension = fileName.split('.').pop().toLowerCase();
|
|
16828
|
-
|
|
16904
|
+
let collection = {};
|
|
16905
|
+
|
|
16829
16906
|
$("#" + ic.pre + "collections_menu").empty();
|
|
16830
16907
|
$("#" + ic.pre + "collections_menu").off("change");
|
|
16908
|
+
|
|
16909
|
+
if (dl_collectionAppendStructureNone.checked || ic.allData === undefined) {
|
|
16910
|
+
ic.bInputfile = false;
|
|
16911
|
+
ic.pdbCollection = {};
|
|
16912
|
+
ic.allData = {};
|
|
16913
|
+
ic.allData['all'] = {
|
|
16914
|
+
'atoms': {},
|
|
16915
|
+
'proteins': {},
|
|
16916
|
+
'nucleotides': {},
|
|
16917
|
+
'chemicals': {},
|
|
16918
|
+
'ions': {},
|
|
16919
|
+
'water': {},
|
|
16920
|
+
'structures': {}, // getSSExpandedAtoms
|
|
16921
|
+
'ssbondpnts': {},
|
|
16922
|
+
'residues': {}, // getSSExpandedAtoms
|
|
16923
|
+
'chains': {},
|
|
16924
|
+
'chainsSeq': {}, //Sequences and Annotation
|
|
16925
|
+
'defNames2Atoms': {},
|
|
16926
|
+
'defNames2Residues': {}
|
|
16927
|
+
};
|
|
16928
|
+
ic.allData['prev'] = {};
|
|
16929
|
+
ic.selectCollectionsCls.reset();
|
|
16930
|
+
|
|
16931
|
+
} else {
|
|
16932
|
+
if (ic.collections) {
|
|
16933
|
+
collection = ic.collections;
|
|
16934
|
+
}
|
|
16935
|
+
}
|
|
16831
16936
|
|
|
16832
16937
|
function parseJsonCollection(data) {
|
|
16833
16938
|
let dataStr = JSON.parse(data);
|
|
16834
|
-
|
|
16939
|
+
let parsedCollection = {};
|
|
16940
|
+
|
|
16941
|
+
dataStr["structures"].map(({ id, title, description, commands }) => {
|
|
16835
16942
|
if (id && id.includes('.pdb')) {
|
|
16836
16943
|
id = id.split('.pdb')[0];
|
|
16837
16944
|
}
|
|
16838
|
-
|
|
16945
|
+
parsedCollection[id] = [id, title, description, commands, false];
|
|
16839
16946
|
});
|
|
16840
|
-
}
|
|
16841
16947
|
|
|
16948
|
+
return parsedCollection;
|
|
16949
|
+
}
|
|
16950
|
+
|
|
16842
16951
|
function parsePdbCollection(data, description = '', commands = []) {
|
|
16843
16952
|
let dataStr = data;
|
|
16844
16953
|
let lines = dataStr.split('\n');
|
|
16845
|
-
|
|
16846
16954
|
let sections = [];
|
|
16847
16955
|
let currentSection = [];
|
|
16848
|
-
|
|
16956
|
+
|
|
16849
16957
|
lines.forEach(line => {
|
|
16850
|
-
|
|
16958
|
+
if (line.startsWith('HEADER')) {
|
|
16851
16959
|
currentSection = [];
|
|
16852
16960
|
sections.push(currentSection);
|
|
16853
|
-
|
|
16854
|
-
|
|
16961
|
+
}
|
|
16962
|
+
currentSection.push(line);
|
|
16855
16963
|
});
|
|
16856
|
-
|
|
16857
|
-
|
|
16858
|
-
let
|
|
16859
|
-
|
|
16964
|
+
|
|
16965
|
+
|
|
16966
|
+
let parsedCollection = {};
|
|
16967
|
+
|
|
16860
16968
|
sections.forEach((section) => {
|
|
16861
|
-
let headerLine = section[0];
|
|
16862
|
-
headerLine = headerLine.replace(/[\n\r]/g, '').trim();
|
|
16969
|
+
let headerLine = section[0].replace(/[\n\r]/g, '').trim();
|
|
16863
16970
|
let header = headerLine.split(' ').filter(Boolean);
|
|
16864
|
-
let
|
|
16865
|
-
|
|
16866
|
-
|
|
16971
|
+
let id = header[header.length - 1];
|
|
16972
|
+
let title = section[1].startsWith('TITLE') ? section[1].split('TITLE').pop().trim() : id;
|
|
16973
|
+
|
|
16974
|
+
parsedCollection[id] = [id, title, description, commands, true];
|
|
16975
|
+
|
|
16976
|
+
const sanitizedSection = section.map(line => line.trim());
|
|
16977
|
+
ic.pdbCollection[id] = sanitizedSection;
|
|
16867
16978
|
});
|
|
16868
|
-
|
|
16869
|
-
if (sections.length > 0) {
|
|
16870
|
-
ic.pdbCollection.push(...sections);
|
|
16871
|
-
}
|
|
16872
16979
|
|
|
16873
|
-
return
|
|
16980
|
+
return parsedCollection;
|
|
16874
16981
|
}
|
|
16875
16982
|
|
|
16876
|
-
let collection = [];
|
|
16877
|
-
|
|
16878
16983
|
if (fileExtension === 'json' || fileExtension === 'pdb') {
|
|
16879
16984
|
let reader = new FileReader();
|
|
16880
16985
|
reader.onload = async function (e) {
|
|
16881
16986
|
if (fileExtension === 'json') {
|
|
16882
|
-
|
|
16987
|
+
let jsonCollection = parseJsonCollection(e.target.result);
|
|
16988
|
+
collection = { ...collection, ...jsonCollection };
|
|
16883
16989
|
} else if (fileExtension === 'pdb') {
|
|
16884
16990
|
ic.bInputfile = true;
|
|
16885
|
-
|
|
16991
|
+
let pdbCollection = parsePdbCollection(e.target.result);
|
|
16992
|
+
collection = { ...collection, ...pdbCollection };
|
|
16886
16993
|
}
|
|
16887
16994
|
|
|
16888
16995
|
let collectionHtml = await ic.selectCollectionsCls.setAtomMenu(collection);
|
|
16889
16996
|
|
|
16997
|
+
ic.collections = collection;
|
|
16998
|
+
|
|
16890
16999
|
$("#" + ic.pre + "collections_menu").html(collectionHtml);
|
|
16891
17000
|
await ic.selectCollectionsCls.clickStructure(collection);
|
|
16892
17001
|
$("#" + ic.pre + "collections_menu").trigger("change");
|
|
@@ -16904,7 +17013,7 @@ class Events {
|
|
|
16904
17013
|
let reader2 = new FileReader();
|
|
16905
17014
|
reader2.onload = async function (e) {
|
|
16906
17015
|
if (fileExtension === 'zip') {
|
|
16907
|
-
let url = './script/jszip.js';
|
|
17016
|
+
let url = './script/jszip.min.js';
|
|
16908
17017
|
await me.getAjaxPromise(url, 'script');
|
|
16909
17018
|
|
|
16910
17019
|
let jszip = new JSZip();
|
|
@@ -16938,7 +17047,8 @@ class Events {
|
|
|
16938
17047
|
let jsonCollection = [];
|
|
16939
17048
|
for (const file of jsonFiles) {
|
|
16940
17049
|
let fileData = await file.async('text');
|
|
16941
|
-
parseJsonCollection(fileData)
|
|
17050
|
+
let parsedJson = Object.values(parseJsonCollection(fileData));
|
|
17051
|
+
parsedJson.forEach(element => {
|
|
16942
17052
|
jsonCollection.push(element);
|
|
16943
17053
|
});
|
|
16944
17054
|
}
|
|
@@ -16948,8 +17058,9 @@ class Events {
|
|
|
16948
17058
|
let matchingPdbFile = pdbFiles.find(file => file.name.toLowerCase().includes(id.toLowerCase()));
|
|
16949
17059
|
if (matchingPdbFile) {
|
|
16950
17060
|
let pdbFileData = await matchingPdbFile.async('text');
|
|
16951
|
-
parsePdbCollection(pdbFileData, description, commands)
|
|
16952
|
-
|
|
17061
|
+
let parsedPdb = Object.values(parsePdbCollection(pdbFileData, description, commands));
|
|
17062
|
+
parsedPdb.forEach(element => {
|
|
17063
|
+
collection[id] = element;
|
|
16953
17064
|
});
|
|
16954
17065
|
}
|
|
16955
17066
|
}
|
|
@@ -16958,27 +17069,30 @@ class Events {
|
|
|
16958
17069
|
// Do something if only JSON files are present
|
|
16959
17070
|
jsonFiles.forEach(async file => {
|
|
16960
17071
|
let fileData = await file.async('text');
|
|
16961
|
-
parseJsonCollection(fileData)
|
|
16962
|
-
|
|
17072
|
+
const parsedJson = Object.values(parseJsonCollection(fileData));
|
|
17073
|
+
parsedJson.forEach(element => {
|
|
17074
|
+
collection[element[0]] = element;
|
|
16963
17075
|
});
|
|
16964
17076
|
});
|
|
16965
17077
|
} else if (hasPdb) {
|
|
16966
17078
|
// Do something if only PDB files are present
|
|
16967
17079
|
pdbFiles.forEach(async file => {
|
|
16968
17080
|
let fileData = await file.async('text');
|
|
16969
|
-
|
|
16970
|
-
|
|
17081
|
+
const parsedPdb = Object.values(parsedPdbCollection(fileData));
|
|
17082
|
+
parsedPdb.forEach(element => {
|
|
17083
|
+
collection[element[0]] = element;
|
|
16971
17084
|
});
|
|
16972
17085
|
});
|
|
16973
17086
|
} else if (hasGz) {
|
|
16974
|
-
let url = './script/pako.js';
|
|
17087
|
+
let url = './script/pako.min.js';
|
|
16975
17088
|
await me.getAjaxPromise(url, 'script');
|
|
16976
17089
|
try {
|
|
16977
17090
|
for (const file of gzFiles) {
|
|
16978
17091
|
let compressed = await file.async('uint8array');
|
|
16979
17092
|
let decompressed = pako.inflate(compressed, { to: 'string' });
|
|
16980
|
-
parsePdbCollection(decompressed)
|
|
16981
|
-
|
|
17093
|
+
const parsedPdb = Object.values(parsePdbCollection(decompressed));
|
|
17094
|
+
parsedPdb.forEach(element => {
|
|
17095
|
+
collection[element[0]] = element;
|
|
16982
17096
|
});
|
|
16983
17097
|
}
|
|
16984
17098
|
} catch (error) {
|
|
@@ -16989,7 +17103,7 @@ class Events {
|
|
|
16989
17103
|
console.error('Error loading ZIP file', error);
|
|
16990
17104
|
}
|
|
16991
17105
|
} else if (fileExtension === 'gz') {
|
|
16992
|
-
let url = './script/pako.js';
|
|
17106
|
+
let url = './script/pako.min.js';
|
|
16993
17107
|
await me.getAjaxPromise(url, 'script');
|
|
16994
17108
|
|
|
16995
17109
|
try {
|
|
@@ -17006,6 +17120,8 @@ class Events {
|
|
|
17006
17120
|
$("#" + ic.pre + "collections_menu").html(collectionHtml);
|
|
17007
17121
|
await ic.selectCollectionsCls.clickStructure(collection);
|
|
17008
17122
|
|
|
17123
|
+
ic.collections = collection;
|
|
17124
|
+
|
|
17009
17125
|
$("#" + ic.pre + "collections_menu").trigger("change");
|
|
17010
17126
|
|
|
17011
17127
|
me.htmlCls.clickMenuCls.setLogCmd(
|
|
@@ -17024,7 +17140,7 @@ class Events {
|
|
|
17024
17140
|
throw new Error('Invalid file type');
|
|
17025
17141
|
}
|
|
17026
17142
|
|
|
17027
|
-
if (Object.keys(
|
|
17143
|
+
if (ic.allData && Object.keys(ic.allData).length > 0) {
|
|
17028
17144
|
$("#" + me.pre + "dl_collection_file").hide();
|
|
17029
17145
|
$("#" + me.pre + "dl_collection_structures").show();
|
|
17030
17146
|
$("#" + me.pre + "dl_collection_file_expand").show();
|
|
@@ -17045,6 +17161,17 @@ class Events {
|
|
|
17045
17161
|
}
|
|
17046
17162
|
});
|
|
17047
17163
|
|
|
17164
|
+
me.myEventCls.onIds("#" + me.pre + "collections_clear_commands", "click", function (e) {
|
|
17165
|
+
var selectedValues = $("#" + ic.pre + "collections_menu").val();
|
|
17166
|
+
selectedValues.forEach(function (selectedValue) {
|
|
17167
|
+
if (ic.allData[selectedValue]) {
|
|
17168
|
+
ic.allData[selectedValue]['commands'] = [];
|
|
17169
|
+
} else {
|
|
17170
|
+
console.warn("No data found for selectedValue:", selectedValue);
|
|
17171
|
+
}
|
|
17172
|
+
});
|
|
17173
|
+
});
|
|
17174
|
+
|
|
17048
17175
|
me.myEventCls.onIds("#" + me.pre + "opendl_export_collections", "click", function (e) {
|
|
17049
17176
|
me.htmlCls.dialogCls.openDlg("dl_export_collections", "Export Collections");
|
|
17050
17177
|
});
|
|
@@ -19531,9 +19658,9 @@ class SetHtml {
|
|
|
19531
19658
|
|
|
19532
19659
|
let pdbstr = '';
|
|
19533
19660
|
|
|
19534
|
-
let bMergeIntoOne = true;
|
|
19535
|
-
pdbstr += ic.saveFileCls.getAtomPDB(atomHash, undefined, undefined, undefined, undefined, undefined, bMergeIntoOne);
|
|
19536
|
-
pdbstr += ic.saveFileCls.getAtomPDB(ionHash, true, undefined, true);
|
|
19661
|
+
let bMergeIntoOne = true, bOneLetterChain = true;
|
|
19662
|
+
pdbstr +=(me.cfg.cid) ? ic.saveFileCls.getAtomPDB(atomHash, true, undefined, undefined, undefined, undefined, bMergeIntoOne, bOneLetterChain) : ic.saveFileCls.getAtomPDB(atomHash, undefined, undefined, undefined, undefined, undefined, bMergeIntoOne, bOneLetterChain);
|
|
19663
|
+
pdbstr += ic.saveFileCls.getAtomPDB(ionHash, true, undefined, true, undefined, undefined, bMergeIntoOne, bOneLetterChain);
|
|
19537
19664
|
|
|
19538
19665
|
let url = me.htmlCls.baseUrl + "delphi/delphi.cgi";
|
|
19539
19666
|
|
|
@@ -28737,698 +28864,244 @@ class Stick {
|
|
|
28737
28864
|
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
28738
28865
|
*/
|
|
28739
28866
|
|
|
28740
|
-
class
|
|
28867
|
+
class FirstAtomObj {
|
|
28741
28868
|
constructor(icn3d) {
|
|
28742
28869
|
this.icn3d = icn3d;
|
|
28743
28870
|
}
|
|
28744
28871
|
|
|
28745
|
-
//
|
|
28746
|
-
|
|
28747
|
-
|
|
28748
|
-
|
|
28749
|
-
|
|
28750
|
-
//"bHighlight" is an option to draw the highlight for these atoms. The highlight could be outlines
|
|
28751
|
-
//with bHighlight=1 and 3D objects with bHighlight=2.
|
|
28752
|
-
createStrand(atoms, num, div, fill, coilWidth, helixSheetWidth, doNotSmoothen, thickness, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
|
|
28753
|
-
if(me.bNode) return;
|
|
28872
|
+
//Return the first atom in the atom hash, which has the atom serial number as the key.
|
|
28873
|
+
getFirstAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
28874
|
+
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
28875
|
+
return undefined;
|
|
28876
|
+
}
|
|
28754
28877
|
|
|
28755
|
-
let
|
|
28878
|
+
let atomKeys = Object.keys(atomsHash);
|
|
28879
|
+
let firstIndex = atomKeys[0];
|
|
28756
28880
|
|
|
28757
|
-
|
|
28758
|
-
|
|
28759
|
-
let atomsAdjust = {};
|
|
28881
|
+
return ic.atoms[firstIndex];
|
|
28882
|
+
}
|
|
28760
28883
|
|
|
28761
|
-
|
|
28762
|
-
|
|
28763
|
-
|
|
28884
|
+
// n is the position of the selected atom
|
|
28885
|
+
getMiddleAtomObj(atomsHash, n) { let ic = this.icn3d; ic.icn3dui;
|
|
28886
|
+
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
28887
|
+
return undefined;
|
|
28764
28888
|
}
|
|
28765
|
-
|
|
28766
|
-
|
|
28889
|
+
|
|
28890
|
+
let atomKeys = Object.keys(atomsHash);
|
|
28891
|
+
let middleIndex = (n && n < atomKeys.length) ? atomKeys[n] : atomKeys[parseInt(atomKeys.length / 2)];
|
|
28892
|
+
|
|
28893
|
+
return ic.atoms[middleIndex];
|
|
28894
|
+
}
|
|
28895
|
+
|
|
28896
|
+
getFirstCalphaAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
28897
|
+
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
28898
|
+
return undefined;
|
|
28767
28899
|
}
|
|
28768
28900
|
|
|
28769
|
-
|
|
28770
|
-
|
|
28771
|
-
|
|
28772
|
-
|
|
28773
|
-
|
|
28774
|
-
|
|
28775
|
-
helixSheetWidth = null;
|
|
28776
|
-
thickness = undefined;
|
|
28901
|
+
let firstIndex;
|
|
28902
|
+
|
|
28903
|
+
for(let i in atomsHash) {
|
|
28904
|
+
if(ic.atoms[i].name == 'CA') {
|
|
28905
|
+
firstIndex = i;
|
|
28906
|
+
break;
|
|
28777
28907
|
}
|
|
28778
|
-
|
|
28779
|
-
|
|
28780
|
-
|
|
28781
|
-
|
|
28782
|
-
|
|
28783
|
-
|
|
28784
|
-
|
|
28908
|
+
}
|
|
28909
|
+
|
|
28910
|
+
if(!firstIndex) {
|
|
28911
|
+
for(let i in atomsHash) {
|
|
28912
|
+
if(ic.atoms[i].name == "O3'" || ic.atoms[i].name == "O3*") {
|
|
28913
|
+
firstIndex = i;
|
|
28914
|
+
break;
|
|
28915
|
+
}
|
|
28785
28916
|
}
|
|
28786
28917
|
}
|
|
28787
28918
|
|
|
28788
|
-
|
|
28789
|
-
|
|
28790
|
-
coilWidth = coilWidth || ic.coilWidth;
|
|
28791
|
-
doNotSmoothen = doNotSmoothen || false;
|
|
28792
|
-
helixSheetWidth = helixSheetWidth || ic.helixSheetWidth;
|
|
28793
|
-
let pnts = {}; for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
28794
|
-
let pntsCA = [];
|
|
28795
|
-
let prevCOArray = [];
|
|
28796
|
-
let bShowArray = [];
|
|
28797
|
-
let calphaIdArray = []; // used to store one of the final positions drawn in 3D
|
|
28798
|
-
let colors = [];
|
|
28799
|
-
let currentChain, currentResi, currentCA = null, currentO = null, currentColor = null, prevCoorCA = null, prevCoorO = null, prevColor = null;
|
|
28800
|
-
let prevCO = null, ss = null, ssend = false, atomid = null, prevAtomid = null, prevAtomSelected = null, prevResi = null, calphaid = null, prevCalphaid = null;
|
|
28801
|
-
let strandWidth, bSheetSegment = false, bHelixSegment = false;
|
|
28919
|
+
return (firstIndex !== undefined) ? ic.atoms[firstIndex] : this.getFirstAtomObj(atomsHash);
|
|
28920
|
+
}
|
|
28802
28921
|
|
|
28803
|
-
|
|
28804
|
-
|
|
28805
|
-
|
|
28806
|
-
let atoms = me.hashUtilsCls.hash2Atoms(ic.chains[chainid], ic.atoms);
|
|
28807
|
-
let bCalphaOnly = me.utilsCls.isCalphaPhosOnly(atoms); //, 'CA');
|
|
28808
|
-
bCalphaOnlyHash[chainid] = bCalphaOnly;
|
|
28922
|
+
getFirstAtomObjByName(atomsHash, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
28923
|
+
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
28924
|
+
return ic.atoms[0];
|
|
28809
28925
|
}
|
|
28810
28926
|
|
|
28811
|
-
|
|
28812
|
-
let residueHash = {};
|
|
28813
|
-
for(let i in atomsAdjust) {
|
|
28814
|
-
let atom = ic.atoms[i];
|
|
28927
|
+
let firstIndex;
|
|
28815
28928
|
|
|
28816
|
-
|
|
28817
|
-
|
|
28929
|
+
for(let i in atomsHash) {
|
|
28930
|
+
if(ic.atoms[i].name == atomName) {
|
|
28931
|
+
firstIndex = i;
|
|
28932
|
+
break;
|
|
28933
|
+
}
|
|
28818
28934
|
}
|
|
28819
|
-
Object.keys(residueHash).length;
|
|
28820
|
-
|
|
28821
|
-
let bFullAtom = (Object.keys(ic.hAtoms).length == Object.keys(ic.atoms).length) ? true : false;
|
|
28822
28935
|
|
|
28823
|
-
|
|
28936
|
+
return (firstIndex !== undefined) ? ic.atoms[firstIndex] : undefined;
|
|
28937
|
+
}
|
|
28824
28938
|
|
|
28825
|
-
|
|
28939
|
+
//Return the last atom in the atom hash, which has the atom serial number as the key.
|
|
28940
|
+
getLastAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
28941
|
+
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
28942
|
+
return ic.atoms[0];
|
|
28943
|
+
}
|
|
28826
28944
|
|
|
28827
|
-
|
|
28828
|
-
let
|
|
28829
|
-
let lastAtomSerial = atomArray[atomArray.length - 1];
|
|
28830
|
-
let lastAtom = ic.atoms[lastAtomSerial];
|
|
28831
|
-
let lastResid = lastAtom.structure + '_' + lastAtom.chain + '_' + lastAtom.resi;
|
|
28945
|
+
let atomKeys = Object.keys(atomsHash);
|
|
28946
|
+
let lastIndex = atomKeys[atomKeys.length - 1];
|
|
28832
28947
|
|
|
28833
|
-
|
|
28834
|
-
|
|
28835
|
-
let chainid = atom.structure + '_' + atom.chain;
|
|
28836
|
-
let resid = atom.structure + '_' + atom.chain + '_' + atom.resi;
|
|
28837
|
-
if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
|
|
28838
|
-
// "CA" has to appear before "O"
|
|
28948
|
+
return ic.atoms[lastIndex];
|
|
28949
|
+
}
|
|
28839
28950
|
|
|
28840
|
-
|
|
28841
|
-
|
|
28951
|
+
//Return the residue hash from the atom hash. The residue hash has the resid as the key and 1 as the value.
|
|
28952
|
+
getResiduesFromAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
28953
|
+
let residuesHash = {};
|
|
28954
|
+
for(let i in atomsHash) {
|
|
28955
|
+
let residueid = ic.atoms[i].structure + '_' + ic.atoms[i].chain + '_' + ic.atoms[i].resi;
|
|
28956
|
+
residuesHash[residueid] = 1;
|
|
28957
|
+
}
|
|
28842
28958
|
|
|
28843
|
-
|
|
28844
|
-
|
|
28845
|
-
calphaid = atom.serial;
|
|
28959
|
+
return residuesHash;
|
|
28960
|
+
}
|
|
28846
28961
|
|
|
28847
|
-
|
|
28962
|
+
getResiduesFromCalphaAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
28963
|
+
let residuesHash = {};
|
|
28964
|
+
for(let i in atomsHash) {
|
|
28965
|
+
if((ic.atoms[i].name == 'CA' && ic.proteins.hasOwnProperty(i)) || !ic.proteins.hasOwnProperty(i)) {
|
|
28966
|
+
let residueid = ic.atoms[i].structure + '_' + ic.atoms[i].chain + '_' + ic.atoms[i].resi;
|
|
28967
|
+
//residuesHash[residueid] = 1;
|
|
28968
|
+
residuesHash[residueid] = ic.atoms[i].resn;
|
|
28848
28969
|
}
|
|
28970
|
+
}
|
|
28849
28971
|
|
|
28850
|
-
|
|
28851
|
-
|
|
28852
|
-
currentCA = atom.coord;
|
|
28853
|
-
currentColor = atom.color;
|
|
28854
|
-
calphaid = atom.serial;
|
|
28855
|
-
}
|
|
28972
|
+
return residuesHash;
|
|
28973
|
+
}
|
|
28856
28974
|
|
|
28857
|
-
|
|
28858
|
-
|
|
28859
|
-
|
|
28860
|
-
|
|
28861
|
-
|
|
28862
|
-
|
|
28863
|
-
// if (currentChain !== atom.chain) {
|
|
28864
|
-
// //if (currentChain !== atom.chain) {
|
|
28865
|
-
// bSameChain = false;
|
|
28866
|
-
// }
|
|
28975
|
+
//Return the chain hash from the atom hash. The chain hash has the chainid as the key and 1 as the value.
|
|
28976
|
+
getChainsFromAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
28977
|
+
let chainsHash = {};
|
|
28978
|
+
for(let i in atomsHash) {
|
|
28979
|
+
let atom = ic.atoms[i];
|
|
28980
|
+
let chainid = atom.structure + "_" + atom.chain;
|
|
28867
28981
|
|
|
28868
|
-
|
|
28869
|
-
|
|
28870
|
-
|
|
28871
|
-
|
|
28872
|
-
|
|
28982
|
+
chainsHash[chainid] = 1;
|
|
28983
|
+
}
|
|
28984
|
+
|
|
28985
|
+
return chainsHash;
|
|
28986
|
+
}
|
|
28987
|
+
|
|
28988
|
+
getAtomFromResi(resid, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
28989
|
+
if(ic.residues.hasOwnProperty(resid)) {
|
|
28990
|
+
for(let i in ic.residues[resid]) {
|
|
28991
|
+
if(ic.atoms[i].name === atomName && !ic.atoms[i].het) {
|
|
28992
|
+
return ic.atoms[i];
|
|
28873
28993
|
}
|
|
28994
|
+
}
|
|
28995
|
+
}
|
|
28874
28996
|
|
|
28875
|
-
|
|
28876
|
-
|
|
28877
|
-
if(bHighlight === 1 || bHighlight === 2) {
|
|
28878
|
-
colors.push(ic.hColor);
|
|
28879
|
-
}
|
|
28880
|
-
else {
|
|
28881
|
-
colors.push(prevColor);
|
|
28882
|
-
}
|
|
28997
|
+
return undefined;
|
|
28998
|
+
}
|
|
28883
28999
|
|
|
28884
|
-
|
|
28885
|
-
|
|
28886
|
-
|
|
28887
|
-
|
|
28888
|
-
strandWidth = coilWidth;
|
|
28889
|
-
}
|
|
28890
|
-
else {
|
|
28891
|
-
strandWidth = (ss === 'coil') ? coilWidth : helixSheetWidth;
|
|
28892
|
-
}
|
|
29000
|
+
getAtomCoordFromResi(resid, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
29001
|
+
let atom = this.getAtomFromResi(resid, atomName);
|
|
29002
|
+
if(atom !== undefined) {
|
|
29003
|
+
let coord = (atom.coord2 !== undefined) ? atom.coord2 : atom.coord;
|
|
28893
29004
|
|
|
28894
|
-
|
|
28895
|
-
|
|
28896
|
-
O = prevCoorO.clone();
|
|
28897
|
-
if(prevCoorCA !== null && prevCoorCA !== undefined) {
|
|
28898
|
-
O.sub(prevCoorCA);
|
|
28899
|
-
}
|
|
28900
|
-
else {
|
|
28901
|
-
prevCoorCA = prevCoorO.clone();
|
|
28902
|
-
if(caArray.length > resSpan + 1) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
28903
|
-
O = prevCoorCA.clone();
|
|
28904
|
-
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan - 1]].coord.clone();
|
|
28905
|
-
//O.sub(oldCA);
|
|
28906
|
-
oldCA.sub(O);
|
|
28907
|
-
}
|
|
28908
|
-
else {
|
|
28909
|
-
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
28910
|
-
}
|
|
28911
|
-
}
|
|
28912
|
-
}
|
|
28913
|
-
else if(bCalphaOnlyHash[chainid] && atom.name === 'CA') {
|
|
28914
|
-
if(caArray.length > resSpan + 1) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
28915
|
-
O = prevCoorCA.clone();
|
|
28916
|
-
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan - 1]].coord.clone();
|
|
28917
|
-
//O.sub(oldCA);
|
|
28918
|
-
oldCA.sub(O);
|
|
28919
|
-
}
|
|
28920
|
-
else {
|
|
28921
|
-
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
28922
|
-
}
|
|
28923
|
-
}
|
|
29005
|
+
return coord;
|
|
29006
|
+
}
|
|
28924
29007
|
|
|
28925
|
-
|
|
28926
|
-
|
|
28927
|
-
|
|
28928
|
-
prevCO = O;
|
|
29008
|
+
return undefined;
|
|
29009
|
+
}
|
|
29010
|
+
}
|
|
28929
29011
|
|
|
28930
|
-
|
|
28931
|
-
|
|
28932
|
-
|
|
28933
|
-
if (!doNotSmoothen && ss === 'sheet') v.smoothen = true;
|
|
28934
|
-
pnts[j].push(v);
|
|
28935
|
-
}
|
|
29012
|
+
/**
|
|
29013
|
+
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
29014
|
+
*/
|
|
28936
29015
|
|
|
28937
|
-
|
|
28938
|
-
|
|
29016
|
+
class Strip {
|
|
29017
|
+
constructor(icn3d) {
|
|
29018
|
+
this.icn3d = icn3d;
|
|
29019
|
+
}
|
|
28939
29020
|
|
|
28940
|
-
|
|
28941
|
-
|
|
28942
|
-
|
|
28943
|
-
|
|
28944
|
-
else {
|
|
28945
|
-
bShowArray.push(0);
|
|
28946
|
-
calphaIdArray.push(0);
|
|
28947
|
-
}
|
|
28948
|
-
}
|
|
29021
|
+
// modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
29022
|
+
createStrip(p0, p1, colors, div, thickness, bHighlight, bNoSmoothen, bShowArray,
|
|
29023
|
+
calphaIdArray, positions, prevone, nexttwo, pntsCA, prevCOArray) { let ic = this.icn3d, me = ic.icn3dui;
|
|
29024
|
+
if(me.bNode) return;
|
|
28949
29025
|
|
|
28950
|
-
|
|
29026
|
+
if (p0.length < 2) return;
|
|
29027
|
+
div = div || ic.axisDIV;
|
|
28951
29028
|
|
|
28952
|
-
|
|
28953
|
-
|
|
28954
|
-
|
|
28955
|
-
|
|
28956
|
-
// check whether the atoms are continuous
|
|
28957
|
-
// atomsAdjusted has all atoms in the secondary structure
|
|
28958
|
-
// atoms has all selected atoms
|
|
28959
|
-
// let bBrokenSs = false;
|
|
28960
|
-
// if(prevAtomSelected && prevAtomid == prevAtomSelected.serial && !atoms.hasOwnProperty(atom.serial)) {
|
|
28961
|
-
// bBrokenSs = true;
|
|
28962
|
-
// }
|
|
29029
|
+
// if(pntsCA && ic.bDoublecolor && !ic.bCalphaOnly) {
|
|
29030
|
+
if(pntsCA && ic.bDoublecolor) {
|
|
29031
|
+
let bExtendLastRes = false; //true;
|
|
28963
29032
|
|
|
29033
|
+
let pnts_clrs = me.subdivideCls.subdivide(pntsCA, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29034
|
+
pntsCA = pnts_clrs[0];
|
|
28964
29035
|
|
|
28965
|
-
|
|
28966
|
-
// 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);
|
|
29036
|
+
this.setCalphaDrawnCoord(pntsCA, div, calphaIdArray);
|
|
28967
29037
|
|
|
28968
|
-
|
|
28969
|
-
|
|
28970
|
-
|
|
28971
|
-
// else if(bBrokenSs && atom.ss === 'helix') {
|
|
28972
|
-
// bHelixSegment = true;
|
|
28973
|
-
// }
|
|
29038
|
+
for(let i = 0, il = prevCOArray.length; i < il; ++i) {
|
|
29039
|
+
prevCOArray[i].normalize();
|
|
29040
|
+
}
|
|
28974
29041
|
|
|
28975
|
-
|
|
28976
|
-
|
|
29042
|
+
let pnts_clrs2 = me.subdivideCls.subdivide(prevCOArray, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29043
|
+
prevCOArray = pnts_clrs2[0];
|
|
28977
29044
|
|
|
28978
|
-
|
|
28979
|
-
|
|
28980
|
-
|
|
28981
|
-
let prevone = [], nexttwo = [];
|
|
29045
|
+
colors = pnts_clrs[2];
|
|
29046
|
+
}
|
|
29047
|
+
else {
|
|
28982
29048
|
|
|
28983
|
-
|
|
28984
|
-
|
|
28985
|
-
|
|
28986
|
-
|
|
28987
|
-
|
|
28988
|
-
|
|
28989
|
-
|
|
28990
|
-
|
|
29049
|
+
if(!bNoSmoothen) {
|
|
29050
|
+
//var bExtendLastRes = true;
|
|
29051
|
+
let bExtendLastRes = false;
|
|
29052
|
+
let pnts_clrs0 = me.subdivideCls.subdivide(p0, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29053
|
+
let pnts_clrs1 = me.subdivideCls.subdivide(p1, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29054
|
+
p0 = pnts_clrs0[0];
|
|
29055
|
+
p1 = pnts_clrs1[0];
|
|
29056
|
+
colors = pnts_clrs0[2];
|
|
29057
|
+
}
|
|
29058
|
+
if (p0.length < 2) return;
|
|
28991
29059
|
|
|
28992
|
-
|
|
28993
|
-
|
|
28994
|
-
let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
|
|
28995
|
-
if(nextoneCoord !== undefined) {
|
|
28996
|
-
nexttwo.push(nextoneCoord);
|
|
28997
|
-
}
|
|
29060
|
+
this.setCalphaDrawnCoord(p0, div, calphaIdArray);
|
|
29061
|
+
}
|
|
28998
29062
|
|
|
28999
|
-
|
|
29000
|
-
|
|
29001
|
-
if(nexttwoCoord !== undefined) {
|
|
29002
|
-
nexttwo.push(nexttwoCoord);
|
|
29003
|
-
}
|
|
29004
|
-
}
|
|
29063
|
+
if(bHighlight === 1) {
|
|
29064
|
+
//mesh = new THREE.Mesh(geo, ic.matShader);
|
|
29005
29065
|
|
|
29006
|
-
|
|
29007
|
-
|
|
29008
|
-
|
|
29009
|
-
|
|
29010
|
-
colors.push(ic.hColor);
|
|
29011
|
-
}
|
|
29012
|
-
else {
|
|
29013
|
-
//colors.push(atom.color);
|
|
29014
|
-
colors.push(prevColor);
|
|
29015
|
-
}
|
|
29066
|
+
let radius = ic.coilWidth / 2;
|
|
29067
|
+
//var radiusSegments = 8;
|
|
29068
|
+
let radiusSegments = 4; // save memory
|
|
29069
|
+
let closed = false;
|
|
29016
29070
|
|
|
29017
|
-
|
|
29018
|
-
|
|
29019
|
-
|
|
29020
|
-
else if(ss === 'coil' && atom.ssbegin) {
|
|
29021
|
-
strandWidth = coilWidth;
|
|
29022
|
-
}
|
|
29023
|
-
else if(ssend && atom.ssbegin) { // current residue is the start of ss and the previous residue is the end of ss, then use coil
|
|
29024
|
-
strandWidth = coilWidth;
|
|
29025
|
-
}
|
|
29026
|
-
else { // use the ss from the previous residue
|
|
29027
|
-
strandWidth = (atom.ss === 'coil') ? coilWidth : helixSheetWidth;
|
|
29028
|
-
}
|
|
29071
|
+
if(positions !== undefined) {
|
|
29072
|
+
let currPos, prevPos;
|
|
29073
|
+
let currP0 = [], currP1 = [];
|
|
29029
29074
|
|
|
29030
|
-
|
|
29031
|
-
|
|
29032
|
-
O = currentO.clone();
|
|
29033
|
-
O.sub(currentCA);
|
|
29034
|
-
}
|
|
29035
|
-
else if(bCalphaOnlyHash[chainid] && atom.name === 'CA') {
|
|
29036
|
-
if(caArray.length > resSpan) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
29037
|
-
O = currentCA.clone();
|
|
29038
|
-
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan]].coord.clone();
|
|
29039
|
-
//O.sub(oldCA);
|
|
29040
|
-
oldCA.sub(O);
|
|
29041
|
-
}
|
|
29042
|
-
else {
|
|
29043
|
-
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
29044
|
-
}
|
|
29045
|
-
}
|
|
29075
|
+
for(let i = 0, il = p0.length; i < il; ++i) {
|
|
29076
|
+
currPos = positions[i];
|
|
29046
29077
|
|
|
29047
|
-
|
|
29048
|
-
|
|
29049
|
-
|
|
29050
|
-
|
|
29078
|
+
if((currPos !== prevPos && parseInt(currPos) !== parseInt(prevPos) + 1 && prevPos !== undefined) || (i === il -1) ) {
|
|
29079
|
+
// first tube
|
|
29080
|
+
let geometry0 = new THREE.TubeGeometry(
|
|
29081
|
+
new THREE.CatmullRomCurve3(currP0), // path
|
|
29082
|
+
currP0.length, // segments
|
|
29083
|
+
radius,
|
|
29084
|
+
radiusSegments,
|
|
29085
|
+
closed
|
|
29086
|
+
);
|
|
29051
29087
|
|
|
29052
|
-
|
|
29053
|
-
|
|
29054
|
-
|
|
29055
|
-
|
|
29056
|
-
pnts[j].push(v);
|
|
29057
|
-
}
|
|
29088
|
+
let mesh = new THREE.Mesh(geometry0, ic.matShader);
|
|
29089
|
+
mesh.renderOrder = ic.renderOrderPicking;
|
|
29090
|
+
//ic.mdlPicking.add(mesh);
|
|
29091
|
+
ic.mdl.add(mesh);
|
|
29058
29092
|
|
|
29059
|
-
|
|
29093
|
+
ic.prevHighlightObjects.push(mesh);
|
|
29060
29094
|
|
|
29061
|
-
|
|
29062
|
-
prevCOArray.push(prevCO);
|
|
29095
|
+
geometry0 = null;
|
|
29063
29096
|
|
|
29064
|
-
//
|
|
29065
|
-
|
|
29066
|
-
|
|
29067
|
-
|
|
29068
|
-
|
|
29069
|
-
|
|
29070
|
-
|
|
29071
|
-
|
|
29072
|
-
calphaIdArray.push(0);
|
|
29073
|
-
}
|
|
29074
|
-
}
|
|
29075
|
-
|
|
29076
|
-
// draw the current segment
|
|
29077
|
-
for (let j = 0; !fill && j < num; ++j) {
|
|
29078
|
-
if(bSheetSegment) {
|
|
29079
|
-
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
29080
|
-
}
|
|
29081
|
-
else if(bHelixSegment) {
|
|
29082
|
-
if(bFullAtom) {
|
|
29083
|
-
ic.curveCls.createCurveSub(pnts[j], 1, colors, div, bHighlight, bRibbon, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo);
|
|
29084
|
-
}
|
|
29085
|
-
else {
|
|
29086
|
-
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
29087
|
-
}
|
|
29088
|
-
}
|
|
29089
|
-
}
|
|
29090
|
-
if (fill) {
|
|
29091
|
-
if(bSheetSegment) {
|
|
29092
|
-
let start = 0, end = num - 1;
|
|
29093
|
-
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
29094
|
-
}
|
|
29095
|
-
else if(bHelixSegment) {
|
|
29096
|
-
if(bFullAtom) {
|
|
29097
|
-
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
29098
|
-
}
|
|
29099
|
-
else {
|
|
29100
|
-
let start = 0, end = num - 1;
|
|
29101
|
-
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
29102
|
-
}
|
|
29103
|
-
}
|
|
29104
|
-
else {
|
|
29105
|
-
if(bHighlight === 2) { // draw coils only when highlighted. if not highlighted, coils will be drawn as tubes separately
|
|
29106
|
-
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
29107
|
-
}
|
|
29108
|
-
}
|
|
29109
|
-
}
|
|
29110
|
-
for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
29111
|
-
|
|
29112
|
-
colors = [];
|
|
29113
|
-
pntsCA = [];
|
|
29114
|
-
prevCOArray = [];
|
|
29115
|
-
bShowArray = [];
|
|
29116
|
-
calphaIdArray = [];
|
|
29117
|
-
bSheetSegment = false;
|
|
29118
|
-
bHelixSegment = false;
|
|
29119
|
-
} // end if (atom.ssbegin || atom.ssend)
|
|
29120
|
-
|
|
29121
|
-
// end of a chain, or end of selection
|
|
29122
|
-
if ((currentChain !== atom.chain
|
|
29123
|
-
|| ic.ParserUtilsCls.getResiNCBI(atom.structure + '_' + currentChain, currentResi) + 1 !== ic.ParserUtilsCls.getResiNCBI(chainid, atom.resi)
|
|
29124
|
-
// || (drawnResidueCount === totalResidueCount - 1)
|
|
29125
|
-
// || bBrokenSs
|
|
29126
|
-
|| (resid == lastResid && atom.ss != 'coil')
|
|
29127
|
-
) && pnts[0].length > 0) {
|
|
29128
|
-
//if ((currentChain !== atom.chain) && pnts[0].length > 0) {
|
|
29129
|
-
|
|
29130
|
-
let atomName = 'CA';
|
|
29131
|
-
|
|
29132
|
-
let prevone = [], nexttwo = [];
|
|
29133
|
-
if(isNaN(ic.atoms[prevAtomid].resi)) {
|
|
29134
|
-
prevone = [];
|
|
29135
|
-
}
|
|
29136
|
-
else {
|
|
29137
|
-
let prevoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) - 1).toString();
|
|
29138
|
-
ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
|
|
29139
|
-
}
|
|
29140
|
-
|
|
29141
|
-
for (let j = 0; !fill && j < num; ++j) {
|
|
29142
|
-
if(bSheetSegment) {
|
|
29143
|
-
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
29144
|
-
}
|
|
29145
|
-
else if(bHelixSegment) {
|
|
29146
|
-
if(bFullAtom) {
|
|
29147
|
-
ic.curveCls.createCurveSub(pnts[j], 1, colors, div, bHighlight, bRibbon, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo);
|
|
29148
|
-
}
|
|
29149
|
-
else {
|
|
29150
|
-
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
29151
|
-
}
|
|
29152
|
-
}
|
|
29153
|
-
}
|
|
29154
|
-
if (fill) {
|
|
29155
|
-
if(bSheetSegment) {
|
|
29156
|
-
let start = 0, end = num - 1;
|
|
29157
|
-
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
29158
|
-
}
|
|
29159
|
-
else if(bHelixSegment) {
|
|
29160
|
-
if(bFullAtom) {
|
|
29161
|
-
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
29162
|
-
}
|
|
29163
|
-
else {
|
|
29164
|
-
let start = 0, end = num - 1;
|
|
29165
|
-
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
29166
|
-
}
|
|
29167
|
-
}
|
|
29168
|
-
}
|
|
29169
|
-
|
|
29170
|
-
for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
29171
|
-
colors = [];
|
|
29172
|
-
pntsCA = [];
|
|
29173
|
-
prevCOArray = [];
|
|
29174
|
-
bShowArray = [];
|
|
29175
|
-
calphaIdArray = [];
|
|
29176
|
-
bSheetSegment = false;
|
|
29177
|
-
bHelixSegment = false;
|
|
29178
|
-
}
|
|
29179
|
-
|
|
29180
|
-
currentChain = atom.chain;
|
|
29181
|
-
currentResi = atom.resi;
|
|
29182
|
-
ss = atom.ss;
|
|
29183
|
-
ssend = atom.ssend;
|
|
29184
|
-
prevAtomid = atom.serial;
|
|
29185
|
-
if(atoms.hasOwnProperty(atom.serial)) prevAtomSelected = atom;
|
|
29186
|
-
prevResi = atom.resi;
|
|
29187
|
-
|
|
29188
|
-
prevCalphaid = calphaid;
|
|
29189
|
-
|
|
29190
|
-
// only update when atom.name === 'O'
|
|
29191
|
-
prevCoorCA = currentCA;
|
|
29192
|
-
prevCoorO = atom.coord;
|
|
29193
|
-
prevColor = currentColor;
|
|
29194
|
-
} // end if (atom.name === 'O' || (bCalphaOnlyHash[chainid] && atom.name === 'CA') ) {
|
|
29195
|
-
} // end if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
|
|
29196
|
-
} // end for
|
|
29197
|
-
|
|
29198
|
-
caArray = [];
|
|
29199
|
-
|
|
29200
|
-
// ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight);
|
|
29201
|
-
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
29202
|
-
ic.tubeCls.createTube(atomsAdjust, 'CA', coilWidth, bHighlight);
|
|
29203
|
-
pnts = {};
|
|
29204
|
-
}
|
|
29205
|
-
|
|
29206
|
-
getOneExtraResidue(residueHash) { let ic = this.icn3d, me = ic.icn3dui;
|
|
29207
|
-
let atomsAdjust = {};
|
|
29208
|
-
|
|
29209
|
-
for(let resid in residueHash) {
|
|
29210
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, ic.residues[resid]);
|
|
29211
|
-
|
|
29212
|
-
let residNcbi = ic.resid2ncbi[resid];
|
|
29213
|
-
let resiNcbi = residNcbi.substr(residNcbi.lastIndexOf('_') + 1);
|
|
29214
|
-
|
|
29215
|
-
let nextResidNcbi = residNcbi.substr(0, residNcbi.lastIndexOf('_')) + '_' + (parseInt(resiNcbi) + 1);
|
|
29216
|
-
let nextResid = ic.ncbi2resid[nextResidNcbi];
|
|
29217
|
-
|
|
29218
|
-
if(!nextResid) {
|
|
29219
|
-
nextResidNcbi = residNcbi.substr(0, residNcbi.lastIndexOf('_')) + '_' + (parseInt(resiNcbi) - 1);
|
|
29220
|
-
nextResid = ic.ncbi2resid[nextResidNcbi];
|
|
29221
|
-
}
|
|
29222
|
-
|
|
29223
|
-
if(nextResid) atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, ic.residues[nextResid]);
|
|
29224
|
-
}
|
|
29225
|
-
|
|
29226
|
-
return atomsAdjust;
|
|
29227
|
-
}
|
|
29228
|
-
|
|
29229
|
-
/*
|
|
29230
|
-
getSSExpandedAtoms(atoms, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
|
|
29231
|
-
let currChain, currResi, currAtom, prevChain, prevResi, prevAtom;
|
|
29232
|
-
let firstAtom, lastAtom;
|
|
29233
|
-
let index = 0, length = Object.keys(atoms).length;
|
|
29234
|
-
|
|
29235
|
-
let atomsAdjust = me.hashUtilsCls.cloneHash(atoms);
|
|
29236
|
-
for(let serial in atoms) {
|
|
29237
|
-
currChain = atoms[serial].structure + '_' + atoms[serial].chain;
|
|
29238
|
-
currResi = atoms[serial].resi; //parseInt(atoms[serial].resi);
|
|
29239
|
-
currAtom = atoms[serial];
|
|
29240
|
-
|
|
29241
|
-
if(prevChain === undefined) firstAtom = atoms[serial];
|
|
29242
|
-
|
|
29243
|
-
if( (currChain !== prevChain && prevChain !== undefined)
|
|
29244
|
-
|| (currResi !== prevResi && ic.resid2ncbi[currResi] !== ic.resid2ncbi[prevResi] + 1 && prevResi !== undefined) || index === length - 1) {
|
|
29245
|
-
if( (currChain !== prevChain && prevChain !== undefined)
|
|
29246
|
-
|| (currResi !== prevResi && currResi !== ic.resid2ncbi[prevResi] + 1 && prevResi !== undefined) ) {
|
|
29247
|
-
lastAtom = prevAtom;
|
|
29248
|
-
}
|
|
29249
|
-
else if(index === length - 1) {
|
|
29250
|
-
lastAtom = currAtom;
|
|
29251
|
-
}
|
|
29252
|
-
|
|
29253
|
-
// fill the beginning
|
|
29254
|
-
let beginResi = firstAtom.resi;
|
|
29255
|
-
if(!isNaN(firstAtom.resi) && firstAtom.ss !== 'coil' && !(firstAtom.ssbegin) ) {
|
|
29256
|
-
for(let i = parseInt(firstAtom.resi) - 1; i > 0; --i) {
|
|
29257
|
-
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + i;
|
|
29258
|
-
if(!ic.residues.hasOwnProperty(residueid)) break;
|
|
29259
|
-
|
|
29260
|
-
let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[residueid]);
|
|
29261
|
-
|
|
29262
|
-
if(atom.ss === firstAtom.ss && atom.ssbegin) {
|
|
29263
|
-
beginResi = atom.resi;
|
|
29264
|
-
break;
|
|
29265
|
-
}
|
|
29266
|
-
}
|
|
29267
|
-
|
|
29268
|
-
for(let i = beginResi; i < firstAtom.resi; ++i) {
|
|
29269
|
-
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + i;
|
|
29270
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
29271
|
-
ic.atoms));
|
|
29272
|
-
}
|
|
29273
|
-
}
|
|
29274
|
-
|
|
29275
|
-
// add one extra residue for coils between strands/helix
|
|
29276
|
-
if(!isNaN(firstAtom.resi) && ic.pk === 3 && bHighlight === 1 && firstAtom.ss === 'coil') {
|
|
29277
|
-
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
|
|
29278
|
-
if(ic.residues.hasOwnProperty(residueid)) {
|
|
29279
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
29280
|
-
ic.atoms));
|
|
29281
|
-
atoms = me.hashUtilsCls.unionHash(atoms, me.hashUtilsCls.hash2Atoms(ic.residues[residueid], ic.atoms));
|
|
29282
|
-
}
|
|
29283
|
-
}
|
|
29284
|
-
|
|
29285
|
-
// fill the end
|
|
29286
|
-
let endResi = lastAtom.resi;
|
|
29287
|
-
// 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.
|
|
29288
|
-
|
|
29289
|
-
if(lastAtom.ss !== undefined && lastAtom.ss !== 'coil' && !(lastAtom.ssend) && !(lastAtom.notshow)) {
|
|
29290
|
-
|
|
29291
|
-
let endChainResi = ic.firstAtomObjCls.getLastAtomObj(ic.chains[lastAtom.structure + '_' + lastAtom.chain]).resi;
|
|
29292
|
-
for(let i = parseInt(lastAtom.resi) + 1; i <= parseInt(endChainResi); ++i) {
|
|
29293
|
-
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + i;
|
|
29294
|
-
if(!ic.residues.hasOwnProperty(residueid)) break;
|
|
29295
|
-
|
|
29296
|
-
let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[residueid]);
|
|
29297
|
-
|
|
29298
|
-
if(atom.ss === lastAtom.ss && atom.ssend) {
|
|
29299
|
-
endResi = atom.resi;
|
|
29300
|
-
break;
|
|
29301
|
-
}
|
|
29302
|
-
}
|
|
29303
|
-
|
|
29304
|
-
for(let i = parseInt(lastAtom.resi) + 1; i <= parseInt(endResi); ++i) {
|
|
29305
|
-
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + i;
|
|
29306
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
29307
|
-
ic.atoms));
|
|
29308
|
-
}
|
|
29309
|
-
}
|
|
29310
|
-
|
|
29311
|
-
// add one extra residue for coils between strands/helix
|
|
29312
|
-
if(ic.pk === 3 && bHighlight === 1 && lastAtom.ss === 'coil') {
|
|
29313
|
-
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + (parseInt(lastAtom.resi) + 1).toString();
|
|
29314
|
-
if(ic.residues.hasOwnProperty(residueid)) {
|
|
29315
|
-
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
29316
|
-
ic.atoms));
|
|
29317
|
-
atoms = me.hashUtilsCls.unionHash(atoms, me.hashUtilsCls.hash2Atoms(ic.residues[residueid], ic.atoms));
|
|
29318
|
-
}
|
|
29319
|
-
}
|
|
29320
|
-
|
|
29321
|
-
// reset notshow
|
|
29322
|
-
if(lastAtom.notshow) lastAtom.notshow = undefined;
|
|
29323
|
-
|
|
29324
|
-
firstAtom = currAtom;
|
|
29325
|
-
}
|
|
29326
|
-
|
|
29327
|
-
prevChain = currChain;
|
|
29328
|
-
prevResi = currResi;
|
|
29329
|
-
prevAtom = currAtom;
|
|
29330
|
-
|
|
29331
|
-
++index;
|
|
29332
|
-
}
|
|
29333
|
-
|
|
29334
|
-
return atomsAdjust;
|
|
29335
|
-
}
|
|
29336
|
-
*/
|
|
29337
|
-
}
|
|
29338
|
-
|
|
29339
|
-
/**
|
|
29340
|
-
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
29341
|
-
*/
|
|
29342
|
-
|
|
29343
|
-
class Strip {
|
|
29344
|
-
constructor(icn3d) {
|
|
29345
|
-
this.icn3d = icn3d;
|
|
29346
|
-
}
|
|
29347
|
-
|
|
29348
|
-
// modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
29349
|
-
createStrip(p0, p1, colors, div, thickness, bHighlight, bNoSmoothen, bShowArray,
|
|
29350
|
-
calphaIdArray, positions, prevone, nexttwo, pntsCA, prevCOArray) { let ic = this.icn3d, me = ic.icn3dui;
|
|
29351
|
-
if(me.bNode) return;
|
|
29352
|
-
|
|
29353
|
-
if (p0.length < 2) return;
|
|
29354
|
-
div = div || ic.axisDIV;
|
|
29355
|
-
|
|
29356
|
-
// if(pntsCA && ic.bDoublecolor && !ic.bCalphaOnly) {
|
|
29357
|
-
if(pntsCA && ic.bDoublecolor) {
|
|
29358
|
-
let bExtendLastRes = false; //true;
|
|
29359
|
-
|
|
29360
|
-
let pnts_clrs = me.subdivideCls.subdivide(pntsCA, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29361
|
-
pntsCA = pnts_clrs[0];
|
|
29362
|
-
|
|
29363
|
-
this.setCalphaDrawnCoord(pntsCA, div, calphaIdArray);
|
|
29364
|
-
|
|
29365
|
-
for(let i = 0, il = prevCOArray.length; i < il; ++i) {
|
|
29366
|
-
prevCOArray[i].normalize();
|
|
29367
|
-
}
|
|
29368
|
-
|
|
29369
|
-
let pnts_clrs2 = me.subdivideCls.subdivide(prevCOArray, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29370
|
-
prevCOArray = pnts_clrs2[0];
|
|
29371
|
-
|
|
29372
|
-
colors = pnts_clrs[2];
|
|
29373
|
-
}
|
|
29374
|
-
else {
|
|
29375
|
-
|
|
29376
|
-
if(!bNoSmoothen) {
|
|
29377
|
-
//var bExtendLastRes = true;
|
|
29378
|
-
let bExtendLastRes = false;
|
|
29379
|
-
let pnts_clrs0 = me.subdivideCls.subdivide(p0, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29380
|
-
let pnts_clrs1 = me.subdivideCls.subdivide(p1, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
|
|
29381
|
-
p0 = pnts_clrs0[0];
|
|
29382
|
-
p1 = pnts_clrs1[0];
|
|
29383
|
-
colors = pnts_clrs0[2];
|
|
29384
|
-
}
|
|
29385
|
-
if (p0.length < 2) return;
|
|
29386
|
-
|
|
29387
|
-
this.setCalphaDrawnCoord(p0, div, calphaIdArray);
|
|
29388
|
-
}
|
|
29389
|
-
|
|
29390
|
-
if(bHighlight === 1) {
|
|
29391
|
-
//mesh = new THREE.Mesh(geo, ic.matShader);
|
|
29392
|
-
|
|
29393
|
-
let radius = ic.coilWidth / 2;
|
|
29394
|
-
//var radiusSegments = 8;
|
|
29395
|
-
let radiusSegments = 4; // save memory
|
|
29396
|
-
let closed = false;
|
|
29397
|
-
|
|
29398
|
-
if(positions !== undefined) {
|
|
29399
|
-
let currPos, prevPos;
|
|
29400
|
-
let currP0 = [], currP1 = [];
|
|
29401
|
-
|
|
29402
|
-
for(let i = 0, il = p0.length; i < il; ++i) {
|
|
29403
|
-
currPos = positions[i];
|
|
29404
|
-
|
|
29405
|
-
if((currPos !== prevPos && parseInt(currPos) !== parseInt(prevPos) + 1 && prevPos !== undefined) || (i === il -1) ) {
|
|
29406
|
-
// first tube
|
|
29407
|
-
let geometry0 = new THREE.TubeGeometry(
|
|
29408
|
-
new THREE.CatmullRomCurve3(currP0), // path
|
|
29409
|
-
currP0.length, // segments
|
|
29410
|
-
radius,
|
|
29411
|
-
radiusSegments,
|
|
29412
|
-
closed
|
|
29413
|
-
);
|
|
29414
|
-
|
|
29415
|
-
let mesh = new THREE.Mesh(geometry0, ic.matShader);
|
|
29416
|
-
mesh.renderOrder = ic.renderOrderPicking;
|
|
29417
|
-
//ic.mdlPicking.add(mesh);
|
|
29418
|
-
ic.mdl.add(mesh);
|
|
29419
|
-
|
|
29420
|
-
ic.prevHighlightObjects.push(mesh);
|
|
29421
|
-
|
|
29422
|
-
geometry0 = null;
|
|
29423
|
-
|
|
29424
|
-
// second tube
|
|
29425
|
-
let geometry1 = new THREE.TubeGeometry(
|
|
29426
|
-
new THREE.CatmullRomCurve3(currP1), // path
|
|
29427
|
-
currP1.length, // segments
|
|
29428
|
-
radius,
|
|
29429
|
-
radiusSegments,
|
|
29430
|
-
closed
|
|
29431
|
-
);
|
|
29097
|
+
// second tube
|
|
29098
|
+
let geometry1 = new THREE.TubeGeometry(
|
|
29099
|
+
new THREE.CatmullRomCurve3(currP1), // path
|
|
29100
|
+
currP1.length, // segments
|
|
29101
|
+
radius,
|
|
29102
|
+
radiusSegments,
|
|
29103
|
+
closed
|
|
29104
|
+
);
|
|
29432
29105
|
|
|
29433
29106
|
mesh = new THREE.Mesh(geometry1, ic.matShader);
|
|
29434
29107
|
mesh.renderOrder = ic.renderOrderPicking;
|
|
@@ -29704,6 +29377,7 @@ class Tube {
|
|
|
29704
29377
|
atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) - 1).toString();
|
|
29705
29378
|
|
|
29706
29379
|
if (index > 0 && (currentChain !== atom.chain || Math.abs(atom.coord.x - prevAtom.coord.x) > maxDist || Math.abs(atom.coord.y - prevAtom.coord.y) > maxDist || Math.abs(atom.coord.z - prevAtom.coord.z) > maxDist
|
|
29380
|
+
|| (prevAtom.ssbegin) // e.g., https://www.ncbi.nlm.nih.gov/Structure/icn3d/?pdbid=7JO8 where a beta sheet has just two residues
|
|
29707
29381
|
// || (parseInt(currentResi) + 1 < parseInt(atom.resi) && (Math.abs(atom.coord.x - prevAtom.coord.x) > maxDist2 || Math.abs(atom.coord.y - prevAtom.coord.y) > maxDist2 || Math.abs(atom.coord.z - prevAtom.coord.z) > maxDist2) && ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[resid]) && ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[resid]).ss == 'helix')
|
|
29708
29382
|
|| (ic.ParserUtilsCls.getResiNCBI(atom.structure + '_' + currentChain, currentResi) + 1 < ic.ParserUtilsCls.getResiNCBI(atom.structure + '_' + atom.chain, atom.resi) && (Math.abs(atom.coord.x - prevAtom.coord.x) > maxDist2 || Math.abs(atom.coord.y - prevAtom.coord.y) > maxDist2 || Math.abs(atom.coord.z - prevAtom.coord.z) > maxDist2))
|
|
29709
29383
|
) ) {
|
|
@@ -29796,7 +29470,7 @@ class Tube {
|
|
|
29796
29470
|
}
|
|
29797
29471
|
|
|
29798
29472
|
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
29799
|
-
if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
|
|
29473
|
+
// if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
|
|
29800
29474
|
|
|
29801
29475
|
//radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
|
|
29802
29476
|
radii.push(radiusFinal);
|
|
@@ -29931,232 +29605,778 @@ class Tube {
|
|
|
29931
29605
|
|
|
29932
29606
|
pnts.push(atom.coord);
|
|
29933
29607
|
|
|
29934
|
-
let radiusFinal;
|
|
29935
|
-
if(bCustom) {
|
|
29936
|
-
radiusFinal = this.getCustomtubesize(atom.structure + '_' + atom.chain + '_' + atom.resi);
|
|
29937
|
-
}
|
|
29938
|
-
else {
|
|
29939
|
-
radiusFinal = this.getRadius(radius, atom);
|
|
29940
|
-
}
|
|
29608
|
+
let radiusFinal;
|
|
29609
|
+
if(bCustom) {
|
|
29610
|
+
radiusFinal = this.getCustomtubesize(atom.structure + '_' + atom.chain + '_' + atom.resi);
|
|
29611
|
+
}
|
|
29612
|
+
else {
|
|
29613
|
+
radiusFinal = this.getRadius(radius, atom);
|
|
29614
|
+
}
|
|
29615
|
+
|
|
29616
|
+
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
29617
|
+
if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
|
|
29618
|
+
|
|
29619
|
+
//radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
|
|
29620
|
+
radii.push(radiusFinal);
|
|
29621
|
+
|
|
29622
|
+
colors.push(atom.color);
|
|
29623
|
+
// the starting residue of a coil uses the color from the next residue to avoid using the color of the last helix/sheet residue
|
|
29624
|
+
if(index === 1) colors[colors.length - 2] = atom.color;
|
|
29625
|
+
|
|
29626
|
+
currentChain = atom.chain;
|
|
29627
|
+
currentResi = atom.resi;
|
|
29628
|
+
|
|
29629
|
+
let scale = 1.2;
|
|
29630
|
+
if(bHighlight === 2 && !atom.ssbegin) {
|
|
29631
|
+
ic.boxCls.createBox(atom, undefined, undefined, scale, undefined, bHighlight);
|
|
29632
|
+
}
|
|
29633
|
+
|
|
29634
|
+
++index;
|
|
29635
|
+
|
|
29636
|
+
prevAtom = atom;
|
|
29637
|
+
}
|
|
29638
|
+
}
|
|
29639
|
+
|
|
29640
|
+
if(bHighlight !== 2) {
|
|
29641
|
+
pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
|
|
29642
|
+
}
|
|
29643
|
+
|
|
29644
|
+
for(let i = 0, il = pnts_colors_radii_prevone_nexttwo.length; i < il; ++i) {
|
|
29645
|
+
let pnts = pnts_colors_radii_prevone_nexttwo[i].pnts;
|
|
29646
|
+
let colors = pnts_colors_radii_prevone_nexttwo[i].colors;
|
|
29647
|
+
let radii = pnts_colors_radii_prevone_nexttwo[i].radii;
|
|
29648
|
+
let prevone = []; // = pnts_colors_radii_prevone_nexttwo[i].prevone;
|
|
29649
|
+
let nexttwo = []; // = pnts_colors_radii_prevone_nexttwo[i].nexttwo;
|
|
29650
|
+
|
|
29651
|
+
this.createTubeSub(pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil);
|
|
29652
|
+
}
|
|
29653
|
+
|
|
29654
|
+
pnts_colors_radii_prevone_nexttwo = [];
|
|
29655
|
+
}
|
|
29656
|
+
*/
|
|
29657
|
+
|
|
29658
|
+
getCustomtubesize(resid) { let ic = this.icn3d; ic.icn3dui;
|
|
29659
|
+
let pos = resid.lastIndexOf('_');
|
|
29660
|
+
let resi = resid.substr(pos + 1);
|
|
29661
|
+
let chainid = resid.substr(0, pos);
|
|
29662
|
+
|
|
29663
|
+
let radiusFinal = (ic.queryresi2score[chainid] && ic.queryresi2score[chainid].hasOwnProperty(resi)) ? ic.queryresi2score[chainid][resi] * 0.01 : ic.coilWidth;
|
|
29664
|
+
|
|
29665
|
+
return radiusFinal;
|
|
29666
|
+
};
|
|
29667
|
+
|
|
29668
|
+
// modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
29669
|
+
createTubeSub(_pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
|
|
29670
|
+
if(me.bNode) return;
|
|
29671
|
+
|
|
29672
|
+
if (_pnts.length < 2) return;
|
|
29673
|
+
|
|
29674
|
+
let circleDiv = ic.tubeDIV, axisDiv = ic.axisDIV;
|
|
29675
|
+
let circleDivInv = 1 / circleDiv, axisDivInv = 1 / axisDiv;
|
|
29676
|
+
//var geo = new THREE.Geometry();
|
|
29677
|
+
let geo = new THREE.BufferGeometry();
|
|
29678
|
+
let verticeArray = [], colorArray = [],indexArray = [], color;
|
|
29679
|
+
let offset = 0, offset2 = 0, offset3 = 0;
|
|
29680
|
+
|
|
29681
|
+
let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv, undefined, undefined, prevone, nexttwo);
|
|
29682
|
+
|
|
29683
|
+
let pnts = pnts_clrs[0];
|
|
29684
|
+
colors = pnts_clrs[2];
|
|
29685
|
+
|
|
29686
|
+
let constRadiius;
|
|
29687
|
+
// a threshold to stop drawing the tube if it's less than this ratio of radius
|
|
29688
|
+
let thresholdRatio = 1; //0.9;
|
|
29689
|
+
|
|
29690
|
+
let prevAxis1 = new THREE.Vector3(), prevAxis2;
|
|
29691
|
+
for (let i = 0, lim = pnts.length; i < lim; ++i) {
|
|
29692
|
+
let r, idx = (i - 1) * axisDivInv;
|
|
29693
|
+
|
|
29694
|
+
if (i === 0) {
|
|
29695
|
+
r = radii[0];
|
|
29696
|
+
if(r > 0) constRadiius = r;
|
|
29697
|
+
}
|
|
29698
|
+
else {
|
|
29699
|
+
if (idx % 1 === 0) {
|
|
29700
|
+
r = radii[idx];
|
|
29701
|
+
if(r > 0) constRadiius = r;
|
|
29702
|
+
}
|
|
29703
|
+
else {
|
|
29704
|
+
let floored = Math.floor(idx);
|
|
29705
|
+
let tmp = idx - floored;
|
|
29706
|
+
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
29707
|
+
// r = radii[floored] * tmp + radii[floored + 1] * (1 - tmp);
|
|
29708
|
+
r = radii[floored] * (1 - tmp) + radii[floored + 1] * tmp;
|
|
29709
|
+
|
|
29710
|
+
// a threshold to stop drawing the tube if it's less than this ratio of radius.
|
|
29711
|
+
// The extra bit of tube connects coil with strands or helices
|
|
29712
|
+
if(!bNonCoil) {
|
|
29713
|
+
if(r < thresholdRatio * constRadiius) {
|
|
29714
|
+
r = 0;
|
|
29715
|
+
}
|
|
29716
|
+
// else if(r < constRadiius) {
|
|
29717
|
+
// r *= 0.5; // use small radius for the connection between coild and sheets/helices
|
|
29718
|
+
// }
|
|
29719
|
+
}
|
|
29720
|
+
}
|
|
29721
|
+
}
|
|
29722
|
+
let delta, axis1, axis2;
|
|
29723
|
+
if (i < lim - 1) {
|
|
29724
|
+
delta = pnts[i].clone().sub(pnts[i + 1]);
|
|
29725
|
+
axis1 = new THREE.Vector3(0, -delta.z, delta.y).normalize().multiplyScalar(r);
|
|
29726
|
+
axis2 = delta.clone().cross(axis1).normalize().multiplyScalar(r);
|
|
29727
|
+
// let dir = 1, offset = 0;
|
|
29728
|
+
if (prevAxis1.dot(axis1) < 0) {
|
|
29729
|
+
axis1.negate(); axis2.negate(); //dir = -1;//offset = 2 * Math.PI / axisDiv;
|
|
29730
|
+
}
|
|
29731
|
+
prevAxis1 = axis1; prevAxis2 = axis2;
|
|
29732
|
+
} else {
|
|
29733
|
+
axis1 = prevAxis1; axis2 = prevAxis2;
|
|
29734
|
+
}
|
|
29735
|
+
for (let j = 0; j < circleDiv; ++j) {
|
|
29736
|
+
let angle = 2 * Math.PI * circleDivInv * j; //* dir + offset;
|
|
29737
|
+
let point = pnts[i].clone().add(axis1.clone().multiplyScalar(Math.cos(angle))).add(axis2.clone().multiplyScalar(Math.sin(angle)));
|
|
29738
|
+
verticeArray[offset++] = point.x;
|
|
29739
|
+
verticeArray[offset++] = point.y;
|
|
29740
|
+
verticeArray[offset++] = point.z;
|
|
29741
|
+
|
|
29742
|
+
color = (i == colors.length - 1 && colors.length > 1) ? me.parasCls.thr(colors[colors.length - 2]) : me.parasCls.thr(colors[i]);
|
|
29743
|
+
colorArray[offset2++] = color.r;
|
|
29744
|
+
colorArray[offset2++] = color.g;
|
|
29745
|
+
colorArray[offset2++] = color.b;
|
|
29746
|
+
}
|
|
29747
|
+
}
|
|
29748
|
+
let offsetTmp = 0, nComp = 3;
|
|
29749
|
+
for (let i = 0, lim = pnts.length - 1; i < lim; ++i) {
|
|
29750
|
+
let reg = 0;
|
|
29751
|
+
//var r1 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv]).lengthSq();
|
|
29752
|
+
//var r2 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv + 1]).lengthSq();
|
|
29753
|
+
let pos = offsetTmp * nComp;
|
|
29754
|
+
let point1 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
29755
|
+
pos = (offsetTmp + circleDiv) * nComp;
|
|
29756
|
+
let point2 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
29757
|
+
pos = (offsetTmp + circleDiv + 1) * nComp;
|
|
29758
|
+
let point3 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
29759
|
+
|
|
29760
|
+
let r1 = point1.clone().sub(point2).lengthSq();
|
|
29761
|
+
let r2 = point1.clone().sub(point3).lengthSq();
|
|
29762
|
+
if (r1 > r2) { r1 = r2; reg = 1; } for (let j = 0; j < circleDiv; ++j) {
|
|
29763
|
+
//geo.faces.push(new THREE.Face3(offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv, undefined, c));
|
|
29764
|
+
//geo.faces.push(new THREE.Face3(offset + (j + 1) % circleDiv, offset + (j + reg) % circleDiv + circleDiv, offset + (j + reg + 1) % circleDiv + circleDiv, undefined, c));
|
|
29765
|
+
//indexArray = indexArray.concat([offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv]);
|
|
29766
|
+
indexArray[offset3++] = offsetTmp + j;
|
|
29767
|
+
indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
|
|
29768
|
+
indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
|
|
29769
|
+
|
|
29770
|
+
//indexArray = indexArray.concat([offset + (j + 1) % circleDiv, offset + (j + reg) % circleDiv + circleDiv, offset + (j + reg + 1) % circleDiv + circleDiv]);
|
|
29771
|
+
indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
|
|
29772
|
+
indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
|
|
29773
|
+
indexArray[offset3++] = offsetTmp + (j + reg + 1) % circleDiv + circleDiv;
|
|
29774
|
+
}
|
|
29775
|
+
offsetTmp += circleDiv;
|
|
29776
|
+
}
|
|
29777
|
+
|
|
29778
|
+
geo.setAttribute('position', new THREE.BufferAttribute(new Float32Array(verticeArray), nComp));
|
|
29779
|
+
geo.setAttribute('color', new THREE.BufferAttribute(new Float32Array(colorArray), nComp));
|
|
29780
|
+
|
|
29781
|
+
geo.setIndex(new THREE.BufferAttribute(new Uint32Array(indexArray), 1));
|
|
29782
|
+
//geo.setIndex(indexArray);
|
|
29783
|
+
|
|
29784
|
+
//geo.computeFaceNormals();
|
|
29785
|
+
//geo.computeVertexNormals(false);
|
|
29786
|
+
geo.computeVertexNormals();
|
|
29787
|
+
|
|
29788
|
+
let mesh;
|
|
29789
|
+
if(bHighlight === 2) {
|
|
29790
|
+
//mesh = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({ transparent: true, opacity: 0.5, specular: ic.frac, shininess: ic.shininess, emissive: ic.emissive, vertexColors: THREE.FaceColors, side: THREE.DoubleSide }));
|
|
29791
|
+
mesh = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({ transparent: true, opacity: 0.5, specular: ic.frac, shininess: ic.shininess, emissive: ic.emissive, vertexColors: true, side: THREE.DoubleSide }));
|
|
29792
|
+
|
|
29793
|
+
if(ic.mdl) ic.mdl.add(mesh);
|
|
29794
|
+
}
|
|
29795
|
+
else if(bHighlight === 1) {
|
|
29796
|
+
mesh = new THREE.Mesh(geo, ic.matShader);
|
|
29797
|
+
mesh.renderOrder = ic.renderOrderPicking;
|
|
29798
|
+
//ic.mdlPicking.add(mesh);
|
|
29799
|
+
if(ic.mdl) ic.mdl.add(mesh);
|
|
29800
|
+
}
|
|
29801
|
+
else {
|
|
29802
|
+
//mesh = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({ specular: ic.frac, shininess: ic.shininess, emissive: ic.emissive, vertexColors: THREE.FaceColors, side: THREE.DoubleSide }));
|
|
29803
|
+
mesh = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({ specular: ic.frac, shininess: ic.shininess, emissive: ic.emissive, vertexColors: true, side: THREE.DoubleSide }));
|
|
29804
|
+
|
|
29805
|
+
if(ic.mdl) ic.mdl.add(mesh);
|
|
29806
|
+
}
|
|
29807
|
+
|
|
29808
|
+
if(bHighlight === 1 || bHighlight === 2) {
|
|
29809
|
+
ic.prevHighlightObjects.push(mesh);
|
|
29810
|
+
}
|
|
29811
|
+
else {
|
|
29812
|
+
ic.objects.push(mesh);
|
|
29813
|
+
}
|
|
29814
|
+
}
|
|
29815
|
+
|
|
29816
|
+
getRadius(radius, atom) { let ic = this.icn3d; ic.icn3dui;
|
|
29817
|
+
let radiusFinal = radius;
|
|
29818
|
+
if(radius) {
|
|
29819
|
+
radiusFinal = radius;
|
|
29820
|
+
}
|
|
29821
|
+
else {
|
|
29822
|
+
if(atom.b > 0 && atom.b <= 100) {
|
|
29823
|
+
radiusFinal = atom.b * 0.01;
|
|
29824
|
+
}
|
|
29825
|
+
else if(atom.b > 100) {
|
|
29826
|
+
radiusFinal = 100 * 0.01;
|
|
29827
|
+
}
|
|
29828
|
+
else {
|
|
29829
|
+
radiusFinal = ic.coilWidth;
|
|
29830
|
+
}
|
|
29831
|
+
}
|
|
29832
|
+
|
|
29833
|
+
return radiusFinal;
|
|
29834
|
+
}
|
|
29835
|
+
}
|
|
29836
|
+
|
|
29837
|
+
/**
|
|
29838
|
+
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
29839
|
+
*/
|
|
29840
|
+
|
|
29841
|
+
class Strand {
|
|
29842
|
+
constructor(icn3d) {
|
|
29843
|
+
this.icn3d = icn3d;
|
|
29844
|
+
}
|
|
29845
|
+
|
|
29846
|
+
// significantly modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
29847
|
+
//Create the style of ribbon or strand for "atoms". "num" means how many lines define the curve.
|
|
29848
|
+
//"num" is 2 for ribbon and 6 for strand. "div" means how many pnts are used to smooth the curve.
|
|
29849
|
+
//It's typically 5. "coilWidth" is the width of curve for coil. "helixSheetWidth" is the width of curve for helix or sheet.
|
|
29850
|
+
//"doNotSmoothen" is a flag to smooth the curve or not. "thickness" is the thickness of the curve.
|
|
29851
|
+
//"bHighlight" is an option to draw the highlight for these atoms. The highlight could be outlines
|
|
29852
|
+
//with bHighlight=1 and 3D objects with bHighlight=2.
|
|
29853
|
+
createStrand(atoms, num, div, fill, coilWidth, helixSheetWidth, doNotSmoothen, thickness, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
|
|
29854
|
+
if(me.bNode) return;
|
|
29855
|
+
|
|
29856
|
+
let bRibbon = fill ? true: false;
|
|
29857
|
+
|
|
29858
|
+
// when highlight, the input atoms may only include part of sheet or helix
|
|
29859
|
+
// include the whole sheet or helix when highlighting
|
|
29860
|
+
let atomsAdjust = {};
|
|
29861
|
+
|
|
29862
|
+
//if( (bHighlight === 1 || bHighlight === 2) && !ic.bAllAtoms) {
|
|
29863
|
+
//if( !ic.bAllAtoms) {
|
|
29864
|
+
if( Object.keys(atoms).length < Object.keys(ic.atoms).length) {
|
|
29865
|
+
atomsAdjust = this.getSSExpandedAtoms(atoms);
|
|
29866
|
+
}
|
|
29867
|
+
else {
|
|
29868
|
+
atomsAdjust = atoms;
|
|
29869
|
+
}
|
|
29870
|
+
|
|
29871
|
+
if(bHighlight === 2) {
|
|
29872
|
+
if(fill) {
|
|
29873
|
+
fill = false;
|
|
29874
|
+
num = null;
|
|
29875
|
+
div = null;
|
|
29876
|
+
coilWidth = null;
|
|
29877
|
+
helixSheetWidth = null;
|
|
29878
|
+
thickness = undefined;
|
|
29879
|
+
}
|
|
29880
|
+
else {
|
|
29881
|
+
fill = true;
|
|
29882
|
+
num = 2;
|
|
29883
|
+
div = undefined;
|
|
29884
|
+
coilWidth = undefined;
|
|
29885
|
+
helixSheetWidth = undefined;
|
|
29886
|
+
thickness = ic.ribbonthickness;
|
|
29887
|
+
}
|
|
29888
|
+
}
|
|
29889
|
+
|
|
29890
|
+
num = num || ic.strandDIV;
|
|
29891
|
+
div = div || ic.axisDIV;
|
|
29892
|
+
coilWidth = coilWidth || ic.coilWidth;
|
|
29893
|
+
doNotSmoothen = doNotSmoothen || false;
|
|
29894
|
+
helixSheetWidth = helixSheetWidth || ic.helixSheetWidth;
|
|
29895
|
+
let pnts = {}; for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
29896
|
+
let pntsCA = [];
|
|
29897
|
+
let prevCOArray = [];
|
|
29898
|
+
let bShowArray = [];
|
|
29899
|
+
let calphaIdArray = []; // used to store one of the final positions drawn in 3D
|
|
29900
|
+
let colors = [];
|
|
29901
|
+
let currentChain, currentCA = null, currentO = null, currentColor = null, prevCoorCA = null, prevCoorO = null, prevColor = null;
|
|
29902
|
+
let prevCO = null, ss = null, ssend = false, atomid = null, prevAtomid = null, prevResi = null, calphaid = null, prevCalphaid = null;
|
|
29903
|
+
let strandWidth, bSheetSegment = false, bHelixSegment = false;
|
|
29904
|
+
let atom, tubeAtoms = {};
|
|
29905
|
+
|
|
29906
|
+
// test the first 30 atoms to see whether only C-alpha is available
|
|
29907
|
+
ic.bCalphaOnly = me.utilsCls.isCalphaPhosOnly(atomsAdjust); //, 'CA');
|
|
29908
|
+
|
|
29909
|
+
// when highlight, draw whole beta sheet and use bShowArray to show the highlight part
|
|
29910
|
+
let residueHash = {};
|
|
29911
|
+
for(let i in atomsAdjust) {
|
|
29912
|
+
let atom = atomsAdjust[i];
|
|
29913
|
+
|
|
29914
|
+
let residueid = atom.structure + '_' + atom.chain + '_' + atom.resi;
|
|
29915
|
+
residueHash[residueid] = 1;
|
|
29916
|
+
}
|
|
29917
|
+
let totalResidueCount = Object.keys(residueHash).length;
|
|
29918
|
+
|
|
29919
|
+
let drawnResidueCount = 0;
|
|
29920
|
+
|
|
29921
|
+
let bFullAtom = (Object.keys(ic.hAtoms).length == Object.keys(ic.atoms).length) ? true : false;
|
|
29922
|
+
|
|
29923
|
+
let caArray = []; // record all C-alpha atoms to predict the helix
|
|
29924
|
+
|
|
29925
|
+
for (let i in atomsAdjust) {
|
|
29926
|
+
atom = atomsAdjust[i];
|
|
29927
|
+
if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
|
|
29928
|
+
// "CA" has to appear before "O"
|
|
29929
|
+
|
|
29930
|
+
if (atom.name === 'CA') {
|
|
29931
|
+
if ( atoms.hasOwnProperty(i) && ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) ) {
|
|
29932
|
+
tubeAtoms[i] = atom;
|
|
29933
|
+
}
|
|
29934
|
+
|
|
29935
|
+
currentCA = atom.coord;
|
|
29936
|
+
currentColor = atom.color;
|
|
29937
|
+
calphaid = atom.serial;
|
|
29938
|
+
|
|
29939
|
+
caArray.push(atom.serial);
|
|
29940
|
+
}
|
|
29941
|
+
|
|
29942
|
+
if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA')) {
|
|
29943
|
+
if(currentCA === null || currentCA === undefined) {
|
|
29944
|
+
currentCA = atom.coord;
|
|
29945
|
+
currentColor = atom.color;
|
|
29946
|
+
calphaid = atom.serial;
|
|
29947
|
+
}
|
|
29948
|
+
|
|
29949
|
+
if(atom.name === 'O') {
|
|
29950
|
+
currentO = atom.coord;
|
|
29951
|
+
}
|
|
29952
|
+
// smoothen each coil, helix and sheet separately. The joint residue has to be included both in the previous and next segment
|
|
29953
|
+
let bSameChain = true;
|
|
29954
|
+
// if (currentChain !== atom.chain || currentResi + 1 !== atom.resi) {
|
|
29955
|
+
if (currentChain !== atom.chain) {
|
|
29956
|
+
bSameChain = false;
|
|
29957
|
+
}
|
|
29958
|
+
|
|
29959
|
+
if(atom.ssend && atom.ss === 'sheet') {
|
|
29960
|
+
bSheetSegment = true;
|
|
29961
|
+
}
|
|
29962
|
+
else if(atom.ssend && atom.ss === 'helix') {
|
|
29963
|
+
bHelixSegment = true;
|
|
29964
|
+
}
|
|
29965
|
+
|
|
29966
|
+
// assign the previous residue
|
|
29967
|
+
if(prevCoorO) {
|
|
29968
|
+
if(bHighlight === 1 || bHighlight === 2) {
|
|
29969
|
+
colors.push(ic.hColor);
|
|
29970
|
+
}
|
|
29971
|
+
else {
|
|
29972
|
+
colors.push(prevColor);
|
|
29973
|
+
}
|
|
29974
|
+
|
|
29975
|
+
if(ss !== 'coil' && atom.ss === 'coil') {
|
|
29976
|
+
strandWidth = coilWidth;
|
|
29977
|
+
}
|
|
29978
|
+
else if(ssend && atom.ssbegin) { // a transition between two ss
|
|
29979
|
+
strandWidth = coilWidth;
|
|
29980
|
+
}
|
|
29981
|
+
else {
|
|
29982
|
+
strandWidth = (ss === 'coil') ? coilWidth : helixSheetWidth;
|
|
29983
|
+
}
|
|
29984
|
+
|
|
29985
|
+
let O, oldCA, resSpan = 4;
|
|
29986
|
+
if(atom.name === 'O') {
|
|
29987
|
+
O = prevCoorO.clone();
|
|
29988
|
+
if(prevCoorCA !== null && prevCoorCA !== undefined) {
|
|
29989
|
+
O.sub(prevCoorCA);
|
|
29990
|
+
}
|
|
29991
|
+
else {
|
|
29992
|
+
prevCoorCA = prevCoorO.clone();
|
|
29993
|
+
if(caArray.length > resSpan + 1) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
29994
|
+
O = prevCoorCA.clone();
|
|
29995
|
+
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan - 1]].coord.clone();
|
|
29996
|
+
//O.sub(oldCA);
|
|
29997
|
+
oldCA.sub(O);
|
|
29998
|
+
}
|
|
29999
|
+
else {
|
|
30000
|
+
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
30001
|
+
}
|
|
30002
|
+
}
|
|
30003
|
+
}
|
|
30004
|
+
else if(ic.bCalphaOnly && atom.name === 'CA') {
|
|
30005
|
+
if(caArray.length > resSpan + 1) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
30006
|
+
O = prevCoorCA.clone();
|
|
30007
|
+
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan - 1]].coord.clone();
|
|
30008
|
+
//O.sub(oldCA);
|
|
30009
|
+
oldCA.sub(O);
|
|
30010
|
+
}
|
|
30011
|
+
else {
|
|
30012
|
+
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
30013
|
+
}
|
|
30014
|
+
}
|
|
30015
|
+
|
|
30016
|
+
O.normalize(); // can be omitted for performance
|
|
30017
|
+
O.multiplyScalar(strandWidth);
|
|
30018
|
+
if (prevCO !== null && O.dot(prevCO) < 0) O.negate();
|
|
30019
|
+
prevCO = O;
|
|
30020
|
+
|
|
30021
|
+
for (let j = 0, numM1Inv2 = 2 / (num - 1); j < num; ++j) {
|
|
30022
|
+
let delta = -1 + numM1Inv2 * j;
|
|
30023
|
+
let v = new THREE.Vector3(prevCoorCA.x + prevCO.x * delta, prevCoorCA.y + prevCO.y * delta, prevCoorCA.z + prevCO.z * delta);
|
|
30024
|
+
if (!doNotSmoothen && ss === 'sheet') v.smoothen = true;
|
|
30025
|
+
pnts[j].push(v);
|
|
30026
|
+
}
|
|
30027
|
+
|
|
30028
|
+
pntsCA.push(prevCoorCA);
|
|
30029
|
+
prevCOArray.push(prevCO);
|
|
30030
|
+
|
|
30031
|
+
if(atoms.hasOwnProperty(prevAtomid)) {
|
|
30032
|
+
bShowArray.push(prevResi);
|
|
30033
|
+
calphaIdArray.push(prevCalphaid);
|
|
30034
|
+
}
|
|
30035
|
+
else {
|
|
30036
|
+
bShowArray.push(0);
|
|
30037
|
+
calphaIdArray.push(0);
|
|
30038
|
+
}
|
|
30039
|
+
|
|
30040
|
+
++drawnResidueCount;
|
|
30041
|
+
}
|
|
30042
|
+
|
|
30043
|
+
let maxDist = 6.0;
|
|
30044
|
+
let bBrokenSs = (prevCoorCA && Math.abs(currentCA.x - prevCoorCA.x) > maxDist) || (prevCoorCA && Math.abs(currentCA.y - prevCoorCA.y) > maxDist) || (prevCoorCA && Math.abs(currentCA.z - prevCoorCA.z) > maxDist);
|
|
30045
|
+
// The following code didn't work to select one residue
|
|
30046
|
+
// let bBrokenSs = !atoms.hasOwnProperty(atom.serial) || (prevCoorCA && Math.abs(currentCA.x - prevCoorCA.x) > maxDist) || (prevCoorCA && Math.abs(currentCA.y - prevCoorCA.y) > maxDist) || (prevCoorCA && Math.abs(currentCA.z - prevCoorCA.z) > maxDist);
|
|
30047
|
+
|
|
30048
|
+
// if(bBrokenSs && atom.ss === 'sheet') {
|
|
30049
|
+
// bSheetSegment = true;
|
|
30050
|
+
// }
|
|
30051
|
+
// else if(bBrokenSs && atom.ss === 'helix') {
|
|
30052
|
+
// bHelixSegment = true;
|
|
30053
|
+
// }
|
|
30054
|
+
|
|
30055
|
+
if ((atom.ssbegin || atom.ssend || (drawnResidueCount === totalResidueCount - 1) || bBrokenSs) && pnts[0].length > 0 && bSameChain) {
|
|
30056
|
+
let atomName = 'CA';
|
|
30057
|
+
|
|
30058
|
+
let prevone = [], nexttwo = [];
|
|
30059
|
+
|
|
30060
|
+
if(isNaN(ic.atoms[prevAtomid].resi)) {
|
|
30061
|
+
prevone = [];
|
|
30062
|
+
}
|
|
30063
|
+
else {
|
|
30064
|
+
let prevoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) - 1).toString();
|
|
30065
|
+
let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
|
|
30066
|
+
prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
|
|
30067
|
+
}
|
|
30068
|
+
|
|
30069
|
+
if(!isNaN(ic.atoms[prevAtomid].resi)) {
|
|
30070
|
+
let nextoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) + 1).toString();
|
|
30071
|
+
let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
|
|
30072
|
+
if(nextoneCoord !== undefined) {
|
|
30073
|
+
nexttwo.push(nextoneCoord);
|
|
30074
|
+
}
|
|
30075
|
+
|
|
30076
|
+
let nexttwoResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) + 2).toString();
|
|
30077
|
+
let nexttwoCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nexttwoResid, atomName);
|
|
30078
|
+
if(nexttwoCoord !== undefined) {
|
|
30079
|
+
nexttwo.push(nexttwoCoord);
|
|
30080
|
+
}
|
|
30081
|
+
}
|
|
30082
|
+
|
|
30083
|
+
if(!bBrokenSs) { // include the current residue
|
|
30084
|
+
// assign the current joint residue to the previous segment
|
|
30085
|
+
if(bHighlight === 1 || bHighlight === 2) {
|
|
30086
|
+
colors.push(ic.hColor);
|
|
30087
|
+
}
|
|
30088
|
+
else {
|
|
30089
|
+
//colors.push(atom.color);
|
|
30090
|
+
colors.push(prevColor);
|
|
30091
|
+
}
|
|
30092
|
+
|
|
30093
|
+
if(atom.ssend && atom.ss === 'sheet') { // current residue is the end of ss and is the end of arrow
|
|
30094
|
+
strandWidth = 0; // make the arrow end sharp
|
|
30095
|
+
}
|
|
30096
|
+
else if(ss === 'coil' && atom.ssbegin) {
|
|
30097
|
+
strandWidth = coilWidth;
|
|
30098
|
+
}
|
|
30099
|
+
else if(ssend && atom.ssbegin) { // current residue is the start of ss and the previous residue is the end of ss, then use coil
|
|
30100
|
+
strandWidth = coilWidth;
|
|
30101
|
+
}
|
|
30102
|
+
else { // use the ss from the previous residue
|
|
30103
|
+
strandWidth = (atom.ss === 'coil') ? coilWidth : helixSheetWidth;
|
|
30104
|
+
}
|
|
30105
|
+
|
|
30106
|
+
let O, oldCA, resSpan = 4;
|
|
30107
|
+
if(atom.name === 'O') {
|
|
30108
|
+
O = currentO.clone();
|
|
30109
|
+
O.sub(currentCA);
|
|
30110
|
+
}
|
|
30111
|
+
else if(ic.bCalphaOnly && atom.name === 'CA') {
|
|
30112
|
+
if(caArray.length > resSpan) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
|
|
30113
|
+
O = currentCA.clone();
|
|
30114
|
+
oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan]].coord.clone();
|
|
30115
|
+
//O.sub(oldCA);
|
|
30116
|
+
oldCA.sub(O);
|
|
30117
|
+
}
|
|
30118
|
+
else {
|
|
30119
|
+
O = new THREE.Vector3(Math.random(),Math.random(),Math.random());
|
|
30120
|
+
}
|
|
30121
|
+
}
|
|
30122
|
+
|
|
30123
|
+
O.normalize(); // can be omitted for performance
|
|
30124
|
+
O.multiplyScalar(strandWidth);
|
|
30125
|
+
if (prevCO !== null && O.dot(prevCO) < 0) O.negate();
|
|
30126
|
+
prevCO = O;
|
|
30127
|
+
|
|
30128
|
+
for (let j = 0, numM1Inv2 = 2 / (num - 1); j < num; ++j) {
|
|
30129
|
+
let delta = -1 + numM1Inv2 * j;
|
|
30130
|
+
let v = new THREE.Vector3(currentCA.x + prevCO.x * delta, currentCA.y + prevCO.y * delta, currentCA.z + prevCO.z * delta);
|
|
30131
|
+
if (!doNotSmoothen && ss === 'sheet') v.smoothen = true;
|
|
30132
|
+
pnts[j].push(v);
|
|
30133
|
+
}
|
|
30134
|
+
|
|
30135
|
+
atomid = atom.serial;
|
|
30136
|
+
|
|
30137
|
+
pntsCA.push(currentCA);
|
|
30138
|
+
prevCOArray.push(prevCO);
|
|
30139
|
+
|
|
30140
|
+
// when a coil connects to a sheet and the last residue of coild is highlighted, the first sheet residue is set as atom.highlightStyle. This residue should not be shown.
|
|
30141
|
+
//if(atoms.hasOwnProperty(atomid) && (bHighlight === 1 && !atom.notshow) ) {
|
|
30142
|
+
if(atoms.hasOwnProperty(atomid)) {
|
|
30143
|
+
bShowArray.push(atom.resi);
|
|
30144
|
+
calphaIdArray.push(calphaid);
|
|
30145
|
+
}
|
|
30146
|
+
else {
|
|
30147
|
+
bShowArray.push(0);
|
|
30148
|
+
calphaIdArray.push(0);
|
|
30149
|
+
}
|
|
30150
|
+
}
|
|
30151
|
+
|
|
30152
|
+
// draw the current segment
|
|
30153
|
+
for (let j = 0; !fill && j < num; ++j) {
|
|
30154
|
+
if(bSheetSegment) {
|
|
30155
|
+
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
30156
|
+
}
|
|
30157
|
+
else if(bHelixSegment) {
|
|
30158
|
+
if(bFullAtom) {
|
|
30159
|
+
ic.curveCls.createCurveSub(pnts[j], 1, colors, div, bHighlight, bRibbon, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo);
|
|
30160
|
+
}
|
|
30161
|
+
else {
|
|
30162
|
+
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
30163
|
+
}
|
|
30164
|
+
}
|
|
30165
|
+
}
|
|
30166
|
+
if (fill) {
|
|
30167
|
+
if(bSheetSegment) {
|
|
30168
|
+
let start = 0, end = num - 1;
|
|
30169
|
+
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
30170
|
+
}
|
|
30171
|
+
else if(bHelixSegment) {
|
|
30172
|
+
if(bFullAtom) {
|
|
30173
|
+
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
30174
|
+
}
|
|
30175
|
+
else {
|
|
30176
|
+
let start = 0, end = num - 1;
|
|
30177
|
+
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
30178
|
+
}
|
|
30179
|
+
}
|
|
30180
|
+
else {
|
|
30181
|
+
if(bHighlight === 2) { // draw coils only when highlighted. if not highlighted, coils will be drawn as tubes separately
|
|
30182
|
+
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
30183
|
+
}
|
|
30184
|
+
}
|
|
30185
|
+
}
|
|
30186
|
+
for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
30187
|
+
|
|
30188
|
+
colors = [];
|
|
30189
|
+
pntsCA = [];
|
|
30190
|
+
prevCOArray = [];
|
|
30191
|
+
bShowArray = [];
|
|
30192
|
+
calphaIdArray = [];
|
|
30193
|
+
bSheetSegment = false;
|
|
30194
|
+
bHelixSegment = false;
|
|
30195
|
+
} // end if (atom.ssbegin || atom.ssend)
|
|
29941
30196
|
|
|
29942
|
-
//
|
|
29943
|
-
|
|
30197
|
+
// end of a chain
|
|
30198
|
+
// if ((currentChain !== atom.chain || currentResi + 1 !== atom.resi) && pnts[0].length > 0) {
|
|
30199
|
+
if ((currentChain !== atom.chain) && pnts[0].length > 0) {
|
|
29944
30200
|
|
|
29945
|
-
|
|
29946
|
-
radii.push(radiusFinal);
|
|
30201
|
+
let atomName = 'CA';
|
|
29947
30202
|
|
|
29948
|
-
|
|
29949
|
-
|
|
29950
|
-
|
|
30203
|
+
let prevone = [], nexttwo = [];
|
|
30204
|
+
if(isNaN(ic.atoms[prevAtomid].resi)) {
|
|
30205
|
+
prevone = [];
|
|
30206
|
+
}
|
|
30207
|
+
else {
|
|
30208
|
+
let prevoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) - 1).toString();
|
|
30209
|
+
ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
|
|
30210
|
+
}
|
|
29951
30211
|
|
|
29952
|
-
|
|
29953
|
-
|
|
30212
|
+
for (let j = 0; !fill && j < num; ++j) {
|
|
30213
|
+
if(bSheetSegment) {
|
|
30214
|
+
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
30215
|
+
}
|
|
30216
|
+
else if(bHelixSegment) {
|
|
30217
|
+
if(bFullAtom) {
|
|
30218
|
+
ic.curveCls.createCurveSub(pnts[j], 1, colors, div, bHighlight, bRibbon, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo);
|
|
30219
|
+
}
|
|
30220
|
+
else {
|
|
30221
|
+
ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
30222
|
+
}
|
|
30223
|
+
}
|
|
30224
|
+
}
|
|
30225
|
+
if (fill) {
|
|
30226
|
+
if(bSheetSegment) {
|
|
30227
|
+
let start = 0, end = num - 1;
|
|
30228
|
+
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
|
|
30229
|
+
}
|
|
30230
|
+
else if(bHelixSegment) {
|
|
30231
|
+
if(bFullAtom) {
|
|
30232
|
+
ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
|
|
30233
|
+
}
|
|
30234
|
+
else {
|
|
30235
|
+
let start = 0, end = num - 1;
|
|
30236
|
+
ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
|
|
30237
|
+
}
|
|
30238
|
+
}
|
|
30239
|
+
}
|
|
29954
30240
|
|
|
29955
|
-
|
|
29956
|
-
|
|
29957
|
-
|
|
30241
|
+
for (let k = 0; k < num; ++k) pnts[k] = [];
|
|
30242
|
+
colors = [];
|
|
30243
|
+
pntsCA = [];
|
|
30244
|
+
prevCOArray = [];
|
|
30245
|
+
bShowArray = [];
|
|
30246
|
+
calphaIdArray = [];
|
|
30247
|
+
bSheetSegment = false;
|
|
30248
|
+
bHelixSegment = false;
|
|
29958
30249
|
}
|
|
29959
30250
|
|
|
29960
|
-
|
|
30251
|
+
currentChain = atom.chain;
|
|
30252
|
+
ss = atom.ss;
|
|
30253
|
+
ssend = atom.ssend;
|
|
30254
|
+
prevAtomid = atom.serial;
|
|
30255
|
+
prevResi = atom.resi;
|
|
29961
30256
|
|
|
29962
|
-
|
|
29963
|
-
}
|
|
29964
|
-
}
|
|
30257
|
+
prevCalphaid = calphaid;
|
|
29965
30258
|
|
|
29966
|
-
|
|
29967
|
-
|
|
29968
|
-
|
|
30259
|
+
// only update when atom.name === 'O'
|
|
30260
|
+
prevCoorCA = currentCA;
|
|
30261
|
+
prevCoorO = atom.coord;
|
|
30262
|
+
prevColor = currentColor;
|
|
30263
|
+
} // end if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA') ) {
|
|
30264
|
+
} // end if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
|
|
30265
|
+
} // end for
|
|
29969
30266
|
|
|
29970
|
-
|
|
29971
|
-
let pnts = pnts_colors_radii_prevone_nexttwo[i].pnts;
|
|
29972
|
-
let colors = pnts_colors_radii_prevone_nexttwo[i].colors;
|
|
29973
|
-
let radii = pnts_colors_radii_prevone_nexttwo[i].radii;
|
|
29974
|
-
let prevone = []; // = pnts_colors_radii_prevone_nexttwo[i].prevone;
|
|
29975
|
-
let nexttwo = []; // = pnts_colors_radii_prevone_nexttwo[i].nexttwo;
|
|
30267
|
+
caArray = [];
|
|
29976
30268
|
|
|
29977
|
-
|
|
29978
|
-
}
|
|
30269
|
+
ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight);
|
|
29979
30270
|
|
|
29980
|
-
|
|
30271
|
+
tubeAtoms = {};
|
|
30272
|
+
pnts = {};
|
|
29981
30273
|
}
|
|
29982
|
-
*/
|
|
29983
|
-
|
|
29984
|
-
getCustomtubesize(resid) { let ic = this.icn3d; ic.icn3dui;
|
|
29985
|
-
let pos = resid.lastIndexOf('_');
|
|
29986
|
-
let resi = resid.substr(pos + 1);
|
|
29987
|
-
let chainid = resid.substr(0, pos);
|
|
29988
30274
|
|
|
29989
|
-
|
|
29990
|
-
|
|
29991
|
-
|
|
29992
|
-
|
|
29993
|
-
|
|
29994
|
-
// modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
29995
|
-
createTubeSub(_pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
|
|
29996
|
-
if(me.bNode) return;
|
|
29997
|
-
|
|
29998
|
-
if (_pnts.length < 2) return;
|
|
29999
|
-
|
|
30000
|
-
let circleDiv = ic.tubeDIV, axisDiv = ic.axisDIV;
|
|
30001
|
-
let circleDivInv = 1 / circleDiv, axisDivInv = 1 / axisDiv;
|
|
30002
|
-
//var geo = new THREE.Geometry();
|
|
30003
|
-
let geo = new THREE.BufferGeometry();
|
|
30004
|
-
let verticeArray = [], colorArray = [],indexArray = [], color;
|
|
30005
|
-
let offset = 0, offset2 = 0, offset3 = 0;
|
|
30275
|
+
getSSExpandedAtoms(atoms, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
|
|
30276
|
+
let currChain, currResi, currAtom, prevChain, prevResi, prevAtom;
|
|
30277
|
+
let firstAtom, lastAtom;
|
|
30278
|
+
let index = 0, length = Object.keys(atoms).length;
|
|
30006
30279
|
|
|
30007
|
-
let
|
|
30280
|
+
let atomsAdjust = me.hashUtilsCls.cloneHash(atoms);
|
|
30281
|
+
for(let serial in atoms) {
|
|
30282
|
+
currChain = atoms[serial].structure + '_' + atoms[serial].chain;
|
|
30283
|
+
currResi = atoms[serial].resi; //parseInt(atoms[serial].resi);
|
|
30284
|
+
currAtom = atoms[serial];
|
|
30008
30285
|
|
|
30009
|
-
|
|
30010
|
-
colors = pnts_clrs[2];
|
|
30286
|
+
if(prevChain === undefined) firstAtom = atoms[serial];
|
|
30011
30287
|
|
|
30012
|
-
|
|
30013
|
-
|
|
30014
|
-
|
|
30288
|
+
if( (currChain !== prevChain && prevChain !== undefined)
|
|
30289
|
+
|| (currResi !== prevResi && currResi !== parseInt(prevResi) + 1 && prevResi !== undefined) || index === length - 1) {
|
|
30290
|
+
if( (currChain !== prevChain && prevChain !== undefined)
|
|
30291
|
+
|| (currResi !== prevResi && currResi !== parseInt(prevResi) + 1 && prevResi !== undefined) ) {
|
|
30292
|
+
lastAtom = prevAtom;
|
|
30293
|
+
}
|
|
30294
|
+
else if(index === length - 1) {
|
|
30295
|
+
lastAtom = currAtom;
|
|
30296
|
+
}
|
|
30015
30297
|
|
|
30016
|
-
|
|
30017
|
-
|
|
30018
|
-
|
|
30298
|
+
// fill the beginning
|
|
30299
|
+
let beginResi = firstAtom.resi;
|
|
30300
|
+
if(!isNaN(firstAtom.resi) && firstAtom.ss !== 'coil' && !(firstAtom.ssbegin) ) {
|
|
30301
|
+
for(let i = parseInt(firstAtom.resi) - 1; i > 0; --i) {
|
|
30302
|
+
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + i;
|
|
30303
|
+
if(!ic.residues.hasOwnProperty(residueid)) break;
|
|
30019
30304
|
|
|
30020
|
-
|
|
30021
|
-
r = radii[0];
|
|
30022
|
-
if(r > 0) constRadiius = r;
|
|
30023
|
-
}
|
|
30024
|
-
else {
|
|
30025
|
-
if (idx % 1 === 0) {
|
|
30026
|
-
r = radii[idx];
|
|
30027
|
-
if(r > 0) constRadiius = r;
|
|
30028
|
-
}
|
|
30029
|
-
else {
|
|
30030
|
-
let floored = Math.floor(idx);
|
|
30031
|
-
let tmp = idx - floored;
|
|
30032
|
-
// draw all atoms in tubes and assign zero radius when the residue is not coil
|
|
30033
|
-
// r = radii[floored] * tmp + radii[floored + 1] * (1 - tmp);
|
|
30034
|
-
r = radii[floored] * (1 - tmp) + radii[floored + 1] * tmp;
|
|
30305
|
+
let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[residueid]);
|
|
30035
30306
|
|
|
30036
|
-
|
|
30037
|
-
|
|
30038
|
-
|
|
30039
|
-
if(r < thresholdRatio * constRadiius) {
|
|
30040
|
-
r = 0;
|
|
30041
|
-
}
|
|
30042
|
-
// else if(r < constRadiius) {
|
|
30043
|
-
// r *= 0.5; // use small radius for the connection between coild and sheets/helices
|
|
30044
|
-
// }
|
|
30307
|
+
if(atom.ss === firstAtom.ss && atom.ssbegin) {
|
|
30308
|
+
beginResi = atom.resi;
|
|
30309
|
+
break;
|
|
30045
30310
|
}
|
|
30046
30311
|
}
|
|
30047
|
-
|
|
30048
|
-
|
|
30049
|
-
|
|
30050
|
-
|
|
30051
|
-
|
|
30052
|
-
axis2 = delta.clone().cross(axis1).normalize().multiplyScalar(r);
|
|
30053
|
-
// let dir = 1, offset = 0;
|
|
30054
|
-
if (prevAxis1.dot(axis1) < 0) {
|
|
30055
|
-
axis1.negate(); axis2.negate(); //dir = -1;//offset = 2 * Math.PI / axisDiv;
|
|
30312
|
+
|
|
30313
|
+
for(let i = beginResi; i < firstAtom.resi; ++i) {
|
|
30314
|
+
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + i;
|
|
30315
|
+
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
30316
|
+
ic.atoms));
|
|
30056
30317
|
}
|
|
30057
|
-
prevAxis1 = axis1; prevAxis2 = axis2;
|
|
30058
|
-
} else {
|
|
30059
|
-
axis1 = prevAxis1; axis2 = prevAxis2;
|
|
30060
30318
|
}
|
|
30061
|
-
for (let j = 0; j < circleDiv; ++j) {
|
|
30062
|
-
let angle = 2 * Math.PI * circleDivInv * j; //* dir + offset;
|
|
30063
|
-
let point = pnts[i].clone().add(axis1.clone().multiplyScalar(Math.cos(angle))).add(axis2.clone().multiplyScalar(Math.sin(angle)));
|
|
30064
|
-
verticeArray[offset++] = point.x;
|
|
30065
|
-
verticeArray[offset++] = point.y;
|
|
30066
|
-
verticeArray[offset++] = point.z;
|
|
30067
30319
|
|
|
30068
|
-
|
|
30069
|
-
|
|
30070
|
-
|
|
30071
|
-
|
|
30320
|
+
// add one extra residue for coils between strands/helix
|
|
30321
|
+
if(!isNaN(firstAtom.resi) && ic.pk === 3 && bHighlight === 1 && firstAtom.ss === 'coil') {
|
|
30322
|
+
let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
|
|
30323
|
+
if(ic.residues.hasOwnProperty(residueid)) {
|
|
30324
|
+
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
30325
|
+
ic.atoms));
|
|
30326
|
+
atoms = me.hashUtilsCls.unionHash(atoms, me.hashUtilsCls.hash2Atoms(ic.residues[residueid], ic.atoms));
|
|
30327
|
+
}
|
|
30072
30328
|
}
|
|
30073
|
-
}
|
|
30074
|
-
let offsetTmp = 0, nComp = 3;
|
|
30075
|
-
for (let i = 0, lim = pnts.length - 1; i < lim; ++i) {
|
|
30076
|
-
let reg = 0;
|
|
30077
|
-
//var r1 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv]).lengthSq();
|
|
30078
|
-
//var r2 = geo.vertices[offset].clone().sub(geo.vertices[offset + circleDiv + 1]).lengthSq();
|
|
30079
|
-
let pos = offsetTmp * nComp;
|
|
30080
|
-
let point1 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
30081
|
-
pos = (offsetTmp + circleDiv) * nComp;
|
|
30082
|
-
let point2 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
30083
|
-
pos = (offsetTmp + circleDiv + 1) * nComp;
|
|
30084
|
-
let point3 = new THREE.Vector3(verticeArray[pos], verticeArray[pos + 1], verticeArray[pos + 2]);
|
|
30085
30329
|
|
|
30086
|
-
|
|
30087
|
-
let
|
|
30088
|
-
|
|
30089
|
-
//geo.faces.push(new THREE.Face3(offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv, undefined, c));
|
|
30090
|
-
//geo.faces.push(new THREE.Face3(offset + (j + 1) % circleDiv, offset + (j + reg) % circleDiv + circleDiv, offset + (j + reg + 1) % circleDiv + circleDiv, undefined, c));
|
|
30091
|
-
//indexArray = indexArray.concat([offset + j, offset + (j + reg) % circleDiv + circleDiv, offset + (j + 1) % circleDiv]);
|
|
30092
|
-
indexArray[offset3++] = offsetTmp + j;
|
|
30093
|
-
indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
|
|
30094
|
-
indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
|
|
30330
|
+
// fill the end
|
|
30331
|
+
let endResi = lastAtom.resi;
|
|
30332
|
+
// when a coil connects to a sheet and the last residue of coil is highlighted, the first sheet residue is set as atom.notshow. This residue should not be shown.
|
|
30095
30333
|
|
|
30096
|
-
|
|
30097
|
-
indexArray[offset3++] = offsetTmp + (j + 1) % circleDiv;
|
|
30098
|
-
indexArray[offset3++] = offsetTmp + (j + reg) % circleDiv + circleDiv;
|
|
30099
|
-
indexArray[offset3++] = offsetTmp + (j + reg + 1) % circleDiv + circleDiv;
|
|
30100
|
-
}
|
|
30101
|
-
offsetTmp += circleDiv;
|
|
30102
|
-
}
|
|
30334
|
+
if(lastAtom.ss !== undefined && lastAtom.ss !== 'coil' && !(lastAtom.ssend) && !(lastAtom.notshow)) {
|
|
30103
30335
|
|
|
30104
|
-
|
|
30105
|
-
|
|
30336
|
+
let endChainResi = ic.firstAtomObjCls.getLastAtomObj(ic.chains[lastAtom.structure + '_' + lastAtom.chain]).resi;
|
|
30337
|
+
for(let i = parseInt(lastAtom.resi) + 1; i <= parseInt(endChainResi); ++i) {
|
|
30338
|
+
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + i;
|
|
30339
|
+
if(!ic.residues.hasOwnProperty(residueid)) break;
|
|
30106
30340
|
|
|
30107
|
-
|
|
30108
|
-
//geo.setIndex(indexArray);
|
|
30341
|
+
let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[residueid]);
|
|
30109
30342
|
|
|
30110
|
-
|
|
30111
|
-
|
|
30112
|
-
|
|
30343
|
+
if(atom.ss === lastAtom.ss && atom.ssend) {
|
|
30344
|
+
endResi = atom.resi;
|
|
30345
|
+
break;
|
|
30346
|
+
}
|
|
30347
|
+
}
|
|
30113
30348
|
|
|
30114
|
-
|
|
30115
|
-
|
|
30116
|
-
|
|
30117
|
-
|
|
30349
|
+
for(let i = parseInt(lastAtom.resi) + 1; i <= parseInt(endResi); ++i) {
|
|
30350
|
+
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + i;
|
|
30351
|
+
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
30352
|
+
ic.atoms));
|
|
30353
|
+
}
|
|
30354
|
+
}
|
|
30118
30355
|
|
|
30119
|
-
|
|
30120
|
-
|
|
30121
|
-
|
|
30122
|
-
|
|
30123
|
-
|
|
30124
|
-
|
|
30125
|
-
|
|
30126
|
-
|
|
30127
|
-
|
|
30128
|
-
//mesh = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({ specular: ic.frac, shininess: ic.shininess, emissive: ic.emissive, vertexColors: THREE.FaceColors, side: THREE.DoubleSide }));
|
|
30129
|
-
mesh = new THREE.Mesh(geo, new THREE.MeshPhongMaterial({ specular: ic.frac, shininess: ic.shininess, emissive: ic.emissive, vertexColors: true, side: THREE.DoubleSide }));
|
|
30356
|
+
// add one extra residue for coils between strands/helix
|
|
30357
|
+
if(ic.pk === 3 && bHighlight === 1 && lastAtom.ss === 'coil') {
|
|
30358
|
+
let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + (parseInt(lastAtom.resi) + 1).toString();
|
|
30359
|
+
if(ic.residues.hasOwnProperty(residueid)) {
|
|
30360
|
+
atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
|
|
30361
|
+
ic.atoms));
|
|
30362
|
+
atoms = me.hashUtilsCls.unionHash(atoms, me.hashUtilsCls.hash2Atoms(ic.residues[residueid], ic.atoms));
|
|
30363
|
+
}
|
|
30364
|
+
}
|
|
30130
30365
|
|
|
30131
|
-
|
|
30132
|
-
|
|
30366
|
+
// reset notshow
|
|
30367
|
+
if(lastAtom.notshow) lastAtom.notshow = undefined;
|
|
30133
30368
|
|
|
30134
|
-
|
|
30135
|
-
|
|
30136
|
-
}
|
|
30137
|
-
else {
|
|
30138
|
-
ic.objects.push(mesh);
|
|
30139
|
-
}
|
|
30140
|
-
}
|
|
30369
|
+
firstAtom = currAtom;
|
|
30370
|
+
}
|
|
30141
30371
|
|
|
30142
|
-
|
|
30143
|
-
|
|
30144
|
-
|
|
30145
|
-
|
|
30146
|
-
|
|
30147
|
-
else {
|
|
30148
|
-
if(atom.b > 0 && atom.b <= 100) {
|
|
30149
|
-
radiusFinal = atom.b * 0.01;
|
|
30150
|
-
}
|
|
30151
|
-
else if(atom.b > 100) {
|
|
30152
|
-
radiusFinal = 100 * 0.01;
|
|
30153
|
-
}
|
|
30154
|
-
else {
|
|
30155
|
-
radiusFinal = ic.coilWidth;
|
|
30156
|
-
}
|
|
30372
|
+
prevChain = currChain;
|
|
30373
|
+
prevResi = currResi;
|
|
30374
|
+
prevAtom = currAtom;
|
|
30375
|
+
|
|
30376
|
+
++index;
|
|
30157
30377
|
}
|
|
30158
30378
|
|
|
30159
|
-
return
|
|
30379
|
+
return atomsAdjust;
|
|
30160
30380
|
}
|
|
30161
30381
|
}
|
|
30162
30382
|
|
|
@@ -47810,6 +48030,13 @@ class ShowAnno {
|
|
|
47810
48030
|
} // align seq to structure
|
|
47811
48031
|
}
|
|
47812
48032
|
//ic.bAnnoShown = true;
|
|
48033
|
+
|
|
48034
|
+
if($("#" + ic.pre + "anno_ig").length && $("#" + ic.pre + "anno_ig")[0].checked) {
|
|
48035
|
+
ic.bRunRefnumAgain = true;
|
|
48036
|
+
await ic.annotationCls.setAnnoTabIg();
|
|
48037
|
+
|
|
48038
|
+
ic.bRunRefnumAgain = false;
|
|
48039
|
+
}
|
|
47813
48040
|
}
|
|
47814
48041
|
|
|
47815
48042
|
async showAnnoSeqData(nucleotide_chainid, chemical_chainid, chemical_set) { let ic = this.icn3d, me = ic.icn3dui;
|
|
@@ -53544,6 +53771,7 @@ class AlignParser {
|
|
|
53544
53771
|
|
|
53545
53772
|
async downloadAlignmentPart2(data, seqalign, chainresiCalphaHash2) { let ic = this.icn3d, me = ic.icn3dui;
|
|
53546
53773
|
//ic.init();
|
|
53774
|
+
|
|
53547
53775
|
ic.loadAtomDataCls.loadAtomDataIn(data, undefined, 'align', seqalign);
|
|
53548
53776
|
|
|
53549
53777
|
if(me.cfg.align === undefined && Object.keys(ic.structures).length == 1) {
|
|
@@ -53587,20 +53815,21 @@ class AlignParser {
|
|
|
53587
53815
|
async loadOpmDataForAlign(data, seqalign, mmdbidArray) { let ic = this.icn3d, me = ic.icn3dui;
|
|
53588
53816
|
let thisClass = this;
|
|
53589
53817
|
|
|
53590
|
-
let url = "https://opm-assets.storage.googleapis.com/pdb/" + mmdbidArray[0].toLowerCase()+ ".pdb";
|
|
53591
|
-
let prms1 = me.getAjaxPromise(url, 'text');
|
|
53592
|
-
let url2 = "https://opm-assets.storage.googleapis.com/pdb/" + mmdbidArray[1].toLowerCase()+ ".pdb";
|
|
53593
|
-
let prms2 = me.getAjaxPromise(url2, 'text');
|
|
53594
|
-
|
|
53595
|
-
let allPromise = Promise.allSettled([prms1, prms2]);
|
|
53596
53818
|
try {
|
|
53819
|
+
let url = "https://opm-assets.storage.googleapis.com/pdb/" + mmdbidArray[0].toLowerCase()+ ".pdb";
|
|
53820
|
+
let prms1 = me.getAjaxPromise(url, 'text');
|
|
53821
|
+
let url2 = "https://opm-assets.storage.googleapis.com/pdb/" + mmdbidArray[1].toLowerCase()+ ".pdb";
|
|
53822
|
+
let prms2 = me.getAjaxPromise(url2, 'text');
|
|
53823
|
+
|
|
53824
|
+
let allPromise = Promise.allSettled([prms1, prms2]);
|
|
53825
|
+
|
|
53597
53826
|
let dataArray = await allPromise;
|
|
53598
|
-
|
|
53827
|
+
|
|
53599
53828
|
let bFound = false;
|
|
53600
53829
|
for(let i = 0, il = dataArray.length; i < il; ++i) {
|
|
53601
|
-
//
|
|
53602
|
-
let opmdata = dataArray[i].value;
|
|
53830
|
+
// if(dataArray[i].status == 'rejected') continue;
|
|
53603
53831
|
|
|
53832
|
+
let opmdata = dataArray[i].value;
|
|
53604
53833
|
if(!opmdata) continue;
|
|
53605
53834
|
|
|
53606
53835
|
ic.selectedPdbid = mmdbidArray[i];
|
|
@@ -53616,6 +53845,7 @@ class AlignParser {
|
|
|
53616
53845
|
$("#" + ic.pre + "intra_mem_z").val(-ic.halfBilayerSize);
|
|
53617
53846
|
|
|
53618
53847
|
ic.init(); // remove all previously loaded data
|
|
53848
|
+
|
|
53619
53849
|
await thisClass.downloadAlignmentPart2(data, seqalign, chainresiCalphaHash);
|
|
53620
53850
|
|
|
53621
53851
|
bFound = true;
|
|
@@ -58191,7 +58421,7 @@ class SdfParser {
|
|
|
58191
58421
|
let sdfStr = await me.getAjaxPromise(urlSmiles, 'text');
|
|
58192
58422
|
|
|
58193
58423
|
ic.init();
|
|
58194
|
-
ic.bInputfile = true;
|
|
58424
|
+
//ic.bInputfile = true;
|
|
58195
58425
|
ic.InputfileData = (ic.InputfileData) ? ic.InputfileData + '\nENDMDL\n' + sdfStr : sdfStr;
|
|
58196
58426
|
ic.InputfileType = 'sdf';
|
|
58197
58427
|
await ic.sdfParserCls.loadSdfData(sdfStr);
|
|
@@ -61000,6 +61230,7 @@ class ParserUtils {
|
|
|
61000
61230
|
ic.selectionCls.oneStructurePerWindow(); // for alignment
|
|
61001
61231
|
ic.drawCls.draw();
|
|
61002
61232
|
}
|
|
61233
|
+
|
|
61003
61234
|
if(ic.bOpm) {
|
|
61004
61235
|
let axis = new THREE.Vector3(1,0,0);
|
|
61005
61236
|
let angle = -0.5 * Math.PI;
|
|
@@ -63537,7 +63768,8 @@ class LoadPDB {
|
|
|
63537
63768
|
|
|
63538
63769
|
// modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
|
|
63539
63770
|
//This PDB parser feeds the viewer with the content of a PDB file, pdbData.
|
|
63540
|
-
async loadPDB(src, pdbid, bOpm, bVector, bMutation, bAppend, type, bEsmfold) { let ic = this.icn3d, me = ic.icn3dui;
|
|
63771
|
+
// async loadPDB(src, pdbid, bOpm, bVector, bMutation, bAppend, type, bEsmfold) { let ic = this.icn3d, me = ic.icn3dui;
|
|
63772
|
+
loadPDB(src, pdbid, bOpm, bVector, bMutation, bAppend, type, bEsmfold) { let ic = this.icn3d, me = ic.icn3dui;
|
|
63541
63773
|
let hAtoms = {};
|
|
63542
63774
|
|
|
63543
63775
|
let bNMR = false;
|
|
@@ -68658,17 +68890,15 @@ class SelectCollections {
|
|
|
68658
68890
|
}
|
|
68659
68891
|
|
|
68660
68892
|
//Set the menu of defined sets with an array of defined names "commandnameArray".
|
|
68661
|
-
setAtomMenu(
|
|
68893
|
+
setAtomMenu(collection) {
|
|
68662
68894
|
let ic = this.icn3d;
|
|
68663
68895
|
ic.icn3dui;
|
|
68664
68896
|
let html = "";
|
|
68665
|
-
|
|
68666
|
-
|
|
68667
|
-
let name = nameArray[i][0];
|
|
68668
|
-
let title = nameArray[i][1];
|
|
68669
|
-
let description = nameArray[i][2];
|
|
68670
|
-
|
|
68897
|
+
|
|
68898
|
+
Object.entries(collection).forEach(([name, structure], index) => {
|
|
68671
68899
|
let atomHash;
|
|
68900
|
+
let [id, title, description, commands, pdb] = structure;
|
|
68901
|
+
|
|
68672
68902
|
if (
|
|
68673
68903
|
ic.defNames2Atoms !== undefined &&
|
|
68674
68904
|
ic.defNames2Atoms.hasOwnProperty(name)
|
|
@@ -68689,12 +68919,12 @@ class SelectCollections {
|
|
|
68689
68919
|
}
|
|
68690
68920
|
}
|
|
68691
68921
|
|
|
68692
|
-
if (
|
|
68693
|
-
html += "<option value='" +
|
|
68694
|
-
|
|
68922
|
+
if (index === 0) {
|
|
68923
|
+
html += "<option value='" + name + "' selected='selected' data-description='" + description + "'>" + title + "</option>";
|
|
68924
|
+
} else {
|
|
68695
68925
|
html += "<option value='" + name + "' data-description='" + description + "'>" + title + "</option>";
|
|
68696
|
-
|
|
68697
|
-
}
|
|
68926
|
+
}
|
|
68927
|
+
});
|
|
68698
68928
|
|
|
68699
68929
|
return html;
|
|
68700
68930
|
}
|
|
@@ -68748,7 +68978,7 @@ class SelectCollections {
|
|
|
68748
68978
|
let nameArray = $(this).val();
|
|
68749
68979
|
let nameStructure = $(this).find("option:selected").text();
|
|
68750
68980
|
let selectedIndices = Array.from(this.selectedOptions).map(option => option.index);
|
|
68751
|
-
|
|
68981
|
+
nameArray.reduce((map, name, i) => {
|
|
68752
68982
|
map[name] = selectedIndices[i];
|
|
68753
68983
|
return map;
|
|
68754
68984
|
}, {});
|
|
@@ -68785,13 +69015,13 @@ class SelectCollections {
|
|
|
68785
69015
|
if (Object.keys(ic.structures).length == 0) {
|
|
68786
69016
|
bAppend = false;
|
|
68787
69017
|
}
|
|
68788
|
-
await ic.pdbParserCls.loadPdbData(ic.pdbCollection[
|
|
69018
|
+
await ic.pdbParserCls.loadPdbData(ic.pdbCollection[name].join('\n'), undefined, undefined, bAppend);
|
|
68789
69019
|
} else {
|
|
68790
69020
|
await ic.chainalignParserCls.downloadMmdbAf(name, undefined, undefined, bNoDuplicate);
|
|
68791
69021
|
}
|
|
68792
69022
|
}
|
|
68793
69023
|
|
|
68794
|
-
await loadStructure(collection[
|
|
69024
|
+
await loadStructure(collection[name][4]).then(() => {
|
|
68795
69025
|
ic.allData['all'] = {
|
|
68796
69026
|
'atoms': ic.atoms,
|
|
68797
69027
|
'proteins': ic.proteins,
|
|
@@ -68851,9 +69081,9 @@ class SelectCollections {
|
|
|
68851
69081
|
|
|
68852
69082
|
ic.molTitle = ic.allData[name]['title'];
|
|
68853
69083
|
|
|
68854
|
-
if (collection[
|
|
69084
|
+
if (collection[name][3] !== undefined && collection[name][3].length > 0) {
|
|
68855
69085
|
if (ic.allData[name]['commands'] == undefined) {
|
|
68856
|
-
let commands = collection[
|
|
69086
|
+
let commands = collection[name][3];
|
|
68857
69087
|
ic.allData[name]['commands'] = commands;
|
|
68858
69088
|
}
|
|
68859
69089
|
}
|
|
@@ -71495,155 +71725,6 @@ class Resid2spec {
|
|
|
71495
71725
|
}
|
|
71496
71726
|
}
|
|
71497
71727
|
|
|
71498
|
-
/**
|
|
71499
|
-
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
71500
|
-
*/
|
|
71501
|
-
|
|
71502
|
-
class FirstAtomObj {
|
|
71503
|
-
constructor(icn3d) {
|
|
71504
|
-
this.icn3d = icn3d;
|
|
71505
|
-
}
|
|
71506
|
-
|
|
71507
|
-
//Return the first atom in the atom hash, which has the atom serial number as the key.
|
|
71508
|
-
getFirstAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
71509
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
71510
|
-
return undefined;
|
|
71511
|
-
}
|
|
71512
|
-
|
|
71513
|
-
let atomKeys = Object.keys(atomsHash);
|
|
71514
|
-
let firstIndex = atomKeys[0];
|
|
71515
|
-
|
|
71516
|
-
return ic.atoms[firstIndex];
|
|
71517
|
-
}
|
|
71518
|
-
|
|
71519
|
-
// n is the position of the selected atom
|
|
71520
|
-
getMiddleAtomObj(atomsHash, n) { let ic = this.icn3d; ic.icn3dui;
|
|
71521
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
71522
|
-
return undefined;
|
|
71523
|
-
}
|
|
71524
|
-
|
|
71525
|
-
let atomKeys = Object.keys(atomsHash);
|
|
71526
|
-
let middleIndex = (n && n < atomKeys.length) ? atomKeys[n] : atomKeys[parseInt(atomKeys.length / 2)];
|
|
71527
|
-
|
|
71528
|
-
return ic.atoms[middleIndex];
|
|
71529
|
-
}
|
|
71530
|
-
|
|
71531
|
-
getFirstCalphaAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
71532
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
71533
|
-
return undefined;
|
|
71534
|
-
}
|
|
71535
|
-
|
|
71536
|
-
let firstIndex;
|
|
71537
|
-
|
|
71538
|
-
for(let i in atomsHash) {
|
|
71539
|
-
if(ic.atoms[i].name == 'CA') {
|
|
71540
|
-
firstIndex = i;
|
|
71541
|
-
break;
|
|
71542
|
-
}
|
|
71543
|
-
}
|
|
71544
|
-
|
|
71545
|
-
if(!firstIndex) {
|
|
71546
|
-
for(let i in atomsHash) {
|
|
71547
|
-
if(ic.atoms[i].name == "O3'" || ic.atoms[i].name == "O3*") {
|
|
71548
|
-
firstIndex = i;
|
|
71549
|
-
break;
|
|
71550
|
-
}
|
|
71551
|
-
}
|
|
71552
|
-
}
|
|
71553
|
-
|
|
71554
|
-
return (firstIndex !== undefined) ? ic.atoms[firstIndex] : this.getFirstAtomObj(atomsHash);
|
|
71555
|
-
}
|
|
71556
|
-
|
|
71557
|
-
getFirstAtomObjByName(atomsHash, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
71558
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
71559
|
-
return ic.atoms[0];
|
|
71560
|
-
}
|
|
71561
|
-
|
|
71562
|
-
let firstIndex;
|
|
71563
|
-
|
|
71564
|
-
for(let i in atomsHash) {
|
|
71565
|
-
if(ic.atoms[i].name == atomName) {
|
|
71566
|
-
firstIndex = i;
|
|
71567
|
-
break;
|
|
71568
|
-
}
|
|
71569
|
-
}
|
|
71570
|
-
|
|
71571
|
-
return (firstIndex !== undefined) ? ic.atoms[firstIndex] : undefined;
|
|
71572
|
-
}
|
|
71573
|
-
|
|
71574
|
-
//Return the last atom in the atom hash, which has the atom serial number as the key.
|
|
71575
|
-
getLastAtomObj(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
71576
|
-
if(atomsHash === undefined || Object.keys(atomsHash).length === 0) {
|
|
71577
|
-
return ic.atoms[0];
|
|
71578
|
-
}
|
|
71579
|
-
|
|
71580
|
-
let atomKeys = Object.keys(atomsHash);
|
|
71581
|
-
let lastIndex = atomKeys[atomKeys.length - 1];
|
|
71582
|
-
|
|
71583
|
-
return ic.atoms[lastIndex];
|
|
71584
|
-
}
|
|
71585
|
-
|
|
71586
|
-
//Return the residue hash from the atom hash. The residue hash has the resid as the key and 1 as the value.
|
|
71587
|
-
getResiduesFromAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
71588
|
-
let residuesHash = {};
|
|
71589
|
-
for(let i in atomsHash) {
|
|
71590
|
-
let residueid = ic.atoms[i].structure + '_' + ic.atoms[i].chain + '_' + ic.atoms[i].resi;
|
|
71591
|
-
residuesHash[residueid] = 1;
|
|
71592
|
-
}
|
|
71593
|
-
|
|
71594
|
-
return residuesHash;
|
|
71595
|
-
}
|
|
71596
|
-
|
|
71597
|
-
getResiduesFromCalphaAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
71598
|
-
let residuesHash = {};
|
|
71599
|
-
for(let i in atomsHash) {
|
|
71600
|
-
if((ic.atoms[i].name == 'CA' && ic.proteins.hasOwnProperty(i)) || !ic.proteins.hasOwnProperty(i)) {
|
|
71601
|
-
let residueid = ic.atoms[i].structure + '_' + ic.atoms[i].chain + '_' + ic.atoms[i].resi;
|
|
71602
|
-
//residuesHash[residueid] = 1;
|
|
71603
|
-
residuesHash[residueid] = ic.atoms[i].resn;
|
|
71604
|
-
}
|
|
71605
|
-
}
|
|
71606
|
-
|
|
71607
|
-
return residuesHash;
|
|
71608
|
-
}
|
|
71609
|
-
|
|
71610
|
-
//Return the chain hash from the atom hash. The chain hash has the chainid as the key and 1 as the value.
|
|
71611
|
-
getChainsFromAtoms(atomsHash) { let ic = this.icn3d; ic.icn3dui;
|
|
71612
|
-
let chainsHash = {};
|
|
71613
|
-
for(let i in atomsHash) {
|
|
71614
|
-
let atom = ic.atoms[i];
|
|
71615
|
-
let chainid = atom.structure + "_" + atom.chain;
|
|
71616
|
-
|
|
71617
|
-
chainsHash[chainid] = 1;
|
|
71618
|
-
}
|
|
71619
|
-
|
|
71620
|
-
return chainsHash;
|
|
71621
|
-
}
|
|
71622
|
-
|
|
71623
|
-
getAtomFromResi(resid, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
71624
|
-
if(ic.residues.hasOwnProperty(resid)) {
|
|
71625
|
-
for(let i in ic.residues[resid]) {
|
|
71626
|
-
if(ic.atoms[i].name === atomName && !ic.atoms[i].het) {
|
|
71627
|
-
return ic.atoms[i];
|
|
71628
|
-
}
|
|
71629
|
-
}
|
|
71630
|
-
}
|
|
71631
|
-
|
|
71632
|
-
return undefined;
|
|
71633
|
-
}
|
|
71634
|
-
|
|
71635
|
-
getAtomCoordFromResi(resid, atomName) { let ic = this.icn3d; ic.icn3dui;
|
|
71636
|
-
let atom = this.getAtomFromResi(resid, atomName);
|
|
71637
|
-
if(atom !== undefined) {
|
|
71638
|
-
let coord = (atom.coord2 !== undefined) ? atom.coord2 : atom.coord;
|
|
71639
|
-
|
|
71640
|
-
return coord;
|
|
71641
|
-
}
|
|
71642
|
-
|
|
71643
|
-
return undefined;
|
|
71644
|
-
}
|
|
71645
|
-
}
|
|
71646
|
-
|
|
71647
71728
|
/**
|
|
71648
71729
|
* @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
|
|
71649
71730
|
*/
|
|
@@ -71704,9 +71785,9 @@ class Delphi {
|
|
|
71704
71785
|
let pdbstr = '';
|
|
71705
71786
|
/// pdbstr += ic.saveFileCls.getPDBHeader();
|
|
71706
71787
|
|
|
71707
|
-
let bMergeIntoOne = true;
|
|
71708
|
-
pdbstr +=(me.cfg.cid) ? ic.saveFileCls.getAtomPDB(atomHash, true, undefined, undefined, undefined, undefined, bMergeIntoOne) : ic.saveFileCls.getAtomPDB(atomHash, undefined, undefined, undefined, undefined, undefined, bMergeIntoOne);
|
|
71709
|
-
pdbstr += ic.saveFileCls.getAtomPDB(ionHash, true, undefined, true);
|
|
71788
|
+
let bMergeIntoOne = true, bOneLetterChain = true;
|
|
71789
|
+
pdbstr +=(me.cfg.cid) ? ic.saveFileCls.getAtomPDB(atomHash, true, undefined, undefined, undefined, undefined, bMergeIntoOne, bOneLetterChain) : ic.saveFileCls.getAtomPDB(atomHash, undefined, undefined, undefined, undefined, undefined, bMergeIntoOne, bOneLetterChain);
|
|
71790
|
+
pdbstr += ic.saveFileCls.getAtomPDB(ionHash, true, undefined, true, undefined, undefined, bMergeIntoOne, bOneLetterChain);
|
|
71710
71791
|
|
|
71711
71792
|
return pdbstr;
|
|
71712
71793
|
}
|
|
@@ -78976,7 +79057,7 @@ class SaveFile {
|
|
|
78976
79057
|
}
|
|
78977
79058
|
|
|
78978
79059
|
//getAtomPDB: function(atomHash, bPqr, bPdb, bNoChem) { let ic = this.icn3d, me = ic.icn3dui;
|
|
78979
|
-
getAtomPDB(atomHash, bPqr, bNoChem, bNoHeader, chainResi2pdb, pdbid, bMergeIntoOne,
|
|
79060
|
+
getAtomPDB(atomHash, bPqr, bNoChem, bNoHeader, chainResi2pdb, pdbid, bMergeIntoOne, bOneLetterChain) { let ic = this.icn3d, me = ic.icn3dui;
|
|
78980
79061
|
let pdbStr = '';
|
|
78981
79062
|
|
|
78982
79063
|
// get all phosphate groups in lipids
|
|
@@ -79251,7 +79332,7 @@ class SaveFile {
|
|
|
79251
79332
|
//line +=(atom.chain.length <= 1) ? atom.chain.padStart(1, ' ') : atom.chain.substr(0, 1);
|
|
79252
79333
|
if(atom.chain.length >= 2) {
|
|
79253
79334
|
let chainTmp = atom.chain.replace(/_/gi, '').substr(0, 2);
|
|
79254
|
-
if(
|
|
79335
|
+
if(bOneLetterChain) chainTmp = ' ' + chainTmp.substr(0,1); // VAST search only support one lettter chain ID
|
|
79255
79336
|
line += chainTmp;
|
|
79256
79337
|
}
|
|
79257
79338
|
else if(atom.chain.length == 1) {
|
|
@@ -79330,8 +79411,8 @@ class SaveFile {
|
|
|
79330
79411
|
}
|
|
79331
79412
|
else {
|
|
79332
79413
|
line += "1.00".padStart(6, ' ');
|
|
79333
|
-
//
|
|
79334
|
-
let defaultBFactor =
|
|
79414
|
+
// let defaultBFactor = (bOneLetterChain) ? "1.0" : " ";
|
|
79415
|
+
let defaultBFactor = " ";
|
|
79335
79416
|
line +=(atom.b) ? parseFloat(atom.b).toFixed(2).toString().padStart(6, ' ') : defaultBFactor.padStart(6, ' ');
|
|
79336
79417
|
line += ' '.padStart(10, ' ');
|
|
79337
79418
|
line += atom.elem.padStart(2, ' ');
|
|
@@ -79379,7 +79460,7 @@ class SaveFile {
|
|
|
79379
79460
|
let resn = me.utilsCls.residueName2Abbr(atom.resn);
|
|
79380
79461
|
let ss = this.secondary2Abbr(atom.ss);
|
|
79381
79462
|
|
|
79382
|
-
if(chainid != prevChainid) {
|
|
79463
|
+
if(chainid != prevChainid && !data[chainid]) {
|
|
79383
79464
|
data[chainid] = {"resi": [], "resn": [], "secondary": []};
|
|
79384
79465
|
}
|
|
79385
79466
|
|
|
@@ -79400,8 +79481,8 @@ class SaveFile {
|
|
|
79400
79481
|
json += '{"chain": "' + chainid + '",\n';
|
|
79401
79482
|
|
|
79402
79483
|
json += '"resi": "' + data[chainid]["resi"].join(',') + '",\n';
|
|
79403
|
-
json += '"resn": "' + data[chainid]["resn"].join('') + '",\n';
|
|
79404
|
-
json += '"secondary": "' + data[chainid]["secondary"].join('') + '"';
|
|
79484
|
+
json += '"resn": "' + data[chainid]["resn"].join(',') + '",\n';
|
|
79485
|
+
json += '"secondary": "' + data[chainid]["secondary"].join(',') + '"';
|
|
79405
79486
|
|
|
79406
79487
|
if(i < cnt - 1) {
|
|
79407
79488
|
json += '},\n';
|
|
@@ -82903,7 +82984,7 @@ class iCn3DUI {
|
|
|
82903
82984
|
//even when multiple iCn3D viewers are shown together.
|
|
82904
82985
|
this.pre = this.cfg.divid + "_";
|
|
82905
82986
|
|
|
82906
|
-
this.REVISION = '3.40.
|
|
82987
|
+
this.REVISION = '3.40.3';
|
|
82907
82988
|
|
|
82908
82989
|
// In nodejs, iCn3D defines "window = {navigator: {}}"
|
|
82909
82990
|
this.bNode = (Object.keys(window).length < 2) ? true : false;
|
|
@@ -83065,7 +83146,7 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
|
|
|
83065
83146
|
ic.molTitle = '';
|
|
83066
83147
|
ic.loadCmd;
|
|
83067
83148
|
|
|
83068
|
-
// set menus
|
|
83149
|
+
// set menus
|
|
83069
83150
|
me.htmlCls.clickMenuCls.getHiddenMenusFromCache();
|
|
83070
83151
|
me.htmlCls.clickMenuCls.applyShownMenus();
|
|
83071
83152
|
|