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.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,7 +37783,7 @@ 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
37789
  if(titleArray) {
@@ -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);
39145
38708
 
39146
- if(me.bNode) return {html: '', html2: '', html3: ''};
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);
38724
+
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
+ }
39241
38837
 
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;
38838
+ html2 += htmlCnt;
39246
38839
 
39247
- let result = ic.annoCddSiteCls.setDomainFeature(rangeArray, chnid, 'ig', htmlTmp, htmlTmp2, htmlTmp3, undefined, titleArray, fullTitleArray);
38840
+ html2 += '</div></div>';
38841
+ html3 += '</div></div>';
39248
38842
 
39249
- html += result.html + '</div>';
39250
- html2 += result.html2 + '</div>';
39251
- html3 += result.html3 + '</div>';
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;
38847
+
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
  }
@@ -44193,7 +43795,8 @@ class Annotation {
44193
43795
 
44194
43796
  ic.hlUpdateCls.updateHlAll();
44195
43797
  ic.drawCls.draw();
44196
- }
43798
+ }
43799
+
44197
43800
  }
44198
43801
  }
44199
43802
 
@@ -53803,7 +53406,7 @@ class PdbParser {
53803
53406
  //Load structures from a "URL". Due to the same domain policy of Ajax call, the URL should be in the same
53804
53407
  //domain. "type" could be "pdb", "mol2", "sdf", "xyz", "icn3dpng", or "pae"
53805
53408
  //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;
53409
+ async downloadUrl(url, type, command, template) { let ic = this.icn3d, me = ic.icn3dui;
53807
53410
  let pos = url.lastIndexOf('/');
53808
53411
  if(pos != -1) {
53809
53412
  let posDot = url.lastIndexOf('.');
@@ -53821,9 +53424,19 @@ class PdbParser {
53821
53424
  ic.InputfileData = (ic.InputfileData) ? ic.InputfileData + '\nENDMDL\n' + data : data;
53822
53425
  ic.InputfileType = type;
53823
53426
 
53427
+ // append
53428
+ ic.hAtoms = {};
53429
+ ic.dAtoms = {};
53430
+
53431
+ ic.resetConfig();
53432
+ ic.bResetAnno = true;
53433
+ ic.bResetSets = true;
53434
+
53824
53435
  if(type === 'pdb') {
53825
- await this.loadPdbData(data);
53826
- //await ic.loadScriptCls.loadScript(command, undefined, true);
53436
+ // await this.loadPdbData(data);
53437
+ let bAppend = true;
53438
+ let id = (template) ? template.replace(/_/g, '').substr(0, 4) : undefined;
53439
+ await this.loadPdbData(data, id, undefined, bAppend);
53827
53440
  }
53828
53441
  else if(type === 'mmcif') {
53829
53442
  let url = me.htmlCls.baseUrl + "mmcifparser/mmcifparser.cgi";
@@ -53851,6 +53464,17 @@ class PdbParser {
53851
53464
  let bFull = true;
53852
53465
  ic.contactMapCls.processAfErrorMap(JSON.parse(data), bFull);
53853
53466
  }
53467
+
53468
+ //append
53469
+ if(ic.bSetChainsAdvancedMenu) ic.definedSetsCls.showSets();
53470
+
53471
+ ic.bResetAnno = true;
53472
+
53473
+ if(ic.bAnnoShown) {
53474
+ await ic.showAnnoCls.showAnnotations();
53475
+
53476
+ ic.annotationCls.resetAnnoTabAll();
53477
+ }
53854
53478
  }
53855
53479
 
53856
53480
  //Atom "data" from PDB file was parsed to set up parameters for the 3D viewer. The deferred parameter
@@ -67005,7 +66629,7 @@ class Dssp {
67005
66629
  ic.ref2igtype['BArrestin1_4jqiA_rat_n1'] = 'IgFN3-like';
67006
66630
  ic.ref2igtype['BTLA_2aw2A_human_Iset'] = 'IgI';
67007
66631
  ic.ref2igtype['C3_2qkiD_human_n1'] = 'IgFN3-like';
67008
- ic.ref2igtype['CD19_6al5A_human_C2orV-n1'] = 'other Ig'; //'CD19';
66632
+ ic.ref2igtype['CD19_6al5A_human_C2orV-n1'] = 'CD19';
67009
66633
  ic.ref2igtype['CD28_1yjdC_human_V'] = 'IgV';
67010
66634
  ic.ref2igtype['CD2_1hnfA_human_C2-n2'] = 'IgC2';
67011
66635
  ic.ref2igtype['CD2_1hnfA_human_V-n1'] = 'IgV';
@@ -67016,8 +66640,8 @@ class Dssp {
67016
66640
  ic.ref2igtype['CoAtomerGamma1_1r4xA_human'] = 'IgE';
67017
66641
  ic.ref2igtype['Contactin1_2ee2A_human_FN3-n9'] = 'IgFN3';
67018
66642
  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';
66643
+ ic.ref2igtype['CuZnSuperoxideDismutase_1hl5C_human'] = 'SOD';
66644
+ ic.ref2igtype['ECadherin_4zt1A_human_n2'] = 'Cadherin';
67021
66645
  ic.ref2igtype['Endo-1,4-BetaXylanase10A_1i8aA_bacteria_n4'] = 'IgE';
67022
66646
  ic.ref2igtype['FAB-HEAVY_5esv_C1-n2'] = 'IgC1';
67023
66647
  ic.ref2igtype['FAB-HEAVY_5esv_V-n1'] = 'IgV';
@@ -67033,12 +66657,12 @@ class Dssp {
67033
66657
  ic.ref2igtype['JAM1_1nbqA_human_VorIset-n2'] = 'IgI';
67034
66658
  ic.ref2igtype['LAG3_7tzgD_human_C2-n2'] = 'IgC2';
67035
66659
  ic.ref2igtype['LAG3_7tzgD_human_V-n1'] = 'IgV';
67036
- ic.ref2igtype['LaminAC_1ifrA_human'] = 'other Ig'; //'Lamin';
66660
+ ic.ref2igtype['LaminAC_1ifrA_human'] = 'Lamin';
67037
66661
  ic.ref2igtype['MHCIa_7phrH_human_C1'] = 'IgC1';
67038
66662
  ic.ref2igtype['MPT63_1lmiA_bacteria'] = 'IgE';
67039
66663
  ic.ref2igtype['NaCaExchanger_2fwuA_dog_n2'] = 'IgE';
67040
66664
  ic.ref2igtype['NaKATPaseTransporterBeta_2zxeB_spurdogshark'] = 'IgE';
67041
- ic.ref2igtype['ORF7a_1xakA_virus'] = 'other Ig'; //'ORF';
66665
+ ic.ref2igtype['ORF7a_1xakA_virus'] = 'ORF';
67042
66666
  ic.ref2igtype['PD1_4zqkB_human_V'] = 'IgV';
67043
66667
  ic.ref2igtype['PDL1_4z18B_human_V-n1'] = 'IgV';
67044
66668
  ic.ref2igtype['Palladin_2dm3A_human_Iset-n1'] = 'IgI';
@@ -67089,7 +66713,7 @@ class Dssp {
67089
66713
  let numRound = 0;
67090
66714
 
67091
66715
  //while(!bNoMoreIg) {
67092
- while(!bNoMoreIg && numRound < 10) {
66716
+ while(!bNoMoreIg && numRound < 15) {
67093
66717
  let bRerun = true;
67094
66718
  bNoMoreIg = await thisClass.parseRefPdbData(ic.pdbDataArray, template, bRerun);
67095
66719
  ++numRound;
@@ -67128,7 +66752,7 @@ class Dssp {
67128
66752
  for(let j = 0, jl = chainidArray.length; j < jl; ++j) {
67129
66753
  let chainid = chainidArray[j];
67130
66754
 
67131
- // for selected atoms only, assign ic.resid2domainid[resid]
66755
+ // for selected atoms only
67132
66756
  let domainAtomsArray = this.getDomainAtomsArray(chainid, bRerun);
67133
66757
 
67134
66758
  if(!ic.domainid2refpdbname) ic.domainid2refpdbname = {};
@@ -67169,7 +66793,7 @@ class Dssp {
67169
66793
  }
67170
66794
  }
67171
66795
  else {
67172
- ic.domainid2refpdbname[domainid] = template;
66796
+ ic.domainid2refpdbname[domainid] = [template];
67173
66797
  domainidpairArray.push(domainid + "|1" + template); // "1" was added for the first round strand-only template
67174
66798
  }
67175
66799
  }
@@ -67209,9 +66833,6 @@ class Dssp {
67209
66833
  let pdbDataArray = await this.promiseWithFixedJobs(pdbAjaxArray);
67210
66834
 
67211
66835
  for(let domainid in ic.domainid2refpdbname) {
67212
- ic.domainid2refpdbname[domainid];
67213
- domainid.substr(0, domainid.indexOf(','));
67214
-
67215
66836
  let pdb_target = ic.domainid2pdb[domainid];
67216
66837
  for(let index = 0, indexl = pdbDataArray.length; index < indexl; ++index) {
67217
66838
  let struct2 = ic.defaultPdbId + index;
@@ -67272,12 +66893,10 @@ class Dssp {
67272
66893
 
67273
66894
  if(bRerunDomain) {
67274
66895
  let atomsAssigned = {};
66896
+ //ic.resid2refnum_ori should be used
67275
66897
  for(let resid in ic.resid2refnum_ori) {
67276
66898
  atomsAssigned = me.hashUtilsCls.unionHash(atomsAssigned, ic.residues[resid]);
67277
66899
  }
67278
- // for(let resid in ic.resid2refnum) {
67279
- // if(ic.resid2refnum[resid]) atomsAssigned = me.hashUtilsCls.unionHash(atomsAssigned, ic.residues[resid]);
67280
- // }
67281
66900
 
67282
66901
  currAtoms = me.hashUtilsCls.exclHash(currAtoms, atomsAssigned);
67283
66902
 
@@ -67301,19 +66920,12 @@ class Dssp {
67301
66920
  if(subdomains.length <= 1) {
67302
66921
  let residueArray = ic.resid2specCls.atoms2residues(Object.keys(currAtoms));
67303
66922
  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
- */
66923
+
67309
66924
  for(let n = 0, nl = residueArray.length; n < nl; ++n) {
67310
66925
  let resid = residueArray[n];
67311
- /*
67312
- ic.resid2domainid[resid] = chainid + ',0' + '_' + resiSum;
67313
- */
66926
+
67314
66927
  // clear previous refnum assignment if any
67315
- // if(!bRerunDomain && ic.resid2refnum && ic.resid2refnum[resid]) {
67316
- // if(ic.resid2refnum && ic.resid2refnum[resid]) {
66928
+ // if(bRerunDomain) {
67317
66929
  delete ic.resid2refnum[resid];
67318
66930
  delete ic.residIgLoop[resid];
67319
66931
  // }
@@ -67334,11 +66946,9 @@ class Dssp {
67334
66946
  let resid = chainid + '_' + pos2resi[n];
67335
66947
  ++resCnt;
67336
66948
  domainAtoms = me.hashUtilsCls.unionHash(domainAtoms, ic.residues[resid]);
67337
- //ic.resid2domainid[resid] = chainid + '-' + k;
67338
66949
 
67339
66950
  // clear previous refnum assignment if any
67340
- // if(!bRerunDomain && ic.resid2refnum && ic.resid2refnum[resid]) {
67341
- // if(ic.resid2refnum && ic.resid2refnum[resid]) {
66951
+ // if(bRerunDomain) {
67342
66952
  delete ic.resid2refnum[resid];
67343
66953
  delete ic.residIgLoop[resid];
67344
66954
  // }
@@ -67372,7 +66982,7 @@ class Dssp {
67372
66982
  getTemplateList(domainid) { let ic = this.icn3d; ic.icn3dui;
67373
66983
  let refpdbname = '', score = '', seqid = '', nresAlign = '';
67374
66984
 
67375
- refpdbname = ic.domainid2refpdbname[domainid];
66985
+ refpdbname = ic.domainid2refpdbname[domainid][0]; // one template in round 2
67376
66986
 
67377
66987
  if(ic.domainid2score[domainid]) {
67378
66988
  let itemArray = ic.domainid2score[domainid].split('_');
@@ -67392,6 +67002,8 @@ class Dssp {
67392
67002
 
67393
67003
  // find the best alignment for each chain
67394
67004
  let domainid2segs = {};
67005
+ let domainid2strandcnt = {};
67006
+ let domainid2refpdbnamelist = {};
67395
67007
 
67396
67008
  if(!ic.chainid2refpdbname) ic.chainid2refpdbname = {};
67397
67009
  // if(!ic.chainid2score) ic.chainid2score = {};
@@ -67484,7 +67096,7 @@ class Dssp {
67484
67096
  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
67097
  if(!me.bNode && !(bBSheet && bCSheet && bESheet && bFSheet)) console.log("Some of the Ig strands B, C, E, F are not beta sheets...");
67486
67098
  // 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) {
67099
+ if(ic.domainid2refpdbname[domainid][0] == refpdbname) {
67488
67100
  delete ic.domainid2refpdbname[domainid];
67489
67101
  delete ic.domainid2score[domainid];
67490
67102
  }
@@ -67496,21 +67108,65 @@ class Dssp {
67496
67108
  if(!me.bNode) console.log("domainid: " + domainid);
67497
67109
  }
67498
67110
 
67499
- if(!domainid2segs.hasOwnProperty(domainid) || queryData[0].score >= ic.domainid2score[domainid].split('_')[0]) {
67111
+ // count the number of matched strands
67112
+ let strandHash = {};
67113
+ for(let j = 0, jl = queryData[0].segs.length; j < jl; ++j) {
67114
+ let seg = queryData[0].segs[j];
67115
+ let q_start = parseInt(seg.q_start);
67116
+
67117
+ let strand = this.getStrandFromRefnum(q_start);
67118
+ strandHash[strand] = 1;
67119
+ }
67120
+ let score = parseFloat(queryData[0].score);
67121
+ //!!!
67122
+ // if the TM score difference is within 0.1 and more strands are found, use the template with more strands
67123
+ // if(!domainid2segs.hasOwnProperty(domainid) ||
67124
+ // (score >= parseFloat(ic.domainid2score[domainid].split('_')[0]) + tmAdjust)
67125
+ // || (score >= parseFloat(ic.domainid2score[domainid].split('_')[0]) - tmAdjust && score < parseFloat(ic.domainid2score[domainid].split('_')[0]) + tmAdjust && Object.keys(strandHash).length > domainid2strandcnt[domainid])
67126
+ // ) {
67127
+
67128
+ // use TM-score alone
67129
+ if(!domainid2segs.hasOwnProperty(domainid) || score >= parseFloat(ic.domainid2score[domainid].split('_')[0])) {
67500
67130
  ic.domainid2score[domainid] = queryData[0].score + '_' + queryData[0].frac_identical + '_' + queryData[0].num_res ;
67131
+
67501
67132
  if(bRound1) {
67502
- ic.domainid2refpdbname[domainid] = parseFloat(queryData[0].score) > 0.75 ? refpdbname : 'all_templates';
67133
+ ic.domainid2refpdbname[domainid] = score > 0.75 ? [refpdbname] : ['all_templates'];
67503
67134
  }
67504
67135
  else {
67505
- ic.domainid2refpdbname[domainid] = refpdbname;
67136
+ ic.domainid2refpdbname[domainid] = [refpdbname];
67506
67137
  }
67138
+
67507
67139
  domainid2segs[domainid] = queryData[0].segs;
67140
+ domainid2strandcnt[domainid] = Object.keys(strandHash).length;
67141
+
67508
67142
  ic.domainid2ig2kabat[domainid] = queryData[0].ig2kabat;
67509
67143
  ic.domainid2ig2imgt[domainid] = queryData[0].ig2imgt;
67510
67144
  }
67511
- }
67512
67145
 
67513
- return domainid2segs;
67146
+ if(bRound1) {
67147
+ if(!domainid2refpdbnamelist[domainid]) domainid2refpdbnamelist[domainid] = {};
67148
+ domainid2refpdbnamelist[domainid][refpdbname] = score;
67149
+ }
67150
+ }
67151
+ /* !!!
67152
+ // combine the top three clusters for the 2nd round alignment
67153
+ if(bRound1) {
67154
+ for(let domainid in domainid2refpdbnamelist) {
67155
+ console.log("###score " + ic.domainid2score[domainid].split('_')[0] + " ic.domainid2refpdbname[domainid][0] " + ic.domainid2refpdbname[domainid][0])
67156
+ if(!me.bNode && ic.domainid2refpdbname[domainid][0] == 'all_templates') {
67157
+ let refpdbname2score = domainid2refpdbnamelist[domainid];
67158
+ let refpdbnameList = Object.keys(refpdbname2score);
67159
+ refpdbnameList.sort(function(a, b) {
67160
+ return refpdbname2score[b] - refpdbname2score[a]
67161
+ });
67162
+ // top 3 templates
67163
+ ic.domainid2refpdbname[domainid] = refpdbnameList.slice(0,3);
67164
+ }
67165
+ console.log("###bb ic.domainid2refpdbname[domainid] " + ic.domainid2refpdbname[domainid])
67166
+ }
67167
+ }
67168
+ */
67169
+ return domainid2segs; // only used in round 2
67514
67170
  }
67515
67171
 
67516
67172
  async parseAlignData(dataArray, domainidpairArray, bRound1) { let ic = this.icn3d, me = ic.icn3dui;
@@ -67518,6 +67174,7 @@ class Dssp {
67518
67174
 
67519
67175
  let domainid2segs = this.parseAlignData_part1(dataArray, domainidpairArray, bRound1);
67520
67176
 
67177
+ // !!!no more Igs to detect
67521
67178
  if(Object.keys(domainid2segs).length == 0) {
67522
67179
  bNoMoreIg = true;
67523
67180
  return bNoMoreIg;
@@ -67532,25 +67189,30 @@ class Dssp {
67532
67189
  let urltmalign = me.htmlCls.tmalignUrl;
67533
67190
  for(let domainid in ic.domainid2refpdbname) {
67534
67191
  let pdbAjaxArray = [];
67535
- let refpdbname = ic.domainid2refpdbname[domainid];
67192
+ let refpdbnameList = ic.domainid2refpdbname[domainid];
67536
67193
  //let pdbid = domainid.substr(0, domainid.indexOf('_'));
67537
67194
  let chainid = domainid.substr(0, domainid.indexOf(','));
67538
67195
 
67539
- //if(ic.refpdbHash.hasOwnProperty(pdbid)) {
67540
67196
  if(ic.refpdbHash.hasOwnProperty(chainid)) {
67541
- // use itself as the ref structure
67542
- //refpdbname = pdbid;
67543
- refpdbname = chainid;
67197
+ refpdbnameList = [chainid];
67544
67198
 
67545
- if(!me.bNode) console.log("Adjusted refpdbname for domainid " + domainid + ": " + refpdbname);
67199
+ if(!me.bNode) console.log("Adjusted refpdbname for domainid " + domainid + ": " + chainid);
67546
67200
  }
67547
67201
 
67548
- if(!ic.refpdbHash[refpdbname]) {
67202
+ let templates = [];
67203
+ for(let i = 0, il = refpdbnameList.length; i < il; ++i) {
67204
+ let refpdbname = refpdbnameList[i];
67205
+ if(!ic.refpdbHash[refpdbname]) continue;
67206
+ templates = templates.concat(ic.refpdbHash[refpdbname]);
67207
+ }
67208
+
67209
+ // if(!ic.refpdbHash[refpdbname]) {
67210
+ if(templates.length == 0) {
67549
67211
  continue;
67550
67212
  }
67551
67213
 
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];
67214
+ for(let k = 0, kl = templates.length; k < kl; ++k) {
67215
+ let urlpdb = me.htmlCls.baseUrl + "mmcifparser/mmcifparser.cgi?refpdbid=" + templates[k];
67554
67216
 
67555
67217
  let pdbAjax = me.getAjaxPromise(urlpdb, 'text');
67556
67218
 
@@ -67570,12 +67232,11 @@ class Dssp {
67570
67232
  let header = 'HEADER ' + struct2 + '\n';
67571
67233
  pdb_query = header + pdb_query;
67572
67234
 
67573
- let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target, "queryid": ic.refpdbHash[refpdbname][index]};
67235
+ let dataObj = {'pdb_query': pdb_query, 'pdb_target': pdb_target, "queryid": templates[index]};
67574
67236
  let alignAjax = me.getAjaxPostPromise(urltmalign, dataObj);
67575
67237
  ajaxArray.push(alignAjax);
67576
67238
 
67577
- //domainidpairArray3.push(domainid + "," + refpdbname);
67578
- domainidpairArray3.push(domainid + "|" + ic.refpdbHash[refpdbname][index]);
67239
+ domainidpairArray3.push(domainid + "|" + templates[index]);
67579
67240
  }
67580
67241
  }
67581
67242
 
@@ -67591,19 +67252,19 @@ class Dssp {
67591
67252
  return bNoMoreIg;
67592
67253
  }
67593
67254
 
67594
- await this.parseAlignData_part3(domainid2segs);
67255
+ this.parseAlignData_part3(domainid2segs);
67595
67256
 
67596
67257
  return bNoMoreIg;
67597
67258
  }
67598
67259
 
67599
- async parseAlignData_part3(domainid2segs) { let ic = this.icn3d, me = ic.icn3dui;
67260
+ parseAlignData_part3(domainid2segs) { let ic = this.icn3d, me = ic.icn3dui;
67600
67261
 
67601
67262
  // combine domainid into chainid
67602
67263
  let processedChainid = {};
67603
67264
 
67604
67265
  for(let domainid in ic.domainid2refpdbname) {
67605
67266
  // remove the first round template
67606
- if(ic.domainid2refpdbname[domainid].substr(0,1) == '1') {
67267
+ if(ic.domainid2refpdbname[domainid][0].substr(0,1) == '1') {
67607
67268
  delete ic.domainid2refpdbname[domainid];
67608
67269
  delete ic.domainid2score[domainid];
67609
67270
  continue;
@@ -67618,7 +67279,7 @@ class Dssp {
67618
67279
  processedChainid[chainid] = 1;
67619
67280
 
67620
67281
  if(!ic.chainid2refpdbname.hasOwnProperty(chainid)) ic.chainid2refpdbname[chainid] = [];
67621
- ic.chainid2refpdbname[chainid].push(ic.domainid2refpdbname[domainid] + '|' + domainid);
67282
+ ic.chainid2refpdbname[chainid].push(ic.domainid2refpdbname[domainid][0] + '|' + domainid);
67622
67283
 
67623
67284
  // if(!ic.chainid2score.hasOwnProperty(chainid)) ic.chainid2score[chainid] = [];
67624
67285
  // ic.chainid2score[chainid].push(ic.domainid2score[domainid] + '|' + domainid);
@@ -67648,9 +67309,6 @@ class Dssp {
67648
67309
  let segArray = domainid2segs[domainid];
67649
67310
  let chainid = domainid.split(',')[0];
67650
67311
 
67651
- // let refpdbnameArray = ic.chainid2refpdbname[chainid];
67652
-
67653
- // let result = this.getTemplateList(chainid);
67654
67312
  let result = this.getTemplateList(domainid);
67655
67313
  let refpdbname = result.refpdbname;
67656
67314
  let score = result.score;
@@ -67818,6 +67476,15 @@ class Dssp {
67818
67476
  }
67819
67477
  }
67820
67478
 
67479
+ if(!ic.chainid2igtrack) ic.chainid2igtrack = {};
67480
+ for(let chainid in ic.chains) {
67481
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chainid]);
67482
+ if(ic.proteins.hasOwnProperty(atom.serial)) {
67483
+ let giSeq = ic.showSeqCls.getSeq(chainid);
67484
+ ic.chainid2igtrack[chainid] = this.ajdustRefnum(giSeq, chainid);
67485
+ }
67486
+ }
67487
+
67821
67488
  /*
67822
67489
  if(Object.keys(ic.resid2refnum).length > 0) {
67823
67490
  ic.bShowRefnum = true;
@@ -67847,7 +67514,7 @@ class Dssp {
67847
67514
  */
67848
67515
  }
67849
67516
 
67850
- getLabelFromRefnum(oriRefnum, prevStrand) { let ic = this.icn3d; ic.icn3dui;
67517
+ getStrandFromRefnum(oriRefnum, prevStrand) { let ic = this.icn3d; ic.icn3dui;
67851
67518
  let refnum = parseInt(oriRefnum);
67852
67519
 
67853
67520
  //N-terminus = 0999-0001
@@ -67874,33 +67541,44 @@ class Dssp {
67874
67541
 
67875
67542
  // loops may have numbers such as 1310, 1410
67876
67543
 
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
67544
+ let strand;
67545
+
67546
+ if(refnum < 1000) strand = undefined;
67547
+ else if(refnum >= 1200 && refnum < 1290) strand = "A---";
67548
+ else if(refnum >= 1320 && refnum < 1390) strand = "A--";
67549
+ else if(refnum >= 1420 && refnum < 1490) strand = "A-";
67550
+ else if(refnum >= 1520 && refnum < 1590) strand = "A";
67551
+ else if(refnum >= 1620 && refnum < 1690) strand = "A+";
67552
+ else if(refnum >= 1820 && refnum < 1890) strand = "A'";
67553
+ else if(refnum >= 2000 && refnum < 2900) strand = "B";
67554
+ else if(refnum >= 3300 && refnum < 3390) strand = "C--";
67555
+ else if(refnum >= 3420 && refnum < 3490) strand = "C-";
67556
+ else if(refnum >= 3520 && refnum < 3590) strand = "C";
67557
+ else if(refnum >= 4000 && refnum < 4900) strand = "C'";
67558
+ else if(refnum >= 5000 && refnum < 5900) strand = "C''";
67559
+ else if(refnum >= 6000 && refnum < 6900) strand = "D";
67560
+ else if(refnum >= 7500 && refnum < 7590) strand = "E";
67561
+ else if(refnum >= 7620 && refnum < 7900) strand = "E+";
67562
+ else if(refnum >= 8000 && refnum < 8900) strand = "F";
67563
+ else if(refnum >= 9500 && refnum < 9590) strand = "G";
67564
+ else if(refnum >= 9620 && refnum < 9690) strand = "G+";
67565
+ else if(refnum >= 9720 && refnum < 9790) strand = "G++";
67566
+ else if(refnum > 9900) strand = undefined;
67567
+ else strand = " ";
67568
+ if(prevStrand) strand = prevStrand;
67569
+
67570
+ return strand
67571
+ }
67572
+
67573
+ getLabelFromRefnum(oriRefnum, prevStrand) { let ic = this.icn3d; ic.icn3dui;
67574
+ let strand = this.getStrandFromRefnum(oriRefnum, prevStrand);
67575
+
67576
+ if(strand) {
67577
+ return strand + oriRefnum;
67578
+ }
67579
+ else {
67580
+ return undefined;
67581
+ }
67904
67582
  }
67905
67583
 
67906
67584
  async parseCustomRefFile(data) { let ic = this.icn3d; ic.icn3dui;
@@ -67979,7 +67657,8 @@ class Dssp {
67979
67657
  // 1. show IgStrand ref numbers
67980
67658
  if(type == 'igstrand' || type == 'IgStrand') {
67981
67659
  // iGStrand reference numbers were adjusted when showing in sequences
67982
- if(me.bNode) {
67660
+ // if(me.bNode) {
67661
+ if(ic.bShowRefnum) {
67983
67662
  for(let chnid in ic.chains) {
67984
67663
  let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chnid]);
67985
67664
  if(ic.proteins.hasOwnProperty(atom.serial)) {
@@ -68021,29 +67700,6 @@ class Dssp {
68021
67700
 
68022
67701
  // refData += '{"Ig domain" : ' + bIgDomain + ', "ref PDB" : ' + JSON.stringify(ic.refPdbList) + ',\n';
68023
67702
  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
67703
 
68048
67704
  if(bIgDomain) {
68049
67705
  refData += '"igs": [\n';
@@ -68054,8 +67710,8 @@ class Dssp {
68054
67710
  refData += '{"' + chnid + '": {\n';
68055
67711
 
68056
67712
  for(let i = 0, il = igArray.length; i < il; ++i) {
68057
- let startPos = igArray[i].startPos;
68058
- let endPos = igArray[i].endPos;
67713
+ let startPosArray = igArray[i].startPosArray;
67714
+ let endPosArray = igArray[i].endPosArray;
68059
67715
  let domainid = igArray[i].domainid;
68060
67716
  let info = ic.domainid2info[domainid];
68061
67717
  if(!info) continue;
@@ -68063,9 +67719,13 @@ class Dssp {
68063
67719
  refData += '"' + domainid + '": {\n';
68064
67720
 
68065
67721
  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';
67722
+ for(let j = 0, jl = startPosArray.length; j < jl; ++j) {
67723
+ let startPos = startPosArray[j];
67724
+ let endPos = endPosArray[j];
67725
+ for(let k = startPos; k <= endPos; ++k) {
67726
+ const resid = chnid + '_' + ic.chainsSeq[chnid][k].resi + '_' + ic.chainsSeq[chnid][k].name;
67727
+ refData += '{"' + resid + '": "' + resid2refnum[resid] + '"},\n';
67728
+ }
68069
67729
  }
68070
67730
  refData += '],\n';
68071
67731
 
@@ -68162,6 +67822,487 @@ class Dssp {
68162
67822
 
68163
67823
  return dataArray3;
68164
67824
  }
67825
+
67826
+ ajdustRefnum(giSeq, chnid) { let ic = this.icn3d, me = ic.icn3dui;
67827
+ if(!ic.chainid2refpdbname[chnid]) return false;
67828
+
67829
+ // auto-generate ref numbers for loops
67830
+ let currStrand = '', prevStrand = '';
67831
+ let refnumLabel, refnumStr_ori, refnumStr, postfix, strandPostfix, refnum, refnum3c, refnum2c;
67832
+ let bExtendedStrand = false, bSecThird9 = false;
67833
+
67834
+ // sometimes one chain may have several Ig domains,set an index for each IgDomain
67835
+ let index = 1, bStart = false;
67836
+
67837
+ if(!me.bNode) { // do not overwrite loops in node
67838
+ // reset ic.residIgLoop for the current selection, which could be the second round of ref num assignment
67839
+ // just current chain
67840
+ let atomHash = me.hashUtilsCls.intHash(ic.chains[chnid], ic.hAtoms);
67841
+ ic.firstAtomObjCls.getResiduesFromAtoms(atomHash);
67842
+ }
67843
+
67844
+ // 1. get the range of each strand excluding loops
67845
+ let strandArray = [], strandHash = {}, strandCnt = 0, resCnt = 0, resCntBfAnchor = 0, resCntAtAnchor = 0;
67846
+ let bFoundAnchor = false;
67847
+
67848
+ for(let i = 0, il = giSeq.length; i < il; ++i, ++resCnt, ++resCntBfAnchor, ++resCntAtAnchor) {
67849
+ let currResi = ic.ParserUtilsCls.getResi(chnid, i);
67850
+ let residueid = chnid + '_' + currResi;
67851
+ let domainid;
67852
+
67853
+ refnumLabel = ic.resid2refnum[residueid];
67854
+
67855
+ let firstChar = (refnumLabel) ? refnumLabel.substr(0,1) : '';
67856
+ if(!bStart && refnumLabel && (firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
67857
+ bStart = true;
67858
+ resCnt = 1; // the first one is included
67859
+ bFoundAnchor = false;
67860
+ }
67861
+
67862
+ //if((prevStrand.substr(0,1) == 'F' || prevStrand.substr(0,1) == 'G') && !refnumLabel) { // indicate the end of an IG domain
67863
+ if((prevStrand.substr(0,1) == 'G') && !refnumLabel) { // indicate the end of an IG domain
67864
+ bStart = false;
67865
+ }
67866
+
67867
+ if(refnumLabel) {
67868
+ domainid = ic.resid2domainid[residueid];
67869
+
67870
+ refnumStr_ori = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
67871
+ currStrand = refnumLabel.replace(new RegExp(refnumStr_ori,'g'), '');
67872
+ refnumStr_ori.substr(0, 1);
67873
+
67874
+ refnumStr = refnumStr_ori;
67875
+ refnum = parseInt(refnumStr);
67876
+ refnum3c = (refnum - parseInt(refnum/1000) * 1000).toString();
67877
+ refnum2c = (refnum - parseInt(refnum/100) * 100).toString();
67878
+
67879
+ // for extended strands, since A is 1550 and A+ is 1650, then the AA+ loop will be 1591, 1592, ... 1610, 1611, etc
67880
+ bSecThird9 = refnum3c.substr(0,1) == '9' || refnum2c.substr(0,1) == '9' || refnum2c.substr(0,1) == '0' || refnum2c.substr(0,1) == '1';
67881
+ if(bSecThird9) ic.residIgLoop[residueid] = 1;
67882
+
67883
+ strandPostfix = refnumStr.replace(refnum.toString(), '');
67884
+
67885
+ postfix = strandPostfix + '_' + index;
67886
+
67887
+ let firstTwo = parseInt(refnum.toString().substr(0, 2)); // check extended strands
67888
+ bExtendedStrand = refnum3c.substr(0,1) != '5' && firstTwo != '18'; // all strands and A' (18##)
67889
+
67890
+ if(currStrand && currStrand != ' ') {
67891
+ if(!bSecThird9 || (bExtendedStrand && !bSecThird9)) {
67892
+ let lastTwo = parseInt(refnum.toString().substr(refnum.toString().length - 2, 2));
67893
+
67894
+ if(currStrand != prevStrand) { // reset currCnt
67895
+ bFoundAnchor = false;
67896
+
67897
+ if(strandHash[currStrand + postfix]) {
67898
+ ++index;
67899
+ postfix = refnumStr.replace(refnum.toString(), '') + '_' + index;
67900
+ }
67901
+
67902
+ strandHash[currStrand + postfix] = 1;
67903
+
67904
+ strandArray[strandCnt] = {};
67905
+
67906
+ strandArray[strandCnt].startResi = currResi;
67907
+ strandArray[strandCnt].startRefnum = refnum; // 1250 in A1250a
67908
+
67909
+ resCntBfAnchor = 0;
67910
+
67911
+ strandArray[strandCnt].domainid = domainid;
67912
+
67913
+ strandArray[strandCnt].endResi = currResi;
67914
+ strandArray[strandCnt].endRefnum = refnum; // 1250a
67915
+
67916
+ if(lastTwo == 50) {
67917
+ strandArray[strandCnt].anchorRefnum = refnum;
67918
+ strandArray[strandCnt].resCntBfAnchor = resCntBfAnchor;
67919
+
67920
+ resCntAtAnchor = 0;
67921
+
67922
+ bFoundAnchor = true;
67923
+ }
67924
+
67925
+ // in case A1550 is not found, but A1551 is found
67926
+ if(!bFoundAnchor && (lastTwo == 51 || lastTwo == 52 || lastTwo == 53 || lastTwo == 54) ) {
67927
+ let offset = lastTwo - 50;
67928
+ strandArray[strandCnt].anchorRefnum = refnum - offset;
67929
+ strandArray[strandCnt].resCntBfAnchor = resCntBfAnchor - offset;
67930
+
67931
+ resCntAtAnchor = offset;
67932
+
67933
+ bFoundAnchor = true;
67934
+ }
67935
+
67936
+ if(bExtendedStrand) {
67937
+ strandArray[strandCnt].anchorRefnum = 0;
67938
+ }
67939
+
67940
+ strandArray[strandCnt].strandPostfix = strandPostfix; // a in A1250a
67941
+ strandArray[strandCnt].strand = currStrand; // A in A1250a
67942
+
67943
+ strandArray[strandCnt].postfix = postfix; // Aa_1
67944
+
67945
+ strandArray[strandCnt].loopResCnt = resCnt - 1;
67946
+
67947
+ ++strandCnt;
67948
+ resCnt = 0;
67949
+ }
67950
+ else {
67951
+ if(strandHash[currStrand + postfix]) {
67952
+ if(lastTwo == 50) {
67953
+ strandArray[strandCnt - 1].anchorRefnum = refnum;
67954
+ strandArray[strandCnt - 1].resCntBfAnchor = resCntBfAnchor;
67955
+
67956
+ // update
67957
+ strandArray[strandCnt - 1].startRefnum = strandArray[strandCnt - 1].anchorRefnum - strandArray[strandCnt - 1].resCntBfAnchor;
67958
+
67959
+ resCntAtAnchor = 0;
67960
+
67961
+ bFoundAnchor = true;
67962
+ }
67963
+
67964
+ // in case A1550 is not found, but A1551 is found
67965
+ if(!bFoundAnchor && (lastTwo == 51 || lastTwo == 52 || lastTwo == 53 || lastTwo == 54) ) {
67966
+ let offset = lastTwo - 50;
67967
+ strandArray[strandCnt - 1].anchorRefnum = refnum - offset;
67968
+ strandArray[strandCnt - 1].resCntBfAnchor = resCntBfAnchor - offset;
67969
+
67970
+ // update
67971
+ strandArray[strandCnt - 1].startRefnum = strandArray[strandCnt - 1].anchorRefnum - strandArray[strandCnt - 1].resCntBfAnchor;
67972
+
67973
+ resCntAtAnchor = offset;
67974
+
67975
+ bFoundAnchor = true;
67976
+ }
67977
+
67978
+ if(bExtendedStrand) {
67979
+ strandArray[strandCnt - 1].anchorRefnum = 0;
67980
+ }
67981
+
67982
+ strandArray[strandCnt - 1].domainid = domainid;
67983
+
67984
+ strandArray[strandCnt - 1].endResi = currResi;
67985
+ strandArray[strandCnt - 1].endRefnum = refnum; // 1250a
67986
+ strandArray[strandCnt - 1].resCntAtAnchor = resCntAtAnchor;
67987
+
67988
+ if(strandArray[strandCnt - 1].anchorRefnum) {
67989
+ strandArray[strandCnt - 1].endRefnum = strandArray[strandCnt - 1].anchorRefnum + strandArray[strandCnt - 1].resCntAtAnchor;
67990
+ }
67991
+
67992
+ resCnt = 0;
67993
+ }
67994
+ }
67995
+ }
67996
+ }
67997
+ }
67998
+
67999
+ prevStrand = currStrand;
68000
+ }
68001
+
68002
+ // 2. extend the strand to end of sheet
68003
+ let maxExtend = 8;
68004
+ for(let i = 0, il = strandArray.length; i < il; ++i) {
68005
+ let startAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[chnid + '_' + strandArray[i].startResi]);
68006
+ let endAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[chnid + '_' + strandArray[i].endResi]);
68007
+
68008
+ let startPos = ic.setSeqAlignCls.getPosFromResi(chnid, strandArray[i].startResi);
68009
+ let endPos = ic.setSeqAlignCls.getPosFromResi(chnid, strandArray[i].endResi);
68010
+
68011
+ if(startAtom.ss == 'sheet' && !startAtom.ssbegin) {
68012
+ for(let j = 1; j <= maxExtend; ++j) {
68013
+ let currPos = startPos - j;
68014
+ let currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
68015
+ if(i > 0 && parseInt(currResi) <= parseInt(strandArray[i-1].endResi)) break;
68016
+
68017
+ let currResid = chnid + '_' + currResi;
68018
+ let currAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[currResid]);
68019
+ let domainid = ic.resid2domainid[currResid];
68020
+ if(currAtom.ssbegin) { // find the start of the sheet
68021
+ // update the following: startResi,startRefnum,endResi,endRefnum,loopResCnt,resCntBfAnchor,resCntAtAnchor
68022
+ strandArray[i].startResi = currResi;
68023
+ strandArray[i].startRefnum -= j;
68024
+ strandArray[i].loopResCnt -= j;
68025
+ if(strandArray[i].loopResCnt < 0) strandArray[i].loopResCnt = 0;
68026
+ strandArray[i].resCntBfAnchor += j;
68027
+
68028
+ // update ic.resid2refnum
68029
+ for(let k = 1; k <= j; ++k) {
68030
+ currPos = startPos - k;
68031
+ currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
68032
+ let currResid = chnid + '_' + currResi;
68033
+ delete ic.residIgLoop[currResid];
68034
+ ic.resid2domainid[currResid] = domainid;
68035
+ }
68036
+
68037
+ break;
68038
+ }
68039
+ }
68040
+ }
68041
+
68042
+ if(endAtom.ss == 'sheet' && !endAtom.ssend) {
68043
+ for(let j = 1; j <= maxExtend; ++j) {
68044
+ let currPos = endPos + j;
68045
+ let currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
68046
+ if(i < il - 1 && parseInt(currResi) >= parseInt(strandArray[i+1].startResi)) break;
68047
+
68048
+ let currResid = chnid + '_' + currResi;
68049
+ let currAtom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[currResid]);
68050
+ let domainid = ic.resid2domainid[currResid];
68051
+ if(currAtom.ssend) { // find the end of the sheet
68052
+ // update the following: startResi,startRefnum,endResi,endRefnum,loopResCnt,resCntBfAnchor,resCntAtAnchor
68053
+ strandArray[i].endResi = currResi;
68054
+ strandArray[i].endRefnum += j;
68055
+ if(i < il - 1) {
68056
+ strandArray[i + 1].loopResCnt -= j;
68057
+ if(strandArray[i + 1].loopResCnt < 0) strandArray[i + 1].loopResCnt = 0;
68058
+ }
68059
+ strandArray[i].resCntAtAnchor += j;
68060
+
68061
+ // update ic.residIgLoop[resid];
68062
+ for(let k = 1; k <= j; ++k) {
68063
+ currPos = endPos + k;
68064
+ currResi = ic.ParserUtilsCls.getResi(chnid, currPos);
68065
+ let currResid = chnid + '_' + currResi;
68066
+ delete ic.residIgLoop[currResid];
68067
+ ic.resid2domainid[currResid] = domainid;
68068
+ }
68069
+
68070
+ break;
68071
+ }
68072
+ }
68073
+ }
68074
+ }
68075
+ /*
68076
+ // 2b. remove strands with less than 3 residues except G strand
68077
+ for(let il = strandArray.length, i = il - 1; i >= 0; --i) {
68078
+ let strandTmp = strandArray[i].strand.substr(0, 1);
68079
+ if(strandTmp != 'G' && strandArray[i].endRefnum - strandArray[i].startRefnum + 1 < 3) { // remove the strand
68080
+ if(strandTmp == 'B' || strandTmp == 'C' || strandTmp == 'E' || strandTmp == 'F') {
68081
+ if(!me.bNode) console.log("Some of the Ig strands B, C, E, F are removed since they are too short...");
68082
+
68083
+ console.log("### strandTmp " + strandTmp + " strandArray[i].endRefnum - strandArray[i].startRefnum + 1 " + (strandArray[i].endRefnum - strandArray[i].startRefnum + 1))
68084
+ return false;
68085
+ }
68086
+
68087
+ if(i != il - 1) { // modify
68088
+ strandArray[i + 1].loopResCnt += strandArray[i].loopResCnt + parseInt(strandArray[i].endResi) - parseInt(strandArray[i].startResi) + 1;
68089
+ }
68090
+
68091
+ strandArray.splice(i, 1);
68092
+ }
68093
+ }
68094
+ */
68095
+ // 3. assign refnumLabel for each resid
68096
+ strandCnt = 0;
68097
+ let loopCnt = 0;
68098
+
68099
+ let bBeforeAstrand = true, bAfterGstrand = true, refnumLabelNoPostfix, prevStrandCnt = 0, currRefnum;
68100
+ bStart = false;
68101
+ let refnumInStrand = 0;
68102
+ if(strandArray.length > 0) {
68103
+ for(let i = 0, il = giSeq.length; i < il; ++i, ++loopCnt, ++refnumInStrand) {
68104
+ let currResi = ic.ParserUtilsCls.getResi(chnid, i);
68105
+ let residueid = chnid + '_' + currResi;
68106
+ refnumLabel = ic.resid2refnum[residueid];
68107
+
68108
+ currStrand = strandArray[strandCnt].strand;
68109
+
68110
+ let domainid;
68111
+
68112
+ if(refnumLabel) {
68113
+ domainid = ic.resid2domainid[residueid];
68114
+
68115
+ refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
68116
+ currRefnum = parseInt(refnumStr);
68117
+ refnumLabelNoPostfix = currStrand + currRefnum;
68118
+
68119
+ currStrand = refnumLabel.replace(new RegExp(refnumStr,'g'), '');
68120
+
68121
+ let firstChar = refnumLabel.substr(0,1);
68122
+ if(!bStart && (firstChar == 'A' || firstChar == 'B')) { // start of a new IG domain
68123
+ bStart = true;
68124
+ bBeforeAstrand = true;
68125
+ loopCnt = 0;
68126
+ }
68127
+ }
68128
+
68129
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[residueid]);
68130
+
68131
+ // skip non-protein residues
68132
+ if(!atom || !ic.proteins.hasOwnProperty(atom.serial)) {
68133
+ refnumLabel = undefined;
68134
+ }
68135
+ else {
68136
+ let bBefore = false, bInRange= false, bAfter = false;
68137
+ // 100, 100A
68138
+ if(parseInt(currResi) == parseInt(strandArray[strandCnt].startResi) && currResi != strandArray[strandCnt].startResi) {
68139
+ bBefore = currResi < strandArray[strandCnt].startResi;
68140
+ }
68141
+ else {
68142
+ bBefore = parseInt(currResi) < parseInt(strandArray[strandCnt].startResi);
68143
+ }
68144
+
68145
+ // 100, 100A
68146
+ if(parseInt(currResi) == parseInt(strandArray[strandCnt].endResi) && currResi != strandArray[strandCnt].endResi) {
68147
+ bAfter = currResi > strandArray[strandCnt].endResi;
68148
+ }
68149
+ else {
68150
+ bAfter = parseInt(currResi) > parseInt(strandArray[strandCnt].endResi);
68151
+ }
68152
+
68153
+ bInRange = (!bBefore && !bAfter) ? true : false;
68154
+
68155
+ if(bBefore) {
68156
+ ic.residIgLoop[residueid] = 1;
68157
+
68158
+ if(bBeforeAstrand) { // make it continuous to the 1st strand
68159
+ if(bStart) {
68160
+ currRefnum = strandArray[strandCnt].startRefnum - strandArray[strandCnt].loopResCnt + loopCnt;
68161
+ refnumLabelNoPostfix = strandArray[strandCnt].strand + currRefnum;
68162
+ refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
68163
+ domainid = strandArray[strandCnt].domainid;
68164
+ }
68165
+ else {
68166
+ //loopCnt = 0;
68167
+ refnumLabelNoPostfix = undefined;
68168
+ refnumLabel = undefined;
68169
+ }
68170
+ }
68171
+ else {
68172
+ if(prevStrandCnt >= 0
68173
+ // && (strandArray[prevStrandCnt].strand.substr(0, 1) == 'F' || strandArray[prevStrandCnt].strand.substr(0, 1) == 'G')) {
68174
+ && (strandArray[prevStrandCnt].strand.substr(0, 1) == 'G')) {
68175
+ if(!bAfterGstrand) {
68176
+ //loopCnt = 0;
68177
+ refnumLabelNoPostfix = undefined;
68178
+ refnumLabel = undefined;
68179
+ }
68180
+ else {
68181
+ if(bStart && ic.resid2refnum[residueid]) {
68182
+ bAfterGstrand = true;
68183
+
68184
+ currRefnum = strandArray[prevStrandCnt].endRefnum + loopCnt;
68185
+ refnumLabelNoPostfix = strandArray[prevStrandCnt].strand + currRefnum;
68186
+ refnumLabel = refnumLabelNoPostfix + strandArray[prevStrandCnt].strandPostfix;
68187
+ domainid = strandArray[prevStrandCnt].domainid;
68188
+ }
68189
+ else {
68190
+ bStart = false;
68191
+ bBeforeAstrand = true;
68192
+ //loopCnt = 0;
68193
+
68194
+ bAfterGstrand = false;
68195
+
68196
+ refnumLabelNoPostfix = undefined;
68197
+ refnumLabel = undefined;
68198
+ }
68199
+ }
68200
+ }
68201
+ else {
68202
+ bAfterGstrand = true; // reset
68203
+
68204
+ let len = strandArray[strandCnt].loopResCnt;
68205
+ let halfLen = parseInt(len / 2.0 + 0.5);
68206
+
68207
+ if(loopCnt <= halfLen) {
68208
+ currRefnum = strandArray[prevStrandCnt].endRefnum + loopCnt;
68209
+ refnumLabelNoPostfix = strandArray[prevStrandCnt].strand + currRefnum;
68210
+ refnumLabel = refnumLabelNoPostfix + strandArray[prevStrandCnt].strandPostfix;
68211
+ domainid = strandArray[prevStrandCnt].domainid;
68212
+ }
68213
+ else {
68214
+ currRefnum = strandArray[strandCnt].startRefnum - len + loopCnt - 1;
68215
+ refnumLabelNoPostfix = strandArray[strandCnt].strand + currRefnum;
68216
+ refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
68217
+ domainid = strandArray[strandCnt].domainid;
68218
+ }
68219
+ }
68220
+ }
68221
+ }
68222
+ else if(bInRange) {
68223
+ // not in loop any more if you assign ref numbers multiple times
68224
+ //delete ic.residIgLoop[residueid];
68225
+
68226
+ bBeforeAstrand = false;
68227
+
68228
+ if(strandArray[strandCnt].anchorRefnum) { // use anchor to name refnum
68229
+ if(currResi == strandArray[strandCnt].startResi) {
68230
+ refnumInStrand = strandArray[strandCnt].anchorRefnum - strandArray[strandCnt].resCntBfAnchor;
68231
+ strandArray[strandCnt].startRefnum = refnumInStrand;
68232
+ }
68233
+ else if(currResi == strandArray[strandCnt].endResi) {
68234
+ strandArray[strandCnt].endRefnum = refnumInStrand;
68235
+ }
68236
+
68237
+ refnumLabelNoPostfix = strandArray[strandCnt].strand + refnumInStrand;
68238
+ refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
68239
+ domainid = strandArray[strandCnt].domainid;
68240
+ }
68241
+
68242
+ if(currResi == strandArray[strandCnt].endResi) {
68243
+ ++strandCnt; // next strand
68244
+ loopCnt = 0;
68245
+
68246
+ if(!strandArray[strandCnt]) { // last strand
68247
+ --strandCnt;
68248
+ }
68249
+ }
68250
+ }
68251
+ else if(bAfter) {
68252
+ ic.residIgLoop[residueid] = 1;
68253
+
68254
+ if(!bAfterGstrand) {
68255
+ refnumLabelNoPostfix = undefined;
68256
+ refnumLabel = undefined;
68257
+ }
68258
+ else {
68259
+ // C-terminal
68260
+ if(!ic.resid2refnum[residueid]) {
68261
+ bAfterGstrand = false;
68262
+
68263
+ refnumLabelNoPostfix = undefined;
68264
+ refnumLabel = undefined;
68265
+ }
68266
+ else {
68267
+ bAfterGstrand = true;
68268
+
68269
+ currRefnum = strandArray[strandCnt].endRefnum + loopCnt;
68270
+ refnumLabelNoPostfix = strandArray[strandCnt].strand + currRefnum;
68271
+ refnumLabel = refnumLabelNoPostfix + strandArray[strandCnt].strandPostfix;
68272
+ domainid = strandArray[strandCnt].domainid;
68273
+ }
68274
+ }
68275
+ }
68276
+ }
68277
+
68278
+ prevStrand = currStrand;
68279
+ prevStrandCnt = strandCnt - 1;
68280
+
68281
+ // assign the adjusted reference numbers
68282
+ ic.resid2refnum[residueid] = refnumLabel;
68283
+ ic.resid2domainid[residueid] = domainid;
68284
+
68285
+ refnumStr = ic.refnumCls.rmStrandFromRefnumlabel(refnumLabel);
68286
+
68287
+ if(!ic.refnum2residArray.hasOwnProperty(refnumStr)) {
68288
+ ic.refnum2residArray[refnumStr] = [residueid];
68289
+ }
68290
+ else {
68291
+ ic.refnum2residArray[refnumStr].push(residueid);
68292
+ }
68293
+
68294
+ if(!ic.chainsMapping.hasOwnProperty(chnid)) {
68295
+ ic.chainsMapping[chnid] = {};
68296
+ }
68297
+
68298
+ // remove the postfix when comparing interactions
68299
+ //ic.chainsMapping[chnid][residueid] = refnumLabel;
68300
+ ic.chainsMapping[chnid][residueid] = refnumLabelNoPostfix;
68301
+ }
68302
+ }
68303
+
68304
+ return true;
68305
+ }
68165
68306
  }
68166
68307
 
68167
68308
  /**