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.module.js CHANGED
@@ -8309,6 +8309,26 @@ class ClickMenu {
8309
8309
  await ic.annotationCls.setAnnoTabIg(bSelection, template);
8310
8310
  });
8311
8311
 
8312
+ me.myEventCls.onIds("#" + me.pre + "mn6_alignrefTpl", "click", async function(e) { me.icn3d; //e.preventDefault();
8313
+ me.htmlCls.dialogCls.openDlg('dl_alignrefTpl', 'Align with an Ig template');
8314
+ });
8315
+
8316
+ me.myEventCls.onIds("#" + me.pre + "mn6_alignrefTpl_apply", "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
8317
+ if(!me.cfg.notebook) dialog.dialog( "close" );
8318
+
8319
+ let template = $("#" + me.pre + "refTpl2").val();
8320
+
8321
+ // load the template
8322
+ let url = me.htmlCls.baseUrl + "icn3d/refpdb/" + template + ".pdb";
8323
+ await ic.pdbParserCls.downloadUrl(url, 'pdb', undefined, template);
8324
+ thisClass.setLogCmd('load url ' + url + ' | type pdb', true);
8325
+
8326
+ // align the template with the selection
8327
+ me.cfg.aligntool = 'tmalign';
8328
+ await ic.realignParserCls.realignOnStructAlign();
8329
+ thisClass.setLogCmd('realign on tmalign', true);
8330
+ });
8331
+
8312
8332
  me.myEventCls.onIds("#" + me.pre + "mn6_igrefNo", "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
8313
8333
  thisClass.setLogCmd('ig refnum off', true);
8314
8334
  await ic.refnumCls.hideIgRefNum();
@@ -10660,11 +10680,14 @@ class SetMenu {
10660
10680
  /*
10661
10681
  html += this.getLink('mn6_igrefYes', 'Show Ig for Selection', undefined, 2);
10662
10682
  html += this.getLink('mn6_igrefTpl', 'Ig w/ Specified Template', undefined, 2);
10683
+ html += this.getLink('mn6_alignrefTpl', 'Align w/ Specified Template', undefined, 2);
10663
10684
  html += this.getLink('mn6_igrefNo', 'Reset Ig Ref. Number', undefined, 2);
10664
10685
 
10665
10686
  html += this.getMenuSep();
10666
10687
  */
10667
10688
 
10689
+
10690
+
10668
10691
  html += this.getLink('mn6_customref', 'Custom Ref. Number', undefined, 2);
10669
10692
  html += "</ul>";
10670
10693
  html += "</li>";
@@ -12811,8 +12834,24 @@ class SetDialog {
12811
12834
  html += me.htmlCls.divStr + "dl_igrefTpl' class='" + dialogClass + "'>";
12812
12835
  html += this.addNotebookTitle('dl_igrefTpl', 'Choose an Ig template');
12813
12836
  html += "<span style='white-space:nowrap;font-weight:bold;'>Choose an Ig template for selected residues:</span> <br><br><select id='" + me.pre + "refTpl'>";
12837
+ html += this.setTemplateMenu();
12838
+ html += "</select><br><br><span style='white-space:nowrap;'>" + me.htmlCls.buttonStr + "mn6_igrefTpl_apply'>Show Ig Ref. Number</button></span>";
12839
+ html += "</div>";
12840
+
12841
+ html += me.htmlCls.divStr + "dl_alignrefTpl' class='" + dialogClass + "'>";
12842
+ html += this.addNotebookTitle('dl_alignrefTpl', 'Align with an Ig template');
12843
+ 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'>";
12844
+ html += this.setTemplateMenu();
12845
+ html += "</select><br><br><span style='white-space:nowrap;'>" + me.htmlCls.buttonStr + "mn6_alignrefTpl_apply'>Align Template with Selection</button></span>";
12846
+ html += "</div>";
12814
12847
 
12815
- //html += me.htmlCls.setHtmlCls.getOptionHtml(['0', '10', '20', '30', '40', '50', '60', '70', '80', '90', '100'], 3);
12848
+ html += "</div>";
12849
+ html += "<!--/form-->";
12850
+
12851
+ return html;
12852
+ }
12853
+
12854
+ setTemplateMenu() { let me = this.icn3dui; me.icn3d;
12816
12855
  let group2tpl = {};
12817
12856
  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'];
12818
12857
  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'];
@@ -12826,6 +12865,7 @@ class SetDialog {
12826
12865
 
12827
12866
  group2tpl['Other'] = ['CuZnSuperoxideDismutase_1hl5C_human', 'ECadherin_4zt1A_human_n2', 'LaminAC_1ifrA_human', 'ORF7a_1xakA_virus'];
12828
12867
 
12868
+ let html = '';
12829
12869
  for(let group in group2tpl) {
12830
12870
  html += "<optgroup label='" + group + "'>";
12831
12871
  for(let i = 0, il = group2tpl[group].length; i < il; ++i) {
@@ -12835,12 +12875,6 @@ class SetDialog {
12835
12875
  html += "</optgroup>";
12836
12876
  }
12837
12877
 
12838
- html += "</select><br><br><span style='white-space:nowrap;'>" + me.htmlCls.buttonStr + "mn6_igrefTpl_apply'>Show Ig Ref. Number</button></span>";
12839
- html += "</div>";
12840
-
12841
- html += "</div>";
12842
- html += "<!--/form-->";
12843
-
12844
12878
  return html;
12845
12879
  }
12846
12880
 
@@ -12880,6 +12914,7 @@ class SetDialog {
12880
12914
  html += tmpStr1 + me.htmlCls.inputCheckStr + "id='" + me.pre + "anno_ig'>Ig Domains" + me.htmlCls.space2 + "</span></td>";
12881
12915
  */
12882
12916
 
12917
+
12883
12918
  html += "<td></td>";
12884
12919
  html += "</tr></table></div></div>";
12885
12920
 
@@ -37644,7 +37679,7 @@ class AnnoCddSite {
37644
37679
  let fromArray = [], toArray = [];
37645
37680
  let resiHash = {};
37646
37681
  let resCnt = 0;
37647
- let segArray =(type == 'domain') ? domainRepeatArray[r].segs : [domainRepeatArray[r]];
37682
+ let segArray =(type == 'domain' || type == 'ig') ? domainRepeatArray[r].segs : [domainRepeatArray[r]];
37648
37683
  for(let s = 0, sl = segArray.length; s < sl; ++s) {
37649
37684
  let domainFrom = Math.round(segArray[s].from);
37650
37685
  let domainTo = Math.round(segArray[s].to);
@@ -37748,15 +37783,15 @@ class AnnoCddSite {
37748
37783
 
37749
37784
  if(me.cfg.blast_rep_id != chnid) { // regular
37750
37785
  for(let i = 0, il = fromArray.length; i < il; ++i) {
37751
- let color = this.getColorFromPos(chnid, i, titleArray);
37786
+ let color = this.getColorFromPos(chnid, fromArray[i], titleArray);
37752
37787
 
37753
37788
  let emptyWidth;
37754
- if(titleArray) {
37789
+ // if(titleArray) {
37755
37790
  emptyWidth =(i == 0) ? Math.round(ic.seqAnnWidth *(fromArray[i]) / ic.maxAnnoLength) : Math.round(ic.seqAnnWidth *(fromArray[i] - toArray[i-1] - 1) / ic.maxAnnoLength);
37756
- }
37757
- else {
37758
- 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);
37759
- }
37791
+ // }
37792
+ // else {
37793
+ // 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);
37794
+ // }
37760
37795
 
37761
37796
  html2 += '<div style="display:inline-block; width:' + emptyWidth + 'px;">&nbsp;</div>';
37762
37797
  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>';
@@ -37775,7 +37810,7 @@ class AnnoCddSite {
37775
37810
  toArray2.push(toArray[i]);
37776
37811
  }
37777
37812
  for(let i = 0, il = fromArray2.length; i < il; ++i) {
37778
- let color = this.getColorFromPos(chnid, i, titleArray);
37813
+ let color = this.getColorFromPos(chnid, fromArray2[i], titleArray);
37779
37814
 
37780
37815
  html2 += ic.showSeqCls.insertGapOverview(chnid, fromArray2[i]);
37781
37816
  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));
@@ -38485,7 +38520,7 @@ class AnnoIg {
38485
38520
  if(ic.bShowRefnum && ic.chainid2refpdbname.hasOwnProperty(chnid) && ic.chainid2refpdbname[chnid].length > 0) {
38486
38521
  let giSeq = ic.showSeqCls.getSeq(chnid);
38487
38522
  let result = ic.annoIgCls.showAllRefNum(giSeq, chnid);
38488
-
38523
+
38489
38524
  html += result.html;
38490
38525
  html2 += result.html2;
38491
38526
  html3 += result.html3;
@@ -38499,38 +38534,12 @@ class AnnoIg {
38499
38534
  showAllRefNum(giSeq, chnid) { let ic = this.icn3d; ic.icn3dui;
38500
38535
  let html = '', html2 = '', html3 = '';
38501
38536
 
38502
- let result = this.showRefNum(giSeq, chnid);
38503
- html += result.html;
38504
- html2 += result.html2;
38505
- html3 += result.html3;
38506
-
38507
- let kabat_or_imgt = 1;
38508
- result = this.showRefNum(giSeq, chnid, kabat_or_imgt);
38509
- html += result.html;
38510
- html2 += result.html2;
38511
- html3 += result.html3;
38512
-
38513
- kabat_or_imgt = 2;
38514
- result = this.showRefNum(giSeq, chnid, kabat_or_imgt);
38515
- html += result.html;
38516
- html2 += result.html2;
38517
- html3 += result.html3;
38518
-
38519
- return {'html': html, 'html2': html2, 'html3': html3};
38520
- }
38521
-
38522
- showRefNum(giSeq, chnid, kabat_or_imgt, bCustom) { let ic = this.icn3d, me = ic.icn3dui;
38523
- let html = '', html2 = '', html3 = '';
38524
-
38525
- if(!ic.chainid2refpdbname[chnid]) return {html: html, html2: html2, html3: html3};
38526
-
38527
38537
  //check if Kabat refnum available
38528
38538
  let bKabatFound = false;
38529
-
38530
38539
  for(let i = 0, il = giSeq.length; i < il; ++i) {
38531
38540
  let currResi = ic.ParserUtilsCls.getResi(chnid, i);
38532
38541
  let residueid = chnid + '_' + currResi;
38533
- let domainid = (bCustom) ? 0 : ic.resid2domainid[residueid];
38542
+ let domainid = ic.resid2domainid[residueid];
38534
38543
 
38535
38544
  if(ic.domainid2ig2kabat[domainid] && Object.keys(ic.domainid2ig2kabat[domainid]).length > 0) {
38536
38545
  bKabatFound = true;
@@ -38538,479 +38547,52 @@ class AnnoIg {
38538
38547
  }
38539
38548
  }
38540
38549
 
38541
- if(kabat_or_imgt == 1 && !bKabatFound) {
38542
- return {html: '', html2: '', html3: ''};
38543
- }
38544
-
38545
38550
  //check if IMGT refnum available
38546
38551
  let bImgtFound = false;
38547
38552
  for(let i = 0, il = giSeq.length; i < il; ++i) {
38548
38553
  let currResi = ic.ParserUtilsCls.getResi(chnid, i);
38549
38554
  let residueid = chnid + '_' + currResi;
38550
- let domainid = (bCustom) ? 0 : ic.resid2domainid[residueid];
38555
+ let domainid = ic.resid2domainid[residueid];
38551
38556
 
38552
38557
  if(ic.domainid2ig2imgt[domainid] && Object.keys(ic.domainid2ig2imgt[domainid]).length > 0) {
38553
38558
  bImgtFound = true;
38554
38559
  break;
38555
38560
  }
38556
38561
  }
38557
- if(kabat_or_imgt == 2 && !bImgtFound) {
38558
- return {html: '', html2: '', html3: ''};
38559
- }
38560
38562
 
38561
- // auto-generate ref numbers for loops
38562
- let currStrand = '', prevStrand = '';
38563
- let refnumLabel, refnumStr_ori, refnumStr, postfix, strandPostfix, refnum, refnum3c, refnum2c;
38564
- let bExtendedStrand = false, bSecThird9 = false;
38565
-
38566
- // sometimes one chain may have several Ig domains,set an index for each IgDomain
38567
- let index = 1, bStart = false;
38563
+ let result = this.showRefNum(giSeq, chnid);
38564
+ html += result.html;
38565
+ html2 += result.html2;
38566
+ html3 += result.html3;
38568
38567
 
38569
- if(!bCustom && !kabat_or_imgt && !me.bNode) { // do not overwrite loops in node
38570
- // reset ic.residIgLoop for the current selection, which could be the second round of ref num assignment
38571
- // just current chain
38572
- let atomHash = me.hashUtilsCls.intHash(ic.chains[chnid], ic.hAtoms);
38573
- ic.firstAtomObjCls.getResiduesFromAtoms(atomHash);
38574
-
38575
- // for(let resid in residHash) {
38576
- // // not in loop any more if you assign ref numbers multiple times
38577
- // delete ic.residIgLoop[resid];
38578
- // }
38568
+ let kabat_or_imgt = 1;
38569
+ if(!bKabatFound) {
38570
+ return {html: html, html2: html2, html3: html3};
38571
+ }
38572
+ else {
38573
+ result = this.showRefNum(giSeq, chnid, kabat_or_imgt);
38574
+ html += result.html;
38575
+ html2 += result.html2;
38576
+ html3 += result.html3;
38579
38577
  }
38580
38578
 
38581
- // 1. get the range of each strand excluding loops
38582
- let strandArray = [], strandHash = {}, strandCnt = 0, resCnt = 0, resCntBfAnchor = 0, resCntAtAnchor = 0;
38583
- let bFoundAnchor = false;
38584
- if(!bCustom && !kabat_or_imgt) {
38585
- for(let i = 0, il = giSeq.length; i < il; ++i, ++resCnt, ++resCntBfAnchor, ++resCntAtAnchor) {
38586
- let currResi = ic.ParserUtilsCls.getResi(chnid, i);
38587
- let residueid = chnid + '_' + currResi;
38588
-
38589
- refnumLabel = ic.resid2refnum[residueid];
38590
-
38591
- let firstChar = (refnumLabel) ? refnumLabel.substr(0,1) : '';
38592
- if(!bStart && refnumLabel && (firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
38593
- bStart = true;
38594
- resCnt = 1; // the first one is included
38595
- bFoundAnchor = false;
38596
- }
38597
-
38598
- if((prevStrand.substr(0,1) == 'F' || prevStrand.substr(0,1) == 'G') && !refnumLabel) { // indicate the end of an IG domain
38599
- bStart = false;
38600
- }
38601
-
38602
- if(refnumLabel) {
38603
- refnumStr_ori = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
38604
- currStrand = refnumLabel.replace(new RegExp(refnumStr_ori,'g'), '');
38605
- refnumStr_ori.substr(0, 1);
38606
-
38607
- refnumStr = refnumStr_ori;
38608
- refnum = parseInt(refnumStr);
38609
- refnum3c = (refnum - parseInt(refnum/1000) * 1000).toString();
38610
- refnum2c = (refnum - parseInt(refnum/100) * 100).toString();
38611
-
38612
- // for extended strands, since A is 1550 and A+ is 1650, then the AA+ loop will be 1591, 1592, ... 1610, 1611, etc
38613
- bSecThird9 = refnum3c.substr(0,1) == '9' || refnum2c.substr(0,1) == '9' || refnum2c.substr(0,1) == '0' || refnum2c.substr(0,1) == '1';
38614
- if(bSecThird9) ic.residIgLoop[residueid] = 1;
38615
-
38616
- strandPostfix = refnumStr.replace(refnum.toString(), '');
38617
-
38618
- postfix = strandPostfix + '_' + index;
38619
-
38620
- let firstTwo = parseInt(refnum.toString().substr(0, 2)); // check extended strands
38621
- bExtendedStrand = refnum3c.substr(0,1) != '5' && firstTwo != '18'; // all strands and A' (18##)
38622
-
38623
- if(currStrand && currStrand != ' ') {
38624
- if(!bSecThird9 || (bExtendedStrand && !bSecThird9)) {
38625
- let lastTwo = parseInt(refnum.toString().substr(refnum.toString().length - 2, 2));
38626
-
38627
- if(currStrand != prevStrand) { // reset currCnt
38628
- bFoundAnchor = false;
38629
-
38630
- if(strandHash[currStrand + postfix]) {
38631
- ++index;
38632
- postfix = refnumStr.replace(refnum.toString(), '') + '_' + index;
38633
- }
38634
-
38635
- strandHash[currStrand + postfix] = 1;
38636
-
38637
- strandArray[strandCnt] = {};
38638
- strandArray[strandCnt].startResi = currResi;
38639
- strandArray[strandCnt].startRefnum = refnum; // 1250 in A1250a
38640
-
38641
- resCntBfAnchor = 0;
38642
-
38643
- strandArray[strandCnt].endResi = currResi;
38644
- strandArray[strandCnt].endRefnum = refnum; // 1250a
38645
-
38646
- if(lastTwo == 50) {
38647
- strandArray[strandCnt].anchorRefnum = refnum;
38648
- strandArray[strandCnt].resCntBfAnchor = resCntBfAnchor;
38649
-
38650
- resCntAtAnchor = 0;
38651
-
38652
- bFoundAnchor = true;
38653
- }
38654
-
38655
- // in case A1550 is not found, but A1551 is found
38656
- if(!bFoundAnchor && (lastTwo == 51 || lastTwo == 52 || lastTwo == 53) ) {
38657
- let offset = lastTwo - 50;
38658
- strandArray[strandCnt].anchorRefnum = refnum - offset;
38659
- strandArray[strandCnt].resCntBfAnchor = resCntBfAnchor - offset;
38660
-
38661
- resCntAtAnchor = offset;
38662
-
38663
- bFoundAnchor = true;
38664
- }
38665
-
38666
- if(bExtendedStrand) {
38667
- strandArray[strandCnt].anchorRefnum = 0;
38668
- }
38669
-
38670
- strandArray[strandCnt].strandPostfix = strandPostfix; // a in A1250a
38671
- strandArray[strandCnt].strand = currStrand; // A in A1250a
38672
-
38673
- strandArray[strandCnt].postfix = postfix; // Aa_1
38674
-
38675
- strandArray[strandCnt].loopResCnt = resCnt - 1;
38676
-
38677
- ++strandCnt;
38678
- resCnt = 0;
38679
- }
38680
- else {
38681
- if(strandHash[currStrand + postfix]) {
38682
- if(lastTwo == 50) {
38683
- strandArray[strandCnt - 1].anchorRefnum = refnum;
38684
- strandArray[strandCnt - 1].resCntBfAnchor = resCntBfAnchor;
38685
-
38686
- // update
38687
- strandArray[strandCnt - 1].startRefnum = strandArray[strandCnt - 1].anchorRefnum - strandArray[strandCnt - 1].resCntBfAnchor;
38688
-
38689
- resCntAtAnchor = 0;
38690
-
38691
- bFoundAnchor = true;
38692
- }
38693
-
38694
- // in case A1550 is not found, but A1551 is found
38695
- if(!bFoundAnchor && (lastTwo == 51 || lastTwo == 52 || lastTwo == 53) ) {
38696
- let offset = lastTwo - 50;
38697
- strandArray[strandCnt - 1].anchorRefnum = refnum - offset;
38698
- strandArray[strandCnt - 1].resCntBfAnchor = resCntBfAnchor - offset;
38699
-
38700
- // update
38701
- strandArray[strandCnt - 1].startRefnum = strandArray[strandCnt - 1].anchorRefnum - strandArray[strandCnt - 1].resCntBfAnchor;
38702
-
38703
- resCntAtAnchor = offset;
38704
-
38705
- bFoundAnchor = true;
38706
- }
38707
-
38708
- if(bExtendedStrand) {
38709
- strandArray[strandCnt - 1].anchorRefnum = 0;
38710
- }
38711
-
38712
- strandArray[strandCnt - 1].endResi = currResi;
38713
- strandArray[strandCnt - 1].endRefnum = refnum; // 1250a
38714
- strandArray[strandCnt - 1].resCntAtAnchor = resCntAtAnchor;
38715
-
38716
- if(strandArray[strandCnt - 1].anchorRefnum) {
38717
- strandArray[strandCnt - 1].endRefnum = strandArray[strandCnt - 1].anchorRefnum + strandArray[strandCnt - 1].resCntAtAnchor;
38718
- }
38719
-
38720
- resCnt = 0;
38721
- }
38722
- }
38723
- }
38724
- }
38725
- }
38726
-
38727
- prevStrand = currStrand;
38728
- }
38729
-
38730
- // 2. remove strands with less than 3 residues except G strand
38731
- for(let il = strandArray.length, i = il - 1; i >= 0; --i) {
38732
- let strandTmp = strandArray[i].strand.substr(0, 1);
38733
- if(strandTmp != 'G' && strandArray[i].endRefnum - strandArray[i].startRefnum + 1 < 3) { // remove the strand
38734
- if(strandTmp == 'B' || strandTmp == 'C' || strandTmp == 'E' || strandTmp == 'F') {
38735
- if(!me.bNode) console.log("Some of the Ig strands B, C, E, F are missing...");
38736
- return {html: '', html2: '', html3: ''};
38737
- }
38738
-
38739
- if(i != il - 1) { // modify
38740
- strandArray[i + 1].loopResCnt += strandArray[i].loopResCnt + parseInt(strandArray[i].endResi) - parseInt(strandArray[i].startResi) + 1;
38741
- }
38742
-
38743
- strandArray.splice(i, 1);
38744
- }
38745
- }
38746
-
38747
- // 2b. extend the strand to end of sheet
38748
- let maxExtend = 8;
38749
- for(let i = 0, il = strandArray.length; i < il; ++i) {
38750
- let startAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[chnid + '_' + strandArray[i].startResi]);
38751
- let endAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[chnid + '_' + strandArray[i].endResi]);
38752
-
38753
- let startPos = ic.setSeqAlignCls.getPosFromResi(chnid, strandArray[i].startResi);
38754
- let endPos = ic.setSeqAlignCls.getPosFromResi(chnid, strandArray[i].endResi);
38755
-
38756
- if(startAtom.ss == 'sheet' && !startAtom.ssbegin) {
38757
- for(let j = 1; j <= maxExtend; ++j) {
38758
- let currPos = startPos - j;
38759
- let currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
38760
- if(i > 0 && parseInt(currResi) <= parseInt(strandArray[i-1].endResi)) break;
38761
-
38762
- let currResid = chnid + '_' + currResi;
38763
- let currAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[currResid]);
38764
- if(currAtom.ssbegin) { // find the start of the sheet
38765
- // update the following: startResi,startRefnum,endResi,endRefnum,loopResCnt,resCntBfAnchor,resCntAtAnchor
38766
- strandArray[i].startResi = currResi;
38767
- strandArray[i].startRefnum -= j;
38768
- strandArray[i].loopResCnt -= j;
38769
- if(strandArray[i].loopResCnt < 0) strandArray[i].loopResCnt = 0;
38770
- strandArray[i].resCntBfAnchor += j;
38771
-
38772
- // update ic.resid2refnum
38773
- for(let k = 1; k <= j; ++k) {
38774
- currPos = startPos - k;
38775
- currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
38776
- let currResid = chnid + '_' + currResi;
38777
- delete ic.residIgLoop[currResid];
38778
- }
38779
-
38780
- break;
38781
- }
38782
- }
38783
- }
38784
-
38785
- if(endAtom.ss == 'sheet' && !endAtom.ssend) {
38786
- for(let j = 1; j <= maxExtend; ++j) {
38787
- let currPos = endPos + j;
38788
- let currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
38789
- if(i < il - 1 && parseInt(currResi) >= parseInt(strandArray[i+1].startResi)) break;
38790
-
38791
- let currResid = chnid + '_' + currResi;
38792
- let currAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[currResid]);
38793
- if(currAtom.ssend) { // find the end of the sheet
38794
- // update the following: startResi,startRefnum,endResi,endRefnum,loopResCnt,resCntBfAnchor,resCntAtAnchor
38795
- strandArray[i].endResi = currResi;
38796
- strandArray[i].endRefnum += j;
38797
- if(i < il - 1) {
38798
- strandArray[i + 1].loopResCnt -= j;
38799
- if(strandArray[i + 1].loopResCnt < 0) strandArray[i + 1].loopResCnt = 0;
38800
- }
38801
- strandArray[i].resCntAtAnchor += j;
38802
-
38803
- // update ic.residIgLoop[resid];
38804
- for(let k = 1; k <= j; ++k) {
38805
- currPos = endPos + k;
38806
- currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
38807
- let currResid = chnid + '_' + currResi;
38808
- delete ic.residIgLoop[currResid];
38809
- }
38810
-
38811
- break;
38812
- }
38813
- }
38814
- }
38815
- }
38816
-
38817
- // 3. assign refnumLabel for each resid
38818
- strandCnt = 0;
38819
- let loopCnt = 0;
38820
-
38821
- let bBeforeAstrand = true, bAfterGstrand = true, refnumLabelNoPostfix, prevStrandCnt = 0, currRefnum;
38822
- bStart = false;
38823
- let refnumInStrand = 0;
38824
- if(strandArray.length > 0) {
38825
- for(let i = 0, il = giSeq.length; i < il; ++i, ++loopCnt, ++refnumInStrand) {
38826
- let currResi = ic.ParserUtilsCls.getResi(chnid, i);
38827
- let residueid = chnid + '_' + currResi;
38828
- refnumLabel = ic.resid2refnum[residueid];
38829
-
38830
- currStrand = strandArray[strandCnt].strand;
38831
-
38832
- if(refnumLabel) {
38833
- refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
38834
- currRefnum = parseInt(refnumStr);
38835
- refnumLabelNoPostfix = currStrand + currRefnum;
38836
-
38837
- currStrand = refnumLabel.replace(new RegExp(refnumStr,'g'), '');
38838
-
38839
- let firstChar = refnumLabel.substr(0,1);
38840
- if(!bStart && (firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
38841
- bStart = true;
38842
- bBeforeAstrand = true;
38843
- loopCnt = 0;
38844
- }
38845
- }
38846
-
38847
- let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[residueid]);
38848
-
38849
- // skip non-protein residues
38850
- if(!atom || !ic.proteins.hasOwnProperty(atom.serial)) {
38851
- refnumLabel = undefined;
38852
- }
38853
- else {
38854
- let bBefore = false, bInRange= false, bAfter = false;
38855
- // 100, 100A
38856
- if(parseInt(currResi) == parseInt(strandArray[strandCnt].startResi) && currResi != strandArray[strandCnt].startResi) {
38857
- bBefore = currResi < strandArray[strandCnt].startResi;
38858
- }
38859
- else {
38860
- bBefore = parseInt(currResi) < parseInt(strandArray[strandCnt].startResi);
38861
- }
38862
-
38863
- // 100, 100A
38864
- if(parseInt(currResi) == parseInt(strandArray[strandCnt].endResi) && currResi != strandArray[strandCnt].endResi) {
38865
- bAfter = currResi > strandArray[strandCnt].endResi;
38866
- }
38867
- else {
38868
- bAfter = parseInt(currResi) > parseInt(strandArray[strandCnt].endResi);
38869
- }
38870
-
38871
- bInRange = (!bBefore && !bAfter) ? true : false;
38872
-
38873
- if(bBefore) {
38874
- ic.residIgLoop[residueid] = 1;
38875
-
38876
- if(bBeforeAstrand) { // make it continuous to the 1st strand
38877
- if(bStart) {
38878
- currRefnum = strandArray[strandCnt].startRefnum - strandArray[strandCnt].loopResCnt + loopCnt;
38879
- refnumLabelNoPostfix = strandArray[strandCnt].strand + currRefnum;
38880
- refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
38881
- }
38882
- else {
38883
- //loopCnt = 0;
38884
- refnumLabelNoPostfix = undefined;
38885
- refnumLabel = undefined;
38886
- }
38887
- }
38888
- else {
38889
- if(prevStrandCnt >= 0
38890
- && (strandArray[prevStrandCnt].strand.substr(0, 1) == 'F' || strandArray[prevStrandCnt].strand.substr(0, 1) == 'G')) {
38891
- if(!bAfterGstrand) {
38892
- //loopCnt = 0;
38893
- refnumLabelNoPostfix = undefined;
38894
- refnumLabel = undefined;
38895
- }
38896
- else {
38897
- if(bStart && ic.resid2refnum[residueid]) {
38898
- bAfterGstrand = true;
38899
-
38900
- currRefnum = strandArray[prevStrandCnt].endRefnum + loopCnt;
38901
- refnumLabelNoPostfix = strandArray[prevStrandCnt].strand + currRefnum;
38902
- refnumLabel = refnumLabelNoPostfix + strandArray[prevStrandCnt].strandPostfix;
38903
- }
38904
- else {
38905
- bStart = false;
38906
- bBeforeAstrand = true;
38907
- //loopCnt = 0;
38908
-
38909
- bAfterGstrand = false;
38910
-
38911
- refnumLabelNoPostfix = undefined;
38912
- refnumLabel = undefined;
38913
- }
38914
- }
38915
- }
38916
- else {
38917
- bAfterGstrand = true; // reset
38918
-
38919
- let len = strandArray[strandCnt].loopResCnt;
38920
- let halfLen = parseInt(len / 2.0 + 0.5);
38921
-
38922
- if(loopCnt <= halfLen) {
38923
- currRefnum = strandArray[prevStrandCnt].endRefnum + loopCnt;
38924
- refnumLabelNoPostfix = strandArray[prevStrandCnt].strand + currRefnum;
38925
- refnumLabel = refnumLabelNoPostfix + strandArray[prevStrandCnt].strandPostfix;
38926
- }
38927
- else {
38928
- currRefnum = strandArray[strandCnt].startRefnum - len + loopCnt - 1;
38929
- refnumLabelNoPostfix = strandArray[strandCnt].strand + currRefnum;
38930
- refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
38931
- }
38932
- }
38933
- }
38934
- }
38935
- else if(bInRange) {
38936
- // not in loop any more if you assign ref numbers multiple times
38937
- //delete ic.residIgLoop[residueid];
38938
-
38939
- bBeforeAstrand = false;
38940
-
38941
- if(strandArray[strandCnt].anchorRefnum) { // use anchor to name refnum
38942
- if(currResi == strandArray[strandCnt].startResi) {
38943
- refnumInStrand = strandArray[strandCnt].anchorRefnum - strandArray[strandCnt].resCntBfAnchor;
38944
- strandArray[strandCnt].startRefnum = refnumInStrand;
38945
- }
38946
- else if(currResi == strandArray[strandCnt].endResi) {
38947
- strandArray[strandCnt].endRefnum = refnumInStrand;
38948
- }
38949
-
38950
- refnumLabelNoPostfix = strandArray[strandCnt].strand + refnumInStrand;
38951
- refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
38952
- }
38953
-
38954
- if(currResi == strandArray[strandCnt].endResi) {
38955
- ++strandCnt; // next strand
38956
- loopCnt = 0;
38957
-
38958
- if(!strandArray[strandCnt]) { // last strand
38959
- --strandCnt;
38960
- }
38961
- }
38962
- }
38963
- else if(bAfter) {
38964
- ic.residIgLoop[residueid] = 1;
38965
-
38966
- if(!bAfterGstrand) {
38967
- refnumLabelNoPostfix = undefined;
38968
- refnumLabel = undefined;
38969
- }
38970
- else {
38971
- // C-terminal
38972
- if(!ic.resid2refnum[residueid]) {
38973
- bAfterGstrand = false;
38974
-
38975
- refnumLabelNoPostfix = undefined;
38976
- refnumLabel = undefined;
38977
- }
38978
- else {
38979
- bAfterGstrand = true;
38980
-
38981
- currRefnum = strandArray[strandCnt].endRefnum + loopCnt;
38982
- refnumLabelNoPostfix = strandArray[strandCnt].strand + currRefnum;
38983
- refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
38984
- }
38985
- }
38986
- }
38987
- }
38988
-
38989
- prevStrand = currStrand;
38990
- prevStrandCnt = strandCnt - 1;
38991
-
38992
- // assign the adjusted reference numbers
38993
- ic.resid2refnum[residueid] = refnumLabel;
38994
-
38995
- refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
38996
-
38997
- if(!ic.refnum2residArray.hasOwnProperty(refnumStr)) {
38998
- ic.refnum2residArray[refnumStr] = [residueid];
38999
- }
39000
- else {
39001
- ic.refnum2residArray[refnumStr].push(residueid);
39002
- }
38579
+ kabat_or_imgt = 2;
38580
+ if(!bImgtFound) {
38581
+ return {html: html, html2: html2, html3: html3};
38582
+ }
38583
+ else {
38584
+ result = this.showRefNum(giSeq, chnid, kabat_or_imgt);
38585
+ html += result.html;
38586
+ html2 += result.html2;
38587
+ html3 += result.html3;
38588
+ }
39003
38589
 
39004
- if(!ic.chainsMapping.hasOwnProperty(chnid)) {
39005
- ic.chainsMapping[chnid] = {};
39006
- }
38590
+ return {html: html, html2: html2, html3: html3};
38591
+ }
39007
38592
 
39008
- // remove the postfix when comparing interactions
39009
- //ic.chainsMapping[chnid][residueid] = refnumLabel;
39010
- ic.chainsMapping[chnid][residueid] = refnumLabelNoPostfix;
39011
- }
39012
- }
39013
- }
38593
+ showRefNum(giSeq, chnid, kabat_or_imgt, bCustom) { let ic = this.icn3d; ic.icn3dui;
38594
+ let bResult = ic.chainid2igtrack[chnid];
38595
+ if(!bResult) return {html: '', html2: '', html3: ''};
39014
38596
 
39015
38597
  // add color to atoms
39016
38598
  if(ic.bShowRefnum) {
@@ -39028,15 +38610,11 @@ class AnnoIg {
39028
38610
  if(!ic.chain2igArray) ic.chain2igArray = {};
39029
38611
  ic.chain2igArray[chnid] = [];
39030
38612
 
39031
- let igElem = {};
39032
- let currStrand_ori;
39033
- let prevStrand = undefined;
39034
- let prevPos;
39035
-
39036
38613
  let bLoop = false, currStrand = '';
39037
38614
  let refnumLabel, refnumStr_ori, refnumStr;
39038
38615
 
39039
38616
  // show tracks
38617
+ let domainid2respos = {};
39040
38618
  let htmlIg = '';
39041
38619
  for(let i = 0, il = giSeq.length; i < il; ++i) {
39042
38620
  htmlIg += ic.showSeqCls.insertGap(chnid, i, '-');
@@ -39044,6 +38622,7 @@ class AnnoIg {
39044
38622
  let currResi = ic.ParserUtilsCls.getResi(chnid, i);
39045
38623
  let residueid = chnid + '_' + currResi;
39046
38624
  let domainid = (bCustom) ? 0 : ic.resid2domainid[residueid];
38625
+
39047
38626
  //if(!ic.residues.hasOwnProperty(residueid)) {
39048
38627
  // htmlIg += '<span></span>';
39049
38628
  //}
@@ -39051,10 +38630,12 @@ class AnnoIg {
39051
38630
  refnumLabel = ic.resid2refnum[residueid];
39052
38631
  let bHidelabel = false;
39053
38632
 
39054
- if(refnumLabel) {
38633
+ if(refnumLabel) {
38634
+ if(!domainid2respos[domainid]) domainid2respos[domainid] = [];
38635
+ domainid2respos[domainid].push(i);
38636
+
39055
38637
  refnumStr_ori = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
39056
38638
  currStrand = refnumLabel.replace(new RegExp(refnumStr_ori,'g'), '');
39057
- currStrand_ori = currStrand;
39058
38639
 
39059
38640
  refnumStr_ori.substr(0, 1);
39060
38641
 
@@ -39070,21 +38651,6 @@ class AnnoIg {
39070
38651
  else {
39071
38652
  refnumStr = refnumStr_ori;
39072
38653
  }
39073
-
39074
- let prevStrandFirstLet = (prevStrand) ? prevStrand.substr(0, 1) : '';
39075
- let currStrandFirstLet = (currStrand) ? currStrand.substr(0, 1) : '';
39076
-
39077
- if(prevStrand != currStrand && (!prevStrandFirstLet || prevStrandFirstLet == 'F' || prevStrandFirstLet == 'G') && (currStrandFirstLet == 'A' || currStrandFirstLet == 'B') ) { // a new Ig domain starts
39078
- if(prevStrand) {
39079
- igElem.endPos = prevPos;
39080
- ic.chain2igArray[chnid].push(igElem);
39081
- }
39082
-
39083
- igElem = {};
39084
- igElem.startPos = i;
39085
- }
39086
-
39087
- if(domainid) igElem.domainid = domainid;
39088
38654
 
39089
38655
  if(bCustom) {
39090
38656
  if(!refnumStr) {
@@ -39130,9 +38696,6 @@ class AnnoIg {
39130
38696
  htmlIg += '<span></span>';
39131
38697
  }
39132
38698
  }
39133
-
39134
- prevStrand = currStrand_ori; //currStrand;
39135
- prevPos = i;
39136
38699
  }
39137
38700
  else {
39138
38701
  htmlIg += '<span></span>';
@@ -39140,10 +38703,33 @@ class AnnoIg {
39140
38703
  //}
39141
38704
  }
39142
38705
 
39143
- igElem.endPos = prevPos;
39144
- ic.chain2igArray[chnid].push(igElem);
38706
+ // igElem.endPos = prevPos;
38707
+ // ic.chain2igArray[chnid].push(igElem);
38708
+
38709
+ for(let domainid in domainid2respos) {
38710
+ let posArray = domainid2respos[domainid];
38711
+ let pos, prevPos, startPosArray = [], endPosArray = [];
38712
+ for(let i = 0, il = posArray.length; i < il; ++i) {
38713
+ pos = posArray[i];
38714
+ if(i == 0) startPosArray.push(pos);
38715
+
38716
+ if(i > 0 && pos != prevPos + 1) { // a new range
38717
+ endPosArray.push(prevPos);
38718
+ startPosArray.push(pos);
38719
+ }
38720
+
38721
+ prevPos = pos;
38722
+ }
38723
+ endPosArray.push(pos);
39145
38724
 
39146
- if(me.bNode) return {html: '', html2: '', html3: ''};
38725
+ let igElem = {};
38726
+ igElem.domainid = domainid;
38727
+ igElem.startPosArray = startPosArray;
38728
+ igElem.endPosArray = endPosArray;
38729
+ ic.chain2igArray[chnid].push(igElem);
38730
+ }
38731
+
38732
+ if(me.bNode) return {html: html, html2: html2, html3: html3}
39147
38733
  let titleSpace = 120;
39148
38734
 
39149
38735
  let linkStr = 'icn3d-link icn3d-blue';
@@ -39151,10 +38737,16 @@ class AnnoIg {
39151
38737
 
39152
38738
  let igCnt = ic.chain2igArray[chnid].length;
39153
38739
  let fromArray = [], toArray = [];
38740
+ let posindex2domainindex = {};
39154
38741
  for(let i = 0; i < igCnt; ++i) {
39155
38742
  let igElem = ic.chain2igArray[chnid][i];
39156
- fromArray.push(igElem.startPos);
39157
- toArray.push(igElem.endPos);
38743
+ fromArray = fromArray.concat(igElem.startPosArray);
38744
+ toArray = toArray.concat(igElem.endPosArray);
38745
+
38746
+ for(let j = 0, jl = igElem.startPosArray.length; j < jl; ++j) {
38747
+ let pos = igElem.startPosArray[j];
38748
+ posindex2domainindex[pos] = i;
38749
+ }
39158
38750
  }
39159
38751
 
39160
38752
  // let htmlCnt = '<span class="icn3d-residueNum" title="Ig domain count">' + igCnt.toString() + ' Igs</span>';
@@ -39186,11 +38778,6 @@ class AnnoIg {
39186
38778
  html3 += htmlTmp + '<br>';
39187
38779
  html += htmlTmp + '<span class="icn3d-seqLine">';
39188
38780
 
39189
- // summary html2
39190
- html2 += htmlTitle;
39191
- html2 += htmlCnt + '<span class="icn3d-seqLine">';
39192
-
39193
-
39194
38781
  html += htmlIg;
39195
38782
 
39196
38783
  html += htmlCnt;
@@ -39200,7 +38787,8 @@ class AnnoIg {
39200
38787
  html += '</div>';
39201
38788
 
39202
38789
  let igArray = ic.chain2igArray[chnid];
39203
- if(igArray.length == 0) return {html: '', html2: '', html3: ''};
38790
+
38791
+ if(igArray.length == 0) return {html: html, html2: html2, html3: html3}
39204
38792
  let rangeArray = [], titleArray = [], fullTitleArray = [], domainArray = [];
39205
38793
 
39206
38794
  for(let i = 0, il = igArray.length; i < il; ++i) {
@@ -39210,45 +38798,59 @@ class AnnoIg {
39210
38798
 
39211
38799
  let tmscore = info.score;
39212
38800
  let igType = ic.ref2igtype[info.refpdbname];
39213
- titleArray.push(igType + ' (TM:' + parseFloat(tmscore).toFixed(2) + ')');
39214
- fullTitleArray.push(igType + ' (TM:' + parseFloat(tmscore).toFixed(2) + '), template: ' + info.refpdbname + ', Seq. identity: ' + parseFloat(info.seqid).toFixed(2) + ', aligned residues: ' + info.nresAlign);
38801
+ let confidance = (parseFloat(tmscore) < 0.75 ) ? '?' : '';
38802
+ titleArray.push(igType + confidance + ' (TM:' + parseFloat(tmscore).toFixed(2) + ')');
38803
+ fullTitleArray.push(igType + confidance + ' (TM:' + parseFloat(tmscore).toFixed(2) + '), template: ' + info.refpdbname + ', Seq. identity: ' + parseFloat(info.seqid).toFixed(2) + ', aligned residues: ' + info.nresAlign);
39215
38804
  domainArray.push(igType);
39216
38805
 
38806
+ let segs = [];
38807
+ for(let j = 0, jl = igArray[i].startPosArray.length; j < jl; ++j) {
38808
+ segs.push({"from":igArray[i].startPosArray[j], "to":igArray[i].endPosArray[j]});
38809
+ }
39217
38810
  let range = {};
39218
- range.locs = [{"from":igArray[i].startPos, "to":igArray[i].endPos}];
38811
+ range.locs = [{"segs": segs}];
39219
38812
  rangeArray.push(range);
39220
38813
  }
39221
- if(titleArray.length == 0) return {html: '', html2: '', html3: ''};
38814
+
38815
+ if(titleArray.length == 0) return {html: html, html2: html2, html3: html3}
39222
38816
 
39223
38817
  // add tracks for the summary view
39224
- for(let i = 0, il = fromArray.length; i < il; ++i) {
39225
- let resi = ic.ParserUtilsCls.getResi(chnid, fromArray[i]);
39226
- let resid = chnid + "_" + resi;
39227
- let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]);
39228
- let colorStr =(!atom || atom.color === undefined || atom.color.getHexString() === 'FFFFFF') ? 'DDDDDD' : atom.color.getHexString();
39229
- let color =(atom && atom.color !== undefined) ? colorStr : "CCCCCC";
38818
+ if(!kabat_or_imgt && !bCustom) {
38819
+ // summary html2
38820
+ html2 += htmlTitle;
38821
+ html2 += htmlCnt + '<span class="icn3d-seqLine">';
39230
38822
 
39231
- let emptyWidth =(i == 0) ? Math.round(ic.seqAnnWidth *(fromArray[i]) / ic.maxAnnoLength) :
39232
- Math.round(ic.seqAnnWidth *(fromArray[i] - toArray[i-1] - 1) / ic.maxAnnoLength);
39233
- html2 += '<div style="display:inline-block; width:' + emptyWidth + 'px;">&nbsp;</div>';
39234
- 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>';
39235
- }
38823
+ for(let i = 0, il = fromArray.length; i < il; ++i) {
38824
+ let resi = ic.ParserUtilsCls.getResi(chnid, fromArray[i]);
38825
+ let resid = chnid + "_" + resi;
38826
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]);
38827
+ let colorStr =(!atom || atom.color === undefined || atom.color.getHexString() === 'FFFFFF') ? 'DDDDDD' : atom.color.getHexString();
38828
+ let color =(atom && atom.color !== undefined) ? colorStr : "CCCCCC";
39236
38829
 
39237
- html2 += htmlCnt;
38830
+ let domainindex = posindex2domainindex[fromArray[i]];
39238
38831
 
39239
- html2 += '</div></div>';
39240
- html3 += '</div></div>';
38832
+ let emptyWidth =(i == 0) ? Math.round(ic.seqAnnWidth *(fromArray[i]) / ic.maxAnnoLength) :
38833
+ Math.round(ic.seqAnnWidth *(fromArray[i] - toArray[i-1] - 1) / ic.maxAnnoLength);
38834
+ html2 += '<div style="display:inline-block; width:' + emptyWidth + 'px;">&nbsp;</div>';
38835
+ 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>';
38836
+ }
38837
+
38838
+ html2 += htmlCnt;
39241
38839
 
39242
- // add tracks for each Ig domain
39243
- htmlTmp = '<div id="' + ic.pre + chnid + '_igseq_sequence" class="icn3d-ig icn3d-dl_sequence">';
39244
- let htmlTmp2 = htmlTmp;
39245
- let htmlTmp3 = htmlTmp;
38840
+ html2 += '</div></div>';
38841
+ html3 += '</div></div>';
39246
38842
 
39247
- let result = ic.annoCddSiteCls.setDomainFeature(rangeArray, chnid, 'ig', htmlTmp, htmlTmp2, htmlTmp3, undefined, titleArray, fullTitleArray);
38843
+ // add tracks for each Ig domain
38844
+ htmlTmp = '<div id="' + ic.pre + chnid + '_igseq_sequence" class="icn3d-ig icn3d-dl_sequence">';
38845
+ let htmlTmp2 = htmlTmp;
38846
+ let htmlTmp3 = htmlTmp;
39248
38847
 
39249
- html += result.html + '</div>';
39250
- html2 += result.html2 + '</div>';
39251
- html3 += result.html3 + '</div>';
38848
+ let result = ic.annoCddSiteCls.setDomainFeature(rangeArray, chnid, 'ig', htmlTmp, htmlTmp2, htmlTmp3, undefined, titleArray, fullTitleArray);
38849
+
38850
+ html += result.html + '</div>';
38851
+ html2 += result.html2 + '</div>';
38852
+ html3 += result.html3 + '</div>';
38853
+ }
39252
38854
 
39253
38855
  return {html: html, html2: html2, html3: html3}
39254
38856
  }
@@ -39630,7 +39232,9 @@ class AnnoDomain {
39630
39232
 
39631
39233
  if(me.cfg.blast_rep_id != chnid) { // regular
39632
39234
  for(let i = 0, il = fromArray.length; i < il; ++i) {
39633
- 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);
39235
+ // 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);
39236
+ let emptyWidth =(i == 0) ? Math.round(ic.seqAnnWidth *(fromArray[i]) / ic.maxAnnoLength) : Math.round(ic.seqAnnWidth *(fromArray[i] - toArray[i-1] - 1) / ic.maxAnnoLength);
39237
+
39634
39238
  html2 += '<div style="display:inline-block; width:' + emptyWidth + 'px;">&nbsp;</div>';
39635
39239
  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>';
39636
39240
  }
@@ -41239,7 +40843,7 @@ class Domain3d {
41239
40843
  // get a list of Calpha-Calpha contacts
41240
40844
  ///list< pair< pair< int, let >, let > >
41241
40845
  let cts = this.c2b_AlphaContacts(seqLen, x0, y0, z0, dcut, resiArray);
41242
-
40846
+
41243
40847
  //
41244
40848
  // Produce a "map" of the SSEs, i.e. vec_sse[i] = 0 means residue i + 1
41245
40849
  // is in a loop, and vec_sse[i] = k means residue i + 1 belongs to SSE
@@ -41300,7 +40904,7 @@ class Domain3d {
41300
40904
  vec_cts1.push(i + 1);
41301
40905
  vec_cts2.push(i + 1);
41302
40906
  }
41303
-
40907
+
41304
40908
  // create contact counts from the contacts/interactions
41305
40909
  //map< pair< int, let >, let > ctable = this.c2b_ContactTable(vec_cts1, vec_cts2);
41306
40910
  let ctable = this.c2b_ContactTable(vec_cts1, vec_cts2);
@@ -41324,7 +40928,7 @@ class Domain3d {
41324
40928
  sheetNeighbor[ss2][ss1] = 1;
41325
40929
  }
41326
40930
  }
41327
-
40931
+
41328
40932
  //https://www.geeksforgeeks.org/number-groups-formed-graph-friends/
41329
40933
  let existing_groups = 0;
41330
40934
  let sheet2sheetnum = {};
@@ -41452,7 +41056,7 @@ class Domain3d {
41452
41056
  this.parts[2*i] = this.parts[2*i + 1] = 0;
41453
41057
  ratios[i] = 0.0;
41454
41058
  }
41455
-
41059
+
41456
41060
  n_saved = this.new_split_chain(nsse, sratio, minSize, minSSE, maxCsz, avgCts, cDelta, ncFact, this.parts, n_saved, ratios);
41457
41061
 
41458
41062
  // save domain data
@@ -41500,6 +41104,36 @@ class Domain3d {
41500
41104
 
41501
41105
  list_parts = list_partsTmp;
41502
41106
 
41107
+ // if there is only one domain, add all
41108
+ if(list_parts.length == 0) {
41109
+ let groupnum2cnt = {}, groupnum2sseList = {}, chosenGroupnum = 0;
41110
+ for(let i = 0, il = this.group_num.length; i < il; ++i) {
41111
+ let groupnum = this.group_num[i];
41112
+ let sse = i + 1;
41113
+ if(groupnum && groupnum != i + 1) {
41114
+ if(!groupnum2sseList[groupnum]) groupnum2sseList[groupnum] = [];
41115
+ // collect all sse for this groupnum
41116
+ groupnum2sseList[groupnum].push(sse);
41117
+
41118
+ if(!groupnum2cnt[groupnum]) {
41119
+ groupnum2cnt[groupnum] = 1;
41120
+ }
41121
+ else {
41122
+ ++groupnum2cnt[groupnum];
41123
+ if(groupnum2cnt[groupnum] >= 3) { // minimum 3 sse
41124
+ chosenGroupnum = groupnum;
41125
+ }
41126
+ }
41127
+ }
41128
+ }
41129
+
41130
+ if(chosenGroupnum != 0) { // found a domain
41131
+ let sseArray = [chosenGroupnum].concat(groupnum2sseList[chosenGroupnum]);
41132
+
41133
+ list_parts.push(sseArray);
41134
+ }
41135
+ }
41136
+
41503
41137
  //for (lplet = list_parts.begin(); lplet != list_parts.end(); lpint++) {
41504
41138
  for (let index = 0, indexl = list_parts.length; index < indexl; ++index) {
41505
41139
  //vector<int> prts = *lpint;
@@ -41637,7 +41271,7 @@ class Domain3d {
41637
41271
  ic.tddomains[domainName][resid] = 1;
41638
41272
  }
41639
41273
  }
41640
- }
41274
+ }
41641
41275
 
41642
41276
  return {subdomains: subdomains, substruct: substruct, pos2resi: pos2resi };
41643
41277
  } // end c2b_NewSplitChain
@@ -44193,7 +43827,8 @@ class Annotation {
44193
43827
 
44194
43828
  ic.hlUpdateCls.updateHlAll();
44195
43829
  ic.drawCls.draw();
44196
- }
43830
+ }
43831
+
44197
43832
  }
44198
43833
  }
44199
43834
 
@@ -53803,7 +53438,7 @@ class PdbParser {
53803
53438
  //Load structures from a "URL". Due to the same domain policy of Ajax call, the URL should be in the same
53804
53439
  //domain. "type" could be "pdb", "mol2", "sdf", "xyz", "icn3dpng", or "pae"
53805
53440
  //for pdb file, mol2file, sdf file, xyz file, iCn3D PNG image, and ALphaFold PAE file, respectively.
53806
- async downloadUrl(url, type, command) { let ic = this.icn3d, me = ic.icn3dui;
53441
+ async downloadUrl(url, type, command, template) { let ic = this.icn3d, me = ic.icn3dui;
53807
53442
  let pos = url.lastIndexOf('/');
53808
53443
  if(pos != -1) {
53809
53444
  let posDot = url.lastIndexOf('.');
@@ -53821,9 +53456,19 @@ class PdbParser {
53821
53456
  ic.InputfileData = (ic.InputfileData) ? ic.InputfileData + '\nENDMDL\n' + data : data;
53822
53457
  ic.InputfileType = type;
53823
53458
 
53459
+ // append
53460
+ ic.hAtoms = {};
53461
+ ic.dAtoms = {};
53462
+
53463
+ ic.resetConfig();
53464
+ ic.bResetAnno = true;
53465
+ ic.bResetSets = true;
53466
+
53824
53467
  if(type === 'pdb') {
53825
- await this.loadPdbData(data);
53826
- //await ic.loadScriptCls.loadScript(command, undefined, true);
53468
+ // await this.loadPdbData(data);
53469
+ let bAppend = true;
53470
+ let id = (template) ? template.replace(/_/g, '').substr(0, 4) : undefined;
53471
+ await this.loadPdbData(data, id, undefined, bAppend);
53827
53472
  }
53828
53473
  else if(type === 'mmcif') {
53829
53474
  let url = me.htmlCls.baseUrl + "mmcifparser/mmcifparser.cgi";
@@ -53851,6 +53496,17 @@ class PdbParser {
53851
53496
  let bFull = true;
53852
53497
  ic.contactMapCls.processAfErrorMap(JSON.parse(data), bFull);
53853
53498
  }
53499
+
53500
+ //append
53501
+ if(ic.bSetChainsAdvancedMenu) ic.definedSetsCls.showSets();
53502
+
53503
+ ic.bResetAnno = true;
53504
+
53505
+ if(ic.bAnnoShown) {
53506
+ await ic.showAnnoCls.showAnnotations();
53507
+
53508
+ ic.annotationCls.resetAnnoTabAll();
53509
+ }
53854
53510
  }
53855
53511
 
53856
53512
  //Atom "data" from PDB file was parsed to set up parameters for the 3D viewer. The deferred parameter
@@ -67005,7 +66661,7 @@ class Dssp {
67005
66661
  ic.ref2igtype['BArrestin1_4jqiA_rat_n1'] = 'IgFN3-like';
67006
66662
  ic.ref2igtype['BTLA_2aw2A_human_Iset'] = 'IgI';
67007
66663
  ic.ref2igtype['C3_2qkiD_human_n1'] = 'IgFN3-like';
67008
- ic.ref2igtype['CD19_6al5A_human_C2orV-n1'] = 'other Ig'; //'CD19';
66664
+ ic.ref2igtype['CD19_6al5A_human_C2orV-n1'] = 'CD19';
67009
66665
  ic.ref2igtype['CD28_1yjdC_human_V'] = 'IgV';
67010
66666
  ic.ref2igtype['CD2_1hnfA_human_C2-n2'] = 'IgC2';
67011
66667
  ic.ref2igtype['CD2_1hnfA_human_V-n1'] = 'IgV';
@@ -67016,8 +66672,8 @@ class Dssp {
67016
66672
  ic.ref2igtype['CoAtomerGamma1_1r4xA_human'] = 'IgE';
67017
66673
  ic.ref2igtype['Contactin1_2ee2A_human_FN3-n9'] = 'IgFN3';
67018
66674
  ic.ref2igtype['Contactin1_3s97C_human_C2-n2'] = 'IgC2';
67019
- ic.ref2igtype['CuZnSuperoxideDismutase_1hl5C_human'] = 'other Ig'; //'SOD';
67020
- ic.ref2igtype['ECadherin_4zt1A_human_n2'] = 'other Ig'; //'Cadherin';
66675
+ ic.ref2igtype['CuZnSuperoxideDismutase_1hl5C_human'] = 'SOD';
66676
+ ic.ref2igtype['ECadherin_4zt1A_human_n2'] = 'Cadherin';
67021
66677
  ic.ref2igtype['Endo-1,4-BetaXylanase10A_1i8aA_bacteria_n4'] = 'IgE';
67022
66678
  ic.ref2igtype['FAB-HEAVY_5esv_C1-n2'] = 'IgC1';
67023
66679
  ic.ref2igtype['FAB-HEAVY_5esv_V-n1'] = 'IgV';
@@ -67033,12 +66689,12 @@ class Dssp {
67033
66689
  ic.ref2igtype['JAM1_1nbqA_human_VorIset-n2'] = 'IgI';
67034
66690
  ic.ref2igtype['LAG3_7tzgD_human_C2-n2'] = 'IgC2';
67035
66691
  ic.ref2igtype['LAG3_7tzgD_human_V-n1'] = 'IgV';
67036
- ic.ref2igtype['LaminAC_1ifrA_human'] = 'other Ig'; //'Lamin';
66692
+ ic.ref2igtype['LaminAC_1ifrA_human'] = 'Lamin';
67037
66693
  ic.ref2igtype['MHCIa_7phrH_human_C1'] = 'IgC1';
67038
66694
  ic.ref2igtype['MPT63_1lmiA_bacteria'] = 'IgE';
67039
66695
  ic.ref2igtype['NaCaExchanger_2fwuA_dog_n2'] = 'IgE';
67040
66696
  ic.ref2igtype['NaKATPaseTransporterBeta_2zxeB_spurdogshark'] = 'IgE';
67041
- ic.ref2igtype['ORF7a_1xakA_virus'] = 'other Ig'; //'ORF';
66697
+ ic.ref2igtype['ORF7a_1xakA_virus'] = 'ORF';
67042
66698
  ic.ref2igtype['PD1_4zqkB_human_V'] = 'IgV';
67043
66699
  ic.ref2igtype['PDL1_4z18B_human_V-n1'] = 'IgV';
67044
66700
  ic.ref2igtype['Palladin_2dm3A_human_Iset-n1'] = 'IgI';
@@ -67089,7 +66745,7 @@ class Dssp {
67089
66745
  let numRound = 0;
67090
66746
 
67091
66747
  //while(!bNoMoreIg) {
67092
- while(!bNoMoreIg && numRound < 10) {
66748
+ while(!bNoMoreIg && numRound < 15) {
67093
66749
  let bRerun = true;
67094
66750
  bNoMoreIg = await thisClass.parseRefPdbData(ic.pdbDataArray, template, bRerun);
67095
66751
  ++numRound;
@@ -67128,7 +66784,7 @@ class Dssp {
67128
66784
  for(let j = 0, jl = chainidArray.length; j < jl; ++j) {
67129
66785
  let chainid = chainidArray[j];
67130
66786
 
67131
- // for selected atoms only, assign ic.resid2domainid[resid]
66787
+ // for selected atoms only
67132
66788
  let domainAtomsArray = this.getDomainAtomsArray(chainid, bRerun);
67133
66789
 
67134
66790
  if(!ic.domainid2refpdbname) ic.domainid2refpdbname = {};
@@ -67169,7 +66825,7 @@ class Dssp {
67169
66825
  }
67170
66826
  }
67171
66827
  else {
67172
- ic.domainid2refpdbname[domainid] = template;
66828
+ ic.domainid2refpdbname[domainid] = [template];
67173
66829
  domainidpairArray.push(domainid + "|1" + template); // "1" was added for the first round strand-only template
67174
66830
  }
67175
66831
  }
@@ -67209,9 +66865,6 @@ class Dssp {
67209
66865
  let pdbDataArray = await this.promiseWithFixedJobs(pdbAjaxArray);
67210
66866
 
67211
66867
  for(let domainid in ic.domainid2refpdbname) {
67212
- ic.domainid2refpdbname[domainid];
67213
- domainid.substr(0, domainid.indexOf(','));
67214
-
67215
66868
  let pdb_target = ic.domainid2pdb[domainid];
67216
66869
  for(let index = 0, indexl = pdbDataArray.length; index < indexl; ++index) {
67217
66870
  let struct2 = ic.defaultPdbId + index;
@@ -67272,12 +66925,10 @@ class Dssp {
67272
66925
 
67273
66926
  if(bRerunDomain) {
67274
66927
  let atomsAssigned = {};
66928
+ //ic.resid2refnum_ori should be used
67275
66929
  for(let resid in ic.resid2refnum_ori) {
67276
66930
  atomsAssigned = me.hashUtilsCls.unionHash(atomsAssigned, ic.residues[resid]);
67277
66931
  }
67278
- // for(let resid in ic.resid2refnum) {
67279
- // if(ic.resid2refnum[resid]) atomsAssigned = me.hashUtilsCls.unionHash(atomsAssigned, ic.residues[resid]);
67280
- // }
67281
66932
 
67282
66933
  currAtoms = me.hashUtilsCls.exclHash(currAtoms, atomsAssigned);
67283
66934
 
@@ -67297,23 +66948,16 @@ class Dssp {
67297
66948
  let result = ic.domain3dCls.c2b_NewSplitChain(currAtoms, undefined);
67298
66949
  let subdomains = result.subdomains;
67299
66950
  let pos2resi = result.pos2resi;
67300
-
66951
+ /*
67301
66952
  if(subdomains.length <= 1) {
67302
66953
  let residueArray = ic.resid2specCls.atoms2residues(Object.keys(currAtoms));
67303
66954
  if(residueArray.length < minResidues) return domainAtomsArray;
67304
- /*
67305
- let atomFirst = ic.firstAtomObjCls.getFirstAtomObj(currAtoms);
67306
- let atomLast = ic.firstAtomObjCls.getLastAtomObj(currAtoms);
67307
- let resiSum = atomFirst.resi + ':' + atomLast.resi + ':' + Object.keys(currAtoms).length;
67308
- */
66955
+
67309
66956
  for(let n = 0, nl = residueArray.length; n < nl; ++n) {
67310
66957
  let resid = residueArray[n];
67311
- /*
67312
- ic.resid2domainid[resid] = chainid + ',0' + '_' + resiSum;
67313
- */
66958
+
67314
66959
  // clear previous refnum assignment if any
67315
- // if(!bRerunDomain && ic.resid2refnum && ic.resid2refnum[resid]) {
67316
- // if(ic.resid2refnum && ic.resid2refnum[resid]) {
66960
+ // if(bRerunDomain) {
67317
66961
  delete ic.resid2refnum[resid];
67318
66962
  delete ic.residIgLoop[resid];
67319
66963
  // }
@@ -67321,27 +66965,27 @@ class Dssp {
67321
66965
 
67322
66966
  domainAtomsArray.push(currAtoms);
67323
66967
  }
67324
- else {
66968
+ else
66969
+ */
66970
+
66971
+ if(subdomains.length >= 1) {
67325
66972
  for(let k = 0, kl = subdomains.length; k < kl; ++k) {
67326
66973
  let domainAtoms = {};
67327
66974
  let segArray = subdomains[k];
67328
66975
 
67329
66976
  let resCnt = 0;
67330
66977
  for(let m = 0, ml = segArray.length; m < ml; m += 2) {
67331
- let startResi = segArray[m];
67332
- let endResi = segArray[m+1];
67333
- for(let n = parseInt(startResi); n <= parseInt(endResi); ++n) {
66978
+ let startResi = parseInt(segArray[m]);
66979
+ let endResi = parseInt(segArray[m+1]);
66980
+
66981
+ for(let n = startResi; n <= endResi; ++n) {
67334
66982
  let resid = chainid + '_' + pos2resi[n];
67335
66983
  ++resCnt;
67336
66984
  domainAtoms = me.hashUtilsCls.unionHash(domainAtoms, ic.residues[resid]);
67337
- //ic.resid2domainid[resid] = chainid + '-' + k;
67338
66985
 
67339
66986
  // clear previous refnum assignment if any
67340
- // if(!bRerunDomain && ic.resid2refnum && ic.resid2refnum[resid]) {
67341
- // if(ic.resid2refnum && ic.resid2refnum[resid]) {
67342
- delete ic.resid2refnum[resid];
67343
- delete ic.residIgLoop[resid];
67344
- // }
66987
+ delete ic.resid2refnum[resid];
66988
+ delete ic.residIgLoop[resid];
67345
66989
  }
67346
66990
  }
67347
66991
 
@@ -67372,7 +67016,7 @@ class Dssp {
67372
67016
  getTemplateList(domainid) { let ic = this.icn3d; ic.icn3dui;
67373
67017
  let refpdbname = '', score = '', seqid = '', nresAlign = '';
67374
67018
 
67375
- refpdbname = ic.domainid2refpdbname[domainid];
67019
+ refpdbname = ic.domainid2refpdbname[domainid][0]; // one template in round 2
67376
67020
 
67377
67021
  if(ic.domainid2score[domainid]) {
67378
67022
  let itemArray = ic.domainid2score[domainid].split('_');
@@ -67392,6 +67036,8 @@ class Dssp {
67392
67036
 
67393
67037
  // find the best alignment for each chain
67394
67038
  let domainid2segs = {};
67039
+ let domainid2strandcnt = {};
67040
+ let domainid2refpdbnamelist = {};
67395
67041
 
67396
67042
  if(!ic.chainid2refpdbname) ic.chainid2refpdbname = {};
67397
67043
  // if(!ic.chainid2score) ic.chainid2score = {};
@@ -67484,7 +67130,7 @@ class Dssp {
67484
67130
  if(!me.bNode && !(bBstrand && bCstrand && bEstrand && bFstrand)) console.log("Some of the Ig strands B, C, E, F are missing in the domain " + domainid + "...");
67485
67131
  if(!me.bNode && !(bBSheet && bCSheet && bESheet && bFSheet)) console.log("Some of the Ig strands B, C, E, F are not beta sheets...");
67486
67132
  // 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 + "...");
67487
- if(ic.domainid2refpdbname[domainid] == refpdbname) {
67133
+ if(ic.domainid2refpdbname[domainid][0] == refpdbname) {
67488
67134
  delete ic.domainid2refpdbname[domainid];
67489
67135
  delete ic.domainid2score[domainid];
67490
67136
  }
@@ -67496,21 +67142,67 @@ class Dssp {
67496
67142
  if(!me.bNode) console.log("domainid: " + domainid);
67497
67143
  }
67498
67144
 
67499
- if(!domainid2segs.hasOwnProperty(domainid) || queryData[0].score >= ic.domainid2score[domainid].split('_')[0]) {
67145
+ // count the number of matched strands
67146
+ let strandHash = {};
67147
+ for(let j = 0, jl = queryData[0].segs.length; j < jl; ++j) {
67148
+ let seg = queryData[0].segs[j];
67149
+ let q_start = parseInt(seg.q_start);
67150
+
67151
+ let strand = this.getStrandFromRefnum(q_start);
67152
+ strandHash[strand] = 1;
67153
+ }
67154
+ let score = parseFloat(queryData[0].score);
67155
+ //!!!
67156
+ // if the TM score difference is within 0.1 and more strands are found, use the template with more strands
67157
+ // if(!domainid2segs.hasOwnProperty(domainid) ||
67158
+ // (score >= parseFloat(ic.domainid2score[domainid].split('_')[0]) + tmAdjust)
67159
+ // || (score >= parseFloat(ic.domainid2score[domainid].split('_')[0]) - tmAdjust && score < parseFloat(ic.domainid2score[domainid].split('_')[0]) + tmAdjust && Object.keys(strandHash).length > domainid2strandcnt[domainid])
67160
+ // ) {
67161
+
67162
+ // use TM-score alone
67163
+ if(!domainid2segs.hasOwnProperty(domainid) || score >= parseFloat(ic.domainid2score[domainid].split('_')[0])) {
67500
67164
  ic.domainid2score[domainid] = queryData[0].score + '_' + queryData[0].frac_identical + '_' + queryData[0].num_res ;
67165
+
67501
67166
  if(bRound1) {
67502
- ic.domainid2refpdbname[domainid] = parseFloat(queryData[0].score) > 0.75 ? refpdbname : 'all_templates';
67167
+ ic.domainid2refpdbname[domainid] = score > 0.75 ? [refpdbname] : ['all_templates'];
67503
67168
  }
67504
67169
  else {
67505
- ic.domainid2refpdbname[domainid] = refpdbname;
67170
+ ic.domainid2refpdbname[domainid] = [refpdbname];
67506
67171
  }
67172
+
67507
67173
  domainid2segs[domainid] = queryData[0].segs;
67174
+ domainid2strandcnt[domainid] = Object.keys(strandHash).length;
67175
+
67508
67176
  ic.domainid2ig2kabat[domainid] = queryData[0].ig2kabat;
67509
67177
  ic.domainid2ig2imgt[domainid] = queryData[0].ig2imgt;
67510
67178
  }
67179
+
67180
+ if(bRound1) {
67181
+ if(!domainid2refpdbnamelist[domainid]) domainid2refpdbnamelist[domainid] = {};
67182
+ domainid2refpdbnamelist[domainid][refpdbname] = score;
67183
+ }
67511
67184
  }
67512
67185
 
67513
- return domainid2segs;
67186
+ //!!!
67187
+ /*
67188
+ // combine the top three clusters for the 2nd round alignment
67189
+ if(bRound1) {
67190
+ for(let domainid in domainid2refpdbnamelist) {
67191
+ if(!me.bNode) console.log("###score " + ic.domainid2score[domainid].split('_')[0] + " ic.domainid2refpdbname[domainid][0] " + ic.domainid2refpdbname[domainid][0])
67192
+ if(!me.bNode && ic.domainid2refpdbname[domainid][0] == 'all_templates') {
67193
+ let refpdbname2score = domainid2refpdbnamelist[domainid];
67194
+ let refpdbnameList = Object.keys(refpdbname2score);
67195
+ refpdbnameList.sort(function(a, b) {
67196
+ return refpdbname2score[b] - refpdbname2score[a]
67197
+ });
67198
+ // top 3 templates
67199
+ ic.domainid2refpdbname[domainid] = refpdbnameList.slice(0,3);
67200
+ }
67201
+ if(!me.bNode) console.log("###bb ic.domainid2refpdbname[domainid] " + ic.domainid2refpdbname[domainid])
67202
+ }
67203
+ }
67204
+ */
67205
+ return domainid2segs; // only used in round 2
67514
67206
  }
67515
67207
 
67516
67208
  async parseAlignData(dataArray, domainidpairArray, bRound1) { let ic = this.icn3d, me = ic.icn3dui;
@@ -67518,6 +67210,7 @@ class Dssp {
67518
67210
 
67519
67211
  let domainid2segs = this.parseAlignData_part1(dataArray, domainidpairArray, bRound1);
67520
67212
 
67213
+ // !!!no more Igs to detect
67521
67214
  if(Object.keys(domainid2segs).length == 0) {
67522
67215
  bNoMoreIg = true;
67523
67216
  return bNoMoreIg;
@@ -67532,25 +67225,30 @@ class Dssp {
67532
67225
  let urltmalign = me.htmlCls.tmalignUrl;
67533
67226
  for(let domainid in ic.domainid2refpdbname) {
67534
67227
  let pdbAjaxArray = [];
67535
- let refpdbname = ic.domainid2refpdbname[domainid];
67228
+ let refpdbnameList = ic.domainid2refpdbname[domainid];
67536
67229
  //let pdbid = domainid.substr(0, domainid.indexOf('_'));
67537
67230
  let chainid = domainid.substr(0, domainid.indexOf(','));
67538
67231
 
67539
- //if(ic.refpdbHash.hasOwnProperty(pdbid)) {
67540
67232
  if(ic.refpdbHash.hasOwnProperty(chainid)) {
67541
- // use itself as the ref structure
67542
- //refpdbname = pdbid;
67543
- refpdbname = chainid;
67233
+ refpdbnameList = [chainid];
67544
67234
 
67545
- if(!me.bNode) console.log("Adjusted refpdbname for domainid " + domainid + ": " + refpdbname);
67235
+ if(!me.bNode) console.log("Adjusted refpdbname for domainid " + domainid + ": " + chainid);
67546
67236
  }
67547
67237
 
67548
- if(!ic.refpdbHash[refpdbname]) {
67238
+ let templates = [];
67239
+ for(let i = 0, il = refpdbnameList.length; i < il; ++i) {
67240
+ let refpdbname = refpdbnameList[i];
67241
+ if(!ic.refpdbHash[refpdbname]) continue;
67242
+ templates = templates.concat(ic.refpdbHash[refpdbname]);
67243
+ }
67244
+
67245
+ // if(!ic.refpdbHash[refpdbname]) {
67246
+ if(templates.length == 0) {
67549
67247
  continue;
67550
67248
  }
67551
67249
 
67552
- for(let k = 0, kl = ic.refpdbHash[refpdbname].length; k < kl; ++k) {
67553
- let urlpdb = me.htmlCls.baseUrl + "mmcifparser/mmcifparser.cgi?refpdbid=" + ic.refpdbHash[refpdbname][k];
67250
+ for(let k = 0, kl = templates.length; k < kl; ++k) {
67251
+ let urlpdb = me.htmlCls.baseUrl + "mmcifparser/mmcifparser.cgi?refpdbid=" + templates[k];
67554
67252
 
67555
67253
  let pdbAjax = me.getAjaxPromise(urlpdb, 'text');
67556
67254
 
@@ -67570,12 +67268,11 @@ class Dssp {
67570
67268
  let header = 'HEADER ' + struct2 + '\n';
67571
67269
  pdb_query = header + pdb_query;
67572
67270
 
67573
- let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target, "queryid": ic.refpdbHash[refpdbname][index]};
67271
+ let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target, "queryid": templates[index]};
67574
67272
  let alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
67575
67273
  ajaxArray.push(alignAjax);
67576
67274
 
67577
- //domainidpairArray3.push(domainid + "," + refpdbname);
67578
- domainidpairArray3.push(domainid + "|" + ic.refpdbHash[refpdbname][index]);
67275
+ domainidpairArray3.push(domainid + "|" + templates[index]);
67579
67276
  }
67580
67277
  }
67581
67278
 
@@ -67591,19 +67288,19 @@ class Dssp {
67591
67288
  return bNoMoreIg;
67592
67289
  }
67593
67290
 
67594
- await this.parseAlignData_part3(domainid2segs);
67291
+ this.parseAlignData_part3(domainid2segs);
67595
67292
 
67596
67293
  return bNoMoreIg;
67597
67294
  }
67598
67295
 
67599
- async parseAlignData_part3(domainid2segs) { let ic = this.icn3d, me = ic.icn3dui;
67296
+ parseAlignData_part3(domainid2segs) { let ic = this.icn3d, me = ic.icn3dui;
67600
67297
 
67601
67298
  // combine domainid into chainid
67602
67299
  let processedChainid = {};
67603
67300
 
67604
67301
  for(let domainid in ic.domainid2refpdbname) {
67605
67302
  // remove the first round template
67606
- if(ic.domainid2refpdbname[domainid].substr(0,1) == '1') {
67303
+ if(ic.domainid2refpdbname[domainid][0].substr(0,1) == '1') {
67607
67304
  delete ic.domainid2refpdbname[domainid];
67608
67305
  delete ic.domainid2score[domainid];
67609
67306
  continue;
@@ -67618,7 +67315,7 @@ class Dssp {
67618
67315
  processedChainid[chainid] = 1;
67619
67316
 
67620
67317
  if(!ic.chainid2refpdbname.hasOwnProperty(chainid)) ic.chainid2refpdbname[chainid] = [];
67621
- ic.chainid2refpdbname[chainid].push(ic.domainid2refpdbname[domainid] + '|' + domainid);
67318
+ ic.chainid2refpdbname[chainid].push(ic.domainid2refpdbname[domainid][0] + '|' + domainid);
67622
67319
 
67623
67320
  // if(!ic.chainid2score.hasOwnProperty(chainid)) ic.chainid2score[chainid] = [];
67624
67321
  // ic.chainid2score[chainid].push(ic.domainid2score[domainid] + '|' + domainid);
@@ -67648,9 +67345,6 @@ class Dssp {
67648
67345
  let segArray = domainid2segs[domainid];
67649
67346
  let chainid = domainid.split(',')[0];
67650
67347
 
67651
- // let refpdbnameArray = ic.chainid2refpdbname[chainid];
67652
-
67653
- // let result = this.getTemplateList(chainid);
67654
67348
  let result = this.getTemplateList(domainid);
67655
67349
  let refpdbname = result.refpdbname;
67656
67350
  let score = result.score;
@@ -67818,6 +67512,15 @@ class Dssp {
67818
67512
  }
67819
67513
  }
67820
67514
 
67515
+ if(!ic.chainid2igtrack) ic.chainid2igtrack = {};
67516
+ for(let chainid in ic.chains) {
67517
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chainid]);
67518
+ if(ic.proteins.hasOwnProperty(atom.serial)) {
67519
+ let giSeq = ic.showSeqCls.getSeq(chainid);
67520
+ ic.chainid2igtrack[chainid] = this.ajdustRefnum(giSeq, chainid);
67521
+ }
67522
+ }
67523
+
67821
67524
  /*
67822
67525
  if(Object.keys(ic.resid2refnum).length > 0) {
67823
67526
  ic.bShowRefnum = true;
@@ -67847,7 +67550,7 @@ class Dssp {
67847
67550
  */
67848
67551
  }
67849
67552
 
67850
- getLabelFromRefnum(oriRefnum, prevStrand) { let ic = this.icn3d; ic.icn3dui;
67553
+ getStrandFromRefnum(oriRefnum, prevStrand) { let ic = this.icn3d; ic.icn3dui;
67851
67554
  let refnum = parseInt(oriRefnum);
67852
67555
 
67853
67556
  //N-terminus = 0999-0001
@@ -67874,33 +67577,44 @@ class Dssp {
67874
67577
 
67875
67578
  // loops may have numbers such as 1310, 1410
67876
67579
 
67877
- let refnumLabel;
67878
-
67879
- if(refnum < 1000) refnumLabel = undefined;
67880
- else if(refnum >= 1200 && refnum < 1290) refnumLabel = "A---" + oriRefnum;
67881
- else if(refnum >= 1320 && refnum < 1390) refnumLabel = "A--" + oriRefnum;
67882
- else if(refnum >= 1420 && refnum < 1490) refnumLabel = "A-" + oriRefnum;
67883
- else if(refnum >= 1520 && refnum < 1590) refnumLabel = "A" + oriRefnum;
67884
- else if(refnum >= 1620 && refnum < 1690) refnumLabel = "A+" + oriRefnum;
67885
- else if(refnum >= 1820 && refnum < 1890) refnumLabel = "A'" + oriRefnum;
67886
- else if(refnum >= 2000 && refnum < 2900) refnumLabel = "B" + oriRefnum;
67887
- else if(refnum >= 3300 && refnum < 3390) refnumLabel = "C--" + oriRefnum;
67888
- else if(refnum >= 3420 && refnum < 3490) refnumLabel = "C-" + oriRefnum;
67889
- else if(refnum >= 3520 && refnum < 3590) refnumLabel = "C" + oriRefnum;
67890
- else if(refnum >= 4000 && refnum < 4900) refnumLabel = "C'" + oriRefnum;
67891
- else if(refnum >= 5000 && refnum < 5900) refnumLabel = "C''" + oriRefnum;
67892
- else if(refnum >= 6000 && refnum < 6900) refnumLabel = "D" + oriRefnum;
67893
- else if(refnum >= 7500 && refnum < 7590) refnumLabel = "E" + oriRefnum;
67894
- else if(refnum >= 7620 && refnum < 7900) refnumLabel = "E+" + oriRefnum;
67895
- else if(refnum >= 8000 && refnum < 8900) refnumLabel = "F" + oriRefnum;
67896
- else if(refnum >= 9500 && refnum < 9590) refnumLabel = "G" + oriRefnum;
67897
- else if(refnum >= 9620 && refnum < 9690) refnumLabel = "G+" + oriRefnum;
67898
- else if(refnum >= 9720 && refnum < 9790) refnumLabel = "G++" + oriRefnum;
67899
- else if(refnum > 9900) refnumLabel = undefined;
67900
- else refnumLabel = " " + oriRefnum;
67901
- if(prevStrand) refnumLabel = prevStrand + oriRefnum;
67902
-
67903
- return refnumLabel
67580
+ let strand;
67581
+
67582
+ if(refnum < 1000) strand = undefined;
67583
+ else if(refnum >= 1200 && refnum < 1290) strand = "A---";
67584
+ else if(refnum >= 1320 && refnum < 1390) strand = "A--";
67585
+ else if(refnum >= 1420 && refnum < 1490) strand = "A-";
67586
+ else if(refnum >= 1520 && refnum < 1590) strand = "A";
67587
+ else if(refnum >= 1620 && refnum < 1690) strand = "A+";
67588
+ else if(refnum >= 1820 && refnum < 1890) strand = "A'";
67589
+ else if(refnum >= 2000 && refnum < 2900) strand = "B";
67590
+ else if(refnum >= 3300 && refnum < 3390) strand = "C--";
67591
+ else if(refnum >= 3420 && refnum < 3490) strand = "C-";
67592
+ else if(refnum >= 3520 && refnum < 3590) strand = "C";
67593
+ else if(refnum >= 4000 && refnum < 4900) strand = "C'";
67594
+ else if(refnum >= 5000 && refnum < 5900) strand = "C''";
67595
+ else if(refnum >= 6000 && refnum < 6900) strand = "D";
67596
+ else if(refnum >= 7500 && refnum < 7590) strand = "E";
67597
+ else if(refnum >= 7620 && refnum < 7900) strand = "E+";
67598
+ else if(refnum >= 8000 && refnum < 8900) strand = "F";
67599
+ else if(refnum >= 9500 && refnum < 9590) strand = "G";
67600
+ else if(refnum >= 9620 && refnum < 9690) strand = "G+";
67601
+ else if(refnum >= 9720 && refnum < 9790) strand = "G++";
67602
+ else if(refnum > 9900) strand = undefined;
67603
+ else strand = " ";
67604
+ if(prevStrand) strand = prevStrand;
67605
+
67606
+ return strand
67607
+ }
67608
+
67609
+ getLabelFromRefnum(oriRefnum, prevStrand) { let ic = this.icn3d; ic.icn3dui;
67610
+ let strand = this.getStrandFromRefnum(oriRefnum, prevStrand);
67611
+
67612
+ if(strand) {
67613
+ return strand + oriRefnum;
67614
+ }
67615
+ else {
67616
+ return undefined;
67617
+ }
67904
67618
  }
67905
67619
 
67906
67620
  async parseCustomRefFile(data) { let ic = this.icn3d; ic.icn3dui;
@@ -67979,7 +67693,8 @@ class Dssp {
67979
67693
  // 1. show IgStrand ref numbers
67980
67694
  if(type == 'igstrand' || type == 'IgStrand') {
67981
67695
  // iGStrand reference numbers were adjusted when showing in sequences
67982
- if(me.bNode) {
67696
+ // if(me.bNode) {
67697
+ if(ic.bShowRefnum) {
67983
67698
  for(let chnid in ic.chains) {
67984
67699
  let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chnid]);
67985
67700
  if(ic.proteins.hasOwnProperty(atom.serial)) {
@@ -68021,29 +67736,6 @@ class Dssp {
68021
67736
 
68022
67737
  // refData += '{"Ig domain" : ' + bIgDomain + ', "ref PDB" : ' + JSON.stringify(ic.refPdbList) + ',\n';
68023
67738
  refData += '{"Ig domain" : ' + bIgDomain + ',\n';
68024
- /*
68025
- if(bIgDomain) {
68026
- refData += '"data": {\n';
68027
- for(let chnid in ic.chains) {
68028
- let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chnid]);
68029
- if(ic.proteins.hasOwnProperty(atom.serial)) {
68030
- let bIgChain = false;
68031
- let chainRefData = '"' + chnid + '": [\n';
68032
- for(let i = 0; i < ic.chainsSeq[chnid].length; ++i) {
68033
- const resid = chnid + '_' + ic.chainsSeq[chnid][i].resi + '_' + ic.chainsSeq[chnid][i].name;
68034
- chainRefData += '{"' + resid + '": "' + resid2refnum[resid] + '"},\n';
68035
- if(resid2refnum[resid]) bIgChain = true;
68036
- }
68037
- chainRefData += '],\n';
68038
-
68039
- if(bIgChain) {
68040
- refData += chainRefData;
68041
- }
68042
- }
68043
- }
68044
- refData += '}\n';
68045
- }
68046
- */
68047
67739
 
68048
67740
  if(bIgDomain) {
68049
67741
  refData += '"igs": [\n';
@@ -68054,8 +67746,8 @@ class Dssp {
68054
67746
  refData += '{"' + chnid + '": {\n';
68055
67747
 
68056
67748
  for(let i = 0, il = igArray.length; i < il; ++i) {
68057
- let startPos = igArray[i].startPos;
68058
- let endPos = igArray[i].endPos;
67749
+ let startPosArray = igArray[i].startPosArray;
67750
+ let endPosArray = igArray[i].endPosArray;
68059
67751
  let domainid = igArray[i].domainid;
68060
67752
  let info = ic.domainid2info[domainid];
68061
67753
  if(!info) continue;
@@ -68063,9 +67755,13 @@ class Dssp {
68063
67755
  refData += '"' + domainid + '": {\n';
68064
67756
 
68065
67757
  refData += '"refpdbname":"' + info.refpdbname + '", "score":' + info.score + ', "seqid":' + info.seqid + ', "nresAlign":' + info.nresAlign + ', "data": [';
68066
- for(let i = startPos; i <= endPos; ++i) {
68067
- const resid = chnid + '_' + ic.chainsSeq[chnid][i].resi + '_' + ic.chainsSeq[chnid][i].name;
68068
- refData += '{"' + resid + '": "' + resid2refnum[resid] + '"},\n';
67758
+ for(let j = 0, jl = startPosArray.length; j < jl; ++j) {
67759
+ let startPos = startPosArray[j];
67760
+ let endPos = endPosArray[j];
67761
+ for(let k = startPos; k <= endPos; ++k) {
67762
+ const resid = chnid + '_' + ic.chainsSeq[chnid][k].resi + '_' + ic.chainsSeq[chnid][k].name;
67763
+ refData += '{"' + resid + '": "' + resid2refnum[resid] + '"},\n';
67764
+ }
68069
67765
  }
68070
67766
  refData += '],\n';
68071
67767
 
@@ -68162,6 +67858,485 @@ class Dssp {
68162
67858
 
68163
67859
  return dataArray3;
68164
67860
  }
67861
+
67862
+ ajdustRefnum(giSeq, chnid) { let ic = this.icn3d, me = ic.icn3dui;
67863
+ if(!ic.chainid2refpdbname[chnid]) return false;
67864
+
67865
+ // auto-generate ref numbers for loops
67866
+ let currStrand = '', prevStrand = '';
67867
+ let refnumLabel, refnumStr_ori, refnumStr, postfix, strandPostfix, refnum, refnum3c, refnum2c;
67868
+ let bExtendedStrand = false, bSecThird9 = false;
67869
+
67870
+ // sometimes one chain may have several Ig domains,set an index for each IgDomain
67871
+ let index = 1, bStart = false;
67872
+
67873
+ if(!me.bNode) { // do not overwrite loops in node
67874
+ // reset ic.residIgLoop for the current selection, which could be the second round of ref num assignment
67875
+ // just current chain
67876
+ let atomHash = me.hashUtilsCls.intHash(ic.chains[chnid], ic.hAtoms);
67877
+ ic.firstAtomObjCls.getResiduesFromAtoms(atomHash);
67878
+ }
67879
+
67880
+ // 1. get the range of each strand excluding loops
67881
+ let strandArray = [], strandHash = {}, strandCnt = 0, resCnt = 0, resCntBfAnchor = 0, resCntAtAnchor = 0;
67882
+ let bFoundAnchor = false;
67883
+
67884
+ for(let i = 0, il = giSeq.length; i < il; ++i, ++resCnt, ++resCntBfAnchor, ++resCntAtAnchor) {
67885
+ let currResi = ic.ParserUtilsCls.getResi(chnid, i);
67886
+ let residueid = chnid + '_' + currResi;
67887
+ let domainid;
67888
+
67889
+ refnumLabel = ic.resid2refnum[residueid];
67890
+
67891
+ let firstChar = (refnumLabel) ? refnumLabel.substr(0,1) : '';
67892
+ if(!bStart && refnumLabel && (firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
67893
+ bStart = true;
67894
+ resCnt = 1; // the first one is included
67895
+ bFoundAnchor = false;
67896
+ }
67897
+
67898
+ //if((prevStrand.substr(0,1) == 'F' || prevStrand.substr(0,1) == 'G') && !refnumLabel) { // indicate the end of an IG domain
67899
+ if((prevStrand.substr(0,1) == 'G') && !refnumLabel) { // indicate the end of an IG domain
67900
+ bStart = false;
67901
+ }
67902
+
67903
+ if(refnumLabel) {
67904
+ domainid = ic.resid2domainid[residueid];
67905
+
67906
+ refnumStr_ori = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
67907
+ currStrand = refnumLabel.replace(new RegExp(refnumStr_ori,'g'), '');
67908
+ refnumStr_ori.substr(0, 1);
67909
+
67910
+ refnumStr = refnumStr_ori;
67911
+ refnum = parseInt(refnumStr);
67912
+ refnum3c = (refnum - parseInt(refnum/1000) * 1000).toString();
67913
+ refnum2c = (refnum - parseInt(refnum/100) * 100).toString();
67914
+
67915
+ // for extended strands, since A is 1550 and A+ is 1650, then the AA+ loop will be 1591, 1592, ... 1610, 1611, etc
67916
+ bSecThird9 = refnum3c.substr(0,1) == '9' || refnum2c.substr(0,1) == '9' || refnum2c.substr(0,1) == '0' || refnum2c.substr(0,1) == '1';
67917
+ if(bSecThird9) ic.residIgLoop[residueid] = 1;
67918
+
67919
+ strandPostfix = refnumStr.replace(refnum.toString(), '');
67920
+
67921
+ postfix = strandPostfix + '_' + index;
67922
+
67923
+ let firstTwo = parseInt(refnum.toString().substr(0, 2)); // check extended strands
67924
+ bExtendedStrand = refnum3c.substr(0,1) != '5' && firstTwo != '18'; // all strands and A' (18##)
67925
+
67926
+ if(currStrand && currStrand != ' ') {
67927
+ if(!bSecThird9 || (bExtendedStrand && !bSecThird9)) {
67928
+ let lastTwo = parseInt(refnum.toString().substr(refnum.toString().length - 2, 2));
67929
+
67930
+ if(currStrand != prevStrand) { // reset currCnt
67931
+ bFoundAnchor = false;
67932
+
67933
+ if(strandHash[currStrand + postfix]) {
67934
+ ++index;
67935
+ postfix = refnumStr.replace(refnum.toString(), '') + '_' + index;
67936
+ }
67937
+
67938
+ strandHash[currStrand + postfix] = 1;
67939
+
67940
+ strandArray[strandCnt] = {};
67941
+
67942
+ strandArray[strandCnt].startResi = currResi;
67943
+ strandArray[strandCnt].startRefnum = refnum; // 1250 in A1250a
67944
+
67945
+ resCntBfAnchor = 0;
67946
+
67947
+ strandArray[strandCnt].domainid = domainid;
67948
+
67949
+ strandArray[strandCnt].endResi = currResi;
67950
+ strandArray[strandCnt].endRefnum = refnum; // 1250a
67951
+
67952
+ if(lastTwo == 50) {
67953
+ strandArray[strandCnt].anchorRefnum = refnum;
67954
+ strandArray[strandCnt].resCntBfAnchor = resCntBfAnchor;
67955
+
67956
+ resCntAtAnchor = 0;
67957
+
67958
+ bFoundAnchor = true;
67959
+ }
67960
+
67961
+ // in case A1550 is not found, but A1551 is found
67962
+ if(!bFoundAnchor && (lastTwo == 51 || lastTwo == 52 || lastTwo == 53 || lastTwo == 54) ) {
67963
+ let offset = lastTwo - 50;
67964
+ strandArray[strandCnt].anchorRefnum = refnum - offset;
67965
+ strandArray[strandCnt].resCntBfAnchor = resCntBfAnchor - offset;
67966
+
67967
+ resCntAtAnchor = offset;
67968
+
67969
+ bFoundAnchor = true;
67970
+ }
67971
+
67972
+ if(bExtendedStrand) {
67973
+ strandArray[strandCnt].anchorRefnum = 0;
67974
+ }
67975
+
67976
+ strandArray[strandCnt].strandPostfix = strandPostfix; // a in A1250a
67977
+ strandArray[strandCnt].strand = currStrand; // A in A1250a
67978
+
67979
+ strandArray[strandCnt].postfix = postfix; // Aa_1
67980
+
67981
+ strandArray[strandCnt].loopResCnt = resCnt - 1;
67982
+
67983
+ ++strandCnt;
67984
+ resCnt = 0;
67985
+ }
67986
+ else {
67987
+ if(strandHash[currStrand + postfix]) {
67988
+ if(lastTwo == 50) {
67989
+ strandArray[strandCnt - 1].anchorRefnum = refnum;
67990
+ strandArray[strandCnt - 1].resCntBfAnchor = resCntBfAnchor;
67991
+
67992
+ // update
67993
+ strandArray[strandCnt - 1].startRefnum = strandArray[strandCnt - 1].anchorRefnum - strandArray[strandCnt - 1].resCntBfAnchor;
67994
+
67995
+ resCntAtAnchor = 0;
67996
+
67997
+ bFoundAnchor = true;
67998
+ }
67999
+
68000
+ // in case A1550 is not found, but A1551 is found
68001
+ if(!bFoundAnchor && (lastTwo == 51 || lastTwo == 52 || lastTwo == 53 || lastTwo == 54) ) {
68002
+ let offset = lastTwo - 50;
68003
+ strandArray[strandCnt - 1].anchorRefnum = refnum - offset;
68004
+ strandArray[strandCnt - 1].resCntBfAnchor = resCntBfAnchor - offset;
68005
+
68006
+ // update
68007
+ strandArray[strandCnt - 1].startRefnum = strandArray[strandCnt - 1].anchorRefnum - strandArray[strandCnt - 1].resCntBfAnchor;
68008
+
68009
+ resCntAtAnchor = offset;
68010
+
68011
+ bFoundAnchor = true;
68012
+ }
68013
+
68014
+ if(bExtendedStrand) {
68015
+ strandArray[strandCnt - 1].anchorRefnum = 0;
68016
+ }
68017
+
68018
+ strandArray[strandCnt - 1].domainid = domainid;
68019
+
68020
+ strandArray[strandCnt - 1].endResi = currResi;
68021
+ strandArray[strandCnt - 1].endRefnum = refnum; // 1250a
68022
+ strandArray[strandCnt - 1].resCntAtAnchor = resCntAtAnchor;
68023
+
68024
+ if(strandArray[strandCnt - 1].anchorRefnum) {
68025
+ strandArray[strandCnt - 1].endRefnum = strandArray[strandCnt - 1].anchorRefnum + strandArray[strandCnt - 1].resCntAtAnchor;
68026
+ }
68027
+
68028
+ resCnt = 0;
68029
+ }
68030
+ }
68031
+ }
68032
+ }
68033
+ }
68034
+
68035
+ prevStrand = currStrand;
68036
+ }
68037
+
68038
+ // 2. extend the strand to end of sheet
68039
+ let maxExtend = 8;
68040
+ for(let i = 0, il = strandArray.length; i < il; ++i) {
68041
+ let startAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[chnid + '_' + strandArray[i].startResi]);
68042
+ let endAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[chnid + '_' + strandArray[i].endResi]);
68043
+
68044
+ let startPos = ic.setSeqAlignCls.getPosFromResi(chnid, strandArray[i].startResi);
68045
+ let endPos = ic.setSeqAlignCls.getPosFromResi(chnid, strandArray[i].endResi);
68046
+
68047
+ if(startAtom.ss == 'sheet' && !startAtom.ssbegin) {
68048
+ for(let j = 1; j <= maxExtend; ++j) {
68049
+ let currPos = startPos - j;
68050
+ let currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
68051
+ if(i > 0 && parseInt(currResi) <= parseInt(strandArray[i-1].endResi)) break;
68052
+
68053
+ let currResid = chnid + '_' + currResi;
68054
+ let currAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[currResid]);
68055
+ let domainid = ic.resid2domainid[currResid];
68056
+ if(currAtom.ssbegin) { // find the start of the sheet
68057
+ // update the following: startResi,startRefnum,endResi,endRefnum,loopResCnt,resCntBfAnchor,resCntAtAnchor
68058
+ strandArray[i].startResi = currResi;
68059
+ strandArray[i].startRefnum -= j;
68060
+ strandArray[i].loopResCnt -= j;
68061
+ if(strandArray[i].loopResCnt < 0) strandArray[i].loopResCnt = 0;
68062
+ strandArray[i].resCntBfAnchor += j;
68063
+
68064
+ // update ic.resid2refnum
68065
+ for(let k = 1; k <= j; ++k) {
68066
+ currPos = startPos - k;
68067
+ currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
68068
+ let currResid = chnid + '_' + currResi;
68069
+ delete ic.residIgLoop[currResid];
68070
+ ic.resid2domainid[currResid] = domainid;
68071
+ }
68072
+
68073
+ break;
68074
+ }
68075
+ }
68076
+ }
68077
+
68078
+ if(endAtom.ss == 'sheet' && !endAtom.ssend) {
68079
+ for(let j = 1; j <= maxExtend; ++j) {
68080
+ let currPos = endPos + j;
68081
+ let currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
68082
+ if(i < il - 1 && parseInt(currResi) >= parseInt(strandArray[i+1].startResi)) break;
68083
+
68084
+ let currResid = chnid + '_' + currResi;
68085
+ let currAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[currResid]);
68086
+ let domainid = ic.resid2domainid[currResid];
68087
+ if(currAtom.ssend) { // find the end of the sheet
68088
+ // update the following: startResi,startRefnum,endResi,endRefnum,loopResCnt,resCntBfAnchor,resCntAtAnchor
68089
+ strandArray[i].endResi = currResi;
68090
+ strandArray[i].endRefnum += j;
68091
+ if(i < il - 1) {
68092
+ strandArray[i + 1].loopResCnt -= j;
68093
+ if(strandArray[i + 1].loopResCnt < 0) strandArray[i + 1].loopResCnt = 0;
68094
+ }
68095
+ strandArray[i].resCntAtAnchor += j;
68096
+
68097
+ // update ic.residIgLoop[resid];
68098
+ for(let k = 1; k <= j; ++k) {
68099
+ currPos = endPos + k;
68100
+ currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
68101
+ let currResid = chnid + '_' + currResi;
68102
+ delete ic.residIgLoop[currResid];
68103
+ ic.resid2domainid[currResid] = domainid;
68104
+ }
68105
+
68106
+ break;
68107
+ }
68108
+ }
68109
+ }
68110
+ }
68111
+
68112
+ // 2b. remove strands with less than 3 residues except G strand
68113
+ for(let il = strandArray.length, i = il - 1; i >= 0; --i) {
68114
+ let strandTmp = strandArray[i].strand.substr(0, 1);
68115
+ if(strandTmp != 'G' && strandArray[i].endRefnum - strandArray[i].startRefnum + 1 < 3) { // remove the strand
68116
+ if(strandTmp == 'B' || strandTmp == 'C' || strandTmp == 'E' || strandTmp == 'F') {
68117
+ if(!me.bNode) console.log("Some of the Ig strands B, C, E, F are removed since they are too short...");
68118
+ return false;
68119
+ }
68120
+
68121
+ if(i != il - 1) { // modify
68122
+ strandArray[i + 1].loopResCnt += strandArray[i].loopResCnt + parseInt(strandArray[i].endResi) - parseInt(strandArray[i].startResi) + 1;
68123
+ }
68124
+
68125
+ strandArray.splice(i, 1);
68126
+ }
68127
+ }
68128
+
68129
+ // 3. assign refnumLabel for each resid
68130
+ strandCnt = 0;
68131
+ let loopCnt = 0;
68132
+
68133
+ let bBeforeAstrand = true, bAfterGstrand = true, refnumLabelNoPostfix, prevStrandCnt = 0, currRefnum;
68134
+ bStart = false;
68135
+ let refnumInStrand = 0;
68136
+ if(strandArray.length > 0) {
68137
+ for(let i = 0, il = giSeq.length; i < il; ++i, ++loopCnt, ++refnumInStrand) {
68138
+ let currResi = ic.ParserUtilsCls.getResi(chnid, i);
68139
+ let residueid = chnid + '_' + currResi;
68140
+ refnumLabel = ic.resid2refnum[residueid];
68141
+
68142
+ currStrand = strandArray[strandCnt].strand;
68143
+
68144
+ let domainid;
68145
+
68146
+ if(refnumLabel) {
68147
+ domainid = ic.resid2domainid[residueid];
68148
+
68149
+ refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
68150
+ currRefnum = parseInt(refnumStr);
68151
+ refnumLabelNoPostfix = currStrand + currRefnum;
68152
+
68153
+ currStrand = refnumLabel.replace(new RegExp(refnumStr,'g'), '');
68154
+
68155
+ let firstChar = refnumLabel.substr(0,1);
68156
+ if(!bStart && (firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
68157
+ bStart = true;
68158
+ bBeforeAstrand = true;
68159
+ loopCnt = 0;
68160
+ }
68161
+ }
68162
+
68163
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[residueid]);
68164
+
68165
+ // skip non-protein residues
68166
+ if(!atom || !ic.proteins.hasOwnProperty(atom.serial)) {
68167
+ refnumLabel = undefined;
68168
+ }
68169
+ else {
68170
+ let bBefore = false, bInRange= false, bAfter = false;
68171
+ // 100, 100A
68172
+ if(parseInt(currResi) == parseInt(strandArray[strandCnt].startResi) && currResi != strandArray[strandCnt].startResi) {
68173
+ bBefore = currResi < strandArray[strandCnt].startResi;
68174
+ }
68175
+ else {
68176
+ bBefore = parseInt(currResi) < parseInt(strandArray[strandCnt].startResi);
68177
+ }
68178
+
68179
+ // 100, 100A
68180
+ if(parseInt(currResi) == parseInt(strandArray[strandCnt].endResi) && currResi != strandArray[strandCnt].endResi) {
68181
+ bAfter = currResi > strandArray[strandCnt].endResi;
68182
+ }
68183
+ else {
68184
+ bAfter = parseInt(currResi) > parseInt(strandArray[strandCnt].endResi);
68185
+ }
68186
+
68187
+ bInRange = (!bBefore && !bAfter) ? true : false;
68188
+
68189
+ if(bBefore) {
68190
+ ic.residIgLoop[residueid] = 1;
68191
+
68192
+ if(bBeforeAstrand) { // make it continuous to the 1st strand
68193
+ if(bStart) {
68194
+ currRefnum = strandArray[strandCnt].startRefnum - strandArray[strandCnt].loopResCnt + loopCnt;
68195
+ refnumLabelNoPostfix = strandArray[strandCnt].strand + currRefnum;
68196
+ refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
68197
+ domainid = strandArray[strandCnt].domainid;
68198
+ }
68199
+ else {
68200
+ //loopCnt = 0;
68201
+ refnumLabelNoPostfix = undefined;
68202
+ refnumLabel = undefined;
68203
+ }
68204
+ }
68205
+ else {
68206
+ if(prevStrandCnt >= 0
68207
+ // && (strandArray[prevStrandCnt].strand.substr(0, 1) == 'F' || strandArray[prevStrandCnt].strand.substr(0, 1) == 'G')) {
68208
+ && (strandArray[prevStrandCnt].strand.substr(0, 1) == 'G')) {
68209
+ if(!bAfterGstrand) {
68210
+ //loopCnt = 0;
68211
+ refnumLabelNoPostfix = undefined;
68212
+ refnumLabel = undefined;
68213
+ }
68214
+ else {
68215
+ if(bStart && ic.resid2refnum[residueid]) {
68216
+ bAfterGstrand = true;
68217
+
68218
+ currRefnum = strandArray[prevStrandCnt].endRefnum + loopCnt;
68219
+ refnumLabelNoPostfix = strandArray[prevStrandCnt].strand + currRefnum;
68220
+ refnumLabel = refnumLabelNoPostfix + strandArray[prevStrandCnt].strandPostfix;
68221
+ domainid = strandArray[prevStrandCnt].domainid;
68222
+ }
68223
+ else {
68224
+ bStart = false;
68225
+ bBeforeAstrand = true;
68226
+ //loopCnt = 0;
68227
+
68228
+ bAfterGstrand = false;
68229
+
68230
+ refnumLabelNoPostfix = undefined;
68231
+ refnumLabel = undefined;
68232
+ }
68233
+ }
68234
+ }
68235
+ else {
68236
+ bAfterGstrand = true; // reset
68237
+
68238
+ let len = strandArray[strandCnt].loopResCnt;
68239
+ let halfLen = parseInt(len / 2.0 + 0.5);
68240
+
68241
+ if(loopCnt <= halfLen) {
68242
+ currRefnum = strandArray[prevStrandCnt].endRefnum + loopCnt;
68243
+ refnumLabelNoPostfix = strandArray[prevStrandCnt].strand + currRefnum;
68244
+ refnumLabel = refnumLabelNoPostfix + strandArray[prevStrandCnt].strandPostfix;
68245
+ domainid = strandArray[prevStrandCnt].domainid;
68246
+ }
68247
+ else {
68248
+ currRefnum = strandArray[strandCnt].startRefnum - len + loopCnt - 1;
68249
+ refnumLabelNoPostfix = strandArray[strandCnt].strand + currRefnum;
68250
+ refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
68251
+ domainid = strandArray[strandCnt].domainid;
68252
+ }
68253
+ }
68254
+ }
68255
+ }
68256
+ else if(bInRange) {
68257
+ // not in loop any more if you assign ref numbers multiple times
68258
+ //delete ic.residIgLoop[residueid];
68259
+
68260
+ bBeforeAstrand = false;
68261
+
68262
+ if(strandArray[strandCnt].anchorRefnum) { // use anchor to name refnum
68263
+ if(currResi == strandArray[strandCnt].startResi) {
68264
+ refnumInStrand = strandArray[strandCnt].anchorRefnum - strandArray[strandCnt].resCntBfAnchor;
68265
+ strandArray[strandCnt].startRefnum = refnumInStrand;
68266
+ }
68267
+ else if(currResi == strandArray[strandCnt].endResi) {
68268
+ strandArray[strandCnt].endRefnum = refnumInStrand;
68269
+ }
68270
+
68271
+ refnumLabelNoPostfix = strandArray[strandCnt].strand + refnumInStrand;
68272
+ refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
68273
+ domainid = strandArray[strandCnt].domainid;
68274
+ }
68275
+
68276
+ if(currResi == strandArray[strandCnt].endResi) {
68277
+ ++strandCnt; // next strand
68278
+ loopCnt = 0;
68279
+
68280
+ if(!strandArray[strandCnt]) { // last strand
68281
+ --strandCnt;
68282
+ }
68283
+ }
68284
+ }
68285
+ else if(bAfter) {
68286
+ ic.residIgLoop[residueid] = 1;
68287
+
68288
+ if(!bAfterGstrand) {
68289
+ refnumLabelNoPostfix = undefined;
68290
+ refnumLabel = undefined;
68291
+ }
68292
+ else {
68293
+ // C-terminal
68294
+ if(!ic.resid2refnum[residueid]) {
68295
+ bAfterGstrand = false;
68296
+
68297
+ refnumLabelNoPostfix = undefined;
68298
+ refnumLabel = undefined;
68299
+ }
68300
+ else {
68301
+ bAfterGstrand = true;
68302
+
68303
+ currRefnum = strandArray[strandCnt].endRefnum + loopCnt;
68304
+ refnumLabelNoPostfix = strandArray[strandCnt].strand + currRefnum;
68305
+ refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
68306
+ domainid = strandArray[strandCnt].domainid;
68307
+ }
68308
+ }
68309
+ }
68310
+ }
68311
+
68312
+ prevStrand = currStrand;
68313
+ prevStrandCnt = strandCnt - 1;
68314
+
68315
+ // assign the adjusted reference numbers
68316
+ ic.resid2refnum[residueid] = refnumLabel;
68317
+ ic.resid2domainid[residueid] = domainid;
68318
+
68319
+ refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
68320
+
68321
+ if(!ic.refnum2residArray.hasOwnProperty(refnumStr)) {
68322
+ ic.refnum2residArray[refnumStr] = [residueid];
68323
+ }
68324
+ else {
68325
+ ic.refnum2residArray[refnumStr].push(residueid);
68326
+ }
68327
+
68328
+ if(!ic.chainsMapping.hasOwnProperty(chnid)) {
68329
+ ic.chainsMapping[chnid] = {};
68330
+ }
68331
+
68332
+ // remove the postfix when comparing interactions
68333
+ //ic.chainsMapping[chnid][residueid] = refnumLabel;
68334
+ ic.chainsMapping[chnid][residueid] = refnumLabelNoPostfix;
68335
+ }
68336
+ }
68337
+
68338
+ return true;
68339
+ }
68165
68340
  }
68166
68341
 
68167
68342
  /**