icn3d 3.53.0 → 3.54.0

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] = [];
79195
-
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];
79129
+ for(let i = 0, il = linePos.length; i < il; ++i) pnts[i] = [];
79200
79130
 
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,53 @@ 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
+ let v = new Vector3$1(pntsCA[i].x + prevCOArray[i].x * delta,
79183
+ pntsCA[i].y + prevCOArray[i].y * delta,
79184
+ pntsCA[i].z + prevCOArray[i].z * delta);
79185
+ //v.smoothen = true;
79186
+ pnts[index].push(v);
79187
+ colorsTmp.push(colors[i]);
79188
+ if(index === 0) posIndex.push(pos);
79289
79189
  }
79290
-
79190
+
79291
79191
  // last residue
79292
79192
  // 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
- }
79193
+ let lastCAIndex = pntsCA.length - 1;
79194
+ let delta = -1 + numM1Inv2 * linePos[index];
79195
+ let scale = 1.8; // scale of the arrow width
79196
+ delta = delta * scale / ic.axisDIV;
79307
79197
 
79308
- pntsCASmooth = [];
79198
+ let v = new Vector3$1(pntsCA[lastCAIndex].x + prevCOArray[lastCAIndex].x * delta,
79199
+ pntsCA[lastCAIndex].y + prevCOArray[lastCAIndex].y * delta,
79200
+ pntsCA[lastCAIndex].z + prevCOArray[lastCAIndex].z * delta);
79309
79201
 
79310
- //colorsTmp.push(colors[colors.length - 2]);
79311
- //colorsTmp.push(colors[colors.length - 1]);
79202
+ pnts[index].push(v);
79203
+ colorsTmp.push(colors[i]);
79204
+ if(index === 0) posIndex.push(positions[lastCAIndex]);
79205
+ }
79312
79206
 
79313
79207
  if(bStrip) {
79314
79208
  ic.stripCls.createStrip(pnts[0], pnts[1], colorsTmp, div, thickness, bHighlight, true,
79315
- undefined, undefined, posIndex, prevone, nexttwo);
79209
+ undefined, undefined, posIndex);
79316
79210
  }
79317
79211
  else {
79318
79212
  ic.curveCls.createCurveSub(pnts[0], width, colorsTmp, div, bHighlight, bRibbon, true,
79319
- undefined, undefined, posIndex, prevone, nexttwo);
79213
+ undefined, undefined, posIndex);
79320
79214
  }
79321
79215
  }
79322
79216
 
79217
+ //pntsCA = [];
79218
+
79323
79219
  for(let i in pnts) {
79324
79220
  for(let j = 0, jl = pnts[i].length; j < jl; ++j) {
79325
79221
  pnts[i][j] = null;
@@ -79328,7 +79224,7 @@ class CurveStripArrow {
79328
79224
  }
79329
79225
 
79330
79226
  pnts = {};
79331
- }
79227
+ }
79332
79228
  }
79333
79229
 
