icn3d 3.40.5 → 3.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/icn3d.js CHANGED
@@ -2539,7 +2539,6 @@ THREE.TrackballControls = function ( object, domElement, icn3d ) {
2539
2539
  _this._panStart.add( mouseChange.subVectors( _this._panEnd, _this._panStart ).multiplyScalar( _this.dynamicDampingFactor ) );
2540
2540
 
2541
2541
  }
2542
-
2543
2542
  }
2544
2543
  }
2545
2544
 
@@ -3576,6 +3575,103 @@ THREE.OrthographicTrackballControls = function ( object, domElement, icn3d ) { v
3576
3575
  THREE.OrthographicTrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype );
3577
3576
  THREE.OrthographicTrackballControls.prototype.constructor = THREE.OrthographicTrackballControls;
3578
3577
 
3578
+ /**
3579
+ * @author alteredq / http://alteredqualia.com/
3580
+ * @authod mrdoob / http://mrdoob.com/
3581
+ * @authod arodic / http://aleksandarrodic.com/
3582
+ * modified by Jiyao Wang
3583
+ */
3584
+
3585
+ THREE.StereoEffect = function ( renderer ) {
3586
+ var _this = this;
3587
+ // API
3588
+
3589
+ _this.separation = 3; // 1;
3590
+
3591
+ // internals
3592
+
3593
+ // _this._width, _this._height;
3594
+
3595
+ _this._position = new THREE.Vector3();
3596
+ _this._quaternion = new THREE.Quaternion();
3597
+ _this._scale = new THREE.Vector3();
3598
+
3599
+ _this._cameraL = new THREE.PerspectiveCamera();
3600
+ _this._cameraR = new THREE.PerspectiveCamera();
3601
+
3602
+ // initialization
3603
+
3604
+ renderer.autoClear = false;
3605
+
3606
+ _this.setSize = function ( width, height ) {
3607
+
3608
+ _this._width = width / 2;
3609
+ _this._height = height;
3610
+
3611
+ renderer.setSize( width, height );
3612
+
3613
+ };
3614
+
3615
+ _this.render = function ( scene, camera ) {
3616
+
3617
+ scene.updateMatrixWorld();
3618
+
3619
+ if ( camera.parent === undefined ) camera.updateMatrixWorld();
3620
+
3621
+ camera.matrixWorld.decompose( _this._position, _this._quaternion, _this._scale );
3622
+
3623
+ // left
3624
+ _this._cameraL.copy(camera);
3625
+ _this._cameraL.aspect = 0.5 * camera.aspect;
3626
+ _this._cameraL.updateProjectionMatrix();
3627
+
3628
+ /*
3629
+ _this._cameraL.fov = camera.fov;
3630
+ _this._cameraL.aspect = 0.5 * camera.aspect;
3631
+ _this._cameraL.near = camera.near;
3632
+ _this._cameraL.far = camera.far;
3633
+ _this._cameraL.updateProjectionMatrix();
3634
+
3635
+ _this._cameraL.position.copy( _this._position );
3636
+ // _this._cameraL.quaternion.copy( _this._quaternion );
3637
+ */
3638
+ _this._cameraL.translateX( - _this.separation );
3639
+
3640
+ // right
3641
+ _this._cameraR.copy(camera);
3642
+ _this._cameraR.aspect = 0.5 * camera.aspect;
3643
+ _this._cameraR.updateProjectionMatrix();
3644
+
3645
+ /*
3646
+ _this._cameraR.fov = camera.fov;
3647
+ _this._cameraR.aspect = 0.5 * camera.aspect;
3648
+ _this._cameraR.near = camera.near;
3649
+ _this._cameraR.far = camera.far;
3650
+ // _this._cameraR.projectionMatrix = _this._cameraL.projectionMatrix;
3651
+ _this._cameraR.updateProjectionMatrix();
3652
+
3653
+ _this._cameraR.position.copy( _this._position );
3654
+ // _this._cameraR.quaternion.copy( _this._quaternion );
3655
+ */
3656
+
3657
+ _this._cameraR.translateX( _this.separation );
3658
+
3659
+ //
3660
+
3661
+ renderer.setViewport( 0, 0, _this._width * 2, _this._height );
3662
+ renderer.clear();
3663
+
3664
+ renderer.setViewport( 0, 0, _this._width, _this._height );
3665
+ renderer.render( scene, _this._cameraL );
3666
+
3667
+ renderer.setViewport( _this._width, 0, _this._width, _this._height );
3668
+ renderer.render( scene, _this._cameraR );
3669
+
3670
+ };
3671
+
3672
+ };
3673
+
3674
+
3579
3675
 
3580
3676
  // ; var __CIFTools = function () {
3581
3677
  // 'use strict';
