icn3d 3.23.1 → 3.23.3

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
@@ -11503,7 +11503,7 @@ class SetDialog {
11503
11503
 
11504
11504
  html += me.htmlCls.divStr + "dl_mutation' class='" + dialogClass + "'>";
11505
11505
  html += "<div style='width:500px'>";
11506
- html += 'Please specify the mutations with a comma separated mutation list. Each mutation can be specified as "[<b>uppercase</b> PDB ID or AlphaFold UniProt ID]_[Chain ID]_[Residue Number]_[One Letter Mutant Residue]". E.g., the mutation of N501Y in the E chain of PDB 6M0J can be specified as "6M0J_E_501_Y". For AlphaFold structures, the "Chain ID" is "A".<br/><br/>';
11506
+ html += 'Please specify the mutations with a comma separated mutation list. Each mutation can be specified as "[<b>uppercase</b> PDB ID or AlphaFold UniProt ID]_[Chain Name]_[Residue Number]_[One Letter Mutant Residue]". E.g., the mutation of N501Y in the E chain of PDB 6M0J can be specified as "6M0J_E_501_Y". For AlphaFold structures, the "Chain ID" is "A".<br/>If you load a custom structure without PDB or UniProt ID, you can open "Seq. & Annotations" window and find the chain ID such as "stru_A". The part before the underscore is the structure ID, which can be used to specify the mutation such as "stru_A_...". Remember to choose "Show Mutation in: Current Page".<br/><br/>';
11507
11507
  html += "<div style='display:inline-block; width:110px'>Mutations: </div>" + me.htmlCls.inputTextStr + "id='" + me.pre + "mutationids' value='6M0J_E_484_K,6M0J_E_501_Y,6M0J_E_417_N' size=50><br/><br/>";
11508
11508
 
11509
11509
  html += '<b>ID Type</b>: ';
@@ -11576,8 +11576,9 @@ class SetDialog {
11576
11576
  html += "</div>";
11577
11577
 
11578
11578
  html += me.htmlCls.divStr + "dl_mmdbafid' class='" + dialogClass + "' style='max-width:600px'>";
11579
- html += "Append a list of PDB, MMDB, or AlphaFold UniProt structures: " + me.htmlCls.inputTextStr + "id='" + me.pre + "mmdbafid' placeholder='e.g., 1HHO,4N7N,P69905,P01942' size=30> <br><br>";
11580
- html += me.htmlCls.buttonStr + "reload_mmdbaf'>Append Biological Unit</button>" + me.htmlCls.buttonStr + "reload_mmdbaf_asym' style='margin-left:30px'>Append Asymmetric Unit (All Chains)</button>" + "<br/><br/>";
11579
+ html += "List of PDB, MMDB, or AlphaFold UniProt structures: " + me.htmlCls.inputTextStr + "id='" + me.pre + "mmdbafid' placeholder='e.g., 1HHO,4N7N,P69905,P01942' size=30> <br><br>";
11580
+ html += "<div style='display:inline-block; width:20px'></div>" + me.htmlCls.buttonStr + "reload_mmdbaf' style='width:150px'>Load Biological Unit</button>" + me.htmlCls.buttonStr + "reload_mmdbaf_asym' style='margin-left:30px; width:250px'>Load Asymmetric Unit (All Chains)</button>" + "<br/><br/>";
11581
+ html += "<div style='display:inline-block; width:20px'>or</div>" + me.htmlCls.buttonStr + "reload_mmdbaf_append' style='width:150px'>Append Biological Unit</button>" + me.htmlCls.buttonStr + "reload_mmdbaf_asym_append' style='margin-left:30px; width:250px'>Append Asymmetric ; Unit (All Chains)</button>" + "<br/><br/>";
11581
11582
 
11582
11583
  html += '<b>Note</b>: The "<b>biological unit</b>" is the <b>biochemically active form of a biomolecule</b>, <div style="width:20px; margin:6px 0 0 20px; display:inline-block;"><span id="'
11583
11584
  + me.pre + 'asu_bu2_expand" class="ui-icon ui-icon-plus icn3d-expand icn3d-link" style="width:15px;" title="Expand"></span><span id="'
@@ -12665,7 +12666,7 @@ class Events {
12665
12666
  $("#" + me.pre + id).resizable();
12666
12667
  }
12667
12668
 
12668
- async launchMmdb(ids, bBiounit, hostUrl) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
12669
+ async launchMmdb(ids, bBiounit, hostUrl, bAppend) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
12669
12670
  if(!me.cfg.notebook) dialog.dialog( "close" );
12670
12671
 
12671
12672
  let flag = bBiounit ? 1 : 0;
@@ -12680,40 +12681,41 @@ class Events {
12680
12681
 
12681
12682
  let idArray = ids.split(',');
12682
12683
 
12683
- /*
12684
- if(idArray.length == 1 && (idArray[0].length == 4 || !isNaN(idArray[0])) ) {
12685
- thisClass.setLogCmd("load mmdb" + flag + " " + ids, false);
12686
- let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
12687
- window.open(hostUrl + '?mmdbid=' + ids + '&bu=' + flag, urlTarget);
12688
- }
12689
- else {
12690
- thisClass.setLogCmd("load mmdbaf" + flag + " " + ids, false);
12691
- let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
12692
- window.open(hostUrl + '?mmdbafid=' + ids + '&bu=' + flag, urlTarget);
12693
- }
12694
- */
12695
-
12696
- // single MMDB ID could show memebranes
12697
- if(!ic.structures && idArray.length == 1 && (idArray[0].length == 4 || !isNaN(idArray[0])) ) {
12698
- thisClass.setLogCmd("load mmdb" + flag + " " + ids, false);
12699
- let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
12700
- window.open(hostUrl + '?mmdbid=' + ids + '&bu=' + flag, urlTarget);
12684
+ if(!bAppend) {
12685
+ if(idArray.length == 1 && (idArray[0].length == 4 || !isNaN(idArray[0])) ) {
12686
+ thisClass.setLogCmd("load mmdb" + flag + " " + ids, false);
12687
+ let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
12688
+ window.open(hostUrl + '?mmdbid=' + ids + '&bu=' + flag, urlTarget);
12689
+ }
12690
+ else {
12691
+ thisClass.setLogCmd("load mmdbaf" + flag + " " + ids, false);
12692
+ let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
12693
+ window.open(hostUrl + '?mmdbafid=' + ids + '&bu=' + flag, urlTarget);
12694
+ }
12701
12695
  }
12702
12696
  else {
12703
- me.cfg.mmdbafid = ids;
12704
- me.cfg.bu = flag;
12705
-
12706
- ic.bMmdbafid = true;
12707
- ic.inputid = (ic.inputid) ? ic.inputid + me.cfg.mmdbafid : me.cfg.mmdbafid;
12708
- if(me.cfg.bu == 1) {
12709
- ic.loadCmd = 'load mmdbaf1 ' + me.cfg.mmdbafid;
12697
+ // single MMDB ID could show memebranes
12698
+ if(!ic.structures && idArray.length == 1 && (idArray[0].length == 4 || !isNaN(idArray[0])) ) {
12699
+ thisClass.setLogCmd("load mmdb" + flag + " " + ids, false);
12700
+ let urlTarget = (ic.structures && Object.keys(ic.structures).length > 0) ? '_blank' : '_self';
12701
+ window.open(hostUrl + '?mmdbid=' + ids + '&bu=' + flag, urlTarget);
12710
12702
  }
12711
12703
  else {
12712
- ic.loadCmd = 'load mmdbaf0 ' + me.cfg.mmdbafid;
12713
- }
12714
- me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
12704
+ me.cfg.mmdbafid = ids;
12705
+ me.cfg.bu = flag;
12706
+
12707
+ ic.bMmdbafid = true;
12708
+ ic.inputid = (ic.inputid) ? ic.inputid + me.cfg.mmdbafid : me.cfg.mmdbafid;
12709
+ if(me.cfg.bu == 1) {
12710
+ ic.loadCmd = 'load mmdbaf1 ' + me.cfg.mmdbafid;
12711
+ }
12712
+ else {
12713
+ ic.loadCmd = 'load mmdbaf0 ' + me.cfg.mmdbafid;
12714
+ }
12715
+ me.htmlCls.clickMenuCls.setLogCmd(ic.loadCmd, true);
12715
12716
 
12716
- await ic.chainalignParserCls.downloadMmdbAf(me.cfg.mmdbafid);
12717
+ await ic.chainalignParserCls.downloadMmdbAf(me.cfg.mmdbafid);
12718
+ }
12717
12719
  }
12718
12720
  }
12719
12721
 
@@ -13455,21 +13457,28 @@ class Events {
13455
13457
 
13456
13458
  me.myEventCls.onIds("#" + me.pre + "reload_mmdbaf", "click", function(e) { me.icn3d;
13457
13459
  e.preventDefault();
13458
-
13459
- // remove space
13460
13460
  let ids = $("#" + me.pre + "mmdbafid").val();
13461
-
13462
13461
  thisClass.launchMmdb(ids, 1, hostUrl);
13463
13462
  });
13464
13463
 
13465
13464
  me.myEventCls.onIds("#" + me.pre + "reload_mmdbaf_asym", "click", function(e) { me.icn3d;
13466
13465
  e.preventDefault();
13467
-
13468
- // remove space
13469
13466
  let ids = $("#" + me.pre + "mmdbafid").val();
13470
13467
  thisClass.launchMmdb(ids, 0, hostUrl);
13471
13468
  });
13472
13469
 
13470
+ me.myEventCls.onIds("#" + me.pre + "reload_mmdbaf_append", "click", function(e) { me.icn3d;
13471
+ e.preventDefault();
13472
+ let ids = $("#" + me.pre + "mmdbafid").val();
13473
+ thisClass.launchMmdb(ids, 1, hostUrl, true);
13474
+ });
13475
+
13476
+ me.myEventCls.onIds("#" + me.pre + "reload_mmdbaf_asym_append", "click", function(e) { me.icn3d;
13477
+ e.preventDefault();
13478
+ let ids = $("#" + me.pre + "mmdbafid").val();
13479
+ thisClass.launchMmdb(ids, 0, hostUrl, true);
13480
+ });
13481
+
13473
13482
  me.myEventCls.onIds("#" + me.pre + "mmdbid", "keyup", function(e) { let ic = me.icn3d;
13474
13483
  if (e.keyCode === 13) {
13475
13484
  e.preventDefault();
@@ -15398,11 +15407,11 @@ class SetHtml {
15398
15407
 
15399
15408
  html += me.htmlCls.divStr + "specguide" + indexStr + "' style='display:none; width:500px' class='icn3d-box'>";
15400
15409
 
15401
- html += "<b>Specification:</b> In the selection \"$1HHO,4N7N.A,B,C:5-10,LV,3AlaVal,chemicals@CA,C\":";
15410
+ html += "<b>Specification:</b> In the selection \"$1HHO,4N7N.A,B,C:5-10,LV,3AlaVal,chemicals@CA,C,C*\":";
15402
15411
  html += "<ul><li>\"$1HHO,4N7N\" uses \"$\" to indicate structure selection.<br/>";
15403
15412
  html += "<li>\".A,B,C\" uses \".\" to indicate chain selection.<br/>";
15404
15413
  html += "<li>\":5-10,LV,3LeuVal,chemicals\" uses the colon \":\" to indicate residue selection. Residue selection could be residue number(5-10), one-letter IUPAC residue name abbreviations(LV), three-letter residue names(AlaVal, \"3\" indicates each residue name has three letters), or predefined names: \"proteins\", \"nucleotides\", \"chemicals\", \"ions\", and \"water\". IUPAC abbreviations can be written either as a contiguous string(e.g., \":LV\"), in order to find all instances of that sequence in the structure, or they can be separated by commas(e.g., \":L,V\") to select all residues of a given type in the structure(in the latter case, select all Leucine and Valine in the structure).<br/>";
15405
- html += "<li>\"@CA,C\" uses \"@\" to indicate atom selection.<br/>";
15414
+ html += "<li>\"@CA,C,C*\" uses \"@\" to indicate atom name selection. \"C*\" selects any atom names starting with \"C\". <br/>";
15406
15415
  html += "<li>Partial definition is allowed, e.g., \":1-10\" selects all residue IDs 1-10 in all chains.<br/>";
15407
15416
  html += "<li>Different selections can be unioned(with \"<b>or</b>\", default), intersected(with \"<b>and</b>\"), or negated(with \"<b>not</b>\"). For example, \":1-10 or :K\" selects all residues 1-10 and all Lys residues. \":1-10 and :K\" selects all Lys residues in the range of residue number 1-10. \":1-10 or not :K\" selects all residues 1-10, which are not Lys residues.<br/>";
15408
15417
  html += "<li>The wild card character \"X\" or \"x\" can be used to represent any character.";
@@ -15411,9 +15420,9 @@ class SetHtml {
15411
15420
  html += "<ul><li>Users can select multiple sets in the menu \"Select > Defined Sets\".<br/>";
15412
15421
  html += "<li>Different sets can be unioned(with \"<b>or</b>\", default), intersected(with \"<b>and</b>\"), or negated(with \"<b>not</b>\"). For example, if the \"Defined Sets\" menu has four sets \":1-10\", \":11-20\", \":5-15\", and \":7-8\", the command \"saved atoms :1-10 or :11-20 and :5-15 not :7-8\" unions all residues 1-10 and 11-20 to get the residues 1-20, then intersects with the residues 5-15 to get the residues 5-15, then exclude the residues 7-8 to get the final residues 5-6 and 9-15.</ul>";
15413
15422
  html += "<b>Full commands in url or command window:</b>";
15414
- html += "<ul><li>Select without saving the set: select $1HHO,4N7N.A,B,C:5-10,LV,chemicals@CA,C<br/>";
15423
+ html += "<ul><li>Select without saving the set: select $1HHO,4N7N.A,B,C:5-10,LV,chemicals@CA,C,C*<br/>";
15415
15424
  //html += "<li>Select and save: select $1HHO,4N7N.A,B,C:5-10,LV,chemicals@CA,C | name my_name | description my_description</ul>";
15416
- html += "<li>Select and save: select $1HHO,4N7N.A,B,C:5-10,LV,chemicals@CA,C | name my_name</ul>";
15425
+ html += "<li>Select and save: select $1HHO,4N7N.A,B,C:5-10,LV,chemicals@CA,C,C* | name my_name</ul>";
15417
15426
 
15418
15427
  html += "</div>";
15419
15428
 
@@ -21489,7 +21498,9 @@ class ControllerGestures extends THREE.EventDispatcher{
21489
21498
  this.up = new THREE.Vector3(0,1,0);
21490
21499
 
21491
21500
  this.type = 'unknown';
21492
- this.touchCount = 0;
21501
+ //this.touchCount = 0;
21502
+
21503
+ this.prevTap = 'none';
21493
21504
 
21494
21505
  this.clock = clock;
21495
21506
 
@@ -21506,9 +21517,9 @@ class ControllerGestures extends THREE.EventDispatcher{
21506
21517
  self.type = 'unknown';
21507
21518
  this.userData.selectPressed = true;
21508
21519
 
21509
- self.touchCount++;
21520
+ //self.touchCount++;
21510
21521
 
21511
- console.log( `onSelectStart touchCount: ${ self.touchCount }` );
21522
+ //console.log( `onSelectStart touchCount: ${ self.touchCount }` );
21512
21523
  }
21513
21524
 
21514
21525
  function onSelectEnd( ){
@@ -21518,29 +21529,36 @@ class ControllerGestures extends THREE.EventDispatcher{
21518
21529
  const startToEnd = data.endTime - data.startTime;
21519
21530
 
21520
21531
  //console.log(`ControllerGestures.onSelectEnd: startToEnd:${startToEnd.toFixed(2)} taps:${data.taps}`);
21521
-
21522
- // if (self.type === 'swipe'){
21523
- // const direction = ( self.controller1.position.y < data.startPosition.y) ? "DOWN" : "UP";
21524
- // self.dispatchEvent( { type:'swipe', direction } );
21525
- // self.type = 'unknown';
21526
- // }else
21527
-
21532
+ /*
21533
+ if (self.type === 'swipe'){
21534
+ const direction = ( self.controller1.position.y < data.startPosition.y) ? "DOWN" : "UP";
21535
+ self.dispatchEvent( { type:'swipe', direction } );
21536
+ self.type = 'unknown';
21537
+ }else
21538
+
21528
21539
  if (self.type !== "pinch" && self.type !== "rotate" && self.type !== 'pan'){
21529
- if ( startToEnd < self.doubleClickLimit ){
21540
+ // if ( startToEnd < self.doubleClickLimit ){
21530
21541
  self.type = "tap";
21531
- data.taps++;
21532
- }else if ( startToEnd > self.pressMinimum ){
21533
- self.dispatchEvent( { type: 'press', position: self.controller1.position, matrixWorld: self.controller1.matrixWorld } );
21534
- self.type = 'unknown';
21535
- }
21536
- }else {
21542
+ //data.taps++;
21543
+ // }
21544
+ // else if ( startToEnd > self.pressMinimum ){
21545
+ // self.dispatchEvent( { type: 'press', position: self.controller1.position, matrixWorld: self.controller1.matrixWorld } );
21546
+ // self.type = 'unknown';
21547
+ // }
21548
+ }else{
21537
21549
  self.type = 'unknown';
21538
21550
  }
21539
-
21551
+ */
21552
+
21553
+ if ( startToEnd < self.doubleClickLimit ){
21554
+ data.taps++;
21555
+ }
21556
+ self.type = 'tap';
21557
+
21540
21558
  this.userData.selectPressed = false;
21541
21559
  data.startPosition = undefined;
21542
21560
 
21543
- self.touchCount--;
21561
+ //self.touchCount--;
21544
21562
  }
21545
21563
  }
21546
21564
 
@@ -21551,8 +21569,7 @@ class ControllerGestures extends THREE.EventDispatcher{
21551
21569
  }else {
21552
21570
  result = this.controller1.userData.selectPressed && this.controller2.userData.selectPressed;
21553
21571
  }
21554
- const self = this;
21555
- console.log( `ControllerGestures multiTouch: ${result} touchCount:${self.touchCount}`);
21572
+ //console.log( `ControllerGestures multiTouch: ${result} touchCount:${self.touchCount}`);
21556
21573
  return result;
21557
21574
  }
21558
21575
 
@@ -21587,61 +21604,62 @@ class ControllerGestures extends THREE.EventDispatcher{
21587
21604
  elapsedTime = currentTime - data2.startTime;
21588
21605
  if (elapsedTime > 0.05 ) data2.startPosition = this.controller2.position.clone();
21589
21606
  }
21590
-
21607
+
21591
21608
  if (!this.controller1.userData.selectPressed && this.type === 'tap' ){
21592
21609
  //Only dispatch event after double click limit is passed
21593
21610
  elapsedTime = this.clock.getElapsedTime() - data1.endTime;
21594
21611
  if (elapsedTime > this.doubleClickLimit){
21595
- console.log( `ControllerGestures.update dispatchEvent taps:${data1.taps}` );
21612
+ //console.log( `ControllerGestures.update dispatchEvent taps:${data1.taps}` );
21596
21613
  switch( data1.taps ){
21597
21614
  case 1:
21598
- this.dispatchEvent( { type: 'tap', position: this.controller1.position, matrixWorld: this.controller1.matrixWorld } );
21599
- data1.prevTap = 'tap';
21615
+ //this.dispatchEvent( { type: 'tap', position: this.controller1.position, matrixWorld: this.controller1.matrixWorld } );
21616
+ self.prevTap = 'tap';
21600
21617
  break;
21601
21618
  case 2:
21602
21619
  this.dispatchEvent( { type: 'doubletap', position: this.controller1.position, matrixWorld: this.controller1.matrixWorld } );
21603
- data1.prevTap = 'doubletap';
21604
- break;
21605
- case 3:
21606
- this.dispatchEvent( { type: 'tripletap', position: this.controller1.position, matrixWorld: this.controller1.matrixWorld } );
21607
- break;
21608
- case 4:
21609
- this.dispatchEvent( { type: 'quadtap', position: this.controller1.position, matrixWorld: this.controller1.matrixWorld } );
21620
+ self.prevTap = 'doubletap';
21610
21621
  break;
21611
21622
  }
21612
21623
  this.type = "unknown";
21613
21624
  data1.taps = 0;
21614
21625
  }
21615
21626
  }
21616
-
21627
+
21617
21628
  if (this.type === 'unknown' && this.touch){
21618
- if (data1.startPosition !== undefined){
21619
- if (this.multiTouch){
21620
- if (data2.startPosition !== undefined){
21629
+ //if (data1.startPosition !== undefined){
21630
+ //if (this.multiTouch){
21631
+
21632
+ if(self.prevTap == 'doubletap') {
21633
+ //if (data2.startPosition !== undefined){
21621
21634
  //startPosition is undefined for 1/20 sec
21622
21635
  //test for pinch or rotate
21623
- data1.startPosition.distanceTo( data2.startPosition );
21624
- this.controller1.position.distanceTo( this.controller2.position );
21625
- //if ( Math.abs(delta) > 0.01 ){
21626
- if(data1.prevTap == 'tap') {
21636
+
21637
+ // const startDistance = data1.startPosition.distanceTo( data2.startPosition );
21638
+ // const currentDistance = this.controller1.position.distanceTo( this.controller2.position );
21639
+ // const delta = currentDistance - startDistance;
21640
+
21641
+ // if ( Math.abs(delta) > 0.01 ){
21627
21642
  this.type = 'pinch';
21628
21643
  this.startDistance = this.controller1.position.distanceTo( this.controller2.position );
21629
- this.dispatchEvent( { type: 'pinch', delta: 0, scale: 1, initialise: true } );
21630
- }else { // data1.prevTap == 'doubletap'
21631
- const v1 = data2.startPosition.clone().sub( data1.startPosition ).normalize();
21632
- const v2 = this.controller2.position.clone().sub( this.controller1.position ).normalize();
21633
- v1.angleTo( v2 );
21634
- //if (Math.abs(theta) > 0.2){
21635
- this.type = 'rotate';
21636
- this.startVector = v2.clone();
21637
- this.dispatchEvent( { type: 'rotate', theta: 0, initialise: true } );
21638
- //}
21639
- }
21640
- }
21641
- }else {
21644
+ //this.dispatchEvent( { type: 'pinch', delta: 0, scale: 1, initialise: true } );
21645
+ this.dispatchEvent( { type: 'pinch', delta: new THREE.Vector3(0,0,0), scale: 1, initialise: true } );
21646
+ // }else{
21647
+ // const v1 = data2.startPosition.clone().sub( data1.startPosition ).normalize();
21648
+ // const v2 = this.controller2.position.clone().sub( this.controller1.position ).normalize();
21649
+ // const theta = v1.angleTo( v2 );
21650
+ // if (Math.abs(theta) > 0.2){
21651
+ // this.type = 'rotate';
21652
+ // this.startVector = v2.clone();
21653
+ // this.dispatchEvent( { type: 'rotate', theta: 0, initialise: true } );
21654
+ // }
21655
+ // }
21656
+ //}
21657
+ }else { //if(self.prevTap == 'tap') {
21642
21658
  //test for swipe or pan
21643
- data1.startPosition.distanceTo( this.controller1.position );
21644
- elapsedTime = this.clock.getElapsedTime() - data1.startTime;
21659
+ // let dist = data1.startPosition.distanceTo( this.controller1.position );
21660
+ // elapsedTime = this.clock.getElapsedTime() - data1.startTime;
21661
+ // const velocity = dist/elapsedTime;
21662
+
21645
21663
  //console.log(`dist:${dist.toFixed(3)} velocity:${velocity.toFixed(3)}`);
21646
21664
  // if ( dist > 0.01 && velocity > 0.1 ){
21647
21665
  // const v = this.controller1.position.clone().sub( data1.startPosition );
@@ -21650,24 +21668,40 @@ class ControllerGestures extends THREE.EventDispatcher{
21650
21668
  // }else if (dist > 0.006 && velocity < 0.03){
21651
21669
  this.type = "pan";
21652
21670
  this.startPosition = this.controller1.position.clone();
21653
- this.dispatchEvent( { type: 'pan', delta: new THREE.Vector3(), initialise: true } );
21671
+ this.dispatchEvent( { type: 'pan', delta: new THREE.Vector3(0,0,0), initialise: true } );
21654
21672
  // }
21655
21673
  }
21674
+ //}
21675
+ }else if (this.type === 'pinch' || this.type === 'pan'){
21676
+ //if (this.type === 'pinch'){
21677
+ //if (this.multiTouch){
21678
+
21679
+ if(self.prevTap == 'doubletap') {
21680
+ if (this.controller2.position) {
21681
+ const currentDistance = this.controller1.position.distanceTo( this.controller2.position );
21682
+ // const delta = currentDistance - this.startDistance;
21683
+ const scale = currentDistance/this.startDistance;
21684
+
21685
+ const delta = this.controller1.position.clone().sub( this.startPosition );
21686
+ this.dispatchEvent( { type: 'pinch', delta, scale });
21687
+ }
21688
+
21689
+ // }else if (this.type === 'rotate'){
21690
+ // const v = this.controller2.position.clone().sub( this.controller1.position ).normalize();
21691
+ // let theta = this.startVector.angleTo( v );
21692
+ // const cross = this.startVector.clone().cross( v );
21693
+ // if (this.up.dot(cross) > 0) theta = -theta;
21694
+ // this.dispatchEvent( { type: 'rotate', theta } );
21695
+ /*
21696
+ //}else if (this.type === 'pan'){
21697
+ } else { //if(self.prevTap == 'tap') {
21698
+ // const delta = this.controller1.position.clone().sub( this.startPosition );
21699
+ // this.dispatchEvent( { type: 'pan', delta } );
21700
+
21701
+ const position = this.controller1.position.clone();
21702
+ this.dispatchEvent( { type: 'pan', position } );
21703
+ */
21656
21704
  }
21657
- }else if (this.type === 'pinch'){
21658
- const currentDistance = this.controller1.position.distanceTo( this.controller2.position );
21659
- const delta = currentDistance - this.startDistance;
21660
- const scale = currentDistance/this.startDistance;
21661
- this.dispatchEvent( { type: 'pinch', delta, scale });
21662
- }else if (this.type === 'rotate'){
21663
- const v = this.controller2.position.clone().sub( this.controller1.position ).normalize();
21664
- let theta = this.startVector.angleTo( v );
21665
- const cross = this.startVector.clone().cross( v );
21666
- if (this.up.dot(cross) > 0) theta = -theta;
21667
- this.dispatchEvent( { type: 'rotate', theta } );
21668
- }else if (this.type === 'pan'){
21669
- const delta = this.controller1.position.clone().sub( this.startPosition );
21670
- this.dispatchEvent( { type: 'pan', delta } );
21671
21705
  }
21672
21706
  }
21673
21707
  }
@@ -22901,45 +22935,51 @@ class Scene {
22901
22935
  ic.scene.add(ic.gestures.controller1);
22902
22936
  ic.scene.add(ic.gestures.controller2);
22903
22937
 
22904
- // firts "tap", then "pinch" event
22905
- ic.gestures.addEventListener('tap', (ev) => {
22906
- // const controller = ic.gestures.controller1;
22907
- // ic.mdl.position.set( -0.03, 0, - 0.3 ).applyMatrix4( controller.matrixWorld );
22908
- // ic.mdl.scale.copy(new THREE.Vector3( 0.001, 0.001, 0.001 ));
22909
-
22910
- const controller = ic.gestures.controller1;
22911
- ic.mdl.position.set( -0.06, 0, - 0.6 ).applyMatrix4( controller.matrixWorld );
22912
- ic.mdl.scale.copy(new THREE.Vector3( 0.005, 0.005, 0.005 ));
22913
- });
22938
+ // ic.gestures.addEventListener('tap', (ev) => {
22939
+ // // const controller = ic.gestures.controller1;
22940
+ // // ic.mdl.position.set( -0.03, 0, - 0.3 ).applyMatrix4( controller.matrixWorld );
22941
+ // // ic.mdl.scale.copy(new THREE.Vector3( 0.001, 0.001, 0.001 ));
22942
+ // });
22914
22943
 
22915
- // first "doubletap", then "rotate" event
22916
22944
  ic.gestures.addEventListener('doubletap', (ev) => {
22917
- const controller = ic.gestures.controller1;
22918
- ic.mdl.position.set( -0.06, 0, - 0.6 ).applyMatrix4( controller.matrixWorld );
22919
- ic.mdl.scale.copy(new THREE.Vector3( 0.005, 0.005, 0.005 ));
22945
+ thisClass.positionCenter();
22920
22946
  });
22921
-
22947
+ /*
22922
22948
  ic.gestures.addEventListener('pan', (ev) => { // touch across screen, move
22923
22949
  if(ev.initialise !== undefined) {
22924
22950
  thisClass.startPosition = ic.mdl.position.clone();
22951
+ thisClass.startQuaternion = ic.mdl.quaternion.clone();
22925
22952
  }
22926
22953
  else {
22927
- const adjustMove = 2; // adjust to follow the finger
22928
- const pos = thisClass.startPosition.clone().add(adjustMove * ev.delta.multiplyScalar(3));
22929
- ic.mdl.position.copy(pos);
22954
+ const endPosition = ev.position;
22955
+ let angle = Math.acos( thisClass.startPosition.dot( endPosition ) / thisClass.startPosition.length() / endPosition.length() );
22956
+
22957
+ let axis = new THREE.Vector3();
22958
+ axis.crossVectors( thisClass.startPosition, endPosition ).normalize();
22959
+
22960
+ let rotateSpeed = 6.0;
22961
+ angle *= rotateSpeed;
22962
+
22963
+ let quaternion = new THREE.Quaternion();
22964
+ quaternion.setFromAxisAngle( axis, -angle );
22965
+
22966
+ ic.mdl.quaternion.copy(thisClass.startQuaternion);
22967
+ ic.mdl.quaternion.multiplyQuaternions(quaternion, ic.mdl.quaternion);
22930
22968
  }
22931
22969
  });
22932
-
22970
+ */
22933
22971
  ic.gestures.addEventListener('pinch', (ev) => { // two fingers opening or closing
22934
22972
  if(ev.initialise !== undefined) {
22973
+ thisClass.startPosition = ic.mdl.position.clone();
22935
22974
  thisClass.startScale = ic.mdl.scale.clone();
22936
22975
  }
22937
22976
  else {
22938
- const scale = thisClass.startScale.clone().multiplyScalar(ev.scale);
22977
+ let zoomSpeed = 1.0;
22978
+ const scale = thisClass.startScale.clone().multiplyScalar(ev.scale * zoomSpeed);
22939
22979
  ic.mdl.scale.copy(scale);
22940
22980
  }
22941
22981
  });
22942
-
22982
+ /*
22943
22983
  ic.gestures.addEventListener('rotate', (ev) => { // two fingers rotating around
22944
22984
  if(ev.initialise !== undefined) {
22945
22985
  thisClass.startQuaternion = ic.mdl.quaternion.clone();
@@ -22948,10 +22988,17 @@ class Scene {
22948
22988
  ic.mdl.quaternion.copy(thisClass.startQuaternion);
22949
22989
  ic.mdl.rotateY(ev.theta);
22950
22990
  }
22951
- });
22991
+ });
22992
+ */
22952
22993
  }
22953
22994
  }
22954
22995
 
22996
+ positionCenter() { let ic = this.icn3d; ic.icn3dui;
22997
+ const controller = ic.gestures.controller1;
22998
+ ic.mdl.position.set( -0.06, 0, - 0.6 ).applyMatrix4( controller.matrixWorld );
22999
+ ic.mdl.scale.copy(new THREE.Vector3( 0.005, 0.005, 0.005 ));
23000
+ }
23001
+
22955
23002
  setVrArButtons() { let ic = this.icn3d, me = ic.icn3dui;
22956
23003
  // call just once
22957
23004
  ic.bSetVrArButtons = true;
@@ -33020,13 +33067,13 @@ class Alternate {
33020
33067
 
33021
33068
  if ( ic.renderer.xr.isPresenting){
33022
33069
  if(ic.canvasUI) ic.canvasUI.update();
33023
- if(ic.canvasUILog) ic.canvasUILog.update();
33070
+ //if(ic.canvasUILog) ic.canvasUILog.update();
33024
33071
  }
33025
33072
  }
33026
33073
  else if(ic.bAr) {
33027
33074
  if ( ic.renderer.xr.isPresenting ){
33028
33075
  ic.gestures.update();
33029
- if(ic.canvasUILog) ic.canvasUILog.update();
33076
+ //if(ic.canvasUILog) ic.canvasUILog.update();
33030
33077
  }
33031
33078
  }
33032
33079
 
@@ -41502,11 +41549,12 @@ class ShowAnno {
41502
41549
  }
41503
41550
  else if(me.cfg.blast_rep_id == chnid && ic.seqStructAlignData === undefined && ic.seqStructAlignDataSmithwm === undefined) {
41504
41551
  let title;
41505
- if(me.cfg.query_id.length > 14) {
41506
- title = 'Query: ' + me.cfg.query_id.substr(0, 6) + '...';
41552
+ let query_id = (me.cfg.oriQuery_id) ? me.cfg.oriQuery_id : me.cfg.query_id;
41553
+ if(query_id.length > 14) {
41554
+ title = 'Query: ' + query_id.substr(0, 6) + '...';
41507
41555
  }
41508
41556
  else {
41509
- title =(isNaN(me.cfg.query_id)) ? 'Query: ' + me.cfg.query_id : 'Query: gi ' + me.cfg.query_id;
41557
+ title =(isNaN(me.cfg.query_id)) ? 'Query: ' + query_id : 'Query: gi ' + query_id;
41510
41558
  }
41511
41559
  let compTitle = undefined;
41512
41560
  let compText = undefined;
@@ -41519,11 +41567,12 @@ class ShowAnno {
41519
41567
  }
41520
41568
  else if(me.cfg.blast_rep_id == chnid && (ic.seqStructAlignData !== undefined || ic.seqStructAlignDataSmithwm !== undefined) ) { // align sequence to structure
41521
41569
  let title;
41522
- if(me.cfg.query_id.length > 14) {
41523
- title = 'Query: ' + me.cfg.query_id.substr(0, 6) + '...';
41570
+ let query_id = (me.cfg.oriQuery_id) ? me.cfg.oriQuery_id : me.cfg.query_id;
41571
+ if(query_id.length > 14) {
41572
+ title = 'Query: ' + query_id.substr(0, 6) + '...';
41524
41573
  }
41525
41574
  else {
41526
- title =(isNaN(me.cfg.query_id)) ? 'Query: ' + me.cfg.query_id : 'Query: gi ' + me.cfg.query_id;
41575
+ title =(isNaN(me.cfg.query_id)) ? 'Query: ' + query_id : 'Query: gi ' + query_id;
41527
41576
  }
41528
41577
 
41529
41578
  let evalue, targetSeq, querySeq, segArray;
@@ -42011,7 +42060,7 @@ class ShowSeq {
42011
42060
  }
42012
42061
  if(me.cfg.blast_rep_id == chnid) {
42013
42062
  // change color in 3D
42014
- ic.opts['color'] = 'conservation';
42063
+ ic.opts['color'] = (ic.blastAcxn) ? 'confidence' : 'conservation';
42015
42064
  ic.setColorCls.setColorByOptions(ic.opts, ic.atoms);
42016
42065
  // remove highlight
42017
42066
  //ic.hlUpdateCls.removeHlSeq();
@@ -42301,14 +42350,14 @@ class ShowSeq {
42301
42350
 
42302
42351
  // set hash for the loops
42303
42352
  let strand2len_start_stop = {};
42304
- let prevRefnumStr, prevPostfix;
42353
+ let prevRefnumStr, prevPostfix, prevRefnum;
42305
42354
 
42306
42355
  // sometimes one chain may have several Ig domains,set a index for each IgDomain
42307
- let index = 1;
42356
+ let index = 1, prevStrandPostfix = '', bStart = false;
42308
42357
  for(let i = 0, il = giSeq.length; i < il; ++i) {
42309
42358
  let currResi = ic.ParserUtilsCls.getResi(chnid, i);
42310
42359
  let residueid = chnid + '_' + currResi;
42311
- if(ic.residues.hasOwnProperty(residueid)) {
42360
+ //if(ic.residues.hasOwnProperty(residueid)) {
42312
42361
  refnumLabel = ic.resid2refnum[residueid];
42313
42362
  if(refnumLabel) {
42314
42363
  refnumStr_ori = refnumLabel.replace(/'/g, '').replace(/\*/g, '').replace(/\^/g, '').substr(1); // C', C''
@@ -42326,27 +42375,37 @@ class ShowSeq {
42326
42375
  strand2len_start_stop[prevStrand + prevPostfix].len = currCnt - 1;
42327
42376
  strand2len_start_stop[prevStrand + prevPostfix].end = refnumStr;
42328
42377
  strand2len_start_stop[prevStrand + prevPostfix].nextStrand = currStrand;
42329
-
42330
- console.log("end: " + residueid);
42331
42378
  }
42332
42379
 
42380
+ bStart = false;
42381
+
42333
42382
  currCnt = 1;
42334
42383
  }
42335
42384
 
42385
+ // sometimes insertions may happen inside a strand. Reset currCnt
42386
+ if(currStrand == prevStrand && refnum > 1000 && refnumStr.substr(1,1) != '9') { // strand region
42387
+ currCnt = 1;
42388
+
42389
+ if(bStart && prevStrandPostfix) {
42390
+ delete strand2len_start_stop[prevStrandPostfix];
42391
+ prevStrandPostfix = '';
42392
+ }
42393
+ }
42394
+
42336
42395
  // #9##
42337
- if(prevStrand && refnum > 1000 && refnumStr.substr(1,1) == '9') { // loop region
42396
+ if(prevStrand && currStrand != ' ' && refnum > 1000 && refnumStr.substr(1,1) == '9') { // loop region
42338
42397
  if(currCnt == 1) { // start of a loop
42339
42398
  if(strand2len_start_stop.hasOwnProperty(currStrand + postfix)) { // the strand appeared in 2nd Id domain
42340
42399
  ++index;
42341
42400
  }
42342
-
42343
- console.log("start: " + residueid + " refnumStr: " + refnumStr);
42344
42401
 
42345
42402
  postfix = refnumStr.replace(refnum.toString(), '') + '_' + index;
42346
42403
  strand2len_start_stop[currStrand + postfix] = {};
42347
42404
 
42348
42405
  strand2len_start_stop[currStrand + postfix].start = prevRefnumStr;
42349
42406
  strand2len_start_stop[currStrand + postfix].chainid = chnid;
42407
+
42408
+ //prevStrandPostfix = currStrand + postfix;
42350
42409
  }
42351
42410
  refnumStr = (parseInt(currFirstDigit) * 1000 + 900 + currCnt).toString();
42352
42411
  refnumLabel = currStrand + refnumStr;
@@ -42356,7 +42415,7 @@ class ShowSeq {
42356
42415
  }
42357
42416
  }
42358
42417
  else {
42359
- if(prevStrand && !bCustom && !kabat_or_imgt) {
42418
+ if(prevStrand && currStrand != ' ' && !bCustom && !kabat_or_imgt) {
42360
42419
  if(currCnt == 1) { // start of a loop
42361
42420
  if(strand2len_start_stop.hasOwnProperty(currStrand + postfix)) { // the strand appeared in 2nd Id domain
42362
42421
  ++index;
@@ -42369,8 +42428,11 @@ class ShowSeq {
42369
42428
 
42370
42429
  strand2len_start_stop[currStrand + postfix].start = prevRefnumStr;
42371
42430
  strand2len_start_stop[currStrand + postfix].chainid = chnid;
42372
- }
42373
42431
 
42432
+ prevStrandPostfix = currStrand + postfix;
42433
+ bStart = true;
42434
+ }
42435
+
42374
42436
  // no ref num
42375
42437
  refnumStr = (parseInt(currFirstDigit) * 1000 + 900 + currCnt).toString();
42376
42438
  refnumLabel = currStrand + refnumStr;
@@ -42379,8 +42441,9 @@ class ShowSeq {
42379
42441
  }
42380
42442
 
42381
42443
  prevRefnumStr = refnumStr;
42444
+ prevRefnum = refnum;
42382
42445
  prevPostfix = postfix;
42383
- }
42446
+ //}
42384
42447
 
42385
42448
  prevStrand = currStrand;
42386
42449
  }
@@ -42389,11 +42452,13 @@ class ShowSeq {
42389
42452
  strand2len_start_stop[prevStrand + prevPostfix].end = prevRefnumStr;
42390
42453
  //strand2len_start_stop[prevStrand].nextStrand = undefined;
42391
42454
  }
42392
-
42455
+
42393
42456
  let refnumLabelNoPostfix;
42394
42457
  // sometimes one chain may have several Ig domains,set a index for each IgDomain
42395
42458
  index = 1;
42396
- let appearedStrands = {}, currStrand_ori;
42459
+ prevStrandPostfix = '';
42460
+ bStart = false;
42461
+ let appearedStrands = {}, currStrand_ori, bShowRefnum = true;
42397
42462
  for(let i = 0, il = giSeq.length; i < il; ++i) {
42398
42463
  bLoop = false;
42399
42464
 
@@ -42402,12 +42467,12 @@ class ShowSeq {
42402
42467
  let currResi = ic.ParserUtilsCls.getResi(chnid, i);
42403
42468
  let residueid = chnid + '_' + currResi;
42404
42469
  let domainid = (bCustom) ? 0 : ic.resid2domainid[residueid];
42405
- if(!ic.residues.hasOwnProperty(residueid)) {
42406
- html += '<span></span>';
42407
- }
42408
- else {
42470
+ //if(!ic.residues.hasOwnProperty(residueid)) {
42471
+ // html += '<span></span>';
42472
+ //}
42473
+ //else {
42409
42474
  refnumLabel = ic.resid2refnum[residueid];
42410
- let bNotShow = false;
42475
+ let bHidelabel = false;
42411
42476
 
42412
42477
  if(refnumLabel) {
42413
42478
  refnumStr_ori = refnumLabel.replace(/'/g, '').replace(/\*/g, '').replace(/\^/g, '').substr(1); // C', C''
@@ -42418,7 +42483,8 @@ class ShowSeq {
42418
42483
 
42419
42484
  refnumLabelNoPostfix = currStrand + parseInt(refnumStr_ori);
42420
42485
 
42421
- if(currStrand != prevStrand) { // reset currCnt
42486
+ if(currStrand_ori != prevStrand) { // reset currCnt
42487
+ bStart = false;
42422
42488
  currCnt = 1;
42423
42489
  }
42424
42490
 
@@ -42436,30 +42502,44 @@ class ShowSeq {
42436
42502
  refnum = parseInt(refnumStr);
42437
42503
  postfix = refnumStr.replace(refnum.toString(), '') + '_' + index;
42438
42504
 
42505
+ // sometimes insertions may happen inside a strand. Reset currCnt
42506
+ if(currStrand_ori == prevStrand && refnum > 1000 && refnumStr.substr(1,1) != '9') { // strand region
42507
+ currCnt = 1;
42508
+
42509
+ if(bStart && prevStrandPostfix) {
42510
+ --index;
42511
+ prevStrandPostfix = '';
42512
+ }
42513
+ }
42514
+
42439
42515
  // #9##
42440
42516
  if(prevStrand && refnum > 1000 && refnumStr.substr(1,1) == '9') { // loop region
42441
42517
  bLoop = true;
42442
42518
 
42443
42519
  if(currCnt == 1) { // start of a loop
42444
- if(appearedStrands.hasOwnProperty(currStrand + postfix)) { // the strand appeared in 2nd Id domain
42520
+ if(appearedStrands.hasOwnProperty(currStrand_ori + postfix)) { // the strand appeared in 2nd Id domain
42445
42521
  ++index;
42446
42522
  postfix = refnumStr.replace(refnum.toString(), '') + '_' + index;
42447
42523
  }
42448
42524
 
42449
- appearedStrands[currStrand + postfix] = 1;
42525
+ appearedStrands[currStrand_ori + postfix] = 1;
42450
42526
  }
42451
42527
 
42452
- let result = this.getAdjustedRefnum(strand2len_start_stop, currStrand, currCnt, currFirstDigit, postfix);
42453
-
42528
+ let result = this.getAdjustedRefnum(strand2len_start_stop, currStrand_ori, currCnt, currFirstDigit, postfix, prevRefnum);
42529
+
42530
+ refnum = result.refnum;
42531
+ bShowRefnum = result.bShowRefnum;
42454
42532
  refnumStr = result.refnumStr;
42455
42533
  refnumLabel = result.refnumLabel;
42456
42534
  refnumLabelNoPostfix = result.refnumLabelNoPostfix;
42457
42535
 
42458
- bNotShow = result.bNotShow;
42536
+ bHidelabel = result.bHidelabel;
42459
42537
  currStrand = refnumLabel.replace(new RegExp(refnumStr,'g'), '');
42460
42538
 
42461
42539
  ++currCnt;
42462
42540
  }
42541
+
42542
+ prevRefnum = refnum;
42463
42543
  }
42464
42544
 
42465
42545
  if(bCustom) {
@@ -42497,40 +42577,59 @@ class ShowSeq {
42497
42577
  }
42498
42578
  }
42499
42579
  else {
42500
- html += this.getRefnumHtml(residueid, refnumStr, refnumStr_ori, refnumLabel, currStrand, bLoop, bNotShow);
42580
+ if(bShowRefnum && currStrand != ' ') {
42581
+ html += this.getRefnumHtml(residueid, refnumStr, refnumStr_ori, refnumLabel, currStrand, bLoop, bHidelabel);
42582
+ }
42583
+ else {
42584
+ html += '<span></span>';
42585
+ }
42501
42586
  }
42502
42587
  }
42503
42588
  else {
42504
42589
  let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[residueid]);
42505
42590
 
42506
42591
  // skip non-protein residues
42507
- if(ic.proteins.hasOwnProperty(atom.serial) && prevStrand && !bCustom && !kabat_or_imgt) {
42592
+ // after G strand and before A strand, just use the mapped reference number
42593
+ if((!atom || ic.proteins.hasOwnProperty(atom.serial)) && prevStrand && !bCustom && !kabat_or_imgt
42594
+ && currStrand_ori.substr(0,1) != 'G') {
42508
42595
  // no ref num
42509
42596
  bLoop = true;
42510
42597
 
42511
42598
  if(currCnt == 1) { // start of a loop
42512
- if(appearedStrands.hasOwnProperty(currStrand + postfix)) { // the strand appeared in 2nd Id domain
42599
+ if(appearedStrands.hasOwnProperty(currStrand_ori + postfix)) { // the strand appeared in 2nd Id domain
42513
42600
  ++index;
42514
42601
  }
42515
42602
 
42516
42603
  postfix = refnumStr.replace(refnum.toString(), '') + '_' + index;
42517
42604
 
42518
- appearedStrands[currStrand + postfix] = 1;
42605
+ appearedStrands[currStrand_ori + postfix] = 1;
42606
+
42607
+ bStart = true;
42608
+ prevStrandPostfix = currStrand_ori + postfix;
42519
42609
  }
42520
42610
 
42521
42611
  // use previous postfix
42522
- let result = this.getAdjustedRefnum(strand2len_start_stop, currStrand, currCnt, currFirstDigit, postfix);
42523
-
42612
+ let result = this.getAdjustedRefnum(strand2len_start_stop, currStrand_ori, currCnt, currFirstDigit, postfix, prevRefnum);
42613
+
42614
+ refnum = result.refnum;
42615
+ bShowRefnum = result.bShowRefnum;
42524
42616
  refnumStr = result.refnumStr;
42525
42617
  refnumLabel = result.refnumLabel;
42526
42618
  refnumLabelNoPostfix = result.refnumLabelNoPostfix;
42527
42619
 
42528
- bNotShow = result.bNotShow;
42620
+ prevRefnum = refnum;
42621
+
42622
+ bHidelabel = result.bHidelabel;
42529
42623
  currStrand = refnumLabel.replace(new RegExp(refnumStr,'g'), '');
42530
42624
 
42531
42625
  ++currCnt;
42532
42626
 
42533
- html += this.getRefnumHtml(residueid, refnumStr, refnumStr_ori, refnumLabel, currStrand, bLoop, bNotShow);
42627
+ if(bShowRefnum && currStrand != ' ') {
42628
+ html += this.getRefnumHtml(residueid, refnumStr, refnumStr_ori, refnumLabel, currStrand, bLoop, bHidelabel);
42629
+ }
42630
+ else {
42631
+ html += '<span></span>';
42632
+ }
42534
42633
  }
42535
42634
  else {
42536
42635
  html += '<span></span>';
@@ -42554,7 +42653,7 @@ class ShowSeq {
42554
42653
  // remove the postfix when comparing interactions
42555
42654
  //ic.chainsMapping[chnid][residueid] = refnumLabel;
42556
42655
  ic.chainsMapping[chnid][residueid] = refnumLabelNoPostfix;
42557
- }
42656
+ //}
42558
42657
 
42559
42658
  prevStrand = currStrand_ori; //currStrand;
42560
42659
  }
@@ -42569,10 +42668,11 @@ class ShowSeq {
42569
42668
  return {html: html, html3: html3}
42570
42669
  }
42571
42670
 
42572
- getAdjustedRefnum(strand2len_start_stop, currStrand, currCnt, currFirstDigit, postfix) { let ic = this.icn3d; ic.icn3dui;
42573
- let refnumStr, refnumLabel, refnumLabelNoPostfix;
42671
+ getAdjustedRefnum(strand2len_start_stop, currStrand, currCnt, currFirstDigit, postfix, prevRefnum) { let ic = this.icn3d; ic.icn3dui;
42672
+ let refnum, refnumStr, refnumLabel, refnumLabelNoPostfix;
42574
42673
 
42575
- let bNotShow = false; // do not show the label
42674
+ let bHidelabel = false; // do not show the label
42675
+ let bShowRefnum = true;
42576
42676
 
42577
42677
  if(strand2len_start_stop[currStrand + postfix]) {
42578
42678
  let start = parseInt(strand2len_start_stop[currStrand + postfix].start);
@@ -42584,7 +42684,6 @@ class ShowSeq {
42584
42684
  let len = strand2len_start_stop[currStrand + postfix].len;
42585
42685
  let halfLen = (strand2len_start_stop[currStrand + postfix].nextStrand) ? parseInt(len / 2.0 + 0.5) : len;
42586
42686
 
42587
- let refnum;
42588
42687
  if(currCnt <= halfLen) {
42589
42688
  refnum = start + currCnt;
42590
42689
  refnumStr = refnum + postfixStart;
@@ -42599,25 +42698,36 @@ class ShowSeq {
42599
42698
 
42600
42699
  refnumLabelNoPostfix = currStrand + refnum;
42601
42700
 
42602
- if(currCnt == 0 || currCnt == halfLen || currCnt == halfLen + 1 || currCnt == end - 1) {
42603
- bNotShow = true;
42701
+ //if(currCnt == 0 || currCnt == halfLen || currCnt == halfLen + 1 || currCnt == end - 1) {
42702
+ if(currCnt == 1 || currCnt == halfLen || currCnt == halfLen + 1 || currCnt == end - 1) {
42703
+ bHidelabel = true;
42704
+ }
42705
+
42706
+ if(currCnt == 1 && start != prevRefnum) { // skip insertions
42707
+ bShowRefnum = false;
42708
+
42709
+ refnum = 0;
42710
+ refnumStr = '';
42711
+ refnumLabel = '';
42712
+ refnumLabelNoPostfix = '';
42604
42713
  }
42605
42714
  }
42606
42715
  else {
42607
42716
  // refnumStr = (parseInt(currFirstDigit) * 1000 + 900 + currCnt).toString();
42608
42717
  // refnumLabel = currStrand + refnumStr;
42609
42718
 
42719
+ refnum = 0;
42610
42720
  refnumStr = '';
42611
42721
  refnumLabel = '';
42612
42722
  refnumLabelNoPostfix = '';
42613
42723
 
42614
- bNotShow = true;
42724
+ bHidelabel = true;
42615
42725
  }
42616
42726
 
42617
- return {refnumStr: refnumStr, refnumLabel: refnumLabel, refnumLabelNoPostfix: refnumLabelNoPostfix, bNotShow: bNotShow};
42727
+ return {refnum: refnum, refnumStr: refnumStr, refnumLabel: refnumLabel, refnumLabelNoPostfix: refnumLabelNoPostfix, bHidelabel: bHidelabel, bShowRefnum: bShowRefnum};
42618
42728
  }
42619
42729
 
42620
- getRefnumHtml(residueid, refnumStr, refnumStr_ori, refnumLabel, currStrand, bLoop, bNotShow) { let ic = this.icn3d, me = ic.icn3dui;
42730
+ getRefnumHtml(residueid, refnumStr, refnumStr_ori, refnumLabel, currStrand, bLoop, bHidelabel) { let ic = this.icn3d, me = ic.icn3dui;
42621
42731
  let refnum = parseInt(refnumStr).toString();
42622
42732
  let color = this.getRefnumColor(currStrand);
42623
42733
  let colorStr = 'style="color:' + color + '"';
@@ -42633,7 +42743,7 @@ class ShowSeq {
42633
42743
 
42634
42744
  html += '<span ' + colorStr + ' title="' + refnumLabel + '"><b>' + refnumLabel.substr(0, 1) + '</b>' + refnumLabel.substr(1) + '</span>';
42635
42745
  }
42636
- else if(lastTwo % 2 == 0 && lastTwo != 52 && !bNotShow) { // don't show label for the first, middle, and last loop residues
42746
+ else if(lastTwo % 2 == 0 && lastTwo != 52 && !bHidelabel) { // don't show label for the first, middle, and last loop residues
42637
42747
  // e.g., 2152a
42638
42748
  let lastTwoStr = isNaN(refnumStr) ? lastTwo + refnumStr.substr(refnumStr.length - 1, 1) : lastTwo;
42639
42749
  html += '<span ' + colorStr + ' title="' + refnumLabel + '">' + lastTwoStr + '</span>';
@@ -44048,6 +44158,8 @@ class LineGraph {
44048
44158
  drawGraphPerType(bCommonDiff, structureArray, bScatterplot, nodeArray1, nodeArray2, linkArray, name2node, heightFinal, height, textHeight, len1Split, r, gap, marginY) { let ic = this.icn3d; ic.icn3dui;
44049
44159
  let html = "";
44050
44160
 
44161
+ let bMutation = structureArray.length == 2 && structureArray[1].replace(structureArray[0], '') == '2';
44162
+
44051
44163
  // draw common interaction
44052
44164
  let label, postfix;
44053
44165
  if(bCommonDiff == 0) {
@@ -44064,11 +44176,21 @@ class LineGraph {
44064
44176
  }
44065
44177
 
44066
44178
  for(let i = 0, il = structureArray.length; i < il; ++i) {
44179
+ let labelFinal = label;
44180
+ if(bMutation) {
44181
+ if(i == 0) {
44182
+ labelFinal += "Wild Type ";
44183
+ }
44184
+ else if(i == 1) {
44185
+ labelFinal += "Mutant ";
44186
+ }
44187
+ }
44188
+
44067
44189
  if(bScatterplot) {
44068
- html += this.drawScatterplot_base(nodeArray1[i], nodeArray2[i], linkArray[i], name2node, heightFinal, undefined, label + structureArray[i], textHeight);
44190
+ html += this.drawScatterplot_base(nodeArray1[i], nodeArray2[i], linkArray[i], name2node, heightFinal, undefined, labelFinal + structureArray[i], textHeight);
44069
44191
  height =(len1Split[i] + 1) *(r + gap) + 2 * marginY + textHeight;
44070
44192
  } else {
44071
- html += this.drawLineGraph_base(nodeArray1[i], nodeArray2[i], linkArray[i], name2node, heightFinal, label + structureArray[i], textHeight);
44193
+ html += this.drawLineGraph_base(nodeArray1[i], nodeArray2[i], linkArray[i], name2node, heightFinal, labelFinal + structureArray[i], textHeight);
44072
44194
  }
44073
44195
  heightFinal += height;
44074
44196
 
@@ -54916,6 +55038,16 @@ class LoadPDB {
54916
55038
  this.icn3d = icn3d;
54917
55039
  }
54918
55040
 
55041
+ getStructureId(id, moleculeNum, bMutation) { let ic = this.icn3d; ic.icn3dui;
55042
+ let structure = id;
55043
+
55044
+ if(id == ic.defaultPdbId || bMutation) { // bMutation: side chain prediction
55045
+ structure = (moleculeNum === 1) ? id : id + moleculeNum.toString();
55046
+ }
55047
+
55048
+ return structure;
55049
+ }
55050
+
54919
55051
  // modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
54920
55052
  //This PDB parser feeds the viewer with the content of a PDB file, pdbData.
54921
55053
  loadPDB(src, pdbid, bOpm, bVector, bMutation, bAppend, type, bLastQuery) { let ic = this.icn3d, me = ic.icn3dui;
@@ -54998,12 +55130,7 @@ class LoadPDB {
54998
55130
  }
54999
55131
  }
55000
55132
 
55001
- structure = id;
55002
-
55003
- if(id == ic.defaultPdbId || bMutation) { // bMutation: side chain prediction
55004
- //if(id == ic.defaultPdbId) {
55005
- structure = (moleculeNum === 1) ? id : id + moleculeNum.toString();
55006
- }
55133
+ structure = this.getStructureId(id, moleculeNum, bMutation);
55007
55134
 
55008
55135
  ic.molTitle = '';
55009
55136
 
@@ -55118,12 +55245,7 @@ class LoadPDB {
55118
55245
  ++moleculeNum;
55119
55246
  id = ic.defaultPdbId;
55120
55247
 
55121
- structure = id;
55122
-
55123
- if(id == ic.defaultPdbId || bMutation) { // bMutation: side chain prediction
55124
- //if(id == ic.defaultPdbId) {
55125
- structure = (moleculeNum === 1) ? id : id + moleculeNum.toString();
55126
- }
55248
+ structure = this.getStructureId(id, moleculeNum, bMutation);
55127
55249
 
55128
55250
  //helices = [];
55129
55251
  //sheets = [];
@@ -55142,12 +55264,7 @@ class LoadPDB {
55142
55264
  ic.pmid = line.substr(19).trim();
55143
55265
  }
55144
55266
  } else if (record === 'ATOM ' || record === 'HETATM') {
55145
- structure = id;
55146
-
55147
- if(id == ic.defaultPdbId || bMutation) { // bMutation: side chain prediction
55148
- //if(id == ic.defaultPdbId) {
55149
- structure = (moleculeNum === 1) ? id : id + moleculeNum.toString();
55150
- }
55267
+ structure = this.getStructureId(id, moleculeNum, bMutation);
55151
55268
 
55152
55269
  let alt = line.substr(16, 1);
55153
55270
  //if (alt !== " " && alt !== "A") continue;
@@ -59896,7 +60013,7 @@ class SelectByCommand {
59896
60013
  // $1,2,3: Structure
59897
60014
  // .A,B,C: chain
59898
60015
  // :5-10,K,chemicals: residues, could be 'proteins', 'nucleotides', 'chemicals', 'ions', and 'water'
59899
- // @CA,C: atoms
60016
+ // @CA,C,C*: atoms
59900
60017
  // wild card * can be used to select all
59901
60018
  //var currHighlightAtoms = {}
59902
60019
 
@@ -59946,7 +60063,7 @@ class SelectByCommand {
59946
60063
  testStr = testStr.substr(0, dollarPos);
59947
60064
  }
59948
60065
 
59949
- if(atomStrArray.length == 1 && atomStrArray[0] !== '*') {
60066
+ if(atomStrArray.length > 1 || (atomStrArray.length == 1 && atomStrArray[0] !== '*')) {
59950
60067
  bSelectResidues = false; // selected atoms
59951
60068
  }
59952
60069
 
@@ -60041,7 +60158,7 @@ class SelectByCommand {
60041
60158
  let residArray = [];
60042
60159
 
60043
60160
  if(bRefnum) {
60044
- let residArrayTmp = ic.refnum2residArray[k];
60161
+ let residArrayTmp = (ic.refnum2residArray[k]) ? ic.refnum2residArray[k] : [];
60045
60162
  for(let m = 0, ml = residArrayTmp.length; m < ml; ++m) {
60046
60163
  let residueId = residArrayTmp[m];
60047
60164
  if(residueId.substr(0, residueId.lastIndexOf('_')) == molecule_chain) {
@@ -60069,17 +60186,16 @@ class SelectByCommand {
60069
60186
  for(let m in ic.residues[residueId]) {
60070
60187
  for(let n = 0, nl = atomStrArray.length; n < nl; ++n) {
60071
60188
  let atomStr = atomStrArray[n];
60072
- if(atomStr === '*' || atomStr === ic.atoms[m].name) {
60073
- if(i === 0) {
60074
- //currHighlightAtoms[m] = 1;
60075
- atomHash[m] = 1;
60076
- }
60077
- else {
60078
- //if(!currHighlightAtoms.hasOwnProperty(m)) currHighlightAtoms[m] = undefined;
60079
- //if(!atomHash.hasOwnProperty(m)) atomHash[m] = undefined;
60080
- if(!atomHash.hasOwnProperty(m)) delete atomHash[m];
60081
- }
60082
- }
60189
+ atomHash = this.processAtomStr(atomStr, atomHash, i, m);
60190
+
60191
+ // if(atomStr === '*' || atomStr === ic.atoms[m].name) {
60192
+ // if(i === 0) {
60193
+ // atomHash[m] = 1;
60194
+ // }
60195
+ // else {
60196
+ // if(!atomHash.hasOwnProperty(m)) delete atomHash[m];
60197
+ // }
60198
+ // }
60083
60199
  }
60084
60200
  }
60085
60201
  } // end for(let l = 0,
@@ -60112,17 +60228,16 @@ class SelectByCommand {
60112
60228
  for(let n = 0, nl = atomStrArray.length; n < nl; ++n) {
60113
60229
  let atomStr = atomStrArray[n];
60114
60230
 
60115
- if(atomStr === '*' || atomStr === ic.atoms[m].name) {
60116
- if(i === 0) {
60117
- //currHighlightAtoms[m] = 1;
60118
- atomHash[m] = 1;
60119
- }
60120
- else {
60121
- //if(!currHighlightAtoms.hasOwnProperty(m)) currHighlightAtoms[m] = undefined;
60122
- //if(!atomHash.hasOwnProperty(m)) atomHash[m] = undefined;
60123
- if(!atomHash.hasOwnProperty(m)) delete atomHash[m];
60124
- }
60125
- }
60231
+ atomHash = this.processAtomStr(atomStr, atomHash, i, m);
60232
+
60233
+ // if(atomStr === '*' || atomStr === ic.atoms[m].name) {
60234
+ // if(i === 0) {
60235
+ // atomHash[m] = 1;
60236
+ // }
60237
+ // else {
60238
+ // if(!atomHash.hasOwnProperty(m)) delete atomHash[m];
60239
+ // }
60240
+ // }
60126
60241
  }
60127
60242
 
60128
60243
  }
@@ -60177,18 +60292,9 @@ class SelectByCommand {
60177
60292
 
60178
60293
  for(let m in ic.residues[residueId]) {
60179
60294
  for(let n = 0, nl = atomStrArray.length; n < nl; ++n) {
60180
- let atomStr = atomStrArray[n];
60181
- if(atomStr === '*' || atomStr === ic.atoms[m].name) {
60182
- if(i === 0) {
60183
- //currHighlightAtoms[m] = 1;
60184
- atomHash[m] = 1;
60185
- }
60186
- else {
60187
- //if(!currHighlightAtoms.hasOwnProperty(m)) currHighlightAtoms[m] = undefined;
60188
- //if(!atomHash.hasOwnProperty(m)) atomHash[m] = undefined;
60189
- if(!atomHash.hasOwnProperty(m)) delete atomHash[m];
60190
- }
60191
- }
60295
+ let atomStr = atomStrArray[n];
60296
+
60297
+ atomHash = this.processAtomStr(atomStr, atomHash, i, m);
60192
60298
  }
60193
60299
  }
60194
60300
  } // for
@@ -60224,6 +60330,34 @@ class SelectByCommand {
60224
60330
  if(!bNoUpdateAll) ic.definedSetsCls.changeCustomAtoms(nameArray);
60225
60331
  }
60226
60332
  }
60333
+
60334
+ processAtomStr(atomStr, atomHash, i, m) { let ic = this.icn3d; ic.icn3dui;
60335
+ let atomStrLen = atomStr.length;
60336
+ let lastChar = atomStr.substr(atomStrLen - 1, 1);
60337
+
60338
+ if(lastChar == '*' && atomStrLen > 1) { // wildcard to replace anything with *
60339
+ if(atomStr.substr(0, atomStrLen - 1) === ic.atoms[m].name.substr(0, atomStrLen - 1)) {
60340
+ if(i === 0) {
60341
+ atomHash[m] = 1;
60342
+ }
60343
+ else {
60344
+ if(!atomHash.hasOwnProperty(m)) delete atomHash[m];
60345
+ }
60346
+ }
60347
+ }
60348
+ else {
60349
+ if(atomStr === '*' || atomStr === ic.atoms[m].name) {
60350
+ if(i === 0) {
60351
+ atomHash[m] = 1;
60352
+ }
60353
+ else {
60354
+ if(!atomHash.hasOwnProperty(m)) delete atomHash[m];
60355
+ }
60356
+ }
60357
+ }
60358
+
60359
+ return atomHash;
60360
+ }
60227
60361
  }
60228
60362
 
60229
60363
  /**
@@ -62464,12 +62598,12 @@ if(!me.bNode) {
62464
62598
  }
62465
62599
 
62466
62600
  let prevStrand;
62601
+ let bCd19 = ic.chainid2index[chainid].length == 1 && ic.refpdbArray[ic.chainid2index[chainid][0]] == '6al5_cd19';
62467
62602
  for(let i = 0, il = segArray.length; i < il; ++i) {
62468
62603
  let seg = segArray[i];
62469
62604
  let qStart = seg.q_start;
62470
62605
  parseInt(seg.q_start);
62471
- let postfix = '';
62472
- if(isNaN(seg.q_start)) postfix = seg.q_start.substr(seg.q_start.length - 1, 1);
62606
+ if(isNaN(seg.q_start)) seg.q_start.substr(seg.q_start.length - 1, 1);
62473
62607
 
62474
62608
  // one item in "seq"
62475
62609
  // q_start and q_end are numbers, but saved in string
@@ -62480,9 +62614,10 @@ if(!me.bNode) {
62480
62614
 
62481
62615
  let resid = chainid + '_' + seg.t_start;
62482
62616
  //let refnum = qStartInt.toString() + postfix;
62483
- let refnum = qStart + postfix;
62617
+ //let refnum = qStart + postfix;
62618
+ let refnum = qStart;
62484
62619
 
62485
- let refnumLabel = thisClass.getLabelFromRefnum(refnum, prevStrand);
62620
+ let refnumLabel = thisClass.getLabelFromRefnum(refnum, prevStrand, bCd19);
62486
62621
  prevStrand = refnumLabel.replace(new RegExp(refnum,'g'), '');
62487
62622
 
62488
62623
  ic.resid2refnum[resid] = refnumLabel;
@@ -62517,7 +62652,7 @@ if(!me.bNode) {
62517
62652
  }
62518
62653
  }
62519
62654
 
62520
- getLabelFromRefnum(oriRefnum, prevStrand) { let ic = this.icn3d; ic.icn3dui;
62655
+ getLabelFromRefnum(oriRefnum, prevStrand, bCd19) { let ic = this.icn3d; ic.icn3dui;
62521
62656
  let refnum = parseInt(oriRefnum);
62522
62657
 
62523
62658
  // A^: 1xx or 2xx
@@ -62535,7 +62670,10 @@ if(!me.bNode) {
62535
62670
  // G*: 94xx
62536
62671
 
62537
62672
  if(refnum < 100) return " " + oriRefnum;
62538
- else if(refnum >= 100 && refnum < 1000) return "A^" + oriRefnum;
62673
+ else if(refnum >= 100 && refnum < 1000) {
62674
+ if(bCd19) return " " + oriRefnum;
62675
+ else return "A^" + oriRefnum;
62676
+ }
62539
62677
  else if(refnum >= 1000 && refnum < 1200) return "A" + oriRefnum;
62540
62678
  else if(refnum >= 1200 && refnum < 1300) return "A'" + oriRefnum;
62541
62679
  else if(refnum >= 1300 && refnum < 1400) return "A*" + oriRefnum;
@@ -62717,7 +62855,7 @@ class Scap {
62717
62855
 
62718
62856
  let data;
62719
62857
 
62720
- try {
62858
+ // try {
62721
62859
  data = await me.getAjaxPostPromise(url, dataObj, true, undefined, undefined, undefined, 'text');
62722
62860
 
62723
62861
  let pos = data.indexOf('\n');
@@ -62807,8 +62945,10 @@ console.log("free energy: " + energy + " kcal/mol");
62807
62945
 
62808
62946
  let atomWT = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]);
62809
62947
 
62810
- ic.atoms[serial].color = atomWT.color;
62811
- ic.atomPrevColors[serial] = atomWT.color;
62948
+ if(atomWT) {
62949
+ ic.atoms[serial].color = atomWT.color;
62950
+ ic.atomPrevColors[serial] = atomWT.color;
62951
+ }
62812
62952
  }
62813
62953
 
62814
62954
  let chainid = atom.structure + '_' + atom.chain;
@@ -62874,6 +63014,7 @@ console.log("free energy: " + energy + " kcal/mol");
62874
63014
  // expand the toolbar
62875
63015
  let id = ic.pre + 'selection';
62876
63016
  $("#" + id).show();
63017
+ /*
62877
63018
  }
62878
63019
  catch(err) {
62879
63020
  alert("There are some problems in predicting the side chain of the mutant...");
@@ -62883,6 +63024,7 @@ console.log("free energy: " + energy + " kcal/mol");
62883
63024
  /// if(ic.deferredScap !== undefined) ic.deferredScap.resolve();
62884
63025
  return;
62885
63026
  }
63027
+ */
62886
63028
  }
62887
63029
 
62888
63030
  async exportPdbProfix(bHydrogen, pdb, snpStr) { let ic = this.icn3d, me = ic.icn3dui;
@@ -67222,7 +67364,11 @@ class SaveFile {
67222
67364
  $("#" + ic.pre + "title").html(title);
67223
67365
  }
67224
67366
  else if(me.cfg.blast_rep_id) {
67225
- text = 'Query: ' + me.cfg.query_id + '; target: ' + me.cfg.blast_rep_id;
67367
+ let query_id = (me.cfg.oriQuery_id) ? me.cfg.oriQuery_id : me.cfg.query_id;
67368
+ let blast_rep_id = (me.cfg.oriBlast_rep_id) ? me.cfg.oriBlast_rep_id : me.cfg.blast_rep_id;
67369
+ if(query_id.length > 20) query_id = query_id.substr(0, 17) + '...';
67370
+
67371
+ text = 'Query: ' + query_id + '; target: ' + blast_rep_id;
67226
67372
  $("#" + ic.pre + "title").html(text + ", " + title);
67227
67373
  }
67228
67374
  else {
@@ -69873,7 +70019,7 @@ class iCn3D {
69873
70019
  // }
69874
70020
  // else { // WebGL2 supports EXT_frag_depth and ANGLE_instanced_arrays
69875
70021
  this.bExtFragDepth = true;
69876
- this.bImpo = false; //true;
70022
+ this.bImpo = true;
69877
70023
 
69878
70024
  //console.log('WebGL2 is supported. Thus EXT_frag_depth and ANGLE_instanced_arrays are supported. All spheres and cylinders are drawn using shaders. Assembly is drawn with one copy of the asymmetric unit using hardware instancing.');
69879
70025
  // }
@@ -70448,7 +70594,7 @@ class iCn3DUI {
70448
70594
  //even when multiple iCn3D viewers are shown together.
70449
70595
  this.pre = this.cfg.divid + "_";
70450
70596
 
70451
- this.REVISION = '3.23.0';
70597
+ this.REVISION = '3.23.1';
70452
70598
 
70453
70599
  // In nodejs, iCn3D defines "window = {navigator: {}}"
70454
70600
  this.bNode = (Object.keys(window).length < 2) ? true : false;
@@ -70742,6 +70888,9 @@ iCn3DUI.prototype.show3DStructure = async function(pdbStr) { let me = this;
70742
70888
  else if(me.cfg.blast_rep_id !== undefined) {
70743
70889
  // ic.bNCBI = true;
70744
70890
  ic.inputid = me.cfg.query_id + ',' + me.cfg.blast_rep_id;
70891
+
70892
+ me.cfg.oriQuery_id = me.cfg.query_id;
70893
+ me.cfg.oriBlast_rep_id = me.cfg.blast_rep_id;
70745
70894
 
70746
70895
  // custom seqeunce has query_id such as "Query_78989" in BLAST
70747
70896
  if(me.cfg.query_id.substr(0,5) !== 'Query' && me.cfg.rid === undefined) {