icn3d 3.53.0 → 3.54.1

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
@@ -57640,31 +57640,24 @@ class SubdivideCls {
57640
57640
 
57641
57641
  // cubic splines for four points: http://thalestriangles.blogspot.com/2014/02/a-bit-of-ex-spline-ation.html
57642
57642
  // https://math.stackexchange.com/questions/577641/how-to-calculate-interpolating-splines-in-3d-space
57643
- subdivide(_pnts, _clrs, DIV, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes) { let me = this.icn3dui;
57643
+ subdivide(_pnts, _clrs, DIV) { let me = this.icn3dui;
57644
57644
 
57645
57645
  let ret = [];
57646
57646
  let pos = [];
57647
57647
  let color = [];
57648
57648
 
57649
- let pnts = new Array(); // Smoothing test
57650
-
57651
- let prevoneLen = (prevone !== undefined) ? prevone.length : 0;
57652
- let nexttwoLenOri = (nexttwo !== undefined) ? nexttwo.length : 0;
57649
+ let pnts_positions = [];
57653
57650
 
57654
- let maxDist = 6.0;
57651
+ if(_pnts.length == 0) {
57652
+ pnts_positions.push(ret);
57653
+ pnts_positions.push(pos);
57654
+ pnts_positions.push(color);
57655
57655
 
57656
- if(prevoneLen > 0
57657
- && Math.abs(prevone[0].x - _pnts[0].x) <= maxDist
57658
- && Math.abs(prevone[0].y - _pnts[0].y) <= maxDist
57659
- && Math.abs(prevone[0].z - _pnts[0].z) <= maxDist
57660
- ) {
57661
- pnts.push(prevone[0]);
57662
- prevoneLen = 1;
57663
- }
57664
- else {
57665
- prevoneLen = 0;
57656
+ return pnts_positions;
57666
57657
  }
57667
57658
 
57659
+ let pnts = new Array(); // Smoothing test
57660
+
57668
57661
  pnts.push(_pnts[0]);
57669
57662
  for (let i = 1, lim = _pnts.length - 1; i < lim; ++i) {
57670
57663
  let p0 = _pnts[i], p1 = _pnts[i + 1];
@@ -57672,38 +57665,13 @@ class SubdivideCls {
57672
57665
  }
57673
57666
  pnts.push(_pnts[_pnts.length - 1]);
57674
57667
 
57675
- let nexttwoLen = 0;
57676
- if(nexttwoLenOri > 0
57677
- && Math.abs(nexttwo[0].x - _pnts[_pnts.length - 1].x) <= maxDist
57678
- && Math.abs(nexttwo[0].y - _pnts[_pnts.length - 1].y) <= maxDist
57679
- && Math.abs(nexttwo[0].z - _pnts[_pnts.length - 1].z) <= maxDist
57680
- ) {
57681
- pnts.push(nexttwo[0]);
57682
- ++nexttwoLen;
57683
- }
57684
-
57685
- if(nexttwoLenOri > 1
57686
- && Math.abs(nexttwo[0].x - nexttwo[1].x) <= maxDist
57687
- && Math.abs(nexttwo[0].y - nexttwo[1].y) <= maxDist
57688
- && Math.abs(nexttwo[0].z - nexttwo[1].z) <= maxDist
57689
- ) {
57690
- pnts.push(nexttwo[1]);
57691
- ++nexttwoLen;
57692
- }
57693
-
57694
57668
  let savedPoints = [];
57695
57669
  let savedPos = [];
57696
57670
  let savedColor = [];
57697
57671
 
57698
- //var nexttwoLen = nexttwoLenOri;
57699
- if(bExtendLastRes) {
57700
- nexttwoLen = (nexttwoLenOri > 0) ? nexttwoLenOri - 1 : 0;
57701
- }
57702
-
57703
57672
  let alpha = 1, newI;
57704
-
57705
57673
  for (let i = -1, size = pnts.length, DIVINV = 1 / DIV; i <= size - 3; ++i) {
57706
- newI = i - prevoneLen;
57674
+ newI = i;
57707
57675
  let p0 = pnts[i === -1 ? 0 : i];
57708
57676
  let p1 = pnts[i + 1];
57709
57677
  let p2 = pnts[i + 2];
@@ -57718,14 +57686,11 @@ class SubdivideCls {
57718
57686
  if(t2 - t1 < 1e-4) t2 = t1 + 1;
57719
57687
  if(t3 - t2 < 1e-4) t3 = t2 + 1;
57720
57688
 
57721
- //if(i > -1 && bHighlight && bShowArray !== undefined && bShowArray[i + 1]) {
57722
- if(i > -1 && (bShowArray === undefined || bShowArray[newI + 1]) ) {
57689
+ if(i > -1 ) {
57723
57690
  // get from previous i for the first half of residue
57724
- if(i >= -1 + prevoneLen && i <= size - 3 - nexttwoLen + 1) {
57725
- ret = ret.concat(savedPoints);
57726
- pos = pos.concat(savedPos);
57727
- color = color.concat(savedColor);
57728
- }
57691
+ ret = ret.concat(savedPoints);
57692
+ pos = pos.concat(savedPos);
57693
+ color = color.concat(savedColor);
57729
57694
  }
57730
57695
 
57731
57696
  savedPoints = [];
@@ -57739,57 +57704,25 @@ class SubdivideCls {
57739
57704
  let y = me.subdivideCls.getValueFromKnot(t, t0, t1, t2, t3, p0.y, p1.y, p2.y, p3.y);
57740
57705
  let z = me.subdivideCls.getValueFromKnot(t, t0, t1, t2, t3, p0.z, p1.z, p2.z, p3.z);
57741
57706
 
57742
- if(!bShowArray) {
57743
- if(i >= -1 + prevoneLen && i <= size - 3 - nexttwoLen) {
57744
- ret.push(new Vector3$1(x, y, z));
57745
- pos.push(newI + 1);
57746
- color.push(_clrs[newI+1]);
57747
- }
57748
- }
57749
- else {
57750
- if(i >= -1 + prevoneLen && i <= size - 3 - nexttwoLen) {
57751
- if(bShowArray[newI + 1]) {
57752
- if(j <= parseInt((DIV) / 2) ) {
57753
- ret.push(new Vector3$1(x, y, z));
57754
- pos.push(bShowArray[newI + 1]);
57755
- color.push(_clrs[newI+1]);
57756
- }
57757
- }
57758
- }
57759
-
57760
- if(i >= -1 + prevoneLen && i <= size - 3 - nexttwoLen + 1) {
57761
- if(bShowArray[newI + 2]) {
57762
- if(j > parseInt((DIV) / 2) ) {
57763
- savedPoints.push(new Vector3$1(x, y, z));
57764
- savedPos.push(bShowArray[newI + 2]);
57765
- savedColor.push(_clrs[newI+2]);
57766
- }
57767
- }
57768
- }
57769
- } // end else
57770
-
57707
+ ret.push(new Vector3$1(x, y, z));
57708
+ pos.push(newI + 1);
57709
+ color.push(_clrs[newI+1]);
57771
57710
  } // end for (let j = 0;
57772
57711
  } // end for (let i = -1;
57773
57712
 
57774
- if(!bShowArray || bShowArray[newI + 1]) {
57775
- //if(bHighlight) {
57776
- ret = ret.concat(savedPoints);
57777
- pos = pos.concat(savedPos);
57778
- color = color.concat(savedColor);
57779
- //}
57713
+ ret = ret.concat(savedPoints);
57714
+ pos = pos.concat(savedPos);
57715
+ color = color.concat(savedColor);
57780
57716
 
57781
- ret.push(pnts[pnts.length - 1 - nexttwoLen]);
57782
- pos.push(pnts.length - 1 - nexttwoLen);
57783
- color.push(_clrs[pnts.length - 1 - nexttwoLen]);
57784
- }
57717
+ ret.push(pnts[pnts.length - 1]);
57718
+ pos.push(pnts.length - 1);
57719
+ color.push(_clrs[pnts.length - 1]);
57785
57720
 
57786
57721
  savedPoints = [];
57787
57722
  savedPos = [];
57788
57723
  savedColor = [];
57789
57724
  pnts = [];
57790
57725
 
57791
- let pnts_positions = [];
57792
-
57793
57726
  pnts_positions.push(ret);
57794
57727
  pnts_positions.push(pos);
57795
57728
  pnts_positions.push(color);
@@ -58595,6 +58528,7 @@ class ClickMenu {
58595
58528
  //var file_pref =(ic.inputid) ? ic.inputid : "custom";
58596
58529
  //ic.saveFileCls.saveFile(file_pref + '_image_icn3d_loadable.png', 'png');
58597
58530
  let bPngHtml = true;
58531
+ ic.scaleFactor = 1;
58598
58532
  await ic.shareLinkCls.shareLink(bPngHtml);
58599
58533
  });
58600
58534
  me.myEventCls.onIds("#" + me.pre + "mn1_exportCanvas1", "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
@@ -58612,11 +58546,11 @@ class ClickMenu {
58612
58546
  ic.scaleFactor = 4;
58613
58547
  await ic.shareLinkCls.shareLink(true, true);
58614
58548
  });
58615
- me.myEventCls.onIds("#" + me.pre + "mn1_exportCanvas8", "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
58616
- thisClass.setLogCmd("export canvas 8", true);
58617
- ic.scaleFactor = 8;
58618
- await ic.shareLinkCls.shareLink(true, true);
58619
- });
58549
+ // me.myEventCls.onIds("#" + me.pre + "mn1_exportCanvas8", "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
58550
+ // thisClass.setLogCmd("export canvas 8", true);
58551
+ // ic.scaleFactor = 8;
58552
+ // await ic.shareLinkCls.shareLink(true, true);
58553
+ // });
58620
58554
 
58621
58555
  me.myEventCls.onIds("#" + me.pre + "mn1_exportCounts", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
58622
58556
  thisClass.setLogCmd("export counts", false);
@@ -61365,9 +61299,8 @@ class SetMenu {
61365
61299
  html += this.getLink('mn1_exportCanvas', 'Original Size & HTML', undefined, 3);
61366
61300
  html += this.getLink('mn1_exportCanvas1', 'Original Size', 1, 3);
61367
61301
 
61368
- html += this.getLink('mn1_exportCanvas2', '2X Large', undefined, 3);
61369
- html += this.getLink('mn1_exportCanvas4', '4X Large', undefined, 3);
61370
- html += this.getLink('mn1_exportCanvas8', '8X Large', undefined, 3);
61302
+ html += this.getLink('mn1_exportCanvas2', '2X for Pub. (Path Tracing)', 1, 3);
61303
+ html += this.getLink('mn1_exportCanvas4', '4X for Pub. (Path Tracing)', undefined, 3);
61371
61304
 
61372
61305
  html += "</ul>";
61373
61306
  html += "</li>";
@@ -65179,6 +65112,11 @@ class Events {
65179
65112
 
65180
65113
  async setRealign(alignType, bMsa) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
65181
65114
  let nameArray = $("#" + me.pre + "atomsCustomRealignByStruct").val();
65115
+
65116
+ if(nameArray.length == 0) {
65117
+ nameArray = $("#" + me.pre + "atomsCustom").val();
65118
+ }
65119
+
65182
65120
  if(nameArray.length > 0) {
65183
65121
  ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(nameArray);
65184
65122
  }
@@ -65464,11 +65402,15 @@ class Events {
65464
65402
  upvectorArray = [childNodes[0].textContent, childNodes[1].textContent, childNodes[2].textContent];
65465
65403
 
65466
65404
  ic.cam.position.set(viewpointArray[0], viewpointArray[1], viewpointArray[2]);
65467
- ic.cam.quaternion.setFromUnitVectors(new Vector3$1(0, 0, -1), new Vector3$1(directionArray[0], directionArray[1], directionArray[2]));
65468
65405
  ic.cam.up.set(upvectorArray[0], upvectorArray[1], upvectorArray[2]);
65469
65406
  ic.cam.fov = fov;
65470
65407
  // ic.container.whratio = aspect;
65471
65408
 
65409
+ ic.cam.quaternion.setFromUnitVectors(new Vector3$1(0, 0, -1), new Vector3$1(directionArray[0], directionArray[1], directionArray[2]));
65410
+ // let dirVec = new THREE.Vector3(directionArray[0], directionArray[1], directionArray[2]);
65411
+ // ic.cam.lookAt(ic.cam.position.clone().add(dirVec));
65412
+ // ic.cam.updateMatrixWorld(true);
65413
+
65472
65414
  ic.drawCls.applyTransformation(ic._zoomFactor, ic.mouseChange, ic.quaternion);
65473
65415
  ic.drawCls.render();
65474
65416
  });
@@ -69278,12 +69220,12 @@ class SetHtml {
69278
69220
 
69279
69221
  // type == '3dprint' or 'style'
69280
69222
  let linerad =(type == '3dprint') ? '1' : '0.1';
69281
- let coilrad =(type == '3dprint') ? '1.2' : '0.3';
69223
+ let coilrad =(type == '3dprint') ? '1.2' : '0.12';
69282
69224
  let stickrad =(type == '3dprint') ? '0.8' : '0.4';
69283
69225
  let crosslinkrad =(type == '3dprint') ? '0.8' : '0.4';
69284
69226
  let tracerad =(type == '3dprint') ? '1' : '0.4';
69285
69227
  let ballscale =(type == '3dprint') ? '0.6' : '0.3';
69286
- let ribbonthick =(type == '3dprint') ? '1' : '0.2';
69228
+ let ribbonthick =(type == '3dprint') ? '1' : '0.35';
69287
69229
  let prtribbonwidth =(type == '3dprint') ? '2' : '1.3';
69288
69230
  let nucleotideribbonwidth =(type == '3dprint') ? '1.4' : '0.8';
69289
69231
 
@@ -69352,12 +69294,12 @@ class SetHtml {
69352
69294
  }
69353
69295
 
69354
69296
  html += "<b>Line Radius</b>: " + me.htmlCls.inputTextStr + "id='" + me.pre + "linerad_" + type + "' value='" + linerad + "' size=4>" + me.htmlCls.space3 + "(for stabilizers, hydrogen bonds, distance lines, default 0.1)<br/>";
69355
- html += "<b>Coil Radius</b>: " + me.htmlCls.inputTextStr + "id='" + me.pre + "coilrad_" + type + "' value='" + coilrad + "' size=4>" + me.htmlCls.space3 + "(for coils, default 0.3)<br/>";
69297
+ html += "<b>Coil Radius</b>: " + me.htmlCls.inputTextStr + "id='" + me.pre + "coilrad_" + type + "' value='" + coilrad + "' size=4>" + me.htmlCls.space3 + "(for coils, default 0.12)<br/>";
69356
69298
  html += "<b>Stick Radius</b>: " + me.htmlCls.inputTextStr + "id='" + me.pre + "stickrad_" + type + "' value='" + stickrad + "' size=4>" + me.htmlCls.space3 + "(for sticks, default 0.4)<br/>";
69357
69299
  html += "<b>Cross-Linkage Radius</b>: " + me.htmlCls.inputTextStr + "id='" + me.pre + "crosslinkrad_" + type + "' value='" + crosslinkrad + "' size=4>" + me.htmlCls.space3 + "(for cross-linkages, default 0.4)<br/>";
69358
69300
  html += "<b>Trace Radius</b>: " + me.htmlCls.inputTextStr + "id='" + me.pre + "tracerad_" + type + "' value='" + tracerad + "' size=4>" + me.htmlCls.space3 + "(for C alpha trace, O3' trace, default 0.4)<br/>";
69359
69301
 
69360
- html += "<b>Ribbon Thickness</b>: " + me.htmlCls.inputTextStr + "id='" + me.pre + "ribbonthick_" + type + "' value='" + ribbonthick + "' size=4>" + me.htmlCls.space3 + "(for helix and sheet ribbons, nucleotide ribbons, default 0.2)<br/>";
69302
+ html += "<b>Ribbon Thickness</b>: " + me.htmlCls.inputTextStr + "id='" + me.pre + "ribbonthick_" + type + "' value='" + ribbonthick + "' size=4>" + me.htmlCls.space3 + "(for helix and sheet ribbons, nucleotide ribbons, default 0.35)<br/>";
69361
69303
  html += "<b>Protein Ribbon Width</b>: " + me.htmlCls.inputTextStr + "id='" + me.pre + "prtribbonwidth_" + type + "' value='" + prtribbonwidth + "' size=4>" + me.htmlCls.space3 + "(for helix and sheet ribbons, default 1.3)<br/>";
69362
69304
  html += "<b>Nucleotide Ribbon Width</b>: " + me.htmlCls.inputTextStr + "id='" + me.pre + "nucleotideribbonwidth_" + type + "' value='" + nucleotideribbonwidth + "' size=4>" + me.htmlCls.space3 + "(for nucleotide ribbons, default 0.8)<br/>";
69363
69305
 
@@ -70011,12 +69953,12 @@ class SetHtml {
70011
69953
 
70012
69954
  if(bReset) {
70013
69955
  $("#" + me.pre + "linerad_" + postfix ).val(0.1); //0.1; // hbonds, distance lines
70014
- $("#" + me.pre + "coilrad_" + postfix ).val(0.3); //0.3; // style cartoon-coil
69956
+ $("#" + me.pre + "coilrad_" + postfix ).val(0.12); //0.12; // style cartoon-coil
70015
69957
  $("#" + me.pre + "stickrad_" + postfix ).val(0.4); //0.4; // style stick
70016
69958
  $("#" + me.pre + "crosslinkrad_" + postfix ).val(0.4); //0.4; // cross-linkage
70017
69959
  $("#" + me.pre + "tracerad_" + postfix ).val(0.4); //0.4; // style c alpha trace, nucleotide stick
70018
69960
  $("#" + me.pre + "ballscale_" + postfix ).val(0.3); //0.3; // style ball and stick, dot
70019
- $("#" + me.pre + "ribbonthick_" + postfix ).val(0.2); //0.2; // style ribbon, nucleotide cartoon, stand thickness
69961
+ $("#" + me.pre + "ribbonthick_" + postfix ).val(0.35); //0.35; // style ribbon, nucleotide cartoon, stand thickness
70020
69962
  $("#" + me.pre + "prtribbonwidth_" + postfix ).val(1.3); //1.3; // style ribbon, stand thickness
70021
69963
  $("#" + me.pre + "nucleotideribbonwidth_" + postfix ).val(0.8); //0.8; // nucleotide cartoon
70022
69964
  }
@@ -79136,129 +79078,90 @@ class CurveStripArrow {
79136
79078
  }
79137
79079
 
79138
79080
  createCurveSubArrow(p, width, colors, div, bHighlight, bRibbon, num, positionIndex,
79139
- pntsCA, prevCOArray, bShowArray, calphaIdArray, bShowArrow, prevone, nexttwo) { let ic = this.icn3d, me = ic.icn3dui;
79081
+ pntsCA, prevCOArray, positions, bShowArrow) { let ic = this.icn3d, me = ic.icn3dui;
79140
79082
  if(me.bNode) return;
79141
79083
 
79142
- let divPoints = [], positions = [];
79084
+ let divPoints = [], linePos = [];
79143
79085
 
79144
79086
  divPoints.push(p);
79145
- positions.push(positionIndex);
79087
+ linePos.push(positionIndex);
79146
79088
 
79147
- this.prepareStrand(divPoints, positions, width, colors, div, undefined, bHighlight, bRibbon, num,
79148
- pntsCA, prevCOArray, false, bShowArray, calphaIdArray, bShowArrow, prevone, nexttwo);
79089
+ this.prepareStrand(divPoints, linePos, width, colors, div, undefined, bHighlight, bRibbon, num,
79090
+ pntsCA, prevCOArray, positions, false, bShowArrow);
79149
79091
 
79150
79092
  divPoints = [];
79151
- positions = [];
79093
+ linePos = [];
79152
79094
  }
79153
79095
 
79154
79096
  createStripArrow(p0, p1, colors, div, thickness, bHighlight, num, start, end,
79155
- pntsCA, prevCOArray, bShowArray, calphaIdArray, bShowArrow, prevone, nexttwo) { let ic = this.icn3d, me = ic.icn3dui;
79097
+ pntsCA, prevCOArray, positions, bShowArrow, ) { let ic = this.icn3d, me = ic.icn3dui;
79156
79098
  if(me.bNode) return;
79157
79099
 
79158
- let divPoints = [], positions = [];
79100
+ let divPoints = [], linePos = [];
79159
79101
 
79160
79102
  divPoints.push(p0);
79161
79103
  divPoints.push(p1);
79162
- positions.push(start);
79163
- positions.push(end);
79104
+ linePos.push(start);
79105
+ linePos.push(end);
79164
79106
 
79165
- this.prepareStrand(divPoints, positions, undefined, colors, div, thickness, bHighlight, undefined, num,
79166
- pntsCA, prevCOArray, true, bShowArray, calphaIdArray, bShowArrow, prevone, nexttwo);
79107
+ this.prepareStrand(divPoints, linePos, undefined, colors, div, thickness, bHighlight, undefined, num,
79108
+ pntsCA, prevCOArray, positions,true, bShowArrow);
79167
79109
 
79168
79110
  divPoints = [];
79169
- positions = [];
79111
+ linePos = [];
79170
79112
  }
79171
79113
 
79172
79114
  /**
79173
79115
  * @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
79174
79116
  */
79175
79117
 
79176
- prepareStrand(divPoints, positions, width, colors, div, thickness, bHighlight, bRibbon, num,
79177
- pntsCA, prevCOArray, bStrip, bShowArray, calphaIdArray, bShowArrow, prevone, nexttwo) { let ic = this.icn3d, me = ic.icn3dui;
79118
+ prepareStrand(divPoints, linePos, width, colors, div, thickness, bHighlight, bRibbon, num,
79119
+ pntsCA, prevCOArray, positions, bStrip, bShowArrow) { let ic = this.icn3d; ic.icn3dui;
79178
79120
  if(pntsCA.length === 1) {
79179
79121
  return;
79180
79122
  }
79181
-
79182
- let oriColors = colors;
79183
79123
  let bHelix = (bShowArrow) ? false : true;
79184
79124
 
79185
- let colorsLastTwo = [];
79186
- colorsLastTwo.push(colors[colors.length - 2]);
79187
- colorsLastTwo.push(colors[colors.length - 1]);
79188
-
79189
79125
  div = div || ic.axisDIV;
79190
79126
  let numM1Inv2 = 2 / (num - 1);
79191
- let delta, lastCAIndex, lastPrevCOIndex, v;
79192
79127
 
79193
79128
  let pnts = {};
79194
- for(let i = 0, il = positions.length; i < il; ++i) pnts[i] = [];
79129
+ for(let i = 0, il = linePos.length; i < il; ++i) pnts[i] = [];
79195
79130
 
79196
- // smooth C-alpha
79197
- let pnts_clrs = me.subdivideCls.subdivide(pntsCA, colors, div, undefined, undefined, prevone, nexttwo);
79198
- let pntsCASmooth = pnts_clrs[0]; // get all smoothen pnts, do not use 'bShowArray'
79199
- //colors = pnts_clrs[2];
79200
-
79201
- if(pntsCASmooth.length === 1) {
79202
- return;
79203
- }
79131
+ //let startOffset = Math.floor(ic.axisDIV / 2) + 1; // first residue has floor(DIV/2)+1 points (8 when axisDIV = 15)
79204
79132
 
79205
79133
  // draw the sheet without the last residue
79206
79134
  // use the sheet coord for n-2 residues
79207
79135
  let colorsTmp = [];
79208
- let i, lastIndex = (bShowArrow === undefined || bShowArrow) ? pntsCA.length - 2 : pntsCA.length;
79136
+ let extraArrow = (bStrip) ? 2 : 0; // extend the tube by 5 sub-points into a preceding/following helix/sheet
79137
+
79138
+ let i, lastIndex = (bShowArrow === undefined || bShowArrow) ? pntsCA.length - ic.axisDIV + extraArrow : pntsCA.length;
79209
79139
 
79210
79140
  let il = lastIndex;
79141
+ let posIndex = [], pntsCATmp = [], prevCOArrayTmp = [];
79211
79142
  for (i = 0; i < il; ++i) {
79212
- for(let index = 0, indexl = positions.length; index < indexl; ++index) {
79143
+ for(let index = 0, indexl = linePos.length; index < indexl; ++index) {
79213
79144
  pnts[index].push(divPoints[index][i]);
79214
79145
  }
79146
+ pntsCATmp.push(pntsCA[i]);
79147
+ prevCOArrayTmp.push(prevCOArray[i]);
79215
79148
  colorsTmp.push(colors[i]);
79216
- }
79217
- colorsTmp.push(colors[i]);
79218
-
79219
- if(bShowArrow === undefined || bShowArrow) {
79220
- // assign the sheet coord from C-alpha for the 2nd to the last residue of the sheet
79221
- for(let i = 0, il = positions.length; i < il; ++i) {
79222
- delta = -1 + numM1Inv2 * positions[i];
79223
- lastCAIndex = pntsCASmooth.length - 1 - div;
79224
- lastPrevCOIndex = pntsCA.length - 2;
79225
- v = new Vector3$1(pntsCASmooth[lastCAIndex].x + prevCOArray[lastPrevCOIndex].x * delta,
79226
- pntsCASmooth[lastCAIndex].y + prevCOArray[lastPrevCOIndex].y * delta,
79227
- pntsCASmooth[lastCAIndex].z + prevCOArray[lastPrevCOIndex].z * delta);
79228
- pnts[i].push(v);
79229
- }
79230
- }
79231
-
79232
- let posIndex = [];
79233
- let results;
79234
- for(let i = 0, il = positions.length; i < il; ++i) {
79235
- results = me.subdivideCls.subdivide(pnts[i], colorsTmp, div, bShowArray, bHighlight);
79236
- pnts[i] = results[0];
79237
- colors = results[2];
79238
- if(i === 0) {
79239
- posIndex = results[1];
79240
- }
79149
+ posIndex.push(positions[i]);
79241
79150
  }
79242
79151
 
79243
79152
  if(bStrip) {
79244
79153
  if(bHelix) {
79245
- if(!ic.bDoublecolor) {
79246
- ic.stripCls.createStrip(pnts[0], pnts[1], colors, div, thickness, bHighlight, true,
79247
- undefined, calphaIdArray, posIndex, prevone, nexttwo, pntsCA, prevCOArray);
79248
- }
79249
- else {
79250
- ic.stripCls.createStrip(pnts[0], pnts[1], oriColors, div, thickness, bHighlight, true,
79251
- undefined, calphaIdArray, posIndex, prevone, nexttwo, pntsCA, prevCOArray);
79252
- }
79154
+ ic.stripCls.createStrip(pnts[0], pnts[1], colorsTmp, div, thickness, bHighlight, true,
79155
+ undefined, posIndex, pntsCATmp, prevCOArrayTmp);
79253
79156
  }
79254
79157
  else {
79255
- ic.stripCls.createStrip(pnts[0], pnts[1], colors, div, thickness, bHighlight, true,
79256
- undefined, calphaIdArray, posIndex, prevone, nexttwo);
79158
+ ic.stripCls.createStrip(pnts[0], pnts[1], colorsTmp, div, thickness, bHighlight, true,
79159
+ undefined, posIndex);
79257
79160
  }
79258
79161
  }
79259
79162
  else {
79260
- ic.curveCls.createCurveSub(pnts[0], width, colors, div, bHighlight, bRibbon, true,
79261
- undefined, calphaIdArray, posIndex, prevone, nexttwo);
79163
+ ic.curveCls.createCurveSub(pnts[0], width, colorsTmp, div, bHighlight, bRibbon, true,
79164
+ undefined, posIndex);
79262
79165
  }
79263
79166
 
79264
79167
  if(bShowArrow === undefined || bShowArrow) {
@@ -79266,60 +79169,55 @@ class CurveStripArrow {
79266
79169
  colorsTmp = [];
79267
79170
 
79268
79171
  posIndex = [];
79269
- for(let index = 0, indexl = positions.length; index < indexl; ++index) {
79172
+ for(let index = 0, indexl = linePos.length; index < indexl; ++index) {
79270
79173
  pnts[index] = [];
79271
79174
 
79272
- for (let i = div * (pntsCA.length - 2), il = div * (pntsCA.length - 1);
79273
- bShowArray[parseInt(i/div)] && i < il; i = i + div) {
79274
- let pos = parseInt(i/div);
79275
- for (let j = 0; j < div; ++j) {
79276
- let delta = -1 + numM1Inv2 * positions[index];
79277
- let scale = 1.8; // scale of the arrow width
79278
- delta = delta * scale * (div - j) / div;
79279
- let oriIndex = parseInt(i/div);
79280
-
79281
- let v = new Vector3$1(pntsCASmooth[i+j].x + prevCOArray[oriIndex].x * delta,
79282
- pntsCASmooth[i+j].y + prevCOArray[oriIndex].y * delta,
79283
- pntsCASmooth[i+j].z + prevCOArray[oriIndex].z * delta);
79284
- v.smoothen = true;
79285
- pnts[index].push(v);
79286
- colorsTmp.push(colorsLastTwo[0]);
79287
- if(index === 0) posIndex.push(pos);
79288
- }
79175
+ let cnt = 0;
79176
+ for (let i = lastIndex - extraArrow, il = lastIndex - extraArrow + ic.axisDIV; i < il; ++i, ++cnt) {
79177
+ let pos = positions[i];
79178
+ let delta = -1 + numM1Inv2 * linePos[index];
79179
+ let scale = 1.8; // scale of the arrow width
79180
+ delta = delta * scale * (ic.axisDIV - cnt) / ic.axisDIV;
79181
+
79182
+ if(!pntsCA[i] || !prevCOArray[i]) continue;
79183
+
79184
+ let v = new Vector3$1(pntsCA[i].x + prevCOArray[i].x * delta,
79185
+ pntsCA[i].y + prevCOArray[i].y * delta,
79186
+ pntsCA[i].z + prevCOArray[i].z * delta);
79187
+ //v.smoothen = true;
79188
+ pnts[index].push(v);
79189
+ colorsTmp.push(colors[i]);
79190
+ if(index === 0) posIndex.push(pos);
79289
79191
  }
79290
-
79192
+
79291
79193
  // last residue
79292
79194
  // make the arrow end with 0
79293
- let delta = 0;
79294
- let lastCAIndex = pntsCASmooth.length - 1;
79295
- let lastPrevCOIndex = pntsCA.length - 1;
79296
-
79297
- //if(bShowArray[lastPrevCOIndex]) {
79298
- let v = new Vector3$1(pntsCASmooth[lastCAIndex].x + prevCOArray[lastPrevCOIndex].x * delta,
79299
- pntsCASmooth[lastCAIndex].y + prevCOArray[lastPrevCOIndex].y * delta,
79300
- pntsCASmooth[lastCAIndex].z + prevCOArray[lastPrevCOIndex].z * delta);
79301
- v.smoothen = true;
79302
- pnts[index].push(v);
79303
- colorsTmp.push(colorsLastTwo[1]);
79304
- if(index === 0) posIndex.push(lastCAIndex);
79305
- //}
79306
- }
79195
+ let lastCAIndex = pntsCA.length - 1;
79196
+ let delta = -1 + numM1Inv2 * linePos[index];
79197
+ let scale = 1.8; // scale of the arrow width
79198
+ delta = delta * scale / ic.axisDIV;
79307
79199
 
79308
- pntsCASmooth = [];
79200
+ let v = new Vector3$1(pntsCA[lastCAIndex].x + prevCOArray[lastCAIndex].x * delta,
79201
+ pntsCA[lastCAIndex].y + prevCOArray[lastCAIndex].y * delta,
79202
+ pntsCA[lastCAIndex].z + prevCOArray[lastCAIndex].z * delta);
79309
79203
 
79310
- //colorsTmp.push(colors[colors.length - 2]);
79311
- //colorsTmp.push(colors[colors.length - 1]);
79204
+ pnts[index].push(v);
79205
+ colorsTmp.push(colors[lastCAIndex]);
79206
+ if(index === 0) posIndex.push(positions[lastCAIndex]);
79207
+ }
79312
79208
 
79313
79209
  if(bStrip) {
79314
79210
  ic.stripCls.createStrip(pnts[0], pnts[1], colorsTmp, div, thickness, bHighlight, true,
79315
- undefined, undefined, posIndex, prevone, nexttwo);
79211
+ undefined, undefined, posIndex);
79316
79212
  }
79317
79213
  else {
79318
79214
  ic.curveCls.createCurveSub(pnts[0], width, colorsTmp, div, bHighlight, bRibbon, true,
79319
- undefined, undefined, posIndex, prevone, nexttwo);
79215
+ undefined, undefined, posIndex);
79320
79216
  }
79321
79217
  }
79322
79218
 
79219
+ //pntsCA = [];
79220
+
79323
79221
  for(let i in pnts) {
79324
79222
  for(let j = 0, jl = pnts[i].length; j < jl; ++j) {
79325
79223
  pnts[i][j] = null;
@@ -79328,7 +79226,7 @@ class CurveStripArrow {
79328
79226
  }
79329
79227
 
79330
79228
  pnts = {};
79331
- }
79229
+ }
79332
79230
  }
79333
79231
 
79334
79232
  /**
@@ -79341,15 +79239,14 @@ class Curve {
79341
79239
  }
79342
79240
 
79343
79241
  // modified from iview (http://star.cse.cuhk.edu.hk/iview/)
79344
- createCurveSub(_pnts, width, colors, div, bHighlight, bRibbon, bNoSmoothen, bShowArray, calphaIdArray, positions, prevone, nexttwo) { let ic = this.icn3d, me = ic.icn3dui;
79242
+ createCurveSub(_pnts, width, colors, div, bHighlight, bRibbon, bNoSmoothen, positions) { let ic = this.icn3d, me = ic.icn3dui;
79345
79243
  if(me.bNode) return;
79346
79244
 
79347
79245
  if (_pnts.length === 0) return;
79348
79246
  div = div || 5;
79349
79247
  let pnts;
79350
- if(!bNoSmoothen) {
79351
- let bExtendLastRes = true;
79352
- let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
79248
+ if(div != 1 && !bNoSmoothen) {
79249
+ let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, div);
79353
79250
  pnts = pnts_clrs[0];
79354
79251
  colors = pnts_clrs[2];
79355
79252
  }
@@ -79358,8 +79255,6 @@ class Curve {
79358
79255
  }
79359
79256
  if (pnts.length === 0) return;
79360
79257
 
79361
- ic.stripCls.setCalphaDrawnCoord(pnts, div, calphaIdArray);
79362
-
79363
79258
  if(bHighlight === 1) {
79364
79259
  let radius = ic.coilWidth / 2;
79365
79260
  //var radiusSegments = 8;
@@ -79486,7 +79381,7 @@ class Curve {
79486
79381
  }
79487
79382
 
79488
79383
  pnts = null;
79489
- }
79384
+ }
79490
79385
  }
79491
79386
 
79492
79387
  /**
@@ -79656,12 +79551,12 @@ class Cylinder {
79656
79551
 
79657
79552
  let start = null;
79658
79553
  let currentChain, currentResi;
79659
- let others = {}, beta = {};
79554
+ let others = [], beta = {};
79660
79555
  let i;
79661
79556
  for (i in atoms) {
79662
79557
  let atom = atoms[i];
79663
79558
  if (atom.het) continue;
79664
- if ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) others[atom.serial] = atom;
79559
+ if ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) others.push(atom);
79665
79560
  if (atom.ss === 'sheet') beta[atom.serial] = atom;
79666
79561
  if (atom.name !== 'CA') continue;
79667
79562
  if (atom.ss === 'helix' && atom.ssend) {
@@ -80637,45 +80532,22 @@ class Strip {
80637
80532
  }
80638
80533
 
80639
80534
  // modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
80640
- createStrip(p0, p1, colors, div, thickness, bHighlight, bNoSmoothen, bShowArray,
80641
- calphaIdArray, positions, prevone, nexttwo, pntsCA, prevCOArray) { let ic = this.icn3d, me = ic.icn3dui;
80535
+ createStrip(p0, p1, colors, div, thickness, bHighlight, bNoSmoothen,
80536
+ positions, pntsCA, prevCOArray) { let ic = this.icn3d, me = ic.icn3dui;
80642
80537
  if(me.bNode) return;
80643
80538
 
80644
80539
  if (p0.length < 2) return;
80645
80540
  div = div || ic.axisDIV;
80646
80541
 
80647
- // if(pntsCA && ic.bDoublecolor && !ic.bCalphaOnly) {
80648
- if(pntsCA && ic.bDoublecolor) {
80649
- let bExtendLastRes = false; //true;
80650
-
80651
- let pnts_clrs = me.subdivideCls.subdivide(pntsCA, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
80652
- pntsCA = pnts_clrs[0];
80653
-
80654
- this.setCalphaDrawnCoord(pntsCA, div, calphaIdArray);
80655
-
80656
- for(let i = 0, il = prevCOArray.length; i < il; ++i) {
80657
- prevCOArray[i].normalize();
80658
- }
80659
-
80660
- let pnts_clrs2 = me.subdivideCls.subdivide(prevCOArray, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
80661
- prevCOArray = pnts_clrs2[0];
80662
-
80663
- colors = pnts_clrs[2];
80664
- }
80665
- else {
80666
-
80542
+ if(div != 1) { // not subdivided yet
80667
80543
  if(!bNoSmoothen) {
80668
- //var bExtendLastRes = true;
80669
- let bExtendLastRes = false;
80670
- let pnts_clrs0 = me.subdivideCls.subdivide(p0, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
80671
- let pnts_clrs1 = me.subdivideCls.subdivide(p1, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
80544
+ let pnts_clrs0 = me.subdivideCls.subdivide(p0, colors, div);
80545
+ let pnts_clrs1 = me.subdivideCls.subdivide(p1, colors, div);
80672
80546
  p0 = pnts_clrs0[0];
80673
80547
  p1 = pnts_clrs1[0];
80674
80548
  colors = pnts_clrs0[2];
80675
80549
  }
80676
80550
  if (p0.length < 2) return;
80677
-
80678
- this.setCalphaDrawnCoord(p0, div, calphaIdArray);
80679
80551
  }
80680
80552
 
80681
80553
  if(bHighlight === 1) {
@@ -80702,7 +80574,7 @@ class Strip {
80702
80574
  radiusSegments,
80703
80575
  closed
80704
80576
  );
80705
-
80577
+
80706
80578
  let mesh = new Mesh$1(geometry0, ic.matShader);
80707
80579
  mesh.renderOrder = ic.renderOrderPicking;
80708
80580
  //ic.mdlPicking.add(mesh);
@@ -80797,33 +80669,29 @@ class Strip {
80797
80669
 
80798
80670
  if(!p0v || !p1v) continue;
80799
80671
 
80800
- //vs = vs.concat((p0v).toArray()); // 0
80801
- //vs = vs.concat((p0v).toArray()); // 1
80802
- //vs = vs.concat((p1v).toArray()); // 2
80803
- //vs = vs.concat((p1v).toArray()); // 3
80672
+ // compute the thickness direction first
80673
+ if (i < lim - 1 && p0[i + 1]) {
80674
+ axis = p1[i].clone().sub(p0[i]).cross(p0[i + 1].clone().sub(p0[i])).normalize().multiplyScalar(thickness);
80675
+ }
80676
+ let half = axis.clone().multiplyScalar(0.5);
80804
80677
 
80678
+ // bottom face: half a thickness below the edge plane
80679
+ let b0v = p0v.clone().sub(half);
80680
+ let b1v = p1v.clone().sub(half);
80805
80681
  for(let j = 0; j < 2; ++j) {
80806
- vs[offset++] = p0v.x;
80807
- vs[offset++] = p0v.y;
80808
- vs[offset++] = p0v.z;
80682
+ vs[offset++] = b0v.x;
80683
+ vs[offset++] = b0v.y;
80684
+ vs[offset++] = b0v.z;
80809
80685
  }
80810
80686
  for(let j = 0; j < 2; ++j) {
80811
- vs[offset++] = p1v.x;
80812
- vs[offset++] = p1v.y;
80813
- vs[offset++] = p1v.z;
80687
+ vs[offset++] = b1v.x;
80688
+ vs[offset++] = b1v.y;
80689
+ vs[offset++] = b1v.z;
80814
80690
  }
80815
80691
 
80816
- if (i < lim - 1) {
80817
- axis = p1[i].clone().sub(p0[i]).cross(p0[i + 1].clone().sub(p0[i])).normalize().multiplyScalar(thickness);
80818
- }
80819
- a0v = p0[i].clone().add(axis);
80820
- a1v = p1[i].clone().add(axis);
80821
-
80822
- //vs = vs.concat((a0v).toArray()); // 4
80823
- //vs = vs.concat((a0v).toArray()); // 5
80824
- //vs = vs.concat((a1v).toArray()); // 6
80825
- //vs = vs.concat((a1v).toArray()); // 7
80826
-
80692
+ // top face: half a thickness above the edge plane
80693
+ a0v = p0v.clone().add(half);
80694
+ a1v = p1v.clone().add(half);
80827
80695
  for(let j = 0; j < 2; ++j) {
80828
80696
  vs[offset++] = a0v.x;
80829
80697
  vs[offset++] = a0v.y;
@@ -80942,22 +80810,6 @@ class Strip {
80942
80810
  p0 = null;
80943
80811
  p1 = null;
80944
80812
  }
80945
-
80946
- setCalphaDrawnCoord(pnts, div, calphaIdArray) { let ic = this.icn3d; ic.icn3dui;
80947
- let index = 0;
80948
-
80949
- if(calphaIdArray !== undefined) {
80950
- for(let i = 0, il = pnts.length; i < il; i += div) { // pnts.length = (calphaIdArray.length - 1) * div + 1
80951
- let serial = calphaIdArray[index];
80952
-
80953
- if(ic.atoms.hasOwnProperty(serial)) {
80954
- ic.atoms[serial].coord2 = pnts[i].clone();
80955
- }
80956
-
80957
- ++index;
80958
- }
80959
- }
80960
- }
80961
80813
  }
80962
80814
 
80963
80815
  /**
@@ -80973,129 +80825,161 @@ class Tube {
80973
80825
  //Create tubes for "atoms" with certain "atomName". "radius" is the radius of the tubes.
80974
80826
  //"bHighlight" is an option to draw the highlight for these atoms. The highlight could be
80975
80827
  //outlines with bHighlight=1 and 3D objects with bHighlight=2.
80976
- createTube(atoms, atomName, radius, bHighlight, bCustom, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
80828
+ createTube(atoms, atomName, radius, bHighlight, bCustom, bNonCoil, tubePosArray, pntsCAAllSub, colorsAllSub) { let ic = this.icn3d, me = ic.icn3dui;
80977
80829
  if(me.bNode) return;
80978
80830
 
80979
- let pnts = [], colors = [], radii = [], prevone = [], nexttwo = [];
80831
+ let pnts = [], colors = [], radii = [];
80980
80832
  let currentChain, currentResi;
80981
80833
  let index = 0;
80982
80834
  let maxDist = 6.0;
80983
80835
  let maxDist2 = 3.0; // avoid tube between the residues in 3 residue helix
80984
80836
 
80985
- let pnts_colors_radii_prevone_nexttwo = [];
80986
- let firstAtom, atom, prevAtom;
80837
+ let pnts_colors_radii = [];
80838
+ let firstAtom, firstPos, atom, prevAtom, prevPos;
80839
+ let half = Math.floor(ic.axisDIV / 2) - 1;
80840
+
80841
+ for (let i = 0, il = atoms.length; i < il; ++i) {
80842
+ let pos = (tubePosArray) ? tubePosArray[i] : undefined;
80987
80843
 
80988
- for (let i in atoms) {
80989
80844
  atom = atoms[i];
80990
80845
  if ((atom.name === atomName) && !atom.het) {
80991
80846
  if(index == 0) {
80992
80847
  firstAtom = atom;
80848
+ firstPos = pos;
80993
80849
  }
80994
80850
 
80995
80851
  atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) - 1).toString();
80996
80852
 
80997
80853
  if (index > 0 && (currentChain !== atom.chain || Math.abs(atom.coord.x - prevAtom.coord.x) > maxDist || Math.abs(atom.coord.y - prevAtom.coord.y) > maxDist || Math.abs(atom.coord.z - prevAtom.coord.z) > maxDist
80998
80854
  || (prevAtom.ssbegin) // e.g., https://www.ncbi.nlm.nih.gov/Structure/icn3d/?pdbid=7JO8 where a beta sheet has just two residues
80999
- // || (parseInt(currentResi) + 1 < parseInt(atom.resi) && (Math.abs(atom.coord.x - prevAtom.coord.x) > maxDist2 || Math.abs(atom.coord.y - prevAtom.coord.y) > maxDist2 || Math.abs(atom.coord.z - prevAtom.coord.z) > maxDist2) && ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[resid]) && ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[resid]).ss == 'helix')
81000
80855
  || (ic.ParserUtilsCls.getResiNCBI(atom.structure + '_' + currentChain, currentResi) + 1 < ic.ParserUtilsCls.getResiNCBI(atom.structure + '_' + atom.chain, atom.resi) && (Math.abs(atom.coord.x - prevAtom.coord.x) > maxDist2 || Math.abs(atom.coord.y - prevAtom.coord.y) > maxDist2 || Math.abs(atom.coord.z - prevAtom.coord.z) > maxDist2))
81001
80856
  ) ) {
81002
80857
  if(bHighlight !== 2) {
81003
- if(!isNaN(firstAtom.resi) && !isNaN(prevAtom.resi)) {
81004
- let prevoneResid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
81005
- let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
81006
- prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
81007
-
81008
- let nextoneResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 1).toString();
81009
- let nexttwoResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 2).toString();
81010
- let nextthreeResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 3).toString();
81011
-
81012
- if(ic.residues.hasOwnProperty(nextoneResid)) {
81013
- let nextAtom = ic.firstAtomObjCls.getAtomFromResi(nextoneResid, atomName);
81014
- if(nextAtom !== undefined && nextAtom.ssbegin) { // include the residue
81015
- nextoneResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 2).toString();
81016
- nexttwoResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 3).toString();
81017
-
81018
- pnts.push(nextAtom.coord);
81019
- if(bCustom) {
81020
- radii.push(this.getCustomtubesize(nextoneResid));
81021
- }
81022
- else {
81023
- radii.push(this.getRadius(radius, nextAtom));
80858
+ if(tubePosArray) {
80859
+ let bMissingEnd = ic.missingResEnd[prevAtom.structure + '_' + prevAtom.chain + '_' + prevAtom.resi];
80860
+ // remove half of the points when missign residues
80861
+ if(bMissingEnd) {
80862
+ pnts.splice(-half);
80863
+ colors.splice(-half);
80864
+ radii.splice(-half);
80865
+ }
80866
+
80867
+ let result = this.closeSegment(firstAtom, firstPos, prevAtom, prevPos, pnts, colors, radii, pntsCAAllSub);
80868
+
80869
+ pnts_colors_radii.push(result);
80870
+ }
80871
+ else {
80872
+ /*
80873
+ if(!isNaN(firstAtom.resi) && !isNaN(prevAtom.resi)) {
80874
+ let prevoneResid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
80875
+ let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
80876
+ prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
80877
+
80878
+ let nextoneResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 1).toString();
80879
+ let nexttwoResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 2).toString();
80880
+ let nextthreeResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 3).toString();
80881
+
80882
+ if(ic.residues.hasOwnProperty(nextoneResid)) {
80883
+ let nextAtom = ic.firstAtomObjCls.getAtomFromResi(nextoneResid, atomName);
80884
+ if(nextAtom !== undefined && nextAtom.ssbegin) { // include the residue
80885
+ nextoneResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 2).toString();
80886
+ nexttwoResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 3).toString();
80887
+
80888
+ pnts.push(nextAtom.coord);
80889
+ if(bCustom) {
80890
+ radii.push(this.getCustomtubesize(nextoneResid));
80891
+ }
80892
+ else {
80893
+ radii.push(this.getRadius(radius, nextAtom));
80894
+ }
80895
+ colors.push(nextAtom.color);
81024
80896
  }
81025
- colors.push(nextAtom.color);
81026
80897
  }
81027
- }
81028
80898
 
81029
- // add one more residue if only one residue is available and it's not part of helix/sheet
81030
- if(pnts.length == 1 && ic.residues.hasOwnProperty(nextoneResid) && atom.ss == 'coil') {
81031
- let nextAtom = ic.firstAtomObjCls.getAtomFromResi(nextoneResid, atomName);
80899
+ // add one more residue if only one residue is available and it's not part of helix/sheet
80900
+ if(pnts.length == 1 && ic.residues.hasOwnProperty(nextoneResid) && atom.ss == 'coil') {
80901
+ let nextAtom = ic.firstAtomObjCls.getAtomFromResi(nextoneResid, atomName);
81032
80902
 
81033
- if(nextAtom) {
81034
- pnts.push(nextAtom.coord);
81035
- colors.push(nextAtom.color);
80903
+ if(nextAtom) {
80904
+ pnts.push(nextAtom.coord);
80905
+ colors.push(nextAtom.color);
81036
80906
 
81037
- let radiusFinal = this.getRadius(radius, atom);
81038
- radii.push(radiusFinal);
80907
+ let radiusFinal = this.getRadius(radius, atom);
80908
+ radii.push(radiusFinal);
81039
80909
 
81040
- nextoneResid = nexttwoResid;
81041
- nexttwoResid = nextthreeResid;
80910
+ nextoneResid = nexttwoResid;
80911
+ nexttwoResid = nextthreeResid;
80912
+ }
81042
80913
  }
81043
- }
81044
80914
 
81045
- let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
81046
- if(nextoneCoord !== undefined) {
81047
- nexttwo.push(nextoneCoord);
81048
- }
80915
+ let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
80916
+ if(nextoneCoord !== undefined) {
80917
+ nexttwo.push(nextoneCoord);
80918
+ }
81049
80919
 
81050
- let nexttwoCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nexttwoResid, atomName);
81051
- if(nexttwoCoord !== undefined) {
81052
- nexttwo.push(nexttwoCoord);
80920
+ let nexttwoCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nexttwoResid, atomName);
80921
+ if(nexttwoCoord !== undefined) {
80922
+ nexttwo.push(nexttwoCoord);
80923
+ }
81053
80924
  }
80925
+ */
80926
+ pnts_colors_radii.push({'pnts':pnts, 'colors':colors, 'radii':radii});
81054
80927
  }
81055
-
81056
- pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
81057
80928
  }
81058
- pnts = []; colors = []; radii = []; prevone = []; nexttwo = [];
81059
- firstAtom = atom;
80929
+ pnts = []; colors = []; radii = []; firstAtom = atom;
80930
+ firstPos = pos;
81060
80931
  index = 0;
81061
80932
  }
81062
80933
 
81063
- if(pnts.length == 0 && !isNaN(atom.resi)) {
81064
- let prevoneResid = atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) - 1).toString();
81065
- if(ic.residues.hasOwnProperty(prevoneResid)) {
81066
- prevAtom = ic.firstAtomObjCls.getAtomFromResi(prevoneResid, atomName);
81067
- if(prevAtom !== undefined && prevAtom.ssend) { // include the residue
81068
- pnts.push(prevAtom.coord);
81069
- if(bCustom) {
81070
- radii.push(this.getCustomtubesize(prevoneResid));
81071
- }
81072
- else {
81073
- radii.push(this.getRadius(radius, prevAtom));
80934
+ if(tubePosArray) { // coil
80935
+ let bMissingStart = ic.missingResStart[atom.structure + '_' + atom.chain + '_' + atom.resi];
80936
+ let bMissingEnd = ic.missingResEnd[atom.structure + '_' + atom.chain + '_' + atom.resi];
80937
+
80938
+ let offsetStart = (bMissingStart) ? half : 0;
80939
+ let offsetEnd = (bMissingEnd) ? half : 0;
80940
+
80941
+ let indexArray = ic.strandCls.pos2IndexArray(pos, pntsCAAllSub);
80942
+ for(let j = offsetEnd, jl = indexArray.length - offsetStart; j < jl; ++j) {
80943
+ pnts.push(pntsCAAllSub[indexArray[j]]);
80944
+ colors.push(colorsAllSub[indexArray[j]]);
80945
+ radii.push(ic.coilWidth);
80946
+ }
80947
+ }
80948
+ else { // b factor, etc
80949
+ /*
80950
+ if(pnts.length == 0 && !isNaN(atom.resi)) {
80951
+ let prevoneResid = atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) - 1).toString();
80952
+ if(ic.residues.hasOwnProperty(prevoneResid)) {
80953
+ prevAtom = ic.firstAtomObjCls.getAtomFromResi(prevoneResid, atomName);
80954
+ if(prevAtom !== undefined && prevAtom.ssend) { // include the residue
80955
+ pnts.push(prevAtom.coord);
80956
+ if(bCustom) {
80957
+ radii.push(this.getCustomtubesize(prevoneResid));
80958
+ }
80959
+ else {
80960
+ radii.push(this.getRadius(radius, prevAtom));
80961
+ }
80962
+ colors.push(prevAtom.color);
81074
80963
  }
81075
- colors.push(prevAtom.color);
81076
80964
  }
81077
80965
  }
81078
- }
80966
+ */
80967
+ pnts.push(atom.coord);
81079
80968
 
81080
- pnts.push(atom.coord);
80969
+ let radiusFinal;
80970
+ if(bCustom) {
80971
+ radiusFinal = this.getCustomtubesize(atom.structure + '_' + atom.chain + '_' + atom.resi);
80972
+ }
80973
+ else {
80974
+ radiusFinal = this.getRadius(radius, atom);
80975
+ }
80976
+
80977
+ radii.push(radiusFinal);
81081
80978
 
81082
- let radiusFinal;
81083
- if(bCustom) {
81084
- radiusFinal = this.getCustomtubesize(atom.structure + '_' + atom.chain + '_' + atom.resi);
81085
- }
81086
- else {
81087
- radiusFinal = this.getRadius(radius, atom);
80979
+ colors.push(atom.color);
80980
+ // the starting residue of a coil uses the color from the next residue to avoid using the color of the last helix/sheet residue
80981
+ if(index === 1) colors[colors.length - 2] = atom.color;
81088
80982
  }
81089
-
81090
- // draw all atoms in tubes and assign zero radius when the residue is not coil
81091
- // if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
81092
-
81093
- //radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
81094
- radii.push(radiusFinal);
81095
-
81096
- colors.push(atom.color);
81097
- // the starting residue of a coil uses the color from the next residue to avoid using the color of the last helix/sheet residue
81098
- if(index === 1) colors[colors.length - 2] = atom.color;
81099
80983
 
81100
80984
  currentChain = atom.chain;
81101
80985
  currentResi = atom.resi;
@@ -81108,170 +80992,128 @@ class Tube {
81108
80992
  ++index;
81109
80993
 
81110
80994
  prevAtom = atom;
80995
+ prevPos = pos;
81111
80996
  }
81112
80997
  }
81113
80998
 
81114
80999
  if(bHighlight !== 2) {
81115
- prevone = [];
81116
- if(firstAtom !== undefined && !isNaN(firstAtom.resi)) {
81117
- let prevoneResid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
81118
- let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
81119
- prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
81120
- }
81121
-
81122
- nexttwo = [];
81123
- if(atom !== undefined && !isNaN(atom.resi)) {
81124
- let nextoneResid = atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) + 1).toString();
81125
- let nexttwoResid = atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) + 2).toString();
81126
- let nextthreeResid = atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) + 3).toString();
81127
-
81128
- // add one more residue if only one residue is available
81129
- if(pnts.length == 1 && ic.residues.hasOwnProperty(nextoneResid)) {
81130
- let nextAtom = ic.firstAtomObjCls.getAtomFromResi(nextoneResid, atomName);
81131
-
81132
- if(nextAtom) {
81133
- pnts.push(nextAtom.coord);
81134
- colors.push(nextAtom.color);
81135
-
81136
- let radiusFinal = this.getRadius(radius, atom);
81137
- radii.push(radiusFinal);
81138
-
81139
- nextoneResid = nexttwoResid;
81140
- nexttwoResid = nextthreeResid;
81000
+ if(tubePosArray) {
81001
+ if(prevAtom) {
81002
+ let bMissingEnd = ic.missingResEnd[prevAtom.structure + '_' + prevAtom.chain + '_' + prevAtom.resi];
81003
+ if(bMissingEnd) {
81004
+ pnts.splice(-half);
81005
+ colors.splice(-half);
81006
+ radii.splice(-half);
81141
81007
  }
81142
- }
81143
81008
 
81144
- let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
81145
- if(nextoneCoord !== undefined) {
81146
- nexttwo.push(nextoneCoord);
81147
- }
81009
+ let result = this.closeSegment(firstAtom, firstPos, prevAtom, prevPos, pnts, colors, radii, pntsCAAllSub);
81148
81010
 
81149
- let nexttwoCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nexttwoResid, atomName);
81150
- if(nexttwoCoord !== undefined) {
81151
- nexttwo.push(nexttwoCoord);
81011
+ pnts_colors_radii.push(result);
81152
81012
  }
81153
81013
  }
81154
-
81155
- pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
81156
- }
81157
-
81158
- for(let i = 0, il = pnts_colors_radii_prevone_nexttwo.length; i < il; ++i) {
81159
- let pnts = pnts_colors_radii_prevone_nexttwo[i].pnts;
81160
- let colors = pnts_colors_radii_prevone_nexttwo[i].colors;
81161
- let radii = pnts_colors_radii_prevone_nexttwo[i].radii;
81162
- let prevone = pnts_colors_radii_prevone_nexttwo[i].prevone;
81163
- let nexttwo = pnts_colors_radii_prevone_nexttwo[i].nexttwo;
81164
-
81165
- this.createTubeSub(pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil);
81166
- }
81167
-
81168
- pnts_colors_radii_prevone_nexttwo = [];
81169
- }
81170
-
81171
- /*
81172
- createTube(atoms, atomName, radius, bHighlight, bCustom, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
81173
- if(me.bNode) return;
81174
-
81175
- let pnts = [], colors = [], radii = [], prevone = [], nexttwo = [];
81176
- let currentChain, currentResi;
81177
- let index = 0;
81178
- let maxDist = 6.0;
81179
- let maxDist2 = 3.0; // avoid tube between the residues in 3 residue helix
81180
-
81181
- let pnts_colors_radii_prevone_nexttwo = [];
81182
- let firstAtom, atom, prevAtom;
81183
-
81184
- for (let i in atoms) {
81185
- atom = atoms[i];
81186
- if ((atom.name === atomName) && !atom.het) {
81187
- if(index == 0) {
81188
- firstAtom = atom;
81014
+ else {
81015
+ /*
81016
+ prevone = [];
81017
+ if(firstAtom !== undefined && !isNaN(firstAtom.resi)) {
81018
+ let prevoneResid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
81019
+ let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
81020
+ prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
81189
81021
  }
81190
81022
 
81191
- if (index > 0 && (currentChain !== atom.chain || Math.abs(atom.coord.x - prevAtom.coord.x) > maxDist || Math.abs(atom.coord.y - prevAtom.coord.y) > maxDist || Math.abs(atom.coord.z - prevAtom.coord.z) > maxDist
81192
- || (ic.ParserUtilsCls.getResiNCBI(atom.structure + '_' + currentChain, currentResi) + 1 < ic.ParserUtilsCls.getResiNCBI(atom.structure + '_' + atom.chain, atom.resi) && (Math.abs(atom.coord.x - prevAtom.coord.x) > maxDist2 || Math.abs(atom.coord.y - prevAtom.coord.y) > maxDist2 || Math.abs(atom.coord.z - prevAtom.coord.z) > maxDist2))
81193
- ) ) {
81194
- if(bHighlight !== 2) {
81195
- if(!isNaN(firstAtom.resi) && !isNaN(prevAtom.resi)) {
81196
- let prevoneResid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
81197
- let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
81198
- prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
81023
+ nexttwo = [];
81024
+ if(atom !== undefined && !isNaN(atom.resi)) {
81025
+ let nextoneResid = atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) + 1).toString();
81026
+ let nexttwoResid = atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) + 2).toString();
81027
+ let nextthreeResid = atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) + 3).toString();
81199
81028
 
81200
- let nextoneResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 1).toString();
81029
+ // add one more residue if only one residue is available
81030
+ if(pnts.length == 1 && ic.residues.hasOwnProperty(nextoneResid)) {
81031
+ let nextAtom = ic.firstAtomObjCls.getAtomFromResi(nextoneResid, atomName);
81201
81032
 
81202
- // add one more residue if only one residue is available
81203
- if(pnts.length == 1 && ic.residues.hasOwnProperty(nextoneResid)) {
81204
- let nextAtom = ic.firstAtomObjCls.getAtomFromResi(nextoneResid, atomName);
81033
+ if(nextAtom) {
81034
+ pnts.push(nextAtom.coord);
81035
+ colors.push(nextAtom.color);
81205
81036
 
81206
- if(nextAtom) {
81207
- pnts.push(nextAtom.coord);
81208
- colors.push(nextAtom.color);
81037
+ let radiusFinal = this.getRadius(radius, atom);
81038
+ radii.push(radiusFinal);
81209
81039
 
81210
- let radiusFinal = this.getRadius(radius, atom);
81211
- radii.push(radiusFinal);
81212
- }
81213
- }
81214
-
81040
+ nextoneResid = nexttwoResid;
81041
+ nexttwoResid = nextthreeResid;
81215
81042
  }
81216
-
81217
- pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
81218
81043
  }
81219
- pnts = []; colors = []; radii = []; prevone = []; nexttwo = [];
81220
- firstAtom = atom;
81221
- index = 0;
81222
- }
81223
81044
 
81224
- pnts.push(atom.coord);
81045
+ let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
81046
+ if(nextoneCoord !== undefined) {
81047
+ nexttwo.push(nextoneCoord);
81048
+ }
81225
81049
 
81226
- let radiusFinal;
81227
- if(bCustom) {
81228
- radiusFinal = this.getCustomtubesize(atom.structure + '_' + atom.chain + '_' + atom.resi);
81229
- }
81230
- else {
81231
- radiusFinal = this.getRadius(radius, atom);
81050
+ let nexttwoCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nexttwoResid, atomName);
81051
+ if(nexttwoCoord !== undefined) {
81052
+ nexttwo.push(nexttwoCoord);
81053
+ }
81232
81054
  }
81055
+ */
81056
+ pnts_colors_radii.push({'pnts':pnts, 'colors':colors, 'radii':radii});
81057
+ }
81058
+ }
81233
81059
 
81234
- // draw all atoms in tubes and assign zero radius when the residue is not coil
81235
- if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
81060
+ for(let i = 0, il = pnts_colors_radii.length; i < il; ++i) {
81061
+ let pnts = pnts_colors_radii[i].pnts;
81062
+ let colors = pnts_colors_radii[i].colors;
81063
+ let radii = pnts_colors_radii[i].radii;
81236
81064
 
81237
- //radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
81238
- radii.push(radiusFinal);
81065
+ if(tubePosArray) {
81066
+ this.createTubeSub(pnts, colors, radii, bHighlight, bNonCoil);
81067
+ }
81068
+ else {
81069
+ this.createTubeSub(pnts, colors, radii, bHighlight, bNonCoil, true);
81070
+ }
81071
+ }
81239
81072
 
81240
- colors.push(atom.color);
81241
- // the starting residue of a coil uses the color from the next residue to avoid using the color of the last helix/sheet residue
81242
- if(index === 1) colors[colors.length - 2] = atom.color;
81073
+ pnts_colors_radii = [];
81074
+ }
81243
81075
 
81244
- currentChain = atom.chain;
81245
- currentResi = atom.resi;
81076
+ closeSegment(firstAtom, firstPos, prevAtom, prevPos, pnts, colors, radii, pntsCAAllSub) { let ic = this.icn3d; ic.icn3dui;
81077
+ if (pnts.length === 0) return {'pnts': [], 'colors': [], 'radii': []};
81246
81078
 
81247
- let scale = 1.2;
81248
- if(bHighlight === 2 && !atom.ssbegin) {
81249
- ic.boxCls.createBox(atom, undefined, undefined, scale, undefined, bHighlight);
81250
- }
81079
+ let extra = 1; // extend the tube by 5 sub-points into a preceding/following helix/sheet
81251
81080
 
81252
- ++index;
81081
+ // extend backward by one sub-point into a preceding helix/sheet
81082
+ if (!isNaN(firstAtom.resi)) {
81083
+ if(firstAtom.style == 'strand') extra = 0;
81253
81084
 
81254
- prevAtom = atom;
81255
- }
81256
- }
81085
+ let resid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1);
81086
+ let before = ic.residues.hasOwnProperty(resid) ? ic.firstAtomObjCls.getAtomFromResi(resid, 'CA') : undefined;
81257
81087
 
81258
- if(bHighlight !== 2) {
81259
- pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
81088
+ for(let i = 1, il = extra + 1; i < il; ++i) {
81089
+ let idx = ic.strandCls.pos2IndexArray(firstPos, pntsCAAllSub)[0] - i;
81090
+ if (before && (before.ssbegin || before.ssend) && idx >= 0) {
81091
+ pnts.unshift(pntsCAAllSub[idx]);
81092
+ colors.unshift(colors[0]); // keep the coil color
81093
+ radii.unshift(radii[0]);
81094
+ }
81095
+ }
81260
81096
  }
81261
81097
 
81262
- for(let i = 0, il = pnts_colors_radii_prevone_nexttwo.length; i < il; ++i) {
81263
- let pnts = pnts_colors_radii_prevone_nexttwo[i].pnts;
81264
- let colors = pnts_colors_radii_prevone_nexttwo[i].colors;
81265
- let radii = pnts_colors_radii_prevone_nexttwo[i].radii;
81266
- let prevone = []; // = pnts_colors_radii_prevone_nexttwo[i].prevone;
81267
- let nexttwo = []; // = pnts_colors_radii_prevone_nexttwo[i].nexttwo;
81098
+ // extend forward by one sub-point into a following helix/sheet
81099
+ if (!isNaN(prevAtom.resi)) {
81100
+ if(prevAtom.style == 'strand') extra = 0;
81268
81101
 
81269
- this.createTubeSub(pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil);
81102
+ let resid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 1);
81103
+ let after = ic.residues.hasOwnProperty(resid) ? ic.firstAtomObjCls.getAtomFromResi(resid, 'CA') : undefined;
81104
+ let arr = ic.strandCls.pos2IndexArray(prevPos, pntsCAAllSub);
81105
+ for(let i = 1, il = extra + 1; i < il; ++i) {
81106
+ let idx = arr[arr.length - 1] + i;
81107
+ if (after && (after.ssbegin || after.ssend) && idx < pntsCAAllSub.length) {
81108
+ pnts.push(pntsCAAllSub[idx]);
81109
+ colors.push(colors[colors.length - 1]);
81110
+ radii.push(radii[radii.length - 1]);
81111
+ }
81112
+ }
81270
81113
  }
81271
81114
 
81272
- pnts_colors_radii_prevone_nexttwo = [];
81115
+ return {'pnts': pnts, 'colors': colors, 'radii': radii};
81273
81116
  }