@@ -8805,6 +8901,7 @@ class ClickMenu {
8805
8901
 
8806
8902
  applyShownMenus(bNoSave) { let me = this.icn3dui; me.icn3d;
8807
8903
  let idArray = [];
8904
+
8808
8905
  for(let id in me.htmlCls.allMenus) {
8809
8906
  if(me.htmlCls.shownMenus.hasOwnProperty(id)) {
8810
8907
  $("#" + me.pre + id).parent().show();
@@ -8827,9 +8924,9 @@ class ClickMenu {
8827
8924
  }
8828
8925
 
8829
8926
  getHiddenMenusFromCache() { let me = this.icn3dui; me.icn3d;
8830
- // me.htmlCls.shownMenus = {};
8927
+ me.htmlCls.shownMenus = {};
8831
8928
 
8832
- // let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
8929
+ let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
8833
8930
 
8834
8931
  let idArrayStr = (localStorage) ? localStorage.getItem('hiddenmenus') : '';
8835
8932
 
@@ -8838,31 +8935,23 @@ class ClickMenu {
8838
8935
 
8839
8936
  let idArray = JSON.parse(idArrayStr);
8840
8937
 
8841
- // for(let i = 0, il = idArray.length; i < il; ++i) {
8842
- // me.htmlCls.shownMenus[idArray[i]] = 1;
8843
- // }
8844
8938
  for(let menu in me.htmlCls.allMenus) {
8845
8939
  if(idArray.indexOf(menu) == -1) {
8846
8940
  me.htmlCls.shownMenus[menu] = 1;
8847
8941
  }
8848
8942
  }
8849
8943
  }
8850
- //###
8851
8944
  else {
8852
- me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
8945
+ if(mode == 'all') {
8946
+ me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
8947
+ }
8948
+ else if(!mode || mode == 'simple') {
8949
+ me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
8950
+ }
8951
+ else {
8952
+ me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
8953
+ }
8853
8954
  }
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
- // }
8866
8955
  }
8867
8956
 
8868
8957
  displayShownMenus() { let me = this.icn3dui; me.icn3d;
@@ -9043,6 +9132,14 @@ class ClickMenu {
9043
9132
  me.htmlCls.dialogCls.openDlg('dl_urlfile', 'Load data by URL');
9044
9133
  });
9045
9134
 
9135
+ me.myEventCls.onIds("#" + me.pre + "mn1_clustalwfile", "click", function(e) { me.icn3d; //e.preventDefault();
9136
+ me.htmlCls.dialogCls.openDlg('dl_clustalwfile', 'Please input CLUSTALW MSA File');
9137
+ });
9138
+
9139
+ me.myEventCls.onIds("#" + me.pre + "mn1_fastafile", "click", function(e) { me.icn3d; //e.preventDefault();
9140
+ me.htmlCls.dialogCls.openDlg('dl_fastafile', 'Please input FASTA MSA File');
9141
+ });
9142
+
9046
9143
  me.myEventCls.onIds("#" + me.pre + "mn1_fixedversion", "click", function(e) { me.icn3d; //e.preventDefault();
9047
9144
  me.htmlCls.dialogCls.openDlg('dl_fixedversion', 'Open Share Link URL in the archived version of iCn3D');
9048
9145
  });
@@ -9144,6 +9241,11 @@ class ClickMenu {
9144
9241
  ic.saveFileCls.saveFile(file_pref + '_statefile.txt', 'command');
9145
9242
  });
9146
9243
 
9244
+ me.myEventCls.onIds("#" + me.pre + "mn1_exportVideo", "click", function(e) { me.icn3d; //e.preventDefault();
9245
+ thisClass.setLogCmd("export video", false);
9246
+ me.htmlCls.dialogCls.openDlg('dl_video', 'Save canvas changes in a video');
9247
+ });
9248
+
9147
9249
 
9148
9250
  me.myEventCls.onIds("#" + me.pre + "mn1_exportPdbRes", "click", function(e) { me.icn3d; //e.preventDefault();
9149
9251
  me.htmlCls.setHtmlCls.exportPdb();
@@ -10836,6 +10938,18 @@ class ClickMenu {
10836
10938
  //}
10837
10939
  });
10838
10940
 
10941
+ me.myEventCls.onIds("#" + me.pre + "mn6_stereoYes", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
10942
+ ic.opts['effect'] = 'stereo';
10943
+ ic.drawCls.draw();
10944
+ thisClass.setLogCmd('stereo on', true);
10945
+ });
10946
+
10947
+ me.myEventCls.onIds("#" + me.pre + "mn6_stereoNo", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
10948
+ ic.opts['effect'] = 'none';
10949
+ ic.drawCls.draw();
10950
+ thisClass.setLogCmd('stereo off', true);
10951
+ });
10952
+
10839
10953
  $(document).on("click", "#" + me.pre + "mn2_translate", function(e) { me.icn3d; //e.preventDefault();
10840
10954
  me.htmlCls.dialogCls.openDlg('dl_translate', 'Translate the X,Y,Z coordinates of the structure');
10841
10955
  });
@@ -11341,7 +11455,7 @@ class SetMenu {
11341
11455
 
11342
11456
  let tdStr = '<td valign="top">';
11343
11457
 
11344
- // html += tdStr + this.setMenuMode() + '</td>';
11458
+ html += tdStr + this.setMenuMode() + '</td>';
11345
11459
 
11346
11460
  html += tdStr + this.setMenu1() + '</td>';
11347
11461
 
@@ -11352,12 +11466,11 @@ class SetMenu {
11352
11466
  html += tdStr + this.setMenu4() + '</td>';
11353
11467
 
11354
11468
  html += tdStr + this.setMenu5() + '</td>';
11355
- //html += tdStr + this.setMenu5b() + '</td>';
11356
11469
  html += tdStr + this.setMenu6() + '</td>';
11357
11470
 
11358
11471
  // reset the menus at the end of the menus
11359
- // let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
11360
- // this.resetMenu(mode);
11472
+ let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
11473
+ this.resetMenu(mode);
11361
11474
 
11362
11475
  // me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
11363
11476
 
@@ -11465,7 +11578,7 @@ class SetMenu {
11465
11578
  }
11466
11579
  html += "<div>";
11467
11580
 
11468
- // html += '<li>' + this.setMenuMode(true);
11581
+ html += '<li>' + this.setMenuMode(true);
11469
11582
 
11470
11583
  let liStr = "<li><span class='icn3d-menu-color'";
11471
11584
 
@@ -11486,8 +11599,8 @@ class SetMenu {
11486
11599
  html += this.setMenu6_base();
11487
11600
 
11488
11601
  // reset the menus at the end of the menus
11489
- // let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
11490
- // this.resetMenu(mode);
11602
+ let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
11603
+ this.resetMenu(mode);
11491
11604
 
11492
11605
  // me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
11493
11606
 
@@ -11577,7 +11690,7 @@ class SetMenu {
11577
11690
 
11578
11691
  html += me.htmlCls.divStr + "selection' style='display:none;'><div style='position:absolute; z-index:555; float:left; display:table-row; margin: 32px 0px 0px 0px;'>";
11579
11692
  //html += "<table style='margin-top: 3px; width:100px;'>";
11580
- html += "<table style='margin-top: 3px; width:770px; background-color:#EEE;'>";
11693
+ html += "<table style='margin: 3px 0px 0px 76px; width:770px; background-color:#EEE;'>";
11581
11694
 
11582
11695
  html += this.setTools_base();
11583
11696
 
@@ -11850,9 +11963,19 @@ class SetMenu {
11850
11963
  html += this.getLink('mn1_mol2file', 'Mol2 File', undefined, 2);
11851
11964
  html += this.getLink('mn1_sdffile', 'SDF File', undefined, 2);
11852
11965
  html += this.getLink('mn1_xyzfile', 'XYZ File', undefined, 2);
11966
+
11967
+ html += this.getMenuSep();
11968
+
11969
+ html += this.getMenuText('mn1_msawrap', 'Multiple Seq. Alignment', undefined, undefined, 2);
11970
+ html += "<ul>";
11971
+ html += this.getLink('mn1_clustalwfile', 'CLUSTALW Format', undefined, 3);
11972
+ html += this.getLink('mn1_fastafile', 'FASTA Format', undefined, 3);
11973
+ html += "</ul>";
11974
+
11853
11975
  html += this.getLink('mn1_afmapfile', 'AlphaFold PAE File', undefined, 2);
11854
11976
 
11855
11977
  html += this.getLink('mn1_urlfile', 'URL(CORS) ' + me.htmlCls.wifiStr, undefined, 2);
11978
+
11856
11979
  html += this.getMenuSep();
11857
11980
  html += this.getLink('mn1_pngimage', 'iCn3D PNG (appendable)', 1, 2);
11858
11981
  html += this.getLink('mn1_state', 'State/Script File', undefined, 2);
@@ -11893,9 +12016,9 @@ class SetMenu {
11893
12016
  html += "</ul>";
11894
12017
  html += "</li>";
11895
12018
 
11896
- html += this.getMenuText('mn1_aligntwostru', 'Protein Complexes', undefined, undefined, 2);
12019
+ html += this.getMenuText('mn1_aligntwostru', 'Protein Complexes', undefined, 1, 2);
11897
12020
  html += "<ul>";
11898
- html += this.getLink('mn1_align', 'Two PDB Structures ' + me.htmlCls.wifiStr, undefined, 3);
12021
+ html += this.getLink('mn1_align', 'Two PDB Structures ' + me.htmlCls.wifiStr, 1, 3);
11899
12022
  html += this.getLink('mn1_alignaf', 'Two AlphaFold Structures ' + me.htmlCls.wifiStr, undefined, 3);
11900
12023
  html += "</ul>";
11901
12024
 
@@ -11949,8 +12072,8 @@ class SetMenu {
11949
12072
  html += "<ul>";
11950
12073
  html += this.getMenuText('mn1_savepngimage', 'iCn3D PNG Image', undefined, 1, 2);
11951
12074
  html += "<ul>";
11952
- html += this.getLink('mn1_exportCanvas', 'Original Size & HTML', 1, 3);
11953
- html += this.getLink('mn1_exportCanvas1', 'Original Size', undefined, 3);
12075
+ html += this.getLink('mn1_exportCanvas', 'Original Size & HTML', undefined, 3);
12076
+ html += this.getLink('mn1_exportCanvas1', 'Original Size', 1, 3);
11954
12077
 
11955
12078
  html += this.getLink('mn1_exportCanvas2', '2X Large', undefined, 3);
11956
12079
  html += this.getLink('mn1_exportCanvas4', '4X Large', undefined, 3);
@@ -11959,6 +12082,7 @@ class SetMenu {
11959
12082
  html += "</ul>";
11960
12083
  html += "</li>";
11961
12084
 
12085
+ html += this.getLink('mn1_exportVideo', 'Video', undefined, 2);
11962
12086
  html += this.getLink('mn1_exportState', 'State File', undefined, 2);
11963
12087
  html += this.getLink('mn1_exportSelections', 'Selection File', undefined, 2);
11964
12088
  html += this.getLink('mn1_exportSelDetails', 'Selection Details', undefined, 2);
@@ -12037,7 +12161,7 @@ class SetMenu {
12037
12161
  html += "<ul class='icn3d-mn-item'>";
12038
12162
 
12039
12163
  html += this.getLink('mn2_definedsets', 'Defined Sets', 1, 1);
12040
- html += this.getLink('mn2_selectall', 'All', undefined, 1);
12164
+ html += this.getLink('mn2_selectall', 'All', 1, 1);
12041
12165
  html += this.getLink('mn2_selectdisplayed', 'Displayed Set', undefined, 1);
12042
12166
  html += this.getLink('mn2_aroundsphere', 'by Distance', 1, 1);
12043
12167
 
@@ -12053,10 +12177,10 @@ class SetMenu {
12053
12177
  html += "</li>";
12054
12178
 
12055
12179
  html += this.getLink('mn2_selectcomplement', 'Inverse', undefined, 1);
12056
- html += this.getLink('mn2_selectmainchains', 'Main Chains', undefined, 1);
12057
- html += this.getLink('mn2_selectsidechains', 'Side Chains', undefined, 1);
12180
+ html += this.getLink('mn2_selectmainchains', 'Main Chains', 1, 1);
12181
+ html += this.getLink('mn2_selectsidechains', 'Side Chains', 1, 1);
12058
12182
  html += this.getLink('mn2_selectmainsidechains', 'Main & Side Chains', undefined, 1);
12059
- html += this.getLink('mn2_command', 'Advanced', undefined, 1);
12183
+ html += this.getLink('mn2_command', 'Advanced', 1, 1);
12060
12184
 
12061
12185
  if(me.cfg.cid === undefined) {
12062
12186
  html += this.getMenuText('mn2_selon3d', 'Select on 3D', undefined, 1, 1);
@@ -12089,7 +12213,7 @@ class SetMenu {
12089
12213
  html += this.getMenuSep();
12090
12214
 
12091
12215
  html += this.getLink('mn2_saveselection', 'Save Selection', 1, 1);
12092
- html += this.getLink('clearall', 'Clear Selection', undefined, 1);
12216
+ html += this.getLink('clearall', 'Clear Selection', 1, 1);
12093
12217
  html += this.getLink('mn2_saveresidue', 'Save Res. in Sel.', 1, 1);
12094
12218
 
12095
12219
  html += this.getMenuSep();
@@ -12154,7 +12278,7 @@ class SetMenu {
12154
12278
  html += this.getLinkWrapper('mn2_alternate', 'Alternate(Key "a")', 'mn2_alternateWrap', undefined, 1);
12155
12279
 
12156
12280
  if(me.cfg.opmid !== undefined) {
12157
- html += this.getLinkWrapper('togglemem', 'Toggle Membrane', 'togglememli', undefined, 1);
12281
+ html += this.getLinkWrapper('togglemem', 'Toggle Membrane', 'togglememli', 1, 1);
12158
12282
  }
12159
12283
  //else if(me.cfg.mmdbafid !== undefined || me.cfg.afid !== undefined) {
12160
12284
  else if(me.cfg.cid === undefined) {
@@ -12169,14 +12293,21 @@ class SetMenu {
12169
12293
 
12170
12294
  html += this.getMenuSep();
12171
12295
 
12172
- html += this.getMenuText('mn2_vrarhints', 'VR & AR Hints', undefined, 1, 1);
12296
+ html += this.getMenuText('mn2_vrarhints', 'VR & AR Hints', undefined, undefined, 1);
12297
+ html += "<ul>";
12298
+ html += this.getMenuUrl("vrhint", me.htmlCls.baseUrl + "icn3d/icn3d.html#vr", "VR: VR Headsets", undefined, 2);
12299
+ html += this.getMenuUrl("arhint", me.htmlCls.baseUrl + "icn3d/icn3d.html#ar", "AR: Chrome in Android", undefined, 2);
12300
+ html += "</ul>";
12301
+ html += "</li>";
12302
+
12303
+ html += this.getMenuText('mn6_stereoWrapper', 'Stereo View', undefined, undefined, 1);
12173
12304
  html += "<ul>";
12174
- html += this.getMenuUrl("vrhint", me.htmlCls.baseUrl + "icn3d/icn3d.html#vr", "VR: VR Headsets", 1, 2);
12175
- html += this.getMenuUrl("arhint", me.htmlCls.baseUrl + "icn3d/icn3d.html#ar", "AR: Chrome in Android", 1, 2);
12305
+ html += this.getRadio('mn6_stereo', 'mn6_stereoYes', 'On', undefined, undefined, 2);
12306
+ html += this.getRadio('mn6_stereo', 'mn6_stereoNo', 'Off', true, undefined, 2);
12176
12307
  html += "</ul>";
12177
12308
  html += "</li>";
12178
12309
 
12179
- html += this.getLink('mn6_sidebyside', 'Side by Side', 1, 1);
12310
+ html += this.getLink('mn6_sidebyside', 'Side by Side', undefined, 1);
12180
12311
 
12181
12312
  html += this.getMenuText('mn2_rotate', 'Rotate', undefined, 1, 1);
12182
12313
  html += "<ul>";
@@ -12288,7 +12419,7 @@ class SetMenu {
12288
12419
  html += this.getRadio('mn3_proteins', 'mn3_proteinsRibbon', 'Ribbon', true, 1, 2);
12289
12420
  }
12290
12421
 
12291
- html += this.getRadio('mn3_proteins', 'mn3_proteinsStrand', 'Strand', undefined, undefined, 2);
12422
+ html += this.getRadio('mn3_proteins', 'mn3_proteinsStrand', 'Strand', undefined, 1, 2);
12292
12423
  html += this.getRadio('mn3_proteins', 'mn3_proteinsCylinder', 'Cylinder and Plate', undefined, undefined, 2);
12293
12424
  html += this.getRadio('mn3_proteins', 'mn3_proteinsSchematic', 'Schematic', undefined, 1, 2);
12294
12425
 
@@ -12300,7 +12431,7 @@ class SetMenu {
12300
12431
  }
12301
12432
 
12302
12433
  html += this.getRadio('mn3_proteins', 'mn3_proteinsBackbone', 'Backbone', undefined, undefined, 2);
12303
- html += this.getRadio('mn3_proteins', 'mn3_proteinsBfactor', 'B-factor Tube', undefined, 1, 2);
12434
+ html += this.getRadio('mn3_proteins', 'mn3_proteinsBfactor', 'B-factor Tube', undefined, undefined, 2);
12304
12435
  html += this.getRadio('mn3_proteins', 'mn3_proteinsLines', 'Lines', undefined, 1, 2);
12305
12436
  html += this.getRadio('mn3_proteins', 'mn3_proteinsStick', 'Stick', undefined, 1, 2);
12306
12437
  html += this.getRadio('mn3_proteins', 'mn3_proteinsBallstick', 'Ball and Stick', undefined, 1, 2);
@@ -12364,10 +12495,10 @@ class SetMenu {
12364
12495
  html += "</li>";
12365
12496
 
12366
12497
  //if(me.cfg.cid !== undefined) {
12367
- html += this.getMenuText('mn3_hydrogenswrap', 'Hydrogens', undefined, 1, 1);
12498
+ html += this.getMenuText('mn3_hydrogenswrap', 'Hydrogens', undefined, undefined, 1);
12368
12499
  html += "<ul>";
12369
- html += this.getRadio('mn3_hydrogens', 'mn3_hydrogensYes', 'Show', true, 1, 2);
12370
- html += this.getRadio('mn3_hydrogens', 'mn3_hydrogensNo', 'Hide', undefined, 1, 2);
12500
+ html += this.getRadio('mn3_hydrogens', 'mn3_hydrogensYes', 'Show', true, undefined, 2);
12501
+ html += this.getRadio('mn3_hydrogens', 'mn3_hydrogensNo', 'Hide', undefined, undefined, 2);
12371
12502
  html += "</ul>";
12372
12503
  html += "</li>";
12373
12504
  //}
@@ -12742,7 +12873,7 @@ class SetMenu {
12742
12873
 
12743
12874
  html += "</ul>";
12744
12875
 
12745
- html += this.getRadio('mn4_clr', 'mn4_clrCustom', 'Color Picker', undefined, undefined, 1);
12876
+ html += this.getRadio('mn4_clr', 'mn4_clrCustom', 'Color Picker', undefined, 1, 1);
12746
12877
  html += this.getMenuSep();
12747
12878
 
12748
12879
  if(me.cfg.cid === undefined) {
@@ -12783,7 +12914,7 @@ class SetMenu {
12783
12914
  html += this.getRadio('mn4_clr', 'mn4_clrBfactorNorm', 'Percentile', undefined, 1, 2);
12784
12915
  html += "</ul>";
12785
12916
 
12786
- html += this.getRadio('mn4_clr', 'mn4_clrArea', 'Solvent<br><span style="padding-left:1.5em;">Accessibility</span>', undefined, undefined, 1);
12917
+ html += this.getRadio('mn4_clr', 'mn4_clrArea', 'Solvent<br><span style="padding-left:1.5em;">Accessibility</span>', undefined, 1, 1);
12787
12918
 
12788
12919
  html += this.getRadio('mn4_clr', 'mn4_clrStructure', 'Structure', undefined, 1, 1);
12789
12920
 
@@ -12795,7 +12926,7 @@ class SetMenu {
12795
12926
  }
12796
12927
 
12797
12928
  //if(me.cfg.mmdbid !== undefined || me.cfg.gi !== undefined) {
12798
- html += this.getRadio('mn4_clr', 'mn4_clrdomain', '3D Domain', undefined, undefined, 1);
12929
+ html += this.getRadio('mn4_clr', 'mn4_clrdomain', '3D Domain', undefined, 1, 1);
12799
12930
  //}
12800
12931
 
12801
12932
  if(me.cfg.cid === undefined) {
@@ -12815,16 +12946,16 @@ class SetMenu {
12815
12946
  html += this.getRadio('mn4_clr', 'mn4_clrAtom', 'Atom', undefined, 1, 1);
12816
12947
 
12817
12948
  if(me.cfg.align !== undefined || me.cfg.chainalign !== undefined) {
12818
- html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', true, undefined, 2);
12819
- html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', undefined, undefined, 2);
12949
+ html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', true, undefined, 1);
12950
+ html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', undefined, undefined, 1);
12820
12951
  }
12821
12952
  else if(me.cfg.blast_rep_id !== undefined) {
12822
- html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', undefined, undefined, 2);
12823
- html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', true, undefined, 2);
12953
+ html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', undefined, undefined, 1);
12954
+ html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', true, undefined, 1);
12824
12955
  }
12825
12956
  else {
12826
- html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', undefined, undefined, 2);
12827
- html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', undefined, undefined, 2);
12957
+ html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', undefined, undefined, 1);
12958
+ html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', undefined, undefined, 1);
12828
12959
  }
12829
12960
 
12830
12961
  //if(me.cfg.afid) html += this.getRadio('mn4_clr', 'mn4_clrConfidence', 'AF Confidence');
@@ -12832,8 +12963,8 @@ class SetMenu {
12832
12963
  html += this.getRadio('mn4_clr', 'mn4_clrConfidence', 'pLDDT', undefined, 1, 1);
12833
12964
  //}
12834
12965
 
12835
- html += this.getRadio('mn4_clr', 'mn4_clrIgstrand', 'Ig Strand', undefined, undefined, 2);
12836
- html += this.getRadio('mn4_clr', 'mn4_clrIgproto', 'Ig Protodomain', undefined, undefined, 2);
12966
+ html += this.getRadio('mn4_clr', 'mn4_clrIgstrand', 'Ig Strand', undefined, undefined, 1);
12967
+ html += this.getRadio('mn4_clr', 'mn4_clrIgproto', 'Ig Protodomain', undefined, undefined, 1);
12837
12968
  }
12838
12969
  else {
12839
12970
  //if(!me.cfg.hidelicense) html += this.getRadio('mn4_clr', 'mn1_delphi2', 'DelPhi<br><span style="padding-left:1.5em;">Potential ' + me.htmlCls.licenseStr + '</span>');
@@ -12886,7 +13017,7 @@ class SetMenu {
12886
13017
  html += this.getLink('mn6_selectannotations', 'Seq. & Annotations ' + me.htmlCls.wifiStr, 1, 1);
12887
13018
 
12888
13019
  //if(me.cfg.align !== undefined || me.cfg.chainalign !== undefined) { // || ic.bRealign || ic.bSymd || ic.bInputfile) {
12889
- html += this.getLink('mn2_alignment', 'Aligned Seq. ' + me.htmlCls.wifiStr, undefined, 1);
13020
+ html += this.getLink('mn2_alignment', 'Aligned Seq. ' + me.htmlCls.wifiStr, 1, 1);
12890
13021
  //}
12891
13022
 
12892
13023
  if(me.cfg.mmdbid !== undefined || me.cfg.gi !== undefined || me.cfg.blast_rep_id !== undefined || me.cfg.align !== undefined || me.cfg.chainalign !== undefined) {
@@ -12956,27 +13087,27 @@ class SetMenu {
12956
13087
  html += "</ul>";
12957
13088
  html += "</li>";
12958
13089
 
12959
- html += this.getMenuText('mn6_anglewrap', 'Angle', undefined, 1, 1);
13090
+ html += this.getMenuText('mn6_anglewrap', 'Angle', undefined, undefined, 1);
12960
13091
  html += "<ul>";
12961
- html += this.getRadio('mn6_angle', 'mn6_angleManySets', 'among Many Sets', undefined, 1, 2);
13092
+ html += this.getRadio('mn6_angle', 'mn6_angleManySets', 'among Many Sets', undefined, undefined, 2);
12962
13093
  html += this.getRadio('mn6_angle', 'mn6_angleTwoSets', 'b/w Two Vectors', undefined, undefined, 2);
12963
13094
  html += "</ul>";
12964
13095
  html += "</li>";
12965
13096
 
12966
- html += this.getLink('mn6_area', 'Surface Area', 1, 1);
13097
+ html += this.getLink('mn6_area', 'Surface Area', undefined, 1);
12967
13098
 
12968
13099
  html += this.getMenuText('mn6_addlabelwrap', 'Label', undefined, 1, 1);
12969
13100
  html += "<ul>";
12970
13101
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelYes', 'by Picking Atoms', undefined, undefined, 2);
12971
13102
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelSelection', 'per Selection', undefined, undefined, 2);
12972
13103
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelAtoms', 'per Atom', undefined, undefined, 2);
12973
- html += this.getRadio('mn6_addlabel', 'mn6_addlabelElements', 'per Atom Element', undefined, 1, 2);
13104
+ html += this.getRadio('mn6_addlabel', 'mn6_addlabelElements', 'per Atom Element', undefined, undefined, 2);
12974
13105
  if(me.cfg.cid === undefined) {
12975
13106
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelResidues', 'per Residue', undefined, 1, 2);
12976
13107
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelResnum', 'per Residue & Number', undefined, 1, 2);
12977
13108
 
12978
- html += this.getRadio('mn6_addlabel', 'mn6_addlabelRefnum', 'per Reference Number', undefined, 1, 2);
12979
- html += this.getRadio('mn6_addlabel', 'mn6_addlabelIg', 'per Ig Domain', undefined, 1, 2);
13109
+ html += this.getRadio('mn6_addlabel', 'mn6_addlabelRefnum', 'per Reference Number', undefined, undefined, 2);
13110
+ html += this.getRadio('mn6_addlabel', 'mn6_addlabelIg', 'per Ig Domain', undefined, undefined, 2);
12980
13111
 
12981
13112
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelChains', 'per Chain', undefined, undefined, 2);
12982
13113
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelTermini', 'N- & C-Termini', undefined, 1, 2);
@@ -13013,10 +13144,10 @@ class SetMenu {
13013
13144
  html += this.getMenuSep();
13014
13145
 
13015
13146
  if(me.cfg.cid === undefined) {
13016
- html += this.getMenuText('mn6_chemicalbindingwrap', 'Chem. Binding', undefined, undefined, 1);
13147
+ html += this.getMenuText('mn6_chemicalbindingwrap', 'Chem. Binding', undefined, 1, 1);
13017
13148
  html += "<ul>";
13018
- html += this.getRadio('mn6_chemicalbinding', 'mn6_chemicalbindingshow', 'Show', undefined, undefined, 2);
13019
- html += this.getRadio('mn6_chemicalbinding', 'mn6_chemicalbindinghide', 'Hide', true, undefined, 2);
13149
+ html += this.getRadio('mn6_chemicalbinding', 'mn6_chemicalbindingshow', 'Show', undefined, 1, 2);
13150
+ html += this.getRadio('mn6_chemicalbinding', 'mn6_chemicalbindinghide', 'Hide', true, 1, 2);
13020
13151
  html += "</ul>";
13021
13152
  html += "</li>";
13022
13153
 
@@ -13175,7 +13306,7 @@ class SetMenu {
13175
13306
 
13176
13307
  //html += liStr + "https://www.ncbi.nlm.nih.gov/structure' target='_blank'>Search Structure " + me.htmlCls.wifiStr + "</a></li>";
13177
13308
  //html += liStr + me.htmlCls.baseUrl + "icn3d/icn3d.html#citing' target='_blank'>Citing iCn3D</a></li>";
13178
- html += this.getMenuUrl('citing', me.htmlCls.baseUrl + "icn3d/icn3d.html#citing", "Citing iCn3D", undefined, 1);
13309
+ html += this.getMenuUrl('citing', me.htmlCls.baseUrl + "icn3d/icn3d.html#citing", "Citing iCn3D", 1, 1);
13179
13310
 
13180
13311
  html += this.getMenuText('mn6_source', 'Source Code', undefined, 1, 1);
13181
13312
  html += "<ul>";
@@ -14205,6 +14336,19 @@ class SetDialog {
14205
14336
  html += me.htmlCls.buttonStr + "reload_xyzfile'>Load</button>";
14206
14337
  html += "</div>";
14207
14338
 
14339
+ html += me.htmlCls.divStr + "dl_clustalwfile' class='" + dialogClass + "' style='max-width:500px'>";
14340
+ html += this.addNotebookTitle('dl_clustalwfile', 'Please input a CLUSTALW MSA file');
14341
+ html += "Note the sequence names are either UniProt ID (e.g., A4D1S0 or A4D1S0_A), RefSeq ID (e.g., NP_001743), or PDB chain ID (e.g., 1HHO_A).<br><br>";
14342
+ html += "CLUSTALW File: " + me.htmlCls.inputFileStr + "id='" + me.pre + "clustalwfile' size=8> ";
14343
+ html += me.htmlCls.buttonStr + "reload_clustalwfile'>Load</button><br>";
14344
+ html += "</div>";
14345
+ html += me.htmlCls.divStr + "dl_fastafile' class='" + dialogClass + "' style='max-width:500px'>";
14346
+ html += this.addNotebookTitle('dl_fastafile', 'Please input a FASTA file');
14347
+ html += "Note the sequence IDs following the symbol \">\" contain either UniProt ID (e.g., sp| or tr|), RefSeq ID (e.g., ref|), PDB chain ID (e.g., pdb|1HHO|A), or iCn3D chain ID (e.g., A4D1S0_A, 1HHO_A).<br><br>";
14348
+ html += "FASTA File: " + me.htmlCls.inputFileStr + "id='" + me.pre + "fastafile' size=8> ";
14349
+ html += me.htmlCls.buttonStr + "reload_fastafile'>Load</button><br>";
14350
+ html += "</div>";
14351
+
14208
14352
  html += me.htmlCls.divStr + "dl_afmapfile' class='" + dialogClass + "'>";
14209
14353
  html += this.addNotebookTitle('dl_afmapfile', 'Please input an AlphaFold PAE file');
14210
14354
  html += "AlphaFold PAE File: " + me.htmlCls.inputFileStr + "id='" + me.pre + "afmapfile' size=8> <br><br>";
@@ -14324,6 +14468,12 @@ class SetDialog {
14324
14468
  html += me.htmlCls.buttonStr + "reload_state' style='margin-top: 6px;'>Load</button>";
14325
14469
  html += "</div>";
14326
14470
 
14471
+ html += me.htmlCls.divStr + "dl_video' class='" + dialogClass + "'>";
14472
+ html += this.addNotebookTitle('dl_video', 'Save canvas changes in a video');
14473
+ html += me.htmlCls.buttonStr + "video_start' style='margin-top: 6px;'>Video Start</button>";
14474
+ html += me.htmlCls.buttonStr + "video_end' style='margin: 6px 0px 0px 30px;'>Video End</button>";
14475
+ html += "</div>";
14476
+
14327
14477
  html += me.htmlCls.divStr + "dl_fixedversion' style='max-width:500px' class='" + dialogClass + "'>";
14328
14478
  html += this.addNotebookTitle('dl_fixedversion', 'Use fixed version of iCn3D');
14329
14479
  html += "Since January 6, 2021, you can show the original view with the archived version of iCn3D by pasting your URL below and click \"Show Originial View\". Note the version in the parameter \"v\" was used to replace \"full.html\" with \"full_[v].html\" in the URL.<br><br>";
@@ -15683,17 +15833,10 @@ class Events {
15683
15833
  }
15684
15834
  }
15685
15835
 
15686
- async loadPdbFile(bAppend, fileId, bmmCIF) { let me = this.icn3dui, ic = me.icn3d;
15836
+ async loadPdbFile(bAppend, fileId, bmmCIF) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
15687
15837
  //me = ic.setIcn3dui(this.id);
15688
15838
  ic.bInitial = true;
15689
- if(!me.cfg.notebook) dialog.dialog( "close" );
15690
- //close all dialog
15691
- if(!me.cfg.notebook) {
15692
- $(".ui-dialog-content").dialog("close");
15693
- }
15694
- else {
15695
- ic.resizeCanvasCls.closeDialogs();
15696
- }
15839
+ thisClass.iniFileLoad();
15697
15840
  let files = $("#" + me.pre + fileId)[0].files;
15698
15841
  if(!files[0]) {
15699
15842
  var aaa = 1; //alert("Please select a file before clicking 'Load'");
@@ -15737,6 +15880,24 @@ class Events {
15737
15880
  $("#" + me.pre + id).resizable();
15738
15881
  }
15739
15882
 
15883
+ exportMsa(type) { let me = this.icn3dui, ic = me.icn3d;
15884
+ let text = ic.msa[type].join('\n\n');
15885
+ let fileType = (type == 'fasta') ? '.fasta' : (type == 'clustalw') ? '.aln' : '.txt';
15886
+
15887
+ ic.saveFileCls.saveFile(ic.inputid + '_align' + fileType, 'text', [text]);
15888
+ }
15889
+
15890
+ iniFileLoad() { let me = this.icn3dui, ic = me.icn3d;
15891
+ if(!me.cfg.notebook) dialog.dialog( "close" );
15892
+ //close all dialog
15893
+ if(!me.cfg.notebook) {
15894
+ $(".ui-dialog-content").dialog("close");
15895
+ }
15896
+ else {
15897
+ ic.resizeCanvasCls.closeDialogs();
15898
+ }
15899
+ }
15900
+
15740
15901
  async launchMmdb(ids, bBiounit, hostUrl, bAppend) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
15741
15902
  if(!me.cfg.notebook) dialog.dialog( "close" );
15742
15903
 
@@ -16832,16 +16993,40 @@ class Events {
16832
16993
 
16833
16994
  me.htmlCls.setHtmlCls.clickReload_pngimage();
16834
16995
 
16996
+ me.myEventCls.onIds("#" + me.pre + "video_start", "click", function(e) { let ic = me.icn3d;
16997
+ e.preventDefault();
16998
+
16999
+ const canvas = document.getElementById(ic.pre + "canvas");
17000
+ ic.videoRecorder = new MediaRecorder(canvas.captureStream());
17001
+ const recordedChunks = [];
17002
+
17003
+ // Collect data chunks
17004
+ ic.videoRecorder.ondataavailable = event => {
17005
+ recordedChunks.push(event.data);
17006
+ };
17007
+
17008
+ ic.videoRecorder.onstop = event => {
17009
+ // Code to save the recordedChunks as a video file
17010
+ const blob = new Blob(recordedChunks, {type: ic.videoRecorder.mimeType});
17011
+ let fileName = ic.inputid + '_video';
17012
+ saveAs(blob, fileName);
17013
+ };
17014
+
17015
+ // Start recording
17016
+ ic.videoRecorder.start();
17017
+ thisClass.setLogCmd('Video revording started', false);
17018
+ });
17019
+
17020
+ me.myEventCls.onIds("#" + me.pre + "video_end", "click", function(e) { let ic = me.icn3d;
17021
+ e.preventDefault();
17022
+
17023
+ ic.videoRecorder.stop();
17024
+ thisClass.setLogCmd('Video revording ended', false);
17025
+ });
17026
+
16835
17027
  me.myEventCls.onIds("#" + me.pre + "reload_state", "click", function(e) { let ic = me.icn3d;
16836
17028
  e.preventDefault();
16837
- if(!me.cfg.notebook) dialog.dialog( "close" );
16838
- //close all dialog
16839
- if(!me.cfg.notebook) {
16840
- $(".ui-dialog-content").dialog("close");
16841
- }
16842
- else {
16843
- ic.resizeCanvasCls.closeDialogs();
16844
- }
17029
+ thisClass.iniFileLoad();
16845
17030
  // initialize icn3dui
16846
17031
  //Do NOT clear data if iCn3D loads a pdb or other data file and then load a state file
16847
17032
  if(!ic.bInputfile) {
@@ -16893,12 +17078,7 @@ class Events {
16893
17078
  if (!file) {
16894
17079
  var aaa = 1; //alert("Please select a file before clicking 'Load'");
16895
17080
  } else {
16896
- if (!me.cfg.notebook) dialog.dialog("close");
16897
- if (!me.cfg.notebook) {
16898
- $(".ui-dialog-content").dialog("close");
16899
- } else {
16900
- ic.resizeCanvasCls.closeDialogs();
16901
- }
17081
+ thisClass.iniFileLoad();
16902
17082
 
16903
17083
  ic.dAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
16904
17084
  ic.hAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
@@ -17453,14 +17633,7 @@ class Events {
17453
17633
  me.myEventCls.onIds("#" + me.pre + "reload_mol2file", "click", function(e) { let ic = me.icn3d;
17454
17634
  e.preventDefault();
17455
17635
  ic.bInitial = true;
17456
- if(!me.cfg.notebook) dialog.dialog( "close" );
17457
- //close all dialog
17458
- if(!me.cfg.notebook) {
17459
- $(".ui-dialog-content").dialog("close");
17460
- }
17461
- else {
17462
- ic.resizeCanvasCls.closeDialogs();
17463
- }
17636
+ thisClass.iniFileLoad();
17464
17637
  let file = $("#" + me.pre + "mol2file")[0].files[0];
17465
17638
  if(!file) {
17466
17639
  var aaa = 1; //alert("Please select a file before clicking 'Load'");
@@ -17487,14 +17660,7 @@ class Events {
17487
17660
  me.myEventCls.onIds("#" + me.pre + "reload_sdffile", "click", function(e) { let ic = me.icn3d;
17488
17661
  e.preventDefault();
17489
17662
  ic.bInitial = true;
17490
- if(!me.cfg.notebook) dialog.dialog( "close" );
17491
- //close all dialog
17492
- if(!me.cfg.notebook) {
17493
- $(".ui-dialog-content").dialog("close");
17494
- }
17495
- else {
17496
- ic.resizeCanvasCls.closeDialogs();
17497
- }
17663
+ thisClass.iniFileLoad();
17498
17664
  let file = $("#" + me.pre + "sdffile")[0].files[0];
17499
17665
  if(!file) {
17500
17666
  var aaa = 1; //alert("Please select a file before clicking 'Load'");
@@ -17521,14 +17687,7 @@ class Events {
17521
17687
  me.myEventCls.onIds("#" + me.pre + "reload_xyzfile", "click", function(e) { let ic = me.icn3d;
17522
17688
  e.preventDefault();
17523
17689
  ic.bInitial = true;
17524
- if(!me.cfg.notebook) dialog.dialog( "close" );
17525
- //close all dialog
17526
- if(!me.cfg.notebook) {
17527
- $(".ui-dialog-content").dialog("close");
17528
- }
17529
- else {
17530
- ic.resizeCanvasCls.closeDialogs();
17531
- }
17690
+ thisClass.iniFileLoad();
17532
17691
  let file = $("#" + me.pre + "xyzfile")[0].files[0];
17533
17692
  if(!file) {
17534
17693
  var aaa = 1; //alert("Please select a file before clicking 'Load'");
@@ -17552,17 +17711,64 @@ class Events {
17552
17711
  }
17553
17712
  });
17554
17713
 
17555
- me.myEventCls.onIds("#" + me.pre + "reload_afmapfile", "click", function(e) { let ic = me.icn3d;
17714
+ me.myEventCls.onIds("#" + me.pre + "reload_clustalwfile", "click", function(e) { let ic = me.icn3d;
17556
17715
  e.preventDefault();
17557
17716
  ic.bInitial = true;
17558
- if(!me.cfg.notebook) dialog.dialog( "close" );
17559
- //close all dialog
17560
- if(!me.cfg.notebook) {
17561
- $(".ui-dialog-content").dialog("close");
17717
+ thisClass.iniFileLoad();
17718
+
17719
+ let file = $("#" + me.pre + "clustalwfile")[0].files[0];
17720
+ if(!file) {
17721
+ var aaa = 1; //alert("Please select a file before clicking 'Load'");
17562
17722
  }
17563
17723
  else {
17564
- ic.resizeCanvasCls.closeDialogs();
17724
+ me.htmlCls.setHtmlCls.fileSupport();
17725
+ let reader = new FileReader();
17726
+ reader.onload = async function(e) {
17727
+ let dataStr = e.target.result; // or = reader.result;
17728
+ thisClass.setLogCmd('load CLUSTALW file ' + $("#" + me.pre + "clustalwfile").val(), false);
17729
+ ic.molTitle = "";
17730
+ ic.inputid = undefined;
17731
+ //ic.initUI();
17732
+ ic.init();
17733
+ ic.bInputfile = false; //true;
17734
+ ic.InputfileType = 'clustalw';
17735
+ await ic.msaParserCls.loadMsaData(dataStr, 'clustalw');
17736
+ };
17737
+ reader.readAsText(file);
17738
+ }
17739
+ });
17740
+
17741
+ me.myEventCls.onIds("#" + me.pre + "reload_fastafile", "click", function(e) { let ic = me.icn3d;
17742
+ e.preventDefault();
17743
+ ic.bInitial = true;
17744
+ thisClass.iniFileLoad();
17745
+
17746
+ let file = $("#" + me.pre + "fastafile")[0].files[0];
17747
+ if(!file) {
17748
+ var aaa = 1; //alert("Please select a file before clicking 'Load'");
17749
+ }
17750
+ else {
17751
+ me.htmlCls.setHtmlCls.fileSupport();
17752
+ let reader = new FileReader();
17753
+ reader.onload = async function(e) {
17754
+ let dataStr = e.target.result; // or = reader.result;
17755
+ thisClass.setLogCmd('load FASTA file ' + $("#" + me.pre + "fastafile").val(), false);
17756
+ ic.molTitle = "";
17757
+ ic.inputid = undefined;
17758
+ //ic.initUI();
17759
+ ic.init();
17760
+ ic.bInputfile = false; //true;
17761
+ ic.InputfileType = 'fasta';
17762
+ await ic.msaParserCls.loadMsaData(dataStr, 'fasta');
17763
+ };
17764
+ reader.readAsText(file);
17565
17765
  }
17766
+ });
17767
+
17768
+ me.myEventCls.onIds("#" + me.pre + "reload_afmapfile", "click", function(e) { let ic = me.icn3d;
17769
+ e.preventDefault();
17770
+ ic.bInitial = true;
17771
+ thisClass.iniFileLoad();
17566
17772
  let file = $("#" + me.pre + "afmapfile")[0].files[0];
17567
17773
  if(!file) {
17568
17774
  var aaa = 1; //alert("Please select a file before clicking 'Load'");
@@ -17584,14 +17790,7 @@ class Events {
17584
17790
  me.myEventCls.onIds("#" + me.pre + "reload_afmapfilefull", "click", function(e) { let ic = me.icn3d;
17585
17791
  e.preventDefault();
17586
17792
  ic.bInitial = true;
17587
- if(!me.cfg.notebook) dialog.dialog( "close" );
17588
- //close all dialog
17589
- if(!me.cfg.notebook) {
17590
- $(".ui-dialog-content").dialog("close");
17591
- }
17592
- else {
17593
- ic.resizeCanvasCls.closeDialogs();
17594
- }
17793
+ thisClass.iniFileLoad();
17595
17794
  let file = $("#" + me.pre + "afmapfile")[0].files[0];
17596
17795
  if(!file) {
17597
17796
  var aaa = 1; //alert("Please select a file before clicking 'Load'");
@@ -17613,14 +17812,7 @@ class Events {
17613
17812
  me.myEventCls.onIds("#" + me.pre + "reload_urlfile", "click", async function(e) { let ic = me.icn3d;
17614
17813
  e.preventDefault();
17615
17814
  ic.bInitial = true;
17616
- if(!me.cfg.notebook) dialog.dialog( "close" );
17617
- //close all dialog
17618
- if(!me.cfg.notebook) {
17619
- $(".ui-dialog-content").dialog("close");
17620
- }
17621
- else {
17622
- ic.resizeCanvasCls.closeDialogs();
17623
- }
17815
+ thisClass.iniFileLoad();
17624
17816
  let type = $("#" + me.pre + "filetype").val();
17625
17817
  let url = $("#" + me.pre + "urlfile").val();
17626
17818
  ic.inputurl = 'type=' + type + '&url=' + encodeURIComponent(url);
@@ -18487,6 +18679,24 @@ class Events {
18487
18679
  ic.selectionCls.saveSelection(name, name);
18488
18680
  });
18489
18681
 
18682
+ me.myEventCls.onIds("#" + me.pre + "saveFasta", "click", function(e) { me.icn3d;
18683
+ e.stopImmediatePropagation();
18684
+ thisClass.exportMsa('fasta');
18685
+ thisClass.setLogCmd('Save alignment in FASTA format', false);
18686
+ });
18687
+
18688
+ me.myEventCls.onIds("#" + me.pre + "saveClustal", "click", function(e) { me.icn3d;
18689
+ e.stopImmediatePropagation();
18690
+ thisClass.exportMsa('clustalw');
18691
+ thisClass.setLogCmd('Save alignment in CLUSTALWW format', false);
18692
+ });
18693
+
18694
+ me.myEventCls.onIds("#" + me.pre + "saveResbyres", "click", function(e) { me.icn3d;
18695
+ e.stopImmediatePropagation();
18696
+ thisClass.exportMsa('resbyres');
18697
+ thisClass.setLogCmd('Save alignment in Residue by Residue format to be used in File > Align (or Realign) > Multiple Chain > Residue by Residue', false);
18698
+ });
18699
+
18490
18700
  $(document).on("click", "." + me.pre + "outputselection", function(e) { let ic = me.icn3d;
18491
18701
  e.stopImmediatePropagation();
18492
18702
  ic.bSelectResidue = false;
@@ -19346,7 +19556,9 @@ class SetHtml {
19346
19556
 
19347
19557
  sequencesHtml += '<div style="width:20px; margin-left:3px; display:inline-block;"><span id="' + me.pre + 'alignseqguide' + suffix + '_expand" class="ui-icon ui-icon-plus icn3d-expand icn3d-link" style="width:15px;" title="Expand"></span><span id="' + me.pre + 'alignseqguide' + suffix + '_shrink" class="ui-icon ui-icon-minus icn3d-shrink icn3d-link" style="display:none; width:15px;" title="Shrink"></span></div> ';
19348
19558
 
19349
- sequencesHtml += "<div style='min-width:200px; display:inline-block;''><b>Selection:</b> Name: " + me.htmlCls.inputTextStr + "id='" + me.pre + "alignseq_command_name' value='alseq_" + index + "' size='10'> " + me.htmlCls.space2 + "<button style='white-space:nowrap;' id='" + me.pre + "alignseq_saveselection'>Save</button> <button style='white-space:nowrap; margin-left:20px;' id='" + me.pre + "alignseq_clearselection'>Clear</button></div><br/>";
19559
+ sequencesHtml += "<div style='min-width:200px; display:inline-block;'><b>Selection:</b> Name: " + me.htmlCls.inputTextStr + "id='" + me.pre + "alignseq_command_name' value='alseq_" + index + "' size='10'> " + me.htmlCls.space2 + "<button style='white-space:nowrap;' id='" + me.pre + "alignseq_saveselection'>Save</button> <button style='white-space:nowrap; margin-left:20px;' id='" + me.pre + "alignseq_clearselection'>Clear</button></div><br/>";
19560
+
19561
+ sequencesHtml += "<div style='min-width:200px; display:inline-block; margin-top:3px'><b>Save Alignment</b>: " + "<button style='white-space:nowrap;' id='" + me.pre + "saveFasta'>FASTA</button> <button style='white-space:nowrap; margin-left:20px;' id='" + me.pre + "saveClustal'>CLUSTALW</button> <button style='white-space:nowrap; margin-left:20px;' id='" + me.pre + "saveResbyres'>Residue by Residue</button></div><br/>";
19350
19562
 
19351
19563
  sequencesHtml += me.htmlCls.divStr + "alignseqguide" + suffix + "' style='display:none; white-space:normal;' class='icn3d-box'>";
19352
19564
 
@@ -19355,7 +19567,9 @@ class SetHtml {
19355
19567
  let resCategories = "<b>Residue labeling:</b> aligned residue with coordinates: UPPER case letter; non-aligned residue with coordinates: lower case letter which can be highlighted; residue missing coordinates: lower case letter which can NOT be highlighted.";
19356
19568
  let scroll =(me.utilsCls.isMac() && !me.utilsCls.isMobile()) ? "<br/><br/><b>Turn on scroll bar:</b> System preferences -> General -> show scroll bars -> check Always" : "";
19357
19569
 
19358
- sequencesHtml += resCategories + scroll + "<br/></div>";
19570
+ sequencesHtml += resCategories + scroll + "<br/>";
19571
+
19572
+ sequencesHtml += "</div>";
19359
19573
 
19360
19574
  return sequencesHtml;
19361
19575
  }
@@ -26600,7 +26814,12 @@ class Scene {
26600
26814
  ic.cams = {
26601
26815
  perspective: ic.perspectiveCamera,
26602
26816
  orthographic: ic.orthographicCamera,
26603
- };
26817
+ };
26818
+
26819
+ if(!me.bNode && ic.opts['effect'] == 'stereo' && !window.icn3duiHash) {
26820
+ ic.effect = ic.effects[options.effect];
26821
+ ic.effect.setSize(ic.container.width(), ic.container.height());
26822
+ }
26604
26823
  };
26605
26824
 
26606
26825
  setVrAr() { let ic = this.icn3d; ic.icn3dui;
@@ -30322,8 +30541,9 @@ class Strand {
30322
30541
  }
30323
30542
  }
30324
30543
 
30325
- // add one extra residue for coils between strands/helix
30326
- if(!isNaN(firstAtom.resi) && ic.pk === 3 && bHighlight === 1 && firstAtom.ss === 'coil') {
30544
+ // add one extra residue for coils between strands/helix if the style is NOT stick, ball and stick, lines, sphere, and dot
30545
+ // if(!isNaN(firstAtom.resi) && ic.pk === 3 && bHighlight === 1 && firstAtom.ss === 'coil') {
30546
+ if(!isNaN(firstAtom.resi) && ic.pk === 3 && bHighlight === 1 && firstAtom.ss === 'coil' && firstAtom.style != 'stick' && firstAtom.style != 'ball and stick' && firstAtom.style != 'lines' && firstAtom.style != 'sphere' && firstAtom.style != 'dot') {
30327
30547
  let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
30328
30548
  if(ic.residues.hasOwnProperty(residueid)) {
30329
30549
  atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
@@ -30358,8 +30578,8 @@ class Strand {
30358
30578
  }
30359
30579
  }
30360
30580
 
30361
- // add one extra residue for coils between strands/helix
30362
- if(ic.pk === 3 && bHighlight === 1 && lastAtom.ss === 'coil') {
30581
+ // add one extra residue for coils between strands/helix if the style is NOT stick, ball and stick, lines, sphere, and dot
30582
+ if(ic.pk === 3 && bHighlight === 1 && lastAtom.ss === 'coil' && firstAtom.style != 'stick' && firstAtom.style != 'ball and stick' && firstAtom.style != 'lines' && firstAtom.style != 'sphere' && firstAtom.style != 'dot') {
30363
30583
  let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + (parseInt(lastAtom.resi) + 1).toString();
30364
30584
  if(ic.residues.hasOwnProperty(residueid)) {
30365
30585
  atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
@@ -33209,6 +33429,7 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
33209
33429
  }
33210
33430
  else {
33211
33431
  // let index2ori = {};
33432
+ let maxdist = this.maxdist;
33212
33433
  for(let serial in atomlist) {
33213
33434
  let atom = atoms[atomlist[serial]];
33214
33435
 
@@ -33225,11 +33446,11 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
33225
33446
  }
33226
33447
 
33227
33448
  // show map near the structure
33228
- for(i = Math.floor(r.x) - this.maxdist, il = Math.ceil(r.x) + this.maxdist; i <= il; ++i) {
33449
+ for(i = Math.floor(r.x) - maxdist, il = Math.ceil(r.x) + maxdist; i <= il; ++i) {
33229
33450
  if(i < 0 || i > this.header.xExtent*this.scaleFactor - 1) continue;
33230
- for(j = Math.floor(r.y) - this.maxdist, jl = Math.ceil(r.y) + this.maxdist; j<= jl; ++j) {
33451
+ for(j = Math.floor(r.y) - maxdist, jl = Math.ceil(r.y) + maxdist; j<= jl; ++j) {
33231
33452
  if(j < 0 || j > this.header.yExtent*this.scaleFactor - 1) continue;
33232
- for(k = Math.floor(r.z) - this.maxdist, kl = Math.ceil(r.z) + this.maxdist; k<= kl; ++k) {
33453
+ for(k = Math.floor(r.z) - maxdist, kl = Math.ceil(r.z) + maxdist; k<= kl; ++k) {
33233
33454
  if(k < 0 || k > this.header.zExtent*this.scaleFactor - 1) continue;
33234
33455
  let index = i * widthHeight + j * height + k;
33235
33456
  indexArray.push(index);
@@ -33238,6 +33459,16 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
33238
33459
  }
33239
33460
  }
33240
33461
 
33462
+ // show all
33463
+ // for(i = 0; i < this.pLength; ++i) {
33464
+ // for(j = 0; j < this.pWidth; ++j) {
33465
+ // for(k = 0; k < this.pHeight; ++k) {
33466
+ // let index = i * widthHeight + j * height + k;
33467
+ // indexArray.push(index);
33468
+ // }
33469
+ // }
33470
+ // }
33471
+
33241
33472
  for(i = 0, il = indexArray.length; i < il; ++i) {
33242
33473
  let index = indexArray[i];
33243
33474
 
@@ -34499,6 +34730,7 @@ class ApplyDisplay {
34499
34730
  for(let residueid in singletonResidueHash) {
34500
34731
  // get calpha
34501
34732
  let calpha = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[residueid]);
34733
+ let sideAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.selectionCls.getSideAtoms(ic.residues[residueid]));
34502
34734
  let atom = calpha;
34503
34735
 
34504
34736
  let prevResidueid = atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) - 1).toString();
@@ -34515,7 +34747,7 @@ class ApplyDisplay {
34515
34747
  }
34516
34748
  else if( (atom.style === 'ribbon' && atom.ss === 'coil') || (atom.style === 'strand' && atom.ss === 'coil') || atom.style === 'o3 trace' || atom.style === 'schematic' || atom.style === 'c alpha trace' || atom.style === 'b factor tube' || (atom.style === 'cylinder and plate' && atom.ss !== 'helix') ) {
34517
34749
  // do not add extra residue if the side chain is shown
34518
- if(calpha !== undefined && calpha.style2 !== undefined && calpha.style2 !== 'nothing') continue;
34750
+ if(sideAtom !== undefined && sideAtom.style2 !== undefined && sideAtom.style2 !== 'nothing') continue;
34519
34751
 
34520
34752
  let bAddResidue = false;
34521
34753
  // add the next residue with same style
@@ -34550,7 +34782,7 @@ class ApplyDisplay {
34550
34782
  }
34551
34783
  else if( (atom.style === 'ribbon' && atom.ss !== 'coil' && atom.ssend) || (atom.style === 'strand' && atom.ss !== 'coil' && atom.ssend)) {
34552
34784
  // do not add extra residue if the side chain is shown
34553
- if(calpha !== undefined && calpha.style2 !== undefined && calpha.style2 !== 'nothing') continue;
34785
+ if(sideAtom !== undefined && sideAtom.style2 !== undefined && sideAtom.style2 !== 'nothing') continue;
34554
34786
 
34555
34787
  let bAddResidue = false;
34556
34788
  // add the next residue with same style
@@ -37435,11 +37667,18 @@ class Alternate {
37435
37667
  }
37436
37668
 
37437
37669
  if(ic.scene) {
37670
+ ic.renderer.clear();
37671
+
37438
37672
  // https://github.com/gkjohnson/three-gpu-pathtracer/blob/main/example/basic.js
37439
37673
  ic.renderer.outputEncoding = THREE.sRGBEncoding;
37440
37674
  //ic.renderer.outputEncoding = THREE.LinearEncoding
37441
37675
 
37442
- ic.renderer.render(ic.scene, cam);
37676
+ if(ic.opts['effect'] == 'stereo' && !window.icn3duiHash) {
37677
+ ic.effect.render(ic.scene, cam);
37678
+ }
37679
+ else {
37680
+ ic.renderer.render(ic.scene, cam);
37681
+ }
37443
37682
  }
37444
37683
  }
37445
37684
 
@@ -51816,13 +52055,20 @@ class ShowInter {
51816
52055
  }
51817
52056
  // do not change the set of displaying atoms
51818
52057
  //ic.dAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
51819
- let commandname, commanddesc;
52058
+ let commandname, commanddesc, commandname2;
51820
52059
  let firstAtom = ic.firstAtomObjCls.getFirstAtomObj(atomlistTarget);
52060
+
51821
52061
  if(firstAtom !== undefined) {
51822
52062
  commandname = "sphere." + firstAtom.chain + ":" + me.utilsCls.residueName2Abbr(firstAtom.resn.substr(0, 3)).trim() + firstAtom.resi + "-" + radius + "A";
51823
- if(bInteraction) commandname = "interactions." + firstAtom.chain + ":" + me.utilsCls.residueName2Abbr(firstAtom.resn.substr(0, 3)).trim() + firstAtom.resi + "-" + $("#" + ic.pre + "contactthreshold").val() + "A";
52063
+ //sometimes firstAtom.resi changed, thus we add a general name
52064
+ commandname2 = "sphere-" + radius + "A";
52065
+ if(bInteraction) {
52066
+ commandname = "interactions." + firstAtom.chain + ":" + me.utilsCls.residueName2Abbr(firstAtom.resn.substr(0, 3)).trim() + firstAtom.resi + "-" + $("#" + ic.pre + "contactthreshold").val() + "A";
52067
+ commandname2 = "interactions-" + $("#" + ic.pre + "contactthreshold").val() + "A";
52068
+ }
51824
52069
  commanddesc = commandname;
51825
52070
  ic.selectionCls.addCustomSelection(residueArray, commandname, commanddesc, select, true);
52071
+ ic.selectionCls.addCustomSelection(residueArray, commandname2, commanddesc, select, true);
51826
52072
  }
51827
52073
  ic.selectionCls.saveSelectionIfSelected();
51828
52074
  ic.drawCls.draw();
@@ -54000,6 +54246,7 @@ class ChainalignParser {
54000
54246
 
54001
54247
  ajaxArray.push(alignAjax);
54002
54248
  indexArray.push(index - 1);
54249
+ mmdbid_q = chainidArray[index].substr(0, chainidArray[index].indexOf('_'));
54003
54250
  struArray.push(mmdbid_q);
54004
54251
  }
54005
54252
 
@@ -54028,7 +54275,8 @@ class ChainalignParser {
54028
54275
  let mmdbid_q = struArray[i];
54029
54276
  let index = indexArray[i];
54030
54277
 
54031
- let bEqualMmdbid = (mmdbid_q == mmdbid_t);
54278
+ // let bEqualMmdbid = (mmdbid_q == mmdbid_t);
54279
+ let bEqualMmdbid = (mmdbid_q.substr(0,4) == mmdbid_t.substr(0,4));
54032
54280
  let bEqualChain = false;
54033
54281
 
54034
54282
  let queryData = {}; // check whether undefined
@@ -54278,7 +54526,7 @@ class ChainalignParser {
54278
54526
 
54279
54527
  transformStructure(mmdbid, index, alignType, bForce) { let ic = this.icn3d, me = ic.icn3dui;
54280
54528
  let chainidArray = ic.structures[mmdbid];
54281
-
54529
+
54282
54530
  for(let i = 0, il = chainidArray.length; i < il; ++i) {
54283
54531
  for(let serial in ic.chains[chainidArray[i]]) {
54284
54532
  let atm = ic.atoms[serial];
@@ -54410,6 +54658,26 @@ class ChainalignParser {
54410
54658
  return chainidArray;
54411
54659
  }
54412
54660
 
54661
+ addPostfixForStructureids(structArray) { let ic = this.icn3d; ic.icn3dui;
54662
+ let struct2cnt = {};
54663
+ for(let i = 0, il = structArray.length; i < il; ++i) {
54664
+ let struct = structArray[i].toUpperCase();
54665
+
54666
+ if(!struct2cnt.hasOwnProperty(struct)) {
54667
+ struct2cnt[struct] = 1;
54668
+ }
54669
+ else {
54670
+ ++struct2cnt[struct];
54671
+ }
54672
+
54673
+ struct = (struct2cnt[struct] == 1) ? struct : struct + struct2cnt[struct];
54674
+
54675
+ structArray[i] = struct;
54676
+ }
54677
+
54678
+ return structArray;
54679
+ }
54680
+
54413
54681
  async downloadChainalignment(chainalign) { let ic = this.icn3d, me = ic.icn3dui;
54414
54682
  let thisClass = this;
54415
54683
 
@@ -54451,6 +54719,7 @@ class ChainalignParser {
54451
54719
 
54452
54720
  ic.afChainIndexHash = {};
54453
54721
  ic.pdbChainIndexHash = {};
54722
+
54454
54723
  for(let index = 1, indexLen = alignArray.length; index < indexLen; ++index) {
54455
54724
  let pos2 = alignArray[index].indexOf('_');
54456
54725
  let mmdbid_q_tmp = alignArray[index].substr(0, pos2).toUpperCase();
@@ -54558,7 +54827,8 @@ class ChainalignParser {
54558
54827
 
54559
54828
  if(queryData !== undefined && JSON.stringify(queryData).indexOf('Oops there was a problem') === -1
54560
54829
  ) {
54561
- ic.mmdbidArray.push(mmdbid_q);
54830
+ // ic.mmdbidArray.push(mmdbid_q);
54831
+ ic.mmdbidArray.push(mmdbid_q.substr(0,4));
54562
54832
  queryDataArray.push(queryData);
54563
54833
  }
54564
54834
  else {
@@ -54597,7 +54867,8 @@ class ChainalignParser {
54597
54867
  // let align = (me.bNode) ? dataArray[index2 - missedChainCnt] : dataArray[index2 - missedChainCnt].value;//[0];
54598
54868
  let align = dataArray[index2 - missedChainCnt].value;//[0];
54599
54869
 
54600
- let bEqualMmdbid = (mmdbid_q == mmdbid_t);
54870
+ // let bEqualMmdbid = (mmdbid_q == mmdbid_t);
54871
+ let bEqualMmdbid = (mmdbid_q.substr(0,4) == mmdbid_t.substr(0,4));
54601
54872
  let bEqualChain = (chain_q == chain_t);
54602
54873
 
54603
54874
  me.htmlCls.clickMenuCls.setLogCmd("Align " + mmdbid_t + " with " + mmdbid_q, false);
@@ -54768,15 +55039,14 @@ class ChainalignParser {
54768
55039
 
54769
55040
  let structArray = [];
54770
55041
 
54771
- for(let i = 0, il = structArrayTmp.length; i < il; ++i) {
54772
- let id = structArrayTmp[i].toUpperCase();
54773
- // sometimes we want to load same structure multiple times
54774
- if(!ic.structures.hasOwnProperty(id) && structArray.indexOf(id) == -1) {
54775
- structArray.push(structArrayTmp[i]);
54776
- }
54777
- else {
54778
- // only when bNoDuplicate is undefined/false, it's allowed to load multiple copies of the same structure
54779
- if(!bNoDuplicate) structArray.push(structArrayTmp[i] + me.htmlCls.postfix);
55042
+ // only when bNoDuplicate is undefined/false, it's allowed to load multiple copies of the same structure
55043
+ if(!bNoDuplicate) {
55044
+ structArray = this.addPostfixForStructureids(structArrayTmp);
55045
+ }
55046
+ else {
55047
+ for(let i = 0, il = structArrayTmp.length; i < il; ++i) {
55048
+ let id = structArrayTmp[i].toUpperCase();
55049
+ if(!ic.structures.hasOwnProperty(id)) structArray.push(structArrayTmp[i]);
54780
55050
  }
54781
55051
  }
54782
55052
 
@@ -58771,6 +59041,283 @@ class XyzParser {
58771
59041
  }
58772
59042
  }
58773
59043
 
59044
+ /**
59045
+ * @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
59046
+ */
59047
+
59048
+ class MsaParser {
59049
+ constructor(icn3d) {
59050
+ this.icn3d = icn3d;
59051
+ }
59052
+
59053
+ async loadMsaData(data, type) { let ic = this.icn3d, me = ic.icn3dui;
59054
+ let bResult = await this.loadMsaSeqData(data, type);
59055
+
59056
+ if(me.cfg.align === undefined && Object.keys(ic.structures).length == 1) {
59057
+ $("#" + ic.pre + "alternateWrapper").hide();
59058
+ }
59059
+
59060
+ let typeStr = type.toUpperCase();
59061
+
59062
+ if(!bResult) {
59063
+ var aaa = 1; //alert('The ' + typeStr + ' file has the wrong format...');
59064
+ }
59065
+ else {
59066
+ // retrieve the structures
59067
+ me.cfg.bu = 0; // show all chains
59068
+ await ic.chainalignParserCls.downloadMmdbAf(ic.struArray.join(','));
59069
+ me.htmlCls.clickMenuCls.setLogCmd('load mmdbaf0 ' + ic.struArray.join(','), true);
59070
+
59071
+ // get the position of the first MSA residue in the full sequence
59072
+ let startPosArray = [];
59073
+ for(let i = 0, il = ic.inputChainidArray.length; i < il; ++i) {
59074
+ let chainid = ic.inputChainidArray[i];
59075
+ let inputSeqNoGap = ic.inputSeqArray[i].replace(/-/g, '');
59076
+
59077
+ // get the full seq
59078
+ let fullSeq = '';
59079
+ for(let j = 0, jl = ic.chainsSeq[chainid].length; j < jl; ++j) {
59080
+ fullSeq += ic.chainsSeq[chainid][j].name;
59081
+ }
59082
+
59083
+ // find the starting position of "inputSeq" in "fullSeq"
59084
+ let pos = fullSeq.toUpperCase().indexOf(inputSeqNoGap.substr(0, 20).toUpperCase());
59085
+ if(pos == -1) {
59086
+ console.log("The sequence of the aligned chain " + chainid + " (" + inputSeqNoGap.toUpperCase() + ") is different from the sequence from the structure (" + fullSeq.toUpperCase() + "), and is thus not aligned correctly...");
59087
+ pos = 0;
59088
+ }
59089
+ startPosArray.push(pos);
59090
+ }
59091
+
59092
+ // define residue mapping
59093
+ // The format is ": "-separated pairs: "1,5,10-50 | 1,5,10-50: 2,6,11-51 | 1,5,10-50"
59094
+ let predefinedres = '';
59095
+
59096
+ let chainid1 = ic.inputChainidArray[0], inputSeq1 = ic.inputSeqArray[0], pos1 = startPosArray[0];
59097
+ // loop through 2nd and forward
59098
+ for(let i = 1, il = ic.inputChainidArray.length; i < il; ++i) {
59099
+ let chainid2 = ic.inputChainidArray[i];
59100
+ let inputSeq2 = ic.inputSeqArray[i];
59101
+ let pos2 = startPosArray[i];
59102
+
59103
+ let index1 = pos1, index2 = pos2;
59104
+ let resiArray1 = [], resiArray2 = [];
59105
+ for(let j = 0, jl = inputSeq2.length; j < jl; ++j) {
59106
+ if(inputSeq1[j] != '-' && inputSeq2[j] != '-' && ic.chainsSeq[chainid1][index1] && ic.chainsSeq[chainid2][index2]) {
59107
+ let resi1 = ic.chainsSeq[chainid1][index1].resi;
59108
+ let resi2 = ic.chainsSeq[chainid2][index2].resi;
59109
+ if(ic.residues[chainid1 + '_' + resi1] && ic.residues[chainid2 + '_' + resi2]) {
59110
+ resiArray1.push(ic.chainsSeq[chainid1][index1].resi);
59111
+ resiArray2.push(ic.chainsSeq[chainid2][index2].resi);
59112
+ }
59113
+ }
59114
+
59115
+ if(inputSeq1[j] != '-') ++index1;
59116
+ if(inputSeq2[j] != '-') ++index2;
59117
+ }
59118
+ let resiRangeStr1 = ic.resid2specCls.resi2range(resiArray1, true);
59119
+ let resiRangeStr2 = ic.resid2specCls.resi2range(resiArray2, true);
59120
+
59121
+ predefinedres += resiRangeStr1 + ' | ' + resiRangeStr2;
59122
+ if(i < il -1) predefinedres += ': ';
59123
+ }
59124
+
59125
+ // realign based on residue by residue
59126
+ let alignment_final = ic.inputChainidArray.join(',');
59127
+
59128
+ if(predefinedres && (alignment_final.split(',').length - 1) != predefinedres.split(': ').length) {
59129
+ var aaa = 1; //alert("Please make sure the number of chains and the lines of predefined residues are the same...");
59130
+ return;
59131
+ }
59132
+
59133
+ me.cfg.resdef = predefinedres.replace(/:/gi, ';');
59134
+
59135
+ let bRealign = true, bPredefined = true;
59136
+ let chainidArray = alignment_final.split(',');
59137
+ await ic.realignParserCls.realignChainOnSeqAlign(undefined, chainidArray, bRealign, bPredefined);
59138
+
59139
+ me.htmlCls.clickMenuCls.setLogCmd("realign predefined " + alignment_final + " " + predefinedres, true);
59140
+
59141
+
59142
+ ic.opts['color'] = 'identity';
59143
+ ic.setColorCls.setColorByOptions(ic.opts, ic.hAtoms);
59144
+ me.htmlCls.clickMenuCls.setLogCmd("color identity", true);
59145
+
59146
+ // show selection
59147
+ ic.selectionCls.showSelection();
59148
+ me.htmlCls.clickMenuCls.setLogCmd("show selection", true);
59149
+ }
59150
+ }
59151
+
59152
+ async loadMsaSeqData(data, type) { let ic = this.icn3d; ic.icn3dui;
59153
+ let lines = data.split(/\r?\n|\r/);
59154
+ if(lines.length < 2) return false;
59155
+
59156
+ ic.init();
59157
+
59158
+ ic.molTitle = "";
59159
+
59160
+ let seqHash = {};
59161
+
59162
+ let bStart = false, bSecBlock = false, chainid = '', seq = '', bFound = false;
59163
+
59164
+ if(type == 'clustalw' && lines[0].substr(0,7) != 'CLUSTAL') { // CLUSTAL W or CLUSTALW
59165
+ return false;
59166
+ }
59167
+
59168
+ let startLineNum = (type == 'clustalw') ? 1 : 0;
59169
+
59170
+ // 1. parse input msa
59171
+ for(let i = startLineNum, il = lines.length; i < il; ++i) {
59172
+ let line = lines[i].trim();
59173
+ if(line === '') {
59174
+ if(bStart) bSecBlock = true;
59175
+ bStart = false;
59176
+ continue;
59177
+ }
59178
+
59179
+ if(!bStart) { // first line
59180
+ if(type == 'fasta' && line.substr(0,1) != '>') {
59181
+ return false;
59182
+ }
59183
+ bStart = true;
59184
+ }
59185
+
59186
+ if(type == 'clustalw') {
59187
+ if(line.substr(0, 1) != ' ' && line.substr(0, 1) != '\t') {
59188
+ let chainid_seq = line.split(/\s+/);
59189
+ let idArray = chainid_seq[0].split('|');
59190
+ let result = this.getChainid(idArray, bStart && !bSecBlock);
59191
+ bFound = result.bFound;
59192
+ chainid = result.chainid;
59193
+
59194
+ if(bFound) {
59195
+ if(!seqHash.hasOwnProperty(chainid)) {
59196
+ seqHash[chainid] = chainid_seq[1];
59197
+ }
59198
+ else {
59199
+ seqHash[chainid] += chainid_seq[1];
59200
+ }
59201
+ }
59202
+ }
59203
+ }
59204
+ else if(type == 'fasta') {
59205
+ if(line.substr(0,1) == ">") {
59206
+ // add the previous seq
59207
+ if(chainid && seq && bFound) seqHash[chainid] = seq;
59208
+ chainid = '';
59209
+ seq = '';
59210
+
59211
+ let pos = line.indexOf(' ');
59212
+ let idArray = line.substr(1, pos).split('|');
59213
+
59214
+ if(idArray.length == 1) {
59215
+ chainid = idArray[0];
59216
+ }
59217
+ else {
59218
+ let result = this.getChainid(idArray, true);
59219
+ bFound = result.bFound;
59220
+ chainid = result.chainid;
59221
+ }
59222
+ }
59223
+ else {
59224
+ seq += line;
59225
+ }
59226
+ }
59227
+ }
59228
+
59229
+ // add the last seq
59230
+ if(type == 'fasta' && chainid && seq && bFound) seqHash[chainid] = seq;
59231
+
59232
+ // 2. get the PDB ID or RefSeqID or AlphaFold ID
59233
+ ic.inputChainidArray = [];
59234
+ ic.inputSeqArray = [];
59235
+ ic.struArray = [];
59236
+
59237
+ // find the tempate where the first residue is not gap
59238
+ let template = '';
59239
+ for(let chainid in seqHash) {
59240
+ let seq = seqHash[chainid];
59241
+ if(seq.substr(0,1) != '-') {
59242
+ template = chainid;
59243
+ await this.processOneChain(chainid, seqHash);
59244
+ break;
59245
+ }
59246
+ }
59247
+ if(!template) template = Object.keys(seqHash)[0];
59248
+
59249
+ for(let chainid in seqHash) {
59250
+ if(chainid != template) await this.processOneChain(chainid, seqHash);
59251
+ }
59252
+
59253
+ return true;
59254
+ }
59255
+
59256
+ async processOneChain(chainid, seqHash) { let ic = this.icn3d, me = ic.icn3dui;
59257
+ ic.inputSeqArray.push(seqHash[chainid]);
59258
+ // ic.inputSeqArray.push(seqHash[chainid].replace(/-/g, '')); // remove the gaps in seq
59259
+
59260
+ if(chainid.lastIndexOf('_') == 2) { // refseq ID
59261
+ // convert refseq to uniprot id
59262
+ let url = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi?refseq2uniprot=" + chainid;
59263
+
59264
+ let data = await me.getAjaxPromise(url, 'jsonp', false, 'The protein accession ' + chainid + ' can not be mapped to AlphaFold UniProt ID...');
59265
+ if(data && data.uniprot) {
59266
+ if(!ic.uniprot2acc) ic.uniprot2acc = {};
59267
+ let uniprot = data.uniprot;
59268
+ ic.uniprot2acc[uniprot] = chainid;
59269
+ ic.struArray.push(uniprot);
59270
+ ic.inputChainidArray.push(uniprot + '_A');
59271
+ }
59272
+ else {
59273
+ console.log('The accession ' + refseqid + ' can not be mapped to AlphaFold UniProt ID. It will be treated as a UniProt ID instead.');
59274
+ ic.struArray.push(chainid);
59275
+ ic.inputChainidArray.push(chainid + '_A');
59276
+ }
59277
+ }
59278
+ else if(chainid.indexOf('_') != -1) { // PDB ID
59279
+ let stru = chainid.substr(0, chainid.indexOf('_')).substr(0, 4);
59280
+ ic.struArray.push(stru);
59281
+ ic.inputChainidArray.push(chainid);
59282
+ }
59283
+ else if(chainid.length > 5) { // UniProt ID
59284
+ ic.struArray.push(chainid);
59285
+ ic.inputChainidArray.push(chainid + '_A');
59286
+ }
59287
+ }
59288
+
59289
+ getChainid(idArray, bWarning) { let ic = this.icn3d; ic.icn3dui;
59290
+ let bFound = false;
59291
+ let chainid = idArray[0];
59292
+
59293
+ for(let j = 0, jl = idArray.length; j < jl; ++j) {
59294
+ if(idArray[j] == 'pdb') {
59295
+ chainid = idArray[j+1] + '_' + idArray[j+2];
59296
+ bFound = true;
59297
+ break;
59298
+ }
59299
+ else if(idArray[j] == 'ref') { // refseq
59300
+ let refseq = idArray[j+1].split('.')[0];
59301
+ chainid = refseq; // + '_A';
59302
+ bFound = true;
59303
+ break;
59304
+ }
59305
+ else if(idArray[j] == 'sp' || idArray[j] == 'tr') { // uniprot
59306
+ let uniprot = idArray[j+1];
59307
+ chainid = uniprot;
59308
+ bFound = true;
59309
+ break;
59310
+ }
59311
+ }
59312
+
59313
+ if(!bFound && bWarning) {
59314
+ var aaa = 1; //alert("The sequence ID " + idArray.join('|') + " does not have the correctly formatted PDB, UniProt or RefSeq ID...");
59315
+ }
59316
+
59317
+ return {chainid: chainid, bFound: bFound};
59318
+ }
59319
+ }
59320
+
58774
59321
  /**
58775
59322
  * @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
58776
59323
  */
@@ -58912,7 +59459,7 @@ class RealignParser {
58912
59459
  // If rmsd from vastsrv is too large, realign the chains
58913
59460
  //if(me.cfg.chainalign && !me.cfg.usepdbnum && me.cfg.resdef && rmsd > 5) {
58914
59461
  // redo algnment only for VAST serv page
58915
- if(!me.cfg.usepdbnum && me.cfg.resdef && rmsd > 5) {
59462
+ if(!me.cfg.usepdbnum && me.cfg.resdef && rmsd > 5 && me.cfg.chainalign) {
58916
59463
  console.log("RMSD from VAST is larger than 5. Realign the chains with TM-align.");
58917
59464
  //let nameArray = me.cfg.chainalign.split(',');
58918
59465
  let nameArray = Object.keys(chainidHash);
@@ -59368,7 +59915,8 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
59368
59915
  let predefinedResArray, predefinedResPair;
59369
59916
 
59370
59917
  if(bPredefined) {
59371
- predefinedResArray = decodeURIComponent(me.cfg.resdef).trim().replace(/\+/gi, ' ').split(': ');
59918
+ // predefinedResArray = decodeURIComponent(me.cfg.resdef).trim().replace(/\+/gi, ' ').split(': ');
59919
+ predefinedResArray = decodeURIComponent(me.cfg.resdef).trim().replace(/\+/gi, ' ').split('; ');
59372
59920
 
59373
59921
  if(predefinedResArray.length != chainidArray.length - 1) {
59374
59922
  var aaa = 1; //alert("Please make sure the number of chains and the lines of predefined residues are the same...");
@@ -59645,7 +60193,7 @@ class DensityCifParser {
59645
60193
  let thisClass = this;
59646
60194
 
59647
60195
  let url;
59648
- let detail = (me.utilsCls.isMobile() || me.cfg.notebook) ? 2 : 4; //0 : 4;
60196
+ let detail = (me.utilsCls.isMobile() || me.cfg.notebook) ? 0 : 4; // max 6
59649
60197
 
59650
60198
  //https://www.ebi.ac.uk/pdbe/densities/doc.html
59651
60199
  if(type == '2fofc' || type == 'fofc') {
@@ -59656,6 +60204,7 @@ class DensityCifParser {
59656
60204
  url = "https://www.ebi.ac.uk/pdbe/volume-server/x-ray/" + pdbid.toLowerCase() + "/box/" + min_max[0][0] + "," + min_max[0][1] + "," + min_max[0][2] + "/" + min_max[1][0] + "," + min_max[1][1] + "," + min_max[1][2] + "?detail=" + detail;
59657
60205
  }
59658
60206
  else if(type == 'em') {
60207
+ detail = (me.utilsCls.isMobile() || me.cfg.notebook) ? 0: 5; // max 6
59659
60208
  url = "https://www.ebi.ac.uk/pdbe/densities/emd/" + emd.toLowerCase() + "/cell?detail=" + detail;
59660
60209
  }
59661
60210
 
@@ -61229,11 +61778,12 @@ class ParserUtils {
61229
61778
 
61230
61779
  // set defined sets before loadScript
61231
61780
  if(ic.bInitial) {
61232
- if(me.cfg.mobilemenu) {
61233
- me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
61234
- let bNoSave = true;
61235
- me.htmlCls.clickMenuCls.applyShownMenus(bNoSave);
61236
- }
61781
+ // if(me.cfg.mobilemenu) {
61782
+ // me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
61783
+ // let bNoSave = true;
61784
+ // me.htmlCls.clickMenuCls.applyShownMenus(bNoSave);
61785
+ // }
61786
+
61237
61787
  // else {
61238
61788
  // me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
61239
61789
  // me.htmlCls.clickMenuCls.applyShownMenus();
@@ -62270,6 +62820,7 @@ class SetSeqAlign {
62270
62820
  setSeqAlign(seqalign, alignedStructures) { let ic = this.icn3d, me = ic.icn3dui;
62271
62821
  let mmdbid1 = alignedStructures[0][0].pdbId;
62272
62822
  let mmdbid2 = alignedStructures[0][1].pdbId;
62823
+ let chainid1, chainid2;
62273
62824
 
62274
62825
  ic.conservedName1 = mmdbid1 + '_cons';
62275
62826
  ic.nonConservedName1 = mmdbid1 + '_ncons';
@@ -62293,7 +62844,7 @@ class SetSeqAlign {
62293
62844
  let molid1 = alignData.moleculeId;
62294
62845
 
62295
62846
  let chain1 = ic.pdbid_molid2chain[mmdbid1 + '_' + molid1];
62296
- let chainid1 = mmdbid1 + '_' + chain1;
62847
+ chainid1 = mmdbid1 + '_' + chain1;
62297
62848
 
62298
62849
  let id2aligninfo = {};
62299
62850
  let start = alignData.sequence.length, end = -1;
@@ -62325,7 +62876,7 @@ class SetSeqAlign {
62325
62876
  let molid2 = alignData.moleculeId;
62326
62877
 
62327
62878
  let chain2 = ic.pdbid_molid2chain[mmdbid2 + '_' + molid2];
62328
- let chainid2 = mmdbid2 + '_' + chain2;
62879
+ chainid2 = mmdbid2 + '_' + chain2;
62329
62880
 
62330
62881
  // annotation title for the master seq only
62331
62882
  if(ic.alnChainsAnTtl[chainid1] === undefined ) ic.alnChainsAnTtl[chainid1] = [];
@@ -62493,7 +63044,9 @@ class SetSeqAlign {
62493
63044
  ic.alnChainsAnno[chainid1][3].push(numberStr); // symbol: 10, 20, etc, empty for rest
62494
63045
 
62495
63046
  ++alignIndex;
62496
- } // end for(let j
63047
+ } // end for(let j
63048
+
63049
+ this.setMsaFormat([chainid1, chainid2]);
62497
63050
  } // end for(let i
62498
63051
 
62499
63052
  seqalign = {};
@@ -62573,7 +63126,7 @@ class SetSeqAlign {
62573
63126
  }
62574
63127
 
62575
63128
  setSeqAlignChain(chainid, chainIndex, chainidArray) { let ic = this.icn3d, me = ic.icn3dui;
62576
- let hAtoms = {};
63129
+ let hAtoms = {};
62577
63130
 
62578
63131
  let bRealign = (chainidArray) ? true : false;
62579
63132
  let mmdbid1, mmdbid2, chain1, chain2, chainid1, chainid2, pos1, pos2;
@@ -62794,23 +63347,6 @@ class SetSeqAlign {
62794
63347
  ///if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid2] === undefined) break;
62795
63348
 
62796
63349
  let resi1, resi2, resn1, resn2;
62797
- /*
62798
- if(bRealign) { // tmalign: just one residue in this for loop
62799
- if(me.cfg.aligntool == 'tmalign') {
62800
- resi1 = ic.qt_start_end[chainIndex][i].t_start;
62801
- resi2 = ic.qt_start_end[chainIndex][i].q_start;
62802
- }
62803
- else {
62804
- resi1 = j + start1;
62805
- resi2 = j + start2;
62806
- }
62807
-
62808
- resn1 = this.getResnFromResi(chainid1, resi1).toUpperCase();
62809
- resn2 = this.getResnFromResi(chainid2, resi2).toUpperCase();
62810
-
62811
- if(resn1 == '?' || resn2 == '?') continue;
62812
- }
62813
- */
62814
63350
  if(bRealign && me.cfg.aligntool == 'tmalign') { // tmalign: just one residue in this for loop
62815
63351
  resi1 = ic.qt_start_end[chainIndex][i].t_start;
62816
63352
  resi2 = ic.qt_start_end[chainIndex][i].q_start;
@@ -62821,15 +63357,6 @@ class SetSeqAlign {
62821
63357
  if(resn1 == '?' || resn2 == '?') continue;
62822
63358
  }
62823
63359
  else {
62824
- ///if(ic.chainsSeq[chainid1][j + start1] === undefined || ic.chainsSeq[chainid2][j + start2] === undefined) continue;
62825
-
62826
- // resi1 = ic.chainsSeq[chainid1][j + start1].resi;
62827
- // resi2 = ic.chainsSeq[chainid2][j + start2].resi;
62828
- // resn1 = ic.chainsSeq[chainid1][j + start1].name.toUpperCase();
62829
- // resn2 = ic.chainsSeq[chainid2][j + start2].name.toUpperCase();
62830
-
62831
- // resi1 = this.getResiAferAlign(chainid1, bRealign, j + start1 + 1);
62832
- // resi2 = this.getResiAferAlign(chainid2, bRealign, j + start2 + 1);
62833
63360
  resi1 = this.getResiAferAlign(chainid1, bRealign, j + start1);
62834
63361
  resi2 = this.getResiAferAlign(chainid2, bRealign, j + start2);
62835
63362
  resn1 = this.getResnFromResi(chainid1, resi1).toUpperCase();
@@ -62869,14 +63396,15 @@ class SetSeqAlign {
62869
63396
 
62870
63397
  prevIndex1 = end1;
62871
63398
  prevIndex2 = end2;
62872
- } // end for(let i
63399
+ } // end for(let i
63400
+
63401
+ this.setMsaFormat([chainid1, chainid2]);
62873
63402
 
62874
63403
  return hAtoms;
62875
63404
  }
62876
63405
 
62877
63406
  setSeqAlignChainForAll(chainidArray, index_alignLen, bRealign) { let ic = this.icn3d, me = ic.icn3dui;
62878
63407
  let hAtoms = {};
62879
-
62880
63408
  let chainid1 = chainidArray[0];
62881
63409
 
62882
63410
  ic.alnChainsAnno[chainid1] = [];
@@ -63030,7 +63558,8 @@ class SetSeqAlign {
63030
63558
  resObject.aligned = (resid2range_t[resid]) ? true : false;
63031
63559
  resObject.color = (resid2range_t[resid]) ? '#FF0000' : me.htmlCls.GREYC; // color by identity
63032
63560
  resObject.color2 = (resid2range_t[resid]) ? '#FF0000' : me.htmlCls.GREYC; // color by conservation
63033
- resObject.class = (resid2range_t[resid]) ? 'icn3d-align' : 'icn3d-nalign';
63561
+ // resObject.class = (resid2range_t[resid]) ? 'icn3d-align' : 'icn3d-nalign';
63562
+ resObject.class = (resid2range_t[resid]) ? 'icn3d-cons' : 'icn3d-nalign';
63034
63563
 
63035
63564
  ic.alnChainsSeq[chainid1].push(resObject);
63036
63565
 
@@ -63049,7 +63578,9 @@ class SetSeqAlign {
63049
63578
  let hAtomsTmp = this.mergeTwoSeqForAll(chainidArray, index, alignedChainIndice, resid2range_t, start_t, end_t, bRealign);
63050
63579
 
63051
63580
  hAtoms = me.hashUtilsCls.unionHash(hAtoms, hAtomsTmp);
63052
- }
63581
+ }
63582
+
63583
+ this.setMsaFormat(chainidArray);
63053
63584
 
63054
63585
  // 3. assign the variable ic.alnChainsAnno
63055
63586
  for(let i = 0; i < 3 + 2*n; ++i) {
@@ -63120,7 +63651,7 @@ class SetSeqAlign {
63120
63651
  resObject.aligned = (bGap) ? false : bAligned;
63121
63652
  resObject.color = (bGap || !bAligned) ? me.htmlCls.GREYC : ((resn == resn_t) ? "#FF0000" : "#0000FF"); // color by identity
63122
63653
  resObject.color2 = (bGap || !bAligned) ? me.htmlCls.GREYC : '#' + ic.showAnnoCls.getColorhexFromBlosum62(resn, resn_t); // color by conservation
63123
- resObject.class = (bGap || !bAligned) ? 'icn3d-nalign' : 'icn3d-align';
63654
+ resObject.class = (bGap || !bAligned) ? 'icn3d-nalign' : ((resn == resn_t) ? "icn3d-cons" : "icn3d-ncons");
63124
63655
 
63125
63656
  return resObject;
63126
63657
  }
@@ -63394,7 +63925,7 @@ class SetSeqAlign {
63394
63925
  pos2 = result.pos2;
63395
63926
  for(let i = pos1; i < pos2; ++i) {
63396
63927
  //for(let i = pos1; i <= pos2; ++i) {
63397
- ic.alnChainsSeq[chainid2].push(gapResObject2);
63928
+ ic.alnChainsSeq[chainid2].push(gapResObject2);
63398
63929
  }
63399
63930
 
63400
63931
  return hAtoms;
@@ -63721,6 +64252,108 @@ class SetSeqAlign {
63721
64252
  }
63722
64253
  }
63723
64254
  }
64255
+
64256
+ setMsaFormat(chainidArray) { let ic = this.icn3d; ic.icn3dui;
64257
+ //set MSA
64258
+ let fastaFormat = '', clustalwFormat = 'CLUSTALWW\n\n', resbyresFormat = '';
64259
+ let chainArrayClustal = [];
64260
+
64261
+ let consArray = [], resiArrayTemplate = [];
64262
+ let chainidTemplate = chainidArray[0];
64263
+ for(let i = 0, il = chainidArray.length; i < il; ++i) {
64264
+ let chainid = chainidArray[i];
64265
+ fastaFormat += '>' + chainid + '\n';
64266
+
64267
+ let clustalwArray = [];
64268
+ let clustalwLine = chainid.padEnd(20, ' ');
64269
+ let consLine = ''.padEnd(20, ' ');
64270
+
64271
+ let resiArrayTarget = [], resiArrayQuery = [];
64272
+
64273
+ let cnt = 0;
64274
+ for(let j = 0, jl = ic.alnChainsSeq[chainid].length; j < jl; ++j) {
64275
+ let resn = ic.alnChainsSeq[chainid][j].resn;
64276
+ fastaFormat += resn;
64277
+ clustalwLine += resn;
64278
+ if(i == il - 1) {
64279
+ let alignedClass = ic.alnChainsSeq[chainid][j].class;
64280
+ if(alignedClass == 'icn3d-cons') {
64281
+ consLine += '*';
64282
+ }
64283
+ else if(alignedClass == 'icn3d-ncons') {
64284
+ consLine += '.';
64285
+ }
64286
+ else {
64287
+ consLine += ' ';
64288
+ }
64289
+ }
64290
+
64291
+ // residue by residue
64292
+ if(i == 0) {
64293
+ resiArrayTemplate.push(ic.alnChainsSeq[chainid][j].resi);
64294
+ }
64295
+ else {
64296
+ // if(ic.alnChainsSeq[chainid][j].aligned) {
64297
+ if(ic.alnChainsSeq[chainid][j].aligned && ic.alnChainsSeq[chainidTemplate][j] && ic.alnChainsSeq[chainid][j]) {
64298
+ resiArrayTarget.push(ic.alnChainsSeq[chainidTemplate][j].resi);
64299
+ resiArrayQuery.push(ic.alnChainsSeq[chainid][j].resi);
64300
+ }
64301
+ }
64302
+
64303
+ ++cnt;
64304
+
64305
+ if(cnt % 60 == 0) {
64306
+ fastaFormat += '\n';
64307
+ clustalwLine += ' ' + String(parseInt(cnt / 60) * 60);
64308
+ clustalwArray.push(clustalwLine);
64309
+ clustalwLine = chainid.padEnd(20, ' ');
64310
+
64311
+ if(i == il - 1) {
64312
+ consArray.push(consLine);
64313
+ consLine = ''.padEnd(20, ' ');
64314
+ }
64315
+ }
64316
+ }
64317
+
64318
+ // add last line
64319
+ if(cnt % 60 != 0) {
64320
+ clustalwArray.push(clustalwLine);
64321
+ if(i == il - 1) {
64322
+ consArray.push(consLine);
64323
+ }
64324
+ }
64325
+
64326
+ fastaFormat += '\n';
64327
+
64328
+ chainArrayClustal.push(clustalwArray);
64329
+ if(i == il - 1) chainArrayClustal.push(consArray);
64330
+
64331
+ // residue by residue
64332
+ let resiRangeStr1 = ic.resid2specCls.resi2range(resiArrayTarget, true);
64333
+ let resiRangeStr2 = ic.resid2specCls.resi2range(resiArrayQuery, true);
64334
+
64335
+ if(i > 0) resbyresFormat += resiRangeStr1 + ' | ' + resiRangeStr2 + '\n';
64336
+ }
64337
+
64338
+ // CLUSTALWW
64339
+ for(let j = 0, jl = chainArrayClustal[0].length; j < jl; ++j) {
64340
+ for(let i = 0, il = chainArrayClustal.length; i < il; ++i) {
64341
+ clustalwFormat += chainArrayClustal[i][j] + '\n';
64342
+ }
64343
+ clustalwFormat += '\n';
64344
+ }
64345
+
64346
+ // seq MSA
64347
+ if(!ic.msa) ic.msa = {};
64348
+
64349
+ if(!ic.msa['fasta']) ic.msa['fasta'] = [];
64350
+ if(!ic.msa['clustalw']) ic.msa['clustalw'] = [];
64351
+ if(!ic.msa['resbyres']) ic.msa['resbyres'] = [];
64352
+
64353
+ ic.msa['fasta'].push(fastaFormat);
64354
+ ic.msa['clustalw'].push(clustalwFormat);
64355
+ ic.msa['resbyres'].push(resbyresFormat);
64356
+ }
63724
64357
  }
63725
64358
 
63726
64359
  /**
@@ -66474,6 +67107,12 @@ class ApplyCommand {
66474
67107
  else if(command == 'set slab off') {
66475
67108
  ic.opts['slab'] = 'no';
66476
67109
  }
67110
+ else if(command == 'stereo on') {
67111
+ ic.opts['effect'] = 'stereo';
67112
+ }
67113
+ else if(command == 'stereo off') {
67114
+ ic.opts['effect'] = 'none';
67115
+ }
66477
67116
  else if(command == 'set assembly on') {
66478
67117
  ic.bAssembly = true;
66479
67118
  }
@@ -68547,16 +69186,26 @@ class DefinedSets {
68547
69186
  } // outer for
68548
69187
  }
68549
69188
 
68550
- setHAtomsFromSets(nameArray, type) { let ic = this.icn3d, me = ic.icn3dui;
69189
+ setHAtomsFromSets(nameArray, type) { let ic = this.icn3d; ic.icn3dui;
68551
69190
  for(let i = 0; i < nameArray.length; ++i) {
68552
69191
  let selectedSet = nameArray[i];
68553
69192
 
68554
- if((ic.defNames2Atoms === undefined || !ic.defNames2Atoms.hasOwnProperty(selectedSet)) &&(ic.defNames2Residues === undefined || !ic.defNames2Residues.hasOwnProperty(selectedSet)) ) continue;
69193
+ this.setHAtomsFromSets_base(selectedSet, type);
68555
69194
 
69195
+ // sometimes the "resi" changed and thus the name changed
69196
+ //"sphere." + firstAtom.chain + ":" + me.utilsCls.residueName2Abbr(firstAtom.resn.substr(0, 3)).trim() + firstAtom.resi + "-" + radius + "A";
69197
+ if(Object.keys(ic.hAtoms).length == 0 && (selectedSet.split('.')[0] == 'sphere' || selectedSet.split('.')[0] == 'interactions')) {
69198
+ let pos = selectedSet.lastIndexOf('-');
69199
+ selectedSet = selectedSet.split('.')[0] + selectedSet.substr(pos);
69200
+ this.setHAtomsFromSets_base(selectedSet, type);
69201
+ }
69202
+ } // outer for
69203
+ }
69204
+
69205
+ setHAtomsFromSets_base(selectedSet, type) { let ic = this.icn3d, me = ic.icn3dui;
68556
69206
  if(ic.defNames2Atoms !== undefined && ic.defNames2Atoms.hasOwnProperty(selectedSet)) {
68557
69207
 
68558
69208
  let atomArray = ic.defNames2Atoms[selectedSet];
68559
-
68560
69209
  if(type === 'or') {
68561
69210
  for(let j = 0, jl = atomArray.length; j < jl; ++j) {
68562
69211
  ic.hAtoms[atomArray[j]] = 1;
@@ -68602,7 +69251,6 @@ class DefinedSets {
68602
69251
  ic.hAtoms = me.hashUtilsCls.exclHash(ic.hAtoms, atomHash);
68603
69252
  }
68604
69253
  }
68605
- } // outer for
68606
69254
  }
68607
69255
 
68608
69256
  updateAdvancedCommands(nameArray, type) { let ic = this.icn3d; ic.icn3dui;
@@ -68625,6 +69273,7 @@ class DefinedSets {
68625
69273
 
68626
69274
  combineSets(orArray, andArray, notArray, commandname) { let ic = this.icn3d, me = ic.icn3dui;
68627
69275
  ic.hAtoms = {};
69276
+
68628
69277
  this.setHAtomsFromSets(orArray, 'or');
68629
69278
 
68630
69279
  if(Object.keys(ic.hAtoms).length == 0) {
@@ -70720,19 +71369,22 @@ class Selection {
70720
71369
  selectSideChains() { let ic = this.icn3d, me = ic.icn3dui;
70721
71370
  let currHAtoms = me.hashUtilsCls.cloneHash(ic.hAtoms);
70722
71371
 
70723
- //let nuclMainArray = ["C1'", "C1*", "C2'", "C2*", "C3'", "C3*", "C4'", "C4*", "C5'", "C5*", "O3'", "O3*", "O4'", "O4*", "O5'", "O5*", "P", "OP1", "O1P", "OP2", "O2P"];
71372
+ ic.hAtoms = this.getSideAtoms(currHAtoms);
71373
+ ic.hlUpdateCls.showHighlight();
71374
+ }
70724
71375
 
70725
- ic.hAtoms = {};
70726
- for(let i in currHAtoms) {
71376
+ getSideAtoms(atoms) { let ic = this.icn3d, me = ic.icn3dui;
71377
+ let sideAtoms = {};
71378
+ for(let i in atoms) {
70727
71379
  if((ic.proteins.hasOwnProperty(i) && ic.atoms[i].name !== "N" && ic.atoms[i].name !== "H"
70728
71380
  && ic.atoms[i].name !== "C" && ic.atoms[i].name !== "O"
70729
71381
  && !(ic.atoms[i].name === "CA" && ic.atoms[i].elem === "C") && ic.atoms[i].name !== "HA")
70730
71382
  ||(ic.nucleotides.hasOwnProperty(i) && me.parasCls.nuclMainArray.indexOf(ic.atoms[i].name) === -1) ) {
70731
- ic.hAtoms[i] = 1;
71383
+ sideAtoms[i] = 1;
70732
71384
  }
70733
71385
  }
70734
71386
 
70735
- ic.hlUpdateCls.showHighlight();
71387
+ return sideAtoms;
70736
71388
  }
70737
71389
 
70738
71390
  selectMainSideChains() { let ic = this.icn3d, me = ic.icn3dui;
@@ -71345,21 +71997,29 @@ class Resid2spec {
71345
71997
  return spec;
71346
71998
  }
71347
71999
 
71348
- resi2range(resiArray) {var ic = this.icn3d; ic.icn3dui;
71349
- let range = [];
72000
+ resi2range(resiArray, bString) {var ic = this.icn3d; ic.icn3dui;
72001
+ let range = [], rangeStr = '';
71350
72002
 
71351
- let resiArraySorted = resiArray.sort(function(a, b) {
71352
- return parseInt(a) - parseInt(b);
71353
- });
72003
+ // some chains such as 3SN6_R start with residues with high residue numbers, then end with residues with low residue numbers
72004
+ // let resiArraySorted = resiArray.sort(function(a, b) {
72005
+ // return parseInt(a) - parseInt(b);
72006
+ // });
72007
+
72008
+ let resiArraySorted = resiArray;
71354
72009
 
71355
72010
  let startResi = resiArraySorted[0];
71356
72011
  let prevResi, resi;
71357
72012
  for(let j = 0, jl = resiArraySorted.length; j < jl; ++j) {
71358
72013
  resi = resiArraySorted[j];
71359
72014
 
71360
- if(j != 0 && resi != prevResi + 1) {
72015
+ if(j != 0 && parseInt(resi) != parseInt(prevResi) + 1) {
71361
72016
  range.push(startResi);
71362
72017
  range.push(prevResi);
72018
+
72019
+ if(rangeStr) rangeStr += ',';
72020
+ if(startResi == prevResi) rangeStr += startResi;
72021
+ else rangeStr += startResi + '-' + prevResi;
72022
+
71363
72023
  startResi = resi;
71364
72024
  }
71365
72025
 
@@ -71369,8 +72029,13 @@ class Resid2spec {
71369
72029
  // last residue
71370
72030
  range.push(startResi);
71371
72031
  range.push(prevResi);
71372
-
71373
- return range;
72032
+
72033
+ if(rangeStr) rangeStr += ',';
72034
+ if(startResi == prevResi) rangeStr += startResi;
72035
+ else rangeStr += startResi + '-' + prevResi;
72036
+
72037
+ if(bString) return rangeStr;
72038
+ else return range;
71374
72039
  }
71375
72040
 
71376
72041
  atoms2spec(atomHash) {var ic = this.icn3d; ic.icn3dui;
@@ -72625,18 +73290,29 @@ class Dssp {
72625
73290
 
72626
73291
  ic.pdbDataArray = await this.promiseWithFixedJobs(pdbAjaxArray);
72627
73292
 
72628
- let bNoMoreIg = await thisClass.parseRefPdbData(ic.pdbDataArray, template);
72629
73293
  let numRound = 0;
73294
+ let bNoMoreIg = await thisClass.parseRefPdbData(ic.pdbDataArray, template, undefined, numRound);
73295
+ ++numRound;
72630
73296
 
72631
73297
  //while(!bNoMoreIg) {
72632
73298
  while(!bNoMoreIg && numRound < 15) {
72633
73299
  let bRerun = true;
72634
- bNoMoreIg = await thisClass.parseRefPdbData(ic.pdbDataArray, template, bRerun);
73300
+ bNoMoreIg = await thisClass.parseRefPdbData(ic.pdbDataArray, template, bRerun, numRound);
72635
73301
  ++numRound;
72636
73302
  }
72637
73303
  }
72638
73304
  else {
72639
- await thisClass.parseRefPdbData(undefined, template);
73305
+ await thisClass.parseRefPdbData(undefined, template, undefined, numRound);
73306
+ }
73307
+
73308
+ // refnum should be adjusted after all Ig are detected since sometimes the sheet extension may affect another Ig domain
73309
+ if(!ic.chainid2igtrack) ic.chainid2igtrack = {};
73310
+ for(let chainid in ic.chains) {
73311
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chainid]);
73312
+ if(ic.proteins.hasOwnProperty(atom.serial)) {
73313
+ let giSeq = ic.showSeqCls.getSeq(chainid);
73314
+ ic.chainid2igtrack[chainid] = this.ajdustRefnum(giSeq, chainid);
73315
+ }
72640
73316
  }
72641
73317
  // }
72642
73318
  // catch(err) {
@@ -72645,7 +73321,7 @@ class Dssp {
72645
73321
  // }
72646
73322
  }
72647
73323
 
72648
- async parseRefPdbData(dataArray, template, bRerun) { let ic = this.icn3d, me = ic.icn3dui;
73324
+ async parseRefPdbData(dataArray, template, bRerun, numRound) { let ic = this.icn3d, me = ic.icn3dui;
72649
73325
  let thisClass = this;
72650
73326
 
72651
73327
  let struArray = Object.keys(ic.structures);
@@ -72739,7 +73415,7 @@ class Dssp {
72739
73415
  dataArray2 = await this.promiseWithFixedJobs(ajaxArray);
72740
73416
 
72741
73417
  let bRound1 = true;
72742
- bNoMoreIg = await thisClass.parseAlignData(dataArray2, domainidpairArray, bRound1);
73418
+ bNoMoreIg = await thisClass.parseAlignData(dataArray2, domainidpairArray, bRound1, numRound);
72743
73419
 
72744
73420
  /// if(ic.deferredRefnum !== undefined) ic.deferredRefnum.resolve();
72745
73421
  }
@@ -72785,7 +73461,7 @@ class Dssp {
72785
73461
 
72786
73462
  dataArray3 = await this.promiseWithFixedJobs(ajaxArray);
72787
73463
 
72788
- bNoMoreIg = await thisClass.parseAlignData(dataArray3, domainidpairArray3);
73464
+ bNoMoreIg = await thisClass.parseAlignData(dataArray3, domainidpairArray3, undefined, numRound);
72789
73465
  }
72790
73466
 
72791
73467
  return bNoMoreIg;
@@ -73013,7 +73689,7 @@ class Dssp {
73013
73689
  delete ic.domainid2refpdbname[domainid];
73014
73690
  delete ic.domainid2score[domainid];
73015
73691
  }
73016
- continue;
73692
+ continue;
73017
73693
  }
73018
73694
  // }
73019
73695
  }
@@ -73077,7 +73753,7 @@ class Dssp {
73077
73753
  return domainid2segs; // only used in round 2
73078
73754
  }
73079
73755
 
73080
- async parseAlignData(dataArray, domainidpairArray, bRound1) { let ic = this.icn3d, me = ic.icn3dui;
73756
+ async parseAlignData(dataArray, domainidpairArray, bRound1, numRound) { let ic = this.icn3d, me = ic.icn3dui;
73081
73757
  let bNoMoreIg = false;
73082
73758
 
73083
73759
  let domainid2segs = this.parseAlignData_part1(dataArray, domainidpairArray, bRound1);
@@ -73102,7 +73778,8 @@ class Dssp {
73102
73778
  //let pdbid = domainid.substr(0, domainid.indexOf('_'));
73103
73779
  let chainid = domainid.substr(0, domainid.indexOf(','));
73104
73780
 
73105
- if(ic.refpdbHash.hasOwnProperty(chainid)) {
73781
+ // Adjusted refpdbname in the first try
73782
+ if(ic.refpdbHash.hasOwnProperty(chainid) && numRound == 0) {
73106
73783
  refpdbnameList = [chainid];
73107
73784
 
73108
73785
  if(!me.bNode) console.log("Adjusted refpdbname for domainid " + domainid + ": " + chainid);
@@ -73155,7 +73832,7 @@ class Dssp {
73155
73832
 
73156
73833
  dataArray3 = await this.promiseWithFixedJobs(ajaxArray);
73157
73834
 
73158
- bNoMoreIg = await this.parseAlignData(dataArray3, domainidpairArray3, false);
73835
+ bNoMoreIg = await this.parseAlignData(dataArray3, domainidpairArray3, false, numRound);
73159
73836
 
73160
73837
  // end of round 2
73161
73838
  return bNoMoreIg;
@@ -73400,6 +74077,8 @@ class Dssp {
73400
74077
  }
73401
74078
  }
73402
74079
 
74080
+ // refnum should be adjusted after all Ig are detected since sometimes the sheet extension may affect another Ig domain
74081
+ /*
73403
74082
  if(!ic.chainid2igtrack) ic.chainid2igtrack = {};
73404
74083
  for(let chainid in ic.chains) {
73405
74084
  let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chainid]);
@@ -73408,6 +74087,7 @@ class Dssp {
73408
74087
  ic.chainid2igtrack[chainid] = this.ajdustRefnum(giSeq, chainid);
73409
74088
  }
73410
74089
  }
74090
+ */
73411
74091
  }
73412
74092
 
73413
74093
  getStrandFromRefnum(oriRefnum, finalStrand) { let ic = this.icn3d; ic.icn3dui;
@@ -78340,7 +79020,7 @@ class ResizeCanvas {
78340
79020
  //let itemArray = ['dl_selectannotations', 'dl_alignment', 'dl_2ddgm', 'dl_definedsets', 'dl_graph',
78341
79021
  // 'dl_linegraph', 'dl_scatterplot', 'dl_contactmap', 'dl_allinteraction', 'dl_copyurl',
78342
79022
  // 'dl_symmetry', 'dl_symd', 'dl_rmsd', 'dl_legend', 'dl_disttable'];
78343
- let itemArray = ['dl_2ddgm', 'dl_2dctn', 'dl_alignment', 'dl_sequence2', 'dl_definedsets', 'dl_setsmenu', 'dl_command', 'dl_setoperations', 'dl_vast', 'dl_foldseek', 'dl_mmtfid', 'dl_pdbid', 'dl_afid', 'dl_opmid', 'dl_pdbfile', 'dl_pdbfile_app', 'dl_rescolorfile', 'dl_customcolor', 'dl_align', 'dl_alignaf', 'dl_chainalign', 'dl_chainalign2', 'dl_chainalign3', 'dl_mutation', 'dl_mol2file', 'dl_sdffile', 'dl_xyzfile', 'dl_afmapfile', 'dl_urlfile', 'dl_mmciffile', 'dl_mmcifid', 'dl_mmdbid', 'dl_mmdbafid', 'dl_blast_rep_id', 'dl_yournote', 'dl_proteinname', 'dl_refseqid', 'dl_cid', 'dl_pngimage', 'dl_state', 'dl_fixedversion', 'dl_selection', 'dl_dsn6', 'dl_dsn6url', 'dl_clr', 'dl_symmetry', 'dl_symd', 'dl_contact', 'dl_hbonds', 'dl_realign', 'dl_realignbystruct', 'dl_allinteracton', 'dl_interactionsorted', 'dl_linegraph', 'dl_linegraphcolor', 'dl_scatterplot', 'dl_scatterploitcolor', 'dl_contactmap', 'dl_alignerrormap', 'dl_elecmap2fofc', 'dl_elecmapfofc', 'dl_emmap', 'dl_aroundsphere', 'dl_adjustmem', 'dl_selectplane', 'dl_addlabel', 'dl_addlabelselection', 'dl_labelColor', 'dl_distance', 'dl_stabilizer', 'dl_disttwosets', 'dl_distmanysets', 'dl_stabilizer_rm', 'dl_thickness', 'dl_thickness2', 'dl_addtrack', 'dl_addtrack_tabs', 'dl_saveselection', 'dl_copyurl', 'dl_selectannotations', 'dl_annotations_tabs', 'dl_anno_view_tabs', 'dl_annotations', 'dl_graph', 'dl_svgcolor', 'dl_area', 'dl_colorbyarea', 'dl_rmsd', 'dl_buriedarea', 'dl_propbypercentout', 'dl_propbybfactor', 'dl_legend', 'dl_disttable', 'dl_translate'];
79023
+ let itemArray = ['dl_2ddgm', 'dl_2dctn', 'dl_alignment', 'dl_sequence2', 'dl_definedsets', 'dl_setsmenu', 'dl_command', 'dl_setoperations', 'dl_vast', 'dl_foldseek', 'dl_mmtfid', 'dl_pdbid', 'dl_afid', 'dl_opmid', 'dl_pdbfile', 'dl_pdbfile_app', 'dl_rescolorfile', 'dl_customcolor', 'dl_align', 'dl_alignaf', 'dl_chainalign', 'dl_chainalign2', 'dl_chainalign3', 'dl_mutation', 'dl_mol2file', 'dl_sdffile', 'dl_xyzfile', 'dl_clustalwfile', 'dl_fastafile', 'dl_afmapfile', 'dl_urlfile', 'dl_mmciffile', 'dl_mmcifid', 'dl_mmdbid', 'dl_mmdbafid', 'dl_blast_rep_id', 'dl_yournote', 'dl_proteinname', 'dl_refseqid', 'dl_cid', 'dl_pngimage', 'dl_state', 'dl_fixedversion', 'dl_selection', 'dl_dsn6', 'dl_dsn6url', 'dl_clr', 'dl_symmetry', 'dl_symd', 'dl_contact', 'dl_hbonds', 'dl_realign', 'dl_realignbystruct', 'dl_allinteracton', 'dl_interactionsorted', 'dl_linegraph', 'dl_linegraphcolor', 'dl_scatterplot', 'dl_scatterploitcolor', 'dl_contactmap', 'dl_alignerrormap', 'dl_elecmap2fofc', 'dl_elecmapfofc', 'dl_emmap', 'dl_aroundsphere', 'dl_adjustmem', 'dl_selectplane', 'dl_addlabel', 'dl_addlabelselection', 'dl_labelColor', 'dl_distance', 'dl_stabilizer', 'dl_disttwosets', 'dl_distmanysets', 'dl_stabilizer_rm', 'dl_thickness', 'dl_thickness2', 'dl_addtrack', 'dl_addtrack_tabs', 'dl_saveselection', 'dl_copyurl', 'dl_selectannotations', 'dl_annotations_tabs', 'dl_anno_view_tabs', 'dl_annotations', 'dl_graph', 'dl_svgcolor', 'dl_area', 'dl_colorbyarea', 'dl_rmsd', 'dl_buriedarea', 'dl_propbypercentout', 'dl_propbybfactor', 'dl_legend', 'dl_disttable', 'dl_translate'];
78344
79024
 
78345
79025
  for(let i in itemArray) {
78346
79026
  let item = itemArray[i];
@@ -79086,9 +79766,10 @@ class SaveFile {
79086
79766
  ssObj.resn = atom.resn;
79087
79767
  ssObj.resi = atom.resi;
79088
79768
 
79089
- if(parseInt(atom.resi) > parseInt(prevResi) + 1) {
79090
- ssObj.ss = ' ';
79091
- ssArray.push(ssObj);
79769
+ if(parseInt(atom.resi) > parseInt(prevResi) + 1 || atom.ssbegin) {
79770
+ let ssObj2 = me.hashUtilsCls.cloneHash(ssObj);
79771
+ ssObj2.ss = ' ';
79772
+ ssArray.push(ssObj2);
79092
79773
  }
79093
79774
 
79094
79775
  if(atom.ss == 'helix') {
@@ -79099,13 +79780,13 @@ class SaveFile {
79099
79780
  ssObj.ss = 'S';
79100
79781
  ssArray.push(ssObj);
79101
79782
  }
79102
-
79783
+ /*
79103
79784
  if(atom.ssend) {
79104
79785
  let ssObj2 = me.hashUtilsCls.cloneHash(ssObj);
79105
79786
  ssObj2.ss = ' ';
79106
79787
  ssArray.push(ssObj2);
79107
79788
  }
79108
-
79789
+ */
79109
79790
  prevResi = atom.resi;
79110
79791
  }
79111
79792
 
@@ -79113,9 +79794,9 @@ class SaveFile {
79113
79794
  for(let i = 0, il = ssArray.length; i < il; ++i) {
79114
79795
  let ssObj = ssArray[i];
79115
79796
 
79116
- if(ssObj.ss != prevSs || ssObj.ssbegin) {
79797
+ if(ssObj.ss != prevSs) {
79117
79798
  // print prev
79118
- stru2header[stru] += this.printPrevSecondary(bHelix, bSheet, prevRealSsObj, ssCnt);
79799
+ if(prevSs !== ' ') stru2header[stru] += this.printPrevSecondary(bHelix, bSheet, prevRealSsObj, ssCnt);
79119
79800
 
79120
79801
  // print current
79121
79802
  ssCnt = 0;
@@ -79123,7 +79804,7 @@ class SaveFile {
79123
79804
  bSheet = false;
79124
79805
  prevRealSsObj = undefined;
79125
79806
 
79126
- if(ssObj.ss != ' ') {
79807
+ if(ssObj.ss !== ' ') {
79127
79808
  if(ssObj.ss == 'H') {
79128
79809
  bHelix = true;
79129
79810
  prevRealSsObj = ssObj;
@@ -79139,7 +79820,7 @@ class SaveFile {
79139
79820
  }
79140
79821
  }
79141
79822
 
79142
- if(ssObj.ss != ' ') {
79823
+ if(ssObj.ss !== ' ') {
79143
79824
  ++ssCnt;
79144
79825
  prevRealSsObj = ssObj;
79145
79826
  }
@@ -80988,8 +81669,10 @@ class Ray {
80988
81669
  this.icn3d = icn3d;
80989
81670
  }
80990
81671
 
80991
- rayCaster(e, bClick) {
81672
+ rayCaster(e, bClick) { let ic = this.icn3d; ic.icn3dui;
81673
+ if(!ic.opts || ic.opts['effect'] == 'none') {
80992
81674
  this.rayCasterBase(e, bClick);
81675
+ }
80993
81676
  }
80994
81677
 
80995
81678
  rayCasterBase(e, bClick) { let ic = this.icn3d; ic.icn3dui;
@@ -82310,6 +82993,14 @@ class iCn3D {
82310
82993
  });
82311
82994
  }
82312
82995
 
82996
+ this.effects = {
82997
+ //'anaglyph': new THREE.AnaglyphEffect(this.renderer),
82998
+ //'parallax barrier': new THREE.ParallaxBarrierEffect(this.renderer),
82999
+ //'oculus rift': new THREE.OculusRiftEffect(this.renderer),
83000
+ 'stereo': new THREE.StereoEffect(this.renderer),
83001
+ 'none': this.renderer
83002
+ };
83003
+
82313
83004
  this.overdraw = 0;
82314
83005
  }
82315
83006
  else {
@@ -82456,14 +83147,6 @@ class iCn3D {
82456
83147
 
82457
83148
  this.bExtrude = true;
82458
83149
 
82459
- this.effects = {
82460
- //'anaglyph': new THREE.AnaglyphEffect(this.renderer),
82461
- //'parallax barrier': new THREE.ParallaxBarrierEffect(this.renderer),
82462
- //'oculus rift': new THREE.OculusRiftEffect(this.renderer),
82463
- //'stereo': new THREE.StereoEffect(this.renderer),
82464
- 'none': this.renderer
82465
- };
82466
-
82467
83150
  this.maxD = 500; // size of the molecule
82468
83151
  this.oriMaxD = this.maxD; // size of the molecule
82469
83152
  //this.cam_z = -150;
@@ -82516,6 +83199,7 @@ class iCn3D {
82516
83199
  //The default display options
82517
83200
  this.optsOri = {};
82518
83201
  this.optsOri['camera'] = 'perspective'; //perspective, orthographic
83202
+ this.optsOri['effect'] = 'none'; //stereo, none
82519
83203
  this.optsOri['background'] = 'black'; //transparent, black, grey, white
82520
83204
  this.optsOri['color'] = 'chain'; //spectrum, secondary structure, charge, hydrophobic, conserved, chain, residue, atom, b factor, red, green, blue, magenta, yellow, cyan, white, grey, custom, ig strand
82521
83205
  this.optsOri['proteins'] = 'ribbon'; //ribbon, strand, cylinder and plate, schematic, c alpha trace, backbone, b factor tube, lines, stick, ball and stick, sphere, nothing
@@ -82709,6 +83393,7 @@ class iCn3D {
82709
83393
  this.pdbParserCls = new PdbParser(this);
82710
83394
  this.sdfParserCls = new SdfParser(this);
82711
83395
  this.xyzParserCls = new XyzParser(this);
83396
+ this.msaParserCls = new MsaParser(this);
82712
83397
  this.realignParserCls = new RealignParser(this);
82713
83398
  this.densityCifParserCls = new DensityCifParser(this);
82714
83399
  this.ParserUtilsCls = new ParserUtils(this);
@@ -82965,7 +83650,7 @@ class iCn3DUI {
82965
83650
  //even when multiple iCn3D viewers are shown together.
82966
83651
  this.pre = this.cfg.divid + "_";
82967
83652
 
82968
- this.REVISION = '3.40.5';
83653
+ this.REVISION = '3.42.0';
82969
83654
 
82970
83655
  // In nodejs, iCn3D defines "window = {navigator: {}}"
82971
83656
  this.bNode = (Object.keys(window).length < 2) ? true : false;
@@ -83788,6 +84473,7 @@ exports.MarchingCube = MarchingCube;
83788
84473
  exports.MmcifParser = MmcifParser;
83789
84474
  exports.MmdbParser = MmdbParser;
83790
84475
  exports.Mol2Parser = Mol2Parser;
84476
+ exports.MsaParser = MsaParser;
83791
84477
  exports.MyEventCls = MyEventCls;
83792
84478
  exports.OpmParser = OpmParser;
83793
84479
  exports.ParasCls = ParasCls;