79334
79230
  /**
@@ -79341,15 +79237,14 @@ class Curve {
79341
79237
  }
79342
79238
 
79343
79239
  // 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;
79240
+ createCurveSub(_pnts, width, colors, div, bHighlight, bRibbon, bNoSmoothen, positions) { let ic = this.icn3d, me = ic.icn3dui;
79345
79241
  if(me.bNode) return;
79346
79242
 
79347
79243
  if (_pnts.length === 0) return;
79348
79244
  div = div || 5;
79349
79245
  let pnts;
79350
- if(!bNoSmoothen) {
79351
- let bExtendLastRes = true;
79352
- let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
79246
+ if(div != 1 && !bNoSmoothen) {
79247
+ let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, div);
79353
79248
  pnts = pnts_clrs[0];
79354
79249
  colors = pnts_clrs[2];
79355
79250
  }
@@ -79358,8 +79253,6 @@ class Curve {
79358
79253
  }
79359
79254
  if (pnts.length === 0) return;
79360
79255
 
79361
- ic.stripCls.setCalphaDrawnCoord(pnts, div, calphaIdArray);
79362
-
79363
79256
  if(bHighlight === 1) {
79364
79257
  let radius = ic.coilWidth / 2;
79365
79258
  //var radiusSegments = 8;
@@ -79486,7 +79379,7 @@ class Curve {
79486
79379
  }
79487
79380
 
79488
79381
  pnts = null;
79489
- }
79382
+ }
79490
79383
  }
79491
79384
 
79492
79385
  /**
@@ -79656,12 +79549,12 @@ class Cylinder {
79656
79549
 
79657
79550
  let start = null;
79658
79551
  let currentChain, currentResi;
79659
- let others = {}, beta = {};
79552
+ let others = [], beta = {};
79660
79553
  let i;
79661
79554
  for (i in atoms) {
79662
79555
  let atom = atoms[i];
79663
79556
  if (atom.het) continue;
79664
- if ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) others[atom.serial] = atom;
79557
+ if ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) others.push(atom);
79665
79558
  if (atom.ss === 'sheet') beta[atom.serial] = atom;
79666
79559
  if (atom.name !== 'CA') continue;
79667
79560
  if (atom.ss === 'helix' && atom.ssend) {
@@ -80637,45 +80530,22 @@ class Strip {
80637
80530
  }
80638
80531
 
80639
80532
  // 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;
80533
+ createStrip(p0, p1, colors, div, thickness, bHighlight, bNoSmoothen,
80534
+ positions, pntsCA, prevCOArray) { let ic = this.icn3d, me = ic.icn3dui;
80642
80535
  if(me.bNode) return;
80643
80536
 
80644
80537
  if (p0.length < 2) return;
80645
80538
  div = div || ic.axisDIV;
80646
80539
 
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
-
80540
+ if(div != 1) { // not subdivided yet
80667
80541
  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);
80542
+ let pnts_clrs0 = me.subdivideCls.subdivide(p0, colors, div);
80543
+ let pnts_clrs1 = me.subdivideCls.subdivide(p1, colors, div);
80672
80544
  p0 = pnts_clrs0[0];
80673
80545
  p1 = pnts_clrs1[0];
80674
80546
  colors = pnts_clrs0[2];
80675
80547
  }
80676
80548
  if (p0.length < 2) return;
80677
-
80678
- this.setCalphaDrawnCoord(p0, div, calphaIdArray);
80679
80549
  }
80680
80550
 
80681
80551
  if(bHighlight === 1) {
@@ -80702,7 +80572,7 @@ class Strip {
80702
80572
  radiusSegments,
80703
80573
  closed
80704
80574
  );
80705
-
80575
+
80706
80576
  let mesh = new Mesh$1(geometry0, ic.matShader);
80707
80577
  mesh.renderOrder = ic.renderOrderPicking;
80708
80578
  //ic.mdlPicking.add(mesh);
@@ -80797,33 +80667,29 @@ class Strip {
80797
80667
 
80798
80668
  if(!p0v || !p1v) continue;
80799
80669
 
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
80670
+ // compute the thickness direction first
80671
+ if (i < lim - 1 && p0[i + 1]) {
80672
+ axis = p1[i].clone().sub(p0[i]).cross(p0[i + 1].clone().sub(p0[i])).normalize().multiplyScalar(thickness);
80673
+ }
80674
+ let half = axis.clone().multiplyScalar(0.5);
80804
80675
 
80676
+ // bottom face: half a thickness below the edge plane
80677
+ let b0v = p0v.clone().sub(half);
80678
+ let b1v = p1v.clone().sub(half);
80805
80679
  for(let j = 0; j < 2; ++j) {
80806
- vs[offset++] = p0v.x;
80807
- vs[offset++] = p0v.y;
80808
- vs[offset++] = p0v.z;
80680
+ vs[offset++] = b0v.x;
80681
+ vs[offset++] = b0v.y;
80682
+ vs[offset++] = b0v.z;
80809
80683
  }
80810
80684
  for(let j = 0; j < 2; ++j) {
80811
- vs[offset++] = p1v.x;
80812
- vs[offset++] = p1v.y;
80813
- vs[offset++] = p1v.z;
80814
- }
80815
-
80816
- if (i < lim - 1) {
80817
- axis = p1[i].clone().sub(p0[i]).cross(p0[i + 1].clone().sub(p0[i])).normalize().multiplyScalar(thickness);
80685
+ vs[offset++] = b1v.x;
80686
+ vs[offset++] = b1v.y;
80687
+ vs[offset++] = b1v.z;
80818
80688
  }
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
80689
 
80690
+ // top face: half a thickness above the edge plane
80691
+ a0v = p0v.clone().add(half);
80692
+ a1v = p1v.clone().add(half);
80827
80693
  for(let j = 0; j < 2; ++j) {
80828
80694
  vs[offset++] = a0v.x;
80829
80695
  vs[offset++] = a0v.y;
@@ -80942,22 +80808,6 @@ class Strip {
80942
80808
  p0 = null;
80943
80809
  p1 = null;
80944
80810
  }
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
80811
  }
80962
80812
 
80963
80813
  /**
@@ -80973,129 +80823,89 @@ class Tube {
80973
80823
  //Create tubes for "atoms" with certain "atomName". "radius" is the radius of the tubes.
80974
80824
  //"bHighlight" is an option to draw the highlight for these atoms. The highlight could be
80975
80825
  //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;
80826
+ createTube(atoms, atomName, radius, bHighlight, bCustom, bNonCoil, tubePosArray, pntsCAAllSub, colorsAllSub) { let ic = this.icn3d, me = ic.icn3dui;
80977
80827
  if(me.bNode) return;
80978
80828
 
80979
- let pnts = [], colors = [], radii = [], prevone = [], nexttwo = [];
80829
+ let pnts = [], colors = [], radii = [];
80980
80830
  let currentChain, currentResi;
80981
80831
  let index = 0;
80982
80832
  let maxDist = 6.0;
80983
80833
  let maxDist2 = 3.0; // avoid tube between the residues in 3 residue helix
80984
80834
 
80985
- let pnts_colors_radii_prevone_nexttwo = [];
80986
- let firstAtom, atom, prevAtom;
80835
+ let pnts_colors_radii = [];
80836
+ let firstAtom, firstPos, prevAtom, prevPos;
80837
+ let half = Math.floor(ic.axisDIV / 2) - 1;
80987
80838
 
80988
- for (let i in atoms) {
80989
- atom = atoms[i];
80839
+ for (let i = 0, il = atoms.length; i < il; ++i) {
80840
+ let pos = (tubePosArray) ? tubePosArray[i] : undefined;
80841
+
80842
+ let atom = atoms[i];
80990
80843
  if ((atom.name === atomName) && !atom.het) {
80991
80844
  if(index == 0) {
80992
80845
  firstAtom = atom;
80846
+ firstPos = pos;
80993
80847
  }
80994
80848
 
80995
80849
  atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) - 1).toString();
80996
80850
 
80997
80851
  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
80852
  || (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
80853
  || (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
80854
  ) ) {
81002
80855
  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));
81024
- }
81025
- colors.push(nextAtom.color);
81026
- }
80856
+ if(tubePosArray) {
80857
+ let bMissingEnd = ic.missingResEnd[prevAtom.structure + '_' + prevAtom.chain + '_' + prevAtom.resi];
80858
+ // remove half of the points when missign residues
80859
+ if(bMissingEnd) {
80860
+ pnts.splice(-half);
80861
+ colors.splice(-half);
80862
+ radii.splice(-half);
81027
80863
  }
81028
80864
 
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);
81032
-
81033
- if(nextAtom) {
81034
- pnts.push(nextAtom.coord);
81035
- colors.push(nextAtom.color);
80865
+ let result = this.closeSegment(firstAtom, firstPos, prevAtom, prevPos, pnts, colors, radii, pntsCAAllSub);
81036
80866
 
81037
- let radiusFinal = this.getRadius(radius, atom);
81038
- radii.push(radiusFinal);
81039
-
81040
- nextoneResid = nexttwoResid;
81041
- nexttwoResid = nextthreeResid;
81042
- }
81043
- }
81044
-
81045
- let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
81046
- if(nextoneCoord !== undefined) {
81047
- nexttwo.push(nextoneCoord);
81048
- }
81049
-
81050
- let nexttwoCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nexttwoResid, atomName);
81051
- if(nexttwoCoord !== undefined) {
81052
- nexttwo.push(nexttwoCoord);
81053
- }
80867
+ pnts_colors_radii.push(result);
80868
+ }
80869
+ else {
80870
+ pnts_colors_radii.push({'pnts':pnts, 'colors':colors, 'radii':radii});
81054
80871
  }
81055
-
81056
- pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
81057
80872
  }
81058
- pnts = []; colors = []; radii = []; prevone = []; nexttwo = [];
81059
- firstAtom = atom;
80873
+ pnts = []; colors = []; radii = []; firstAtom = atom;
80874
+ firstPos = pos;
81060
80875
  index = 0;
81061
80876
  }
81062
80877
 
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));
81074
- }
81075
- colors.push(prevAtom.color);
81076
- }
81077
- }
81078
- }
80878
+ if(tubePosArray) { // coil
80879
+ let bMissingStart = ic.missingResStart[atom.structure + '_' + atom.chain + '_' + atom.resi];
80880
+ let bMissingEnd = ic.missingResEnd[atom.structure + '_' + atom.chain + '_' + atom.resi];
81079
80881
 
81080
- pnts.push(atom.coord);
80882
+ let offsetStart = (bMissingStart) ? half : 0;
80883
+ let offsetEnd = (bMissingEnd) ? half : 0;
81081
80884
 
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);
80885
+ let indexArray = ic.strandCls.pos2IndexArray(pos, pntsCAAllSub);
80886
+ for(let j = offsetEnd, jl = indexArray.length - offsetStart; j < jl; ++j) {
80887
+ pnts.push(pntsCAAllSub[indexArray[j]]);
80888
+ colors.push(colorsAllSub[indexArray[j]]);
80889
+ radii.push(ic.coilWidth);
80890
+ }
81088
80891
  }
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;
80892
+ else { // b factor, etc
80893
+ pnts.push(atom.coord);
81092
80894
 
81093
- //radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
81094
- radii.push(radiusFinal);
80895
+ let radiusFinal;
80896
+ if(bCustom) {
80897
+ radiusFinal = this.getCustomtubesize(atom.structure + '_' + atom.chain + '_' + atom.resi);
80898
+ }
80899
+ else {
80900
+ radiusFinal = this.getRadius(radius, atom);
80901
+ }
80902
+
80903
+ radii.push(radiusFinal);
81095
80904
 
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;
80905
+ colors.push(atom.color);
80906
+ // the starting residue of a coil uses the color from the next residue to avoid using the color of the last helix/sheet residue
80907
+ if(index === 1) colors[colors.length - 2] = atom.color;
80908
+ }
81099
80909
 
81100
80910
  currentChain = atom.chain;
81101
80911
  currentResi = atom.resi;
@@ -81108,170 +80918,82 @@ class Tube {
81108
80918
  ++index;
81109
80919
 
81110
80920
  prevAtom = atom;
80921
+ prevPos = pos;
81111
80922
  }
81112
80923
  }
81113
80924
 
81114
80925
  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;
80926
+ if(tubePosArray) {
80927
+ if(prevAtom) {
80928
+ let bMissingEnd = ic.missingResEnd[prevAtom.structure + '_' + prevAtom.chain + '_' + prevAtom.resi];
80929
+ if(bMissingEnd) {
80930
+ pnts.splice(-half);
80931
+ colors.splice(-half);
80932
+ radii.splice(-half);
81141
80933
  }
81142
- }
81143
80934
 
81144
- let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
81145
- if(nextoneCoord !== undefined) {
81146
- nexttwo.push(nextoneCoord);
81147
- }
80935
+ let result = this.closeSegment(firstAtom, firstPos, prevAtom, prevPos, pnts, colors, radii, pntsCAAllSub);
81148
80936
 
81149
- let nexttwoCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nexttwoResid, atomName);
81150
- if(nexttwoCoord !== undefined) {
81151
- nexttwo.push(nexttwoCoord);
80937
+ pnts_colors_radii.push(result);
81152
80938
  }
81153
80939
  }
81154
-
81155
- pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
80940
+ else {
80941
+ pnts_colors_radii.push({'pnts':pnts, 'colors':colors, 'radii':radii});
80942
+ }
81156
80943
  }
81157
80944
 
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;
80945
+ for(let i = 0, il = pnts_colors_radii.length; i < il; ++i) {
80946
+ let pnts = pnts_colors_radii[i].pnts;
80947
+ let colors = pnts_colors_radii[i].colors;
80948
+ let radii = pnts_colors_radii[i].radii;
81164
80949
 
81165
- this.createTubeSub(pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil);
80950
+ this.createTubeSub(pnts, colors, radii, bHighlight, bNonCoil);
81166
80951
  }
81167
80952
 
81168
- pnts_colors_radii_prevone_nexttwo = [];
80953
+ pnts_colors_radii = [];
81169
80954
  }
81170
80955
 
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;
81189
- }
81190
-
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] : [];
81199
-
81200
- let nextoneResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 1).toString();
81201
-
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);
81205
-
81206
- if(nextAtom) {
81207
- pnts.push(nextAtom.coord);
81208
- colors.push(nextAtom.color);
81209
-
81210
- let radiusFinal = this.getRadius(radius, atom);
81211
- radii.push(radiusFinal);
81212
- }
81213
- }
81214
-
81215
- }
81216
-
81217
- pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
81218
- }
81219
- pnts = []; colors = []; radii = []; prevone = []; nexttwo = [];
81220
- firstAtom = atom;
81221
- index = 0;
81222
- }
81223
-
81224
- pnts.push(atom.coord);
81225
-
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);
81232
- }
80956
+ closeSegment(firstAtom, firstPos, prevAtom, prevPos, pnts, colors, radii, pntsCAAllSub) { let ic = this.icn3d; ic.icn3dui;
80957
+ if (pnts.length === 0) return {'pnts': [], 'colors': [], 'radii': []};
81233
80958
 
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;
80959
+ let extra = 1; // extend the tube by 5 sub-points into a preceding/following helix/sheet
81236
80960
 
81237
- //radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
81238
- radii.push(radiusFinal);
80961
+ // extend backward by one sub-point into a preceding helix/sheet
80962
+ if (!isNaN(firstAtom.resi)) {
80963
+ if(firstAtom.style == 'strand') extra = 0;
81239
80964
 
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;
80965
+ let resid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1);
80966
+ let before = ic.residues.hasOwnProperty(resid) ? ic.firstAtomObjCls.getAtomFromResi(resid, 'CA') : undefined;
81243
80967
 
81244
- currentChain = atom.chain;
81245
- currentResi = atom.resi;
81246
-
81247
- let scale = 1.2;
81248
- if(bHighlight === 2 && !atom.ssbegin) {
81249
- ic.boxCls.createBox(atom, undefined, undefined, scale, undefined, bHighlight);
80968
+ for(let i = 1, il = extra + 1; i < il; ++i) {
80969
+ let idx = ic.strandCls.pos2IndexArray(firstPos, pntsCAAllSub)[0] - i;
80970
+ if (before && (before.ssbegin || before.ssend) && idx >= 0) {
80971
+ pnts.unshift(pntsCAAllSub[idx]);
80972
+ colors.unshift(colors[0]); // keep the coil color
80973
+ radii.unshift(radii[0]);
81250
80974
  }
81251
-
81252
- ++index;
81253
-
81254
- prevAtom = atom;
81255
80975
  }
81256
80976
  }
81257
80977
 
81258
- if(bHighlight !== 2) {
81259
- pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
81260
- }
81261
-
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;
80978
+ // extend forward by one sub-point into a following helix/sheet
80979
+ if (!isNaN(prevAtom.resi)) {
80980
+ if(prevAtom.style == 'strand') extra = 0;
81268
80981
 
81269
- this.createTubeSub(pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil);
80982
+ let resid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 1);
80983
+ let after = ic.residues.hasOwnProperty(resid) ? ic.firstAtomObjCls.getAtomFromResi(resid, 'CA') : undefined;
80984
+ let arr = ic.strandCls.pos2IndexArray(prevPos, pntsCAAllSub);
80985
+ for(let i = 1, il = extra + 1; i < il; ++i) {
80986
+ let idx = arr[arr.length - 1] + i;
80987
+ if (after && (after.ssbegin || after.ssend) && idx < pntsCAAllSub.length) {
80988
+ pnts.push(pntsCAAllSub[idx]);
80989
+ colors.push(colors[colors.length - 1]);
80990
+ radii.push(radii[radii.length - 1]);
80991
+ }
80992
+ }
81270
80993
  }
81271
80994
 
81272
- pnts_colors_radii_prevone_nexttwo = [];
80995
+ return {'pnts': pnts, 'colors': colors, 'radii': radii};
81273
80996
  }
81274
- */
81275
80997
 