81274
- */
81275
81117
 
81276
81118
  getCustomtubesize(resid) { let ic = this.icn3d; ic.icn3dui;
81277
81119
  let pos = resid.lastIndexOf('_');
@@ -81284,11 +81126,11 @@ class Tube {
81284
81126
  };
81285
81127
 
81286
81128
  // modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
81287
- createTubeSub(_pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
81129
+ createTubeSub(_pnts, colors, radii, bHighlight, bNonCoil, bSubdivide) { let ic = this.icn3d, me = ic.icn3dui;
81288
81130
  if(me.bNode) return;
81289
81131
 
81290
81132
  if (_pnts.length < 2) return;
81291
-
81133
+
81292
81134
  let circleDiv = ic.tubeDIV, axisDiv = ic.axisDIV;
81293
81135
  let circleDivInv = 1 / circleDiv, axisDivInv = 1 / axisDiv;
81294
81136
  //var geo = new THREE.Geometry();
@@ -81296,10 +81138,17 @@ class Tube {
81296
81138
  let verticeArray = [], colorArray = [],indexArray = [], color;
81297
81139
  let offset = 0, offset2 = 0, offset3 = 0;
81298
81140
 
81299
- let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv, undefined, undefined, prevone, nexttwo);
81141
+ let pnts;
81142
+
81143
+ if(bSubdivide) {
81144
+ let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv);
81300
81145
 
81301
- let pnts = pnts_clrs[0];
81302
- colors = pnts_clrs[2];
81146
+ pnts = pnts_clrs[0];
81147
+ colors = pnts_clrs[2];
81148
+ }
81149
+ else {
81150
+ pnts = _pnts;
81151
+ }
81303
81152
 
81304
81153
  let constRadiius;
81305
81154
  // a threshold to stop drawing the tube if it's less than this ratio of radius
@@ -81337,6 +81186,7 @@ class Tube {
81337
81186
  }
81338
81187
  }
81339
81188
  }
