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.module.js CHANGED
@@ -2532,7 +2532,6 @@ THREE.TrackballControls = function ( object, domElement, icn3d ) {
2532
2532
  _this._panStart.add( mouseChange.subVectors( _this._panEnd, _this._panStart ).multiplyScalar( _this.dynamicDampingFactor ) );
2533
2533
 
2534
2534
  }
2535
-
2536
2535
  }
2537
2536
  }
2538
2537
 
@@ -3569,6 +3568,103 @@ THREE.OrthographicTrackballControls = function ( object, domElement, icn3d ) { v
3569
3568
  THREE.OrthographicTrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype );
3570
3569
  THREE.OrthographicTrackballControls.prototype.constructor = THREE.OrthographicTrackballControls;
3571
3570
 
3571
+ /**
3572
+ * @author alteredq / http://alteredqualia.com/
3573
+ * @authod mrdoob / http://mrdoob.com/
3574
+ * @authod arodic / http://aleksandarrodic.com/
3575
+ * modified by Jiyao Wang
3576
+ */
3577
+
3578
+ THREE.StereoEffect = function ( renderer ) {
3579
+ var _this = this;
3580
+ // API
3581
+
3582
+ _this.separation = 3; // 1;
3583
+
3584
+ // internals
3585
+
3586
+ // _this._width, _this._height;
3587
+
3588
+ _this._position = new THREE.Vector3();
3589
+ _this._quaternion = new THREE.Quaternion();
3590
+ _this._scale = new THREE.Vector3();
3591
+
3592
+ _this._cameraL = new THREE.PerspectiveCamera();
3593
+ _this._cameraR = new THREE.PerspectiveCamera();
3594
+
3595
+ // initialization
3596
+
3597
+ renderer.autoClear = false;
3598
+
3599
+ _this.setSize = function ( width, height ) {
3600
+
3601
+ _this._width = width / 2;
3602
+ _this._height = height;
3603
+
3604
+ renderer.setSize( width, height );
3605
+
3606
+ };
3607
+
3608
+ _this.render = function ( scene, camera ) {
3609
+
3610
+ scene.updateMatrixWorld();
3611
+
3612
+ if ( camera.parent === undefined ) camera.updateMatrixWorld();
3613
+
3614
+ camera.matrixWorld.decompose( _this._position, _this._quaternion, _this._scale );
3615
+
3616
+ // left
3617
+ _this._cameraL.copy(camera);
3618
+ _this._cameraL.aspect = 0.5 * camera.aspect;
3619
+ _this._cameraL.updateProjectionMatrix();
3620
+
3621
+ /*
3622
+ _this._cameraL.fov = camera.fov;
3623
+ _this._cameraL.aspect = 0.5 * camera.aspect;
3624
+ _this._cameraL.near = camera.near;
3625
+ _this._cameraL.far = camera.far;
3626
+ _this._cameraL.updateProjectionMatrix();
3627
+
3628
+ _this._cameraL.position.copy( _this._position );
3629
+ // _this._cameraL.quaternion.copy( _this._quaternion );
3630
+ */
3631
+ _this._cameraL.translateX( - _this.separation );
3632
+
3633
+ // right
3634
+ _this._cameraR.copy(camera);
3635
+ _this._cameraR.aspect = 0.5 * camera.aspect;
3636
+ _this._cameraR.updateProjectionMatrix();
3637
+
3638
+ /*
3639
+ _this._cameraR.fov = camera.fov;
3640
+ _this._cameraR.aspect = 0.5 * camera.aspect;
3641
+ _this._cameraR.near = camera.near;
3642
+ _this._cameraR.far = camera.far;
3643
+ // _this._cameraR.projectionMatrix = _this._cameraL.projectionMatrix;
3644
+ _this._cameraR.updateProjectionMatrix();
3645
+
3646
+ _this._cameraR.position.copy( _this._position );
3647
+ // _this._cameraR.quaternion.copy( _this._quaternion );
3648
+ */
3649
+
3650
+ _this._cameraR.translateX( _this.separation );
3651
+
3652
+ //
3653
+
3654
+ renderer.setViewport( 0, 0, _this._width * 2, _this._height );
3655
+ renderer.clear();
3656
+
3657
+ renderer.setViewport( 0, 0, _this._width, _this._height );
3658
+ renderer.render( scene, _this._cameraL );
3659
+
3660
+ renderer.setViewport( _this._width, 0, _this._width, _this._height );
3661
+ renderer.render( scene, _this._cameraR );
3662
+
3663
+ };
3664
+
3665
+ };
3666
+
3667
+
3572
3668
 
3573
3669
  // ; var __CIFTools = function () {
3574
3670
  // 'use strict';