81276
80998
  getCustomtubesize(resid) { let ic = this.icn3d; ic.icn3dui;
81277
80999
  let pos = resid.lastIndexOf('_');
@@ -81284,11 +81006,11 @@ class Tube {
81284
81006
  };
81285
81007
 
81286
81008
  // 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;
81009
+ createTubeSub(_pnts, colors, radii, bHighlight, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
81288
81010
  if(me.bNode) return;
81289
81011
 
81290
81012
  if (_pnts.length < 2) return;
81291
-
81013
+
81292
81014
  let circleDiv = ic.tubeDIV, axisDiv = ic.axisDIV;
81293
81015
  let circleDivInv = 1 / circleDiv, axisDivInv = 1 / axisDiv;
81294
81016
  //var geo = new THREE.Geometry();
@@ -81296,10 +81018,19 @@ class Tube {
81296
81018
  let verticeArray = [], colorArray = [],indexArray = [], color;
81297
81019
  let offset = 0, offset2 = 0, offset3 = 0;
81298
81020
 
81299
- let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv, undefined, undefined, prevone, nexttwo);
81021
+ let pnts;
81022
+ /*
81023
+ if(!bSubdivided) {
81024
+ let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv);
81300
81025
 
81301
- let pnts = pnts_clrs[0];
81302
- colors = pnts_clrs[2];
81026
+ pnts = pnts_clrs[0];
81027
+ colors = pnts_clrs[2];
81028
+ }
81029
+ else {
81030
+ pnts = _pnts;
81031
+ }
81032
+ */
81033
+ pnts = _pnts;
81303
81034
 
81304
81035
  let constRadiius;
81305
81036
  // a threshold to stop drawing the tube if it's less than this ratio of radius
@@ -81337,6 +81068,7 @@ class Tube {
81337
81068
  }
81338
81069
  }
81339
81070
  }
81071
+
81340
81072
  let delta, axis1, axis2;