81189
+
81340
81190
  let delta, axis1, axis2;
81341
81191
  if (i < lim - 1) {
81342
81192
  delta = pnts[i].clone().sub(pnts[i + 1]);
@@ -81516,29 +81366,31 @@ class Strand {
81516
81366
  coilWidth = coilWidth || ic.coilWidth;
81517
81367
  doNotSmoothen = doNotSmoothen || false;
81518
81368
  helixSheetWidth = helixSheetWidth || ic.helixSheetWidth;
81519
- let pnts = {}; for (let k = 0; k < num; ++k) pnts[k] = [];
81520
- let pntsCA = [];
81521
- let prevCOArray = [];
81522
- let bShowArray = [];
81523
- let calphaIdArray = []; // used to store one of the final positions drawn in 3D
81524
- let colors = [];
81525
- let currentChain, currentStyle, currentCA = null, currentO = null, currentColor = null, prevCoorCA = null, prevCoorO = null, prevColor = null;
81526
- let prevCO = null, ss = null, ssend = false, atomid = null, prevAtomid = null, prevResi = null, calphaid = null, prevCalphaid = null;
81527
- let strandWidth, bSheetSegment = false, bHelixSegment = false;
81528
- let atom, tubeAtoms = {};
81529
81369
 
81530
81370
  // test the first 30 atoms to see whether only C-alpha is available
81531
81371
  ic.bCalphaOnly = me.utilsCls.isCalphaPhosOnly(atomsAdjust); //, 'CA');
81532
81372
 
81533
- // when highlight, draw whole beta sheet and use bShowArray to show the highlight part
81534
- let residueHash = {};
81373
+ // get chains
81374
+ let chainidHash = {};
81535
81375
  for(let i in atomsAdjust) {
81536
- let atom = atomsAdjust[i];
81537
-
81538
- let residueid = atom.structure + '_' + atom.chain + '_' + atom.resi;
81539
- residueHash[residueid] = 1;
81376
+ let atom = ic.atoms[i];
81377
+ let chainid = atom.structure + '_' + atom.chain;
81378
+ chainidHash[chainid] = 1;
81540
81379
  }
81541
- let totalResidueCount = Object.keys(residueHash).length;
81380
+
81381
+ for(let chainid in chainidHash) {
81382
+ let pntsAll = {}; for (let k = 0; k < num; ++k) pntsAll[k] = [];
81383
+ let pntsAllSub = {}; for (let k = 0; k < num; ++k) pntsAllSub[k] = [];
81384
+ let pntsCAAll = [], posArray = [], tubePosArray = [], missingResArray = [];
81385
+ let prevCOArrayAll = [];
81386
+ let colorsAll = [];
81387
+
81388
+ let pntsCAAllSub = [], prevCOArrayAllSub = [], positionsSub = [], colorsAllSub = [];
81389
+
81390
+ let currentChain, currentStyle, currentCA = null, currentColor = null, prevCoorCA = null, prevCoorO = null, prevColor = null;
81391
+ let prevCO = null, ss = null, ssend = false, ssJoint = false, prevResi = null, prevResid = null;
81392
+ let strandWidth, bSheetSegment = false, bHelixSegment = false;
81393
+ let atom, tubeAtoms = [];
81542
81394
 
81543
81395
  let drawnResidueCount = 0;
81544
81396
 
@@ -81546,64 +81398,56 @@ class Strand {
81546
81398
 
81547
81399
  let caArray = []; // record all C-alpha atoms to predict the helix
81548
81400
 
81549
- for (let i in atomsAdjust) {
81550
- atom = atomsAdjust[i];
81551
- if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
81552
- // "CA" has to appear before "O"
81401
+ let chainAtoms = me.hashUtilsCls.intHash(ic.chains[chainid], atomsAdjust);
81553
81402
 
81554
- if (atom.name === 'CA') {
81555
- if ( atoms.hasOwnProperty(i) && ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) ) {
81556
- tubeAtoms[i] = atom;
81557
- }
81403
+ let residueArray = ic.resid2specCls.atoms2residues(Object.keys(chainAtoms));
81404
+ let totalResidueCount = residueArray.length;
81405
+
81406
+ let index = 0;
81407
+
81408
+ // get pntsAll, pntsCAAll, prevCOArrayAll, colorsAll
81409
+ // get the subdivided points for all atoms
81410
+ let resi2pos = {};
81411
+ for (let i in ic.chains[chainid]) {
81412
+ atom = ic.atoms[i];
81558
81413
 
81414
+ if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
81415
+ if (atom.name === 'CA') {
81559
81416
  currentCA = atom.coord;
81560
81417
  currentColor = atom.color;
81561
- calphaid = atom.serial;
81562
-
81563
81418
  caArray.push(atom.serial);
81564
81419
  }
81565
81420
 
81566
81421
  if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA')) {
81422
+ ++index;
81423
+
81567
81424
  if(currentCA === null || currentCA === undefined) {
81568
81425
  currentCA = atom.coord;
81569
81426
  currentColor = atom.color;
81570
- calphaid = atom.serial;
81571
- }
81572
-
81573
- if(atom.name === 'O') {
81574
- currentO = atom.coord;
81575
- }
81576
- // smoothen each coil, helix and sheet separately. The joint residue has to be included both in the previous and next segment
81577
- let bSameChain = true;
81578
-
81579
- if (currentChain !== atom.chain) {
81580
- bSameChain = false;
81581
- }
81582
-
81583
- if((atom.ssend || currentStyle != atom.style)&& atom.ss === 'sheet') {
81584
- bSheetSegment = true;
81585
- }
81586
- else if((atom.ssend || currentStyle != atom.style) && atom.ss === 'helix') {
81587
- bHelixSegment = true;
81588
81427
  }
81589
81428
 
81590
81429
  // assign the previous residue
81591
81430
  if(prevCoorO) {
81592
- if(bHighlight === 1 || bHighlight === 2) {
81593
- colors.push(ic.hColor);
81431
+ // posArray.push(index - 1 - 1);
81432
+ resi2pos[prevResi] = index - 1 - 1;
81433
+
81434
+ /*
81435
+ strandWidth = (ss === 'coil') ? coilWidth : helixSheetWidth;
81436
+
81437
+ if(ss == 'sheet' && atom.ss == 'sheet' && atom.ssend) { // a transition between two sheets
81438
+ strandWidth = 1.8 * helixSheetWidth;
81594
81439
  }
81595
- else {
81596
- colors.push(prevColor);
81440
+ else if(ss == 'sheet' && ssend && atom.ss == 'coil') { // a transition between two ss
81441
+ strandWidth = 0;
81597
81442
  }
81443
+ */
81444
+ strandWidth = helixSheetWidth;
81598
81445
 
81599
- if(ss !== 'coil' && atom.ss === 'coil') {
81600
- strandWidth = coilWidth;
81601
- }
81602
- else if(ssend && atom.ssbegin) { // a transition between two ss
81603
- strandWidth = coilWidth;
81446
+ if(bHighlight === 1 || bHighlight === 2) {
81447
+ colorsAll.push(ic.hColor);
81604
81448
  }
81605
81449
  else {
81606
- strandWidth = (ss === 'coil') ? coilWidth : helixSheetWidth;
81450
+ colorsAll.push(prevColor);
81607
81451
  }
81608
81452
 
81609
81453
  let O, oldCA, resSpan = 4;
@@ -81645,239 +81489,164 @@ class Strand {
81645
81489
  for (let j = 0, numM1Inv2 = 2 / (num - 1); j < num; ++j) {
81646
81490
  let delta = -1 + numM1Inv2 * j;
81647
81491
  let v = new Vector3$1(prevCoorCA.x + prevCO.x * delta, prevCoorCA.y + prevCO.y * delta, prevCoorCA.z + prevCO.z * delta);
81648
- if (!doNotSmoothen && ss === 'sheet') v.smoothen = true;
81649
- pnts[j].push(v);
81492
+ // no smoothen for the last two residues in sheet
81493
+ if (!doNotSmoothen && ss === 'sheet' && !ssJoint && !(atom.ssend)) v.smoothen = true;
81494
+ pntsAll[j].push(v);
81650
81495
  }
81651
81496
 
81652
- pntsCA.push(prevCoorCA);
81653
- prevCOArray.push(prevCO);
81497
+ pntsCAAll.push(prevCoorCA);
81498
+ prevCOArrayAll.push(prevCO);
81499
+ }
81654
81500
 
81655
- if(atoms.hasOwnProperty(prevAtomid)) {
81656
- bShowArray.push(prevResi);
81657
- calphaIdArray.push(prevCalphaid);
81658
- }
81659
- else {
81660
- bShowArray.push(0);
81661
- calphaIdArray.push(0);
81662
- }
81501
+ // only update when atom.name === 'O'
81502
+ prevResi = atom.resi;
81663
81503
 
81664
- ++drawnResidueCount;
81665
- }
81504
+ prevCoorCA = currentCA;
81505
+ prevCoorO = atom.coord;
81506
+ prevColor = currentColor;
81666
81507
 
81667
- let maxDist = 6.0;
81668
- let bBrokenSs = (prevCoorCA && Math.abs(currentCA.x - prevCoorCA.x) > maxDist) || (prevCoorCA && Math.abs(currentCA.y - prevCoorCA.y) > maxDist) || (prevCoorCA && Math.abs(currentCA.z - prevCoorCA.z) > maxDist);
81669
- // The following code didn't work to select one residue
81670
- // let bBrokenSs = !atoms.hasOwnProperty(atom.serial) || (prevCoorCA && Math.abs(currentCA.x - prevCoorCA.x) > maxDist) || (prevCoorCA && Math.abs(currentCA.y - prevCoorCA.y) > maxDist) || (prevCoorCA && Math.abs(currentCA.z - prevCoorCA.z) > maxDist);
81508
+ ss = atom.ss;
81509
+ ssend = atom.ssend;
81510
+ ssJoint = atom.ssbegin || atom.ssend;
81511
+ } // end if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA') ) {
81512
+ } // end if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
81513
+ } // end for
81671
81514
 
81672
- // if(bBrokenSs && atom.ss === 'sheet') {
81673
- // bSheetSegment = true;
81674
- // }
81675
- // else if(bBrokenSs && atom.ss === 'helix') {
81676
- // bHelixSegment = true;
81677
- // }
81515
+ // add the last residue
81516
+ // posArray.push(index - 1);
81517
+ resi2pos[prevResi] = index - 1;
81678
81518
 
81679
- if ((atom.ssbegin || atom.ssend || (drawnResidueCount === totalResidueCount - 1) || bBrokenSs || currentStyle != atom.style) && pnts[0].length > 0 && bSameChain) {
81680
- let atomName = 'CA';
81519
+ colorsAll.push(prevColor);
81520
+ for (let j = 0, numM1Inv2 = 2 / (num - 1); j < num; ++j) {
81521
+ let delta = -1 + numM1Inv2 * j;
81522
+ let v = new Vector3$1(prevCoorCA.x + prevCO.x * delta, prevCoorCA.y + prevCO.y * delta, prevCoorCA.z + prevCO.z * delta);
81523
+ // no smoothen for the last two residues in sheet
81524
+ if (!doNotSmoothen && ss === 'sheet' && !ssJoint && !(ssend)) v.smoothen = true;
81525
+ pntsAll[j].push(v);
81526
+ }
81527
+ pntsCAAll.push(prevCoorCA);
81528
+ prevCOArrayAll.push(prevCO);
81681
81529
 
81682
- let prevone = [], nexttwo = [];
81530
+ // each point except the last one are divided into div segments. The last point is not divided.
81531
+ let pnts_clrs;
81532
+ for(let i = 0; i < num; ++i) {
81533
+ pnts_clrs = me.subdivideCls.subdivide(pntsAll[i], colorsAll, div);
81534
+ pntsAllSub[i] = pnts_clrs[0];
81535
+ }
81683
81536
 
81684
- if(isNaN(ic.atoms[prevAtomid].resi)) {
81685
- prevone = [];
81686
- }
81687
- else {
81688
- let prevoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) - 1).toString();
81689
- let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
81690
- prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
81691
- }
81537
+ pnts_clrs = me.subdivideCls.subdivide(pntsCAAll, colorsAll, div);
81538
+ pntsCAAllSub = pnts_clrs[0];
81539
+ colorsAllSub = pnts_clrs[2];
81540
+
81541
+ pnts_clrs = me.subdivideCls.subdivide(prevCOArrayAll, colorsAll, div);
81542
+ prevCOArrayAllSub = pnts_clrs[0];
81543
+ positionsSub = pnts_clrs[1];
81692
81544
 
81693
- if(!isNaN(ic.atoms[prevAtomid].resi)) {
81694
- let nextoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) + 1).toString();
81695
- let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
81696
- if(nextoneCoord !== undefined) {
81697
- nexttwo.push(nextoneCoord);
81698
- }
81545
+ posArray = [];
81546
+ prevCoorO = null;
81547
+ prevCoorCA = null;
81548
+ ss = null;
81549
+ ssend = false;
81550
+ ssJoint = false;
81699
81551
 
81700
- let nexttwoResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) + 2).toString();
81701
- let nexttwoCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nexttwoResid, atomName);
81702
- if(nexttwoCoord !== undefined) {
81703
- nexttwo.push(nexttwoCoord);
81704
- }
81705
- }
81552
+ index = 0;
81553
+ let bLastResDrawn = false;
81706
81554
 
