icn3d 3.29.13 → 3.29.15

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,7 +36882,7 @@ 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
36888
  if(titleArray) {
@@ -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);
38244
37807
 
38245
- if(me.bNode) return {html: '', html2: '', html3: ''};
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);
37823
+
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
+ }
38340
37936
 
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;
37937
+ html2 += htmlCnt;
38345
37938
 
38346
- let result = ic.annoCddSiteCls.setDomainFeature(rangeArray, chnid, 'ig', htmlTmp, htmlTmp2, htmlTmp3, undefined, titleArray, fullTitleArray);
37939
+ html2 += '</div></div>';
37940
+ html3 += '</div></div>';
38347
37941
 
38348
- html += result.html + '</div>';
38349
- html2 += result.html2 + '</div>';
38350
- html3 += result.html3 + '</div>';
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;
37946
+
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
  }
@@ -43292,7 +42894,8 @@ class Annotation {
43292
42894
 
43293
42895
  ic.hlUpdateCls.updateHlAll();
43294
42896
  ic.drawCls.draw();
43295
- }
42897
+ }
42898
+
43296
42899
  }
43297
42900
  }
43298
42901
 
@@ -52902,7 +52505,7 @@ class PdbParser {
52902
52505
  //Load structures from a "URL". Due to the same domain policy of Ajax call, the URL should be in the same
52903
52506
  //domain. "type" could be "pdb", "mol2", "sdf", "xyz", "icn3dpng", or "pae"
52904
52507
  //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;
52508
+ async downloadUrl(url, type, command, template) { let ic = this.icn3d, me = ic.icn3dui;
52906
52509
  let pos = url.lastIndexOf('/');
52907
52510
  if(pos != -1) {
52908
52511
  let posDot = url.lastIndexOf('.');
@@ -52920,9 +52523,19 @@ class PdbParser {
52920
52523
  ic.InputfileData = (ic.InputfileData) ? ic.InputfileData + '\nENDMDL\n' + data : data;
52921
52524
  ic.InputfileType = type;
52922
52525
 
52526
+ // append
52527
+ ic.hAtoms = {};
52528
+ ic.dAtoms = {};
52529
+
52530
+ ic.resetConfig();
52531
+ ic.bResetAnno = true;
52532
+ ic.bResetSets = true;
52533
+
52923
52534
  if(type === 'pdb') {
52924
- await this.loadPdbData(data);
52925
- //await ic.loadScriptCls.loadScript(command, undefined, true);
52535
+ // await this.loadPdbData(data);
52536
+ let bAppend = true;
52537
+ let id = (template) ? template.replace(/_/g, '').substr(0, 4) : undefined;
52538
+ await this.loadPdbData(data, id, undefined, bAppend);
52926
52539
  }
52927
52540
  else if(type === 'mmcif') {
52928
52541
  let url = me.htmlCls.baseUrl + "mmcifparser/mmcifparser.cgi";
@@ -52950,6 +52563,17 @@ class PdbParser {
52950
52563
  let bFull = true;
52951
52564
  ic.contactMapCls.processAfErrorMap(JSON.parse(data), bFull);
52952
52565
  }
52566
+
52567
+ //append
52568
+ if(ic.bSetChainsAdvancedMenu) ic.definedSetsCls.showSets();
52569
+
52570
+ ic.bResetAnno = true;
52571
+
52572
+ if(ic.bAnnoShown) {
52573
+ await ic.showAnnoCls.showAnnotations();
52574
+
52575
+ ic.annotationCls.resetAnnoTabAll();
52576
+ }
52953
52577
  }
52954
52578
 
52955
52579
  //Atom "data" from PDB file was parsed to set up parameters for the 3D viewer. The deferred parameter
@@ -66104,7 +65728,7 @@ class Dssp {
66104
65728
  ic.ref2igtype['BArrestin1_4jqiA_rat_n1'] = 'IgFN3-like';
66105
65729
  ic.ref2igtype['BTLA_2aw2A_human_Iset'] = 'IgI';
66106
65730
  ic.ref2igtype['C3_2qkiD_human_n1'] = 'IgFN3-like';
66107
- ic.ref2igtype['CD19_6al5A_human_C2orV-n1'] = 'other Ig'; //'CD19';
65731
+ ic.ref2igtype['CD19_6al5A_human_C2orV-n1'] = 'CD19';
66108
65732
  ic.ref2igtype['CD28_1yjdC_human_V'] = 'IgV';
66109
65733
  ic.ref2igtype['CD2_1hnfA_human_C2-n2'] = 'IgC2';
66110
65734
  ic.ref2igtype['CD2_1hnfA_human_V-n1'] = 'IgV';
@@ -66115,8 +65739,8 @@ class Dssp {
66115
65739
  ic.ref2igtype['CoAtomerGamma1_1r4xA_human'] = 'IgE';
66116
65740
  ic.ref2igtype['Contactin1_2ee2A_human_FN3-n9'] = 'IgFN3';
66117
65741
  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';
65742
+ ic.ref2igtype['CuZnSuperoxideDismutase_1hl5C_human'] = 'SOD';
65743
+ ic.ref2igtype['ECadherin_4zt1A_human_n2'] = 'Cadherin';
66120
65744
  ic.ref2igtype['Endo-1,4-BetaXylanase10A_1i8aA_bacteria_n4'] = 'IgE';
66121
65745
  ic.ref2igtype['FAB-HEAVY_5esv_C1-n2'] = 'IgC1';
66122
65746
  ic.ref2igtype['FAB-HEAVY_5esv_V-n1'] = 'IgV';
@@ -66132,12 +65756,12 @@ class Dssp {
66132
65756
  ic.ref2igtype['JAM1_1nbqA_human_VorIset-n2'] = 'IgI';
66133
65757
  ic.ref2igtype['LAG3_7tzgD_human_C2-n2'] = 'IgC2';
66134
65758
  ic.ref2igtype['LAG3_7tzgD_human_V-n1'] = 'IgV';
66135
- ic.ref2igtype['LaminAC_1ifrA_human'] = 'other Ig'; //'Lamin';
65759
+ ic.ref2igtype['LaminAC_1ifrA_human'] = 'Lamin';
66136
65760
  ic.ref2igtype['MHCIa_7phrH_human_C1'] = 'IgC1';
66137
65761
  ic.ref2igtype['MPT63_1lmiA_bacteria'] = 'IgE';
66138
65762
  ic.ref2igtype['NaCaExchanger_2fwuA_dog_n2'] = 'IgE';
66139
65763
  ic.ref2igtype['NaKATPaseTransporterBeta_2zxeB_spurdogshark'] = 'IgE';
66140
- ic.ref2igtype['ORF7a_1xakA_virus'] = 'other Ig'; //'ORF';
65764
+ ic.ref2igtype['ORF7a_1xakA_virus'] = 'ORF';
66141
65765
  ic.ref2igtype['PD1_4zqkB_human_V'] = 'IgV';
66142
65766
  ic.ref2igtype['PDL1_4z18B_human_V-n1'] = 'IgV';
66143
65767
  ic.ref2igtype['Palladin_2dm3A_human_Iset-n1'] = 'IgI';
@@ -66188,7 +65812,7 @@ class Dssp {
66188
65812
  let numRound = 0;
66189
65813
 
66190
65814
  //while(!bNoMoreIg) {
66191
- while(!bNoMoreIg && numRound < 10) {
65815
+ while(!bNoMoreIg && numRound < 15) {
66192
65816
  let bRerun = true;
66193
65817
  bNoMoreIg = await thisClass.parseRefPdbData(ic.pdbDataArray, template, bRerun);
66194
65818
  ++numRound;
@@ -66227,7 +65851,7 @@ class Dssp {
66227
65851
  for(let j = 0, jl = chainidArray.length; j < jl; ++j) {
66228
65852
  let chainid = chainidArray[j];
66229
65853
 
66230
- // for selected atoms only, assign ic.resid2domainid[resid]
65854
+ // for selected atoms only
66231
65855
  let domainAtomsArray = this.getDomainAtomsArray(chainid, bRerun);
66232
65856
 
66233
65857
  if(!ic.domainid2refpdbname) ic.domainid2refpdbname = {};
@@ -66268,7 +65892,7 @@ class Dssp {
66268
65892
  }
66269
65893
  }
66270
65894
  else {
66271
- ic.domainid2refpdbname[domainid] = template;
65895
+ ic.domainid2refpdbname[domainid] = [template];
66272
65896
  domainidpairArray.push(domainid + "|1" + template); // "1" was added for the first round strand-only template
66273
65897
  }
66274
65898
  }
@@ -66308,9 +65932,6 @@ class Dssp {
66308
65932
  let pdbDataArray = await this.promiseWithFixedJobs(pdbAjaxArray);
66309
65933
 
66310
65934
  for(let domainid in ic.domainid2refpdbname) {
66311
- ic.domainid2refpdbname[domainid];
66312
- domainid.substr(0, domainid.indexOf(','));
66313
-
66314
65935
  let pdb_target = ic.domainid2pdb[domainid];
66315
65936
  for(let index = 0, indexl = pdbDataArray.length; index < indexl; ++index) {
66316
65937
  let struct2 = ic.defaultPdbId + index;
@@ -66371,12 +65992,10 @@ class Dssp {
66371
65992
 
66372
65993
  if(bRerunDomain) {
66373
65994
  let atomsAssigned = {};
65995
+ //ic.resid2refnum_ori should be used
66374
65996
  for(let resid in ic.resid2refnum_ori) {
66375
65997
  atomsAssigned = me.hashUtilsCls.unionHash(atomsAssigned, ic.residues[resid]);
66376
65998
  }
66377
- // for(let resid in ic.resid2refnum) {
66378
- // if(ic.resid2refnum[resid]) atomsAssigned = me.hashUtilsCls.unionHash(atomsAssigned, ic.residues[resid]);
66379
- // }
66380
65999
 
66381
66000
  currAtoms = me.hashUtilsCls.exclHash(currAtoms, atomsAssigned);
66382
66001
 
@@ -66400,19 +66019,12 @@ class Dssp {
66400
66019
  if(subdomains.length <= 1) {
66401
66020
  let residueArray = ic.resid2specCls.atoms2residues(Object.keys(currAtoms));
66402
66021
  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
- */
66022
+
66408
66023
  for(let n = 0, nl = residueArray.length; n < nl; ++n) {
66409
66024
  let resid = residueArray[n];
66410
- /*
66411
- ic.resid2domainid[resid] = chainid + ',0' + '_' + resiSum;
66412
- */
66025
+
66413
66026
  // clear previous refnum assignment if any
66414
- // if(!bRerunDomain && ic.resid2refnum && ic.resid2refnum[resid]) {
66415
- // if(ic.resid2refnum && ic.resid2refnum[resid]) {
66027
+ // if(bRerunDomain) {
66416
66028
  delete ic.resid2refnum[resid];
66417
66029
  delete ic.residIgLoop[resid];
66418
66030
  // }
@@ -66433,11 +66045,9 @@ class Dssp {
66433
66045
  let resid = chainid + '_' + pos2resi[n];
66434
66046
  ++resCnt;
66435
66047
  domainAtoms = me.hashUtilsCls.unionHash(domainAtoms, ic.residues[resid]);
66436
- //ic.resid2domainid[resid] = chainid + '-' + k;
66437
66048
 
66438
66049
  // clear previous refnum assignment if any
66439
- // if(!bRerunDomain && ic.resid2refnum && ic.resid2refnum[resid]) {
66440
- // if(ic.resid2refnum && ic.resid2refnum[resid]) {
66050
+ // if(bRerunDomain) {
66441
66051
  delete ic.resid2refnum[resid];
66442
66052
  delete ic.residIgLoop[resid];
66443
66053
  // }
@@ -66471,7 +66081,7 @@ class Dssp {
66471
66081
  getTemplateList(domainid) { let ic = this.icn3d; ic.icn3dui;
66472
66082
  let refpdbname = '', score = '', seqid = '', nresAlign = '';
66473
66083
 
66474
- refpdbname = ic.domainid2refpdbname[domainid];
66084
+ refpdbname = ic.domainid2refpdbname[domainid][0]; // one template in round 2
66475
66085
 
66476
66086
  if(ic.domainid2score[domainid]) {
66477
66087
  let itemArray = ic.domainid2score[domainid].split('_');
@@ -66491,6 +66101,8 @@ class Dssp {
66491
66101
 
66492
66102
  // find the best alignment for each chain
66493
66103
  let domainid2segs = {};
66104
+ let domainid2strandcnt = {};
66105
+ let domainid2refpdbnamelist = {};
66494
66106
 
66495
66107
  if(!ic.chainid2refpdbname) ic.chainid2refpdbname = {};
66496
66108
  // if(!ic.chainid2score) ic.chainid2score = {};
@@ -66583,7 +66195,7 @@ class Dssp {
66583
66195
  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
66196
  if(!me.bNode && !(bBSheet && bCSheet && bESheet && bFSheet)) console.log("Some of the Ig strands B, C, E, F are not beta sheets...");
66585
66197
  // 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) {
66198
+ if(ic.domainid2refpdbname[domainid][0] == refpdbname) {
66587
66199
  delete ic.domainid2refpdbname[domainid];
66588
66200
  delete ic.domainid2score[domainid];
66589
66201
  }
@@ -66595,21 +66207,65 @@ class Dssp {
66595
66207
  if(!me.bNode) console.log("domainid: " + domainid);
66596
66208
  }
66597
66209
 
66598
- if(!domainid2segs.hasOwnProperty(domainid) || queryData[0].score >= ic.domainid2score[domainid].split('_')[0]) {
66210
+ // count the number of matched strands
66211
+ let strandHash = {};
66212
+ for(let j = 0, jl = queryData[0].segs.length; j < jl; ++j) {
66213
+ let seg = queryData[0].segs[j];
66214
+ let q_start = parseInt(seg.q_start);
66215
+
66216
+ let strand = this.getStrandFromRefnum(q_start);
66217
+ strandHash[strand] = 1;
66218
+ }
66219
+ let score = parseFloat(queryData[0].score);
66220
+ //!!!
66221
+ // if the TM score difference is within 0.1 and more strands are found, use the template with more strands
66222
+ // if(!domainid2segs.hasOwnProperty(domainid) ||
66223
+ // (score >= parseFloat(ic.domainid2score[domainid].split('_')[0]) + tmAdjust)
66224
+ // || (score >= parseFloat(ic.domainid2score[domainid].split('_')[0]) - tmAdjust && score < parseFloat(ic.domainid2score[domainid].split('_')[0]) + tmAdjust && Object.keys(strandHash).length > domainid2strandcnt[domainid])
66225
+ // ) {
66226
+
66227
+ // use TM-score alone
66228
+ if(!domainid2segs.hasOwnProperty(domainid) || score >= parseFloat(ic.domainid2score[domainid].split('_')[0])) {
66599
66229
  ic.domainid2score[domainid] = queryData[0].score + '_' + queryData[0].frac_identical + '_' + queryData[0].num_res ;
66230
+
66600
66231
  if(bRound1) {
66601
- ic.domainid2refpdbname[domainid] = parseFloat(queryData[0].score) > 0.75 ? refpdbname : 'all_templates';
66232
+ ic.domainid2refpdbname[domainid] = score > 0.75 ? [refpdbname] : ['all_templates'];
66602
66233
  }
66603
66234
  else {
66604
- ic.domainid2refpdbname[domainid] = refpdbname;
66235
+ ic.domainid2refpdbname[domainid] = [refpdbname];
66605
66236
  }
66237
+
66606
66238
  domainid2segs[domainid] = queryData[0].segs;
66239
+ domainid2strandcnt[domainid] = Object.keys(strandHash).length;
66240
+
66607
66241
  ic.domainid2ig2kabat[domainid] = queryData[0].ig2kabat;
66608
66242
  ic.domainid2ig2imgt[domainid] = queryData[0].ig2imgt;
66609
66243
  }
66610
- }
66611
66244
 
66612
- return domainid2segs;
66245
+ if(bRound1) {
66246
+ if(!domainid2refpdbnamelist[domainid]) domainid2refpdbnamelist[domainid] = {};
66247
+ domainid2refpdbnamelist[domainid][refpdbname] = score;
66248
+ }
66249
+ }
66250
+ /* !!!
66251
+ // combine the top three clusters for the 2nd round alignment
66252
+ if(bRound1) {
66253
+ for(let domainid in domainid2refpdbnamelist) {
66254
+ console.log("###score " + ic.domainid2score[domainid].split('_')[0] + " ic.domainid2refpdbname[domainid][0] " + ic.domainid2refpdbname[domainid][0])
66255
+ if(!me.bNode && ic.domainid2refpdbname[domainid][0] == 'all_templates') {
66256
+ let refpdbname2score = domainid2refpdbnamelist[domainid];
66257
+ let refpdbnameList = Object.keys(refpdbname2score);
66258
+ refpdbnameList.sort(function(a, b) {
66259
+ return refpdbname2score[b] - refpdbname2score[a]
66260
+ });
66261
+ // top 3 templates
66262
+ ic.domainid2refpdbname[domainid] = refpdbnameList.slice(0,3);
66263
+ }
66264
+ console.log("###bb ic.domainid2refpdbname[domainid] " + ic.domainid2refpdbname[domainid])
66265
+ }
66266
+ }
66267
+ */
66268
+ return domainid2segs; // only used in round 2
66613
66269
  }
66614
66270
 
66615
66271
  async parseAlignData(dataArray, domainidpairArray, bRound1) { let ic = this.icn3d, me = ic.icn3dui;
@@ -66617,6 +66273,7 @@ class Dssp {
66617
66273
 
66618
66274
  let domainid2segs = this.parseAlignData_part1(dataArray, domainidpairArray, bRound1);
66619
66275
 
66276
+ // !!!no more Igs to detect
66620
66277
  if(Object.keys(domainid2segs).length == 0) {
66621
66278
  bNoMoreIg = true;
66622
66279
  return bNoMoreIg;
@@ -66631,25 +66288,30 @@ class Dssp {
66631
66288
  let urltmalign = me.htmlCls.tmalignUrl;
66632
66289
  for(let domainid in ic.domainid2refpdbname) {
66633
66290
  let pdbAjaxArray = [];
66634
- let refpdbname = ic.domainid2refpdbname[domainid];
66291
+ let refpdbnameList = ic.domainid2refpdbname[domainid];
66635
66292
  //let pdbid = domainid.substr(0, domainid.indexOf('_'));
66636
66293
  let chainid = domainid.substr(0, domainid.indexOf(','));
66637
66294
 
66638
- //if(ic.refpdbHash.hasOwnProperty(pdbid)) {
66639
66295
  if(ic.refpdbHash.hasOwnProperty(chainid)) {
66640
- // use itself as the ref structure
66641
- //refpdbname = pdbid;
66642
- refpdbname = chainid;
66296
+ refpdbnameList = [chainid];
66643
66297
 
66644
- if(!me.bNode) console.log("Adjusted refpdbname for domainid " + domainid + ": " + refpdbname);
66298
+ if(!me.bNode) console.log("Adjusted refpdbname for domainid " + domainid + ": " + chainid);
66645
66299
  }
66646
66300
 
66647
- if(!ic.refpdbHash[refpdbname]) {
66301
+ let templates = [];
66302
+ for(let i = 0, il = refpdbnameList.length; i < il; ++i) {
66303
+ let refpdbname = refpdbnameList[i];
66304
+ if(!ic.refpdbHash[refpdbname]) continue;
66305
+ templates = templates.concat(ic.refpdbHash[refpdbname]);
66306
+ }
66307
+
66308
+ // if(!ic.refpdbHash[refpdbname]) {
66309
+ if(templates.length == 0) {
66648
66310
  continue;
66649
66311
  }
66650
66312
 
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];
66313
+ for(let k = 0, kl = templates.length; k < kl; ++k) {
66314
+ let urlpdb = me.htmlCls.baseUrl + "mmcifparser/mmcifparser.cgi?refpdbid=" + templates[k];
66653
66315
 
66654
66316
  let pdbAjax = me.getAjaxPromise(urlpdb, 'text');
66655
66317
 
@@ -66669,12 +66331,11 @@ class Dssp {
66669
66331
  let header = 'HEADER ' + struct2 + '\n';
66670
66332
  pdb_query = header + pdb_query;
66671
66333
 
66672
- let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target, "queryid": ic.refpdbHash[refpdbname][index]};
66334
+ let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target, "queryid": templates[index]};
66673
66335
  let alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
66674
66336
  ajaxArray.push(alignAjax);
66675
66337
 
66676
- //domainidpairArray3.push(domainid + "," + refpdbname);
66677
- domainidpairArray3.push(domainid + "|" + ic.refpdbHash[refpdbname][index]);
66338
+ domainidpairArray3.push(domainid + "|" + templates[index]);
66678
66339
  }
66679
66340
  }
66680
66341
 
@@ -66690,19 +66351,19 @@ class Dssp {
66690
66351
  return bNoMoreIg;
66691
66352
  }
66692
66353
 
66693
- await this.parseAlignData_part3(domainid2segs);
66354
+ this.parseAlignData_part3(domainid2segs);
66694
66355
 
66695
66356
  return bNoMoreIg;
66696
66357
  }
66697
66358
 
66698
- async parseAlignData_part3(domainid2segs) { let ic = this.icn3d, me = ic.icn3dui;
66359
+ parseAlignData_part3(domainid2segs) { let ic = this.icn3d, me = ic.icn3dui;
66699
66360
 
66700
66361
  // combine domainid into chainid
66701
66362
  let processedChainid = {};
66702
66363
 
66703
66364
  for(let domainid in ic.domainid2refpdbname) {
66704
66365
  // remove the first round template
66705
- if(ic.domainid2refpdbname[domainid].substr(0,1) == '1') {
66366
+ if(ic.domainid2refpdbname[domainid][0].substr(0,1) == '1') {
66706
66367
  delete ic.domainid2refpdbname[domainid];
66707
66368
  delete ic.domainid2score[domainid];
66708
66369
  continue;
@@ -66717,7 +66378,7 @@ class Dssp {
66717
66378
  processedChainid[chainid] = 1;
66718
66379
 
66719
66380
  if(!ic.chainid2refpdbname.hasOwnProperty(chainid)) ic.chainid2refpdbname[chainid] = [];
66720
- ic.chainid2refpdbname[chainid].push(ic.domainid2refpdbname[domainid] + '|' + domainid);
66381
+ ic.chainid2refpdbname[chainid].push(ic.domainid2refpdbname[domainid][0] + '|' + domainid);
66721
66382
 
66722
66383
  // if(!ic.chainid2score.hasOwnProperty(chainid)) ic.chainid2score[chainid] = [];
66723
66384
  // ic.chainid2score[chainid].push(ic.domainid2score[domainid] + '|' + domainid);
@@ -66747,9 +66408,6 @@ class Dssp {
66747
66408
  let segArray = domainid2segs[domainid];
66748
66409
  let chainid = domainid.split(',')[0];
66749
66410
 
66750
- // let refpdbnameArray = ic.chainid2refpdbname[chainid];
66751
-
66752
- // let result = this.getTemplateList(chainid);
66753
66411
  let result = this.getTemplateList(domainid);
66754
66412
  let refpdbname = result.refpdbname;
66755
66413
  let score = result.score;
@@ -66917,6 +66575,15 @@ class Dssp {
66917
66575
  }
66918
66576
  }
66919
66577
 
66578
+ if(!ic.chainid2igtrack) ic.chainid2igtrack = {};
66579
+ for(let chainid in ic.chains) {
66580
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chainid]);
66581
+ if(ic.proteins.hasOwnProperty(atom.serial)) {
66582
+ let giSeq = ic.showSeqCls.getSeq(chainid);
66583
+ ic.chainid2igtrack[chainid] = this.ajdustRefnum(giSeq, chainid);
66584
+ }
66585
+ }
66586
+
66920
66587
  /*
66921
66588
  if(Object.keys(ic.resid2refnum).length > 0) {
66922
66589
  ic.bShowRefnum = true;
@@ -66946,7 +66613,7 @@ class Dssp {
66946
66613
  */
66947
66614
  }
66948
66615
 
66949
- getLabelFromRefnum(oriRefnum, prevStrand) { let ic = this.icn3d; ic.icn3dui;
66616
+ getStrandFromRefnum(oriRefnum, prevStrand) { let ic = this.icn3d; ic.icn3dui;
66950
66617
  let refnum = parseInt(oriRefnum);
66951
66618
 
66952
66619
  //N-terminus = 0999-0001
@@ -66973,33 +66640,44 @@ class Dssp {
66973
66640
 
66974
66641
  // loops may have numbers such as 1310, 1410
66975
66642
 
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
66643
+ let strand;
66644
+
66645
+ if(refnum < 1000) strand = undefined;
66646
+ else if(refnum >= 1200 && refnum < 1290) strand = "A---";
66647
+ else if(refnum >= 1320 && refnum < 1390) strand = "A--";
66648
+ else if(refnum >= 1420 && refnum < 1490) strand = "A-";
66649
+ else if(refnum >= 1520 && refnum < 1590) strand = "A";
66650
+ else if(refnum >= 1620 && refnum < 1690) strand = "A+";
66651
+ else if(refnum >= 1820 && refnum < 1890) strand = "A'";
66652
+ else if(refnum >= 2000 && refnum < 2900) strand = "B";
66653
+ else if(refnum >= 3300 && refnum < 3390) strand = "C--";
66654
+ else if(refnum >= 3420 && refnum < 3490) strand = "C-";
66655
+ else if(refnum >= 3520 && refnum < 3590) strand = "C";
66656
+ else if(refnum >= 4000 && refnum < 4900) strand = "C'";
66657
+ else if(refnum >= 5000 && refnum < 5900) strand = "C''";
66658
+ else if(refnum >= 6000 && refnum < 6900) strand = "D";
66659
+ else if(refnum >= 7500 && refnum < 7590) strand = "E";
66660
+ else if(refnum >= 7620 && refnum < 7900) strand = "E+";
66661
+ else if(refnum >= 8000 && refnum < 8900) strand = "F";
66662
+ else if(refnum >= 9500 && refnum < 9590) strand = "G";
66663
+ else if(refnum >= 9620 && refnum < 9690) strand = "G+";
66664
+ else if(refnum >= 9720 && refnum < 9790) strand = "G++";
66665
+ else if(refnum > 9900) strand = undefined;
66666
+ else strand = " ";
66667
+ if(prevStrand) strand = prevStrand;
66668
+
66669
+ return strand
66670
+ }
66671
+
66672
+ getLabelFromRefnum(oriRefnum, prevStrand) { let ic = this.icn3d; ic.icn3dui;
66673
+ let strand = this.getStrandFromRefnum(oriRefnum, prevStrand);
66674
+
66675
+ if(strand) {
66676
+ return strand + oriRefnum;
66677
+ }
66678
+ else {
66679
+ return undefined;
66680
+ }
67003
66681
  }
67004
66682
 
67005
66683
  async parseCustomRefFile(data) { let ic = this.icn3d; ic.icn3dui;
@@ -67078,7 +66756,8 @@ class Dssp {
67078
66756
  // 1. show IgStrand ref numbers
67079
66757
  if(type == 'igstrand' || type == 'IgStrand') {
67080
66758
  // iGStrand reference numbers were adjusted when showing in sequences
67081
- if(me.bNode) {
66759
+ // if(me.bNode) {
66760
+ if(ic.bShowRefnum) {
67082
66761
  for(let chnid in ic.chains) {
67083
66762
  let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chnid]);
67084
66763
  if(ic.proteins.hasOwnProperty(atom.serial)) {
@@ -67120,29 +66799,6 @@ class Dssp {
67120
66799
 
67121
66800
  // refData += '{"Ig domain" : ' + bIgDomain + ', "ref PDB" : ' + JSON.stringify(ic.refPdbList) + ',\n';
67122
66801
  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
66802
 
67147
66803
  if(bIgDomain) {
67148
66804
  refData += '"igs": [\n';
@@ -67153,8 +66809,8 @@ class Dssp {
67153
66809
  refData += '{"' + chnid + '": {\n';
67154
66810
 
67155
66811
  for(let i = 0, il = igArray.length; i < il; ++i) {
67156
- let startPos = igArray[i].startPos;
67157
- let endPos = igArray[i].endPos;
66812
+ let startPosArray = igArray[i].startPosArray;
66813
+ let endPosArray = igArray[i].endPosArray;
67158
66814
  let domainid = igArray[i].domainid;
67159
66815
  let info = ic.domainid2info[domainid];
67160
66816
  if(!info) continue;
@@ -67162,9 +66818,13 @@ class Dssp {
67162
66818
  refData += '"' + domainid + '": {\n';
67163
66819
 
67164
66820
  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';
66821
+ for(let j = 0, jl = startPosArray.length; j < jl; ++j) {
66822
+ let startPos = startPosArray[j];
66823
+ let endPos = endPosArray[j];
66824
+ for(let k = startPos; k <= endPos; ++k) {
66825
+ const resid = chnid + '_' + ic.chainsSeq[chnid][k].resi + '_' + ic.chainsSeq[chnid][k].name;
66826
+ refData += '{"' + resid + '": "' + resid2refnum[resid] + '"},\n';
66827
+ }
67168
66828
  }
67169
66829
  refData += '],\n';
67170
66830
 
@@ -67261,6 +66921,487 @@ class Dssp {
67261
66921
 
67262
66922
  return dataArray3;
67263
66923
  }
66924
+
66925
+ ajdustRefnum(giSeq, chnid) { let ic = this.icn3d, me = ic.icn3dui;
66926
+ if(!ic.chainid2refpdbname[chnid]) return false;
66927
+
66928
+ // auto-generate ref numbers for loops
66929
+ let currStrand = '', prevStrand = '';
66930
+ let refnumLabel, refnumStr_ori, refnumStr, postfix, strandPostfix, refnum, refnum3c, refnum2c;
66931
+ let bExtendedStrand = false, bSecThird9 = false;
66932
+
66933
+ // sometimes one chain may have several Ig domains,set an index for each IgDomain
66934
+ let index = 1, bStart = false;
66935
+
66936
+ if(!me.bNode) { // do not overwrite loops in node
66937
+ // reset ic.residIgLoop for the current selection, which could be the second round of ref num assignment
66938
+ // just current chain
66939
+ let atomHash = me.hashUtilsCls.intHash(ic.chains[chnid], ic.hAtoms);
66940
+ ic.firstAtomObjCls.getResiduesFromAtoms(atomHash);
66941
+ }
66942
+
66943
+ // 1. get the range of each strand excluding loops
66944
+ let strandArray = [], strandHash = {}, strandCnt = 0, resCnt = 0, resCntBfAnchor = 0, resCntAtAnchor = 0;
66945
+ let bFoundAnchor = false;
66946
+
66947
+ for(let i = 0, il = giSeq.length; i < il; ++i, ++resCnt, ++resCntBfAnchor, ++resCntAtAnchor) {
66948
+ let currResi = ic.ParserUtilsCls.getResi(chnid, i);
66949
+ let residueid = chnid + '_' + currResi;
66950
+ let domainid;
66951
+
66952
+ refnumLabel = ic.resid2refnum[residueid];
66953
+
66954
+ let firstChar = (refnumLabel) ? refnumLabel.substr(0,1) : '';
66955
+ if(!bStart && refnumLabel && (firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
66956
+ bStart = true;
66957
+ resCnt = 1; // the first one is included
66958
+ bFoundAnchor = false;
66959
+ }
66960
+
66961
+ //if((prevStrand.substr(0,1) == 'F' || prevStrand.substr(0,1) == 'G') && !refnumLabel) { // indicate the end of an IG domain
66962
+ if((prevStrand.substr(0,1) == 'G') && !refnumLabel) { // indicate the end of an IG domain
66963
+ bStart = false;
66964
+ }
66965
+
66966
+ if(refnumLabel) {
66967
+ domainid = ic.resid2domainid[residueid];
66968
+
66969
+ refnumStr_ori = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
66970
+ currStrand = refnumLabel.replace(new RegExp(refnumStr_ori,'g'), '');
66971
+ refnumStr_ori.substr(0, 1);
66972
+
66973
+ refnumStr = refnumStr_ori;
66974
+ refnum = parseInt(refnumStr);
66975
+ refnum3c = (refnum - parseInt(refnum/1000) * 1000).toString();
66976
+ refnum2c = (refnum - parseInt(refnum/100) * 100).toString();
66977
+
66978
+ // for extended strands, since A is 1550 and A+ is 1650, then the AA+ loop will be 1591, 1592, ... 1610, 1611, etc
66979
+ bSecThird9 = refnum3c.substr(0,1) == '9' || refnum2c.substr(0,1) == '9' || refnum2c.substr(0,1) == '0' || refnum2c.substr(0,1) == '1';
66980
+ if(bSecThird9) ic.residIgLoop[residueid] = 1;
66981
+
66982
+ strandPostfix = refnumStr.replace(refnum.toString(), '');
66983
+
66984
+ postfix = strandPostfix + '_' + index;
66985
+
66986
+ let firstTwo = parseInt(refnum.toString().substr(0, 2)); // check extended strands
66987
+ bExtendedStrand = refnum3c.substr(0,1) != '5' && firstTwo != '18'; // all strands and A' (18##)
66988
+
66989
+ if(currStrand && currStrand != ' ') {
66990
+ if(!bSecThird9 || (bExtendedStrand && !bSecThird9)) {
66991
+ let lastTwo = parseInt(refnum.toString().substr(refnum.toString().length - 2, 2));
66992
+
66993
+ if(currStrand != prevStrand) { // reset currCnt
66994
+ bFoundAnchor = false;
66995
+
66996
+ if(strandHash[currStrand + postfix]) {
66997
+ ++index;
66998
+ postfix = refnumStr.replace(refnum.toString(), '') + '_' + index;
66999
+ }
67000
+
67001
+ strandHash[currStrand + postfix] = 1;
67002
+
67003
+ strandArray[strandCnt] = {};
67004
+
67005
+ strandArray[strandCnt].startResi = currResi;
67006
+ strandArray[strandCnt].startRefnum = refnum; // 1250 in A1250a
67007
+
67008
+ resCntBfAnchor = 0;
67009
+
67010
+ strandArray[strandCnt].domainid = domainid;
67011
+
67012
+ strandArray[strandCnt].endResi = currResi;
67013
+ strandArray[strandCnt].endRefnum = refnum; // 1250a
67014
+
67015
+ if(lastTwo == 50) {
67016
+ strandArray[strandCnt].anchorRefnum = refnum;
67017
+ strandArray[strandCnt].resCntBfAnchor = resCntBfAnchor;
67018
+
67019
+ resCntAtAnchor = 0;
67020
+
67021
+ bFoundAnchor = true;
67022
+ }
67023
+
67024
+ // in case A1550 is not found, but A1551 is found
67025
+ if(!bFoundAnchor && (lastTwo == 51 || lastTwo == 52 || lastTwo == 53 || lastTwo == 54) ) {
67026
+ let offset = lastTwo - 50;
67027
+ strandArray[strandCnt].anchorRefnum = refnum - offset;
67028
+ strandArray[strandCnt].resCntBfAnchor = resCntBfAnchor - offset;
67029
+
67030
+ resCntAtAnchor = offset;
67031
+
67032
+ bFoundAnchor = true;
67033
+ }
67034
+
67035
+ if(bExtendedStrand) {
67036
+ strandArray[strandCnt].anchorRefnum = 0;
67037
+ }
67038
+
67039
+ strandArray[strandCnt].strandPostfix = strandPostfix; // a in A1250a
67040
+ strandArray[strandCnt].strand = currStrand; // A in A1250a
67041
+
67042
+ strandArray[strandCnt].postfix = postfix; // Aa_1
67043
+
67044
+ strandArray[strandCnt].loopResCnt = resCnt - 1;
67045
+
67046
+ ++strandCnt;
67047
+ resCnt = 0;
67048
+ }
67049
+ else {
67050
+ if(strandHash[currStrand + postfix]) {
67051
+ if(lastTwo == 50) {
67052
+ strandArray[strandCnt - 1].anchorRefnum = refnum;
67053
+ strandArray[strandCnt - 1].resCntBfAnchor = resCntBfAnchor;
67054
+
67055
+ // update
67056
+ strandArray[strandCnt - 1].startRefnum = strandArray[strandCnt - 1].anchorRefnum - strandArray[strandCnt - 1].resCntBfAnchor;
67057
+
67058
+ resCntAtAnchor = 0;
67059
+
67060
+ bFoundAnchor = true;
67061
+ }
67062
+
67063
+ // in case A1550 is not found, but A1551 is found
67064
+ if(!bFoundAnchor && (lastTwo == 51 || lastTwo == 52 || lastTwo == 53 || lastTwo == 54) ) {
67065
+ let offset = lastTwo - 50;
67066
+ strandArray[strandCnt - 1].anchorRefnum = refnum - offset;
67067
+ strandArray[strandCnt - 1].resCntBfAnchor = resCntBfAnchor - offset;
67068
+
67069
+ // update
67070
+ strandArray[strandCnt - 1].startRefnum = strandArray[strandCnt - 1].anchorRefnum - strandArray[strandCnt - 1].resCntBfAnchor;
67071
+
67072
+ resCntAtAnchor = offset;
67073
+
67074
+ bFoundAnchor = true;
67075
+ }
67076
+
67077
+ if(bExtendedStrand) {
67078
+ strandArray[strandCnt - 1].anchorRefnum = 0;
67079
+ }
67080
+
67081
+ strandArray[strandCnt - 1].domainid = domainid;
67082
+
67083
+ strandArray[strandCnt - 1].endResi = currResi;
67084
+ strandArray[strandCnt - 1].endRefnum = refnum; // 1250a
67085
+ strandArray[strandCnt - 1].resCntAtAnchor = resCntAtAnchor;
67086
+
67087
+ if(strandArray[strandCnt - 1].anchorRefnum) {
67088
+ strandArray[strandCnt - 1].endRefnum = strandArray[strandCnt - 1].anchorRefnum + strandArray[strandCnt - 1].resCntAtAnchor;
67089
+ }
67090
+
67091
+ resCnt = 0;
67092
+ }
67093
+ }
67094
+ }
67095
+ }
67096
+ }
67097
+
67098
+ prevStrand = currStrand;
67099
+ }
67100
+
67101
+ // 2. extend the strand to end of sheet
67102
+ let maxExtend = 8;
67103
+ for(let i = 0, il = strandArray.length; i < il; ++i) {
67104
+ let startAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[chnid + '_' + strandArray[i].startResi]);
67105
+ let endAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[chnid + '_' + strandArray[i].endResi]);
67106
+
67107
+ let startPos = ic.setSeqAlignCls.getPosFromResi(chnid, strandArray[i].startResi);
67108
+ let endPos = ic.setSeqAlignCls.getPosFromResi(chnid, strandArray[i].endResi);
67109
+
67110
+ if(startAtom.ss == 'sheet' && !startAtom.ssbegin) {
67111
+ for(let j = 1; j <= maxExtend; ++j) {
67112
+ let currPos = startPos - j;
67113
+ let currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
67114
+ if(i > 0 && parseInt(currResi) <= parseInt(strandArray[i-1].endResi)) break;
67115
+
67116
+ let currResid = chnid + '_' + currResi;
67117
+ let currAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[currResid]);
67118
+ let domainid = ic.resid2domainid[currResid];
67119
+ if(currAtom.ssbegin) { // find the start of the sheet
67120
+ // update the following: startResi,startRefnum,endResi,endRefnum,loopResCnt,resCntBfAnchor,resCntAtAnchor
67121
+ strandArray[i].startResi = currResi;
67122
+ strandArray[i].startRefnum -= j;
67123
+ strandArray[i].loopResCnt -= j;
67124
+ if(strandArray[i].loopResCnt < 0) strandArray[i].loopResCnt = 0;
67125
+ strandArray[i].resCntBfAnchor += j;
67126
+
67127
+ // update ic.resid2refnum
67128
+ for(let k = 1; k <= j; ++k) {
67129
+ currPos = startPos - k;
67130
+ currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
67131
+ let currResid = chnid + '_' + currResi;
67132
+ delete ic.residIgLoop[currResid];
67133
+ ic.resid2domainid[currResid] = domainid;
67134
+ }
67135
+
67136
+ break;
67137
+ }
67138
+ }
67139
+ }
67140
+
67141
+ if(endAtom.ss == 'sheet' && !endAtom.ssend) {
67142
+ for(let j = 1; j <= maxExtend; ++j) {
67143
+ let currPos = endPos + j;
67144
+ let currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
67145
+ if(i < il - 1 && parseInt(currResi) >= parseInt(strandArray[i+1].startResi)) break;
67146
+
67147
+ let currResid = chnid + '_' + currResi;
67148
+ let currAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[currResid]);
67149
+ let domainid = ic.resid2domainid[currResid];
67150
+ if(currAtom.ssend) { // find the end of the sheet
67151
+ // update the following: startResi,startRefnum,endResi,endRefnum,loopResCnt,resCntBfAnchor,resCntAtAnchor
67152
+ strandArray[i].endResi = currResi;
67153
+ strandArray[i].endRefnum += j;
67154
+ if(i < il - 1) {
67155
+ strandArray[i + 1].loopResCnt -= j;
67156
+ if(strandArray[i + 1].loopResCnt < 0) strandArray[i + 1].loopResCnt = 0;
67157
+ }
67158
+ strandArray[i].resCntAtAnchor += j;
67159
+
67160
+ // update ic.residIgLoop[resid];
67161
+ for(let k = 1; k <= j; ++k) {
67162
+ currPos = endPos + k;
67163
+ currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
67164
+ let currResid = chnid + '_' + currResi;
67165
+ delete ic.residIgLoop[currResid];
67166
+ ic.resid2domainid[currResid] = domainid;
67167
+ }
67168
+
67169
+ break;
67170
+ }
67171
+ }
67172
+ }
67173
+ }
67174
+ /*
67175
+ // 2b. remove strands with less than 3 residues except G strand
67176
+ for(let il = strandArray.length, i = il - 1; i >= 0; --i) {
67177
+ let strandTmp = strandArray[i].strand.substr(0, 1);
67178
+ if(strandTmp != 'G' && strandArray[i].endRefnum - strandArray[i].startRefnum + 1 < 3) { // remove the strand
67179
+ if(strandTmp == 'B' || strandTmp == 'C' || strandTmp == 'E' || strandTmp == 'F') {
67180
+ if(!me.bNode) console.log("Some of the Ig strands B, C, E, F are removed since they are too short...");
67181
+
67182
+ console.log("### strandTmp " + strandTmp + " strandArray[i].endRefnum - strandArray[i].startRefnum + 1 " + (strandArray[i].endRefnum - strandArray[i].startRefnum + 1))
67183
+ return false;
67184
+ }
67185
+
67186
+ if(i != il - 1) { // modify
67187
+ strandArray[i + 1].loopResCnt += strandArray[i].loopResCnt + parseInt(strandArray[i].endResi) - parseInt(strandArray[i].startResi) + 1;
67188
+ }
67189
+
67190
+ strandArray.splice(i, 1);
67191
+ }
67192
+ }
67193
+ */
67194
+ // 3. assign refnumLabel for each resid
67195
+ strandCnt = 0;
67196
+ let loopCnt = 0;
67197
+
67198
+ let bBeforeAstrand = true, bAfterGstrand = true, refnumLabelNoPostfix, prevStrandCnt = 0, currRefnum;
67199
+ bStart = false;
67200
+ let refnumInStrand = 0;
67201
+ if(strandArray.length > 0) {
67202
+ for(let i = 0, il = giSeq.length; i < il; ++i, ++loopCnt, ++refnumInStrand) {
67203
+ let currResi = ic.ParserUtilsCls.getResi(chnid, i);
67204
+ let residueid = chnid + '_' + currResi;
67205
+ refnumLabel = ic.resid2refnum[residueid];
67206
+
67207
+ currStrand = strandArray[strandCnt].strand;
67208
+
67209
+ let domainid;
67210
+
67211
+ if(refnumLabel) {
67212
+ domainid = ic.resid2domainid[residueid];
67213
+
67214
+ refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
67215
+ currRefnum = parseInt(refnumStr);
67216
+ refnumLabelNoPostfix = currStrand + currRefnum;
67217
+
67218
+ currStrand = refnumLabel.replace(new RegExp(refnumStr,'g'), '');
67219
+
67220
+ let firstChar = refnumLabel.substr(0,1);
67221
+ if(!bStart && (firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
67222
+ bStart = true;
67223
+ bBeforeAstrand = true;
67224
+ loopCnt = 0;
67225
+ }
67226
+ }
67227
+
67228
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[residueid]);
67229
+
67230
+ // skip non-protein residues
67231
+ if(!atom || !ic.proteins.hasOwnProperty(atom.serial)) {
67232
+ refnumLabel = undefined;
67233
+ }
67234
+ else {
67235
+ let bBefore = false, bInRange= false, bAfter = false;
67236
+ // 100, 100A
67237
+ if(parseInt(currResi) == parseInt(strandArray[strandCnt].startResi) && currResi != strandArray[strandCnt].startResi) {
67238
+ bBefore = currResi < strandArray[strandCnt].startResi;
67239
+ }
67240
+ else {
67241
+ bBefore = parseInt(currResi) < parseInt(strandArray[strandCnt].startResi);
67242
+ }
67243
+
67244
+ // 100, 100A
67245
+ if(parseInt(currResi) == parseInt(strandArray[strandCnt].endResi) && currResi != strandArray[strandCnt].endResi) {
67246
+ bAfter = currResi > strandArray[strandCnt].endResi;
67247
+ }
67248
+ else {
67249
+ bAfter = parseInt(currResi) > parseInt(strandArray[strandCnt].endResi);
67250
+ }
67251
+
67252
+ bInRange = (!bBefore && !bAfter) ? true : false;
67253
+
67254
+ if(bBefore) {
67255
+ ic.residIgLoop[residueid] = 1;
67256
+
67257
+ if(bBeforeAstrand) { // make it continuous to the 1st strand
67258
+ if(bStart) {
67259
+ currRefnum = strandArray[strandCnt].startRefnum - strandArray[strandCnt].loopResCnt + loopCnt;
67260
+ refnumLabelNoPostfix = strandArray[strandCnt].strand + currRefnum;
67261
+ refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
67262
+ domainid = strandArray[strandCnt].domainid;
67263
+ }
67264
+ else {
67265
+ //loopCnt = 0;
67266
+ refnumLabelNoPostfix = undefined;
67267
+ refnumLabel = undefined;
67268
+ }
67269
+ }
67270
+ else {
67271
+ if(prevStrandCnt >= 0
67272
+ // && (strandArray[prevStrandCnt].strand.substr(0, 1) == 'F' || strandArray[prevStrandCnt].strand.substr(0, 1) == 'G')) {
67273
+ && (strandArray[prevStrandCnt].strand.substr(0, 1) == 'G')) {
67274
+ if(!bAfterGstrand) {
67275
+ //loopCnt = 0;
67276
+ refnumLabelNoPostfix = undefined;
67277
+ refnumLabel = undefined;
67278
+ }
67279
+ else {
67280
+ if(bStart && ic.resid2refnum[residueid]) {
67281
+ bAfterGstrand = true;
67282
+
67283
+ currRefnum = strandArray[prevStrandCnt].endRefnum + loopCnt;
67284
+ refnumLabelNoPostfix = strandArray[prevStrandCnt].strand + currRefnum;
67285
+ refnumLabel = refnumLabelNoPostfix + strandArray[prevStrandCnt].strandPostfix;
67286
+ domainid = strandArray[prevStrandCnt].domainid;
67287
+ }
67288
+ else {
67289
+ bStart = false;
67290
+ bBeforeAstrand = true;
67291
+ //loopCnt = 0;
67292
+
67293
+ bAfterGstrand = false;
67294
+
67295
+ refnumLabelNoPostfix = undefined;
67296
+ refnumLabel = undefined;
67297
+ }
67298
+ }
67299
+ }
67300
+ else {
67301
+ bAfterGstrand = true; // reset
67302
+
67303
+ let len = strandArray[strandCnt].loopResCnt;
67304
+ let halfLen = parseInt(len / 2.0 + 0.5);
67305
+
67306
+ if(loopCnt <= halfLen) {
67307
+ currRefnum = strandArray[prevStrandCnt].endRefnum + loopCnt;
67308
+ refnumLabelNoPostfix = strandArray[prevStrandCnt].strand + currRefnum;
67309
+ refnumLabel = refnumLabelNoPostfix + strandArray[prevStrandCnt].strandPostfix;
67310
+ domainid = strandArray[prevStrandCnt].domainid;
67311
+ }
67312
+ else {
67313
+ currRefnum = strandArray[strandCnt].startRefnum - len + loopCnt - 1;
67314
+ refnumLabelNoPostfix = strandArray[strandCnt].strand + currRefnum;
67315
+ refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
67316
+ domainid = strandArray[strandCnt].domainid;
67317
+ }
67318
+ }
67319
+ }
67320
+ }
67321
+ else if(bInRange) {
67322
+ // not in loop any more if you assign ref numbers multiple times
67323
+ //delete ic.residIgLoop[residueid];
67324
+
67325
+ bBeforeAstrand = false;
67326
+
67327
+ if(strandArray[strandCnt].anchorRefnum) { // use anchor to name refnum
67328
+ if(currResi == strandArray[strandCnt].startResi) {
67329
+ refnumInStrand = strandArray[strandCnt].anchorRefnum - strandArray[strandCnt].resCntBfAnchor;
67330
+ strandArray[strandCnt].startRefnum = refnumInStrand;
67331
+ }
67332
+ else if(currResi == strandArray[strandCnt].endResi) {
67333
+ strandArray[strandCnt].endRefnum = refnumInStrand;
67334
+ }
67335
+
67336
+ refnumLabelNoPostfix = strandArray[strandCnt].strand + refnumInStrand;
67337
+ refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
67338
+ domainid = strandArray[strandCnt].domainid;
67339
+ }
67340
+
67341
+ if(currResi == strandArray[strandCnt].endResi) {
67342
+ ++strandCnt; // next strand
67343
+ loopCnt = 0;
67344
+
67345
+ if(!strandArray[strandCnt]) { // last strand
67346
+ --strandCnt;
67347
+ }
67348
+ }
67349
+ }
67350
+ else if(bAfter) {
67351
+ ic.residIgLoop[residueid] = 1;
67352
+
67353
+ if(!bAfterGstrand) {
67354
+ refnumLabelNoPostfix = undefined;
67355
+ refnumLabel = undefined;
67356
+ }
67357
+ else {
67358
+ // C-terminal
67359
+ if(!ic.resid2refnum[residueid]) {
67360
+ bAfterGstrand = false;
67361
+
67362
+ refnumLabelNoPostfix = undefined;
67363
+ refnumLabel = undefined;
67364
+ }
67365
+ else {
67366
+ bAfterGstrand = true;
67367
+
67368
+ currRefnum = strandArray[strandCnt].endRefnum + loopCnt;
67369
+ refnumLabelNoPostfix = strandArray[strandCnt].strand + currRefnum;
67370
+ refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
67371
+ domainid = strandArray[strandCnt].domainid;
67372
+ }
67373
+ }
67374
+ }
67375
+ }
67376
+
67377
+ prevStrand = currStrand;
67378
+ prevStrandCnt = strandCnt - 1;
67379
+
67380
+ // assign the adjusted reference numbers
67381
+ ic.resid2refnum[residueid] = refnumLabel;
67382
+ ic.resid2domainid[residueid] = domainid;
67383
+
67384
+ refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
67385
+
67386
+ if(!ic.refnum2residArray.hasOwnProperty(refnumStr)) {
67387
+ ic.refnum2residArray[refnumStr] = [residueid];
67388
+ }
67389
+ else {
67390
+ ic.refnum2residArray[refnumStr].push(residueid);
67391
+ }
67392
+
67393
+ if(!ic.chainsMapping.hasOwnProperty(chnid)) {
67394
+ ic.chainsMapping[chnid] = {};
67395
+ }
67396
+
67397
+ // remove the postfix when comparing interactions
67398
+ //ic.chainsMapping[chnid][residueid] = refnumLabel;
67399
+ ic.chainsMapping[chnid][residueid] = refnumLabelNoPostfix;
67400
+ }
67401
+ }
67402
+
67403
+ return true;
67404
+ }
67264
67405
  }
67265
67406
 
67266
67407
  /**