81341
81073
  if (i < lim - 1) {
81342
81074
  delta = pnts[i].clone().sub(pnts[i + 1]);
@@ -81516,29 +81248,31 @@ class Strand {
81516
81248
  coilWidth = coilWidth || ic.coilWidth;
81517
81249
  doNotSmoothen = doNotSmoothen || false;
81518
81250
  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
81251
 
81530
81252
  // test the first 30 atoms to see whether only C-alpha is available
81531
81253
  ic.bCalphaOnly = me.utilsCls.isCalphaPhosOnly(atomsAdjust); //, 'CA');
81532
81254
 
81533
- // when highlight, draw whole beta sheet and use bShowArray to show the highlight part
81534
- let residueHash = {};
81255
+ // get chains
81256
+ let chainidHash = {};
81535
81257
  for(let i in atomsAdjust) {
81536
- let atom = atomsAdjust[i];
81537
-
81538
- let residueid = atom.structure + '_' + atom.chain + '_' + atom.resi;
81539
- residueHash[residueid] = 1;
81258
+ let atom = ic.atoms[i];
81259
+ let chainid = atom.structure + '_' + atom.chain;
81260
+ chainidHash[chainid] = 1;
81540
81261
  }
81541
- let totalResidueCount = Object.keys(residueHash).length;
81262
+
81263
+ for(let chainid in chainidHash) {
81264
+ let pntsAll = {}; for (let k = 0; k < num; ++k) pntsAll[k] = [];
81265
+ let pntsAllSub = {}; for (let k = 0; k < num; ++k) pntsAllSub[k] = [];
81266
+ let pntsCAAll = [], posArray = [], tubePosArray = [], missingResArray = [];
81267
+ let prevCOArrayAll = [];
81268
+ let colorsAll = [];
81269
+
81270
+ let pntsCAAllSub = [], prevCOArrayAllSub = [], positionsSub = [], colorsAllSub = [];
81271
+
81272
+ let currentChain, currentStyle, currentCA = null, currentColor = null, prevCoorCA = null, prevCoorO = null, prevColor = null;
81273
+ let prevCO = null, ss = null, ssend = false, ssJoint = false, prevResi = null, prevResid = null;
81274
+ let strandWidth, bSheetSegment = false, bHelixSegment = false;
81275
+ let atom, tubeAtoms = [];
81542
81276
 
81543
81277
  let drawnResidueCount = 0;
81544
81278
 
@@ -81546,64 +81280,56 @@ class Strand {
81546
81280
 
81547
81281
  let caArray = []; // record all C-alpha atoms to predict the helix
81548
81282
 
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"
81283
+ let chainAtoms = me.hashUtilsCls.intHash(ic.chains[chainid], atomsAdjust);
81553
81284
 
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
- }
81285
+ let residueArray = ic.resid2specCls.atoms2residues(Object.keys(chainAtoms));
81286
+ let totalResidueCount = residueArray.length;
81287
+
81288
+ let index = 0;
81289
+
81290
+ // get pntsAll, pntsCAAll, prevCOArrayAll, colorsAll
81291
+ // get the subdivided points for all atoms
81292
+ let resi2pos = {};
81293
+ for (let i in ic.chains[chainid]) {
81294
+ atom = ic.atoms[i];
81558
81295
 
81296
+ if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
81297
+ if (atom.name === 'CA') {
81559
81298
  currentCA = atom.coord;
81560
81299
  currentColor = atom.color;
81561
- calphaid = atom.serial;
81562
-
81563
81300
  caArray.push(atom.serial);
81564
81301
  }
81565
81302
 
81566
81303
  if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA')) {
81304
+ ++index;
81305
+
81567
81306
  if(currentCA === null || currentCA === undefined) {
81568
81307
  currentCA = atom.coord;
81569
81308
  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
81309
  }
81589
81310
 
81590
81311
  // assign the previous residue
81591
81312
  if(prevCoorO) {
81592
- if(bHighlight === 1 || bHighlight === 2) {
81593
- colors.push(ic.hColor);
81313
+ // posArray.push(index - 1 - 1);
81314
+ resi2pos[prevResi] = index - 1 - 1;
81315
+
81316
+ /*
81317
+ strandWidth = (ss === 'coil') ? coilWidth : helixSheetWidth;
81318
+
81319
+ if(ss == 'sheet' && atom.ss == 'sheet' && atom.ssend) { // a transition between two sheets
81320
+ strandWidth = 1.8 * helixSheetWidth;
81594
81321
  }
81595
- else {
81596
- colors.push(prevColor);
81322
+ else if(ss == 'sheet' && ssend && atom.ss == 'coil') { // a transition between two ss
81323
+ strandWidth = 0;
81597
81324
  }
81325
+ */
81326
+ strandWidth = helixSheetWidth;
81598
81327
 
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;
81328
+ if(bHighlight === 1 || bHighlight === 2) {
81329
+ colorsAll.push(ic.hColor);
81604
81330
  }
81605
81331
  else {
81606
- strandWidth = (ss === 'coil') ? coilWidth : helixSheetWidth;
81332
+ colorsAll.push(prevColor);
81607
81333
  }
81608
81334
 
81609
81335
  let O, oldCA, resSpan = 4;
@@ -81645,239 +81371,161 @@ class Strand {
81645
81371
  for (let j = 0, numM1Inv2 = 2 / (num - 1); j < num; ++j) {
81646
81372
  let delta = -1 + numM1Inv2 * j;
81647
81373
  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);
81374
+ // no smoothen for the last two residues in sheet
81375
+ if (!doNotSmoothen && ss === 'sheet' && !ssJoint && !(atom.ssend)) v.smoothen = true;
81376
+ pntsAll[j].push(v);
81650
81377
  }
81651
81378
 
81652
- pntsCA.push(prevCoorCA);
81653
- prevCOArray.push(prevCO);
81379
+ pntsCAAll.push(prevCoorCA);
81380
+ prevCOArrayAll.push(prevCO);
81381
+ }
81654
81382
 
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
- }
81383
+ // only update when atom.name === 'O'
81384
+ prevResi = atom.resi;
81663
81385
 
81664
- ++drawnResidueCount;
81665
- }
81386
+ prevCoorCA = currentCA;
81387
+ prevCoorO = atom.coord;
81388
+ prevColor = currentColor;
81666
81389
 
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);
81390
+ ss = atom.ss;
81391
+ ssend = atom.ssend;
81392
+ ssJoint = atom.ssbegin || atom.ssend;
81393
+ } // end if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA') ) {
81394
+ } // end if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
81395
+ } // end for
81671
81396
 
81672
- // if(bBrokenSs && atom.ss === 'sheet') {
81673
- // bSheetSegment = true;
81674
- // }
81675
- // else if(bBrokenSs && atom.ss === 'helix') {
81676
- // bHelixSegment = true;
81677
- // }
81397
+ // add the last residue
81398
+ // posArray.push(index - 1);
81399
+ resi2pos[prevResi] = index - 1;
81678
81400
 
81679
- if ((atom.ssbegin || atom.ssend || (drawnResidueCount === totalResidueCount - 1) || bBrokenSs || currentStyle != atom.style) && pnts[0].length > 0 && bSameChain) {
81680
- let atomName = 'CA';
81401
+ colorsAll.push(prevColor);
81402
+ for (let j = 0, numM1Inv2 = 2 / (num - 1); j < num; ++j) {
81403
+ let delta = -1 + numM1Inv2 * j;
81404
+ let v = new Vector3$1(prevCoorCA.x + prevCO.x * delta, prevCoorCA.y + prevCO.y * delta, prevCoorCA.z + prevCO.z * delta);
81405
+ // no smoothen for the last two residues in sheet
81406
+ if (!doNotSmoothen && ss === 'sheet' && !ssJoint && !(ssend)) v.smoothen = true;
81407
+ pntsAll[j].push(v);
81408
+ }
81409
+ pntsCAAll.push(prevCoorCA);
81410
+ prevCOArrayAll.push(prevCO);
81681
81411
 
81682
- let prevone = [], nexttwo = [];
81412
+ // each point except the last one are divided into div segments. The last point is not divided.
81413
+ let pnts_clrs;
81414
+ for(let i = 0; i < num; ++i) {
81415
+ pnts_clrs = me.subdivideCls.subdivide(pntsAll[i], colorsAll, div);
81416
+ pntsAllSub[i] = pnts_clrs[0];
81417
+ }
81683
81418
 
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
- }
81419
+ pnts_clrs = me.subdivideCls.subdivide(pntsCAAll, colorsAll, div);
81420
+ pntsCAAllSub = pnts_clrs[0];
81421
+ colorsAllSub = pnts_clrs[2];
81422
+
81423
+ pnts_clrs = me.subdivideCls.subdivide(prevCOArrayAll, colorsAll, div);
81424
+ prevCOArrayAllSub = pnts_clrs[0];
81425
+ positionsSub = pnts_clrs[1];
81692
81426
 
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
- }
81427
+ posArray = [];
81428
+ prevCoorO = null;
81429
+ prevCoorCA = null;
81430
+ ss = null;
81431
+ ssend = false;
81432
+ ssJoint = false;
81699
81433
 
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
- }
81434
+ index = 0;
81435
+ let bLastResDrawn = false;
81706
81436
 
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
- }
81437
+ // draw only for the selected atoms
81438
+ for (let i in chainAtoms) {
81439
+ atom = ic.atoms[i];
81440
+ if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
81441
+ // "CA" has to appear before "O"
81716
81442
 
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
- }
81443
+ if (atom.name === 'CA') {
81444
+ // if ( atoms.hasOwnProperty(i) && ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) ) {
81445
+ if ( atoms.hasOwnProperty(i) && ((atom.ss !== 'helix' && atom.ss !== 'sheet') ) ) {
81446
+ tubeAtoms.push(atom);
81447
+ let pos = resi2pos[atom.resi];
81448
+ tubePosArray.push(pos);
81729
81449
 
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
- }
81450
+ continue;
81451
+ }
81452
+ }
81746
81453
 
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;
81454
+ if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA')) {
81455
+ ++index;
81751
81456
 
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
- }
81457
+ currentCA = atom.coord;
81758
81458
 