81707
- if(!bBrokenSs) { // include the current residue
81708
- // assign the current joint residue to the previous segment
81709
- if(bHighlight === 1 || bHighlight === 2) {
81710
- colors.push(ic.hColor);
81711
- }
81712
- else {
81713
- //colors.push(atom.color);
81714
- colors.push(prevColor);
81715
- }
81555
+ // draw only for the selected atoms
81556
+ for (let i in chainAtoms) {
81557
+ atom = ic.atoms[i];
81558
+ if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
81559
+ // "CA" has to appear before "O"
81716
81560
 
81717
- if(atom.ssend && atom.ss === 'sheet') { // current residue is the end of ss and is the end of arrow
81718
- strandWidth = 0; // make the arrow end sharp
81719
- }
81720
- else if(ss === 'coil' && atom.ssbegin) {
81721
- strandWidth = coilWidth;
81722
- }
81723
- else if(ssend && atom.ssbegin) { // current residue is the start of ss and the previous residue is the end of ss, then use coil
81724
- strandWidth = coilWidth;
81725
- }
81726
- else { // use the ss from the previous residue
81727
- strandWidth = (atom.ss === 'coil') ? coilWidth : helixSheetWidth;
81728
- }
81561
+ if (atom.name === 'CA') {
81562
+ // if ( atoms.hasOwnProperty(i) && ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) ) {
81563
+ if ( atoms.hasOwnProperty(i) && ((atom.ss !== 'helix' && atom.ss !== 'sheet') ) ) {
81564
+ tubeAtoms.push(atom);
81565
+ let pos = resi2pos[atom.resi];
81566
+ tubePosArray.push(pos);
81729
81567
 
81730
- let O, oldCA, resSpan = 4;
81731
- if(atom.name === 'O') {
81732
- O = currentO.clone();
81733
- O.sub(currentCA);
81734
- }
81735
- else if(ic.bCalphaOnly && atom.name === 'CA') {
81736
- if(caArray.length > resSpan) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
81737
- O = currentCA.clone();
81738
- oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan]].coord.clone();
81739
- //O.sub(oldCA);
81740
- oldCA.sub(O);
81741
- }
81742
- else {
81743
- O = new Vector3$1(Math.random(),Math.random(),Math.random());
81744
- }
81745
- }
81568
+ continue;
81569
+ }
81570
+ }
81746
81571
 