@@ -9706,6 +9802,7 @@ class ClickMenu {
9706
9802
 
9707
9803
  applyShownMenus(bNoSave) { let me = this.icn3dui; me.icn3d;
9708
9804
  let idArray = [];
9805
+
9709
9806
  for(let id in me.htmlCls.allMenus) {
9710
9807
  if(me.htmlCls.shownMenus.hasOwnProperty(id)) {
9711
9808
  $("#" + me.pre + id).parent().show();
@@ -9728,9 +9825,9 @@ class ClickMenu {
9728
9825
  }
9729
9826
 
9730
9827
  getHiddenMenusFromCache() { let me = this.icn3dui; me.icn3d;
9731
- // me.htmlCls.shownMenus = {};
9828
+ me.htmlCls.shownMenus = {};
9732
9829
 
9733
- // let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
9830
+ let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
9734
9831
 
9735
9832
  let idArrayStr = (localStorage) ? localStorage.getItem('hiddenmenus') : '';
9736
9833
 
@@ -9739,31 +9836,23 @@ class ClickMenu {
9739
9836
 
9740
9837
  let idArray = JSON.parse(idArrayStr);
9741
9838
 
9742
- // for(let i = 0, il = idArray.length; i < il; ++i) {
9743
- // me.htmlCls.shownMenus[idArray[i]] = 1;
9744
- // }
9745
9839
  for(let menu in me.htmlCls.allMenus) {
9746
9840
  if(idArray.indexOf(menu) == -1) {
9747
9841
  me.htmlCls.shownMenus[menu] = 1;
9748
9842
  }
9749
9843
  }
9750
9844
  }
9751
- //###
9752
9845
  else {
9753
- me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
9846
+ if(mode == 'all') {
9847
+ me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
9848
+ }
9849
+ else if(!mode || mode == 'simple') {
9850
+ me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
9851
+ }
9852
+ else {
9853
+ me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
9854
+ }
9754
9855
  }
9755
-
9756
- // else {
9757
- // if(mode == 'all') {
9758
- // me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
9759
- // }
9760
- // else if(!mode || mode == 'simple') {
9761
- // me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
9762
- // }
9763
- // else {
9764
- // me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
9765
- // }
9766
- // }
9767
9856
  }
9768
9857
 
9769
9858
  displayShownMenus() { let me = this.icn3dui; me.icn3d;
@@ -9944,6 +10033,14 @@ class ClickMenu {
9944
10033
  me.htmlCls.dialogCls.openDlg('dl_urlfile', 'Load data by URL');
9945
10034
  });
9946
10035
 
10036
+ me.myEventCls.onIds("#" + me.pre + "mn1_clustalwfile", "click", function(e) { me.icn3d; //e.preventDefault();
10037
+ me.htmlCls.dialogCls.openDlg('dl_clustalwfile', 'Please input CLUSTALW MSA File');
10038
+ });
10039
+
10040
+ me.myEventCls.onIds("#" + me.pre + "mn1_fastafile", "click", function(e) { me.icn3d; //e.preventDefault();
10041
+ me.htmlCls.dialogCls.openDlg('dl_fastafile', 'Please input FASTA MSA File');
10042
+ });
10043
+
9947
10044
  me.myEventCls.onIds("#" + me.pre + "mn1_fixedversion", "click", function(e) { me.icn3d; //e.preventDefault();
9948
10045
  me.htmlCls.dialogCls.openDlg('dl_fixedversion', 'Open Share Link URL in the archived version of iCn3D');
9949
10046
  });
@@ -10045,6 +10142,11 @@ class ClickMenu {
10045
10142
  ic.saveFileCls.saveFile(file_pref + '_statefile.txt', 'command');
10046
10143
  });
10047
10144
 
10145
+ me.myEventCls.onIds("#" + me.pre + "mn1_exportVideo", "click", function(e) { me.icn3d; //e.preventDefault();
10146
+ thisClass.setLogCmd("export video", false);
10147
+ me.htmlCls.dialogCls.openDlg('dl_video', 'Save canvas changes in a video');
10148
+ });
10149
+
10048
10150
 
10049
10151
  me.myEventCls.onIds("#" + me.pre + "mn1_exportPdbRes", "click", function(e) { me.icn3d; //e.preventDefault();
10050
10152
  me.htmlCls.setHtmlCls.exportPdb();
@@ -11737,6 +11839,18 @@ class ClickMenu {
11737
11839
  //}
11738
11840
  });
11739
11841
 
11842
+ me.myEventCls.onIds("#" + me.pre + "mn6_stereoYes", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
11843
+ ic.opts['effect'] = 'stereo';
11844
+ ic.drawCls.draw();
11845
+ thisClass.setLogCmd('stereo on', true);
11846
+ });
11847
+
11848
+ me.myEventCls.onIds("#" + me.pre + "mn6_stereoNo", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
11849
+ ic.opts['effect'] = 'none';
11850
+ ic.drawCls.draw();
11851
+ thisClass.setLogCmd('stereo off', true);
11852
+ });
11853
+
11740
11854
  $(document).on("click", "#" + me.pre + "mn2_translate", function(e) { me.icn3d; //e.preventDefault();
11741
11855
  me.htmlCls.dialogCls.openDlg('dl_translate', 'Translate the X,Y,Z coordinates of the structure');
11742
11856
  });
@@ -12242,7 +12356,7 @@ class SetMenu {
12242
12356
 
12243
12357
  let tdStr = '<td valign="top">';
12244
12358
 
12245
- // html += tdStr + this.setMenuMode() + '</td>';
12359
+ html += tdStr + this.setMenuMode() + '</td>';
12246
12360
 
12247
12361
  html += tdStr + this.setMenu1() + '</td>';
12248
12362
 
@@ -12253,12 +12367,11 @@ class SetMenu {
12253
12367
  html += tdStr + this.setMenu4() + '</td>';
12254
12368
 
12255
12369
  html += tdStr + this.setMenu5() + '</td>';
12256
- //html += tdStr + this.setMenu5b() + '</td>';
12257
12370
  html += tdStr + this.setMenu6() + '</td>';
12258
12371
 
12259
12372
  // reset the menus at the end of the menus
12260
- // let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
12261
- // this.resetMenu(mode);
12373
+ let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
12374
+ this.resetMenu(mode);
12262
12375
 
12263
12376
  // me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
12264
12377
 
@@ -12366,7 +12479,7 @@ class SetMenu {
12366
12479
  }
12367
12480
  html += "<div>";
12368
12481
 
12369
- // html += '<li>' + this.setMenuMode(true);
12482
+ html += '<li>' + this.setMenuMode(true);
12370
12483
 
12371
12484
  let liStr = "<li><span class='icn3d-menu-color'";
12372
12485
 
@@ -12387,8 +12500,8 @@ class SetMenu {
12387
12500
  html += this.setMenu6_base();
12388
12501
 
12389
12502
  // reset the menus at the end of the menus
12390
- // let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
12391
- // this.resetMenu(mode);
12503
+ let mode = me.htmlCls.setHtmlCls.getCookie('menumode');
12504
+ this.resetMenu(mode);
12392
12505
 
12393
12506
  // me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
12394
12507
 
@@ -12478,7 +12591,7 @@ class SetMenu {
12478
12591
 
12479
12592
  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;'>";
12480
12593
  //html += "<table style='margin-top: 3px; width:100px;'>";
12481
- html += "<table style='margin-top: 3px; width:770px; background-color:#EEE;'>";
12594
+ html += "<table style='margin: 3px 0px 0px 76px; width:770px; background-color:#EEE;'>";
12482
12595
 
12483
12596
  html += this.setTools_base();
12484
12597
 
@@ -12751,9 +12864,19 @@ class SetMenu {
12751
12864
  html += this.getLink('mn1_mol2file', 'Mol2 File', undefined, 2);
12752
12865
  html += this.getLink('mn1_sdffile', 'SDF File', undefined, 2);
12753
12866
  html += this.getLink('mn1_xyzfile', 'XYZ File', undefined, 2);
12867
+
12868
+ html += this.getMenuSep();
12869
+
12870
+ html += this.getMenuText('mn1_msawrap', 'Multiple Seq. Alignment', undefined, undefined, 2);
12871
+ html += "<ul>";
12872
+ html += this.getLink('mn1_clustalwfile', 'CLUSTALW Format', undefined, 3);
12873
+ html += this.getLink('mn1_fastafile', 'FASTA Format', undefined, 3);
12874
+ html += "</ul>";
12875
+
12754
12876
  html += this.getLink('mn1_afmapfile', 'AlphaFold PAE File', undefined, 2);
12755
12877
 
12756
12878
  html += this.getLink('mn1_urlfile', 'URL(CORS) ' + me.htmlCls.wifiStr, undefined, 2);
12879
+
12757
12880
  html += this.getMenuSep();
12758
12881
  html += this.getLink('mn1_pngimage', 'iCn3D PNG (appendable)', 1, 2);
12759
12882
  html += this.getLink('mn1_state', 'State/Script File', undefined, 2);
@@ -12794,9 +12917,9 @@ class SetMenu {
12794
12917
  html += "</ul>";
12795
12918
  html += "</li>";
12796
12919
 
12797
- html += this.getMenuText('mn1_aligntwostru', 'Protein Complexes', undefined, undefined, 2);
12920
+ html += this.getMenuText('mn1_aligntwostru', 'Protein Complexes', undefined, 1, 2);
12798
12921
  html += "<ul>";
12799
- html += this.getLink('mn1_align', 'Two PDB Structures ' + me.htmlCls.wifiStr, undefined, 3);
12922
+ html += this.getLink('mn1_align', 'Two PDB Structures ' + me.htmlCls.wifiStr, 1, 3);
12800
12923
  html += this.getLink('mn1_alignaf', 'Two AlphaFold Structures ' + me.htmlCls.wifiStr, undefined, 3);
12801
12924
  html += "</ul>";
12802
12925
 
@@ -12850,8 +12973,8 @@ class SetMenu {
12850
12973
  html += "<ul>";
12851
12974
  html += this.getMenuText('mn1_savepngimage', 'iCn3D PNG Image', undefined, 1, 2);
12852
12975
  html += "<ul>";
12853
- html += this.getLink('mn1_exportCanvas', 'Original Size & HTML', 1, 3);
12854
- html += this.getLink('mn1_exportCanvas1', 'Original Size', undefined, 3);
12976
+ html += this.getLink('mn1_exportCanvas', 'Original Size & HTML', undefined, 3);
12977
+ html += this.getLink('mn1_exportCanvas1', 'Original Size', 1, 3);
12855
12978
 
12856
12979
  html += this.getLink('mn1_exportCanvas2', '2X Large', undefined, 3);
12857
12980
  html += this.getLink('mn1_exportCanvas4', '4X Large', undefined, 3);
@@ -12860,6 +12983,7 @@ class SetMenu {
12860
12983
  html += "</ul>";
12861
12984
  html += "</li>";
12862
12985
 
12986
+ html += this.getLink('mn1_exportVideo', 'Video', undefined, 2);
12863
12987
  html += this.getLink('mn1_exportState', 'State File', undefined, 2);
12864
12988
  html += this.getLink('mn1_exportSelections', 'Selection File', undefined, 2);
12865
12989
  html += this.getLink('mn1_exportSelDetails', 'Selection Details', undefined, 2);
@@ -12938,7 +13062,7 @@ class SetMenu {
12938
13062
  html += "<ul class='icn3d-mn-item'>";
12939
13063
 
12940
13064
  html += this.getLink('mn2_definedsets', 'Defined Sets', 1, 1);
12941
- html += this.getLink('mn2_selectall', 'All', undefined, 1);
13065
+ html += this.getLink('mn2_selectall', 'All', 1, 1);
12942
13066
  html += this.getLink('mn2_selectdisplayed', 'Displayed Set', undefined, 1);
12943
13067
  html += this.getLink('mn2_aroundsphere', 'by Distance', 1, 1);
12944
13068
 
@@ -12954,10 +13078,10 @@ class SetMenu {
12954
13078
  html += "</li>";
12955
13079
 
12956
13080
  html += this.getLink('mn2_selectcomplement', 'Inverse', undefined, 1);
12957
- html += this.getLink('mn2_selectmainchains', 'Main Chains', undefined, 1);
12958
- html += this.getLink('mn2_selectsidechains', 'Side Chains', undefined, 1);
13081
+ html += this.getLink('mn2_selectmainchains', 'Main Chains', 1, 1);
13082
+ html += this.getLink('mn2_selectsidechains', 'Side Chains', 1, 1);
12959
13083
  html += this.getLink('mn2_selectmainsidechains', 'Main & Side Chains', undefined, 1);
12960
- html += this.getLink('mn2_command', 'Advanced', undefined, 1);
13084
+ html += this.getLink('mn2_command', 'Advanced', 1, 1);
12961
13085
 
12962
13086
  if(me.cfg.cid === undefined) {
12963
13087
  html += this.getMenuText('mn2_selon3d', 'Select on 3D', undefined, 1, 1);
@@ -12990,7 +13114,7 @@ class SetMenu {
12990
13114
  html += this.getMenuSep();
12991
13115
 
12992
13116
  html += this.getLink('mn2_saveselection', 'Save Selection', 1, 1);
12993
- html += this.getLink('clearall', 'Clear Selection', undefined, 1);
13117
+ html += this.getLink('clearall', 'Clear Selection', 1, 1);
12994
13118
  html += this.getLink('mn2_saveresidue', 'Save Res. in Sel.', 1, 1);
12995
13119
 
12996
13120
  html += this.getMenuSep();
@@ -13055,7 +13179,7 @@ class SetMenu {
13055
13179
  html += this.getLinkWrapper('mn2_alternate', 'Alternate(Key "a")', 'mn2_alternateWrap', undefined, 1);
13056
13180
 
13057
13181
  if(me.cfg.opmid !== undefined) {
13058
- html += this.getLinkWrapper('togglemem', 'Toggle Membrane', 'togglememli', undefined, 1);
13182
+ html += this.getLinkWrapper('togglemem', 'Toggle Membrane', 'togglememli', 1, 1);
13059
13183
  }
13060
13184
  //else if(me.cfg.mmdbafid !== undefined || me.cfg.afid !== undefined) {
13061
13185
  else if(me.cfg.cid === undefined) {
@@ -13070,14 +13194,21 @@ class SetMenu {
13070
13194
 
13071
13195
  html += this.getMenuSep();
13072
13196
 
13073
- html += this.getMenuText('mn2_vrarhints', 'VR & AR Hints', undefined, 1, 1);
13197
+ html += this.getMenuText('mn2_vrarhints', 'VR & AR Hints', undefined, undefined, 1);
13198
+ html += "<ul>";
13199
+ html += this.getMenuUrl("vrhint", me.htmlCls.baseUrl + "icn3d/icn3d.html#vr", "VR: VR Headsets", undefined, 2);
13200
+ html += this.getMenuUrl("arhint", me.htmlCls.baseUrl + "icn3d/icn3d.html#ar", "AR: Chrome in Android", undefined, 2);
13201
+ html += "</ul>";
13202
+ html += "</li>";
13203
+
13204
+ html += this.getMenuText('mn6_stereoWrapper', 'Stereo View', undefined, undefined, 1);
13074
13205
  html += "<ul>";
13075
- html += this.getMenuUrl("vrhint", me.htmlCls.baseUrl + "icn3d/icn3d.html#vr", "VR: VR Headsets", 1, 2);
13076
- html += this.getMenuUrl("arhint", me.htmlCls.baseUrl + "icn3d/icn3d.html#ar", "AR: Chrome in Android", 1, 2);
13206
+ html += this.getRadio('mn6_stereo', 'mn6_stereoYes', 'On', undefined, undefined, 2);
13207
+ html += this.getRadio('mn6_stereo', 'mn6_stereoNo', 'Off', true, undefined, 2);
13077
13208
  html += "</ul>";
13078
13209
  html += "</li>";
13079
13210
 
13080
- html += this.getLink('mn6_sidebyside', 'Side by Side', 1, 1);
13211
+ html += this.getLink('mn6_sidebyside', 'Side by Side', undefined, 1);
13081
13212
 
13082
13213
  html += this.getMenuText('mn2_rotate', 'Rotate', undefined, 1, 1);
13083
13214
  html += "<ul>";
@@ -13189,7 +13320,7 @@ class SetMenu {
13189
13320
  html += this.getRadio('mn3_proteins', 'mn3_proteinsRibbon', 'Ribbon', true, 1, 2);
13190
13321
  }
13191
13322
 
13192
- html += this.getRadio('mn3_proteins', 'mn3_proteinsStrand', 'Strand', undefined, undefined, 2);
13323
+ html += this.getRadio('mn3_proteins', 'mn3_proteinsStrand', 'Strand', undefined, 1, 2);
13193
13324
  html += this.getRadio('mn3_proteins', 'mn3_proteinsCylinder', 'Cylinder and Plate', undefined, undefined, 2);
13194
13325
  html += this.getRadio('mn3_proteins', 'mn3_proteinsSchematic', 'Schematic', undefined, 1, 2);
13195
13326
 
@@ -13201,7 +13332,7 @@ class SetMenu {
13201
13332
  }
13202
13333
 
13203
13334
  html += this.getRadio('mn3_proteins', 'mn3_proteinsBackbone', 'Backbone', undefined, undefined, 2);
13204
- html += this.getRadio('mn3_proteins', 'mn3_proteinsBfactor', 'B-factor Tube', undefined, 1, 2);
13335
+ html += this.getRadio('mn3_proteins', 'mn3_proteinsBfactor', 'B-factor Tube', undefined, undefined, 2);
13205
13336
  html += this.getRadio('mn3_proteins', 'mn3_proteinsLines', 'Lines', undefined, 1, 2);
13206
13337
  html += this.getRadio('mn3_proteins', 'mn3_proteinsStick', 'Stick', undefined, 1, 2);
13207
13338
  html += this.getRadio('mn3_proteins', 'mn3_proteinsBallstick', 'Ball and Stick', undefined, 1, 2);
@@ -13265,10 +13396,10 @@ class SetMenu {
13265
13396
  html += "</li>";
13266
13397
 
13267
13398
  //if(me.cfg.cid !== undefined) {
13268
- html += this.getMenuText('mn3_hydrogenswrap', 'Hydrogens', undefined, 1, 1);
13399
+ html += this.getMenuText('mn3_hydrogenswrap', 'Hydrogens', undefined, undefined, 1);
13269
13400
  html += "<ul>";
13270
- html += this.getRadio('mn3_hydrogens', 'mn3_hydrogensYes', 'Show', true, 1, 2);
13271
- html += this.getRadio('mn3_hydrogens', 'mn3_hydrogensNo', 'Hide', undefined, 1, 2);
13401
+ html += this.getRadio('mn3_hydrogens', 'mn3_hydrogensYes', 'Show', true, undefined, 2);
13402
+ html += this.getRadio('mn3_hydrogens', 'mn3_hydrogensNo', 'Hide', undefined, undefined, 2);
13272
13403
  html += "</ul>";
13273
13404
  html += "</li>";
13274
13405
  //}
@@ -13643,7 +13774,7 @@ class SetMenu {
13643
13774
 
13644
13775
  html += "</ul>";
13645
13776
 
13646
- html += this.getRadio('mn4_clr', 'mn4_clrCustom', 'Color Picker', undefined, undefined, 1);
13777
+ html += this.getRadio('mn4_clr', 'mn4_clrCustom', 'Color Picker', undefined, 1, 1);
13647
13778
  html += this.getMenuSep();
13648
13779
 
13649
13780
  if(me.cfg.cid === undefined) {
@@ -13684,7 +13815,7 @@ class SetMenu {
13684
13815
  html += this.getRadio('mn4_clr', 'mn4_clrBfactorNorm', 'Percentile', undefined, 1, 2);
13685
13816
  html += "</ul>";
13686
13817
 
13687
- html += this.getRadio('mn4_clr', 'mn4_clrArea', 'Solvent<br><span style="padding-left:1.5em;">Accessibility</span>', undefined, undefined, 1);
13818
+ html += this.getRadio('mn4_clr', 'mn4_clrArea', 'Solvent<br><span style="padding-left:1.5em;">Accessibility</span>', undefined, 1, 1);
13688
13819
 
13689
13820
  html += this.getRadio('mn4_clr', 'mn4_clrStructure', 'Structure', undefined, 1, 1);
13690
13821
 
@@ -13696,7 +13827,7 @@ class SetMenu {
13696
13827
  }
13697
13828
 
13698
13829
  //if(me.cfg.mmdbid !== undefined || me.cfg.gi !== undefined) {
13699
- html += this.getRadio('mn4_clr', 'mn4_clrdomain', '3D Domain', undefined, undefined, 1);
13830
+ html += this.getRadio('mn4_clr', 'mn4_clrdomain', '3D Domain', undefined, 1, 1);
13700
13831
  //}
13701
13832
 
13702
13833
  if(me.cfg.cid === undefined) {
@@ -13716,16 +13847,16 @@ class SetMenu {
13716
13847
  html += this.getRadio('mn4_clr', 'mn4_clrAtom', 'Atom', undefined, 1, 1);
13717
13848
 
13718
13849
  if(me.cfg.align !== undefined || me.cfg.chainalign !== undefined) {
13719
- html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', true, undefined, 2);
13720
- html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', undefined, undefined, 2);
13850
+ html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', true, undefined, 1);
13851
+ html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', undefined, undefined, 1);
13721
13852
  }
13722
13853
  else if(me.cfg.blast_rep_id !== undefined) {
13723
- html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', undefined, undefined, 2);
13724
- html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', true, undefined, 2);
13854
+ html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', undefined, undefined, 1);
13855
+ html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', true, undefined, 1);
13725
13856
  }
13726
13857
  else {
13727
- html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', undefined, undefined, 2);
13728
- html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', undefined, undefined, 2);
13858
+ html += this.getRadio('mn4_clr', 'mn4_clrIdentity', 'Identity', undefined, undefined, 1);
13859
+ html += this.getRadio('mn4_clr', 'mn4_clrConserved', 'Conservation', undefined, undefined, 1);
13729
13860
  }
13730
13861
 
13731
13862
  //if(me.cfg.afid) html += this.getRadio('mn4_clr', 'mn4_clrConfidence', 'AF Confidence');
@@ -13733,8 +13864,8 @@ class SetMenu {
13733
13864
  html += this.getRadio('mn4_clr', 'mn4_clrConfidence', 'pLDDT', undefined, 1, 1);
13734
13865
  //}
13735
13866
 
13736
- html += this.getRadio('mn4_clr', 'mn4_clrIgstrand', 'Ig Strand', undefined, undefined, 2);
13737
- html += this.getRadio('mn4_clr', 'mn4_clrIgproto', 'Ig Protodomain', undefined, undefined, 2);
13867
+ html += this.getRadio('mn4_clr', 'mn4_clrIgstrand', 'Ig Strand', undefined, undefined, 1);
13868
+ html += this.getRadio('mn4_clr', 'mn4_clrIgproto', 'Ig Protodomain', undefined, undefined, 1);
13738
13869
  }
13739
13870
  else {
13740
13871
  //if(!me.cfg.hidelicense) html += this.getRadio('mn4_clr', 'mn1_delphi2', 'DelPhi<br><span style="padding-left:1.5em;">Potential ' + me.htmlCls.licenseStr + '</span>');
@@ -13787,7 +13918,7 @@ class SetMenu {
13787
13918
  html += this.getLink('mn6_selectannotations', 'Seq. & Annotations ' + me.htmlCls.wifiStr, 1, 1);
13788
13919
 
13789
13920
  //if(me.cfg.align !== undefined || me.cfg.chainalign !== undefined) { // || ic.bRealign || ic.bSymd || ic.bInputfile) {
13790
- html += this.getLink('mn2_alignment', 'Aligned Seq. ' + me.htmlCls.wifiStr, undefined, 1);
13921
+ html += this.getLink('mn2_alignment', 'Aligned Seq. ' + me.htmlCls.wifiStr, 1, 1);
13791
13922
  //}
13792
13923
 
13793
13924
  if(me.cfg.mmdbid !== undefined || me.cfg.gi !== undefined || me.cfg.blast_rep_id !== undefined || me.cfg.align !== undefined || me.cfg.chainalign !== undefined) {
@@ -13857,27 +13988,27 @@ class SetMenu {
13857
13988
  html += "</ul>";
13858
13989
  html += "</li>";
13859
13990
 
13860
- html += this.getMenuText('mn6_anglewrap', 'Angle', undefined, 1, 1);
13991
+ html += this.getMenuText('mn6_anglewrap', 'Angle', undefined, undefined, 1);
13861
13992
  html += "<ul>";
13862
- html += this.getRadio('mn6_angle', 'mn6_angleManySets', 'among Many Sets', undefined, 1, 2);
13993
+ html += this.getRadio('mn6_angle', 'mn6_angleManySets', 'among Many Sets', undefined, undefined, 2);
13863
13994
  html += this.getRadio('mn6_angle', 'mn6_angleTwoSets', 'b/w Two Vectors', undefined, undefined, 2);
13864
13995
  html += "</ul>";
13865
13996
  html += "</li>";
13866
13997
 
13867
- html += this.getLink('mn6_area', 'Surface Area', 1, 1);
13998
+ html += this.getLink('mn6_area', 'Surface Area', undefined, 1);
13868
13999
 
13869
14000
  html += this.getMenuText('mn6_addlabelwrap', 'Label', undefined, 1, 1);
13870
14001
  html += "<ul>";
13871
14002
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelYes', 'by Picking Atoms', undefined, undefined, 2);
13872
14003
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelSelection', 'per Selection', undefined, undefined, 2);
13873
14004
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelAtoms', 'per Atom', undefined, undefined, 2);
13874
- html += this.getRadio('mn6_addlabel', 'mn6_addlabelElements', 'per Atom Element', undefined, 1, 2);
14005
+ html += this.getRadio('mn6_addlabel', 'mn6_addlabelElements', 'per Atom Element', undefined, undefined, 2);
13875
14006
  if(me.cfg.cid === undefined) {
13876
14007
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelResidues', 'per Residue', undefined, 1, 2);
13877
14008
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelResnum', 'per Residue & Number', undefined, 1, 2);
13878
14009
 
13879
- html += this.getRadio('mn6_addlabel', 'mn6_addlabelRefnum', 'per Reference Number', undefined, 1, 2);
13880
- html += this.getRadio('mn6_addlabel', 'mn6_addlabelIg', 'per Ig Domain', undefined, 1, 2);
14010
+ html += this.getRadio('mn6_addlabel', 'mn6_addlabelRefnum', 'per Reference Number', undefined, undefined, 2);
14011
+ html += this.getRadio('mn6_addlabel', 'mn6_addlabelIg', 'per Ig Domain', undefined, undefined, 2);
13881
14012
 
13882
14013
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelChains', 'per Chain', undefined, undefined, 2);
13883
14014
  html += this.getRadio('mn6_addlabel', 'mn6_addlabelTermini', 'N- & C-Termini', undefined, 1, 2);
@@ -13914,10 +14045,10 @@ class SetMenu {
13914
14045
  html += this.getMenuSep();
13915
14046
 
13916
14047
  if(me.cfg.cid === undefined) {
13917
- html += this.getMenuText('mn6_chemicalbindingwrap', 'Chem. Binding', undefined, undefined, 1);
14048
+ html += this.getMenuText('mn6_chemicalbindingwrap', 'Chem. Binding', undefined, 1, 1);
13918
14049
  html += "<ul>";
13919
- html += this.getRadio('mn6_chemicalbinding', 'mn6_chemicalbindingshow', 'Show', undefined, undefined, 2);
13920
- html += this.getRadio('mn6_chemicalbinding', 'mn6_chemicalbindinghide', 'Hide', true, undefined, 2);
14050
+ html += this.getRadio('mn6_chemicalbinding', 'mn6_chemicalbindingshow', 'Show', undefined, 1, 2);
14051
+ html += this.getRadio('mn6_chemicalbinding', 'mn6_chemicalbindinghide', 'Hide', true, 1, 2);
13921
14052
  html += "</ul>";
13922
14053
  html += "</li>";
13923
14054
 
@@ -14076,7 +14207,7 @@ class SetMenu {
14076
14207
 
14077
14208
  //html += liStr + "https://www.ncbi.nlm.nih.gov/structure' target='_blank'>Search Structure " + me.htmlCls.wifiStr + "</a></li>";
14078
14209
  //html += liStr + me.htmlCls.baseUrl + "icn3d/icn3d.html#citing' target='_blank'>Citing iCn3D</a></li>";
14079
- html += this.getMenuUrl('citing', me.htmlCls.baseUrl + "icn3d/icn3d.html#citing", "Citing iCn3D", undefined, 1);
14210
+ html += this.getMenuUrl('citing', me.htmlCls.baseUrl + "icn3d/icn3d.html#citing", "Citing iCn3D", 1, 1);
14080
14211
 
14081
14212
  html += this.getMenuText('mn6_source', 'Source Code', undefined, 1, 1);
14082
14213
  html += "<ul>";
@@ -15106,6 +15237,19 @@ class SetDialog {
15106
15237
  html += me.htmlCls.buttonStr + "reload_xyzfile'>Load</button>";
15107
15238
  html += "</div>";
15108
15239
 
15240
+ html += me.htmlCls.divStr + "dl_clustalwfile' class='" + dialogClass + "' style='max-width:500px'>";
15241
+ html += this.addNotebookTitle('dl_clustalwfile', 'Please input a CLUSTALW MSA file');
15242
+ 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>";
15243
+ html += "CLUSTALW File: " + me.htmlCls.inputFileStr + "id='" + me.pre + "clustalwfile' size=8> ";
15244
+ html += me.htmlCls.buttonStr + "reload_clustalwfile'>Load</button><br>";
15245
+ html += "</div>";
15246
+ html += me.htmlCls.divStr + "dl_fastafile' class='" + dialogClass + "' style='max-width:500px'>";
15247
+ html += this.addNotebookTitle('dl_fastafile', 'Please input a FASTA file');
15248
+ 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>";
15249
+ html += "FASTA File: " + me.htmlCls.inputFileStr + "id='" + me.pre + "fastafile' size=8> ";
15250
+ html += me.htmlCls.buttonStr + "reload_fastafile'>Load</button><br>";
15251
+ html += "</div>";
15252
+
15109
15253
  html += me.htmlCls.divStr + "dl_afmapfile' class='" + dialogClass + "'>";
15110
15254
  html += this.addNotebookTitle('dl_afmapfile', 'Please input an AlphaFold PAE file');
15111
15255
  html += "AlphaFold PAE File: " + me.htmlCls.inputFileStr + "id='" + me.pre + "afmapfile' size=8> <br><br>";
@@ -15225,6 +15369,12 @@ class SetDialog {
15225
15369
  html += me.htmlCls.buttonStr + "reload_state' style='margin-top: 6px;'>Load</button>";
15226
15370
  html += "</div>";
15227
15371
 
15372
+ html += me.htmlCls.divStr + "dl_video' class='" + dialogClass + "'>";
15373
+ html += this.addNotebookTitle('dl_video', 'Save canvas changes in a video');
15374
+ html += me.htmlCls.buttonStr + "video_start' style='margin-top: 6px;'>Video Start</button>";
15375
+ html += me.htmlCls.buttonStr + "video_end' style='margin: 6px 0px 0px 30px;'>Video End</button>";
15376
+ html += "</div>";
15377
+
15228
15378
  html += me.htmlCls.divStr + "dl_fixedversion' style='max-width:500px' class='" + dialogClass + "'>";
15229
15379
  html += this.addNotebookTitle('dl_fixedversion', 'Use fixed version of iCn3D');
15230
15380
  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>";
@@ -16584,17 +16734,10 @@ class Events {
16584
16734
  }
16585
16735
  }
16586
16736
 
16587
- async loadPdbFile(bAppend, fileId, bmmCIF) { let me = this.icn3dui, ic = me.icn3d;
16737
+ async loadPdbFile(bAppend, fileId, bmmCIF) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
16588
16738
  //me = ic.setIcn3dui(this.id);
16589
16739
  ic.bInitial = true;
16590
- if(!me.cfg.notebook) dialog.dialog( "close" );
16591
- //close all dialog
16592
- if(!me.cfg.notebook) {
16593
- $(".ui-dialog-content").dialog("close");
16594
- }
16595
- else {
16596
- ic.resizeCanvasCls.closeDialogs();
16597
- }
16740
+ thisClass.iniFileLoad();
16598
16741
  let files = $("#" + me.pre + fileId)[0].files;
16599
16742
  if(!files[0]) {
16600
16743
  alert("Please select a file before clicking 'Load'");
@@ -16638,6 +16781,24 @@ class Events {
16638
16781
  $("#" + me.pre + id).resizable();
16639
16782
  }
16640
16783
 
16784
+ exportMsa(type) { let me = this.icn3dui, ic = me.icn3d;
16785
+ let text = ic.msa[type].join('\n\n');
16786
+ let fileType = (type == 'fasta') ? '.fasta' : (type == 'clustalw') ? '.aln' : '.txt';
16787
+
16788
+ ic.saveFileCls.saveFile(ic.inputid + '_align' + fileType, 'text', [text]);
16789
+ }
16790
+
16791
+ iniFileLoad() { let me = this.icn3dui, ic = me.icn3d;
16792
+ if(!me.cfg.notebook) dialog.dialog( "close" );
16793
+ //close all dialog
16794
+ if(!me.cfg.notebook) {
16795
+ $(".ui-dialog-content").dialog("close");
16796
+ }
16797
+ else {
16798
+ ic.resizeCanvasCls.closeDialogs();
16799
+ }
16800
+ }
16801
+
16641
16802
  async launchMmdb(ids, bBiounit, hostUrl, bAppend) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
16642
16803
  if(!me.cfg.notebook) dialog.dialog( "close" );
16643
16804
 
@@ -17733,16 +17894,40 @@ class Events {
17733
17894
 
17734
17895
  me.htmlCls.setHtmlCls.clickReload_pngimage();
17735
17896
 
17897
+ me.myEventCls.onIds("#" + me.pre + "video_start", "click", function(e) { let ic = me.icn3d;
17898
+ e.preventDefault();
17899
+
17900
+ const canvas = document.getElementById(ic.pre + "canvas");
17901
+ ic.videoRecorder = new MediaRecorder(canvas.captureStream());
17902
+ const recordedChunks = [];
17903
+
17904
+ // Collect data chunks
17905
+ ic.videoRecorder.ondataavailable = event => {
17906
+ recordedChunks.push(event.data);
17907
+ };
17908
+
17909
+ ic.videoRecorder.onstop = event => {
17910
+ // Code to save the recordedChunks as a video file
17911
+ const blob = new Blob(recordedChunks, {type: ic.videoRecorder.mimeType});
17912
+ let fileName = ic.inputid + '_video';
17913
+ saveAs(blob, fileName);
17914
+ };
17915
+
17916
+ // Start recording
17917
+ ic.videoRecorder.start();
17918
+ thisClass.setLogCmd('Video revording started', false);
17919
+ });
17920
+
17921
+ me.myEventCls.onIds("#" + me.pre + "video_end", "click", function(e) { let ic = me.icn3d;
17922
+ e.preventDefault();
17923
+
17924
+ ic.videoRecorder.stop();
17925
+ thisClass.setLogCmd('Video revording ended', false);
17926
+ });
17927
+
17736
17928
  me.myEventCls.onIds("#" + me.pre + "reload_state", "click", function(e) { let ic = me.icn3d;
17737
17929
  e.preventDefault();
17738
- if(!me.cfg.notebook) dialog.dialog( "close" );
17739
- //close all dialog
17740
- if(!me.cfg.notebook) {
17741
- $(".ui-dialog-content").dialog("close");
17742
- }
17743
- else {
17744
- ic.resizeCanvasCls.closeDialogs();
17745
- }
17930
+ thisClass.iniFileLoad();
17746
17931
  // initialize icn3dui
17747
17932
  //Do NOT clear data if iCn3D loads a pdb or other data file and then load a state file
17748
17933
  if(!ic.bInputfile) {
@@ -17794,12 +17979,7 @@ class Events {
17794
17979
  if (!file) {
17795
17980
  alert("Please select a file before clicking 'Load'");
17796
17981
  } else {
17797
- if (!me.cfg.notebook) dialog.dialog("close");
17798
- if (!me.cfg.notebook) {
17799
- $(".ui-dialog-content").dialog("close");
17800
- } else {
17801
- ic.resizeCanvasCls.closeDialogs();
17802
- }
17982
+ thisClass.iniFileLoad();
17803
17983
 
17804
17984
  ic.dAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
17805
17985
  ic.hAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
@@ -18354,14 +18534,7 @@ class Events {
18354
18534
  me.myEventCls.onIds("#" + me.pre + "reload_mol2file", "click", function(e) { let ic = me.icn3d;
18355
18535
  e.preventDefault();
18356
18536
  ic.bInitial = true;
18357
- if(!me.cfg.notebook) dialog.dialog( "close" );
18358
- //close all dialog
18359
- if(!me.cfg.notebook) {
18360
- $(".ui-dialog-content").dialog("close");
18361
- }
18362
- else {
18363
- ic.resizeCanvasCls.closeDialogs();
18364
- }
18537
+ thisClass.iniFileLoad();
18365
18538
  let file = $("#" + me.pre + "mol2file")[0].files[0];
18366
18539
  if(!file) {
18367
18540
  alert("Please select a file before clicking 'Load'");
@@ -18388,14 +18561,7 @@ class Events {
18388
18561
  me.myEventCls.onIds("#" + me.pre + "reload_sdffile", "click", function(e) { let ic = me.icn3d;
18389
18562
  e.preventDefault();
18390
18563
  ic.bInitial = true;
18391
- if(!me.cfg.notebook) dialog.dialog( "close" );
18392
- //close all dialog
18393
- if(!me.cfg.notebook) {
18394
- $(".ui-dialog-content").dialog("close");
18395
- }
18396
- else {
18397
- ic.resizeCanvasCls.closeDialogs();
18398
- }
18564
+ thisClass.iniFileLoad();
18399
18565
  let file = $("#" + me.pre + "sdffile")[0].files[0];
18400
18566
  if(!file) {
18401
18567
  alert("Please select a file before clicking 'Load'");
@@ -18422,14 +18588,7 @@ class Events {
18422
18588
  me.myEventCls.onIds("#" + me.pre + "reload_xyzfile", "click", function(e) { let ic = me.icn3d;
18423
18589
  e.preventDefault();
18424
18590
  ic.bInitial = true;
18425
- if(!me.cfg.notebook) dialog.dialog( "close" );
18426
- //close all dialog
18427
- if(!me.cfg.notebook) {
18428
- $(".ui-dialog-content").dialog("close");
18429
- }
18430
- else {
18431
- ic.resizeCanvasCls.closeDialogs();
18432
- }
18591
+ thisClass.iniFileLoad();
18433
18592
  let file = $("#" + me.pre + "xyzfile")[0].files[0];
18434
18593
  if(!file) {
18435
18594
  alert("Please select a file before clicking 'Load'");
@@ -18453,17 +18612,64 @@ class Events {
18453
18612
  }
18454
18613
  });
18455
18614
 
18456
- me.myEventCls.onIds("#" + me.pre + "reload_afmapfile", "click", function(e) { let ic = me.icn3d;
18615
+ me.myEventCls.onIds("#" + me.pre + "reload_clustalwfile", "click", function(e) { let ic = me.icn3d;
18457
18616
  e.preventDefault();
18458
18617
  ic.bInitial = true;
18459
- if(!me.cfg.notebook) dialog.dialog( "close" );
18460
- //close all dialog
18461
- if(!me.cfg.notebook) {
18462
- $(".ui-dialog-content").dialog("close");
18618
+ thisClass.iniFileLoad();
18619
+
18620
+ let file = $("#" + me.pre + "clustalwfile")[0].files[0];
18621
+ if(!file) {
18622
+ alert("Please select a file before clicking 'Load'");
18463
18623
  }
18464
18624
  else {
18465
- ic.resizeCanvasCls.closeDialogs();
18625
+ me.htmlCls.setHtmlCls.fileSupport();
18626
+ let reader = new FileReader();
18627
+ reader.onload = async function(e) {
18628
+ let dataStr = e.target.result; // or = reader.result;
18629
+ thisClass.setLogCmd('load CLUSTALW file ' + $("#" + me.pre + "clustalwfile").val(), false);
18630
+ ic.molTitle = "";
18631
+ ic.inputid = undefined;
18632
+ //ic.initUI();
18633
+ ic.init();
18634
+ ic.bInputfile = false; //true;
18635
+ ic.InputfileType = 'clustalw';
18636
+ await ic.msaParserCls.loadMsaData(dataStr, 'clustalw');
18637
+ };
18638
+ reader.readAsText(file);
18639
+ }
18640
+ });
18641
+
18642
+ me.myEventCls.onIds("#" + me.pre + "reload_fastafile", "click", function(e) { let ic = me.icn3d;
18643
+ e.preventDefault();
18644
+ ic.bInitial = true;
18645
+ thisClass.iniFileLoad();
18646
+
18647
+ let file = $("#" + me.pre + "fastafile")[0].files[0];
18648
+ if(!file) {
18649
+ alert("Please select a file before clicking 'Load'");
18650
+ }
18651
+ else {
18652
+ me.htmlCls.setHtmlCls.fileSupport();
18653
+ let reader = new FileReader();
18654
+ reader.onload = async function(e) {
18655
+ let dataStr = e.target.result; // or = reader.result;
18656
+ thisClass.setLogCmd('load FASTA file ' + $("#" + me.pre + "fastafile").val(), false);
18657
+ ic.molTitle = "";
18658
+ ic.inputid = undefined;
18659
+ //ic.initUI();
18660
+ ic.init();
18661
+ ic.bInputfile = false; //true;
18662
+ ic.InputfileType = 'fasta';
18663
+ await ic.msaParserCls.loadMsaData(dataStr, 'fasta');
18664
+ };
18665
+ reader.readAsText(file);
18466
18666
  }
18667
+ });
18668
+
18669
+ me.myEventCls.onIds("#" + me.pre + "reload_afmapfile", "click", function(e) { let ic = me.icn3d;
18670
+ e.preventDefault();
18671
+ ic.bInitial = true;
18672
+ thisClass.iniFileLoad();
18467
18673
  let file = $("#" + me.pre + "afmapfile")[0].files[0];
18468
18674
  if(!file) {
18469
18675
  alert("Please select a file before clicking 'Load'");
@@ -18485,14 +18691,7 @@ class Events {
18485
18691
  me.myEventCls.onIds("#" + me.pre + "reload_afmapfilefull", "click", function(e) { let ic = me.icn3d;
18486
18692
  e.preventDefault();
18487
18693
  ic.bInitial = true;
18488
- if(!me.cfg.notebook) dialog.dialog( "close" );
18489
- //close all dialog
18490
- if(!me.cfg.notebook) {
18491
- $(".ui-dialog-content").dialog("close");
18492
- }
18493
- else {
18494
- ic.resizeCanvasCls.closeDialogs();
18495
- }
18694
+ thisClass.iniFileLoad();
18496
18695
  let file = $("#" + me.pre + "afmapfile")[0].files[0];
18497
18696
  if(!file) {
18498
18697
  alert("Please select a file before clicking 'Load'");
@@ -18514,14 +18713,7 @@ class Events {
18514
18713
  me.myEventCls.onIds("#" + me.pre + "reload_urlfile", "click", async function(e) { let ic = me.icn3d;
18515
18714
  e.preventDefault();
18516
18715
  ic.bInitial = true;
18517
- if(!me.cfg.notebook) dialog.dialog( "close" );
18518
- //close all dialog
18519
- if(!me.cfg.notebook) {
18520
- $(".ui-dialog-content").dialog("close");
18521
- }
18522
- else {
18523
- ic.resizeCanvasCls.closeDialogs();
18524
- }
18716
+ thisClass.iniFileLoad();
18525
18717
  let type = $("#" + me.pre + "filetype").val();
18526
18718
  let url = $("#" + me.pre + "urlfile").val();
18527
18719
  ic.inputurl = 'type=' + type + '&url=' + encodeURIComponent(url);
@@ -19388,6 +19580,24 @@ class Events {
19388
19580
  ic.selectionCls.saveSelection(name, name);
19389
19581
  });
19390
19582
 
19583
+ me.myEventCls.onIds("#" + me.pre + "saveFasta", "click", function(e) { me.icn3d;
19584
+ e.stopImmediatePropagation();
19585
+ thisClass.exportMsa('fasta');
19586
+ thisClass.setLogCmd('Save alignment in FASTA format', false);
19587
+ });
19588
+
19589
+ me.myEventCls.onIds("#" + me.pre + "saveClustal", "click", function(e) { me.icn3d;
19590
+ e.stopImmediatePropagation();
19591
+ thisClass.exportMsa('clustalw');
19592
+ thisClass.setLogCmd('Save alignment in CLUSTALWW format', false);
19593
+ });
19594
+
19595
+ me.myEventCls.onIds("#" + me.pre + "saveResbyres", "click", function(e) { me.icn3d;
19596
+ e.stopImmediatePropagation();
19597
+ thisClass.exportMsa('resbyres');
19598
+ thisClass.setLogCmd('Save alignment in Residue by Residue format to be used in File > Align (or Realign) > Multiple Chain > Residue by Residue', false);
19599
+ });
19600
+
19391
19601
  $(document).on("click", "." + me.pre + "outputselection", function(e) { let ic = me.icn3d;
19392
19602
  e.stopImmediatePropagation();
19393
19603
  ic.bSelectResidue = false;
@@ -20247,7 +20457,9 @@ class SetHtml {
20247
20457
 
20248
20458
  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> ';
20249
20459
 
20250
- 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/>";
20460
+ 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/>";
20461
+
20462
+ 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/>";
20251
20463
 
20252
20464
  sequencesHtml += me.htmlCls.divStr + "alignseqguide" + suffix + "' style='display:none; white-space:normal;' class='icn3d-box'>";
20253
20465
 
@@ -20256,7 +20468,9 @@ class SetHtml {
20256
20468
  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.";
20257
20469
  let scroll =(me.utilsCls.isMac() && !me.utilsCls.isMobile()) ? "<br/><br/><b>Turn on scroll bar:</b> System preferences -> General -> show scroll bars -> check Always" : "";
20258
20470
 
20259
- sequencesHtml += resCategories + scroll + "<br/></div>";
20471
+ sequencesHtml += resCategories + scroll + "<br/>";
20472
+
20473
+ sequencesHtml += "</div>";
20260
20474
 
20261
20475
  return sequencesHtml;
20262
20476
  }
@@ -27501,7 +27715,12 @@ class Scene {
27501
27715
  ic.cams = {
27502
27716
  perspective: ic.perspectiveCamera,
27503
27717
  orthographic: ic.orthographicCamera,
27504
- };
27718
+ };
27719
+
27720
+ if(!me.bNode && ic.opts['effect'] == 'stereo' && !window.icn3duiHash) {
27721
+ ic.effect = ic.effects[options.effect];
27722
+ ic.effect.setSize(ic.container.width(), ic.container.height());
27723
+ }
27505
27724
  };
27506
27725
 
27507
27726
  setVrAr() { let ic = this.icn3d; ic.icn3dui;
@@ -31223,8 +31442,9 @@ class Strand {
31223
31442
  }
31224
31443
  }
31225
31444
 
31226
- // add one extra residue for coils between strands/helix
31227
- if(!isNaN(firstAtom.resi) && ic.pk === 3 && bHighlight === 1 && firstAtom.ss === 'coil') {
31445
+ // add one extra residue for coils between strands/helix if the style is NOT stick, ball and stick, lines, sphere, and dot
31446
+ // if(!isNaN(firstAtom.resi) && ic.pk === 3 && bHighlight === 1 && firstAtom.ss === 'coil') {
31447
+ 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') {
31228
31448
  let residueid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
31229
31449
  if(ic.residues.hasOwnProperty(residueid)) {
31230
31450
  atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
@@ -31259,8 +31479,8 @@ class Strand {
31259
31479
  }
31260
31480
  }
31261
31481
 
31262
- // add one extra residue for coils between strands/helix
31263
- if(ic.pk === 3 && bHighlight === 1 && lastAtom.ss === 'coil') {
31482
+ // add one extra residue for coils between strands/helix if the style is NOT stick, ball and stick, lines, sphere, and dot
31483
+ 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') {
31264
31484
  let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + (parseInt(lastAtom.resi) + 1).toString();
31265
31485
  if(ic.residues.hasOwnProperty(residueid)) {
31266
31486
  atomsAdjust = me.hashUtilsCls.unionHash(atomsAdjust, me.hashUtilsCls.hash2Atoms(ic.residues[residueid],
@@ -34110,6 +34330,7 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
34110
34330
  }
34111
34331
  else {
34112
34332
  // let index2ori = {};
34333
+ let maxdist = this.maxdist;
34113
34334
  for(let serial in atomlist) {
34114
34335
  let atom = atoms[atomlist[serial]];
34115
34336
 
@@ -34126,11 +34347,11 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
34126
34347
  }
34127
34348
 
34128
34349
  // show map near the structure
34129
- for(i = Math.floor(r.x) - this.maxdist, il = Math.ceil(r.x) + this.maxdist; i <= il; ++i) {
34350
+ for(i = Math.floor(r.x) - maxdist, il = Math.ceil(r.x) + maxdist; i <= il; ++i) {
34130
34351
  if(i < 0 || i > this.header.xExtent*this.scaleFactor - 1) continue;
34131
- for(j = Math.floor(r.y) - this.maxdist, jl = Math.ceil(r.y) + this.maxdist; j<= jl; ++j) {
34352
+ for(j = Math.floor(r.y) - maxdist, jl = Math.ceil(r.y) + maxdist; j<= jl; ++j) {
34132
34353
  if(j < 0 || j > this.header.yExtent*this.scaleFactor - 1) continue;
34133
- for(k = Math.floor(r.z) - this.maxdist, kl = Math.ceil(r.z) + this.maxdist; k<= kl; ++k) {
34354
+ for(k = Math.floor(r.z) - maxdist, kl = Math.ceil(r.z) + maxdist; k<= kl; ++k) {
34134
34355
  if(k < 0 || k > this.header.zExtent*this.scaleFactor - 1) continue;
34135
34356
  let index = i * widthHeight + j * height + k;
34136
34357
  indexArray.push(index);
@@ -34139,6 +34360,16 @@ ElectronMap.prototype.fillvoxels = function(atoms, atomlist) { //(int seqinit,in
34139
34360
  }
34140
34361
  }
34141
34362
 
34363
+ // show all
34364
+ // for(i = 0; i < this.pLength; ++i) {
34365
+ // for(j = 0; j < this.pWidth; ++j) {
34366
+ // for(k = 0; k < this.pHeight; ++k) {
34367
+ // let index = i * widthHeight + j * height + k;
34368
+ // indexArray.push(index);
34369
+ // }
34370
+ // }
34371
+ // }
34372
+
34142
34373
  for(i = 0, il = indexArray.length; i < il; ++i) {
34143
34374
  let index = indexArray[i];
34144
34375
 
@@ -35400,6 +35631,7 @@ class ApplyDisplay {
35400
35631
  for(let residueid in singletonResidueHash) {
35401
35632
  // get calpha
35402
35633
  let calpha = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[residueid]);
35634
+ let sideAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.selectionCls.getSideAtoms(ic.residues[residueid]));
35403
35635
  let atom = calpha;
35404
35636
 
35405
35637
  let prevResidueid = atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) - 1).toString();
@@ -35416,7 +35648,7 @@ class ApplyDisplay {
35416
35648
  }
35417
35649
  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') ) {
35418
35650
  // do not add extra residue if the side chain is shown
35419
- if(calpha !== undefined && calpha.style2 !== undefined && calpha.style2 !== 'nothing') continue;
35651
+ if(sideAtom !== undefined && sideAtom.style2 !== undefined && sideAtom.style2 !== 'nothing') continue;
35420
35652
 
35421
35653
  let bAddResidue = false;
35422
35654
  // add the next residue with same style
@@ -35451,7 +35683,7 @@ class ApplyDisplay {
35451
35683
  }
35452
35684
  else if( (atom.style === 'ribbon' && atom.ss !== 'coil' && atom.ssend) || (atom.style === 'strand' && atom.ss !== 'coil' && atom.ssend)) {
35453
35685
  // do not add extra residue if the side chain is shown
35454
- if(calpha !== undefined && calpha.style2 !== undefined && calpha.style2 !== 'nothing') continue;
35686
+ if(sideAtom !== undefined && sideAtom.style2 !== undefined && sideAtom.style2 !== 'nothing') continue;
35455
35687
 
35456
35688
  let bAddResidue = false;
35457
35689
  // add the next residue with same style
@@ -38336,11 +38568,18 @@ class Alternate {
38336
38568
  }
38337
38569
 
38338
38570
  if(ic.scene) {
38571
+ ic.renderer.clear();
38572
+
38339
38573
  // https://github.com/gkjohnson/three-gpu-pathtracer/blob/main/example/basic.js
38340
38574
  ic.renderer.outputEncoding = THREE.sRGBEncoding;
38341
38575
  //ic.renderer.outputEncoding = THREE.LinearEncoding
38342
38576
 
38343
- ic.renderer.render(ic.scene, cam);
38577
+ if(ic.opts['effect'] == 'stereo' && !window.icn3duiHash) {
38578
+ ic.effect.render(ic.scene, cam);
38579
+ }
38580
+ else {
38581
+ ic.renderer.render(ic.scene, cam);
38582
+ }
38344
38583
  }
38345
38584
  }
38346
38585
 
@@ -52717,13 +52956,20 @@ class ShowInter {
52717
52956
  }
52718
52957
  // do not change the set of displaying atoms
52719
52958
  //ic.dAtoms = me.hashUtilsCls.cloneHash(ic.atoms);
52720
- let commandname, commanddesc;
52959
+ let commandname, commanddesc, commandname2;
52721
52960
  let firstAtom = ic.firstAtomObjCls.getFirstAtomObj(atomlistTarget);
52961
+
52722
52962
  if(firstAtom !== undefined) {
52723
52963
  commandname = "sphere." + firstAtom.chain + ":" + me.utilsCls.residueName2Abbr(firstAtom.resn.substr(0, 3)).trim() + firstAtom.resi + "-" + radius + "A";
52724
- if(bInteraction) commandname = "interactions." + firstAtom.chain + ":" + me.utilsCls.residueName2Abbr(firstAtom.resn.substr(0, 3)).trim() + firstAtom.resi + "-" + $("#" + ic.pre + "contactthreshold").val() + "A";
52964
+ //sometimes firstAtom.resi changed, thus we add a general name
52965
+ commandname2 = "sphere-" + radius + "A";
52966
+ if(bInteraction) {
52967
+ commandname = "interactions." + firstAtom.chain + ":" + me.utilsCls.residueName2Abbr(firstAtom.resn.substr(0, 3)).trim() + firstAtom.resi + "-" + $("#" + ic.pre + "contactthreshold").val() + "A";
52968
+ commandname2 = "interactions-" + $("#" + ic.pre + "contactthreshold").val() + "A";
52969
+ }
52725
52970
  commanddesc = commandname;
52726
52971
  ic.selectionCls.addCustomSelection(residueArray, commandname, commanddesc, select, true);
52972
+ ic.selectionCls.addCustomSelection(residueArray, commandname2, commanddesc, select, true);
52727
52973
  }
52728
52974
  ic.selectionCls.saveSelectionIfSelected();
52729
52975
  ic.drawCls.draw();
@@ -54901,6 +55147,7 @@ class ChainalignParser {
54901
55147
 
54902
55148
  ajaxArray.push(alignAjax);
54903
55149
  indexArray.push(index - 1);
55150
+ mmdbid_q = chainidArray[index].substr(0, chainidArray[index].indexOf('_'));
54904
55151
  struArray.push(mmdbid_q);
54905
55152
  }
54906
55153
 
@@ -54929,7 +55176,8 @@ class ChainalignParser {
54929
55176
  let mmdbid_q = struArray[i];
54930
55177
  let index = indexArray[i];
54931
55178
 
54932
- let bEqualMmdbid = (mmdbid_q == mmdbid_t);
55179
+ // let bEqualMmdbid = (mmdbid_q == mmdbid_t);
55180
+ let bEqualMmdbid = (mmdbid_q.substr(0,4) == mmdbid_t.substr(0,4));
54933
55181
  let bEqualChain = false;
54934
55182
 
54935
55183
  let queryData = {}; // check whether undefined
@@ -55179,7 +55427,7 @@ class ChainalignParser {
55179
55427
 
55180
55428
  transformStructure(mmdbid, index, alignType, bForce) { let ic = this.icn3d, me = ic.icn3dui;
55181
55429
  let chainidArray = ic.structures[mmdbid];
55182
-
55430
+
55183
55431
  for(let i = 0, il = chainidArray.length; i < il; ++i) {
55184
55432
  for(let serial in ic.chains[chainidArray[i]]) {
55185
55433
  let atm = ic.atoms[serial];
@@ -55311,6 +55559,26 @@ class ChainalignParser {
55311
55559
  return chainidArray;
55312
55560
  }
55313
55561
 
55562
+ addPostfixForStructureids(structArray) { let ic = this.icn3d; ic.icn3dui;
55563
+ let struct2cnt = {};
55564
+ for(let i = 0, il = structArray.length; i < il; ++i) {
55565
+ let struct = structArray[i].toUpperCase();
55566
+
55567
+ if(!struct2cnt.hasOwnProperty(struct)) {
55568
+ struct2cnt[struct] = 1;
55569
+ }
55570
+ else {
55571
+ ++struct2cnt[struct];
55572
+ }
55573
+
55574
+ struct = (struct2cnt[struct] == 1) ? struct : struct + struct2cnt[struct];
55575
+
55576
+ structArray[i] = struct;
55577
+ }
55578
+
55579
+ return structArray;
55580
+ }
55581
+
55314
55582
  async downloadChainalignment(chainalign) { let ic = this.icn3d, me = ic.icn3dui;
55315
55583
  let thisClass = this;
55316
55584
 
@@ -55352,6 +55620,7 @@ class ChainalignParser {
55352
55620
 
55353
55621
  ic.afChainIndexHash = {};
55354
55622
  ic.pdbChainIndexHash = {};
55623
+
55355
55624
  for(let index = 1, indexLen = alignArray.length; index < indexLen; ++index) {
55356
55625
  let pos2 = alignArray[index].indexOf('_');
55357
55626
  let mmdbid_q_tmp = alignArray[index].substr(0, pos2).toUpperCase();
@@ -55459,7 +55728,8 @@ class ChainalignParser {
55459
55728
 
55460
55729
  if(queryData !== undefined && JSON.stringify(queryData).indexOf('Oops there was a problem') === -1
55461
55730
  ) {
55462
- ic.mmdbidArray.push(mmdbid_q);
55731
+ // ic.mmdbidArray.push(mmdbid_q);
55732
+ ic.mmdbidArray.push(mmdbid_q.substr(0,4));
55463
55733
  queryDataArray.push(queryData);
55464
55734
  }
55465
55735
  else {
@@ -55498,7 +55768,8 @@ class ChainalignParser {
55498
55768
  // let align = (me.bNode) ? dataArray[index2 - missedChainCnt] : dataArray[index2 - missedChainCnt].value;//[0];
55499
55769
  let align = dataArray[index2 - missedChainCnt].value;//[0];
55500
55770
 
55501
- let bEqualMmdbid = (mmdbid_q == mmdbid_t);
55771
+ // let bEqualMmdbid = (mmdbid_q == mmdbid_t);
55772
+ let bEqualMmdbid = (mmdbid_q.substr(0,4) == mmdbid_t.substr(0,4));
55502
55773
  let bEqualChain = (chain_q == chain_t);
55503
55774
 
55504
55775
  me.htmlCls.clickMenuCls.setLogCmd("Align " + mmdbid_t + " with " + mmdbid_q, false);
@@ -55669,15 +55940,14 @@ class ChainalignParser {
55669
55940
 
55670
55941
  let structArray = [];
55671
55942
 
55672
- for(let i = 0, il = structArrayTmp.length; i < il; ++i) {
55673
- let id = structArrayTmp[i].toUpperCase();
55674
- // sometimes we want to load same structure multiple times
55675
- if(!ic.structures.hasOwnProperty(id) && structArray.indexOf(id) == -1) {
55676
- structArray.push(structArrayTmp[i]);
55677
- }
55678
- else {
55679
- // only when bNoDuplicate is undefined/false, it's allowed to load multiple copies of the same structure
55680
- if(!bNoDuplicate) structArray.push(structArrayTmp[i] + me.htmlCls.postfix);
55943
+ // only when bNoDuplicate is undefined/false, it's allowed to load multiple copies of the same structure
55944
+ if(!bNoDuplicate) {
55945
+ structArray = this.addPostfixForStructureids(structArrayTmp);
55946
+ }
55947
+ else {
55948
+ for(let i = 0, il = structArrayTmp.length; i < il; ++i) {
55949
+ let id = structArrayTmp[i].toUpperCase();
55950
+ if(!ic.structures.hasOwnProperty(id)) structArray.push(structArrayTmp[i]);
55681
55951
  }
55682
55952
  }
55683
55953
 
@@ -59672,6 +59942,283 @@ class XyzParser {
59672
59942
  }
59673
59943
  }
59674
59944
 
59945
+ /**
59946
+ * @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
59947
+ */
59948
+
59949
+ class MsaParser {
59950
+ constructor(icn3d) {
59951
+ this.icn3d = icn3d;
59952
+ }
59953
+
59954
+ async loadMsaData(data, type) { let ic = this.icn3d, me = ic.icn3dui;
59955
+ let bResult = await this.loadMsaSeqData(data, type);
59956
+
59957
+ if(me.cfg.align === undefined && Object.keys(ic.structures).length == 1) {
59958
+ $("#" + ic.pre + "alternateWrapper").hide();
59959
+ }
59960
+
59961
+ let typeStr = type.toUpperCase();
59962
+
59963
+ if(!bResult) {
59964
+ alert('The ' + typeStr + ' file has the wrong format...');
59965
+ }
59966
+ else {
59967
+ // retrieve the structures
59968
+ me.cfg.bu = 0; // show all chains
59969
+ await ic.chainalignParserCls.downloadMmdbAf(ic.struArray.join(','));
59970
+ me.htmlCls.clickMenuCls.setLogCmd('load mmdbaf0 ' + ic.struArray.join(','), true);
59971
+
59972
+ // get the position of the first MSA residue in the full sequence
59973
+ let startPosArray = [];
59974
+ for(let i = 0, il = ic.inputChainidArray.length; i < il; ++i) {
59975
+ let chainid = ic.inputChainidArray[i];
59976
+ let inputSeqNoGap = ic.inputSeqArray[i].replace(/-/g, '');
59977
+
59978
+ // get the full seq
59979
+ let fullSeq = '';
59980
+ for(let j = 0, jl = ic.chainsSeq[chainid].length; j < jl; ++j) {
59981
+ fullSeq += ic.chainsSeq[chainid][j].name;
59982
+ }
59983
+
59984
+ // find the starting position of "inputSeq" in "fullSeq"
59985
+ let pos = fullSeq.toUpperCase().indexOf(inputSeqNoGap.substr(0, 20).toUpperCase());
59986
+ if(pos == -1) {
59987
+ 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...");
59988
+ pos = 0;
59989
+ }
59990
+ startPosArray.push(pos);
59991
+ }
59992
+
59993
+ // define residue mapping
59994
+ // The format is ": "-separated pairs: "1,5,10-50 | 1,5,10-50: 2,6,11-51 | 1,5,10-50"
59995
+ let predefinedres = '';
59996
+
59997
+ let chainid1 = ic.inputChainidArray[0], inputSeq1 = ic.inputSeqArray[0], pos1 = startPosArray[0];
59998
+ // loop through 2nd and forward
59999
+ for(let i = 1, il = ic.inputChainidArray.length; i < il; ++i) {
60000
+ let chainid2 = ic.inputChainidArray[i];
60001
+ let inputSeq2 = ic.inputSeqArray[i];
60002
+ let pos2 = startPosArray[i];
60003
+
60004
+ let index1 = pos1, index2 = pos2;
60005
+ let resiArray1 = [], resiArray2 = [];
60006
+ for(let j = 0, jl = inputSeq2.length; j < jl; ++j) {
60007
+ if(inputSeq1[j] != '-' && inputSeq2[j] != '-' && ic.chainsSeq[chainid1][index1] && ic.chainsSeq[chainid2][index2]) {
60008
+ let resi1 = ic.chainsSeq[chainid1][index1].resi;
60009
+ let resi2 = ic.chainsSeq[chainid2][index2].resi;
60010
+ if(ic.residues[chainid1 + '_' + resi1] && ic.residues[chainid2 + '_' + resi2]) {
60011
+ resiArray1.push(ic.chainsSeq[chainid1][index1].resi);
60012
+ resiArray2.push(ic.chainsSeq[chainid2][index2].resi);
60013
+ }
60014
+ }
60015
+
60016
+ if(inputSeq1[j] != '-') ++index1;
60017
+ if(inputSeq2[j] != '-') ++index2;
60018
+ }
60019
+ let resiRangeStr1 = ic.resid2specCls.resi2range(resiArray1, true);
60020
+ let resiRangeStr2 = ic.resid2specCls.resi2range(resiArray2, true);
60021
+
60022
+ predefinedres += resiRangeStr1 + ' | ' + resiRangeStr2;
60023
+ if(i < il -1) predefinedres += ': ';
60024
+ }
60025
+
60026
+ // realign based on residue by residue
60027
+ let alignment_final = ic.inputChainidArray.join(',');
60028
+
60029
+ if(predefinedres && (alignment_final.split(',').length - 1) != predefinedres.split(': ').length) {
60030
+ alert("Please make sure the number of chains and the lines of predefined residues are the same...");
60031
+ return;
60032
+ }
60033
+
60034
+ me.cfg.resdef = predefinedres.replace(/:/gi, ';');
60035
+
60036
+ let bRealign = true, bPredefined = true;
60037
+ let chainidArray = alignment_final.split(',');
60038
+ await ic.realignParserCls.realignChainOnSeqAlign(undefined, chainidArray, bRealign, bPredefined);
60039
+
60040
+ me.htmlCls.clickMenuCls.setLogCmd("realign predefined " + alignment_final + " " + predefinedres, true);
60041
+
60042
+
60043
+ ic.opts['color'] = 'identity';
60044
+ ic.setColorCls.setColorByOptions(ic.opts, ic.hAtoms);
60045
+ me.htmlCls.clickMenuCls.setLogCmd("color identity", true);
60046
+
60047
+ // show selection
60048
+ ic.selectionCls.showSelection();
60049
+ me.htmlCls.clickMenuCls.setLogCmd("show selection", true);
60050
+ }
60051
+ }
60052
+
60053
+ async loadMsaSeqData(data, type) { let ic = this.icn3d; ic.icn3dui;
60054
+ let lines = data.split(/\r?\n|\r/);
60055
+ if(lines.length < 2) return false;
60056
+
60057
+ ic.init();
60058
+
60059
+ ic.molTitle = "";
60060
+
60061
+ let seqHash = {};
60062
+
60063
+ let bStart = false, bSecBlock = false, chainid = '', seq = '', bFound = false;
60064
+
60065
+ if(type == 'clustalw' && lines[0].substr(0,7) != 'CLUSTAL') { // CLUSTAL W or CLUSTALW
60066
+ return false;
60067
+ }
60068
+
60069
+ let startLineNum = (type == 'clustalw') ? 1 : 0;
60070
+
60071
+ // 1. parse input msa
60072
+ for(let i = startLineNum, il = lines.length; i < il; ++i) {
60073
+ let line = lines[i].trim();
60074
+ if(line === '') {
60075
+ if(bStart) bSecBlock = true;
60076
+ bStart = false;
60077
+ continue;
60078
+ }
60079
+
60080
+ if(!bStart) { // first line
60081
+ if(type == 'fasta' && line.substr(0,1) != '>') {
60082
+ return false;
60083
+ }
60084
+ bStart = true;
60085
+ }
60086
+
60087
+ if(type == 'clustalw') {
60088
+ if(line.substr(0, 1) != ' ' && line.substr(0, 1) != '\t') {
60089
+ let chainid_seq = line.split(/\s+/);
60090
+ let idArray = chainid_seq[0].split('|');
60091
+ let result = this.getChainid(idArray, bStart && !bSecBlock);
60092
+ bFound = result.bFound;
60093
+ chainid = result.chainid;
60094
+
60095
+ if(bFound) {
60096
+ if(!seqHash.hasOwnProperty(chainid)) {
60097
+ seqHash[chainid] = chainid_seq[1];
60098
+ }
60099
+ else {
60100
+ seqHash[chainid] += chainid_seq[1];
60101
+ }
60102
+ }
60103
+ }
60104
+ }
60105
+ else if(type == 'fasta') {
60106
+ if(line.substr(0,1) == ">") {
60107
+ // add the previous seq
60108
+ if(chainid && seq && bFound) seqHash[chainid] = seq;
60109
+ chainid = '';
60110
+ seq = '';
60111
+
60112
+ let pos = line.indexOf(' ');
60113
+ let idArray = line.substr(1, pos).split('|');
60114
+
60115
+ if(idArray.length == 1) {
60116
+ chainid = idArray[0];
60117
+ }
60118
+ else {
60119
+ let result = this.getChainid(idArray, true);
60120
+ bFound = result.bFound;
60121
+ chainid = result.chainid;
60122
+ }
60123
+ }
60124
+ else {
60125
+ seq += line;
60126
+ }
60127
+ }
60128
+ }
60129
+
60130
+ // add the last seq
60131
+ if(type == 'fasta' && chainid && seq && bFound) seqHash[chainid] = seq;
60132
+
60133
+ // 2. get the PDB ID or RefSeqID or AlphaFold ID
60134
+ ic.inputChainidArray = [];
60135
+ ic.inputSeqArray = [];
60136
+ ic.struArray = [];
60137
+
60138
+ // find the tempate where the first residue is not gap
60139
+ let template = '';
60140
+ for(let chainid in seqHash) {
60141
+ let seq = seqHash[chainid];
60142
+ if(seq.substr(0,1) != '-') {
60143
+ template = chainid;
60144
+ await this.processOneChain(chainid, seqHash);
60145
+ break;
60146
+ }
60147
+ }
60148
+ if(!template) template = Object.keys(seqHash)[0];
60149
+
60150
+ for(let chainid in seqHash) {
60151
+ if(chainid != template) await this.processOneChain(chainid, seqHash);
60152
+ }
60153
+
60154
+ return true;
60155
+ }
60156
+
60157
+ async processOneChain(chainid, seqHash) { let ic = this.icn3d, me = ic.icn3dui;
60158
+ ic.inputSeqArray.push(seqHash[chainid]);
60159
+ // ic.inputSeqArray.push(seqHash[chainid].replace(/-/g, '')); // remove the gaps in seq
60160
+
60161
+ if(chainid.lastIndexOf('_') == 2) { // refseq ID
60162
+ // convert refseq to uniprot id
60163
+ let url = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi?refseq2uniprot=" + chainid;
60164
+
60165
+ let data = await me.getAjaxPromise(url, 'jsonp', false, 'The protein accession ' + chainid + ' can not be mapped to AlphaFold UniProt ID...');
60166
+ if(data && data.uniprot) {
60167
+ if(!ic.uniprot2acc) ic.uniprot2acc = {};
60168
+ let uniprot = data.uniprot;
60169
+ ic.uniprot2acc[uniprot] = chainid;
60170
+ ic.struArray.push(uniprot);
60171
+ ic.inputChainidArray.push(uniprot + '_A');
60172
+ }
60173
+ else {
60174
+ console.log('The accession ' + refseqid + ' can not be mapped to AlphaFold UniProt ID. It will be treated as a UniProt ID instead.');
60175
+ ic.struArray.push(chainid);
60176
+ ic.inputChainidArray.push(chainid + '_A');
60177
+ }
60178
+ }
60179
+ else if(chainid.indexOf('_') != -1) { // PDB ID
60180
+ let stru = chainid.substr(0, chainid.indexOf('_')).substr(0, 4);
60181
+ ic.struArray.push(stru);
60182
+ ic.inputChainidArray.push(chainid);
60183
+ }
60184
+ else if(chainid.length > 5) { // UniProt ID
60185
+ ic.struArray.push(chainid);
60186
+ ic.inputChainidArray.push(chainid + '_A');
60187
+ }
60188
+ }
60189
+
60190
+ getChainid(idArray, bWarning) { let ic = this.icn3d; ic.icn3dui;
60191
+ let bFound = false;
60192
+ let chainid = idArray[0];
60193
+
60194
+ for(let j = 0, jl = idArray.length; j < jl; ++j) {
60195
+ if(idArray[j] == 'pdb') {
60196
+ chainid = idArray[j+1] + '_' + idArray[j+2];
60197
+ bFound = true;
60198
+ break;
60199
+ }
60200
+ else if(idArray[j] == 'ref') { // refseq
60201
+ let refseq = idArray[j+1].split('.')[0];
60202
+ chainid = refseq; // + '_A';
60203
+ bFound = true;
60204
+ break;
60205
+ }
60206
+ else if(idArray[j] == 'sp' || idArray[j] == 'tr') { // uniprot
60207
+ let uniprot = idArray[j+1];
60208
+ chainid = uniprot;
60209
+ bFound = true;
60210
+ break;
60211
+ }
60212
+ }
60213
+
60214
+ if(!bFound && bWarning) {
60215
+ alert("The sequence ID " + idArray.join('|') + " does not have the correctly formatted PDB, UniProt or RefSeq ID...");
60216
+ }
60217
+
60218
+ return {chainid: chainid, bFound: bFound};
60219
+ }
60220
+ }
60221
+
59675
60222
  /**
59676
60223
  * @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
59677
60224
  */
@@ -59813,7 +60360,7 @@ class RealignParser {
59813
60360
  // If rmsd from vastsrv is too large, realign the chains
59814
60361
  //if(me.cfg.chainalign && !me.cfg.usepdbnum && me.cfg.resdef && rmsd > 5) {
59815
60362
  // redo algnment only for VAST serv page
59816
- if(!me.cfg.usepdbnum && me.cfg.resdef && rmsd > 5) {
60363
+ if(!me.cfg.usepdbnum && me.cfg.resdef && rmsd > 5 && me.cfg.chainalign) {
59817
60364
  console.log("RMSD from VAST is larger than 5. Realign the chains with TM-align.");
59818
60365
  //let nameArray = me.cfg.chainalign.split(',');
59819
60366
  let nameArray = Object.keys(chainidHash);
@@ -60269,7 +60816,8 @@ let resRangeArray = (me.cfg.resrange) ? decodeURIComponent(me.cfg.resrange).spli
60269
60816
  let predefinedResArray, predefinedResPair;
60270
60817
 
60271
60818
  if(bPredefined) {
60272
- predefinedResArray = decodeURIComponent(me.cfg.resdef).trim().replace(/\+/gi, ' ').split(': ');
60819
+ // predefinedResArray = decodeURIComponent(me.cfg.resdef).trim().replace(/\+/gi, ' ').split(': ');
60820
+ predefinedResArray = decodeURIComponent(me.cfg.resdef).trim().replace(/\+/gi, ' ').split('; ');
60273
60821
 
60274
60822
  if(predefinedResArray.length != chainidArray.length - 1) {
60275
60823
  alert("Please make sure the number of chains and the lines of predefined residues are the same...");
@@ -60546,7 +61094,7 @@ class DensityCifParser {
60546
61094
  let thisClass = this;
60547
61095
 
60548
61096
  let url;
60549
- let detail = (me.utilsCls.isMobile() || me.cfg.notebook) ? 2 : 4; //0 : 4;
61097
+ let detail = (me.utilsCls.isMobile() || me.cfg.notebook) ? 0 : 4; // max 6
60550
61098
 
60551
61099
  //https://www.ebi.ac.uk/pdbe/densities/doc.html
60552
61100
  if(type == '2fofc' || type == 'fofc') {
@@ -60557,6 +61105,7 @@ class DensityCifParser {
60557
61105
  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;
60558
61106
  }
60559
61107
  else if(type == 'em') {
61108
+ detail = (me.utilsCls.isMobile() || me.cfg.notebook) ? 0: 5; // max 6
60560
61109
  url = "https://www.ebi.ac.uk/pdbe/densities/emd/" + emd.toLowerCase() + "/cell?detail=" + detail;
60561
61110
  }
60562
61111
 
@@ -62130,11 +62679,12 @@ class ParserUtils {
62130
62679
 
62131
62680
  // set defined sets before loadScript
62132
62681
  if(ic.bInitial) {
62133
- if(me.cfg.mobilemenu) {
62134
- me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
62135
- let bNoSave = true;
62136
- me.htmlCls.clickMenuCls.applyShownMenus(bNoSave);
62137
- }
62682
+ // if(me.cfg.mobilemenu) {
62683
+ // me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.simpleMenus);
62684
+ // let bNoSave = true;
62685
+ // me.htmlCls.clickMenuCls.applyShownMenus(bNoSave);
62686
+ // }
62687
+
62138
62688
  // else {
62139
62689
  // me.htmlCls.shownMenus = me.hashUtilsCls.cloneHash(me.htmlCls.allMenus);
62140
62690
  // me.htmlCls.clickMenuCls.applyShownMenus();
@@ -63171,6 +63721,7 @@ class SetSeqAlign {
63171
63721
  setSeqAlign(seqalign, alignedStructures) { let ic = this.icn3d, me = ic.icn3dui;
63172
63722
  let mmdbid1 = alignedStructures[0][0].pdbId;
63173
63723
  let mmdbid2 = alignedStructures[0][1].pdbId;
63724
+ let chainid1, chainid2;
63174
63725
 
63175
63726
  ic.conservedName1 = mmdbid1 + '_cons';
63176
63727
  ic.nonConservedName1 = mmdbid1 + '_ncons';
@@ -63194,7 +63745,7 @@ class SetSeqAlign {
63194
63745
  let molid1 = alignData.moleculeId;
63195
63746
 
63196
63747
  let chain1 = ic.pdbid_molid2chain[mmdbid1 + '_' + molid1];
63197
- let chainid1 = mmdbid1 + '_' + chain1;
63748
+ chainid1 = mmdbid1 + '_' + chain1;
63198
63749
 
63199
63750
  let id2aligninfo = {};
63200
63751
  let start = alignData.sequence.length, end = -1;
@@ -63226,7 +63777,7 @@ class SetSeqAlign {
63226
63777
  let molid2 = alignData.moleculeId;
63227
63778
 
63228
63779
  let chain2 = ic.pdbid_molid2chain[mmdbid2 + '_' + molid2];
63229
- let chainid2 = mmdbid2 + '_' + chain2;
63780
+ chainid2 = mmdbid2 + '_' + chain2;
63230
63781
 
63231
63782
  // annotation title for the master seq only
63232
63783
  if(ic.alnChainsAnTtl[chainid1] === undefined ) ic.alnChainsAnTtl[chainid1] = [];
@@ -63394,7 +63945,9 @@ class SetSeqAlign {
63394
63945
  ic.alnChainsAnno[chainid1][3].push(numberStr); // symbol: 10, 20, etc, empty for rest
63395
63946
 
63396
63947
  ++alignIndex;
63397
- } // end for(let j
63948
+ } // end for(let j
63949
+
63950
+ this.setMsaFormat([chainid1, chainid2]);
63398
63951
  } // end for(let i
63399
63952
 
63400
63953
  seqalign = {};
@@ -63474,7 +64027,7 @@ class SetSeqAlign {
63474
64027
  }
63475
64028
 
63476
64029
  setSeqAlignChain(chainid, chainIndex, chainidArray) { let ic = this.icn3d, me = ic.icn3dui;
63477
- let hAtoms = {};
64030
+ let hAtoms = {};
63478
64031
 
63479
64032
  let bRealign = (chainidArray) ? true : false;
63480
64033
  let mmdbid1, mmdbid2, chain1, chain2, chainid1, chainid2, pos1, pos2;
@@ -63695,23 +64248,6 @@ class SetSeqAlign {
63695
64248
  ///if(ic.chainsSeq[chainid1] === undefined || ic.chainsSeq[chainid2] === undefined) break;
63696
64249
 
63697
64250
  let resi1, resi2, resn1, resn2;
63698
- /*
63699
- if(bRealign) { // tmalign: just one residue in this for loop
63700
- if(me.cfg.aligntool == 'tmalign') {
63701
- resi1 = ic.qt_start_end[chainIndex][i].t_start;
63702
- resi2 = ic.qt_start_end[chainIndex][i].q_start;
63703
- }
63704
- else {
63705
- resi1 = j + start1;
63706
- resi2 = j + start2;
63707
- }
63708
-
63709
- resn1 = this.getResnFromResi(chainid1, resi1).toUpperCase();
63710
- resn2 = this.getResnFromResi(chainid2, resi2).toUpperCase();
63711
-
63712
- if(resn1 == '?' || resn2 == '?') continue;
63713
- }
63714
- */
63715
64251
  if(bRealign && me.cfg.aligntool == 'tmalign') { // tmalign: just one residue in this for loop
63716
64252
  resi1 = ic.qt_start_end[chainIndex][i].t_start;
63717
64253
  resi2 = ic.qt_start_end[chainIndex][i].q_start;
@@ -63722,15 +64258,6 @@ class SetSeqAlign {
63722
64258
  if(resn1 == '?' || resn2 == '?') continue;
63723
64259
  }
63724
64260
  else {
63725
- ///if(ic.chainsSeq[chainid1][j + start1] === undefined || ic.chainsSeq[chainid2][j + start2] === undefined) continue;
63726
-
63727
- // resi1 = ic.chainsSeq[chainid1][j + start1].resi;
63728
- // resi2 = ic.chainsSeq[chainid2][j + start2].resi;
63729
- // resn1 = ic.chainsSeq[chainid1][j + start1].name.toUpperCase();
63730
- // resn2 = ic.chainsSeq[chainid2][j + start2].name.toUpperCase();
63731
-
63732
- // resi1 = this.getResiAferAlign(chainid1, bRealign, j + start1 + 1);
63733
- // resi2 = this.getResiAferAlign(chainid2, bRealign, j + start2 + 1);
63734
64261
  resi1 = this.getResiAferAlign(chainid1, bRealign, j + start1);
63735
64262
  resi2 = this.getResiAferAlign(chainid2, bRealign, j + start2);
63736
64263
  resn1 = this.getResnFromResi(chainid1, resi1).toUpperCase();
@@ -63770,14 +64297,15 @@ class SetSeqAlign {
63770
64297
 
63771
64298
  prevIndex1 = end1;
63772
64299
  prevIndex2 = end2;
63773
- } // end for(let i
64300
+ } // end for(let i
64301
+
64302
+ this.setMsaFormat([chainid1, chainid2]);
63774
64303
 
63775
64304
  return hAtoms;
63776
64305
  }
63777
64306
 
63778
64307
  setSeqAlignChainForAll(chainidArray, index_alignLen, bRealign) { let ic = this.icn3d, me = ic.icn3dui;
63779
64308
  let hAtoms = {};
63780
-
63781
64309
  let chainid1 = chainidArray[0];
63782
64310
 
63783
64311
  ic.alnChainsAnno[chainid1] = [];
@@ -63931,7 +64459,8 @@ class SetSeqAlign {
63931
64459
  resObject.aligned = (resid2range_t[resid]) ? true : false;
63932
64460
  resObject.color = (resid2range_t[resid]) ? '#FF0000' : me.htmlCls.GREYC; // color by identity
63933
64461
  resObject.color2 = (resid2range_t[resid]) ? '#FF0000' : me.htmlCls.GREYC; // color by conservation
63934
- resObject.class = (resid2range_t[resid]) ? 'icn3d-align' : 'icn3d-nalign';
64462
+ // resObject.class = (resid2range_t[resid]) ? 'icn3d-align' : 'icn3d-nalign';
64463
+ resObject.class = (resid2range_t[resid]) ? 'icn3d-cons' : 'icn3d-nalign';
63935
64464
 
63936
64465
  ic.alnChainsSeq[chainid1].push(resObject);
63937
64466
 
@@ -63950,7 +64479,9 @@ class SetSeqAlign {
63950
64479
  let hAtomsTmp = this.mergeTwoSeqForAll(chainidArray, index, alignedChainIndice, resid2range_t, start_t, end_t, bRealign);
63951
64480
 
63952
64481
  hAtoms = me.hashUtilsCls.unionHash(hAtoms, hAtomsTmp);
63953
- }
64482
+ }
64483
+
64484
+ this.setMsaFormat(chainidArray);
63954
64485
 
63955
64486
  // 3. assign the variable ic.alnChainsAnno
63956
64487
  for(let i = 0; i < 3 + 2*n; ++i) {
@@ -64021,7 +64552,7 @@ class SetSeqAlign {
64021
64552
  resObject.aligned = (bGap) ? false : bAligned;
64022
64553
  resObject.color = (bGap || !bAligned) ? me.htmlCls.GREYC : ((resn == resn_t) ? "#FF0000" : "#0000FF"); // color by identity
64023
64554
  resObject.color2 = (bGap || !bAligned) ? me.htmlCls.GREYC : '#' + ic.showAnnoCls.getColorhexFromBlosum62(resn, resn_t); // color by conservation
64024
- resObject.class = (bGap || !bAligned) ? 'icn3d-nalign' : 'icn3d-align';
64555
+ resObject.class = (bGap || !bAligned) ? 'icn3d-nalign' : ((resn == resn_t) ? "icn3d-cons" : "icn3d-ncons");
64025
64556
 
64026
64557
  return resObject;
64027
64558
  }
@@ -64295,7 +64826,7 @@ class SetSeqAlign {
64295
64826
  pos2 = result.pos2;
64296
64827
  for(let i = pos1; i < pos2; ++i) {
64297
64828
  //for(let i = pos1; i <= pos2; ++i) {
64298
- ic.alnChainsSeq[chainid2].push(gapResObject2);
64829
+ ic.alnChainsSeq[chainid2].push(gapResObject2);
64299
64830
  }
64300
64831
 
64301
64832
  return hAtoms;
@@ -64622,6 +65153,108 @@ class SetSeqAlign {
64622
65153
  }
64623
65154
  }
64624
65155
  }
65156
+
65157
+ setMsaFormat(chainidArray) { let ic = this.icn3d; ic.icn3dui;
65158
+ //set MSA
65159
+ let fastaFormat = '', clustalwFormat = 'CLUSTALWW\n\n', resbyresFormat = '';
65160
+ let chainArrayClustal = [];
65161
+
65162
+ let consArray = [], resiArrayTemplate = [];
65163
+ let chainidTemplate = chainidArray[0];
65164
+ for(let i = 0, il = chainidArray.length; i < il; ++i) {
65165
+ let chainid = chainidArray[i];
65166
+ fastaFormat += '>' + chainid + '\n';
65167
+
65168
+ let clustalwArray = [];
65169
+ let clustalwLine = chainid.padEnd(20, ' ');
65170
+ let consLine = ''.padEnd(20, ' ');
65171
+
65172
+ let resiArrayTarget = [], resiArrayQuery = [];
65173
+
65174
+ let cnt = 0;
65175
+ for(let j = 0, jl = ic.alnChainsSeq[chainid].length; j < jl; ++j) {
65176
+ let resn = ic.alnChainsSeq[chainid][j].resn;
65177
+ fastaFormat += resn;
65178
+ clustalwLine += resn;
65179
+ if(i == il - 1) {
65180
+ let alignedClass = ic.alnChainsSeq[chainid][j].class;
65181
+ if(alignedClass == 'icn3d-cons') {
65182
+ consLine += '*';
65183
+ }
65184
+ else if(alignedClass == 'icn3d-ncons') {
65185
+ consLine += '.';
65186
+ }
65187
+ else {
65188
+ consLine += ' ';
65189
+ }
65190
+ }
65191
+
65192
+ // residue by residue
65193
+ if(i == 0) {
65194
+ resiArrayTemplate.push(ic.alnChainsSeq[chainid][j].resi);
65195
+ }
65196
+ else {
65197
+ // if(ic.alnChainsSeq[chainid][j].aligned) {
65198
+ if(ic.alnChainsSeq[chainid][j].aligned && ic.alnChainsSeq[chainidTemplate][j] && ic.alnChainsSeq[chainid][j]) {
65199
+ resiArrayTarget.push(ic.alnChainsSeq[chainidTemplate][j].resi);
65200
+ resiArrayQuery.push(ic.alnChainsSeq[chainid][j].resi);
65201
+ }
65202
+ }
65203
+
65204
+ ++cnt;
65205
+
65206
+ if(cnt % 60 == 0) {
65207
+ fastaFormat += '\n';
65208
+ clustalwLine += ' ' + String(parseInt(cnt / 60) * 60);
65209
+ clustalwArray.push(clustalwLine);
65210
+ clustalwLine = chainid.padEnd(20, ' ');
65211
+
65212
+ if(i == il - 1) {
65213
+ consArray.push(consLine);
65214
+ consLine = ''.padEnd(20, ' ');
65215
+ }
65216
+ }
65217
+ }
65218
+
65219
+ // add last line
65220
+ if(cnt % 60 != 0) {
65221
+ clustalwArray.push(clustalwLine);
65222
+ if(i == il - 1) {
65223
+ consArray.push(consLine);
65224
+ }
65225
+ }
65226
+
65227
+ fastaFormat += '\n';
65228
+
65229
+ chainArrayClustal.push(clustalwArray);
65230
+ if(i == il - 1) chainArrayClustal.push(consArray);
65231
+
65232
+ // residue by residue
65233
+ let resiRangeStr1 = ic.resid2specCls.resi2range(resiArrayTarget, true);
65234
+ let resiRangeStr2 = ic.resid2specCls.resi2range(resiArrayQuery, true);
65235
+
65236
+ if(i > 0) resbyresFormat += resiRangeStr1 + ' | ' + resiRangeStr2 + '\n';
65237
+ }
65238
+
65239
+ // CLUSTALWW
65240
+ for(let j = 0, jl = chainArrayClustal[0].length; j < jl; ++j) {
65241
+ for(let i = 0, il = chainArrayClustal.length; i < il; ++i) {
65242
+ clustalwFormat += chainArrayClustal[i][j] + '\n';
65243
+ }
65244
+ clustalwFormat += '\n';
65245
+ }
65246
+
65247
+ // seq MSA
65248
+ if(!ic.msa) ic.msa = {};
65249
+
65250
+ if(!ic.msa['fasta']) ic.msa['fasta'] = [];
65251
+ if(!ic.msa['clustalw']) ic.msa['clustalw'] = [];
65252
+ if(!ic.msa['resbyres']) ic.msa['resbyres'] = [];
65253
+
65254
+ ic.msa['fasta'].push(fastaFormat);
65255
+ ic.msa['clustalw'].push(clustalwFormat);
65256
+ ic.msa['resbyres'].push(resbyresFormat);
65257
+ }
64625
65258
  }
64626
65259
 
64627
65260
  /**
@@ -67375,6 +68008,12 @@ class ApplyCommand {
67375
68008
  else if(command == 'set slab off') {
67376
68009
  ic.opts['slab'] = 'no';
67377
68010
  }
68011
+ else if(command == 'stereo on') {
68012
+ ic.opts['effect'] = 'stereo';
68013
+ }
68014
+ else if(command == 'stereo off') {
68015
+ ic.opts['effect'] = 'none';
68016
+ }
67378
68017
  else if(command == 'set assembly on') {
67379
68018
  ic.bAssembly = true;
67380
68019
  }
@@ -69448,16 +70087,26 @@ class DefinedSets {
69448
70087
  } // outer for
69449
70088
  }
69450
70089
 
69451
- setHAtomsFromSets(nameArray, type) { let ic = this.icn3d, me = ic.icn3dui;
70090
+ setHAtomsFromSets(nameArray, type) { let ic = this.icn3d; ic.icn3dui;
69452
70091
  for(let i = 0; i < nameArray.length; ++i) {
69453
70092
  let selectedSet = nameArray[i];
69454
70093
 
69455
- if((ic.defNames2Atoms === undefined || !ic.defNames2Atoms.hasOwnProperty(selectedSet)) &&(ic.defNames2Residues === undefined || !ic.defNames2Residues.hasOwnProperty(selectedSet)) ) continue;
70094
+ this.setHAtomsFromSets_base(selectedSet, type);
69456
70095
 
70096
+ // sometimes the "resi" changed and thus the name changed
70097
+ //"sphere." + firstAtom.chain + ":" + me.utilsCls.residueName2Abbr(firstAtom.resn.substr(0, 3)).trim() + firstAtom.resi + "-" + radius + "A";
70098
+ if(Object.keys(ic.hAtoms).length == 0 && (selectedSet.split('.')[0] == 'sphere' || selectedSet.split('.')[0] == 'interactions')) {
70099
+ let pos = selectedSet.lastIndexOf('-');
70100
+ selectedSet = selectedSet.split('.')[0] + selectedSet.substr(pos);
70101
+ this.setHAtomsFromSets_base(selectedSet, type);
70102
+ }
70103
+ } // outer for
70104
+ }
70105
+
70106
+ setHAtomsFromSets_base(selectedSet, type) { let ic = this.icn3d, me = ic.icn3dui;
69457
70107
  if(ic.defNames2Atoms !== undefined && ic.defNames2Atoms.hasOwnProperty(selectedSet)) {
69458
70108
 
69459
70109
  let atomArray = ic.defNames2Atoms[selectedSet];
69460
-
69461
70110
  if(type === 'or') {
69462
70111
  for(let j = 0, jl = atomArray.length; j < jl; ++j) {
69463
70112
  ic.hAtoms[atomArray[j]] = 1;
@@ -69503,7 +70152,6 @@ class DefinedSets {
69503
70152
  ic.hAtoms = me.hashUtilsCls.exclHash(ic.hAtoms, atomHash);
69504
70153
  }
69505
70154
  }
69506
- } // outer for
69507
70155
  }
69508
70156
 
69509
70157
  updateAdvancedCommands(nameArray, type) { let ic = this.icn3d; ic.icn3dui;
@@ -69526,6 +70174,7 @@ class DefinedSets {
69526
70174
 
69527
70175
  combineSets(orArray, andArray, notArray, commandname) { let ic = this.icn3d, me = ic.icn3dui;
69528
70176
  ic.hAtoms = {};
70177
+
69529
70178
  this.setHAtomsFromSets(orArray, 'or');
69530
70179
 
69531
70180
  if(Object.keys(ic.hAtoms).length == 0) {
@@ -71621,19 +72270,22 @@ class Selection {
71621
72270
  selectSideChains() { let ic = this.icn3d, me = ic.icn3dui;
71622
72271
  let currHAtoms = me.hashUtilsCls.cloneHash(ic.hAtoms);
71623
72272
 
71624
- //let nuclMainArray = ["C1'", "C1*", "C2'", "C2*", "C3'", "C3*", "C4'", "C4*", "C5'", "C5*", "O3'", "O3*", "O4'", "O4*", "O5'", "O5*", "P", "OP1", "O1P", "OP2", "O2P"];
72273
+ ic.hAtoms = this.getSideAtoms(currHAtoms);
72274
+ ic.hlUpdateCls.showHighlight();
72275
+ }
71625
72276
 
71626
- ic.hAtoms = {};
71627
- for(let i in currHAtoms) {
72277
+ getSideAtoms(atoms) { let ic = this.icn3d, me = ic.icn3dui;
72278
+ let sideAtoms = {};
72279
+ for(let i in atoms) {
71628
72280
  if((ic.proteins.hasOwnProperty(i) && ic.atoms[i].name !== "N" && ic.atoms[i].name !== "H"
71629
72281
  && ic.atoms[i].name !== "C" && ic.atoms[i].name !== "O"
71630
72282
  && !(ic.atoms[i].name === "CA" && ic.atoms[i].elem === "C") && ic.atoms[i].name !== "HA")
71631
72283
  ||(ic.nucleotides.hasOwnProperty(i) && me.parasCls.nuclMainArray.indexOf(ic.atoms[i].name) === -1) ) {
71632
- ic.hAtoms[i] = 1;
72284
+ sideAtoms[i] = 1;
71633
72285
  }
71634
72286
  }
71635
72287
 
71636
- ic.hlUpdateCls.showHighlight();
72288
+ return sideAtoms;
71637
72289
  }
71638
72290
 
71639
72291
  selectMainSideChains() { let ic = this.icn3d, me = ic.icn3dui;
@@ -72246,21 +72898,29 @@ class Resid2spec {
72246
72898
  return spec;
72247
72899
  }
72248
72900
 
72249
- resi2range(resiArray) {var ic = this.icn3d; ic.icn3dui;
72250
- let range = [];
72901
+ resi2range(resiArray, bString) {var ic = this.icn3d; ic.icn3dui;
72902
+ let range = [], rangeStr = '';
72251
72903
 
72252
- let resiArraySorted = resiArray.sort(function(a, b) {
72253
- return parseInt(a) - parseInt(b);
72254
- });
72904
+ // some chains such as 3SN6_R start with residues with high residue numbers, then end with residues with low residue numbers
72905
+ // let resiArraySorted = resiArray.sort(function(a, b) {
72906
+ // return parseInt(a) - parseInt(b);
72907
+ // });
72908
+
72909
+ let resiArraySorted = resiArray;
72255
72910
 
72256
72911
  let startResi = resiArraySorted[0];
72257
72912
  let prevResi, resi;
72258
72913
  for(let j = 0, jl = resiArraySorted.length; j < jl; ++j) {
72259
72914
  resi = resiArraySorted[j];
72260
72915
 
72261
- if(j != 0 && resi != prevResi + 1) {
72916
+ if(j != 0 && parseInt(resi) != parseInt(prevResi) + 1) {
72262
72917
  range.push(startResi);
72263
72918
  range.push(prevResi);
72919
+
72920
+ if(rangeStr) rangeStr += ',';
72921
+ if(startResi == prevResi) rangeStr += startResi;
72922
+ else rangeStr += startResi + '-' + prevResi;
72923
+
72264
72924
  startResi = resi;
72265
72925
  }
72266
72926
 
@@ -72270,8 +72930,13 @@ class Resid2spec {
72270
72930
  // last residue
72271
72931
  range.push(startResi);
72272
72932
  range.push(prevResi);
72273
-
72274
- return range;
72933
+
72934
+ if(rangeStr) rangeStr += ',';
72935
+ if(startResi == prevResi) rangeStr += startResi;
72936
+ else rangeStr += startResi + '-' + prevResi;
72937
+
72938
+ if(bString) return rangeStr;
72939
+ else return range;
72275
72940
  }
72276
72941
 
72277
72942
  atoms2spec(atomHash) {var ic = this.icn3d; ic.icn3dui;
@@ -73526,18 +74191,29 @@ class Dssp {
73526
74191
 
73527
74192
  ic.pdbDataArray = await this.promiseWithFixedJobs(pdbAjaxArray);
73528
74193
 
73529
- let bNoMoreIg = await thisClass.parseRefPdbData(ic.pdbDataArray, template);
73530
74194
  let numRound = 0;
74195
+ let bNoMoreIg = await thisClass.parseRefPdbData(ic.pdbDataArray, template, undefined, numRound);
74196
+ ++numRound;
73531
74197
 
73532
74198
  //while(!bNoMoreIg) {
73533
74199
  while(!bNoMoreIg && numRound < 15) {
73534
74200
  let bRerun = true;
73535
- bNoMoreIg = await thisClass.parseRefPdbData(ic.pdbDataArray, template, bRerun);
74201
+ bNoMoreIg = await thisClass.parseRefPdbData(ic.pdbDataArray, template, bRerun, numRound);
73536
74202
  ++numRound;
73537
74203
  }
73538
74204
  }
73539
74205
  else {
73540
- await thisClass.parseRefPdbData(undefined, template);
74206
+ await thisClass.parseRefPdbData(undefined, template, undefined, numRound);
74207
+ }
74208
+
74209
+ // refnum should be adjusted after all Ig are detected since sometimes the sheet extension may affect another Ig domain
74210
+ if(!ic.chainid2igtrack) ic.chainid2igtrack = {};
74211
+ for(let chainid in ic.chains) {
74212
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chainid]);
74213
+ if(ic.proteins.hasOwnProperty(atom.serial)) {
74214
+ let giSeq = ic.showSeqCls.getSeq(chainid);
74215
+ ic.chainid2igtrack[chainid] = this.ajdustRefnum(giSeq, chainid);
74216
+ }
73541
74217
  }
73542
74218
  // }
73543
74219
  // catch(err) {
@@ -73546,7 +74222,7 @@ class Dssp {
73546
74222
  // }
73547
74223
  }
73548
74224
 
73549
- async parseRefPdbData(dataArray, template, bRerun) { let ic = this.icn3d, me = ic.icn3dui;
74225
+ async parseRefPdbData(dataArray, template, bRerun, numRound) { let ic = this.icn3d, me = ic.icn3dui;
73550
74226
  let thisClass = this;
73551
74227
 
73552
74228
  let struArray = Object.keys(ic.structures);
@@ -73640,7 +74316,7 @@ class Dssp {
73640
74316
  dataArray2 = await this.promiseWithFixedJobs(ajaxArray);
73641
74317
 
73642
74318
  let bRound1 = true;
73643
- bNoMoreIg = await thisClass.parseAlignData(dataArray2, domainidpairArray, bRound1);
74319
+ bNoMoreIg = await thisClass.parseAlignData(dataArray2, domainidpairArray, bRound1, numRound);
73644
74320
 
73645
74321
  /// if(ic.deferredRefnum !== undefined) ic.deferredRefnum.resolve();
73646
74322
  }
@@ -73686,7 +74362,7 @@ class Dssp {
73686
74362
 
73687
74363
  dataArray3 = await this.promiseWithFixedJobs(ajaxArray);
73688
74364
 
73689
- bNoMoreIg = await thisClass.parseAlignData(dataArray3, domainidpairArray3);
74365
+ bNoMoreIg = await thisClass.parseAlignData(dataArray3, domainidpairArray3, undefined, numRound);
73690
74366
  }
73691
74367
 
73692
74368
  return bNoMoreIg;
@@ -73914,7 +74590,7 @@ class Dssp {
73914
74590
  delete ic.domainid2refpdbname[domainid];
73915
74591
  delete ic.domainid2score[domainid];
73916
74592
  }
73917
- continue;
74593
+ continue;
73918
74594
  }
73919
74595
  // }
73920
74596
  }
@@ -73978,7 +74654,7 @@ class Dssp {
73978
74654
  return domainid2segs; // only used in round 2
73979
74655
  }
73980
74656
 
73981
- async parseAlignData(dataArray, domainidpairArray, bRound1) { let ic = this.icn3d, me = ic.icn3dui;
74657
+ async parseAlignData(dataArray, domainidpairArray, bRound1, numRound) { let ic = this.icn3d, me = ic.icn3dui;
73982
74658
  let bNoMoreIg = false;
73983
74659
 
73984
74660
  let domainid2segs = this.parseAlignData_part1(dataArray, domainidpairArray, bRound1);
@@ -74003,7 +74679,8 @@ class Dssp {
74003
74679
  //let pdbid = domainid.substr(0, domainid.indexOf('_'));
74004
74680
  let chainid = domainid.substr(0, domainid.indexOf(','));
74005
74681
 
74006
- if(ic.refpdbHash.hasOwnProperty(chainid)) {
74682
+ // Adjusted refpdbname in the first try
74683
+ if(ic.refpdbHash.hasOwnProperty(chainid) && numRound == 0) {
74007
74684
  refpdbnameList = [chainid];
74008
74685
 
74009
74686
  if(!me.bNode) console.log("Adjusted refpdbname for domainid " + domainid + ": " + chainid);
@@ -74056,7 +74733,7 @@ class Dssp {
74056
74733
 
74057
74734
  dataArray3 = await this.promiseWithFixedJobs(ajaxArray);
74058
74735
 
74059
- bNoMoreIg = await this.parseAlignData(dataArray3, domainidpairArray3, false);
74736
+ bNoMoreIg = await this.parseAlignData(dataArray3, domainidpairArray3, false, numRound);
74060
74737
 
74061
74738
  // end of round 2
74062
74739
  return bNoMoreIg;
@@ -74301,6 +74978,8 @@ class Dssp {
74301
74978
  }
74302
74979
  }
74303
74980
 
74981
+ // refnum should be adjusted after all Ig are detected since sometimes the sheet extension may affect another Ig domain
74982
+ /*
74304
74983
  if(!ic.chainid2igtrack) ic.chainid2igtrack = {};
74305
74984
  for(let chainid in ic.chains) {
74306
74985
  let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chainid]);
@@ -74309,6 +74988,7 @@ class Dssp {
74309
74988
  ic.chainid2igtrack[chainid] = this.ajdustRefnum(giSeq, chainid);
74310
74989
  }
74311
74990
  }
74991
+ */
74312
74992
  }
74313
74993
 
74314
74994
  getStrandFromRefnum(oriRefnum, finalStrand) { let ic = this.icn3d; ic.icn3dui;
@@ -79241,7 +79921,7 @@ class ResizeCanvas {
79241
79921
  //let itemArray = ['dl_selectannotations', 'dl_alignment', 'dl_2ddgm', 'dl_definedsets', 'dl_graph',
79242
79922
  // 'dl_linegraph', 'dl_scatterplot', 'dl_contactmap', 'dl_allinteraction', 'dl_copyurl',
79243
79923
  // 'dl_symmetry', 'dl_symd', 'dl_rmsd', 'dl_legend', 'dl_disttable'];
79244
- 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'];
79924
+ 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'];
79245
79925
 
79246
79926
  for(let i in itemArray) {
79247
79927
  let item = itemArray[i];
@@ -79987,9 +80667,10 @@ class SaveFile {
79987
80667
  ssObj.resn = atom.resn;
79988
80668
  ssObj.resi = atom.resi;
79989
80669
 
79990
- if(parseInt(atom.resi) > parseInt(prevResi) + 1) {
79991
- ssObj.ss = ' ';
79992
- ssArray.push(ssObj);
80670
+ if(parseInt(atom.resi) > parseInt(prevResi) + 1 || atom.ssbegin) {
80671
+ let ssObj2 = me.hashUtilsCls.cloneHash(ssObj);
80672
+ ssObj2.ss = ' ';
80673
+ ssArray.push(ssObj2);
79993
80674
  }
79994
80675
 
79995
80676
  if(atom.ss == 'helix') {
@@ -80000,13 +80681,13 @@ class SaveFile {
80000
80681
  ssObj.ss = 'S';
80001
80682
  ssArray.push(ssObj);
80002
80683
  }
80003
-
80684
+ /*
80004
80685
  if(atom.ssend) {
80005
80686
  let ssObj2 = me.hashUtilsCls.cloneHash(ssObj);
80006
80687
  ssObj2.ss = ' ';
80007
80688
  ssArray.push(ssObj2);
80008
80689
  }
80009
-
80690
+ */
80010
80691
  prevResi = atom.resi;
80011
80692
  }
80012
80693
 
@@ -80014,9 +80695,9 @@ class SaveFile {
80014
80695
  for(let i = 0, il = ssArray.length; i < il; ++i) {
80015
80696
  let ssObj = ssArray[i];
80016
80697
 
80017
- if(ssObj.ss != prevSs || ssObj.ssbegin) {
80698
+ if(ssObj.ss != prevSs) {
80018
80699
  // print prev
80019
- stru2header[stru] += this.printPrevSecondary(bHelix, bSheet, prevRealSsObj, ssCnt);
80700
+ if(prevSs !== ' ') stru2header[stru] += this.printPrevSecondary(bHelix, bSheet, prevRealSsObj, ssCnt);
80020
80701
 
80021
80702
  // print current
80022
80703
  ssCnt = 0;
@@ -80024,7 +80705,7 @@ class SaveFile {
80024
80705
  bSheet = false;
80025
80706
  prevRealSsObj = undefined;
80026
80707
 
80027
- if(ssObj.ss != ' ') {
80708
+ if(ssObj.ss !== ' ') {
80028
80709
  if(ssObj.ss == 'H') {
80029
80710
  bHelix = true;
80030
80711
  prevRealSsObj = ssObj;
@@ -80040,7 +80721,7 @@ class SaveFile {
80040
80721
  }
80041
80722
  }
80042
80723
 
80043
- if(ssObj.ss != ' ') {
80724
+ if(ssObj.ss !== ' ') {
80044
80725
  ++ssCnt;
80045
80726
  prevRealSsObj = ssObj;
80046
80727
  }
@@ -81889,8 +82570,10 @@ class Ray {
81889
82570
  this.icn3d = icn3d;
81890
82571
  }
81891
82572
 
81892
- rayCaster(e, bClick) {
82573
+ rayCaster(e, bClick) { let ic = this.icn3d; ic.icn3dui;
82574
+ if(!ic.opts || ic.opts['effect'] == 'none') {
81893
82575
  this.rayCasterBase(e, bClick);
82576
+ }
81894
82577
  }
81895
82578
 
81896
82579
  rayCasterBase(e, bClick) { let ic = this.icn3d; ic.icn3dui;
@@ -83211,6 +83894,14 @@ class iCn3D {
83211
83894
  });
83212
83895
  }
83213
83896
 
83897
+ this.effects = {
83898
+ //'anaglyph': new THREE.AnaglyphEffect(this.renderer),
83899
+ //'parallax barrier': new THREE.ParallaxBarrierEffect(this.renderer),
83900
+ //'oculus rift': new THREE.OculusRiftEffect(this.renderer),
83901
+ 'stereo': new THREE.StereoEffect(this.renderer),
83902
+ 'none': this.renderer
83903
+ };
83904
+
83214
83905
  this.overdraw = 0;
83215
83906
  }
83216
83907
  else {
@@ -83357,14 +84048,6 @@ class iCn3D {
83357
84048
 
83358
84049
  this.bExtrude = true;
83359
84050
 
83360
- this.effects = {
83361
- //'anaglyph': new THREE.AnaglyphEffect(this.renderer),
83362
- //'parallax barrier': new THREE.ParallaxBarrierEffect(this.renderer),
83363
- //'oculus rift': new THREE.OculusRiftEffect(this.renderer),
83364
- //'stereo': new THREE.StereoEffect(this.renderer),
83365
- 'none': this.renderer
83366
- };
83367
-
83368
84051
  this.maxD = 500; // size of the molecule
83369
84052
  this.oriMaxD = this.maxD; // size of the molecule
83370
84053
  //this.cam_z = -150;
@@ -83417,6 +84100,7 @@ class iCn3D {
83417
84100
  //The default display options
83418
84101
  this.optsOri = {};
83419
84102
  this.optsOri['camera'] = 'perspective'; //perspective, orthographic
84103
+ this.optsOri['effect'] = 'none'; //stereo, none
83420
84104
  this.optsOri['background'] = 'black'; //transparent, black, grey, white
83421
84105
  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
83422
84106
  this.optsOri['proteins'] = 'ribbon'; //ribbon, strand, cylinder and plate, schematic, c alpha trace, backbone, b factor tube, lines, stick, ball and stick, sphere, nothing
@@ -83610,6 +84294,7 @@ class iCn3D {
83610
84294
  this.pdbParserCls = new PdbParser(this);
83611
84295
  this.sdfParserCls = new SdfParser(this);
83612
84296
  this.xyzParserCls = new XyzParser(this);
84297
+ this.msaParserCls = new MsaParser(this);
83613
84298
  this.realignParserCls = new RealignParser(this);
83614
84299
  this.densityCifParserCls = new DensityCifParser(this);
83615
84300
  this.ParserUtilsCls = new ParserUtils(this);
@@ -83866,7 +84551,7 @@ class iCn3DUI {
83866
84551
  //even when multiple iCn3D viewers are shown together.
83867
84552
  this.pre = this.cfg.divid + "_";
83868
84553
 
83869
- this.REVISION = '3.40.5';
84554
+ this.REVISION = '3.42.0';
83870
84555
 
83871
84556
  // In nodejs, iCn3D defines "window = {navigator: {}}"
83872
84557
  this.bNode = (Object.keys(window).length < 2) ? true : false;
@@ -84617,4 +85302,4 @@ class printMsg {
84617
85302
  }
84618
85303
  }
84619
85304
 
84620
- export { ARButton, AddTrack, AlignParser, AlignSW, AlignSeq, Alternate, Analysis, AnnoCddSite, AnnoContact, AnnoCrossLink, AnnoDomain, AnnoSnpClinVar, AnnoSsbond, AnnoTransMem, Annotation, ApplyCenter, ApplyClbonds, ApplyCommand, ApplyDisplay, ApplyMap, ApplyOther, ApplySsbonds, ApplySymd, Axes, Box, Brick, Camera, CartoonNucl, ChainalignParser, ClickMenu, Contact, Control, ConvertTypeCls, Curve, CurveStripArrow, Cylinder, DefinedSets, Delphi, DensityCifParser, Diagram2d, Dialog, Domain3d, Draw, DrawGraph, Dsn6Parser, Dssp, ElectronMap, Events, Export3D, FirstAtomObj, Fog, GetGraph, Glycan, HBond, HashUtilsCls, HlObjects, HlSeq, HlUpdate, Html, Impostor, Instancing, Label, Line$1 as Line, LineGraph, LoadAtomData, LoadCIF, LoadPDB, LoadScript, MarchingCube, MmcifParser, MmdbParser, Mol2Parser, MyEventCls, OpmParser, ParasCls, ParserUtils, PdbParser, PiHalogen, Picking, ProteinSurface, Ray, RealignParser, Refnum, ReprSub, Resid2spec, ResidueLabels, ResizeCanvas, RmsdSuprCls, Saltbridge, SaveFile, Scap, Scene, SdfParser, SelectByCommand, Selection, SetColor, SetDialog, SetHtml, SetMenu, SetOption, SetSeqAlign, SetStyle, ShareLink, ShowAnno, ShowInter, ShowSeq, Sphere$1 as Sphere, Stick, Strand, Strip, SubdivideCls, Surface, Symd, ThreeDPrint, Transform, Tube, UtilsCls, VRButton, Vastplus, ViewInterPairs, XyzParser, iCn3D, iCn3DUI, printMsg };
85305
+ export { ARButton, AddTrack, AlignParser, AlignSW, AlignSeq, Alternate, Analysis, AnnoCddSite, AnnoContact, AnnoCrossLink, AnnoDomain, AnnoSnpClinVar, AnnoSsbond, AnnoTransMem, Annotation, ApplyCenter, ApplyClbonds, ApplyCommand, ApplyDisplay, ApplyMap, ApplyOther, ApplySsbonds, ApplySymd, Axes, Box, Brick, Camera, CartoonNucl, ChainalignParser, ClickMenu, Contact, Control, ConvertTypeCls, Curve, CurveStripArrow, Cylinder, DefinedSets, Delphi, DensityCifParser, Diagram2d, Dialog, Domain3d, Draw, DrawGraph, Dsn6Parser, Dssp, ElectronMap, Events, Export3D, FirstAtomObj, Fog, GetGraph, Glycan, HBond, HashUtilsCls, HlObjects, HlSeq, HlUpdate, Html, Impostor, Instancing, Label, Line$1 as Line, LineGraph, LoadAtomData, LoadCIF, LoadPDB, LoadScript, MarchingCube, MmcifParser, MmdbParser, Mol2Parser, MsaParser, MyEventCls, OpmParser, ParasCls, ParserUtils, PdbParser, PiHalogen, Picking, ProteinSurface, Ray, RealignParser, Refnum, ReprSub, Resid2spec, ResidueLabels, ResizeCanvas, RmsdSuprCls, Saltbridge, SaveFile, Scap, Scene, SdfParser, SelectByCommand, Selection, SetColor, SetDialog, SetHtml, SetMenu, SetOption, SetSeqAlign, SetStyle, ShareLink, ShowAnno, ShowInter, ShowSeq, Sphere$1 as Sphere, Stick, Strand, Strip, SubdivideCls, Surface, Symd, ThreeDPrint, Transform, Tube, UtilsCls, VRButton, Vastplus, ViewInterPairs, XyzParser, iCn3D, iCn3DUI, printMsg };