81759
- atomid = atom.serial;
81459
+ // smoothen each coil, helix and sheet separately. The joint residue has to be included both in the previous and next segment
81460
+ // if((atom.ssend || currentStyle != atom.style)&& atom.ss === 'sheet') {
81461
+ // bSheetSegment = true;
81462
+ // }
81463
+ // else if((atom.ssend || currentStyle != atom.style) && atom.ss === 'helix') {
81464
+ // bHelixSegment = true;
81465
+ // }
81466
+ if(atom.ss === 'sheet') {
81467
+ bSheetSegment = true;
81468
+ bHelixSegment = false;
81469
+ }
81470
+ else if(atom.ss === 'helix') {
81471
+ bSheetSegment = false;
81472
+ bHelixSegment = true;
81473
+ }
81474
+ else {
81475
+ bSheetSegment = false;
81476
+ bHelixSegment = false;
81477
+ }
81760
81478
 
81761
- pntsCA.push(currentCA);
81762
- prevCOArray.push(prevCO);
81479
+ // assign the previous residue
81480
+ if(prevCoorO) {
81481
+ //pntsCA.push(prevCoorCA);
81482
+ //prevCOArray.push(prevCO);
81483
+ let pos = resi2pos[prevResi];
81484
+ // posArray.push(index - 1 - 1);
81485
+ posArray.push(pos);
81763
81486
 
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
- }
81487
+ let bMissingStart = ic.missingResStart[prevResid];
81488
+ let bMissingEnd = ic.missingResEnd[prevResid];
81489
+ let missingResType = bMissingStart ? 1 : (bMissingEnd ? 2 : 0);
81490
+ missingResArray.push(missingResType);
81775
81491
 
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] = [];
81492
+ ++drawnResidueCount;
81493
+ }
81811
81494
 
81812
- colors = [];
81813
- pntsCA = [];
81814
- prevCOArray = [];
81815
- bShowArray = [];
81816
- calphaIdArray = [];
81817
- bSheetSegment = false;
81818
- bHelixSegment = false;
81819
- } // end if (atom.ssbegin || atom.ssend)
81495
+ let maxDist = 6.0;
81496
+ 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
81497
 
81821
- // end of a chain
81822
- if ((currentChain !== atom.chain || currentStyle != atom.style) && pnts[0].length > 0) {
81823
- let atomName = 'CA';
81498
+ // check for the last atom
81499
+ if ((atom.ssbegin || atom.ssend || bBrokenSs || currentStyle != atom.style || currentChain !== atom.chain) ) {
81500
+ // && posArray.length > 0) {
81501
+ if(!bBrokenSs) { // include the current residue
81502
+ if(drawnResidueCount === totalResidueCount - 1) bLastResDrawn = true;
81824
81503
 
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
- }
81504
+ let pos = resi2pos[atom.resi];
81505
+ // posArray.push(index - 1);
81506
+ posArray.push(pos);
81833
81507
 
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
- }
81508
+ let bMissingStart = ic.missingResStart[atom.structure + '_' + atom.chain + '_' + atom.resi];
81509
+ let bMissingEnd = ic.missingResEnd[atom.structure + '_' + atom.chain + '_' + atom.resi];
81510
+ let missingResType = bMissingStart ? 1 : (bMissingEnd ? 2 : 0);
81511
+ missingResArray.push(missingResType);
81861
81512
  }
81862
81513
 
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
- }
81514
+ bSheetSegment = prevCoorO ? (ss === 'sheet') : (atom.ss === 'sheet');
81515
+ bHelixSegment = prevCoorO ? (ss === 'helix') : (atom.ss === 'helix');
81516
+ this.createStrand_base(posArray, pntsAllSub, pntsCAAllSub, prevCOArrayAllSub, colorsAllSub, positionsSub, missingResArray, fill, bHighlight, bRibbon, num, bSheetSegment, bHelixSegment, bFullAtom, thickness);
81517
+ posArray = [];
81518
+ missingResArray = [];
81519
+ } // end if (atom.ssbegin || atom.ssend)
81872
81520
 
81873
81521
  currentChain = atom.chain;
81874
81522
  currentStyle = atom.style;
81875
81523
  ss = atom.ss;
81876
81524
  ssend = atom.ssend;
81877
- prevAtomid = atom.serial;
81525
+ atom.serial;
81878
81526
  prevResi = atom.resi;
81879
81527
 
81880
- prevCalphaid = calphaid;
81528
+ prevResid = atom.structure + '_' + atom.chain + '_' + atom.resi;
81881
81529
 
81882
81530
  // only update when atom.name === 'O'
81883
81531
  prevCoorCA = currentCA;
@@ -81887,12 +81535,95 @@ class Strand {
81887
81535
  } // end if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
81888
81536
  } // end for
81889
81537
 
81538
+ // draw the last residue
81539
+ if(!bLastResDrawn && drawnResidueCount === totalResidueCount - 1) {
81540
+ let pos = resi2pos[prevResi];
81541
+ // posArray.push(index - 1);
81542
+ posArray.push(pos);
81543
+
81544
+ let bMissingStart = ic.missingResStart[prevResid];
81545
+ let bMissingEnd = ic.missingResEnd[prevResid];
81546
+ let missingResType = bMissingStart ? 1 : (bMissingEnd ? 2 : 0);
81547
+ missingResArray.push(missingResType);
81548
+
81549
+ bSheetSegment = prevCoorO ? (ss === 'sheet') : (atom.ss === 'sheet');
81550
+ bHelixSegment = prevCoorO ? (ss === 'helix') : (atom.ss === 'helix');
81551
+ this.createStrand_base(posArray, pntsAllSub, pntsCAAllSub, prevCOArrayAllSub, colorsAllSub, positionsSub, missingResArray, fill, bHighlight, bRibbon, num, bSheetSegment, bHelixSegment, bFullAtom, thickness);
81552
+ } // end if (atom.ssbegin || atom.ssend)
81553
+
81554
+ ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight, undefined, undefined, tubePosArray, pntsCAAllSub, colorsAllSub);
81555
+
81890
81556
  caArray = [];
81557
+ tubeAtoms = [];
81558
+ posArray = [];
81559
+ missingResArray = [];
81560
+ tubePosArray = [];
81561
+ pntsAll = {}, pntsCAAll = [], prevCOArrayAll = [], colorsAll = [];
81562
+ } // end for chainid in ic.chains
81563
+ }
81891
81564
 