81747
- O.normalize(); // can be omitted for performance
81748
- O.multiplyScalar(strandWidth);
81749
- if (prevCO !== null && O.dot(prevCO) < 0) O.negate();
81750
- prevCO = O;
81572
+ if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA')) {
81573
+ ++index;
81751
81574
 
81752
- for (let j = 0, numM1Inv2 = 2 / (num - 1); j < num; ++j) {
81753
- let delta = -1 + numM1Inv2 * j;
81754
- let v = new Vector3$1(currentCA.x + prevCO.x * delta, currentCA.y + prevCO.y * delta, currentCA.z + prevCO.z * delta);
81755
- if (!doNotSmoothen && ss === 'sheet') v.smoothen = true;
81756
- pnts[j].push(v);
81757
- }
81575
+ currentCA = atom.coord;
81758
81576
 
81759
- atomid = atom.serial;
81577
+ // smoothen each coil, helix and sheet separately. The joint residue has to be included both in the previous and next segment
81578
+ // if((atom.ssend || currentStyle != atom.style)&& atom.ss === 'sheet') {
81579
+ // bSheetSegment = true;
81580
+ // }
81581
+ // else if((atom.ssend || currentStyle != atom.style) && atom.ss === 'helix') {
81582
+ // bHelixSegment = true;
81583
+ // }
81584
+ if(atom.ss === 'sheet') {
81585
+ bSheetSegment = true;
81586
+ bHelixSegment = false;
81587
+ }
81588
+ else if(atom.ss === 'helix') {
81589
+ bSheetSegment = false;
81590
+ bHelixSegment = true;
81591
+ }
81592
+ else {
81593
+ bSheetSegment = false;
81594
+ bHelixSegment = false;
81595
+ }
81760
81596
 
