icn3d 3.29.13 → 3.29.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/icn3d.js CHANGED
@@ -7408,6 +7408,26 @@ class ClickMenu {
7408
7408
  await ic.annotationCls.setAnnoTabIg(bSelection, template);
7409
7409
  });
7410
7410
 
7411
+ me.myEventCls.onIds("#" + me.pre + "mn6_alignrefTpl", "click", async function(e) { me.icn3d; //e.preventDefault();
7412
+ me.htmlCls.dialogCls.openDlg('dl_alignrefTpl', 'Align with an Ig template');
7413
+ });
7414
+
7415
+ me.myEventCls.onIds("#" + me.pre + "mn6_alignrefTpl_apply", "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
7416
+ if(!me.cfg.notebook) dialog.dialog( "close" );
7417
+
7418
+ let template = $("#" + me.pre + "refTpl2").val();
7419
+
7420
+ // load the template
7421
+ let url = me.htmlCls.baseUrl + "icn3d/refpdb/" + template + ".pdb";
7422
+ await ic.pdbParserCls.downloadUrl(url, 'pdb', undefined, template);
7423
+ thisClass.setLogCmd('load url ' + url + ' | type pdb', true);
7424
+
7425
+ // align the template with the selection
7426
+ me.cfg.aligntool = 'tmalign';
7427
+ await ic.realignParserCls.realignOnStructAlign();
7428
+ thisClass.setLogCmd('realign on tmalign', true);
7429
+ });
7430
+
7411
7431
  me.myEventCls.onIds("#" + me.pre + "mn6_igrefNo", "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
7412
7432
  thisClass.setLogCmd('ig refnum off', true);
7413
7433
  await ic.refnumCls.hideIgRefNum();
@@ -9759,11 +9779,14 @@ class SetMenu {
9759
9779
  /*
9760
9780
  html += this.getLink('mn6_igrefYes', 'Show Ig for Selection', undefined, 2);
9761
9781
  html += this.getLink('mn6_igrefTpl', 'Ig w/ Specified Template', undefined, 2);
9782
+ html += this.getLink('mn6_alignrefTpl', 'Align w/ Specified Template', undefined, 2);
9762
9783
  html += this.getLink('mn6_igrefNo', 'Reset Ig Ref. Number', undefined, 2);
9763
9784
 
9764
9785
  html += this.getMenuSep();
9765
9786
  */
9766
9787
 
9788
+
9789
+
9767
9790
  html += this.getLink('mn6_customref', 'Custom Ref. Number', undefined, 2);
9768
9791
  html += "</ul>";
9769
9792
  html += "</li>";
@@ -11910,8 +11933,24 @@ class SetDialog {
11910
11933
  html += me.htmlCls.divStr + "dl_igrefTpl' class='" + dialogClass + "'>";
11911
11934
  html += this.addNotebookTitle('dl_igrefTpl', 'Choose an Ig template');
11912
11935
  html += "<span style='white-space:nowrap;font-weight:bold;'>Choose an Ig template for selected residues:</span> <br><br><select id='" + me.pre + "refTpl'>";
11936
+ html += this.setTemplateMenu();
11937
+ html += "</select><br><br><span style='white-space:nowrap;'>" + me.htmlCls.buttonStr + "mn6_igrefTpl_apply'>Show Ig Ref. Number</button></span>";
11938
+ html += "</div>";
11939
+
11940
+ html += me.htmlCls.divStr + "dl_alignrefTpl' class='" + dialogClass + "'>";
11941
+ html += this.addNotebookTitle('dl_alignrefTpl', 'Align with an Ig template');
11942
+ html += "<span style='white-space:nowrap;font-weight:bold;'>Choose an Ig template to align with selected residues:</span> <br><br><select id='" + me.pre + "refTpl2'>";
11943
+ html += this.setTemplateMenu();
11944
+ html += "</select><br><br><span style='white-space:nowrap;'>" + me.htmlCls.buttonStr + "mn6_alignrefTpl_apply'>Align Template with Selection</button></span>";
11945
+ html += "</div>";
11913
11946
 
11914
- //html += me.htmlCls.setHtmlCls.getOptionHtml(['0', '10', '20', '30', '40', '50', '60', '70', '80', '90', '100'], 3);
11947
+ html += "</div>";
11948
+ html += "<!--/form-->";
11949
+
11950
+ return html;
11951
+ }
11952
+
11953
+ setTemplateMenu() { let me = this.icn3dui; me.icn3d;
11915
11954
  let group2tpl = {};
11916
11955
  group2tpl['V'] = ['CD28_1yjdC_human_V', 'CD2_1hnfA_human_V-n1', 'CD8a_1cd8A_human_V', 'FAB-HEAVY_5esv_V-n1', 'FAB-LIGHT_5esv_V-n1', 'ICOS_6x4gA_human_V', 'LAG3_7tzgD_human_V-n1', 'PDL1_4z18B_human_V-n1', 'PD1_4zqkB_human_V', 'TCRa_6jxrm_human_V-n1', 'VISTA_6oilA_human_V', 'VNAR_1t6vN_shark_V'];
11917
11956
  group2tpl['C1'] = ['B2Microglobulin_7phrL_human_C1', 'FAB-LIGHT_5esv_C1-n2', 'FAB-HEAVY_5esv_C1-n2', 'GHR_1axiB_human_FN3-n1', 'MHCIa_7phrH_human_C1', 'TCRa_6jxrm_human_C1-n2', 'VTCN1_Q7Z7D3_human_V-n2'];
@@ -11925,6 +11964,7 @@ class SetDialog {
11925
11964
 
11926
11965
  group2tpl['Other'] = ['CuZnSuperoxideDismutase_1hl5C_human', 'ECadherin_4zt1A_human_n2', 'LaminAC_1ifrA_human', 'ORF7a_1xakA_virus'];
11927
11966
 
11967
+ let html = '';
11928
11968
  for(let group in group2tpl) {
11929
11969
  html += "<optgroup label='" + group + "'>";
11930
11970
  for(let i = 0, il = group2tpl[group].length; i < il; ++i) {
@@ -11934,12 +11974,6 @@ class SetDialog {
11934
11974
  html += "</optgroup>";
11935
11975
  }
11936
11976
 
11937
- html += "</select><br><br><span style='white-space:nowrap;'>" + me.htmlCls.buttonStr + "mn6_igrefTpl_apply'>Show Ig Ref. Number</button></span>";
11938
- html += "</div>";
11939
-
11940
- html += "</div>";
11941
- html += "<!--/form-->";
11942
-
11943
11977
  return html;
11944
11978
  }
11945
11979
 
@@ -11979,6 +12013,7 @@ class SetDialog {
11979
12013
  html += tmpStr1 + me.htmlCls.inputCheckStr + "id='" + me.pre + "anno_ig'>Ig Domains" + me.htmlCls.space2 + "</span></td>";
11980
12014
  */
11981
12015
 
12016
+
11982
12017
  html += "<td></td>";
11983
12018
  html += "</tr></table></div></div>";
11984
12019
 
@@ -36743,7 +36778,7 @@ class AnnoCddSite {
36743
36778
  let fromArray = [], toArray = [];
36744
36779
  let resiHash = {};
36745
36780
  let resCnt = 0;
36746
- let segArray =(type == 'domain') ? domainRepeatArray[r].segs : [domainRepeatArray[r]];
36781
+ let segArray =(type == 'domain' || type == 'ig') ? domainRepeatArray[r].segs : [domainRepeatArray[r]];
36747
36782
  for(let s = 0, sl = segArray.length; s < sl; ++s) {
36748
36783
  let domainFrom = Math.round(segArray[s].from);
36749
36784
  let domainTo = Math.round(segArray[s].to);
@@ -36847,15 +36882,15 @@ class AnnoCddSite {
36847
36882
 
36848
36883
  if(me.cfg.blast_rep_id != chnid) { // regular
36849
36884
  for(let i = 0, il = fromArray.length; i < il; ++i) {
36850
- let color = this.getColorFromPos(chnid, i, titleArray);
36885
+ let color = this.getColorFromPos(chnid, fromArray[i], titleArray);
36851
36886
 
36852
36887
  let emptyWidth;
36853
- if(titleArray) {
36888
+ // if(titleArray) {
36854
36889
  emptyWidth =(i == 0) ? Math.round(ic.seqAnnWidth *(fromArray[i]) / ic.maxAnnoLength) : Math.round(ic.seqAnnWidth *(fromArray[i] - toArray[i-1] - 1) / ic.maxAnnoLength);
36855
- }
36856
- else {
36857
- emptyWidth =(i == 0) ? Math.round(ic.seqAnnWidth *(fromArray[i] - ic.baseResi[chnid] - 1) / ic.maxAnnoLength) : Math.round(ic.seqAnnWidth *(fromArray[i] - toArray[i-1] - 1) / ic.maxAnnoLength);
36858
- }
36890
+ // }
36891
+ // else {
36892
+ // emptyWidth =(i == 0) ? Math.round(ic.seqAnnWidth *(fromArray[i] - ic.baseResi[chnid] - 1) / ic.maxAnnoLength) : Math.round(ic.seqAnnWidth *(fromArray[i] - toArray[i-1] - 1) / ic.maxAnnoLength);
36893
+ // }
36859
36894
 
36860
36895
  html2 += '<div style="display:inline-block; width:' + emptyWidth + 'px;">&nbsp;</div>';
36861
36896
  html2 += '<div style="display:inline-block; color:white!important; font-weight:bold; background-color:#' + color + '; width:' + Math.round(ic.seqAnnWidth *(toArray[i] - fromArray[i] + 1) / ic.maxAnnoLength) + 'px;" class="icn3d-seqTitle ' + linkStr + '" ' + type + '="' +(index+1).toString() + '" from="' + fromArray + '" to="' + toArray + '" shorttitle="' + title + '" index="' + index + '" setname="' + setname + '" id="' + chnid + '_domain_' + index + '_' + r + '" anno="sequence" chain="' + chnid + '" title="' + fulltitle + '">' + domain + ' </div>';
@@ -36874,7 +36909,7 @@ class AnnoCddSite {
36874
36909
  toArray2.push(toArray[i]);
36875
36910
  }
36876
36911
  for(let i = 0, il = fromArray2.length; i < il; ++i) {
36877
- let color = this.getColorFromPos(chnid, i, titleArray);
36912
+ let color = this.getColorFromPos(chnid, fromArray2[i], titleArray);
36878
36913
 
36879
36914
  html2 += ic.showSeqCls.insertGapOverview(chnid, fromArray2[i]);
36880
36915
  let emptyWidth =(i == 0) ? Math.round(ic.seqAnnWidth *(fromArray2[i] - ic.baseResi[chnid] - 1) /(ic.maxAnnoLength + ic.nTotalGap)) : Math.round(ic.seqAnnWidth *(fromArray2[i] - toArray2[i-1] - 1) /(ic.maxAnnoLength + ic.nTotalGap));
@@ -37584,7 +37619,7 @@ class AnnoIg {
37584
37619
  if(ic.bShowRefnum && ic.chainid2refpdbname.hasOwnProperty(chnid) && ic.chainid2refpdbname[chnid].length > 0) {
37585
37620
  let giSeq = ic.showSeqCls.getSeq(chnid);
37586
37621
  let result = ic.annoIgCls.showAllRefNum(giSeq, chnid);
37587
-
37622
+
37588
37623
  html += result.html;
37589
37624
  html2 += result.html2;
37590
37625
  html3 += result.html3;
@@ -37598,38 +37633,12 @@ class AnnoIg {
37598
37633
  showAllRefNum(giSeq, chnid) { let ic = this.icn3d; ic.icn3dui;
37599
37634
  let html = '', html2 = '', html3 = '';
37600
37635
 
37601
- let result = this.showRefNum(giSeq, chnid);
37602
- html += result.html;
37603
- html2 += result.html2;
37604
- html3 += result.html3;
37605
-
37606
- let kabat_or_imgt = 1;
37607
- result = this.showRefNum(giSeq, chnid, kabat_or_imgt);
37608
- html += result.html;
37609
- html2 += result.html2;
37610
- html3 += result.html3;
37611
-
37612
- kabat_or_imgt = 2;
37613
- result = this.showRefNum(giSeq, chnid, kabat_or_imgt);
37614
- html += result.html;
37615
- html2 += result.html2;
37616
- html3 += result.html3;
37617
-
37618
- return {'html': html, 'html2': html2, 'html3': html3};
37619
- }
37620
-
37621
- showRefNum(giSeq, chnid, kabat_or_imgt, bCustom) { let ic = this.icn3d, me = ic.icn3dui;
37622
- let html = '', html2 = '', html3 = '';
37623
-
37624
- if(!ic.chainid2refpdbname[chnid]) return {html: html, html2: html2, html3: html3};
37625
-
37626
37636
  //check if Kabat refnum available
37627
37637
  let bKabatFound = false;
37628
-
37629
37638
  for(let i = 0, il = giSeq.length; i < il; ++i) {
37630
37639
  let currResi = ic.ParserUtilsCls.getResi(chnid, i);
37631
37640
  let residueid = chnid + '_' + currResi;
37632
- let domainid = (bCustom) ? 0 : ic.resid2domainid[residueid];
37641
+ let domainid = ic.resid2domainid[residueid];
37633
37642
 
37634
37643
  if(ic.domainid2ig2kabat[domainid] && Object.keys(ic.domainid2ig2kabat[domainid]).length > 0) {
37635
37644
  bKabatFound = true;
@@ -37637,479 +37646,52 @@ class AnnoIg {
37637
37646
  }
37638
37647
  }
37639
37648
 
37640
- if(kabat_or_imgt == 1 && !bKabatFound) {
37641
- return {html: '', html2: '', html3: ''};
37642
- }
37643
-
37644
37649
  //check if IMGT refnum available
37645
37650
  let bImgtFound = false;
37646
37651
  for(let i = 0, il = giSeq.length; i < il; ++i) {
37647
37652
  let currResi = ic.ParserUtilsCls.getResi(chnid, i);
37648
37653
  let residueid = chnid + '_' + currResi;
37649
- let domainid = (bCustom) ? 0 : ic.resid2domainid[residueid];
37654
+ let domainid = ic.resid2domainid[residueid];
37650
37655
 
37651
37656
  if(ic.domainid2ig2imgt[domainid] && Object.keys(ic.domainid2ig2imgt[domainid]).length > 0) {
37652
37657
  bImgtFound = true;
37653
37658
  break;
37654
37659
  }
37655
37660
  }
37656
- if(kabat_or_imgt == 2 && !bImgtFound) {
37657
- return {html: '', html2: '', html3: ''};
37658
- }
37659
37661
 
37660
- // auto-generate ref numbers for loops
37661
- let currStrand = '', prevStrand = '';
37662
- let refnumLabel, refnumStr_ori, refnumStr, postfix, strandPostfix, refnum, refnum3c, refnum2c;
37663
- let bExtendedStrand = false, bSecThird9 = false;
37664
-
37665
- // sometimes one chain may have several Ig domains,set an index for each IgDomain
37666
- let index = 1, bStart = false;
37662
+ let result = this.showRefNum(giSeq, chnid);
37663
+ html += result.html;
37664
+ html2 += result.html2;
37665
+ html3 += result.html3;
37667
37666
 
37668
- if(!bCustom && !kabat_or_imgt && !me.bNode) { // do not overwrite loops in node
37669
- // reset ic.residIgLoop for the current selection, which could be the second round of ref num assignment
37670
- // just current chain
37671
- let atomHash = me.hashUtilsCls.intHash(ic.chains[chnid], ic.hAtoms);
37672
- ic.firstAtomObjCls.getResiduesFromAtoms(atomHash);
37673
-
37674
- // for(let resid in residHash) {
37675
- // // not in loop any more if you assign ref numbers multiple times
37676
- // delete ic.residIgLoop[resid];
37677
- // }
37667
+ let kabat_or_imgt = 1;
37668
+ if(!bKabatFound) {
37669
+ return {html: html, html2: html2, html3: html3};
37670
+ }
37671
+ else {
37672
+ result = this.showRefNum(giSeq, chnid, kabat_or_imgt);
37673
+ html += result.html;
37674
+ html2 += result.html2;
37675
+ html3 += result.html3;
37678
37676
  }
37679
37677
 
37680
- // 1. get the range of each strand excluding loops
37681
- let strandArray = [], strandHash = {}, strandCnt = 0, resCnt = 0, resCntBfAnchor = 0, resCntAtAnchor = 0;
37682
- let bFoundAnchor = false;
37683
- if(!bCustom && !kabat_or_imgt) {
37684
- for(let i = 0, il = giSeq.length; i < il; ++i, ++resCnt, ++resCntBfAnchor, ++resCntAtAnchor) {
37685
- let currResi = ic.ParserUtilsCls.getResi(chnid, i);
37686
- let residueid = chnid + '_' + currResi;
37687
-
37688
- refnumLabel = ic.resid2refnum[residueid];
37689
-
37690
- let firstChar = (refnumLabel) ? refnumLabel.substr(0,1) : '';
37691
- if(!bStart && refnumLabel && (firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
37692
- bStart = true;
37693
- resCnt = 1; // the first one is included
37694
- bFoundAnchor = false;
37695
- }
37696
-
37697
- if((prevStrand.substr(0,1) == 'F' || prevStrand.substr(0,1) == 'G') && !refnumLabel) { // indicate the end of an IG domain
37698
- bStart = false;
37699
- }
37700
-
37701
- if(refnumLabel) {
37702
- refnumStr_ori = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
37703
- currStrand = refnumLabel.replace(new RegExp(refnumStr_ori,'g'), '');
37704
- refnumStr_ori.substr(0, 1);
37705
-
37706
- refnumStr = refnumStr_ori;
37707
- refnum = parseInt(refnumStr);
37708
- refnum3c = (refnum - parseInt(refnum/1000) * 1000).toString();
37709
- refnum2c = (refnum - parseInt(refnum/100) * 100).toString();
37710
-
37711
- // for extended strands, since A is 1550 and A+ is 1650, then the AA+ loop will be 1591, 1592, ... 1610, 1611, etc
37712
- bSecThird9 = refnum3c.substr(0,1) == '9' || refnum2c.substr(0,1) == '9' || refnum2c.substr(0,1) == '0' || refnum2c.substr(0,1) == '1';
37713
- if(bSecThird9) ic.residIgLoop[residueid] = 1;
37714
-
37715
- strandPostfix = refnumStr.replace(refnum.toString(), '');
37716
-
37717
- postfix = strandPostfix + '_' + index;
37718
-
37719
- let firstTwo = parseInt(refnum.toString().substr(0, 2)); // check extended strands
37720
- bExtendedStrand = refnum3c.substr(0,1) != '5' && firstTwo != '18'; // all strands and A' (18##)
37721
-
37722
- if(currStrand && currStrand != ' ') {
37723
- if(!bSecThird9 || (bExtendedStrand && !bSecThird9)) {
37724
- let lastTwo = parseInt(refnum.toString().substr(refnum.toString().length - 2, 2));
37725
-
37726
- if(currStrand != prevStrand) { // reset currCnt
37727
- bFoundAnchor = false;
37728
-
37729
- if(strandHash[currStrand + postfix]) {
37730
- ++index;
37731
- postfix = refnumStr.replace(refnum.toString(), '') + '_' + index;
37732
- }
37733
-
37734
- strandHash[currStrand + postfix] = 1;
37735
-
37736
- strandArray[strandCnt] = {};
37737
- strandArray[strandCnt].startResi = currResi;
37738
- strandArray[strandCnt].startRefnum = refnum; // 1250 in A1250a
37739
-
37740
- resCntBfAnchor = 0;
37741
-
37742
- strandArray[strandCnt].endResi = currResi;
37743
- strandArray[strandCnt].endRefnum = refnum; // 1250a
37744
-
37745
- if(lastTwo == 50) {
37746
- strandArray[strandCnt].anchorRefnum = refnum;
37747
- strandArray[strandCnt].resCntBfAnchor = resCntBfAnchor;
37748
-
37749
- resCntAtAnchor = 0;
37750
-
37751
- bFoundAnchor = true;
37752
- }
37753
-
37754
- // in case A1550 is not found, but A1551 is found
37755
- if(!bFoundAnchor && (lastTwo == 51 || lastTwo == 52 || lastTwo == 53) ) {
37756
- let offset = lastTwo - 50;
37757
- strandArray[strandCnt].anchorRefnum = refnum - offset;
37758
- strandArray[strandCnt].resCntBfAnchor = resCntBfAnchor - offset;
37759
-
37760
- resCntAtAnchor = offset;
37761
-
37762
- bFoundAnchor = true;
37763
- }
37764
-
37765
- if(bExtendedStrand) {
37766
- strandArray[strandCnt].anchorRefnum = 0;
37767
- }
37768
-
37769
- strandArray[strandCnt].strandPostfix = strandPostfix; // a in A1250a
37770
- strandArray[strandCnt].strand = currStrand; // A in A1250a
37771
-
37772
- strandArray[strandCnt].postfix = postfix; // Aa_1
37773
-
37774
- strandArray[strandCnt].loopResCnt = resCnt - 1;
37775
-
37776
- ++strandCnt;
37777
- resCnt = 0;
37778
- }
37779
- else {
37780
- if(strandHash[currStrand + postfix]) {
37781
- if(lastTwo == 50) {
37782
- strandArray[strandCnt - 1].anchorRefnum = refnum;
37783
- strandArray[strandCnt - 1].resCntBfAnchor = resCntBfAnchor;
37784
-
37785
- // update
37786
- strandArray[strandCnt - 1].startRefnum = strandArray[strandCnt - 1].anchorRefnum - strandArray[strandCnt - 1].resCntBfAnchor;
37787
-
37788
- resCntAtAnchor = 0;
37789
-
37790
- bFoundAnchor = true;
37791
- }
37792
-
37793
- // in case A1550 is not found, but A1551 is found
37794
- if(!bFoundAnchor && (lastTwo == 51 || lastTwo == 52 || lastTwo == 53) ) {
37795
- let offset = lastTwo - 50;
37796
- strandArray[strandCnt - 1].anchorRefnum = refnum - offset;
37797
- strandArray[strandCnt - 1].resCntBfAnchor = resCntBfAnchor - offset;
37798
-
37799
- // update
37800
- strandArray[strandCnt - 1].startRefnum = strandArray[strandCnt - 1].anchorRefnum - strandArray[strandCnt - 1].resCntBfAnchor;
37801
-
37802
- resCntAtAnchor = offset;
37803
-
37804
- bFoundAnchor = true;
37805
- }
37806
-
37807
- if(bExtendedStrand) {
37808
- strandArray[strandCnt - 1].anchorRefnum = 0;
37809
- }
37810
-
37811
- strandArray[strandCnt - 1].endResi = currResi;
37812
- strandArray[strandCnt - 1].endRefnum = refnum; // 1250a
37813
- strandArray[strandCnt - 1].resCntAtAnchor = resCntAtAnchor;
37814
-
37815
- if(strandArray[strandCnt - 1].anchorRefnum) {
37816
- strandArray[strandCnt - 1].endRefnum = strandArray[strandCnt - 1].anchorRefnum + strandArray[strandCnt - 1].resCntAtAnchor;
37817
- }
37818
-
37819
- resCnt = 0;
37820
- }
37821
- }
37822
- }
37823
- }
37824
- }
37825
-
37826
- prevStrand = currStrand;
37827
- }
37828
-
37829
- // 2. remove strands with less than 3 residues except G strand
37830
- for(let il = strandArray.length, i = il - 1; i >= 0; --i) {
37831
- let strandTmp = strandArray[i].strand.substr(0, 1);
37832
- if(strandTmp != 'G' && strandArray[i].endRefnum - strandArray[i].startRefnum + 1 < 3) { // remove the strand
37833
- if(strandTmp == 'B' || strandTmp == 'C' || strandTmp == 'E' || strandTmp == 'F') {
37834
- if(!me.bNode) console.log("Some of the Ig strands B, C, E, F are missing...");
37835
- return {html: '', html2: '', html3: ''};
37836
- }
37837
-
37838
- if(i != il - 1) { // modify
37839
- strandArray[i + 1].loopResCnt += strandArray[i].loopResCnt + parseInt(strandArray[i].endResi) - parseInt(strandArray[i].startResi) + 1;
37840
- }
37841
-
37842
- strandArray.splice(i, 1);
37843
- }
37844
- }
37845
-
37846
- // 2b. extend the strand to end of sheet
37847
- let maxExtend = 8;
37848
- for(let i = 0, il = strandArray.length; i < il; ++i) {
37849
- let startAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[chnid + '_' + strandArray[i].startResi]);
37850
- let endAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[chnid + '_' + strandArray[i].endResi]);
37851
-
37852
- let startPos = ic.setSeqAlignCls.getPosFromResi(chnid, strandArray[i].startResi);
37853
- let endPos = ic.setSeqAlignCls.getPosFromResi(chnid, strandArray[i].endResi);
37854
-
37855
- if(startAtom.ss == 'sheet' && !startAtom.ssbegin) {
37856
- for(let j = 1; j <= maxExtend; ++j) {
37857
- let currPos = startPos - j;
37858
- let currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
37859
- if(i > 0 && parseInt(currResi) <= parseInt(strandArray[i-1].endResi)) break;
37860
-
37861
- let currResid = chnid + '_' + currResi;
37862
- let currAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[currResid]);
37863
- if(currAtom.ssbegin) { // find the start of the sheet
37864
- // update the following: startResi,startRefnum,endResi,endRefnum,loopResCnt,resCntBfAnchor,resCntAtAnchor
37865
- strandArray[i].startResi = currResi;
37866
- strandArray[i].startRefnum -= j;
37867
- strandArray[i].loopResCnt -= j;
37868
- if(strandArray[i].loopResCnt < 0) strandArray[i].loopResCnt = 0;
37869
- strandArray[i].resCntBfAnchor += j;
37870
-
37871
- // update ic.resid2refnum
37872
- for(let k = 1; k <= j; ++k) {
37873
- currPos = startPos - k;
37874
- currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
37875
- let currResid = chnid + '_' + currResi;
37876
- delete ic.residIgLoop[currResid];
37877
- }
37878
-
37879
- break;
37880
- }
37881
- }
37882
- }
37883
-
37884
- if(endAtom.ss == 'sheet' && !endAtom.ssend) {
37885
- for(let j = 1; j <= maxExtend; ++j) {
37886
- let currPos = endPos + j;
37887
- let currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
37888
- if(i < il - 1 && parseInt(currResi) >= parseInt(strandArray[i+1].startResi)) break;
37889
-
37890
- let currResid = chnid + '_' + currResi;
37891
- let currAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[currResid]);
37892
- if(currAtom.ssend) { // find the end of the sheet
37893
- // update the following: startResi,startRefnum,endResi,endRefnum,loopResCnt,resCntBfAnchor,resCntAtAnchor
37894
- strandArray[i].endResi = currResi;
37895
- strandArray[i].endRefnum += j;
37896
- if(i < il - 1) {
37897
- strandArray[i + 1].loopResCnt -= j;
37898
- if(strandArray[i + 1].loopResCnt < 0) strandArray[i + 1].loopResCnt = 0;
37899
- }
37900
- strandArray[i].resCntAtAnchor += j;
37901
-
37902
- // update ic.residIgLoop[resid];
37903
- for(let k = 1; k <= j; ++k) {
37904
- currPos = endPos + k;
37905
- currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
37906
- let currResid = chnid + '_' + currResi;
37907
- delete ic.residIgLoop[currResid];
37908
- }
37909
-
37910
- break;
37911
- }
37912
- }
37913
- }
37914
- }
37915
-
37916
- // 3. assign refnumLabel for each resid
37917
- strandCnt = 0;
37918
- let loopCnt = 0;
37919
-
37920
- let bBeforeAstrand = true, bAfterGstrand = true, refnumLabelNoPostfix, prevStrandCnt = 0, currRefnum;
37921
- bStart = false;
37922
- let refnumInStrand = 0;
37923
- if(strandArray.length > 0) {
37924
- for(let i = 0, il = giSeq.length; i < il; ++i, ++loopCnt, ++refnumInStrand) {
37925
- let currResi = ic.ParserUtilsCls.getResi(chnid, i);
37926
- let residueid = chnid + '_' + currResi;
37927
- refnumLabel = ic.resid2refnum[residueid];
37928
-
37929
- currStrand = strandArray[strandCnt].strand;
37930
-
37931
- if(refnumLabel) {
37932
- refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
37933
- currRefnum = parseInt(refnumStr);
37934
- refnumLabelNoPostfix = currStrand + currRefnum;
37935
-
37936
- currStrand = refnumLabel.replace(new RegExp(refnumStr,'g'), '');
37937
-
37938
- let firstChar = refnumLabel.substr(0,1);
37939
- if(!bStart && (firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
37940
- bStart = true;
37941
- bBeforeAstrand = true;
37942
- loopCnt = 0;
37943
- }
37944
- }
37945
-
37946
- let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[residueid]);
37947
-
37948
- // skip non-protein residues
37949
- if(!atom || !ic.proteins.hasOwnProperty(atom.serial)) {
37950
- refnumLabel = undefined;
37951
- }
37952
- else {
37953
- let bBefore = false, bInRange= false, bAfter = false;
37954
- // 100, 100A
37955
- if(parseInt(currResi) == parseInt(strandArray[strandCnt].startResi) && currResi != strandArray[strandCnt].startResi) {
37956
- bBefore = currResi < strandArray[strandCnt].startResi;
37957
- }
37958
- else {
37959
- bBefore = parseInt(currResi) < parseInt(strandArray[strandCnt].startResi);
37960
- }
37961
-
37962
- // 100, 100A
37963
- if(parseInt(currResi) == parseInt(strandArray[strandCnt].endResi) && currResi != strandArray[strandCnt].endResi) {
37964
- bAfter = currResi > strandArray[strandCnt].endResi;
37965
- }
37966
- else {
37967
- bAfter = parseInt(currResi) > parseInt(strandArray[strandCnt].endResi);
37968
- }
37969
-
37970
- bInRange = (!bBefore && !bAfter) ? true : false;
37971
-
37972
- if(bBefore) {
37973
- ic.residIgLoop[residueid] = 1;
37974
-
37975
- if(bBeforeAstrand) { // make it continuous to the 1st strand
37976
- if(bStart) {
37977
- currRefnum = strandArray[strandCnt].startRefnum - strandArray[strandCnt].loopResCnt + loopCnt;
37978
- refnumLabelNoPostfix = strandArray[strandCnt].strand + currRefnum;
37979
- refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
37980
- }
37981
- else {
37982
- //loopCnt = 0;
37983
- refnumLabelNoPostfix = undefined;
37984
- refnumLabel = undefined;
37985
- }
37986
- }
37987
- else {
37988
- if(prevStrandCnt >= 0
37989
- && (strandArray[prevStrandCnt].strand.substr(0, 1) == 'F' || strandArray[prevStrandCnt].strand.substr(0, 1) == 'G')) {
37990
- if(!bAfterGstrand) {
37991
- //loopCnt = 0;
37992
- refnumLabelNoPostfix = undefined;
37993
- refnumLabel = undefined;
37994
- }
37995
- else {
37996
- if(bStart && ic.resid2refnum[residueid]) {
37997
- bAfterGstrand = true;
37998
-
37999
- currRefnum = strandArray[prevStrandCnt].endRefnum + loopCnt;
38000
- refnumLabelNoPostfix = strandArray[prevStrandCnt].strand + currRefnum;
38001
- refnumLabel = refnumLabelNoPostfix + strandArray[prevStrandCnt].strandPostfix;
38002
- }
38003
- else {
38004
- bStart = false;
38005
- bBeforeAstrand = true;
38006
- //loopCnt = 0;
38007
-
38008
- bAfterGstrand = false;
38009
-
38010
- refnumLabelNoPostfix = undefined;
38011
- refnumLabel = undefined;
38012
- }
38013
- }
38014
- }
38015
- else {
38016
- bAfterGstrand = true; // reset
38017
-
38018
- let len = strandArray[strandCnt].loopResCnt;
38019
- let halfLen = parseInt(len / 2.0 + 0.5);
38020
-
38021
- if(loopCnt <= halfLen) {
38022
- currRefnum = strandArray[prevStrandCnt].endRefnum + loopCnt;
38023
- refnumLabelNoPostfix = strandArray[prevStrandCnt].strand + currRefnum;
38024
- refnumLabel = refnumLabelNoPostfix + strandArray[prevStrandCnt].strandPostfix;
38025
- }
38026
- else {
38027
- currRefnum = strandArray[strandCnt].startRefnum - len + loopCnt - 1;
38028
- refnumLabelNoPostfix = strandArray[strandCnt].strand + currRefnum;
38029
- refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
38030
- }
38031
- }
38032
- }
38033
- }
38034
- else if(bInRange) {
38035
- // not in loop any more if you assign ref numbers multiple times
38036
- //delete ic.residIgLoop[residueid];
38037
-
38038
- bBeforeAstrand = false;
38039
-
38040
- if(strandArray[strandCnt].anchorRefnum) { // use anchor to name refnum
38041
- if(currResi == strandArray[strandCnt].startResi) {
38042
- refnumInStrand = strandArray[strandCnt].anchorRefnum - strandArray[strandCnt].resCntBfAnchor;
38043
- strandArray[strandCnt].startRefnum = refnumInStrand;
38044
- }
38045
- else if(currResi == strandArray[strandCnt].endResi) {
38046
- strandArray[strandCnt].endRefnum = refnumInStrand;
38047
- }
38048
-
38049
- refnumLabelNoPostfix = strandArray[strandCnt].strand + refnumInStrand;
38050
- refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
38051
- }
38052
-
38053
- if(currResi == strandArray[strandCnt].endResi) {
38054
- ++strandCnt; // next strand
38055
- loopCnt = 0;
38056
-
38057
- if(!strandArray[strandCnt]) { // last strand
38058
- --strandCnt;
38059
- }
38060
- }
38061
- }
38062
- else if(bAfter) {
38063
- ic.residIgLoop[residueid] = 1;
38064
-
38065
- if(!bAfterGstrand) {
38066
- refnumLabelNoPostfix = undefined;
38067
- refnumLabel = undefined;
38068
- }
38069
- else {
38070
- // C-terminal
38071
- if(!ic.resid2refnum[residueid]) {
38072
- bAfterGstrand = false;
38073
-
38074
- refnumLabelNoPostfix = undefined;
38075
- refnumLabel = undefined;
38076
- }
38077
- else {
38078
- bAfterGstrand = true;
38079
-
38080
- currRefnum = strandArray[strandCnt].endRefnum + loopCnt;
38081
- refnumLabelNoPostfix = strandArray[strandCnt].strand + currRefnum;
38082
- refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
38083
- }
38084
- }
38085
- }
38086
- }
38087
-
38088
- prevStrand = currStrand;
38089
- prevStrandCnt = strandCnt - 1;
38090
-
38091
- // assign the adjusted reference numbers
38092
- ic.resid2refnum[residueid] = refnumLabel;
38093
-
38094
- refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
38095
-
38096
- if(!ic.refnum2residArray.hasOwnProperty(refnumStr)) {
38097
- ic.refnum2residArray[refnumStr] = [residueid];
38098
- }
38099
- else {
38100
- ic.refnum2residArray[refnumStr].push(residueid);
38101
- }
37678
+ kabat_or_imgt = 2;
37679
+ if(!bImgtFound) {
37680
+ return {html: html, html2: html2, html3: html3};
37681
+ }
37682
+ else {
37683
+ result = this.showRefNum(giSeq, chnid, kabat_or_imgt);
37684
+ html += result.html;
37685
+ html2 += result.html2;
37686
+ html3 += result.html3;
37687
+ }
38102
37688
 
38103
- if(!ic.chainsMapping.hasOwnProperty(chnid)) {
38104
- ic.chainsMapping[chnid] = {};
38105
- }
37689
+ return {html: html, html2: html2, html3: html3};
37690
+ }
38106
37691
 
38107
- // remove the postfix when comparing interactions
38108
- //ic.chainsMapping[chnid][residueid] = refnumLabel;
38109
- ic.chainsMapping[chnid][residueid] = refnumLabelNoPostfix;
38110
- }
38111
- }
38112
- }
37692
+ showRefNum(giSeq, chnid, kabat_or_imgt, bCustom) { let ic = this.icn3d; ic.icn3dui;
37693
+ let bResult = ic.chainid2igtrack[chnid];
37694
+ if(!bResult) return {html: '', html2: '', html3: ''};
38113
37695
 
38114
37696
  // add color to atoms
38115
37697
  if(ic.bShowRefnum) {
@@ -38127,15 +37709,11 @@ class AnnoIg {
38127
37709
  if(!ic.chain2igArray) ic.chain2igArray = {};
38128
37710
  ic.chain2igArray[chnid] = [];
38129
37711
 
38130
- let igElem = {};
38131
- let currStrand_ori;
38132
- let prevStrand = undefined;
38133
- let prevPos;
38134
-
38135
37712
  let bLoop = false, currStrand = '';
38136
37713
  let refnumLabel, refnumStr_ori, refnumStr;
38137
37714
 
38138
37715
  // show tracks
37716
+ let domainid2respos = {};
38139
37717
  let htmlIg = '';
38140
37718
  for(let i = 0, il = giSeq.length; i < il; ++i) {
38141
37719
  htmlIg += ic.showSeqCls.insertGap(chnid, i, '-');
@@ -38143,6 +37721,7 @@ class AnnoIg {
38143
37721
  let currResi = ic.ParserUtilsCls.getResi(chnid, i);
38144
37722
  let residueid = chnid + '_' + currResi;
38145
37723
  let domainid = (bCustom) ? 0 : ic.resid2domainid[residueid];
37724
+
38146
37725
  //if(!ic.residues.hasOwnProperty(residueid)) {
38147
37726
  // htmlIg += '<span></span>';
38148
37727
  //}
@@ -38150,10 +37729,12 @@ class AnnoIg {
38150
37729
  refnumLabel = ic.resid2refnum[residueid];
38151
37730
  let bHidelabel = false;
38152
37731
 
38153
- if(refnumLabel) {
37732
+ if(refnumLabel) {
37733
+ if(!domainid2respos[domainid]) domainid2respos[domainid] = [];
37734
+ domainid2respos[domainid].push(i);
37735
+
38154
37736
  refnumStr_ori = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
38155
37737
  currStrand = refnumLabel.replace(new RegExp(refnumStr_ori,'g'), '');
38156
- currStrand_ori = currStrand;
38157
37738
 
38158
37739
  refnumStr_ori.substr(0, 1);
38159
37740
 
@@ -38169,21 +37750,6 @@ class AnnoIg {
38169
37750
  else {
38170
37751
  refnumStr = refnumStr_ori;
38171
37752
  }
38172
-
38173
- let prevStrandFirstLet = (prevStrand) ? prevStrand.substr(0, 1) : '';
38174
- let currStrandFirstLet = (currStrand) ? currStrand.substr(0, 1) : '';
38175
-
38176
- if(prevStrand != currStrand && (!prevStrandFirstLet || prevStrandFirstLet == 'F' || prevStrandFirstLet == 'G') && (currStrandFirstLet == 'A' || currStrandFirstLet == 'B') ) { // a new Ig domain starts
38177
- if(prevStrand) {
38178
- igElem.endPos = prevPos;
38179
- ic.chain2igArray[chnid].push(igElem);
38180
- }
38181
-
38182
- igElem = {};
38183
- igElem.startPos = i;
38184
- }
38185
-
38186
- if(domainid) igElem.domainid = domainid;
38187
37753
 
38188
37754
  if(bCustom) {
38189
37755
  if(!refnumStr) {
@@ -38229,9 +37795,6 @@ class AnnoIg {
38229
37795
  htmlIg += '<span></span>';
38230
37796
  }
38231
37797
  }
38232
-
38233
- prevStrand = currStrand_ori; //currStrand;
38234
- prevPos = i;
38235
37798
  }
38236
37799
  else {
38237
37800
  htmlIg += '<span></span>';
@@ -38239,10 +37802,33 @@ class AnnoIg {
38239
37802
  //}
38240
37803
  }
38241
37804
 
38242
- igElem.endPos = prevPos;
38243
- ic.chain2igArray[chnid].push(igElem);
37805
+ // igElem.endPos = prevPos;
37806
+ // ic.chain2igArray[chnid].push(igElem);
37807
+
37808
+ for(let domainid in domainid2respos) {
37809
+ let posArray = domainid2respos[domainid];
37810
+ let pos, prevPos, startPosArray = [], endPosArray = [];
37811
+ for(let i = 0, il = posArray.length; i < il; ++i) {
37812
+ pos = posArray[i];
37813
+ if(i == 0) startPosArray.push(pos);
37814
+
37815
+ if(i > 0 && pos != prevPos + 1) { // a new range
37816
+ endPosArray.push(prevPos);
37817
+ startPosArray.push(pos);
37818
+ }
37819
+
37820
+ prevPos = pos;
37821
+ }
37822
+ endPosArray.push(pos);
38244
37823
 
38245
- if(me.bNode) return {html: '', html2: '', html3: ''};
37824
+ let igElem = {};
37825
+ igElem.domainid = domainid;
37826
+ igElem.startPosArray = startPosArray;
37827
+ igElem.endPosArray = endPosArray;
37828
+ ic.chain2igArray[chnid].push(igElem);
37829
+ }
37830
+
37831
+ if(me.bNode) return {html: html, html2: html2, html3: html3}
38246
37832
  let titleSpace = 120;
38247
37833
 
38248
37834
  let linkStr = 'icn3d-link icn3d-blue';
@@ -38250,10 +37836,16 @@ class AnnoIg {
38250
37836
 
38251
37837
  let igCnt = ic.chain2igArray[chnid].length;
38252
37838
  let fromArray = [], toArray = [];
37839
+ let posindex2domainindex = {};
38253
37840
  for(let i = 0; i < igCnt; ++i) {
38254
37841
  let igElem = ic.chain2igArray[chnid][i];
38255
- fromArray.push(igElem.startPos);
38256
- toArray.push(igElem.endPos);
37842
+ fromArray = fromArray.concat(igElem.startPosArray);
37843
+ toArray = toArray.concat(igElem.endPosArray);
37844
+
37845
+ for(let j = 0, jl = igElem.startPosArray.length; j < jl; ++j) {
37846
+ let pos = igElem.startPosArray[j];
37847
+ posindex2domainindex[pos] = i;
37848
+ }
38257
37849
  }
38258
37850
 
38259
37851
  // let htmlCnt = '<span class="icn3d-residueNum" title="Ig domain count">' + igCnt.toString() + ' Igs</span>';
@@ -38285,11 +37877,6 @@ class AnnoIg {
38285
37877
  html3 += htmlTmp + '<br>';
38286
37878
  html += htmlTmp + '<span class="icn3d-seqLine">';
38287
37879
 
38288
- // summary html2
38289
- html2 += htmlTitle;
38290
- html2 += htmlCnt + '<span class="icn3d-seqLine">';
38291
-
38292
-
38293
37880
  html += htmlIg;
38294
37881
 
38295
37882
  html += htmlCnt;
@@ -38299,7 +37886,8 @@ class AnnoIg {
38299
37886
  html += '</div>';
38300
37887
 
38301
37888
  let igArray = ic.chain2igArray[chnid];
38302
- if(igArray.length == 0) return {html: '', html2: '', html3: ''};
37889
+
37890
+ if(igArray.length == 0) return {html: html, html2: html2, html3: html3}
38303
37891
  let rangeArray = [], titleArray = [], fullTitleArray = [], domainArray = [];
38304
37892
 
38305
37893
  for(let i = 0, il = igArray.length; i < il; ++i) {
@@ -38309,45 +37897,59 @@ class AnnoIg {
38309
37897
 
38310
37898
  let tmscore = info.score;
38311
37899
  let igType = ic.ref2igtype[info.refpdbname];
38312
- titleArray.push(igType + ' (TM:' + parseFloat(tmscore).toFixed(2) + ')');
38313
- fullTitleArray.push(igType + ' (TM:' + parseFloat(tmscore).toFixed(2) + '), template: ' + info.refpdbname + ', Seq. identity: ' + parseFloat(info.seqid).toFixed(2) + ', aligned residues: ' + info.nresAlign);
37900
+ let confidance = (parseFloat(tmscore) < 0.75 ) ? '?' : '';
37901
+ titleArray.push(igType + confidance + ' (TM:' + parseFloat(tmscore).toFixed(2) + ')');
37902
+ fullTitleArray.push(igType + confidance + ' (TM:' + parseFloat(tmscore).toFixed(2) + '), template: ' + info.refpdbname + ', Seq. identity: ' + parseFloat(info.seqid).toFixed(2) + ', aligned residues: ' + info.nresAlign);
38314
37903
  domainArray.push(igType);
38315
37904
 
37905
+ let segs = [];
37906
+ for(let j = 0, jl = igArray[i].startPosArray.length; j < jl; ++j) {
37907
+ segs.push({"from":igArray[i].startPosArray[j], "to":igArray[i].endPosArray[j]});
37908
+ }
38316
37909
  let range = {};
38317
- range.locs = [{"from":igArray[i].startPos, "to":igArray[i].endPos}];
37910
+ range.locs = [{"segs": segs}];
38318
37911
  rangeArray.push(range);
38319
37912
  }
38320
- if(titleArray.length == 0) return {html: '', html2: '', html3: ''};
37913
+
37914
+ if(titleArray.length == 0) return {html: html, html2: html2, html3: html3}
38321
37915
 
38322
37916
  // add tracks for the summary view
38323
- for(let i = 0, il = fromArray.length; i < il; ++i) {
38324
- let resi = ic.ParserUtilsCls.getResi(chnid, fromArray[i]);
38325
- let resid = chnid + "_" + resi;
38326
- let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]);
38327
- let colorStr =(!atom || atom.color === undefined || atom.color.getHexString() === 'FFFFFF') ? 'DDDDDD' : atom.color.getHexString();
38328
- let color =(atom && atom.color !== undefined) ? colorStr : "CCCCCC";
37917
+ if(!kabat_or_imgt && !bCustom) {
37918
+ // summary html2
37919
+ html2 += htmlTitle;
37920
+ html2 += htmlCnt + '<span class="icn3d-seqLine">';
38329
37921
 
38330
- let emptyWidth =(i == 0) ? Math.round(ic.seqAnnWidth *(fromArray[i]) / ic.maxAnnoLength) :
38331
- Math.round(ic.seqAnnWidth *(fromArray[i] - toArray[i-1] - 1) / ic.maxAnnoLength);
38332
- html2 += '<div style="display:inline-block; width:' + emptyWidth + 'px;">&nbsp;</div>';
38333
- html2 += '<div style="display:inline-block; color:white!important; font-weight:bold; background-color:#' + color + '; width:' + Math.round(ic.seqAnnWidth *(toArray[i] - fromArray[i] + 1) / ic.maxAnnoLength) + 'px;" class="icn3d-seqTitle ' + linkStr + '" ig="0" from="' + fromArray + '" to="' + toArray + '" shorttitle="' + domainArray[i] + '" index="0" setname="' + chnid + '_igs" id="' + chnid + '_igs" anno="sequence" chain="' + chnid + '" title="' + domainArray[i] + '">' + domainArray[i] + ' </div>';
38334
- }
37922
+ for(let i = 0, il = fromArray.length; i < il; ++i) {
37923
+ let resi = ic.ParserUtilsCls.getResi(chnid, fromArray[i]);
37924
+ let resid = chnid + "_" + resi;
37925
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]);
37926
+ let colorStr =(!atom || atom.color === undefined || atom.color.getHexString() === 'FFFFFF') ? 'DDDDDD' : atom.color.getHexString();
37927
+ let color =(atom && atom.color !== undefined) ? colorStr : "CCCCCC";
38335
37928
 
38336
- html2 += htmlCnt;
37929
+ let domainindex = posindex2domainindex[fromArray[i]];
38337
37930
 
38338
- html2 += '</div></div>';
38339
- html3 += '</div></div>';
37931
+ let emptyWidth =(i == 0) ? Math.round(ic.seqAnnWidth *(fromArray[i]) / ic.maxAnnoLength) :
37932
+ Math.round(ic.seqAnnWidth *(fromArray[i] - toArray[i-1] - 1) / ic.maxAnnoLength);
37933
+ html2 += '<div style="display:inline-block; width:' + emptyWidth + 'px;">&nbsp;</div>';
37934
+ html2 += '<div style="display:inline-block; color:white!important; font-weight:bold; background-color:#' + color + '; width:' + Math.round(ic.seqAnnWidth *(toArray[i] - fromArray[i] + 1) / ic.maxAnnoLength) + 'px;" class="icn3d-seqTitle ' + linkStr + '" ig="0" from="' + fromArray + '" to="' + toArray + '" shorttitle="' + domainArray[domainindex] + '" index="0" setname="' + chnid + '_igs" id="' + chnid + '_igs" anno="sequence" chain="' + chnid + '" title="' + domainArray[domainindex] + '">' + domainArray[domainindex] + ' </div>';
37935
+ }
37936
+
37937
+ html2 += htmlCnt;
38340
37938
 
38341
- // add tracks for each Ig domain
38342
- htmlTmp = '<div id="' + ic.pre + chnid + '_igseq_sequence" class="icn3d-ig icn3d-dl_sequence">';
38343
- let htmlTmp2 = htmlTmp;
38344
- let htmlTmp3 = htmlTmp;
37939
+ html2 += '</div></div>';
37940
+ html3 += '</div></div>';
38345
37941
 
38346
- let result = ic.annoCddSiteCls.setDomainFeature(rangeArray, chnid, 'ig', htmlTmp, htmlTmp2, htmlTmp3, undefined, titleArray, fullTitleArray);
37942
+ // add tracks for each Ig domain
37943
+ htmlTmp = '<div id="' + ic.pre + chnid + '_igseq_sequence" class="icn3d-ig icn3d-dl_sequence">';
37944
+ let htmlTmp2 = htmlTmp;
37945
+ let htmlTmp3 = htmlTmp;
38347
37946
 
38348
- html += result.html + '</div>';
38349
- html2 += result.html2 + '</div>';
38350
- html3 += result.html3 + '</div>';
37947
+ let result = ic.annoCddSiteCls.setDomainFeature(rangeArray, chnid, 'ig', htmlTmp, htmlTmp2, htmlTmp3, undefined, titleArray, fullTitleArray);
37948
+
37949
+ html += result.html + '</div>';
37950
+ html2 += result.html2 + '</div>';
37951
+ html3 += result.html3 + '</div>';
37952
+ }
38351
37953
 
38352
37954
  return {html: html, html2: html2, html3: html3}
38353
37955
  }
@@ -38729,7 +38331,9 @@ class AnnoDomain {
38729
38331
 
38730
38332
  if(me.cfg.blast_rep_id != chnid) { // regular
38731
38333
  for(let i = 0, il = fromArray.length; i < il; ++i) {
38732
- let emptyWidth =(i == 0) ? Math.round(ic.seqAnnWidth *(fromArray[i] - ic.baseResi[chnid] - 1) / ic.maxAnnoLength) : Math.round(ic.seqAnnWidth *(fromArray[i] - toArray[i-1] - 1) / ic.maxAnnoLength);
38334
+ // let emptyWidth =(i == 0) ? Math.round(ic.seqAnnWidth *(fromArray[i] - ic.baseResi[chnid] - 1) / ic.maxAnnoLength) : Math.round(ic.seqAnnWidth *(fromArray[i] - toArray[i-1] - 1) / ic.maxAnnoLength);
38335
+ let emptyWidth =(i == 0) ? Math.round(ic.seqAnnWidth *(fromArray[i]) / ic.maxAnnoLength) : Math.round(ic.seqAnnWidth *(fromArray[i] - toArray[i-1] - 1) / ic.maxAnnoLength);
38336
+
38733
38337
  html2 += '<div style="display:inline-block; width:' + emptyWidth + 'px;">&nbsp;</div>';
38734
38338
  html2 += '<div style="display:inline-block; color:white!important; font-weight:bold; background-color:#' + color + '; width:' + Math.round(ic.seqAnnWidth *(toArray[i] - fromArray[i] + 1) / ic.maxAnnoLength) + 'px;" class="icn3d-seqTitle icn3d-link icn3d-blue" 3ddomain="' +(index+1).toString() + '" from="' + fromArray + '" to="' + toArray + '" shorttitle="' + title + '" index="' + index + '" setname="' + chnid + '_3d_domain_' +(index+1).toString() + '" id="' + chnid + '_3d_domain_' + index + '" anno="sequence" chain="' + chnid + '" title="' + fulltitle + '">3D domain ' +(index+1).toString() + '</div>';
38735
38339
  }
@@ -40338,7 +39942,7 @@ class Domain3d {
40338
39942
  // get a list of Calpha-Calpha contacts
40339
39943
  ///list< pair< pair< int, let >, let > >
40340
39944
  let cts = this.c2b_AlphaContacts(seqLen, x0, y0, z0, dcut, resiArray);
40341
-
39945
+
40342
39946
  //
40343
39947
  // Produce a "map" of the SSEs, i.e. vec_sse[i] = 0 means residue i + 1
40344
39948
  // is in a loop, and vec_sse[i] = k means residue i + 1 belongs to SSE
@@ -40399,7 +40003,7 @@ class Domain3d {
40399
40003
  vec_cts1.push(i + 1);
40400
40004
  vec_cts2.push(i + 1);
40401
40005
  }
40402
-
40006
+
40403
40007
  // create contact counts from the contacts/interactions
40404
40008
  //map< pair< int, let >, let > ctable = this.c2b_ContactTable(vec_cts1, vec_cts2);
40405
40009
  let ctable = this.c2b_ContactTable(vec_cts1, vec_cts2);
@@ -40423,7 +40027,7 @@ class Domain3d {
40423
40027
  sheetNeighbor[ss2][ss1] = 1;
40424
40028
  }
40425
40029
  }
40426
-
40030
+
40427
40031
  //https://www.geeksforgeeks.org/number-groups-formed-graph-friends/
40428
40032
  let existing_groups = 0;
40429
40033
  let sheet2sheetnum = {};
@@ -40551,7 +40155,7 @@ class Domain3d {
40551
40155
  this.parts[2*i] = this.parts[2*i + 1] = 0;
40552
40156
  ratios[i] = 0.0;
40553
40157
  }
40554
-
40158
+
40555
40159
  n_saved = this.new_split_chain(nsse, sratio, minSize, minSSE, maxCsz, avgCts, cDelta, ncFact, this.parts, n_saved, ratios);
40556
40160
 
40557
40161
  // save domain data
@@ -40599,6 +40203,36 @@ class Domain3d {
40599
40203
 
40600
40204
  list_parts = list_partsTmp;
40601
40205
 
40206
+ // if there is only one domain, add all
40207
+ if(list_parts.length == 0) {
40208
+ let groupnum2cnt = {}, groupnum2sseList = {}, chosenGroupnum = 0;
40209
+ for(let i = 0, il = this.group_num.length; i < il; ++i) {
40210
+ let groupnum = this.group_num[i];
40211
+ let sse = i + 1;
40212
+ if(groupnum && groupnum != i + 1) {
40213
+ if(!groupnum2sseList[groupnum]) groupnum2sseList[groupnum] = [];
40214
+ // collect all sse for this groupnum
40215
+ groupnum2sseList[groupnum].push(sse);
40216
+
40217
+ if(!groupnum2cnt[groupnum]) {
40218
+ groupnum2cnt[groupnum] = 1;
40219
+ }
40220
+ else {
40221
+ ++groupnum2cnt[groupnum];
40222
+ if(groupnum2cnt[groupnum] >= 3) { // minimum 3 sse
40223
+ chosenGroupnum = groupnum;
40224
+ }
40225
+ }
40226
+ }
40227
+ }
40228
+
40229
+ if(chosenGroupnum != 0) { // found a domain
40230
+ let sseArray = [chosenGroupnum].concat(groupnum2sseList[chosenGroupnum]);
40231
+
40232
+ list_parts.push(sseArray);
40233
+ }
40234
+ }
40235
+
40602
40236
  //for (lplet = list_parts.begin(); lplet != list_parts.end(); lpint++) {
40603
40237
  for (let index = 0, indexl = list_parts.length; index < indexl; ++index) {
40604
40238
  //vector<int> prts = *lpint;
@@ -40736,7 +40370,7 @@ class Domain3d {
40736
40370
  ic.tddomains[domainName][resid] = 1;
40737
40371
  }
40738
40372
  }
40739
- }
40373
+ }
40740
40374
 
40741
40375
  return {subdomains: subdomains, substruct: substruct, pos2resi: pos2resi };
40742
40376
  } // end c2b_NewSplitChain
@@ -43292,7 +42926,8 @@ class Annotation {
43292
42926
 
43293
42927
  ic.hlUpdateCls.updateHlAll();
43294
42928
  ic.drawCls.draw();
43295
- }
42929
+ }
42930
+
43296
42931
  }
43297
42932
  }
43298
42933
 
@@ -52902,7 +52537,7 @@ class PdbParser {
52902
52537
  //Load structures from a "URL". Due to the same domain policy of Ajax call, the URL should be in the same
52903
52538
  //domain. "type" could be "pdb", "mol2", "sdf", "xyz", "icn3dpng", or "pae"
52904
52539
  //for pdb file, mol2file, sdf file, xyz file, iCn3D PNG image, and ALphaFold PAE file, respectively.
52905
- async downloadUrl(url, type, command) { let ic = this.icn3d, me = ic.icn3dui;
52540
+ async downloadUrl(url, type, command, template) { let ic = this.icn3d, me = ic.icn3dui;
52906
52541
  let pos = url.lastIndexOf('/');
52907
52542
  if(pos != -1) {
52908
52543
  let posDot = url.lastIndexOf('.');
@@ -52920,9 +52555,19 @@ class PdbParser {
52920
52555
  ic.InputfileData = (ic.InputfileData) ? ic.InputfileData + '\nENDMDL\n' + data : data;
52921
52556
  ic.InputfileType = type;
52922
52557
 
52558
+ // append
52559
+ ic.hAtoms = {};
52560
+ ic.dAtoms = {};
52561
+
52562
+ ic.resetConfig();
52563
+ ic.bResetAnno = true;
52564
+ ic.bResetSets = true;
52565
+
52923
52566
  if(type === 'pdb') {
52924
- await this.loadPdbData(data);
52925
- //await ic.loadScriptCls.loadScript(command, undefined, true);
52567
+ // await this.loadPdbData(data);
52568
+ let bAppend = true;
52569
+ let id = (template) ? template.replace(/_/g, '').substr(0, 4) : undefined;
52570
+ await this.loadPdbData(data, id, undefined, bAppend);
52926
52571
  }
52927
52572
  else if(type === 'mmcif') {
52928
52573
  let url = me.htmlCls.baseUrl + "mmcifparser/mmcifparser.cgi";
@@ -52950,6 +52595,17 @@ class PdbParser {
52950
52595
  let bFull = true;
52951
52596
  ic.contactMapCls.processAfErrorMap(JSON.parse(data), bFull);
52952
52597
  }
52598
+
52599
+ //append
52600
+ if(ic.bSetChainsAdvancedMenu) ic.definedSetsCls.showSets();
52601
+
52602
+ ic.bResetAnno = true;
52603
+
52604
+ if(ic.bAnnoShown) {
52605
+ await ic.showAnnoCls.showAnnotations();
52606
+
52607
+ ic.annotationCls.resetAnnoTabAll();
52608
+ }
52953
52609
  }
52954
52610
 
52955
52611
  //Atom "data" from PDB file was parsed to set up parameters for the 3D viewer. The deferred parameter
@@ -66104,7 +65760,7 @@ class Dssp {
66104
65760
  ic.ref2igtype['BArrestin1_4jqiA_rat_n1'] = 'IgFN3-like';
66105
65761
  ic.ref2igtype['BTLA_2aw2A_human_Iset'] = 'IgI';
66106
65762
  ic.ref2igtype['C3_2qkiD_human_n1'] = 'IgFN3-like';
66107
- ic.ref2igtype['CD19_6al5A_human_C2orV-n1'] = 'other Ig'; //'CD19';
65763
+ ic.ref2igtype['CD19_6al5A_human_C2orV-n1'] = 'CD19';
66108
65764
  ic.ref2igtype['CD28_1yjdC_human_V'] = 'IgV';
66109
65765
  ic.ref2igtype['CD2_1hnfA_human_C2-n2'] = 'IgC2';
66110
65766
  ic.ref2igtype['CD2_1hnfA_human_V-n1'] = 'IgV';
@@ -66115,8 +65771,8 @@ class Dssp {
66115
65771
  ic.ref2igtype['CoAtomerGamma1_1r4xA_human'] = 'IgE';
66116
65772
  ic.ref2igtype['Contactin1_2ee2A_human_FN3-n9'] = 'IgFN3';
66117
65773
  ic.ref2igtype['Contactin1_3s97C_human_C2-n2'] = 'IgC2';
66118
- ic.ref2igtype['CuZnSuperoxideDismutase_1hl5C_human'] = 'other Ig'; //'SOD';
66119
- ic.ref2igtype['ECadherin_4zt1A_human_n2'] = 'other Ig'; //'Cadherin';
65774
+ ic.ref2igtype['CuZnSuperoxideDismutase_1hl5C_human'] = 'SOD';
65775
+ ic.ref2igtype['ECadherin_4zt1A_human_n2'] = 'Cadherin';
66120
65776
  ic.ref2igtype['Endo-1,4-BetaXylanase10A_1i8aA_bacteria_n4'] = 'IgE';
66121
65777
  ic.ref2igtype['FAB-HEAVY_5esv_C1-n2'] = 'IgC1';
66122
65778
  ic.ref2igtype['FAB-HEAVY_5esv_V-n1'] = 'IgV';
@@ -66132,12 +65788,12 @@ class Dssp {
66132
65788
  ic.ref2igtype['JAM1_1nbqA_human_VorIset-n2'] = 'IgI';
66133
65789
  ic.ref2igtype['LAG3_7tzgD_human_C2-n2'] = 'IgC2';
66134
65790
  ic.ref2igtype['LAG3_7tzgD_human_V-n1'] = 'IgV';
66135
- ic.ref2igtype['LaminAC_1ifrA_human'] = 'other Ig'; //'Lamin';
65791
+ ic.ref2igtype['LaminAC_1ifrA_human'] = 'Lamin';
66136
65792
  ic.ref2igtype['MHCIa_7phrH_human_C1'] = 'IgC1';
66137
65793
  ic.ref2igtype['MPT63_1lmiA_bacteria'] = 'IgE';
66138
65794
  ic.ref2igtype['NaCaExchanger_2fwuA_dog_n2'] = 'IgE';
66139
65795
  ic.ref2igtype['NaKATPaseTransporterBeta_2zxeB_spurdogshark'] = 'IgE';
66140
- ic.ref2igtype['ORF7a_1xakA_virus'] = 'other Ig'; //'ORF';
65796
+ ic.ref2igtype['ORF7a_1xakA_virus'] = 'ORF';
66141
65797
  ic.ref2igtype['PD1_4zqkB_human_V'] = 'IgV';
66142
65798
  ic.ref2igtype['PDL1_4z18B_human_V-n1'] = 'IgV';
66143
65799
  ic.ref2igtype['Palladin_2dm3A_human_Iset-n1'] = 'IgI';
@@ -66188,7 +65844,7 @@ class Dssp {
66188
65844
  let numRound = 0;
66189
65845
 
66190
65846
  //while(!bNoMoreIg) {
66191
- while(!bNoMoreIg && numRound < 10) {
65847
+ while(!bNoMoreIg && numRound < 15) {
66192
65848
  let bRerun = true;
66193
65849
  bNoMoreIg = await thisClass.parseRefPdbData(ic.pdbDataArray, template, bRerun);
66194
65850
  ++numRound;
@@ -66227,7 +65883,7 @@ class Dssp {
66227
65883
  for(let j = 0, jl = chainidArray.length; j < jl; ++j) {
66228
65884
  let chainid = chainidArray[j];
66229
65885
 
66230
- // for selected atoms only, assign ic.resid2domainid[resid]
65886
+ // for selected atoms only
66231
65887
  let domainAtomsArray = this.getDomainAtomsArray(chainid, bRerun);
66232
65888
 
66233
65889
  if(!ic.domainid2refpdbname) ic.domainid2refpdbname = {};
@@ -66268,7 +65924,7 @@ class Dssp {
66268
65924
  }
66269
65925
  }
66270
65926
  else {
66271
- ic.domainid2refpdbname[domainid] = template;
65927
+ ic.domainid2refpdbname[domainid] = [template];
66272
65928
  domainidpairArray.push(domainid + "|1" + template); // "1" was added for the first round strand-only template
66273
65929
  }
66274
65930
  }
@@ -66308,9 +65964,6 @@ class Dssp {
66308
65964
  let pdbDataArray = await this.promiseWithFixedJobs(pdbAjaxArray);
66309
65965
 
66310
65966
  for(let domainid in ic.domainid2refpdbname) {
66311
- ic.domainid2refpdbname[domainid];
66312
- domainid.substr(0, domainid.indexOf(','));
66313
-
66314
65967
  let pdb_target = ic.domainid2pdb[domainid];
66315
65968
  for(let index = 0, indexl = pdbDataArray.length; index < indexl; ++index) {
66316
65969
  let struct2 = ic.defaultPdbId + index;
@@ -66371,12 +66024,10 @@ class Dssp {
66371
66024
 
66372
66025
  if(bRerunDomain) {
66373
66026
  let atomsAssigned = {};
66027
+ //ic.resid2refnum_ori should be used
66374
66028
  for(let resid in ic.resid2refnum_ori) {
66375
66029
  atomsAssigned = me.hashUtilsCls.unionHash(atomsAssigned, ic.residues[resid]);
66376
66030
  }
66377
- // for(let resid in ic.resid2refnum) {
66378
- // if(ic.resid2refnum[resid]) atomsAssigned = me.hashUtilsCls.unionHash(atomsAssigned, ic.residues[resid]);
66379
- // }
66380
66031
 
66381
66032
  currAtoms = me.hashUtilsCls.exclHash(currAtoms, atomsAssigned);
66382
66033
 
@@ -66396,23 +66047,16 @@ class Dssp {
66396
66047
  let result = ic.domain3dCls.c2b_NewSplitChain(currAtoms, undefined);
66397
66048
  let subdomains = result.subdomains;
66398
66049
  let pos2resi = result.pos2resi;
66399
-
66050
+ /*
66400
66051
  if(subdomains.length <= 1) {
66401
66052
  let residueArray = ic.resid2specCls.atoms2residues(Object.keys(currAtoms));
66402
66053
  if(residueArray.length < minResidues) return domainAtomsArray;
66403
- /*
66404
- let atomFirst = ic.firstAtomObjCls.getFirstAtomObj(currAtoms);
66405
- let atomLast = ic.firstAtomObjCls.getLastAtomObj(currAtoms);
66406
- let resiSum = atomFirst.resi + ':' + atomLast.resi + ':' + Object.keys(currAtoms).length;
66407
- */
66054
+
66408
66055
  for(let n = 0, nl = residueArray.length; n < nl; ++n) {
66409
66056
  let resid = residueArray[n];
66410
- /*
66411
- ic.resid2domainid[resid] = chainid + ',0' + '_' + resiSum;
66412
- */
66057
+
66413
66058
  // clear previous refnum assignment if any
66414
- // if(!bRerunDomain && ic.resid2refnum && ic.resid2refnum[resid]) {
66415
- // if(ic.resid2refnum && ic.resid2refnum[resid]) {
66059
+ // if(bRerunDomain) {
66416
66060
  delete ic.resid2refnum[resid];
66417
66061
  delete ic.residIgLoop[resid];
66418
66062
  // }
@@ -66420,27 +66064,27 @@ class Dssp {
66420
66064
 
66421
66065
  domainAtomsArray.push(currAtoms);
66422
66066
  }
66423
- else {
66067
+ else
66068
+ */
66069
+
66070
+ if(subdomains.length >= 1) {
66424
66071
  for(let k = 0, kl = subdomains.length; k < kl; ++k) {
66425
66072
  let domainAtoms = {};
66426
66073
  let segArray = subdomains[k];
66427
66074
 
66428
66075
  let resCnt = 0;
66429
66076
  for(let m = 0, ml = segArray.length; m < ml; m += 2) {
66430
- let startResi = segArray[m];
66431
- let endResi = segArray[m+1];
66432
- for(let n = parseInt(startResi); n <= parseInt(endResi); ++n) {
66077
+ let startResi = parseInt(segArray[m]);
66078
+ let endResi = parseInt(segArray[m+1]);
66079
+
66080
+ for(let n = startResi; n <= endResi; ++n) {
66433
66081
  let resid = chainid + '_' + pos2resi[n];
66434
66082
  ++resCnt;
66435
66083
  domainAtoms = me.hashUtilsCls.unionHash(domainAtoms, ic.residues[resid]);
66436
- //ic.resid2domainid[resid] = chainid + '-' + k;
66437
66084
 
66438
66085
  // clear previous refnum assignment if any
66439
- // if(!bRerunDomain && ic.resid2refnum && ic.resid2refnum[resid]) {
66440
- // if(ic.resid2refnum && ic.resid2refnum[resid]) {
66441
- delete ic.resid2refnum[resid];
66442
- delete ic.residIgLoop[resid];
66443
- // }
66086
+ delete ic.resid2refnum[resid];
66087
+ delete ic.residIgLoop[resid];
66444
66088
  }
66445
66089
  }
66446
66090
 
@@ -66471,7 +66115,7 @@ class Dssp {
66471
66115
  getTemplateList(domainid) { let ic = this.icn3d; ic.icn3dui;
66472
66116
  let refpdbname = '', score = '', seqid = '', nresAlign = '';
66473
66117
 
66474
- refpdbname = ic.domainid2refpdbname[domainid];
66118
+ refpdbname = ic.domainid2refpdbname[domainid][0]; // one template in round 2
66475
66119
 
66476
66120
  if(ic.domainid2score[domainid]) {
66477
66121
  let itemArray = ic.domainid2score[domainid].split('_');
@@ -66491,6 +66135,8 @@ class Dssp {
66491
66135
 
66492
66136
  // find the best alignment for each chain
66493
66137
  let domainid2segs = {};
66138
+ let domainid2strandcnt = {};
66139
+ let domainid2refpdbnamelist = {};
66494
66140
 
66495
66141
  if(!ic.chainid2refpdbname) ic.chainid2refpdbname = {};
66496
66142
  // if(!ic.chainid2score) ic.chainid2score = {};
@@ -66583,7 +66229,7 @@ class Dssp {
66583
66229
  if(!me.bNode && !(bBstrand && bCstrand && bEstrand && bFstrand)) console.log("Some of the Ig strands B, C, E, F are missing in the domain " + domainid + "...");
66584
66230
  if(!me.bNode && !(bBSheet && bCSheet && bESheet && bFSheet)) console.log("Some of the Ig strands B, C, E, F are not beta sheets...");
66585
66231
  // if(!me.bNode && (BCnt < 3 || CCnt < 3 || ECnt < 3 || FCnt < 3)) console.log("Some of the Ig strands B, C, E, F are missing in the domain " + domainid + "...");
66586
- if(ic.domainid2refpdbname[domainid] == refpdbname) {
66232
+ if(ic.domainid2refpdbname[domainid][0] == refpdbname) {
66587
66233
  delete ic.domainid2refpdbname[domainid];
66588
66234
  delete ic.domainid2score[domainid];
66589
66235
  }
@@ -66595,21 +66241,67 @@ class Dssp {
66595
66241
  if(!me.bNode) console.log("domainid: " + domainid);
66596
66242
  }
66597
66243
 
66598
- if(!domainid2segs.hasOwnProperty(domainid) || queryData[0].score >= ic.domainid2score[domainid].split('_')[0]) {
66244
+ // count the number of matched strands
66245
+ let strandHash = {};
66246
+ for(let j = 0, jl = queryData[0].segs.length; j < jl; ++j) {
66247
+ let seg = queryData[0].segs[j];
66248
+ let q_start = parseInt(seg.q_start);
66249
+
66250
+ let strand = this.getStrandFromRefnum(q_start);
66251
+ strandHash[strand] = 1;
66252
+ }
66253
+ let score = parseFloat(queryData[0].score);
66254
+ //!!!
66255
+ // if the TM score difference is within 0.1 and more strands are found, use the template with more strands
66256
+ // if(!domainid2segs.hasOwnProperty(domainid) ||
66257
+ // (score >= parseFloat(ic.domainid2score[domainid].split('_')[0]) + tmAdjust)
66258
+ // || (score >= parseFloat(ic.domainid2score[domainid].split('_')[0]) - tmAdjust && score < parseFloat(ic.domainid2score[domainid].split('_')[0]) + tmAdjust && Object.keys(strandHash).length > domainid2strandcnt[domainid])
66259
+ // ) {
66260
+
66261
+ // use TM-score alone
66262
+ if(!domainid2segs.hasOwnProperty(domainid) || score >= parseFloat(ic.domainid2score[domainid].split('_')[0])) {
66599
66263
  ic.domainid2score[domainid] = queryData[0].score + '_' + queryData[0].frac_identical + '_' + queryData[0].num_res ;
66264
+
66600
66265
  if(bRound1) {
66601
- ic.domainid2refpdbname[domainid] = parseFloat(queryData[0].score) > 0.75 ? refpdbname : 'all_templates';
66266
+ ic.domainid2refpdbname[domainid] = score > 0.75 ? [refpdbname] : ['all_templates'];
66602
66267
  }
66603
66268
  else {
66604
- ic.domainid2refpdbname[domainid] = refpdbname;
66269
+ ic.domainid2refpdbname[domainid] = [refpdbname];
66605
66270
  }
66271
+
66606
66272
  domainid2segs[domainid] = queryData[0].segs;
66273
+ domainid2strandcnt[domainid] = Object.keys(strandHash).length;
66274
+
66607
66275
  ic.domainid2ig2kabat[domainid] = queryData[0].ig2kabat;
66608
66276
  ic.domainid2ig2imgt[domainid] = queryData[0].ig2imgt;
66609
66277
  }
66278
+
66279
+ if(bRound1) {
66280
+ if(!domainid2refpdbnamelist[domainid]) domainid2refpdbnamelist[domainid] = {};
66281
+ domainid2refpdbnamelist[domainid][refpdbname] = score;
66282
+ }
66610
66283
  }
66611
66284
 
66612
- return domainid2segs;
66285
+ //!!!
66286
+ /*
66287
+ // combine the top three clusters for the 2nd round alignment
66288
+ if(bRound1) {
66289
+ for(let domainid in domainid2refpdbnamelist) {
66290
+ if(!me.bNode) console.log("###score " + ic.domainid2score[domainid].split('_')[0] + " ic.domainid2refpdbname[domainid][0] " + ic.domainid2refpdbname[domainid][0])
66291
+ if(!me.bNode && ic.domainid2refpdbname[domainid][0] == 'all_templates') {
66292
+ let refpdbname2score = domainid2refpdbnamelist[domainid];
66293
+ let refpdbnameList = Object.keys(refpdbname2score);
66294
+ refpdbnameList.sort(function(a, b) {
66295
+ return refpdbname2score[b] - refpdbname2score[a]
66296
+ });
66297
+ // top 3 templates
66298
+ ic.domainid2refpdbname[domainid] = refpdbnameList.slice(0,3);
66299
+ }
66300
+ if(!me.bNode) console.log("###bb ic.domainid2refpdbname[domainid] " + ic.domainid2refpdbname[domainid])
66301
+ }
66302
+ }
66303
+ */
66304
+ return domainid2segs; // only used in round 2
66613
66305
  }
66614
66306
 
66615
66307
  async parseAlignData(dataArray, domainidpairArray, bRound1) { let ic = this.icn3d, me = ic.icn3dui;
@@ -66617,6 +66309,7 @@ class Dssp {
66617
66309
 
66618
66310
  let domainid2segs = this.parseAlignData_part1(dataArray, domainidpairArray, bRound1);
66619
66311
 
66312
+ // !!!no more Igs to detect
66620
66313
  if(Object.keys(domainid2segs).length == 0) {
66621
66314
  bNoMoreIg = true;
66622
66315
  return bNoMoreIg;
@@ -66631,25 +66324,30 @@ class Dssp {
66631
66324
  let urltmalign = me.htmlCls.tmalignUrl;
66632
66325
  for(let domainid in ic.domainid2refpdbname) {
66633
66326
  let pdbAjaxArray = [];
66634
- let refpdbname = ic.domainid2refpdbname[domainid];
66327
+ let refpdbnameList = ic.domainid2refpdbname[domainid];
66635
66328
  //let pdbid = domainid.substr(0, domainid.indexOf('_'));
66636
66329
  let chainid = domainid.substr(0, domainid.indexOf(','));
66637
66330
 
66638
- //if(ic.refpdbHash.hasOwnProperty(pdbid)) {
66639
66331
  if(ic.refpdbHash.hasOwnProperty(chainid)) {
66640
- // use itself as the ref structure
66641
- //refpdbname = pdbid;
66642
- refpdbname = chainid;
66332
+ refpdbnameList = [chainid];
66643
66333
 
66644
- if(!me.bNode) console.log("Adjusted refpdbname for domainid " + domainid + ": " + refpdbname);
66334
+ if(!me.bNode) console.log("Adjusted refpdbname for domainid " + domainid + ": " + chainid);
66645
66335
  }
66646
66336
 
66647
- if(!ic.refpdbHash[refpdbname]) {
66337
+ let templates = [];
66338
+ for(let i = 0, il = refpdbnameList.length; i < il; ++i) {
66339
+ let refpdbname = refpdbnameList[i];
66340
+ if(!ic.refpdbHash[refpdbname]) continue;
66341
+ templates = templates.concat(ic.refpdbHash[refpdbname]);
66342
+ }
66343
+
66344
+ // if(!ic.refpdbHash[refpdbname]) {
66345
+ if(templates.length == 0) {
66648
66346
  continue;
66649
66347
  }
66650
66348
 
66651
- for(let k = 0, kl = ic.refpdbHash[refpdbname].length; k < kl; ++k) {
66652
- let urlpdb = me.htmlCls.baseUrl + "mmcifparser/mmcifparser.cgi?refpdbid=" + ic.refpdbHash[refpdbname][k];
66349
+ for(let k = 0, kl = templates.length; k < kl; ++k) {
66350
+ let urlpdb = me.htmlCls.baseUrl + "mmcifparser/mmcifparser.cgi?refpdbid=" + templates[k];
66653
66351
 
66654
66352
  let pdbAjax = me.getAjaxPromise(urlpdb, 'text');
66655
66353
 
@@ -66669,12 +66367,11 @@ class Dssp {
66669
66367
  let header = 'HEADER ' + struct2 + '\n';
66670
66368
  pdb_query = header + pdb_query;
66671
66369
 
66672
- let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target, "queryid": ic.refpdbHash[refpdbname][index]};
66370
+ let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target, "queryid": templates[index]};
66673
66371
  let alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
66674
66372
  ajaxArray.push(alignAjax);
66675
66373
 
66676
- //domainidpairArray3.push(domainid + "," + refpdbname);
66677
- domainidpairArray3.push(domainid + "|" + ic.refpdbHash[refpdbname][index]);
66374
+ domainidpairArray3.push(domainid + "|" + templates[index]);
66678
66375
  }
66679
66376
  }
66680
66377
 
@@ -66690,19 +66387,19 @@ class Dssp {
66690
66387
  return bNoMoreIg;
66691
66388
  }
66692
66389
 
66693
- await this.parseAlignData_part3(domainid2segs);
66390
+ this.parseAlignData_part3(domainid2segs);
66694
66391
 
66695
66392
  return bNoMoreIg;
66696
66393
  }
66697
66394
 
66698
- async parseAlignData_part3(domainid2segs) { let ic = this.icn3d, me = ic.icn3dui;
66395
+ parseAlignData_part3(domainid2segs) { let ic = this.icn3d, me = ic.icn3dui;
66699
66396
 
66700
66397
  // combine domainid into chainid
66701
66398
  let processedChainid = {};
66702
66399
 
66703
66400
  for(let domainid in ic.domainid2refpdbname) {
66704
66401
  // remove the first round template
66705
- if(ic.domainid2refpdbname[domainid].substr(0,1) == '1') {
66402
+ if(ic.domainid2refpdbname[domainid][0].substr(0,1) == '1') {
66706
66403
  delete ic.domainid2refpdbname[domainid];
66707
66404
  delete ic.domainid2score[domainid];
66708
66405
  continue;
@@ -66717,7 +66414,7 @@ class Dssp {
66717
66414
  processedChainid[chainid] = 1;
66718
66415
 
66719
66416
  if(!ic.chainid2refpdbname.hasOwnProperty(chainid)) ic.chainid2refpdbname[chainid] = [];
66720
- ic.chainid2refpdbname[chainid].push(ic.domainid2refpdbname[domainid] + '|' + domainid);
66417
+ ic.chainid2refpdbname[chainid].push(ic.domainid2refpdbname[domainid][0] + '|' + domainid);
66721
66418
 
66722
66419
  // if(!ic.chainid2score.hasOwnProperty(chainid)) ic.chainid2score[chainid] = [];
66723
66420
  // ic.chainid2score[chainid].push(ic.domainid2score[domainid] + '|' + domainid);
@@ -66747,9 +66444,6 @@ class Dssp {
66747
66444
  let segArray = domainid2segs[domainid];
66748
66445
  let chainid = domainid.split(',')[0];
66749
66446
 
66750
- // let refpdbnameArray = ic.chainid2refpdbname[chainid];
66751
-
66752
- // let result = this.getTemplateList(chainid);
66753
66447
  let result = this.getTemplateList(domainid);
66754
66448
  let refpdbname = result.refpdbname;
66755
66449
  let score = result.score;
@@ -66917,6 +66611,15 @@ class Dssp {
66917
66611
  }
66918
66612
  }
66919
66613
 
66614
+ if(!ic.chainid2igtrack) ic.chainid2igtrack = {};
66615
+ for(let chainid in ic.chains) {
66616
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chainid]);
66617
+ if(ic.proteins.hasOwnProperty(atom.serial)) {
66618
+ let giSeq = ic.showSeqCls.getSeq(chainid);
66619
+ ic.chainid2igtrack[chainid] = this.ajdustRefnum(giSeq, chainid);
66620
+ }
66621
+ }
66622
+
66920
66623
  /*
66921
66624
  if(Object.keys(ic.resid2refnum).length > 0) {
66922
66625
  ic.bShowRefnum = true;
@@ -66946,7 +66649,7 @@ class Dssp {
66946
66649
  */
66947
66650
  }
66948
66651
 
66949
- getLabelFromRefnum(oriRefnum, prevStrand) { let ic = this.icn3d; ic.icn3dui;
66652
+ getStrandFromRefnum(oriRefnum, prevStrand) { let ic = this.icn3d; ic.icn3dui;
66950
66653
  let refnum = parseInt(oriRefnum);
66951
66654
 
66952
66655
  //N-terminus = 0999-0001
@@ -66973,33 +66676,44 @@ class Dssp {
66973
66676
 
66974
66677
  // loops may have numbers such as 1310, 1410
66975
66678
 
66976
- let refnumLabel;
66977
-
66978
- if(refnum < 1000) refnumLabel = undefined;
66979
- else if(refnum >= 1200 && refnum < 1290) refnumLabel = "A---" + oriRefnum;
66980
- else if(refnum >= 1320 && refnum < 1390) refnumLabel = "A--" + oriRefnum;
66981
- else if(refnum >= 1420 && refnum < 1490) refnumLabel = "A-" + oriRefnum;
66982
- else if(refnum >= 1520 && refnum < 1590) refnumLabel = "A" + oriRefnum;
66983
- else if(refnum >= 1620 && refnum < 1690) refnumLabel = "A+" + oriRefnum;
66984
- else if(refnum >= 1820 && refnum < 1890) refnumLabel = "A'" + oriRefnum;
66985
- else if(refnum >= 2000 && refnum < 2900) refnumLabel = "B" + oriRefnum;
66986
- else if(refnum >= 3300 && refnum < 3390) refnumLabel = "C--" + oriRefnum;
66987
- else if(refnum >= 3420 && refnum < 3490) refnumLabel = "C-" + oriRefnum;
66988
- else if(refnum >= 3520 && refnum < 3590) refnumLabel = "C" + oriRefnum;
66989
- else if(refnum >= 4000 && refnum < 4900) refnumLabel = "C'" + oriRefnum;
66990
- else if(refnum >= 5000 && refnum < 5900) refnumLabel = "C''" + oriRefnum;
66991
- else if(refnum >= 6000 && refnum < 6900) refnumLabel = "D" + oriRefnum;
66992
- else if(refnum >= 7500 && refnum < 7590) refnumLabel = "E" + oriRefnum;
66993
- else if(refnum >= 7620 && refnum < 7900) refnumLabel = "E+" + oriRefnum;
66994
- else if(refnum >= 8000 && refnum < 8900) refnumLabel = "F" + oriRefnum;
66995
- else if(refnum >= 9500 && refnum < 9590) refnumLabel = "G" + oriRefnum;
66996
- else if(refnum >= 9620 && refnum < 9690) refnumLabel = "G+" + oriRefnum;
66997
- else if(refnum >= 9720 && refnum < 9790) refnumLabel = "G++" + oriRefnum;
66998
- else if(refnum > 9900) refnumLabel = undefined;
66999
- else refnumLabel = " " + oriRefnum;
67000
- if(prevStrand) refnumLabel = prevStrand + oriRefnum;
67001
-
67002
- return refnumLabel
66679
+ let strand;
66680
+
66681
+ if(refnum < 1000) strand = undefined;
66682
+ else if(refnum >= 1200 && refnum < 1290) strand = "A---";
66683
+ else if(refnum >= 1320 && refnum < 1390) strand = "A--";
66684
+ else if(refnum >= 1420 && refnum < 1490) strand = "A-";
66685
+ else if(refnum >= 1520 && refnum < 1590) strand = "A";
66686
+ else if(refnum >= 1620 && refnum < 1690) strand = "A+";
66687
+ else if(refnum >= 1820 && refnum < 1890) strand = "A'";
66688
+ else if(refnum >= 2000 && refnum < 2900) strand = "B";
66689
+ else if(refnum >= 3300 && refnum < 3390) strand = "C--";
66690
+ else if(refnum >= 3420 && refnum < 3490) strand = "C-";
66691
+ else if(refnum >= 3520 && refnum < 3590) strand = "C";
66692
+ else if(refnum >= 4000 && refnum < 4900) strand = "C'";
66693
+ else if(refnum >= 5000 && refnum < 5900) strand = "C''";
66694
+ else if(refnum >= 6000 && refnum < 6900) strand = "D";
66695
+ else if(refnum >= 7500 && refnum < 7590) strand = "E";
66696
+ else if(refnum >= 7620 && refnum < 7900) strand = "E+";
66697
+ else if(refnum >= 8000 && refnum < 8900) strand = "F";
66698
+ else if(refnum >= 9500 && refnum < 9590) strand = "G";
66699
+ else if(refnum >= 9620 && refnum < 9690) strand = "G+";
66700
+ else if(refnum >= 9720 && refnum < 9790) strand = "G++";
66701
+ else if(refnum > 9900) strand = undefined;
66702
+ else strand = " ";
66703
+ if(prevStrand) strand = prevStrand;
66704
+
66705
+ return strand
66706
+ }
66707
+
66708
+ getLabelFromRefnum(oriRefnum, prevStrand) { let ic = this.icn3d; ic.icn3dui;
66709
+ let strand = this.getStrandFromRefnum(oriRefnum, prevStrand);
66710
+
66711
+ if(strand) {
66712
+ return strand + oriRefnum;
66713
+ }
66714
+ else {
66715
+ return undefined;
66716
+ }
67003
66717
  }
67004
66718
 
67005
66719
  async parseCustomRefFile(data) { let ic = this.icn3d; ic.icn3dui;
@@ -67078,7 +66792,8 @@ class Dssp {
67078
66792
  // 1. show IgStrand ref numbers
67079
66793
  if(type == 'igstrand' || type == 'IgStrand') {
67080
66794
  // iGStrand reference numbers were adjusted when showing in sequences
67081
- if(me.bNode) {
66795
+ // if(me.bNode) {
66796
+ if(ic.bShowRefnum) {
67082
66797
  for(let chnid in ic.chains) {
67083
66798
  let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chnid]);
67084
66799
  if(ic.proteins.hasOwnProperty(atom.serial)) {
@@ -67120,29 +66835,6 @@ class Dssp {
67120
66835
 
67121
66836
  // refData += '{"Ig domain" : ' + bIgDomain + ', "ref PDB" : ' + JSON.stringify(ic.refPdbList) + ',\n';
67122
66837
  refData += '{"Ig domain" : ' + bIgDomain + ',\n';
67123
- /*
67124
- if(bIgDomain) {
67125
- refData += '"data": {\n';
67126
- for(let chnid in ic.chains) {
67127
- let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chnid]);
67128
- if(ic.proteins.hasOwnProperty(atom.serial)) {
67129
- let bIgChain = false;
67130
- let chainRefData = '"' + chnid + '": [\n';
67131
- for(let i = 0; i < ic.chainsSeq[chnid].length; ++i) {
67132
- const resid = chnid + '_' + ic.chainsSeq[chnid][i].resi + '_' + ic.chainsSeq[chnid][i].name;
67133
- chainRefData += '{"' + resid + '": "' + resid2refnum[resid] + '"},\n';
67134
- if(resid2refnum[resid]) bIgChain = true;
67135
- }
67136
- chainRefData += '],\n';
67137
-
67138
- if(bIgChain) {
67139
- refData += chainRefData;
67140
- }
67141
- }
67142
- }
67143
- refData += '}\n';
67144
- }
67145
- */
67146
66838
 
67147
66839
  if(bIgDomain) {
67148
66840
  refData += '"igs": [\n';
@@ -67153,8 +66845,8 @@ class Dssp {
67153
66845
  refData += '{"' + chnid + '": {\n';
67154
66846
 
67155
66847
  for(let i = 0, il = igArray.length; i < il; ++i) {
67156
- let startPos = igArray[i].startPos;
67157
- let endPos = igArray[i].endPos;
66848
+ let startPosArray = igArray[i].startPosArray;
66849
+ let endPosArray = igArray[i].endPosArray;
67158
66850
  let domainid = igArray[i].domainid;
67159
66851
  let info = ic.domainid2info[domainid];
67160
66852
  if(!info) continue;
@@ -67162,9 +66854,13 @@ class Dssp {
67162
66854
  refData += '"' + domainid + '": {\n';
67163
66855
 
67164
66856
  refData += '"refpdbname":"' + info.refpdbname + '", "score":' + info.score + ', "seqid":' + info.seqid + ', "nresAlign":' + info.nresAlign + ', "data": [';
67165
- for(let i = startPos; i <= endPos; ++i) {
67166
- const resid = chnid + '_' + ic.chainsSeq[chnid][i].resi + '_' + ic.chainsSeq[chnid][i].name;
67167
- refData += '{"' + resid + '": "' + resid2refnum[resid] + '"},\n';
66857
+ for(let j = 0, jl = startPosArray.length; j < jl; ++j) {
66858
+ let startPos = startPosArray[j];
66859
+ let endPos = endPosArray[j];
66860
+ for(let k = startPos; k <= endPos; ++k) {
66861
+ const resid = chnid + '_' + ic.chainsSeq[chnid][k].resi + '_' + ic.chainsSeq[chnid][k].name;
66862
+ refData += '{"' + resid + '": "' + resid2refnum[resid] + '"},\n';
66863
+ }
67168
66864
  }
67169
66865
  refData += '],\n';
67170
66866
 
@@ -67261,6 +66957,485 @@ class Dssp {
67261
66957
 
67262
66958
  return dataArray3;
67263
66959
  }
66960
+
66961
+ ajdustRefnum(giSeq, chnid) { let ic = this.icn3d, me = ic.icn3dui;
66962
+ if(!ic.chainid2refpdbname[chnid]) return false;
66963
+
66964
+ // auto-generate ref numbers for loops
66965
+ let currStrand = '', prevStrand = '';
66966
+ let refnumLabel, refnumStr_ori, refnumStr, postfix, strandPostfix, refnum, refnum3c, refnum2c;
66967
+ let bExtendedStrand = false, bSecThird9 = false;
66968
+
66969
+ // sometimes one chain may have several Ig domains,set an index for each IgDomain
66970
+ let index = 1, bStart = false;
66971
+
66972
+ if(!me.bNode) { // do not overwrite loops in node
66973
+ // reset ic.residIgLoop for the current selection, which could be the second round of ref num assignment
66974
+ // just current chain
66975
+ let atomHash = me.hashUtilsCls.intHash(ic.chains[chnid], ic.hAtoms);
66976
+ ic.firstAtomObjCls.getResiduesFromAtoms(atomHash);
66977
+ }
66978
+
66979
+ // 1. get the range of each strand excluding loops
66980
+ let strandArray = [], strandHash = {}, strandCnt = 0, resCnt = 0, resCntBfAnchor = 0, resCntAtAnchor = 0;
66981
+ let bFoundAnchor = false;
66982
+
66983
+ for(let i = 0, il = giSeq.length; i < il; ++i, ++resCnt, ++resCntBfAnchor, ++resCntAtAnchor) {
66984
+ let currResi = ic.ParserUtilsCls.getResi(chnid, i);
66985
+ let residueid = chnid + '_' + currResi;
66986
+ let domainid;
66987
+
66988
+ refnumLabel = ic.resid2refnum[residueid];
66989
+
66990
+ let firstChar = (refnumLabel) ? refnumLabel.substr(0,1) : '';
66991
+ if(!bStart && refnumLabel && (firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
66992
+ bStart = true;
66993
+ resCnt = 1; // the first one is included
66994
+ bFoundAnchor = false;
66995
+ }
66996
+
66997
+ //if((prevStrand.substr(0,1) == 'F' || prevStrand.substr(0,1) == 'G') && !refnumLabel) { // indicate the end of an IG domain
66998
+ if((prevStrand.substr(0,1) == 'G') && !refnumLabel) { // indicate the end of an IG domain
66999
+ bStart = false;
67000
+ }
67001
+
67002
+ if(refnumLabel) {
67003
+ domainid = ic.resid2domainid[residueid];
67004
+
67005
+ refnumStr_ori = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
67006
+ currStrand = refnumLabel.replace(new RegExp(refnumStr_ori,'g'), '');
67007
+ refnumStr_ori.substr(0, 1);
67008
+
67009
+ refnumStr = refnumStr_ori;
67010
+ refnum = parseInt(refnumStr);
67011
+ refnum3c = (refnum - parseInt(refnum/1000) * 1000).toString();
67012
+ refnum2c = (refnum - parseInt(refnum/100) * 100).toString();
67013
+
67014
+ // for extended strands, since A is 1550 and A+ is 1650, then the AA+ loop will be 1591, 1592, ... 1610, 1611, etc
67015
+ bSecThird9 = refnum3c.substr(0,1) == '9' || refnum2c.substr(0,1) == '9' || refnum2c.substr(0,1) == '0' || refnum2c.substr(0,1) == '1';
67016
+ if(bSecThird9) ic.residIgLoop[residueid] = 1;
67017
+
67018
+ strandPostfix = refnumStr.replace(refnum.toString(), '');
67019
+
67020
+ postfix = strandPostfix + '_' + index;
67021
+
67022
+ let firstTwo = parseInt(refnum.toString().substr(0, 2)); // check extended strands
67023
+ bExtendedStrand = refnum3c.substr(0,1) != '5' && firstTwo != '18'; // all strands and A' (18##)
67024
+
67025
+ if(currStrand && currStrand != ' ') {
67026
+ if(!bSecThird9 || (bExtendedStrand && !bSecThird9)) {
67027
+ let lastTwo = parseInt(refnum.toString().substr(refnum.toString().length - 2, 2));
67028
+
67029
+ if(currStrand != prevStrand) { // reset currCnt
67030
+ bFoundAnchor = false;
67031
+
67032
+ if(strandHash[currStrand + postfix]) {
67033
+ ++index;
67034
+ postfix = refnumStr.replace(refnum.toString(), '') + '_' + index;
67035
+ }
67036
+
67037
+ strandHash[currStrand + postfix] = 1;
67038
+
67039
+ strandArray[strandCnt] = {};
67040
+
67041
+ strandArray[strandCnt].startResi = currResi;
67042
+ strandArray[strandCnt].startRefnum = refnum; // 1250 in A1250a
67043
+
67044
+ resCntBfAnchor = 0;
67045
+
67046
+ strandArray[strandCnt].domainid = domainid;
67047
+
67048
+ strandArray[strandCnt].endResi = currResi;
67049
+ strandArray[strandCnt].endRefnum = refnum; // 1250a
67050
+
67051
+ if(lastTwo == 50) {
67052
+ strandArray[strandCnt].anchorRefnum = refnum;
67053
+ strandArray[strandCnt].resCntBfAnchor = resCntBfAnchor;
67054
+
67055
+ resCntAtAnchor = 0;
67056
+
67057
+ bFoundAnchor = true;
67058
+ }
67059
+
67060
+ // in case A1550 is not found, but A1551 is found
67061
+ if(!bFoundAnchor && (lastTwo == 51 || lastTwo == 52 || lastTwo == 53 || lastTwo == 54) ) {
67062
+ let offset = lastTwo - 50;
67063
+ strandArray[strandCnt].anchorRefnum = refnum - offset;
67064
+ strandArray[strandCnt].resCntBfAnchor = resCntBfAnchor - offset;
67065
+
67066
+ resCntAtAnchor = offset;
67067
+
67068
+ bFoundAnchor = true;
67069
+ }
67070
+
67071
+ if(bExtendedStrand) {
67072
+ strandArray[strandCnt].anchorRefnum = 0;
67073
+ }
67074
+
67075
+ strandArray[strandCnt].strandPostfix = strandPostfix; // a in A1250a
67076
+ strandArray[strandCnt].strand = currStrand; // A in A1250a
67077
+
67078
+ strandArray[strandCnt].postfix = postfix; // Aa_1
67079
+
67080
+ strandArray[strandCnt].loopResCnt = resCnt - 1;
67081
+
67082
+ ++strandCnt;
67083
+ resCnt = 0;
67084
+ }
67085
+ else {
67086
+ if(strandHash[currStrand + postfix]) {
67087
+ if(lastTwo == 50) {
67088
+ strandArray[strandCnt - 1].anchorRefnum = refnum;
67089
+ strandArray[strandCnt - 1].resCntBfAnchor = resCntBfAnchor;
67090
+
67091
+ // update
67092
+ strandArray[strandCnt - 1].startRefnum = strandArray[strandCnt - 1].anchorRefnum - strandArray[strandCnt - 1].resCntBfAnchor;
67093
+
67094
+ resCntAtAnchor = 0;
67095
+
67096
+ bFoundAnchor = true;
67097
+ }
67098
+
67099
+ // in case A1550 is not found, but A1551 is found
67100
+ if(!bFoundAnchor && (lastTwo == 51 || lastTwo == 52 || lastTwo == 53 || lastTwo == 54) ) {
67101
+ let offset = lastTwo - 50;
67102
+ strandArray[strandCnt - 1].anchorRefnum = refnum - offset;
67103
+ strandArray[strandCnt - 1].resCntBfAnchor = resCntBfAnchor - offset;
67104
+
67105
+ // update
67106
+ strandArray[strandCnt - 1].startRefnum = strandArray[strandCnt - 1].anchorRefnum - strandArray[strandCnt - 1].resCntBfAnchor;
67107
+
67108
+ resCntAtAnchor = offset;
67109
+
67110
+ bFoundAnchor = true;
67111
+ }
67112
+
67113
+ if(bExtendedStrand) {
67114
+ strandArray[strandCnt - 1].anchorRefnum = 0;
67115
+ }
67116
+
67117
+ strandArray[strandCnt - 1].domainid = domainid;
67118
+
67119
+ strandArray[strandCnt - 1].endResi = currResi;
67120
+ strandArray[strandCnt - 1].endRefnum = refnum; // 1250a
67121
+ strandArray[strandCnt - 1].resCntAtAnchor = resCntAtAnchor;
67122
+
67123
+ if(strandArray[strandCnt - 1].anchorRefnum) {
67124
+ strandArray[strandCnt - 1].endRefnum = strandArray[strandCnt - 1].anchorRefnum + strandArray[strandCnt - 1].resCntAtAnchor;
67125
+ }
67126
+
67127
+ resCnt = 0;
67128
+ }
67129
+ }
67130
+ }
67131
+ }
67132
+ }
67133
+
67134
+ prevStrand = currStrand;
67135
+ }
67136
+
67137
+ // 2. extend the strand to end of sheet
67138
+ let maxExtend = 8;
67139
+ for(let i = 0, il = strandArray.length; i < il; ++i) {
67140
+ let startAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[chnid + '_' + strandArray[i].startResi]);
67141
+ let endAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[chnid + '_' + strandArray[i].endResi]);
67142
+
67143
+ let startPos = ic.setSeqAlignCls.getPosFromResi(chnid, strandArray[i].startResi);
67144
+ let endPos = ic.setSeqAlignCls.getPosFromResi(chnid, strandArray[i].endResi);
67145
+
67146
+ if(startAtom.ss == 'sheet' && !startAtom.ssbegin) {
67147
+ for(let j = 1; j <= maxExtend; ++j) {
67148
+ let currPos = startPos - j;
67149
+ let currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
67150
+ if(i > 0 && parseInt(currResi) <= parseInt(strandArray[i-1].endResi)) break;
67151
+
67152
+ let currResid = chnid + '_' + currResi;
67153
+ let currAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[currResid]);
67154
+ let domainid = ic.resid2domainid[currResid];
67155
+ if(currAtom.ssbegin) { // find the start of the sheet
67156
+ // update the following: startResi,startRefnum,endResi,endRefnum,loopResCnt,resCntBfAnchor,resCntAtAnchor
67157
+ strandArray[i].startResi = currResi;
67158
+ strandArray[i].startRefnum -= j;
67159
+ strandArray[i].loopResCnt -= j;
67160
+ if(strandArray[i].loopResCnt < 0) strandArray[i].loopResCnt = 0;
67161
+ strandArray[i].resCntBfAnchor += j;
67162
+
67163
+ // update ic.resid2refnum
67164
+ for(let k = 1; k <= j; ++k) {
67165
+ currPos = startPos - k;
67166
+ currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
67167
+ let currResid = chnid + '_' + currResi;
67168
+ delete ic.residIgLoop[currResid];
67169
+ ic.resid2domainid[currResid] = domainid;
67170
+ }
67171
+
67172
+ break;
67173
+ }
67174
+ }
67175
+ }
67176
+
67177
+ if(endAtom.ss == 'sheet' && !endAtom.ssend) {
67178
+ for(let j = 1; j <= maxExtend; ++j) {
67179
+ let currPos = endPos + j;
67180
+ let currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
67181
+ if(i < il - 1 && parseInt(currResi) >= parseInt(strandArray[i+1].startResi)) break;
67182
+
67183
+ let currResid = chnid + '_' + currResi;
67184
+ let currAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[currResid]);
67185
+ let domainid = ic.resid2domainid[currResid];
67186
+ if(currAtom.ssend) { // find the end of the sheet
67187
+ // update the following: startResi,startRefnum,endResi,endRefnum,loopResCnt,resCntBfAnchor,resCntAtAnchor
67188
+ strandArray[i].endResi = currResi;
67189
+ strandArray[i].endRefnum += j;
67190
+ if(i < il - 1) {
67191
+ strandArray[i + 1].loopResCnt -= j;
67192
+ if(strandArray[i + 1].loopResCnt < 0) strandArray[i + 1].loopResCnt = 0;
67193
+ }
67194
+ strandArray[i].resCntAtAnchor += j;
67195
+
67196
+ // update ic.residIgLoop[resid];
67197
+ for(let k = 1; k <= j; ++k) {
67198
+ currPos = endPos + k;
67199
+ currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
67200
+ let currResid = chnid + '_' + currResi;
67201
+ delete ic.residIgLoop[currResid];
67202
+ ic.resid2domainid[currResid] = domainid;
67203
+ }
67204
+
67205
+ break;
67206
+ }
67207
+ }
67208
+ }
67209
+ }
67210
+
67211
+ // 2b. remove strands with less than 3 residues except G strand
67212
+ for(let il = strandArray.length, i = il - 1; i >= 0; --i) {
67213
+ let strandTmp = strandArray[i].strand.substr(0, 1);
67214
+ if(strandTmp != 'G' && strandArray[i].endRefnum - strandArray[i].startRefnum + 1 < 3) { // remove the strand
67215
+ if(strandTmp == 'B' || strandTmp == 'C' || strandTmp == 'E' || strandTmp == 'F') {
67216
+ if(!me.bNode) console.log("Some of the Ig strands B, C, E, F are removed since they are too short...");
67217
+ return false;
67218
+ }
67219
+
67220
+ if(i != il - 1) { // modify
67221
+ strandArray[i + 1].loopResCnt += strandArray[i].loopResCnt + parseInt(strandArray[i].endResi) - parseInt(strandArray[i].startResi) + 1;
67222
+ }
67223
+
67224
+ strandArray.splice(i, 1);
67225
+ }
67226
+ }
67227
+
67228
+ // 3. assign refnumLabel for each resid
67229
+ strandCnt = 0;
67230
+ let loopCnt = 0;
67231
+
67232
+ let bBeforeAstrand = true, bAfterGstrand = true, refnumLabelNoPostfix, prevStrandCnt = 0, currRefnum;
67233
+ bStart = false;
67234
+ let refnumInStrand = 0;
67235
+ if(strandArray.length > 0) {
67236
+ for(let i = 0, il = giSeq.length; i < il; ++i, ++loopCnt, ++refnumInStrand) {
67237
+ let currResi = ic.ParserUtilsCls.getResi(chnid, i);
67238
+ let residueid = chnid + '_' + currResi;
67239
+ refnumLabel = ic.resid2refnum[residueid];
67240
+
67241
+ currStrand = strandArray[strandCnt].strand;
67242
+
67243
+ let domainid;
67244
+
67245
+ if(refnumLabel) {
67246
+ domainid = ic.resid2domainid[residueid];
67247
+
67248
+ refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
67249
+ currRefnum = parseInt(refnumStr);
67250
+ refnumLabelNoPostfix = currStrand + currRefnum;
67251
+
67252
+ currStrand = refnumLabel.replace(new RegExp(refnumStr,'g'), '');
67253
+
67254
+ let firstChar = refnumLabel.substr(0,1);
67255
+ if(!bStart && (firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
67256
+ bStart = true;
67257
+ bBeforeAstrand = true;
67258
+ loopCnt = 0;
67259
+ }
67260
+ }
67261
+
67262
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[residueid]);
67263
+
67264
+ // skip non-protein residues
67265
+ if(!atom || !ic.proteins.hasOwnProperty(atom.serial)) {
67266
+ refnumLabel = undefined;
67267
+ }
67268
+ else {
67269
+ let bBefore = false, bInRange= false, bAfter = false;
67270
+ // 100, 100A
67271
+ if(parseInt(currResi) == parseInt(strandArray[strandCnt].startResi) && currResi != strandArray[strandCnt].startResi) {
67272
+ bBefore = currResi < strandArray[strandCnt].startResi;
67273
+ }
67274
+ else {
67275
+ bBefore = parseInt(currResi) < parseInt(strandArray[strandCnt].startResi);
67276
+ }
67277
+
67278
+ // 100, 100A
67279
+ if(parseInt(currResi) == parseInt(strandArray[strandCnt].endResi) && currResi != strandArray[strandCnt].endResi) {
67280
+ bAfter = currResi > strandArray[strandCnt].endResi;
67281
+ }
67282
+ else {
67283
+ bAfter = parseInt(currResi) > parseInt(strandArray[strandCnt].endResi);
67284
+ }
67285
+
67286
+ bInRange = (!bBefore && !bAfter) ? true : false;
67287
+
67288
+ if(bBefore) {
67289
+ ic.residIgLoop[residueid] = 1;
67290
+
67291
+ if(bBeforeAstrand) { // make it continuous to the 1st strand
67292
+ if(bStart) {
67293
+ currRefnum = strandArray[strandCnt].startRefnum - strandArray[strandCnt].loopResCnt + loopCnt;
67294
+ refnumLabelNoPostfix = strandArray[strandCnt].strand + currRefnum;
67295
+ refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
67296
+ domainid = strandArray[strandCnt].domainid;
67297
+ }
67298
+ else {
67299
+ //loopCnt = 0;
67300
+ refnumLabelNoPostfix = undefined;
67301
+ refnumLabel = undefined;
67302
+ }
67303
+ }
67304
+ else {
67305
+ if(prevStrandCnt >= 0
67306
+ // && (strandArray[prevStrandCnt].strand.substr(0, 1) == 'F' || strandArray[prevStrandCnt].strand.substr(0, 1) == 'G')) {
67307
+ && (strandArray[prevStrandCnt].strand.substr(0, 1) == 'G')) {
67308
+ if(!bAfterGstrand) {
67309
+ //loopCnt = 0;
67310
+ refnumLabelNoPostfix = undefined;
67311
+ refnumLabel = undefined;
67312
+ }
67313
+ else {
67314
+ if(bStart && ic.resid2refnum[residueid]) {
67315
+ bAfterGstrand = true;
67316
+
67317
+ currRefnum = strandArray[prevStrandCnt].endRefnum + loopCnt;
67318
+ refnumLabelNoPostfix = strandArray[prevStrandCnt].strand + currRefnum;
67319
+ refnumLabel = refnumLabelNoPostfix + strandArray[prevStrandCnt].strandPostfix;
67320
+ domainid = strandArray[prevStrandCnt].domainid;
67321
+ }
67322
+ else {
67323
+ bStart = false;
67324
+ bBeforeAstrand = true;
67325
+ //loopCnt = 0;
67326
+
67327
+ bAfterGstrand = false;
67328
+
67329
+ refnumLabelNoPostfix = undefined;
67330
+ refnumLabel = undefined;
67331
+ }
67332
+ }
67333
+ }
67334
+ else {
67335
+ bAfterGstrand = true; // reset
67336
+
67337
+ let len = strandArray[strandCnt].loopResCnt;
67338
+ let halfLen = parseInt(len / 2.0 + 0.5);
67339
+
67340
+ if(loopCnt <= halfLen) {
67341
+ currRefnum = strandArray[prevStrandCnt].endRefnum + loopCnt;
67342
+ refnumLabelNoPostfix = strandArray[prevStrandCnt].strand + currRefnum;
67343
+ refnumLabel = refnumLabelNoPostfix + strandArray[prevStrandCnt].strandPostfix;
67344
+ domainid = strandArray[prevStrandCnt].domainid;
67345
+ }
67346
+ else {
67347
+ currRefnum = strandArray[strandCnt].startRefnum - len + loopCnt - 1;
67348
+ refnumLabelNoPostfix = strandArray[strandCnt].strand + currRefnum;
67349
+ refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
67350
+ domainid = strandArray[strandCnt].domainid;
67351
+ }
67352
+ }
67353
+ }
67354
+ }
67355
+ else if(bInRange) {
67356
+ // not in loop any more if you assign ref numbers multiple times
67357
+ //delete ic.residIgLoop[residueid];
67358
+
67359
+ bBeforeAstrand = false;
67360
+
67361
+ if(strandArray[strandCnt].anchorRefnum) { // use anchor to name refnum
67362
+ if(currResi == strandArray[strandCnt].startResi) {
67363
+ refnumInStrand = strandArray[strandCnt].anchorRefnum - strandArray[strandCnt].resCntBfAnchor;
67364
+ strandArray[strandCnt].startRefnum = refnumInStrand;
67365
+ }
67366
+ else if(currResi == strandArray[strandCnt].endResi) {
67367
+ strandArray[strandCnt].endRefnum = refnumInStrand;
67368
+ }
67369
+
67370
+ refnumLabelNoPostfix = strandArray[strandCnt].strand + refnumInStrand;
67371
+ refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
67372
+ domainid = strandArray[strandCnt].domainid;
67373
+ }
67374
+
67375
+ if(currResi == strandArray[strandCnt].endResi) {
67376
+ ++strandCnt; // next strand
67377
+ loopCnt = 0;
67378
+
67379
+ if(!strandArray[strandCnt]) { // last strand
67380
+ --strandCnt;
67381
+ }
67382
+ }
67383
+ }
67384
+ else if(bAfter) {
67385
+ ic.residIgLoop[residueid] = 1;
67386
+
67387
+ if(!bAfterGstrand) {
67388
+ refnumLabelNoPostfix = undefined;
67389
+ refnumLabel = undefined;
67390
+ }
67391
+ else {
67392
+ // C-terminal
67393
+ if(!ic.resid2refnum[residueid]) {
67394
+ bAfterGstrand = false;
67395
+
67396
+ refnumLabelNoPostfix = undefined;
67397
+ refnumLabel = undefined;
67398
+ }
67399
+ else {
67400
+ bAfterGstrand = true;
67401
+
67402
+ currRefnum = strandArray[strandCnt].endRefnum + loopCnt;
67403
+ refnumLabelNoPostfix = strandArray[strandCnt].strand + currRefnum;
67404
+ refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
67405
+ domainid = strandArray[strandCnt].domainid;
67406
+ }
67407
+ }
67408
+ }
67409
+ }
67410
+
67411
+ prevStrand = currStrand;
67412
+ prevStrandCnt = strandCnt - 1;
67413
+
67414
+ // assign the adjusted reference numbers
67415
+ ic.resid2refnum[residueid] = refnumLabel;
67416
+ ic.resid2domainid[residueid] = domainid;
67417
+
67418
+ refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
67419
+
67420
+ if(!ic.refnum2residArray.hasOwnProperty(refnumStr)) {
67421
+ ic.refnum2residArray[refnumStr] = [residueid];
67422
+ }
67423
+ else {
67424
+ ic.refnum2residArray[refnumStr].push(residueid);
67425
+ }
67426
+
67427
+ if(!ic.chainsMapping.hasOwnProperty(chnid)) {
67428
+ ic.chainsMapping[chnid] = {};
67429
+ }
67430
+
67431
+ // remove the postfix when comparing interactions
67432
+ //ic.chainsMapping[chnid][residueid] = refnumLabel;
67433
+ ic.chainsMapping[chnid][residueid] = refnumLabelNoPostfix;
67434
+ }
67435
+ }
67436
+
67437
+ return true;
67438
+ }
67264
67439
  }
67265
67440
 
67266
67441
  /**