81892
- ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight);
81565
+ createStrand_base(posArray, pntsAllSub, pntsCAAllSub, prevCOArrayAllSub, colorsAllSub, positionsSub, missingResArray, fill, bHighlight, bRibbon, num, bSheetSegment, bHelixSegment, bFullAtom, thickness) { let ic = this.icn3d; ic.icn3dui;
81566
+ let pntsCATmp = [], prevCOArrayTmp = [], colorsTmp = [], positionsTmp = [];
81567
+ let pntsTmp = {}; for (let k = 0; k < num; ++k) pntsTmp[k] = [];
81568
+ let half = Math.floor(ic.axisDIV / 2) - 1;
81893
81569
 
81894
- tubeAtoms = {};
81895
- pnts = {};
81570
+ for(let j = 0, jl = posArray.length; j < jl; ++j) {
81571
+ let pos = posArray[j];
81572
+ let missingResType = missingResArray[j];
81573
+
81574
+ let offsetStart = (missingResType == 1) ? half : 0;
81575
+ let offsetEnd = (missingResType == 2) ? half : 0;
81576
+
81577
+ let indexArray = this.pos2IndexArray(pos, pntsCAAllSub);
81578
+
81579
+ for(let k = offsetEnd, kl = indexArray.length - offsetStart; k < kl; ++k) {
81580
+ pntsCATmp.push(pntsCAAllSub[indexArray[k]]);
81581
+ prevCOArrayTmp.push(prevCOArrayAllSub[indexArray[k]]);
81582
+ colorsTmp.push(colorsAllSub[indexArray[k]]);
81583
+ positionsTmp.push(positionsSub[indexArray[k]]);
81584
+ }
81585
+
81586
+ for(let k = 0; k < num; ++k) {
81587
+ for(let l = 0, ll = indexArray.length; l < ll; ++l) {
81588
+ pntsTmp[k].push(pntsAllSub[k][indexArray[l]]);
81589
+ }
81590
+ }
81591
+ }
81592
+
81593
+ // draw the current segment
81594
+ for (let j = 0; !fill && j < num; ++j) {
81595
+ if(bSheetSegment) {
81596
+ ic.curveStripArrowCls.createCurveSubArrow(pntsTmp[j], 1, colorsTmp, 1, bHighlight, bRibbon, num, j, pntsCATmp, prevCOArrayTmp, positionsTmp, true);
81597
+ }
81598
+ else if(bHelixSegment) {
81599
+ if(bFullAtom) {
81600
+ ic.curveCls.createCurveSub(pntsTmp[j], 1, colorsTmp, 1, bHighlight, bRibbon, false, undefined);
81601
+ }
81602
+ else {
81603
+ ic.curveStripArrowCls.createCurveSubArrow(pntsTmp[j], 1, colorsTmp, 1, bHighlight, bRibbon, num, j, pntsCATmp, prevCOArrayTmp, positionsTmp, false);
81604
+ }
81605
+ }
81606
+ }
81607
+ if (fill) {
81608
+ if(bSheetSegment) {
81609
+ let start = 0, end = num - 1;
81610
+ ic.curveStripArrowCls.createStripArrow(pntsTmp[0], pntsTmp[num - 1], colorsTmp, 1, thickness, bHighlight, num, start, end, pntsCATmp, prevCOArrayTmp, positionsTmp, true);
81611
+ }
81612
+ else if(bHelixSegment) {
81613
+ if(bFullAtom) {
81614
+ ic.stripCls.createStrip(pntsTmp[0], pntsTmp[num - 1], colorsTmp, 1, thickness, bHighlight, false, undefined, pntsCATmp, prevCOArrayTmp);
81615
+ }
81616
+ else {
81617
+ let start = 0, end = num - 1;
81618
+ ic.curveStripArrowCls.createStripArrow(pntsTmp[0], pntsTmp[num - 1], colorsTmp, 1, thickness, bHighlight, num, start, end, pntsCATmp, prevCOArrayTmp, positionsTmp, false);
81619
+ }
81620
+ }
81621
+ else {
81622
+ if(bHighlight === 2) { // draw coils only when highlighted. if not highlighted, coils will be drawn as tubes separately
81623
+ ic.stripCls.createStrip(pntsTmp[0], pntsTmp[num - 1], colorsTmp, 1, thickness, bHighlight, false, undefined, pntsCATmp, prevCOArrayTmp);
81624
+ }
81625
+ }
81626
+ }
81896
81627
  }
81897
81628
 
81898
81629
  getSSExpandedAtoms(atoms, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
@@ -81917,7 +81648,7 @@ class Strand {
81917
81648
  else if(index === length - 1) {
81918
81649
  lastAtom = currAtom;
81919
81650
  }
81920
-
81651
+ /*
81921
81652
  // fill the beginning
81922
81653
  let beginResi = firstAtom.resi;
81923
81654
  if(!isNaN(firstAtom.resi) && firstAtom.ss !== 'coil' && !(firstAtom.ssbegin) ) {
@@ -81939,7 +81670,7 @@ class Strand {
81939
81670
  ic.atoms));
81940
81671
  }
81941
81672
  }
81942
-
81673
+ */
81943
81674
  // add one extra residue for coils between strands/helix if the style is NOT stick, ball and stick, lines, sphere, and dot
81944
81675
  // if(!isNaN(firstAtom.resi) && ic.pk === 3 && bHighlight === 1 && firstAtom.ss === 'coil') {
81945
81676
  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 +81681,7 @@ class Strand {
81950
81681
  atoms = me.hashUtilsCls.unionHash(atoms, me.hashUtilsCls.hash2Atoms(ic.residues[residueid], ic.atoms));
81951
81682
  }
81952
81683
  }
81953
-
81684
+ /*
81954
81685
  // fill the end
81955
81686
  let endResi = lastAtom.resi;
81956
81687
  // 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 +81707,7 @@ class Strand {
81976
81707
  ic.atoms));
81977
81708
  }
81978
81709
  }
81979
-
81710
+ */
81980
81711
  // add one extra residue for coils between strands/helix if the style is NOT stick, ball and stick, lines, sphere, and dot
81981
81712
  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
81713
  let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + (parseInt(lastAtom.resi) + 1).toString();
@@ -82002,6 +81733,32 @@ class Strand {
82002
81733
 
82003
81734
  return atomsAdjust;
82004
81735
  }
81736
+
81737
+ pos2IndexArray(pos, pntsCAAllSub) { let ic = this.icn3d; ic.icn3dui;
81738
+ let indexArray = [];
81739
+
81740
+ let offset = Math.floor(ic.axisDIV / 2) + 1; // first residue has floor(DIV/2)+1 points (8 when axisDIV = 15)
81741
+
81742
+ //subdivide() gives the first residue only floor(DIV/2)+1 points (8 when axisDIV = 15) and each later residue 15.
81743
+ if(pos == 0) {
81744
+ for(let j = 0; j < offset; ++j) {
81745
+ indexArray.push(j);
81746
+ }
81747
+ }
81748
+ else {
81749
+ for(let j = 0; j < ic.axisDIV; ++j) {
81750
+ let index = offset + (pos - 1) * ic.axisDIV + j;
81751
+ if(index >= pntsCAAllSub.length) {
81752
+ indexArray.push(pntsCAAllSub.length - 1);
81753
+ break;
81754
+ } else {
81755
+ indexArray.push(index);
81756
+ }
81757
+ }
81758
+ }
81759
+
81760
+ return indexArray;
81761
+ }
82005
81762
  }
82006
81763
 