81761
- pntsCA.push(currentCA);
81762
- prevCOArray.push(prevCO);
81597
+ // assign the previous residue
81598
+ if(prevCoorO) {
81599
+ //pntsCA.push(prevCoorCA);
81600
+ //prevCOArray.push(prevCO);
81601
+ let pos = resi2pos[prevResi];
81602
+ // posArray.push(index - 1 - 1);
81603
+ posArray.push(pos);
81763
81604
 
81764
- // when a coil connects to a sheet and the last residue of coild is highlighted, the first sheet residue is set as atom.highlightStyle. This residue should not be shown.
81765
- //if(atoms.hasOwnProperty(atomid) && (bHighlight === 1 && !atom.notshow) ) {
81766
- if(atoms.hasOwnProperty(atomid)) {
81767
- bShowArray.push(atom.resi);
81768
- calphaIdArray.push(calphaid);
81769
- }
81770
- else {
81771
- bShowArray.push(0);
81772
- calphaIdArray.push(0);
81773
- }
81774
- }
81605
+ let bMissingStart = ic.missingResStart[prevResid];
81606
+ let bMissingEnd = ic.missingResEnd[prevResid];
81607
+ let missingResType = bMissingStart ? 1 : (bMissingEnd ? 2 : 0);
81608
+ missingResArray.push(missingResType);
81775
81609
 
81776
- // draw the current segment
81777
- for (let j = 0; !fill && j < num; ++j) {
81778
- if(bSheetSegment) {
81779
- ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
81780
- }
81781
- else if(bHelixSegment) {
81782
- if(bFullAtom) {
81783
- ic.curveCls.createCurveSub(pnts[j], 1, colors, div, bHighlight, bRibbon, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo);
81784
- }
81785
- else {
81786
- ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
81787
- }
81788
- }
81789
- }
81790
- if (fill) {
81791
- if(bSheetSegment) {
81792
- let start = 0, end = num - 1;
81793
- ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
81794
- }
81795
- else if(bHelixSegment) {
81796
- if(bFullAtom) {
81797
- ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
81798
- }
81799
- else {
81800
- let start = 0, end = num - 1;
81801
- ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
81802
- }
81803
- }
81804
- else {
81805
- if(bHighlight === 2) { // draw coils only when highlighted. if not highlighted, coils will be drawn as tubes separately
81806
- ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
81807
- }
81808
- }
81809
- }
81810
- for (let k = 0; k < num; ++k) pnts[k] = [];
81610
+ ++drawnResidueCount;
81611
+ }
81811
81612
 
81812
- colors = [];
81813
- pntsCA = [];
81814
- prevCOArray = [];
81815
- bShowArray = [];
81816
- calphaIdArray = [];
81817
- bSheetSegment = false;
81818
- bHelixSegment = false;
81819
- } // end if (atom.ssbegin || atom.ssend)
81613
+ let maxDist = 6.0;
81614
+ let bBrokenSs = (ic.ParserUtilsCls.getResiNCBI(chainid, atom.resi) > ic.ParserUtilsCls.getResiNCBI(chainid,prevResi) + 1) || (prevCoorCA && Math.abs(currentCA.x - prevCoorCA.x) > maxDist) || (prevCoorCA && Math.abs(currentCA.y - prevCoorCA.y) > maxDist) || (prevCoorCA && Math.abs(currentCA.z - prevCoorCA.z) > maxDist);
81820
81615
 