82007
81764
  /**
@@ -86125,6 +85882,9 @@ class ApplyMissingRes {
86125
85882
  }
86126
85883
  }
86127
85884
 
85885
+ if(ic.missingResStart === undefined) ic.missingResStart = {};
85886
+ if(ic.missingResEnd === undefined) ic.missingResEnd = {};
85887
+
86128
85888
  for(let i = 0, il = misingResArray.length; i < il; i += 2) {
86129
85889
  let resid0 = misingResArray[i];
86130
85890
  let resid1 = misingResArray[i + 1];
@@ -86141,6 +85901,10 @@ class ApplyMissingRes {
86141
85901
  ic.missingResPnts[structure].push(resid0);
86142
85902
  ic.missingResPnts[structure].push(resid1);
86143
85903
 
85904
+ ic.missingResStart[resid0] = 1;
85905
+ ic.missingResEnd[resid1] = 1;
85906
+
85907
+
86144
85908
  ic.missingResResid2serial[resid0 + ',' + resid1] = atom0.serial;
86145
85909
  ic.missingResResid2serial[resid1 + ',' + resid0] = atom1.serial;
86146
85910
  }
@@ -86420,10 +86184,20 @@ class ApplyDisplay {
86420
86184
  ic.cylinderCls.createCylinderCurve(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), ['CA'], ic.traceRadius, false, bHighlight);
86421
86185
  }
86422
86186
  else if(style === 'b factor tube') {
86423
- ic.tubeCls.createTube(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), 'CA', null, bHighlight, false, true);
86187
+ let atomArray = [];
86188
+ for(let i in atomHash) {
86189
+ let atom = ic.atoms[i];
86190
+ atomArray.push(atom);
86191
+ }
86192
+ ic.tubeCls.createTube(atomArray, 'CA', null, bHighlight, false, true);
86424
86193
  }
86425
86194
  else if(style === 'custom tube') {
86426
- ic.tubeCls.createTube(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), 'CA', null, bHighlight, true, true);
86195
+ let atomArray = [];
86196
+ for(let i in atomHash) {
86197
+ let atom = ic.atoms[i];
86198
+ atomArray.push(atom);
86199
+ }
86200
+ ic.tubeCls.createTube(atomArray, 'CA', null, bHighlight, true, true);
86427
86201
  }
86428
86202
  else if(style === 'lines' || style === 'lines2') {
86429
86203
  if(bHighlight === 1) {
@@ -86734,7 +86508,7 @@ class ApplyOther {
86734
86508
  break;
86735
86509
  }
86736
86510
  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;
86511
+ pos = ic.atoms[i].coord;
86738
86512
  break;
86739
86513
  }
86740
86514
  }
@@ -106059,7 +105833,6 @@ class WebGLPathTracer {
106059
105833
  }
106060
105834
  else {
106061
105835
  if(bPathTracer) {
106062
- console.log("###pathTracer");
106063
105836
  ic.bImpo = false; // disable impostor for path tracing
106064
105837
  const pathTracer = new WebGLPathTracer(ic.renderer);
106065
105838
  pathTracer.setScene(ic.scene, cam);
@@ -132463,6 +132236,59 @@ class SetSeqAlign {
132463
132236
  ic.nconsHash2 = {};
132464
132237
  ic.nalignHash2 = {};
132465
132238
 
132239
+ let msaSameColor = [];
132240
+ // assume all aligned seq are the same. If any aligned res is different,set it to false (0)
132241
+ for(let i = 0, il = seqalign[0].length; i < il; ++i) {
132242
+ msaSameColor.push(1);
132243
+ }
132244
+
132245
+ for(let i = 0, il = seqalign.length; i < il; ++i) {
132246
+ // first sequence
132247
+ let alignData = seqalign[i][0];
132248
+ let molid1 = alignData.moleculeId;
132249
+
132250
+ let chain1 = ic.pdbid_molid2chain[mmdbid1 + '_' + molid1];
132251
+ chainid1 = mmdbid1 + '_' + chain1;
132252
+
132253
+ let id2aligninfo = {};
132254
+ let start = alignData.sequence.length, end = -1;
132255
+ let bStart = false;
132256
+ for(let j = 0, jl = alignData.sequence.length; j < jl; ++j) {
132257
+ // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
132258
+ let resi =(ic.bUsePdbNum) ? ic.ParserUtilsCls.getResi(chainid1, alignData.sequence[j][0] - 1) : alignData.sequence[j][0];
132259
+ let resn =(alignData.sequence[j][2] === '~') ? '-' : alignData.sequence[j][2];
132260
+ resn =(resn === ' ' || resn === '') ? 'X' : resn;
132261
+
132262
+ let aligned =(alignData.sequence[j][3]) ? 1 : 0;
132263
+
132264
+ if(aligned == 1) {
132265
+ if(j < start && !bStart) {
132266
+ start = j;
132267
+ bStart = true; // set start just once
132268
+ }
132269
+ if(j > end) end = j;
132270
+ }
132271
+
132272
+ id2aligninfo[j] = {"resi": resi, "resn": resn, "aligned": aligned};
132273
+ }
132274
+
132275
+ // second sequence
132276
+ alignData = seqalign[i][1];
132277
+
132278
+ for(let j = start; j <= end; ++j) {
132279
+ // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
132280
+ let alignedTmp =(alignData.sequence[j][3]) ? 1 : 0;
132281
+
132282
+ let aligned = id2aligninfo[j].aligned + alignedTmp; // 0 or 2
132283
+
132284
+ if(aligned === 2) { // aligned
132285
+ if(id2aligninfo[j].resn != resn) {
132286
+ msaSameColor[j] = 0;
132287
+ }
132288
+ }
132289
+ }
132290
+ }
132291
+
132466
132292
  for(let i = 0, il = seqalign.length; i < il; ++i) {
132467
132293
  // first sequence
132468
132294
  let alignData = seqalign[i][0];
@@ -132559,6 +132385,8 @@ class SetSeqAlign {
132559
132385
  ic.nconsHash2[chainid2 + '_' + resi] = 1;
132560
132386
  }
132561
132387
 
132388
+ color = (msaSameColor[j] == 0) ? '#0000FF' : '#FF0000';
132389
+
132562
132390
  // mapping, use the firstsequence as the reference structure
132563
132391
  ic.chainsMapping[chainid1][chainid1 + '_' + id2aligninfo[j].resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
132564
132392
  ic.chainsMapping[chainid2][chainid2 + '_' + resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
@@ -132575,6 +132403,8 @@ class SetSeqAlign {
132575
132403
 
132576
132404
  ic.nalignHash1[chainid1 + '_' + id2aligninfo[j].resi] = 1;
132577
132405
  ic.nalignHash2[chainid2 + '_' + resi] = 1;
132406
+
132407
+ msaSameColor[j] = 2; // not aligned
132578
132408
  }
132579
132409
 
132580
132410
  // chain1
@@ -133672,8 +133502,10 @@ class SetSeqAlign {
133672
133502
  ic.msaSeq[chainid2] += '-';
133673
133503
  }
133674
133504
  }
133675
-
133505
+ /*
133676
133506
  setSeqAlignForRealign(chainid_t, chainid, chainIndex) { let ic = this.icn3d, me = ic.icn3dui;
133507
+ //loadSeqAlignment
133508
+ let alignedAtoms = {};
133677
133509
  //var chainid_t = ic.chainidArray[0];
133678
133510
 
133679
133511
  // let structureArray = Object.keys(ic.structures);
@@ -133695,7 +133527,7 @@ class SetSeqAlign {
133695
133527
  ic.alnChains = {};
133696
133528
 
133697
133529
  ic.alnChainsSeq[chainid_t] = [];
133698
- ic.alnChains[chainid_t] = {};
133530
+ ic.alnChains[chainid_t] = {}
133699
133531
  ic.alnChainsAnno[chainid_t] = [];
133700
133532
  ic.alnChainsAnTtl[chainid_t] = [];
133701
133533
 
@@ -133773,8 +133605,8 @@ class SetSeqAlign {
133773
133605
  ic.alnChainsSeq[chainid1].push(resObject1);
133774
133606
  ic.alnChainsSeq[chainid2].push(resObject2);
133775
133607
 
133776
- if(ic.alnChains[chainid1] === undefined) ic.alnChains[chainid1] = {};
133777
- if(ic.alnChains[chainid2] === undefined) ic.alnChains[chainid2] = {};
133608
+ if(ic.alnChains[chainid1] === undefined) ic.alnChains[chainid1] = {}
133609
+ if(ic.alnChains[chainid2] === undefined) ic.alnChains[chainid2] = {}
133778
133610
  $.extend(ic.alnChains[chainid1], ic.residues[chainid1 + '_' + resObject1.resi] );
133779
133611
  $.extend(ic.alnChains[chainid2], ic.residues[chainid2 + '_' + resObject2.resi] );
133780
133612
 
@@ -133804,6 +133636,7 @@ class SetSeqAlign {
133804
133636
  let select = "select " + ic.resid2specCls.residueids2spec(Object.keys(residuesHash));
133805
133637
  ic.selectionCls.addCustomSelection(Object.keys(residuesHash), commandname, commanddescr, select, true);
133806
133638
  }
133639
+ */
133807
133640
 
133808
133641
  setSeqPerResi(chainid, chainid1, chainid2, resi, resn, bAligned, color, color2, classname, bFirstChain, bFirstResi, alignIndex) { let ic = this.icn3d, me = ic.icn3dui;
133809
133642
  if(ic.alnChainsSeq[chainid] === undefined) ic.alnChainsSeq[chainid] = [];
@@ -138121,16 +137954,6 @@ class ApplyCommand {
138121
137954
  let color = command.substr(command.lastIndexOf(' ') + 1);
138122
137955
  me.htmlCls.setMenuCls.setTheme(color);
138123
137956
  }
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
137957
  else if(command.indexOf('adjust dialog') == 0) {
138135
137958
  let id = command.substr(command.lastIndexOf(' ') + 1);
138136
137959
  ic.scapCls.adjust2DWidth(id);
@@ -138597,7 +138420,6 @@ class ApplyCommand {
138597
138420
  else if(cmd.indexOf('replay on') !== -1) return 'File > Replay Each Step > On';
138598
138421
  else if(cmd.indexOf('replay off') !== -1) return 'File > Replay Each Step > Off';
138599
138422
  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
138423
  else return '';
138602
138424
  }
138603
138425
  }
@@ -139715,6 +139537,17 @@ class LoadScript {
139715
139537
  nameArray = paraArray[1].split(',');
139716
139538
  ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(nameArray);
139717
139539
  }
139540
+ else {
139541
+ let structureHash = {};
139542
+
139543
+ for(let chainid in ic.chains) {
139544
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chainid]);
139545
+ if(!structureHash.hasOwnProperty(atom.structure) && (ic.proteins.hasOwnProperty(atom.serial) || ic.nucleotides.hasOwnProperty(atom.serial))) {
139546
+ nameArray.push(chainid);
139547
+ structureHash[atom.structure] = 1;
139548
+ }
139549
+ }
139550
+ }
139718
139551
 
139719
139552
  return nameArray;
139720
139553
  }
@@ -149828,24 +149661,31 @@ class Transform {
149828
149661
  }
149829
149662
  else { // |||pos:a,b,c|dir:a,b,c|up:a,b,c|fov:a
149830
149663
  let bcfArray = commandTransformation[1].split('|');
149664
+ // let dirVec;
149831
149665
  bcfArray.forEach(item => {
149832
149666
  let itemArray = item.split(':');
149833
149667
  if(itemArray[0] == 'fov') {
149834
149668
  ic.cam.fov = parseFloat(itemArray[1]);
149835
149669
  }
149836
149670
  else {
149837
- let abc = itemArray[1].split(',');
149671
+ let abc = itemArray[1].split(',').map(parseFloat);
149838
149672
  if(itemArray[0] == 'pos') {
149839
- ic.cam.position.set(parseFloat(abc[0]), parseFloat(abc[1]), parseFloat(abc[2]));
149673
+ ic.cam.position.set(abc[0], abc[1], abc[2]);
149840
149674
  }
149841
149675
  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])));
149676
+ ic.cam.quaternion.setFromUnitVectors(new Vector3$1(0, 0, -1), new Vector3$1(abc[0], abc[1], abc[2]));
149677
+ // dirVec = new THREE.Vector3(abc[0], abc[1], abc[2]);
149843
149678
  }
149844
149679
  else if(itemArray[0] == 'up') {
149845
- ic.cam.up.set(parseFloat(abc[0]), parseFloat(abc[1]), parseFloat(abc[2]));
149680
+ ic.cam.up.set(abc[0], abc[1], abc[2]);
149846
149681
  }
149847
149682
  }
149848
149683
  });
149684
+ // apply after pos and up are known, so the roll follows "up"
149685
+ // if(dirVec) {
149686
+ // ic.cam.lookAt(ic.cam.position.clone().add(dirVec));
149687
+ // ic.cam.updateMatrixWorld(true);
149688
+ // }
149849
149689
 
149850
149690
  // set the aspect ratio
149851
149691
  if(!ic.container.whratio) {
@@ -150186,17 +150026,30 @@ class SaveFile {
150186
150026
  let height = $("#" + ic.pre + "canvas").height();
150187
150027
  ic.applyCenterCls.setWidthHeight(width, height);
150188
150028
 
150029
+ let bPathTracer = (ic.scaleFactor == 1) ? false : true;
150030
+ /*
150189
150031
  // disable path tracing for large structures
150190
- let bPathTracer = (Object.keys(ic.atoms).length > ic.maxatomcnt) ? false : true;
150032
+ let bPathTracer = (Object.keys(ic.atoms).length > ic.maxatomcnt || ic.scaleFactor == 1) ? false : true;
150191
150033
 
150192
150034
  if(ic.biomtMatrices !== undefined && ic.biomtMatrices.length > 1 && ic.bAssembly
150193
150035
  && Object.keys(ic.atoms).length * ic.biomtMatrices.length > ic.maxatomcnt) {
150194
150036
  bPathTracer = false; // disable path tracing for large assemblies
150195
150037
  }
150038
+ */
150196
150039
 
150197
- //if(ic.bRender) ic.drawCls.render(undefined, bPathTracer);
150198
- if(ic.bRender) ic.drawCls.draw(undefined, bPathTracer);
150040
+ if(bPathTracer) {
150041
+ if(ic.bRender) ic.drawCls.draw(undefined, bPathTracer);
150199
150042
 
150043
+ /*
150044
+ let commandTransformation = ic.commands[ic.commands.length-1].split('|||');
150045
+ ic.transformCls.resetOrientation_base(commandTransformation);
150046
+ if(ic.bRender) ic.drawCls.render(undefined, bPathTracer);
150047
+ */
150048
+ }
150049
+ else {
150050
+ if(ic.bRender) ic.drawCls.render(undefined, bPathTracer);
150051
+ }
150052
+
150200
150053
  // reset impostor and instancing
150201
150054
  ic.bImpo = true; // enable impostor
150202
150055
  ic.bInstanced = true; // enable instancing
@@ -153881,8 +153734,6 @@ class iCn3D {
153881
153734
 
153882
153735
  this.bInitial = true; // first 3d display
153883
153736
 
153884
- this.bDoublecolor = false;
153885
-
153886
153737
  this.originSize = 1; // radius
153887
153738
 
153888
153739
  this.ALTERNATE_STRUCTURE = -1;
@@ -153959,7 +153810,7 @@ class iCn3D {
153959
153810
  //This is the line radius for stabilizers, hydrogen bonds, and distance lines. It's 0.1 by default.
153960
153811
  this.lineRadius = 0.1; // hbonds, distance lines
153961
153812
  //This is the coil radius for coils. It's 0.3 by default.
153962
- this.coilWidth = 0.3; //0.4; // style cartoon-coil
153813
+ this.coilWidth = 0.12; //0.3; // style cartoon-coil
153963
153814
  //This is the stick radius. It's 0.4 by default.
153964
153815
  this.cylinderRadius = 0.4; // style stick
153965
153816
  //This is the cross-linkage radius. It's 0.4 by default.
@@ -153974,7 +153825,7 @@ class iCn3D {
153974
153825
  this.cylinderHelixRadius = 1.6; // style cylinder and plate
153975
153826
 
153976
153827
  //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
153828
+ this.ribbonthickness = 0.35; // 0.2; // style ribbon, nucleotide cartoon, stand thickness
153978
153829
  //This is the width of protein ribbons. It's 1.3 by default.
153979
153830
  this.helixSheetWidth = 1.3; // style ribbon, nucleotide cartoon, stand thickness
153980
153831
  //This is the width of nucleotide ribbons. It's 0.8 by default.
@@ -154592,7 +154443,7 @@ class iCn3DUI {
154592
154443
  //even when multiple iCn3D viewers are shown together.
154593
154444
  this.pre = this.cfg.divid + "_";
154594
154445
 
154595
- this.REVISION = '3.53.0';
154446
+ this.REVISION = '3.54.0';
154596
154447
 
154597
154448
  // In nodejs, iCn3D defines "window = {navigator: {}}", and added window = {navigator: {}, "__THREE__":"177"}
154598
154449
  this.bNode = (Object.keys(window).length < 3) ? true : false;