81821
- // end of a chain
81822
- if ((currentChain !== atom.chain || currentStyle != atom.style) && pnts[0].length > 0) {
81823
- let atomName = 'CA';
81616
+ // check for the last atom
81617
+ if ((atom.ssbegin || atom.ssend || bBrokenSs || currentStyle != atom.style || currentChain !== atom.chain) ) {
81618
+ // && posArray.length > 0) {
81619
+ if(!bBrokenSs) { // include the current residue
81620
+ if(drawnResidueCount === totalResidueCount - 1) bLastResDrawn = true;
81824
81621
 
81825
- let prevone = [], nexttwo = [];
81826
- if(isNaN(ic.atoms[prevAtomid].resi)) {
81827
- prevone = [];
81828
- }
81829
- else {
81830
- let prevoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) - 1).toString();
81831
- ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
81832
- }
81622
+ let pos = resi2pos[atom.resi];
81623
+ // posArray.push(index - 1);
81624
+ posArray.push(pos);
81833
81625
 
81834
- for (let j = 0; !fill && j < num; ++j) {
81835
- if(bSheetSegment) {
81836
- ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
81837
- }
81838
- else if(bHelixSegment) {
81839
- if(bFullAtom) {
81840
- ic.curveCls.createCurveSub(pnts[j], 1, colors, div, bHighlight, bRibbon, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo);
81841
- }
81842
- else {
81843
- ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
81844
- }
81845
- }
81846
- }
81847
- if (fill) {
81848
- if(bSheetSegment) {
81849
- let start = 0, end = num - 1;
81850
- ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
81851
- }
81852
- else if(bHelixSegment) {
81853
- if(bFullAtom) {
81854
- ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
81855
- }
81856
- else {
81857
- let start = 0, end = num - 1;
81858
- ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
81859
- }
81860
- }
81626
+ let bMissingStart = ic.missingResStart[atom.structure + '_' + atom.chain + '_' + atom.resi];
81627
+ let bMissingEnd = ic.missingResEnd[atom.structure + '_' + atom.chain + '_' + atom.resi];
81628
+ let missingResType = bMissingStart ? 1 : (bMissingEnd ? 2 : 0);
81629
+ missingResArray.push(missingResType);
81861
81630
  }
81862
81631
 
81863
- for (let k = 0; k < num; ++k) pnts[k] = [];
81864
- colors = [];
81865
- pntsCA = [];
81866
- prevCOArray = [];
81867
- bShowArray = [];
81868
- calphaIdArray = [];
81869
- bSheetSegment = false;
81870
- bHelixSegment = false;
81871
- }
81632
+ bSheetSegment = prevCoorO ? (ss === 'sheet') : (atom.ss === 'sheet');
81633
+ bHelixSegment = prevCoorO ? (ss === 'helix') : (atom.ss === 'helix');
81634
+ // skip the 2-residue joint between two adjacent SS (sheet end -> helix begin)
81635
+ if(!(ssend && atom.ssbegin)) {
81636
+ this.createStrand_base(posArray, pntsAllSub, pntsCAAllSub, prevCOArrayAllSub, colorsAllSub, positionsSub, missingResArray, fill, bHighlight, bRibbon, num, bSheetSegment, bHelixSegment, bFullAtom, thickness);
81637
+ }
81638
+ posArray = [];
81639
+ missingResArray = [];
81640
+ } // end if (atom.ssbegin || atom.ssend)
81872
81641
 
81873
81642
  currentChain = atom.chain;
81874
81643
  currentStyle = atom.style;
81875
81644
  ss = atom.ss;
81876
81645
  ssend = atom.ssend;
81877
- prevAtomid = atom.serial;
81646
+ atom.serial;
81878
81647
  prevResi = atom.resi;
81879
81648
 
81880
- prevCalphaid = calphaid;
81649
+ prevResid = atom.structure + '_' + atom.chain + '_' + atom.resi;
81881
81650
 
81882
81651
  // only update when atom.name === 'O'
81883
81652
  prevCoorCA = currentCA;
@@ -81887,12 +81656,95 @@ class Strand {
81887
81656
  } // end if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
81888
81657
  } // end for
81889
81658
 
81659
+ // draw the last residue
81660
+ if(!bLastResDrawn && drawnResidueCount === totalResidueCount - 1) {
81661
+ let pos = resi2pos[prevResi];
81662
+ // posArray.push(index - 1);
81663
+ posArray.push(pos);
81664
+
81665
+ let bMissingStart = ic.missingResStart[prevResid];
81666
+ let bMissingEnd = ic.missingResEnd[prevResid];
81667
+ let missingResType = bMissingStart ? 1 : (bMissingEnd ? 2 : 0);
81668
+ missingResArray.push(missingResType);
81669
+
81670
+ bSheetSegment = prevCoorO ? (ss === 'sheet') : (atom.ss === 'sheet');
81671
+ bHelixSegment = prevCoorO ? (ss === 'helix') : (atom.ss === 'helix');
81672
+ this.createStrand_base(posArray, pntsAllSub, pntsCAAllSub, prevCOArrayAllSub, colorsAllSub, positionsSub, missingResArray, fill, bHighlight, bRibbon, num, bSheetSegment, bHelixSegment, bFullAtom, thickness);
81673
+ } // end if (atom.ssbegin || atom.ssend)
81674
+
81675
+ ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight, undefined, undefined, tubePosArray, pntsCAAllSub, colorsAllSub);
81676
+
81890
81677
  caArray = [];
81678
+ tubeAtoms = [];
81679
+ posArray = [];
81680
+ missingResArray = [];
81681
+ tubePosArray = [];
81682
+ pntsAll = {}, pntsCAAll = [], prevCOArrayAll = [], colorsAll = [];
81683
+ } // end for chainid in ic.chains
81684
+ }
81891
81685
 
81892
- ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight);
81686
+ createStrand_base(posArray, pntsAllSub, pntsCAAllSub, prevCOArrayAllSub, colorsAllSub, positionsSub, missingResArray, fill, bHighlight, bRibbon, num, bSheetSegment, bHelixSegment, bFullAtom, thickness) { let ic = this.icn3d; ic.icn3dui;
81687
+ let pntsCATmp = [], prevCOArrayTmp = [], colorsTmp = [], positionsTmp = [];
81688
+ let pntsTmp = {}; for (let k = 0; k < num; ++k) pntsTmp[k] = [];
81689
+ let half = Math.floor(ic.axisDIV / 2) - 1;
81893
81690
 
81894
- tubeAtoms = {};
81895
- pnts = {};
81691
+ for(let j = 0, jl = posArray.length; j < jl; ++j) {
81692
+ let pos = posArray[j];
81693
+ let missingResType = missingResArray[j];
81694
+
81695
+ let offsetStart = (missingResType == 1) ? half : 0;
81696
+ let offsetEnd = (missingResType == 2) ? half : 0;
81697
+
81698
+ let indexArray = this.pos2IndexArray(pos, pntsCAAllSub);
81699
+
81700
+ for(let k = offsetEnd, kl = indexArray.length - offsetStart; k < kl; ++k) {
81701
+ pntsCATmp.push(pntsCAAllSub[indexArray[k]]);
81702
+ prevCOArrayTmp.push(prevCOArrayAllSub[indexArray[k]]);
81703
+ colorsTmp.push(colorsAllSub[indexArray[k]]);
81704
+ positionsTmp.push(positionsSub[indexArray[k]]);
81705
+ }
81706
+
81707
+ for(let k = 0; k < num; ++k) {
81708
+ for(let l = 0, ll = indexArray.length; l < ll; ++l) {
81709
+ pntsTmp[k].push(pntsAllSub[k][indexArray[l]]);
81710
+ }
81711
+ }
81712
+ }
81713
+
81714
+ // draw the current segment
81715
+ for (let j = 0; !fill && j < num; ++j) {
81716
+ if(bSheetSegment) {
81717
+ ic.curveStripArrowCls.createCurveSubArrow(pntsTmp[j], 1, colorsTmp, 1, bHighlight, bRibbon, num, j, pntsCATmp, prevCOArrayTmp, positionsTmp, true);
81718
+ }
81719
+ else if(bHelixSegment) {
81720
+ if(bFullAtom) {
81721
+ ic.curveCls.createCurveSub(pntsTmp[j], 1, colorsTmp, 1, bHighlight, bRibbon, false, undefined);
81722
+ }
81723
+ else {
81724
+ ic.curveStripArrowCls.createCurveSubArrow(pntsTmp[j], 1, colorsTmp, 1, bHighlight, bRibbon, num, j, pntsCATmp, prevCOArrayTmp, positionsTmp, false);
81725
+ }
81726
+ }
81727
+ }
81728
+ if (fill) {
81729
+ if(bSheetSegment) {
81730
+ let start = 0, end = num - 1;
81731
+ ic.curveStripArrowCls.createStripArrow(pntsTmp[0], pntsTmp[num - 1], colorsTmp, 1, thickness, bHighlight, num, start, end, pntsCATmp, prevCOArrayTmp, positionsTmp, true);
81732
+ }
81733
+ else if(bHelixSegment) {
81734
+ if(bFullAtom) {
81735
+ ic.stripCls.createStrip(pntsTmp[0], pntsTmp[num - 1], colorsTmp, 1, thickness, bHighlight, false, undefined, pntsCATmp, prevCOArrayTmp);
81736
+ }
81737
+ else {
81738
+ let start = 0, end = num - 1;
81739
+ ic.curveStripArrowCls.createStripArrow(pntsTmp[0], pntsTmp[num - 1], colorsTmp, 1, thickness, bHighlight, num, start, end, pntsCATmp, prevCOArrayTmp, positionsTmp, false);
81740
+ }
81741
+ }
81742
+ else {
81743
+ if(bHighlight === 2) { // draw coils only when highlighted. if not highlighted, coils will be drawn as tubes separately
81744
+ ic.stripCls.createStrip(pntsTmp[0], pntsTmp[num - 1], colorsTmp, 1, thickness, bHighlight, false, undefined, pntsCATmp, prevCOArrayTmp);
81745
+ }
81746
+ }
81747
+ }
81896
81748
  }
81897
81749
 
81898
81750
  getSSExpandedAtoms(atoms, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
@@ -81917,7 +81769,7 @@ class Strand {
81917
81769
  else if(index === length - 1) {
81918
81770
  lastAtom = currAtom;
81919
81771
  }
81920
-
81772
+ /*
81921
81773
  // fill the beginning
81922
81774
  let beginResi = firstAtom.resi;
81923
81775
  if(!isNaN(firstAtom.resi) && firstAtom.ss !== 'coil' && !(firstAtom.ssbegin) ) {
@@ -81939,7 +81791,7 @@ class Strand {
81939
81791
  ic.atoms));
81940
81792
  }
81941
81793
  }
81942
-
81794
+ */
81943
81795
  // add one extra residue for coils between strands/helix if the style is NOT stick, ball and stick, lines, sphere, and dot
81944
81796
  // if(!isNaN(firstAtom.resi) && ic.pk === 3 && bHighlight === 1 && firstAtom.ss === 'coil') {
81945
81797
  if(!isNaN(firstAtom.resi) && ic.pk === 3 && bHighlight === 1 && firstAtom.ss === 'coil' && firstAtom.style != 'stick' && firstAtom.style != 'ball and stick' && firstAtom.style != 'lines' && firstAtom.style != 'sphere' && firstAtom.style != 'dot') {
@@ -81950,7 +81802,7 @@ class Strand {
81950
81802
  atoms = me.hashUtilsCls.unionHash(atoms, me.hashUtilsCls.hash2Atoms(ic.residues[residueid], ic.atoms));
81951
81803
  }
81952
81804
  }
81953
-
81805
+ /*
81954
81806
  // fill the end
81955
81807
  let endResi = lastAtom.resi;
81956
81808
  // when a coil connects to a sheet and the last residue of coil is highlighted, the first sheet residue is set as atom.notshow. This residue should not be shown.
@@ -81976,7 +81828,7 @@ class Strand {
81976
81828
  ic.atoms));
81977
81829
  }
81978
81830
  }
81979
-
81831
+ */
81980
81832
  // add one extra residue for coils between strands/helix if the style is NOT stick, ball and stick, lines, sphere, and dot
81981
81833
  if(ic.pk === 3 && bHighlight === 1 && lastAtom.ss === 'coil' && firstAtom.style != 'stick' && firstAtom.style != 'ball and stick' && firstAtom.style != 'lines' && firstAtom.style != 'sphere' && firstAtom.style != 'dot') {
81982
81834
  let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + (parseInt(lastAtom.resi) + 1).toString();
@@ -82002,6 +81854,32 @@ class Strand {
82002
81854
 
82003
81855
  return atomsAdjust;
82004
81856
  }
81857
+
81858
+ pos2IndexArray(pos, pntsCAAllSub) { let ic = this.icn3d; ic.icn3dui;
81859
+ let indexArray = [];
81860
+
81861
+ let offset = Math.floor(ic.axisDIV / 2) + 1; // first residue has floor(DIV/2)+1 points (8 when axisDIV = 15)
81862
+
81863
+ //subdivide() gives the first residue only floor(DIV/2)+1 points (8 when axisDIV = 15) and each later residue 15.
81864
+ if(pos == 0) {
81865
+ for(let j = 0; j < offset; ++j) {
81866
+ indexArray.push(j);
81867
+ }
81868
+ }
81869
+ else {
81870
+ for(let j = 0; j < ic.axisDIV; ++j) {
81871
+ let index = offset + (pos - 1) * ic.axisDIV + j;
81872
+ if(index >= pntsCAAllSub.length) {
81873
+ indexArray.push(pntsCAAllSub.length - 1);
81874
+ break;
81875
+ } else {
81876
+ indexArray.push(index);
81877
+ }
81878
+ }
81879
+ }
81880
+
81881
+ return indexArray;
81882
+ }
82005
81883
  }
82006
81884
 
82007
81885
  /**
@@ -86125,6 +86003,9 @@ class ApplyMissingRes {
86125
86003
  }
86126
86004
  }
86127
86005
 
86006
+ if(ic.missingResStart === undefined) ic.missingResStart = {};
86007
+ if(ic.missingResEnd === undefined) ic.missingResEnd = {};
86008
+
86128
86009
  for(let i = 0, il = misingResArray.length; i < il; i += 2) {
86129
86010
  let resid0 = misingResArray[i];
86130
86011
  let resid1 = misingResArray[i + 1];
@@ -86141,6 +86022,10 @@ class ApplyMissingRes {
86141
86022
  ic.missingResPnts[structure].push(resid0);
86142
86023
  ic.missingResPnts[structure].push(resid1);
86143
86024
 
86025
+ ic.missingResStart[resid0] = 1;
86026
+ ic.missingResEnd[resid1] = 1;
86027
+
86028
+
86144
86029
  ic.missingResResid2serial[resid0 + ',' + resid1] = atom0.serial;
86145
86030
  ic.missingResResid2serial[resid1 + ',' + resid0] = atom1.serial;
86146
86031
  }
@@ -86420,10 +86305,20 @@ class ApplyDisplay {
86420
86305
  ic.cylinderCls.createCylinderCurve(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), ['CA'], ic.traceRadius, false, bHighlight);
86421
86306
  }
86422
86307
  else if(style === 'b factor tube') {
86423
- ic.tubeCls.createTube(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), 'CA', null, bHighlight, false, true);
86308
+ let atomArray = [];
86309
+ for(let i in atomHash) {
86310
+ let atom = ic.atoms[i];
86311
+ atomArray.push(atom);
86312
+ }
86313
+ ic.tubeCls.createTube(atomArray, 'CA', null, bHighlight, false, true);
86424
86314
  }
86425
86315
  else if(style === 'custom tube') {
86426
- ic.tubeCls.createTube(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), 'CA', null, bHighlight, true, true);
86316
+ let atomArray = [];
86317
+ for(let i in atomHash) {
86318
+ let atom = ic.atoms[i];
86319
+ atomArray.push(atom);
86320
+ }
86321
+ ic.tubeCls.createTube(atomArray, 'CA', null, bHighlight, true, true);
86427
86322
  }
86428
86323
  else if(style === 'lines' || style === 'lines2') {
86429
86324
  if(bHighlight === 1) {
@@ -86734,7 +86629,7 @@ class ApplyOther {
86734
86629
  break;
86735
86630
  }
86736
86631
  else if(atom.name === 'CA' && (atom.ss == 'helix' || atom.ss == 'sheet')) { // protein secondary: CA
86737
- pos = (ic.atoms[i].coord2 !== undefined) ? ic.atoms[i].coord2 : ic.atoms[i].coord;
86632
+ pos = ic.atoms[i].coord;
86738
86633
  break;
86739
86634
  }
86740
86635
  }
@@ -106059,7 +105954,6 @@ class WebGLPathTracer {
106059
105954
  }
106060
105955
  else {
106061
105956
  if(bPathTracer) {
106062
- console.log("###pathTracer");
106063
105957
  ic.bImpo = false; // disable impostor for path tracing
106064
105958
  const pathTracer = new WebGLPathTracer(ic.renderer);
106065
105959
  pathTracer.setScene(ic.scene, cam);
@@ -132463,6 +132357,59 @@ class SetSeqAlign {
132463
132357
  ic.nconsHash2 = {};
132464
132358
  ic.nalignHash2 = {};
132465
132359
 
132360
+ let msaSameColor = [];
132361
+ // assume all aligned seq are the same. If any aligned res is different,set it to false (0)
132362
+ for(let i = 0, il = seqalign[0].length; i < il; ++i) {
132363
+ msaSameColor.push(1);
132364
+ }
132365
+
132366
+ for(let i = 0, il = seqalign.length; i < il; ++i) {
132367
+ // first sequence
132368
+ let alignData = seqalign[i][0];
132369
+ let molid1 = alignData.moleculeId;
132370
+
132371
+ let chain1 = ic.pdbid_molid2chain[mmdbid1 + '_' + molid1];
132372
+ chainid1 = mmdbid1 + '_' + chain1;
132373
+
132374
+ let id2aligninfo = {};
132375
+ let start = alignData.sequence.length, end = -1;
132376
+ let bStart = false;
132377
+ for(let j = 0, jl = alignData.sequence.length; j < jl; ++j) {
132378
+ // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
132379
+ let resi =(ic.bUsePdbNum) ? ic.ParserUtilsCls.getResi(chainid1, alignData.sequence[j][0] - 1) : alignData.sequence[j][0];
132380
+ let resn =(alignData.sequence[j][2] === '~') ? '-' : alignData.sequence[j][2];
132381
+ resn =(resn === ' ' || resn === '') ? 'X' : resn;
132382
+
132383
+ let aligned =(alignData.sequence[j][3]) ? 1 : 0;
132384
+
132385
+ if(aligned == 1) {
132386
+ if(j < start && !bStart) {
132387
+ start = j;
132388
+ bStart = true; // set start just once
132389
+ }
132390
+ if(j > end) end = j;
132391
+ }
132392
+
132393
+ id2aligninfo[j] = {"resi": resi, "resn": resn, "aligned": aligned};
132394
+ }
132395
+
132396
+ // second sequence
132397
+ alignData = seqalign[i][1];
132398
+
132399
+ for(let j = start; j <= end; ++j) {
132400
+ // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
132401
+ let alignedTmp =(alignData.sequence[j][3]) ? 1 : 0;
132402
+
132403
+ let aligned = id2aligninfo[j].aligned + alignedTmp; // 0 or 2
132404
+
132405
+ if(aligned === 2) { // aligned
132406
+ if(id2aligninfo[j].resn != resn) {
132407
+ msaSameColor[j] = 0;
132408
+ }
132409
+ }
132410
+ }
132411
+ }
132412
+
132466
132413
  for(let i = 0, il = seqalign.length; i < il; ++i) {
132467
132414
  // first sequence
132468
132415
  let alignData = seqalign[i][0];
@@ -132559,6 +132506,8 @@ class SetSeqAlign {
132559
132506
  ic.nconsHash2[chainid2 + '_' + resi] = 1;
132560
132507
  }
132561
132508
 
132509
+ color = (msaSameColor[j] == 0) ? '#0000FF' : '#FF0000';
132510
+
132562
132511
  // mapping, use the firstsequence as the reference structure
132563
132512
  ic.chainsMapping[chainid1][chainid1 + '_' + id2aligninfo[j].resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
132564
132513
  ic.chainsMapping[chainid2][chainid2 + '_' + resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
@@ -132575,6 +132524,8 @@ class SetSeqAlign {
132575
132524
 
132576
132525
  ic.nalignHash1[chainid1 + '_' + id2aligninfo[j].resi] = 1;
132577
132526
  ic.nalignHash2[chainid2 + '_' + resi] = 1;
132527
+
132528
+ msaSameColor[j] = 2; // not aligned
132578
132529
  }
132579
132530
 
132580
132531
  // chain1
@@ -133672,8 +133623,10 @@ class SetSeqAlign {
133672
133623
  ic.msaSeq[chainid2] += '-';
133673
133624
  }
133674
133625
  }
133675
-
133626
+ /*
133676
133627
  setSeqAlignForRealign(chainid_t, chainid, chainIndex) { let ic = this.icn3d, me = ic.icn3dui;
133628
+ //loadSeqAlignment
133629
+ let alignedAtoms = {};
133677
133630
  //var chainid_t = ic.chainidArray[0];
133678
133631
 
133679
133632
  // let structureArray = Object.keys(ic.structures);
@@ -133695,7 +133648,7 @@ class SetSeqAlign {
133695
133648
  ic.alnChains = {};
133696
133649
 
133697
133650
  ic.alnChainsSeq[chainid_t] = [];
133698
- ic.alnChains[chainid_t] = {};
133651
+ ic.alnChains[chainid_t] = {}
133699
133652
  ic.alnChainsAnno[chainid_t] = [];
133700
133653
  ic.alnChainsAnTtl[chainid_t] = [];
133701
133654
 
@@ -133773,8 +133726,8 @@ class SetSeqAlign {
133773
133726
  ic.alnChainsSeq[chainid1].push(resObject1);
133774
133727
  ic.alnChainsSeq[chainid2].push(resObject2);
133775
133728
 
133776
- if(ic.alnChains[chainid1] === undefined) ic.alnChains[chainid1] = {};
133777
- if(ic.alnChains[chainid2] === undefined) ic.alnChains[chainid2] = {};
133729
+ if(ic.alnChains[chainid1] === undefined) ic.alnChains[chainid1] = {}
133730
+ if(ic.alnChains[chainid2] === undefined) ic.alnChains[chainid2] = {}
133778
133731
  $.extend(ic.alnChains[chainid1], ic.residues[chainid1 + '_' + resObject1.resi] );
133779
133732
  $.extend(ic.alnChains[chainid2], ic.residues[chainid2 + '_' + resObject2.resi] );
133780
133733
 
@@ -133804,6 +133757,7 @@ class SetSeqAlign {
133804
133757
  let select = "select " + ic.resid2specCls.residueids2spec(Object.keys(residuesHash));
133805
133758
  ic.selectionCls.addCustomSelection(Object.keys(residuesHash), commandname, commanddescr, select, true);
133806
133759
  }
133760
+ */
133807
133761
 
133808
133762
  setSeqPerResi(chainid, chainid1, chainid2, resi, resn, bAligned, color, color2, classname, bFirstChain, bFirstResi, alignIndex) { let ic = this.icn3d, me = ic.icn3dui;
133809
133763
  if(ic.alnChainsSeq[chainid] === undefined) ic.alnChainsSeq[chainid] = [];
@@ -138121,16 +138075,6 @@ class ApplyCommand {
138121
138075
  let color = command.substr(command.lastIndexOf(' ') + 1);
138122
138076
  me.htmlCls.setMenuCls.setTheme(color);
138123
138077
  }
138124
- else if(command.indexOf('set double color') == 0) {
138125
- let value = command.substr(command.lastIndexOf(' ') + 1);
138126
- if(value == 'on') {
138127
- ic.bDoublecolor = true;
138128
- ic.setOptionCls.setStyle('proteins', 'ribbon');
138129
- }
138130
- else if(value == 'off') {
138131
- ic.bDoublecolor = false;
138132
- }
138133
- }
138134
138078
  else if(command.indexOf('adjust dialog') == 0) {
138135
138079
  let id = command.substr(command.lastIndexOf(' ') + 1);
138136
138080
  ic.scapCls.adjust2DWidth(id);
@@ -138597,7 +138541,6 @@ class ApplyCommand {
138597
138541
  else if(cmd.indexOf('replay on') !== -1) return 'File > Replay Each Step > On';
138598
138542
  else if(cmd.indexOf('replay off') !== -1) return 'File > Replay Each Step > Off';
138599
138543
  else if(cmd.indexOf('set theme') !== -1) return 'Style > Theme Color';
138600
- else if(cmd.indexOf('set double color') !== -1) return 'Style > Two-color Helix';
138601
138544
  else return '';
138602
138545
  }
138603
138546
  }
@@ -139715,6 +139658,17 @@ class LoadScript {
139715
139658
  nameArray = paraArray[1].split(',');
139716
139659
  ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(nameArray);
139717
139660
  }
139661
+ else {
139662
+ let structureHash = {};
139663
+
139664
+ for(let chainid in ic.chains) {
139665
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chainid]);
139666
+ if(!structureHash.hasOwnProperty(atom.structure) && (ic.proteins.hasOwnProperty(atom.serial) || ic.nucleotides.hasOwnProperty(atom.serial))) {
139667
+ nameArray.push(chainid);
139668
+ structureHash[atom.structure] = 1;
139669
+ }
139670
+ }
139671
+ }
139718
139672
 
139719
139673
  return nameArray;
139720
139674
  }
@@ -149828,24 +149782,31 @@ class Transform {
149828
149782
  }
149829
149783
  else { // |||pos:a,b,c|dir:a,b,c|up:a,b,c|fov:a
149830
149784
  let bcfArray = commandTransformation[1].split('|');
149785
+ // let dirVec;
149831
149786
  bcfArray.forEach(item => {
149832
149787
  let itemArray = item.split(':');
149833
149788
  if(itemArray[0] == 'fov') {
149834
149789
  ic.cam.fov = parseFloat(itemArray[1]);
149835
149790
  }
149836
149791
  else {
149837
- let abc = itemArray[1].split(',');
149792
+ let abc = itemArray[1].split(',').map(parseFloat);
149838
149793
  if(itemArray[0] == 'pos') {
149839
- ic.cam.position.set(parseFloat(abc[0]), parseFloat(abc[1]), parseFloat(abc[2]));
149794
+ ic.cam.position.set(abc[0], abc[1], abc[2]);
149840
149795
  }
149841
149796
  else if(itemArray[0] == 'dir') {
149842
- ic.cam.quaternion.setFromUnitVectors(new Vector3$1(0, 0, -1), new Vector3$1(parseFloat(abc[0]), parseFloat(abc[1]), parseFloat(abc[2])));
149797
+ ic.cam.quaternion.setFromUnitVectors(new Vector3$1(0, 0, -1), new Vector3$1(abc[0], abc[1], abc[2]));
149798
+ // dirVec = new THREE.Vector3(abc[0], abc[1], abc[2]);
149843
149799
  }
149844
149800
  else if(itemArray[0] == 'up') {
149845
- ic.cam.up.set(parseFloat(abc[0]), parseFloat(abc[1]), parseFloat(abc[2]));
149801
+ ic.cam.up.set(abc[0], abc[1], abc[2]);
149846
149802
  }
149847
149803
  }
149848
149804
  });
149805
+ // apply after pos and up are known, so the roll follows "up"
149806
+ // if(dirVec) {
149807
+ // ic.cam.lookAt(ic.cam.position.clone().add(dirVec));
149808
+ // ic.cam.updateMatrixWorld(true);
149809
+ // }
149849
149810
 
149850
149811
  // set the aspect ratio
149851
149812
  if(!ic.container.whratio) {
@@ -150186,17 +150147,30 @@ class SaveFile {
150186
150147
  let height = $("#" + ic.pre + "canvas").height();
150187
150148
  ic.applyCenterCls.setWidthHeight(width, height);
150188
150149
 
150150
+ let bPathTracer = (ic.scaleFactor == 1) ? false : true;
150151
+ /*
150189
150152
  // disable path tracing for large structures
150190
- let bPathTracer = (Object.keys(ic.atoms).length > ic.maxatomcnt) ? false : true;
150153
+ let bPathTracer = (Object.keys(ic.atoms).length > ic.maxatomcnt || ic.scaleFactor == 1) ? false : true;
150191
150154
 
150192
150155
  if(ic.biomtMatrices !== undefined && ic.biomtMatrices.length > 1 && ic.bAssembly
150193
150156
  && Object.keys(ic.atoms).length * ic.biomtMatrices.length > ic.maxatomcnt) {
150194
150157
  bPathTracer = false; // disable path tracing for large assemblies
150195
150158
  }
150159
+ */
150196
150160
 
150197
- //if(ic.bRender) ic.drawCls.render(undefined, bPathTracer);
150198
- if(ic.bRender) ic.drawCls.draw(undefined, bPathTracer);
150161
+ if(bPathTracer) {
150162
+ if(ic.bRender) ic.drawCls.draw(undefined, bPathTracer);
150199
150163
 
150164
+ /*
150165
+ let commandTransformation = ic.commands[ic.commands.length-1].split('|||');
150166
+ ic.transformCls.resetOrientation_base(commandTransformation);
150167
+ if(ic.bRender) ic.drawCls.render(undefined, bPathTracer);
150168
+ */
150169
+ }
150170
+ else {
150171
+ if(ic.bRender) ic.drawCls.render(undefined, bPathTracer);
150172
+ }
150173
+
150200
150174
  // reset impostor and instancing
150201
150175
  ic.bImpo = true; // enable impostor
150202
150176
  ic.bInstanced = true; // enable instancing
@@ -153881,8 +153855,6 @@ class iCn3D {
153881
153855
 
153882
153856
  this.bInitial = true; // first 3d display
153883
153857
 
153884
- this.bDoublecolor = false;
153885
-
153886
153858
  this.originSize = 1; // radius
153887
153859
 
153888
153860
  this.ALTERNATE_STRUCTURE = -1;
@@ -153959,7 +153931,7 @@ class iCn3D {
153959
153931
  //This is the line radius for stabilizers, hydrogen bonds, and distance lines. It's 0.1 by default.
153960
153932
  this.lineRadius = 0.1; // hbonds, distance lines
153961
153933
  //This is the coil radius for coils. It's 0.3 by default.
153962
- this.coilWidth = 0.3; //0.4; // style cartoon-coil
153934
+ this.coilWidth = 0.12; //0.3; // style cartoon-coil
153963
153935
  //This is the stick radius. It's 0.4 by default.
153964
153936
  this.cylinderRadius = 0.4; // style stick
153965
153937
  //This is the cross-linkage radius. It's 0.4 by default.
@@ -153974,7 +153946,7 @@ class iCn3D {
153974
153946
  this.cylinderHelixRadius = 1.6; // style cylinder and plate
153975
153947
 
153976
153948
  //This is the ribbon thickness for helix and sheet ribbons, and nucleotide ribbons. It's 0.4 by default.
153977
- this.ribbonthickness = 0.2; // 0.4; // style ribbon, nucleotide cartoon, stand thickness
153949
+ this.ribbonthickness = 0.35; // 0.2; // style ribbon, nucleotide cartoon, stand thickness
153978
153950
  //This is the width of protein ribbons. It's 1.3 by default.
153979
153951
  this.helixSheetWidth = 1.3; // style ribbon, nucleotide cartoon, stand thickness
153980
153952
  //This is the width of nucleotide ribbons. It's 0.8 by default.
@@ -154592,7 +154564,7 @@ class iCn3DUI {
154592
154564
  //even when multiple iCn3D viewers are shown together.
154593
154565
  this.pre = this.cfg.divid + "_";
154594
154566
 
154595
- this.REVISION = '3.53.0';
154567
+ this.REVISION = '3.54.0';
154596
154568
 
154597
154569
  // In nodejs, iCn3D defines "window = {navigator: {}}", and added window = {navigator: {}, "__THREE__":"177"}
154598
154570
  this.bNode = (Object.keys(window).length < 3) ? true : false;