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.js CHANGED
@@ -56739,31 +56739,24 @@ class SubdivideCls {
56739
56739
 
56740
56740
  // cubic splines for four points: http://thalestriangles.blogspot.com/2014/02/a-bit-of-ex-spline-ation.html
56741
56741
  // https://math.stackexchange.com/questions/577641/how-to-calculate-interpolating-splines-in-3d-space
56742
- subdivide(_pnts, _clrs, DIV, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes) { let me = this.icn3dui;
56742
+ subdivide(_pnts, _clrs, DIV) { let me = this.icn3dui;
56743
56743
 
56744
56744
  let ret = [];
56745
56745
  let pos = [];
56746
56746
  let color = [];
56747
56747
 
56748
- let pnts = new Array(); // Smoothing test
56749
-
56750
- let prevoneLen = (prevone !== undefined) ? prevone.length : 0;
56751
- let nexttwoLenOri = (nexttwo !== undefined) ? nexttwo.length : 0;
56748
+ let pnts_positions = [];
56752
56749
 
56753
- let maxDist = 6.0;
56750
+ if(_pnts.length == 0) {
56751
+ pnts_positions.push(ret);
56752
+ pnts_positions.push(pos);
56753
+ pnts_positions.push(color);
56754
56754
 
56755
- if(prevoneLen > 0
56756
- && Math.abs(prevone[0].x - _pnts[0].x) <= maxDist
56757
- && Math.abs(prevone[0].y - _pnts[0].y) <= maxDist
56758
- && Math.abs(prevone[0].z - _pnts[0].z) <= maxDist
56759
- ) {
56760
- pnts.push(prevone[0]);
56761
- prevoneLen = 1;
56762
- }
56763
- else {
56764
- prevoneLen = 0;
56755
+ return pnts_positions;
56765
56756
  }
56766
56757
 
56758
+ let pnts = new Array(); // Smoothing test
56759
+
56767
56760
  pnts.push(_pnts[0]);
56768
56761
  for (let i = 1, lim = _pnts.length - 1; i < lim; ++i) {
56769
56762
  let p0 = _pnts[i], p1 = _pnts[i + 1];
@@ -56771,38 +56764,13 @@ class SubdivideCls {
56771
56764
  }
56772
56765
  pnts.push(_pnts[_pnts.length - 1]);
56773
56766
 
56774
- let nexttwoLen = 0;
56775
- if(nexttwoLenOri > 0
56776
- && Math.abs(nexttwo[0].x - _pnts[_pnts.length - 1].x) <= maxDist
56777
- && Math.abs(nexttwo[0].y - _pnts[_pnts.length - 1].y) <= maxDist
56778
- && Math.abs(nexttwo[0].z - _pnts[_pnts.length - 1].z) <= maxDist
56779
- ) {
56780
- pnts.push(nexttwo[0]);
56781
- ++nexttwoLen;
56782
- }
56783
-
56784
- if(nexttwoLenOri > 1
56785
- && Math.abs(nexttwo[0].x - nexttwo[1].x) <= maxDist
56786
- && Math.abs(nexttwo[0].y - nexttwo[1].y) <= maxDist
56787
- && Math.abs(nexttwo[0].z - nexttwo[1].z) <= maxDist
56788
- ) {
56789
- pnts.push(nexttwo[1]);
56790
- ++nexttwoLen;
56791
- }
56792
-
56793
56767
  let savedPoints = [];
56794
56768
  let savedPos = [];
56795
56769
  let savedColor = [];
56796
56770
 
56797
- //var nexttwoLen = nexttwoLenOri;
56798
- if(bExtendLastRes) {
56799
- nexttwoLen = (nexttwoLenOri > 0) ? nexttwoLenOri - 1 : 0;
56800
- }
56801
-
56802
56771
  let alpha = 1, newI;
56803
-
56804
56772
  for (let i = -1, size = pnts.length, DIVINV = 1 / DIV; i <= size - 3; ++i) {
56805
- newI = i - prevoneLen;
56773
+ newI = i;
56806
56774
  let p0 = pnts[i === -1 ? 0 : i];
56807
56775
  let p1 = pnts[i + 1];
56808
56776
  let p2 = pnts[i + 2];
@@ -56817,14 +56785,11 @@ class SubdivideCls {
56817
56785
  if(t2 - t1 < 1e-4) t2 = t1 + 1;
56818
56786
  if(t3 - t2 < 1e-4) t3 = t2 + 1;
56819
56787
 
56820
- //if(i > -1 && bHighlight && bShowArray !== undefined && bShowArray[i + 1]) {
56821
- if(i > -1 && (bShowArray === undefined || bShowArray[newI + 1]) ) {
56788
+ if(i > -1 ) {
56822
56789
  // get from previous i for the first half of residue
56823
- if(i >= -1 + prevoneLen && i <= size - 3 - nexttwoLen + 1) {
56824
- ret = ret.concat(savedPoints);
56825
- pos = pos.concat(savedPos);
56826
- color = color.concat(savedColor);
56827
- }
56790
+ ret = ret.concat(savedPoints);
56791
+ pos = pos.concat(savedPos);
56792
+ color = color.concat(savedColor);
56828
56793
  }
56829
56794
 
56830
56795
  savedPoints = [];
@@ -56838,57 +56803,25 @@ class SubdivideCls {
56838
56803
  let y = me.subdivideCls.getValueFromKnot(t, t0, t1, t2, t3, p0.y, p1.y, p2.y, p3.y);
56839
56804
  let z = me.subdivideCls.getValueFromKnot(t, t0, t1, t2, t3, p0.z, p1.z, p2.z, p3.z);
56840
56805
 
56841
- if(!bShowArray) {
56842
- if(i >= -1 + prevoneLen && i <= size - 3 - nexttwoLen) {
56843
- ret.push(new Vector3$1(x, y, z));
56844
- pos.push(newI + 1);
56845
- color.push(_clrs[newI+1]);
56846
- }
56847
- }
56848
- else {
56849
- if(i >= -1 + prevoneLen && i <= size - 3 - nexttwoLen) {
56850
- if(bShowArray[newI + 1]) {
56851
- if(j <= parseInt((DIV) / 2) ) {
56852
- ret.push(new Vector3$1(x, y, z));
56853
- pos.push(bShowArray[newI + 1]);
56854
- color.push(_clrs[newI+1]);
56855
- }
56856
- }
56857
- }
56858
-
56859
- if(i >= -1 + prevoneLen && i <= size - 3 - nexttwoLen + 1) {
56860
- if(bShowArray[newI + 2]) {
56861
- if(j > parseInt((DIV) / 2) ) {
56862
- savedPoints.push(new Vector3$1(x, y, z));
56863
- savedPos.push(bShowArray[newI + 2]);
56864
- savedColor.push(_clrs[newI+2]);
56865
- }
56866
- }
56867
- }
56868
- } // end else
56869
-
56806
+ ret.push(new Vector3$1(x, y, z));
56807
+ pos.push(newI + 1);
56808
+ color.push(_clrs[newI+1]);
56870
56809
  } // end for (let j = 0;
56871
56810
  } // end for (let i = -1;
56872
56811
 
56873
- if(!bShowArray || bShowArray[newI + 1]) {
56874
- //if(bHighlight) {
56875
- ret = ret.concat(savedPoints);
56876
- pos = pos.concat(savedPos);
56877
- color = color.concat(savedColor);
56878
- //}
56812
+ ret = ret.concat(savedPoints);
56813
+ pos = pos.concat(savedPos);
56814
+ color = color.concat(savedColor);
56879
56815
 
56880
- ret.push(pnts[pnts.length - 1 - nexttwoLen]);
56881
- pos.push(pnts.length - 1 - nexttwoLen);
56882
- color.push(_clrs[pnts.length - 1 - nexttwoLen]);
56883
- }
56816
+ ret.push(pnts[pnts.length - 1]);
56817
+ pos.push(pnts.length - 1);
56818
+ color.push(_clrs[pnts.length - 1]);
56884
56819
 
56885
56820
  savedPoints = [];
56886
56821
  savedPos = [];
56887
56822
  savedColor = [];
56888
56823
  pnts = [];
56889
56824
 
56890
- let pnts_positions = [];
56891
-
56892
56825
  pnts_positions.push(ret);
56893
56826
  pnts_positions.push(pos);
56894
56827
  pnts_positions.push(color);
@@ -57694,6 +57627,7 @@ class ClickMenu {
57694
57627
  //var file_pref =(ic.inputid) ? ic.inputid : "custom";
57695
57628
  //ic.saveFileCls.saveFile(file_pref + '_image_icn3d_loadable.png', 'png');
57696
57629
  let bPngHtml = true;
57630
+ ic.scaleFactor = 1;
57697
57631
  await ic.shareLinkCls.shareLink(bPngHtml);
57698
57632
  });
57699
57633
  me.myEventCls.onIds("#" + me.pre + "mn1_exportCanvas1", "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
@@ -57711,11 +57645,11 @@ class ClickMenu {
57711
57645
  ic.scaleFactor = 4;
57712
57646
  await ic.shareLinkCls.shareLink(true, true);
57713
57647
  });
57714
- me.myEventCls.onIds("#" + me.pre + "mn1_exportCanvas8", "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
57715
- thisClass.setLogCmd("export canvas 8", true);
57716
- ic.scaleFactor = 8;
57717
- await ic.shareLinkCls.shareLink(true, true);
57718
- });
57648
+ // me.myEventCls.onIds("#" + me.pre + "mn1_exportCanvas8", "click", async function(e) { let ic = me.icn3d; //e.preventDefault();
57649
+ // thisClass.setLogCmd("export canvas 8", true);
57650
+ // ic.scaleFactor = 8;
57651
+ // await ic.shareLinkCls.shareLink(true, true);
57652
+ // });
57719
57653
 
57720
57654
  me.myEventCls.onIds("#" + me.pre + "mn1_exportCounts", "click", function(e) { let ic = me.icn3d; //e.preventDefault();
57721
57655
  thisClass.setLogCmd("export counts", false);
@@ -60464,9 +60398,8 @@ class SetMenu {
60464
60398
  html += this.getLink('mn1_exportCanvas', 'Original Size & HTML', undefined, 3);
60465
60399
  html += this.getLink('mn1_exportCanvas1', 'Original Size', 1, 3);
60466
60400
 
60467
- html += this.getLink('mn1_exportCanvas2', '2X Large', undefined, 3);
60468
- html += this.getLink('mn1_exportCanvas4', '4X Large', undefined, 3);
60469
- html += this.getLink('mn1_exportCanvas8', '8X Large', undefined, 3);
60401
+ html += this.getLink('mn1_exportCanvas2', '2X for Pub. (Path Tracing)', 1, 3);
60402
+ html += this.getLink('mn1_exportCanvas4', '4X for Pub. (Path Tracing)', undefined, 3);
60470
60403
 
60471
60404
  html += "</ul>";
60472
60405
  html += "</li>";
@@ -64278,6 +64211,11 @@ class Events {
64278
64211
 
64279
64212
  async setRealign(alignType, bMsa) { let me = this.icn3dui, ic = me.icn3d, thisClass = this;
64280
64213
  let nameArray = $("#" + me.pre + "atomsCustomRealignByStruct").val();
64214
+
64215
+ if(nameArray.length == 0) {
64216
+ nameArray = $("#" + me.pre + "atomsCustom").val();
64217
+ }
64218
+
64281
64219
  if(nameArray.length > 0) {
64282
64220
  ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(nameArray);
64283
64221
  }
@@ -64563,11 +64501,15 @@ class Events {
64563
64501
  upvectorArray = [childNodes[0].textContent, childNodes[1].textContent, childNodes[2].textContent];
64564
64502
 
64565
64503
  ic.cam.position.set(viewpointArray[0], viewpointArray[1], viewpointArray[2]);
64566
- ic.cam.quaternion.setFromUnitVectors(new Vector3$1(0, 0, -1), new Vector3$1(directionArray[0], directionArray[1], directionArray[2]));
64567
64504
  ic.cam.up.set(upvectorArray[0], upvectorArray[1], upvectorArray[2]);
64568
64505
  ic.cam.fov = fov;
64569
64506
  // ic.container.whratio = aspect;
64570
64507
 
64508
+ ic.cam.quaternion.setFromUnitVectors(new Vector3$1(0, 0, -1), new Vector3$1(directionArray[0], directionArray[1], directionArray[2]));
64509
+ // let dirVec = new THREE.Vector3(directionArray[0], directionArray[1], directionArray[2]);
64510
+ // ic.cam.lookAt(ic.cam.position.clone().add(dirVec));
64511
+ // ic.cam.updateMatrixWorld(true);
64512
+
64571
64513
  ic.drawCls.applyTransformation(ic._zoomFactor, ic.mouseChange, ic.quaternion);
64572
64514
  ic.drawCls.render();
64573
64515
  });
@@ -68377,12 +68319,12 @@ class SetHtml {
68377
68319
 
68378
68320
  // type == '3dprint' or 'style'
68379
68321
  let linerad =(type == '3dprint') ? '1' : '0.1';
68380
- let coilrad =(type == '3dprint') ? '1.2' : '0.3';
68322
+ let coilrad =(type == '3dprint') ? '1.2' : '0.12';
68381
68323
  let stickrad =(type == '3dprint') ? '0.8' : '0.4';
68382
68324
  let crosslinkrad =(type == '3dprint') ? '0.8' : '0.4';
68383
68325
  let tracerad =(type == '3dprint') ? '1' : '0.4';
68384
68326
  let ballscale =(type == '3dprint') ? '0.6' : '0.3';
68385
- let ribbonthick =(type == '3dprint') ? '1' : '0.2';
68327
+ let ribbonthick =(type == '3dprint') ? '1' : '0.35';
68386
68328
  let prtribbonwidth =(type == '3dprint') ? '2' : '1.3';
68387
68329
  let nucleotideribbonwidth =(type == '3dprint') ? '1.4' : '0.8';
68388
68330
 
@@ -68451,12 +68393,12 @@ class SetHtml {
68451
68393
  }
68452
68394
 
68453
68395
  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/>";
68454
- 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/>";
68396
+ 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/>";
68455
68397
  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/>";
68456
68398
  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/>";
68457
68399
  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/>";
68458
68400
 
68459
- 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/>";
68401
+ 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/>";
68460
68402
  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/>";
68461
68403
  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/>";
68462
68404
 
@@ -69110,12 +69052,12 @@ class SetHtml {
69110
69052
 
69111
69053
  if(bReset) {
69112
69054
  $("#" + me.pre + "linerad_" + postfix ).val(0.1); //0.1; // hbonds, distance lines
69113
- $("#" + me.pre + "coilrad_" + postfix ).val(0.3); //0.3; // style cartoon-coil
69055
+ $("#" + me.pre + "coilrad_" + postfix ).val(0.12); //0.12; // style cartoon-coil
69114
69056
  $("#" + me.pre + "stickrad_" + postfix ).val(0.4); //0.4; // style stick
69115
69057
  $("#" + me.pre + "crosslinkrad_" + postfix ).val(0.4); //0.4; // cross-linkage
69116
69058
  $("#" + me.pre + "tracerad_" + postfix ).val(0.4); //0.4; // style c alpha trace, nucleotide stick
69117
69059
  $("#" + me.pre + "ballscale_" + postfix ).val(0.3); //0.3; // style ball and stick, dot
69118
- $("#" + me.pre + "ribbonthick_" + postfix ).val(0.2); //0.2; // style ribbon, nucleotide cartoon, stand thickness
69060
+ $("#" + me.pre + "ribbonthick_" + postfix ).val(0.35); //0.35; // style ribbon, nucleotide cartoon, stand thickness
69119
69061
  $("#" + me.pre + "prtribbonwidth_" + postfix ).val(1.3); //1.3; // style ribbon, stand thickness
69120
69062
  $("#" + me.pre + "nucleotideribbonwidth_" + postfix ).val(0.8); //0.8; // nucleotide cartoon
69121
69063
  }
@@ -78235,129 +78177,90 @@ class CurveStripArrow {
78235
78177
  }
78236
78178
 
78237
78179
  createCurveSubArrow(p, width, colors, div, bHighlight, bRibbon, num, positionIndex,
78238
- pntsCA, prevCOArray, bShowArray, calphaIdArray, bShowArrow, prevone, nexttwo) { let ic = this.icn3d, me = ic.icn3dui;
78180
+ pntsCA, prevCOArray, positions, bShowArrow) { let ic = this.icn3d, me = ic.icn3dui;
78239
78181
  if(me.bNode) return;
78240
78182
 
78241
- let divPoints = [], positions = [];
78183
+ let divPoints = [], linePos = [];
78242
78184
 
78243
78185
  divPoints.push(p);
78244
- positions.push(positionIndex);
78186
+ linePos.push(positionIndex);
78245
78187
 
78246
- this.prepareStrand(divPoints, positions, width, colors, div, undefined, bHighlight, bRibbon, num,
78247
- pntsCA, prevCOArray, false, bShowArray, calphaIdArray, bShowArrow, prevone, nexttwo);
78188
+ this.prepareStrand(divPoints, linePos, width, colors, div, undefined, bHighlight, bRibbon, num,
78189
+ pntsCA, prevCOArray, positions, false, bShowArrow);
78248
78190
 
78249
78191
  divPoints = [];
78250
- positions = [];
78192
+ linePos = [];
78251
78193
  }
78252
78194
 
78253
78195
  createStripArrow(p0, p1, colors, div, thickness, bHighlight, num, start, end,
78254
- pntsCA, prevCOArray, bShowArray, calphaIdArray, bShowArrow, prevone, nexttwo) { let ic = this.icn3d, me = ic.icn3dui;
78196
+ pntsCA, prevCOArray, positions, bShowArrow, ) { let ic = this.icn3d, me = ic.icn3dui;
78255
78197
  if(me.bNode) return;
78256
78198
 
78257
- let divPoints = [], positions = [];
78199
+ let divPoints = [], linePos = [];
78258
78200
 
78259
78201
  divPoints.push(p0);
78260
78202
  divPoints.push(p1);
78261
- positions.push(start);
78262
- positions.push(end);
78203
+ linePos.push(start);
78204
+ linePos.push(end);
78263
78205
 
78264
- this.prepareStrand(divPoints, positions, undefined, colors, div, thickness, bHighlight, undefined, num,
78265
- pntsCA, prevCOArray, true, bShowArray, calphaIdArray, bShowArrow, prevone, nexttwo);
78206
+ this.prepareStrand(divPoints, linePos, undefined, colors, div, thickness, bHighlight, undefined, num,
78207
+ pntsCA, prevCOArray, positions,true, bShowArrow);
78266
78208
 
78267
78209
  divPoints = [];
78268
- positions = [];
78210
+ linePos = [];
78269
78211
  }
78270
78212
 
78271
78213
  /**
78272
78214
  * @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
78273
78215
  */
78274
78216
 
78275
- prepareStrand(divPoints, positions, width, colors, div, thickness, bHighlight, bRibbon, num,
78276
- pntsCA, prevCOArray, bStrip, bShowArray, calphaIdArray, bShowArrow, prevone, nexttwo) { let ic = this.icn3d, me = ic.icn3dui;
78217
+ prepareStrand(divPoints, linePos, width, colors, div, thickness, bHighlight, bRibbon, num,
78218
+ pntsCA, prevCOArray, positions, bStrip, bShowArrow) { let ic = this.icn3d; ic.icn3dui;
78277
78219
  if(pntsCA.length === 1) {
78278
78220
  return;
78279
78221
  }
78280
-
78281
- let oriColors = colors;
78282
78222
  let bHelix = (bShowArrow) ? false : true;
78283
78223
 
78284
- let colorsLastTwo = [];
78285
- colorsLastTwo.push(colors[colors.length - 2]);
78286
- colorsLastTwo.push(colors[colors.length - 1]);
78287
-
78288
78224
  div = div || ic.axisDIV;
78289
78225
  let numM1Inv2 = 2 / (num - 1);
78290
- let delta, lastCAIndex, lastPrevCOIndex, v;
78291
78226
 
78292
78227
  let pnts = {};
78293
- for(let i = 0, il = positions.length; i < il; ++i) pnts[i] = [];
78294
-
78295
- // smooth C-alpha
78296
- let pnts_clrs = me.subdivideCls.subdivide(pntsCA, colors, div, undefined, undefined, prevone, nexttwo);
78297
- let pntsCASmooth = pnts_clrs[0]; // get all smoothen pnts, do not use 'bShowArray'
78298
- //colors = pnts_clrs[2];
78228
+ for(let i = 0, il = linePos.length; i < il; ++i) pnts[i] = [];
78299
78229
 
78300
- if(pntsCASmooth.length === 1) {
78301
- return;
78302
- }
78230
+ //let startOffset = Math.floor(ic.axisDIV / 2) + 1; // first residue has floor(DIV/2)+1 points (8 when axisDIV = 15)
78303
78231
 
78304
78232
  // draw the sheet without the last residue
78305
78233
  // use the sheet coord for n-2 residues
78306
78234
  let colorsTmp = [];
78307
- let i, lastIndex = (bShowArrow === undefined || bShowArrow) ? pntsCA.length - 2 : pntsCA.length;
78235
+ let extraArrow = (bStrip) ? 2 : 0; // extend the tube by 5 sub-points into a preceding/following helix/sheet
78236
+
78237
+ let i, lastIndex = (bShowArrow === undefined || bShowArrow) ? pntsCA.length - ic.axisDIV + extraArrow : pntsCA.length;
78308
78238
 
78309
78239
  let il = lastIndex;
78240
+ let posIndex = [], pntsCATmp = [], prevCOArrayTmp = [];
78310
78241
  for (i = 0; i < il; ++i) {
78311
- for(let index = 0, indexl = positions.length; index < indexl; ++index) {
78242
+ for(let index = 0, indexl = linePos.length; index < indexl; ++index) {
78312
78243
  pnts[index].push(divPoints[index][i]);
78313
78244
  }
78245
+ pntsCATmp.push(pntsCA[i]);
78246
+ prevCOArrayTmp.push(prevCOArray[i]);
78314
78247
  colorsTmp.push(colors[i]);
78315
- }
78316
- colorsTmp.push(colors[i]);
78317
-
78318
- if(bShowArrow === undefined || bShowArrow) {
78319
- // assign the sheet coord from C-alpha for the 2nd to the last residue of the sheet
78320
- for(let i = 0, il = positions.length; i < il; ++i) {
78321
- delta = -1 + numM1Inv2 * positions[i];
78322
- lastCAIndex = pntsCASmooth.length - 1 - div;
78323
- lastPrevCOIndex = pntsCA.length - 2;
78324
- v = new Vector3$1(pntsCASmooth[lastCAIndex].x + prevCOArray[lastPrevCOIndex].x * delta,
78325
- pntsCASmooth[lastCAIndex].y + prevCOArray[lastPrevCOIndex].y * delta,
78326
- pntsCASmooth[lastCAIndex].z + prevCOArray[lastPrevCOIndex].z * delta);
78327
- pnts[i].push(v);
78328
- }
78329
- }
78330
-
78331
- let posIndex = [];
78332
- let results;
78333
- for(let i = 0, il = positions.length; i < il; ++i) {
78334
- results = me.subdivideCls.subdivide(pnts[i], colorsTmp, div, bShowArray, bHighlight);
78335
- pnts[i] = results[0];
78336
- colors = results[2];
78337
- if(i === 0) {
78338
- posIndex = results[1];
78339
- }
78248
+ posIndex.push(positions[i]);
78340
78249
  }
78341
78250
 
78342
78251
  if(bStrip) {
78343
78252
  if(bHelix) {
78344
- if(!ic.bDoublecolor) {
78345
- ic.stripCls.createStrip(pnts[0], pnts[1], colors, div, thickness, bHighlight, true,
78346
- undefined, calphaIdArray, posIndex, prevone, nexttwo, pntsCA, prevCOArray);
78347
- }
78348
- else {
78349
- ic.stripCls.createStrip(pnts[0], pnts[1], oriColors, div, thickness, bHighlight, true,
78350
- undefined, calphaIdArray, posIndex, prevone, nexttwo, pntsCA, prevCOArray);
78351
- }
78253
+ ic.stripCls.createStrip(pnts[0], pnts[1], colorsTmp, div, thickness, bHighlight, true,
78254
+ undefined, posIndex, pntsCATmp, prevCOArrayTmp);
78352
78255
  }
78353
78256
  else {
78354
- ic.stripCls.createStrip(pnts[0], pnts[1], colors, div, thickness, bHighlight, true,
78355
- undefined, calphaIdArray, posIndex, prevone, nexttwo);
78257
+ ic.stripCls.createStrip(pnts[0], pnts[1], colorsTmp, div, thickness, bHighlight, true,
78258
+ undefined, posIndex);
78356
78259
  }
78357
78260
  }
78358
78261
  else {
78359
- ic.curveCls.createCurveSub(pnts[0], width, colors, div, bHighlight, bRibbon, true,
78360
- undefined, calphaIdArray, posIndex, prevone, nexttwo);
78262
+ ic.curveCls.createCurveSub(pnts[0], width, colorsTmp, div, bHighlight, bRibbon, true,
78263
+ undefined, posIndex);
78361
78264
  }
78362
78265
 
78363
78266
  if(bShowArrow === undefined || bShowArrow) {
@@ -78365,60 +78268,53 @@ class CurveStripArrow {
78365
78268
  colorsTmp = [];
78366
78269
 
78367
78270
  posIndex = [];
78368
- for(let index = 0, indexl = positions.length; index < indexl; ++index) {
78271
+ for(let index = 0, indexl = linePos.length; index < indexl; ++index) {
78369
78272
  pnts[index] = [];
78370
78273
 
78371
- for (let i = div * (pntsCA.length - 2), il = div * (pntsCA.length - 1);
78372
- bShowArray[parseInt(i/div)] && i < il; i = i + div) {
78373
- let pos = parseInt(i/div);
78374
- for (let j = 0; j < div; ++j) {
78375
- let delta = -1 + numM1Inv2 * positions[index];
78376
- let scale = 1.8; // scale of the arrow width
78377
- delta = delta * scale * (div - j) / div;
78378
- let oriIndex = parseInt(i/div);
78379
-
78380
- let v = new Vector3$1(pntsCASmooth[i+j].x + prevCOArray[oriIndex].x * delta,
78381
- pntsCASmooth[i+j].y + prevCOArray[oriIndex].y * delta,
78382
- pntsCASmooth[i+j].z + prevCOArray[oriIndex].z * delta);
78383
- v.smoothen = true;
78384
- pnts[index].push(v);
78385
- colorsTmp.push(colorsLastTwo[0]);
78386
- if(index === 0) posIndex.push(pos);
78387
- }
78274
+ let cnt = 0;
78275
+ for (let i = lastIndex - extraArrow, il = lastIndex - extraArrow + ic.axisDIV; i < il; ++i, ++cnt) {
78276
+ let pos = positions[i];
78277
+ let delta = -1 + numM1Inv2 * linePos[index];
78278
+ let scale = 1.8; // scale of the arrow width
78279
+ delta = delta * scale * (ic.axisDIV - cnt) / ic.axisDIV;
78280
+
78281
+ let v = new Vector3$1(pntsCA[i].x + prevCOArray[i].x * delta,
78282
+ pntsCA[i].y + prevCOArray[i].y * delta,
78283
+ pntsCA[i].z + prevCOArray[i].z * delta);
78284
+ //v.smoothen = true;
78285
+ pnts[index].push(v);
78286
+ colorsTmp.push(colors[i]);
78287
+ if(index === 0) posIndex.push(pos);
78388
78288
  }
78389
-
78289
+
78390
78290
  // last residue
78391
78291
  // make the arrow end with 0
78392
- let delta = 0;
78393
- let lastCAIndex = pntsCASmooth.length - 1;
78394
- let lastPrevCOIndex = pntsCA.length - 1;
78395
-
78396
- //if(bShowArray[lastPrevCOIndex]) {
78397
- let v = new Vector3$1(pntsCASmooth[lastCAIndex].x + prevCOArray[lastPrevCOIndex].x * delta,
78398
- pntsCASmooth[lastCAIndex].y + prevCOArray[lastPrevCOIndex].y * delta,
78399
- pntsCASmooth[lastCAIndex].z + prevCOArray[lastPrevCOIndex].z * delta);
78400
- v.smoothen = true;
78401
- pnts[index].push(v);
78402
- colorsTmp.push(colorsLastTwo[1]);
78403
- if(index === 0) posIndex.push(lastCAIndex);
78404
- //}
78405
- }
78292
+ let lastCAIndex = pntsCA.length - 1;
78293
+ let delta = -1 + numM1Inv2 * linePos[index];
78294
+ let scale = 1.8; // scale of the arrow width
78295
+ delta = delta * scale / ic.axisDIV;
78406
78296
 
78407
- pntsCASmooth = [];
78297
+ let v = new Vector3$1(pntsCA[lastCAIndex].x + prevCOArray[lastCAIndex].x * delta,
78298
+ pntsCA[lastCAIndex].y + prevCOArray[lastCAIndex].y * delta,
78299
+ pntsCA[lastCAIndex].z + prevCOArray[lastCAIndex].z * delta);
78408
78300
 
78409
- //colorsTmp.push(colors[colors.length - 2]);
78410
- //colorsTmp.push(colors[colors.length - 1]);
78301
+ pnts[index].push(v);
78302
+ colorsTmp.push(colors[i]);
78303
+ if(index === 0) posIndex.push(positions[lastCAIndex]);
78304
+ }
78411
78305
 
78412
78306
  if(bStrip) {
78413
78307
  ic.stripCls.createStrip(pnts[0], pnts[1], colorsTmp, div, thickness, bHighlight, true,
78414
- undefined, undefined, posIndex, prevone, nexttwo);
78308
+ undefined, undefined, posIndex);
78415
78309
  }
78416
78310
  else {
78417
78311
  ic.curveCls.createCurveSub(pnts[0], width, colorsTmp, div, bHighlight, bRibbon, true,
78418
- undefined, undefined, posIndex, prevone, nexttwo);
78312
+ undefined, undefined, posIndex);
78419
78313
  }
78420
78314
  }
78421
78315
 
78316
+ //pntsCA = [];
78317
+
78422
78318
  for(let i in pnts) {
78423
78319
  for(let j = 0, jl = pnts[i].length; j < jl; ++j) {
78424
78320
  pnts[i][j] = null;
@@ -78427,7 +78323,7 @@ class CurveStripArrow {
78427
78323
  }
78428
78324
 
78429
78325
  pnts = {};
78430
- }
78326
+ }
78431
78327
  }
78432
78328
 
78433
78329
  /**
@@ -78440,15 +78336,14 @@ class Curve {
78440
78336
  }
78441
78337
 
78442
78338
  // modified from iview (http://star.cse.cuhk.edu.hk/iview/)
78443
- createCurveSub(_pnts, width, colors, div, bHighlight, bRibbon, bNoSmoothen, bShowArray, calphaIdArray, positions, prevone, nexttwo) { let ic = this.icn3d, me = ic.icn3dui;
78339
+ createCurveSub(_pnts, width, colors, div, bHighlight, bRibbon, bNoSmoothen, positions) { let ic = this.icn3d, me = ic.icn3dui;
78444
78340
  if(me.bNode) return;
78445
78341
 
78446
78342
  if (_pnts.length === 0) return;
78447
78343
  div = div || 5;
78448
78344
  let pnts;
78449
- if(!bNoSmoothen) {
78450
- let bExtendLastRes = true;
78451
- let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
78345
+ if(div != 1 && !bNoSmoothen) {
78346
+ let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, div);
78452
78347
  pnts = pnts_clrs[0];
78453
78348
  colors = pnts_clrs[2];
78454
78349
  }
@@ -78457,8 +78352,6 @@ class Curve {
78457
78352
  }
78458
78353
  if (pnts.length === 0) return;
78459
78354
 
78460
- ic.stripCls.setCalphaDrawnCoord(pnts, div, calphaIdArray);
78461
-
78462
78355
  if(bHighlight === 1) {
78463
78356
  let radius = ic.coilWidth / 2;
78464
78357
  //var radiusSegments = 8;
@@ -78585,7 +78478,7 @@ class Curve {
78585
78478
  }
78586
78479
 
78587
78480
  pnts = null;
78588
- }
78481
+ }
78589
78482
  }
78590
78483
 
78591
78484
  /**
@@ -78755,12 +78648,12 @@ class Cylinder {
78755
78648
 
78756
78649
  let start = null;
78757
78650
  let currentChain, currentResi;
78758
- let others = {}, beta = {};
78651
+ let others = [], beta = {};
78759
78652
  let i;
78760
78653
  for (i in atoms) {
78761
78654
  let atom = atoms[i];
78762
78655
  if (atom.het) continue;
78763
- if ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) others[atom.serial] = atom;
78656
+ if ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) others.push(atom);
78764
78657
  if (atom.ss === 'sheet') beta[atom.serial] = atom;
78765
78658
  if (atom.name !== 'CA') continue;
78766
78659
  if (atom.ss === 'helix' && atom.ssend) {
@@ -79736,45 +79629,22 @@ class Strip {
79736
79629
  }
79737
79630
 
79738
79631
  // modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
79739
- createStrip(p0, p1, colors, div, thickness, bHighlight, bNoSmoothen, bShowArray,
79740
- calphaIdArray, positions, prevone, nexttwo, pntsCA, prevCOArray) { let ic = this.icn3d, me = ic.icn3dui;
79632
+ createStrip(p0, p1, colors, div, thickness, bHighlight, bNoSmoothen,
79633
+ positions, pntsCA, prevCOArray) { let ic = this.icn3d, me = ic.icn3dui;
79741
79634
  if(me.bNode) return;
79742
79635
 
79743
79636
  if (p0.length < 2) return;
79744
79637
  div = div || ic.axisDIV;
79745
79638
 
79746
- // if(pntsCA && ic.bDoublecolor && !ic.bCalphaOnly) {
79747
- if(pntsCA && ic.bDoublecolor) {
79748
- let bExtendLastRes = false; //true;
79749
-
79750
- let pnts_clrs = me.subdivideCls.subdivide(pntsCA, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
79751
- pntsCA = pnts_clrs[0];
79752
-
79753
- this.setCalphaDrawnCoord(pntsCA, div, calphaIdArray);
79754
-
79755
- for(let i = 0, il = prevCOArray.length; i < il; ++i) {
79756
- prevCOArray[i].normalize();
79757
- }
79758
-
79759
- let pnts_clrs2 = me.subdivideCls.subdivide(prevCOArray, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
79760
- prevCOArray = pnts_clrs2[0];
79761
-
79762
- colors = pnts_clrs[2];
79763
- }
79764
- else {
79765
-
79639
+ if(div != 1) { // not subdivided yet
79766
79640
  if(!bNoSmoothen) {
79767
- //var bExtendLastRes = true;
79768
- let bExtendLastRes = false;
79769
- let pnts_clrs0 = me.subdivideCls.subdivide(p0, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
79770
- let pnts_clrs1 = me.subdivideCls.subdivide(p1, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
79641
+ let pnts_clrs0 = me.subdivideCls.subdivide(p0, colors, div);
79642
+ let pnts_clrs1 = me.subdivideCls.subdivide(p1, colors, div);
79771
79643
  p0 = pnts_clrs0[0];
79772
79644
  p1 = pnts_clrs1[0];
79773
79645
  colors = pnts_clrs0[2];
79774
79646
  }
79775
79647
  if (p0.length < 2) return;
79776
-
79777
- this.setCalphaDrawnCoord(p0, div, calphaIdArray);
79778
79648
  }
79779
79649
 
79780
79650
  if(bHighlight === 1) {
@@ -79801,7 +79671,7 @@ class Strip {
79801
79671
  radiusSegments,
79802
79672
  closed
79803
79673
  );
79804
-
79674
+
79805
79675
  let mesh = new Mesh$1(geometry0, ic.matShader);
79806
79676
  mesh.renderOrder = ic.renderOrderPicking;
79807
79677
  //ic.mdlPicking.add(mesh);
@@ -79896,33 +79766,29 @@ class Strip {
79896
79766
 
79897
79767
  if(!p0v || !p1v) continue;
79898
79768
 
79899
- //vs = vs.concat((p0v).toArray()); // 0
79900
- //vs = vs.concat((p0v).toArray()); // 1
79901
- //vs = vs.concat((p1v).toArray()); // 2
79902
- //vs = vs.concat((p1v).toArray()); // 3
79769
+ // compute the thickness direction first
79770
+ if (i < lim - 1 && p0[i + 1]) {
79771
+ axis = p1[i].clone().sub(p0[i]).cross(p0[i + 1].clone().sub(p0[i])).normalize().multiplyScalar(thickness);
79772
+ }
79773
+ let half = axis.clone().multiplyScalar(0.5);
79903
79774
 
79775
+ // bottom face: half a thickness below the edge plane
79776
+ let b0v = p0v.clone().sub(half);
79777
+ let b1v = p1v.clone().sub(half);
79904
79778
  for(let j = 0; j < 2; ++j) {
79905
- vs[offset++] = p0v.x;
79906
- vs[offset++] = p0v.y;
79907
- vs[offset++] = p0v.z;
79779
+ vs[offset++] = b0v.x;
79780
+ vs[offset++] = b0v.y;
79781
+ vs[offset++] = b0v.z;
79908
79782
  }
79909
79783
  for(let j = 0; j < 2; ++j) {
79910
- vs[offset++] = p1v.x;
79911
- vs[offset++] = p1v.y;
79912
- vs[offset++] = p1v.z;
79913
- }
79914
-
79915
- if (i < lim - 1) {
79916
- axis = p1[i].clone().sub(p0[i]).cross(p0[i + 1].clone().sub(p0[i])).normalize().multiplyScalar(thickness);
79784
+ vs[offset++] = b1v.x;
79785
+ vs[offset++] = b1v.y;
79786
+ vs[offset++] = b1v.z;
79917
79787
  }
79918
- a0v = p0[i].clone().add(axis);
79919
- a1v = p1[i].clone().add(axis);
79920
-
79921
- //vs = vs.concat((a0v).toArray()); // 4
79922
- //vs = vs.concat((a0v).toArray()); // 5
79923
- //vs = vs.concat((a1v).toArray()); // 6
79924
- //vs = vs.concat((a1v).toArray()); // 7
79925
79788
 
79789
+ // top face: half a thickness above the edge plane
79790
+ a0v = p0v.clone().add(half);
79791
+ a1v = p1v.clone().add(half);
79926
79792
  for(let j = 0; j < 2; ++j) {
79927
79793
  vs[offset++] = a0v.x;
79928
79794
  vs[offset++] = a0v.y;
@@ -80041,22 +79907,6 @@ class Strip {
80041
79907
  p0 = null;
80042
79908
  p1 = null;
80043
79909
  }
80044
-
80045
- setCalphaDrawnCoord(pnts, div, calphaIdArray) { let ic = this.icn3d; ic.icn3dui;
80046
- let index = 0;
80047
-
80048
- if(calphaIdArray !== undefined) {
80049
- for(let i = 0, il = pnts.length; i < il; i += div) { // pnts.length = (calphaIdArray.length - 1) * div + 1
80050
- let serial = calphaIdArray[index];
80051
-
80052
- if(ic.atoms.hasOwnProperty(serial)) {
80053
- ic.atoms[serial].coord2 = pnts[i].clone();
80054
- }
80055
-
80056
- ++index;
80057
- }
80058
- }
80059
- }
80060
79910
  }
80061
79911
 
80062
79912
  /**
@@ -80072,129 +79922,89 @@ class Tube {
80072
79922
  //Create tubes for "atoms" with certain "atomName". "radius" is the radius of the tubes.
80073
79923
  //"bHighlight" is an option to draw the highlight for these atoms. The highlight could be
80074
79924
  //outlines with bHighlight=1 and 3D objects with bHighlight=2.
80075
- createTube(atoms, atomName, radius, bHighlight, bCustom, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
79925
+ createTube(atoms, atomName, radius, bHighlight, bCustom, bNonCoil, tubePosArray, pntsCAAllSub, colorsAllSub) { let ic = this.icn3d, me = ic.icn3dui;
80076
79926
  if(me.bNode) return;
80077
79927
 
80078
- let pnts = [], colors = [], radii = [], prevone = [], nexttwo = [];
79928
+ let pnts = [], colors = [], radii = [];
80079
79929
  let currentChain, currentResi;
80080
79930
  let index = 0;
80081
79931
  let maxDist = 6.0;
80082
79932
  let maxDist2 = 3.0; // avoid tube between the residues in 3 residue helix
80083
79933
 
80084
- let pnts_colors_radii_prevone_nexttwo = [];
80085
- let firstAtom, atom, prevAtom;
79934
+ let pnts_colors_radii = [];
79935
+ let firstAtom, firstPos, prevAtom, prevPos;
79936
+ let half = Math.floor(ic.axisDIV / 2) - 1;
80086
79937
 
80087
- for (let i in atoms) {
80088
- atom = atoms[i];
79938
+ for (let i = 0, il = atoms.length; i < il; ++i) {
79939
+ let pos = (tubePosArray) ? tubePosArray[i] : undefined;
79940
+
79941
+ let atom = atoms[i];
80089
79942
  if ((atom.name === atomName) && !atom.het) {
80090
79943
  if(index == 0) {
80091
79944
  firstAtom = atom;
79945
+ firstPos = pos;
80092
79946
  }
80093
79947
 
80094
79948
  atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) - 1).toString();
80095
79949
 
80096
79950
  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
80097
79951
  || (prevAtom.ssbegin) // e.g., https://www.ncbi.nlm.nih.gov/Structure/icn3d/?pdbid=7JO8 where a beta sheet has just two residues
80098
- // || (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')
80099
79952
  || (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))
80100
79953
  ) ) {
80101
79954
  if(bHighlight !== 2) {
80102
- if(!isNaN(firstAtom.resi) && !isNaN(prevAtom.resi)) {
80103
- let prevoneResid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
80104
- let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
80105
- prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
80106
-
80107
- let nextoneResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 1).toString();
80108
- let nexttwoResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 2).toString();
80109
- let nextthreeResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 3).toString();
80110
-
80111
- if(ic.residues.hasOwnProperty(nextoneResid)) {
80112
- let nextAtom = ic.firstAtomObjCls.getAtomFromResi(nextoneResid, atomName);
80113
- if(nextAtom !== undefined && nextAtom.ssbegin) { // include the residue
80114
- nextoneResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 2).toString();
80115
- nexttwoResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 3).toString();
80116
-
80117
- pnts.push(nextAtom.coord);
80118
- if(bCustom) {
80119
- radii.push(this.getCustomtubesize(nextoneResid));
80120
- }
80121
- else {
80122
- radii.push(this.getRadius(radius, nextAtom));
80123
- }
80124
- colors.push(nextAtom.color);
80125
- }
79955
+ if(tubePosArray) {
79956
+ let bMissingEnd = ic.missingResEnd[prevAtom.structure + '_' + prevAtom.chain + '_' + prevAtom.resi];
79957
+ // remove half of the points when missign residues
79958
+ if(bMissingEnd) {
79959
+ pnts.splice(-half);
79960
+ colors.splice(-half);
79961
+ radii.splice(-half);
80126
79962
  }
80127
79963
 
80128
- // add one more residue if only one residue is available and it's not part of helix/sheet
80129
- if(pnts.length == 1 && ic.residues.hasOwnProperty(nextoneResid) && atom.ss == 'coil') {
80130
- let nextAtom = ic.firstAtomObjCls.getAtomFromResi(nextoneResid, atomName);
80131
-
80132
- if(nextAtom) {
80133
- pnts.push(nextAtom.coord);
80134
- colors.push(nextAtom.color);
79964
+ let result = this.closeSegment(firstAtom, firstPos, prevAtom, prevPos, pnts, colors, radii, pntsCAAllSub);
80135
79965
 
80136
- let radiusFinal = this.getRadius(radius, atom);
80137
- radii.push(radiusFinal);
80138
-
80139
- nextoneResid = nexttwoResid;
80140
- nexttwoResid = nextthreeResid;
80141
- }
80142
- }
80143
-
80144
- let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
80145
- if(nextoneCoord !== undefined) {
80146
- nexttwo.push(nextoneCoord);
80147
- }
80148
-
80149
- let nexttwoCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nexttwoResid, atomName);
80150
- if(nexttwoCoord !== undefined) {
80151
- nexttwo.push(nexttwoCoord);
80152
- }
79966
+ pnts_colors_radii.push(result);
79967
+ }
79968
+ else {
79969
+ pnts_colors_radii.push({'pnts':pnts, 'colors':colors, 'radii':radii});
80153
79970
  }
80154
-
80155
- pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
80156
79971
  }
80157
- pnts = []; colors = []; radii = []; prevone = []; nexttwo = [];
80158
- firstAtom = atom;
79972
+ pnts = []; colors = []; radii = []; firstAtom = atom;
79973
+ firstPos = pos;
80159
79974
  index = 0;
80160
79975
  }
80161
79976
 
80162
- if(pnts.length == 0 && !isNaN(atom.resi)) {
80163
- let prevoneResid = atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) - 1).toString();
80164
- if(ic.residues.hasOwnProperty(prevoneResid)) {
80165
- prevAtom = ic.firstAtomObjCls.getAtomFromResi(prevoneResid, atomName);
80166
- if(prevAtom !== undefined && prevAtom.ssend) { // include the residue
80167
- pnts.push(prevAtom.coord);
80168
- if(bCustom) {
80169
- radii.push(this.getCustomtubesize(prevoneResid));
80170
- }
80171
- else {
80172
- radii.push(this.getRadius(radius, prevAtom));
80173
- }
80174
- colors.push(prevAtom.color);
80175
- }
80176
- }
80177
- }
79977
+ if(tubePosArray) { // coil
79978
+ let bMissingStart = ic.missingResStart[atom.structure + '_' + atom.chain + '_' + atom.resi];
79979
+ let bMissingEnd = ic.missingResEnd[atom.structure + '_' + atom.chain + '_' + atom.resi];
80178
79980
 
80179
- pnts.push(atom.coord);
79981
+ let offsetStart = (bMissingStart) ? half : 0;
79982
+ let offsetEnd = (bMissingEnd) ? half : 0;
80180
79983
 
80181
- let radiusFinal;
80182
- if(bCustom) {
80183
- radiusFinal = this.getCustomtubesize(atom.structure + '_' + atom.chain + '_' + atom.resi);
80184
- }
80185
- else {
80186
- radiusFinal = this.getRadius(radius, atom);
79984
+ let indexArray = ic.strandCls.pos2IndexArray(pos, pntsCAAllSub);
79985
+ for(let j = offsetEnd, jl = indexArray.length - offsetStart; j < jl; ++j) {
79986
+ pnts.push(pntsCAAllSub[indexArray[j]]);
79987
+ colors.push(colorsAllSub[indexArray[j]]);
79988
+ radii.push(ic.coilWidth);
79989
+ }
80187
79990
  }
80188
-
80189
- // draw all atoms in tubes and assign zero radius when the residue is not coil
80190
- // if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
79991
+ else { // b factor, etc
79992
+ pnts.push(atom.coord);
80191
79993
 
80192
- //radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
80193
- radii.push(radiusFinal);
79994
+ let radiusFinal;
79995
+ if(bCustom) {
79996
+ radiusFinal = this.getCustomtubesize(atom.structure + '_' + atom.chain + '_' + atom.resi);
79997
+ }
79998
+ else {
79999
+ radiusFinal = this.getRadius(radius, atom);
80000
+ }
80001
+
80002
+ radii.push(radiusFinal);
80194
80003
 
80195
- colors.push(atom.color);
80196
- // the starting residue of a coil uses the color from the next residue to avoid using the color of the last helix/sheet residue
80197
- if(index === 1) colors[colors.length - 2] = atom.color;
80004
+ colors.push(atom.color);
80005
+ // the starting residue of a coil uses the color from the next residue to avoid using the color of the last helix/sheet residue
80006
+ if(index === 1) colors[colors.length - 2] = atom.color;
80007
+ }
80198
80008
 
80199
80009
  currentChain = atom.chain;
80200
80010
  currentResi = atom.resi;
@@ -80207,170 +80017,82 @@ class Tube {
80207
80017
  ++index;
80208
80018
 
80209
80019
  prevAtom = atom;
80020
+ prevPos = pos;
80210
80021
  }
80211
80022
  }
80212
80023
 
80213
80024
  if(bHighlight !== 2) {
80214
- prevone = [];
80215
- if(firstAtom !== undefined && !isNaN(firstAtom.resi)) {
80216
- let prevoneResid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
80217
- let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
80218
- prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
80219
- }
80220
-
80221
- nexttwo = [];
80222
- if(atom !== undefined && !isNaN(atom.resi)) {
80223
- let nextoneResid = atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) + 1).toString();
80224
- let nexttwoResid = atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) + 2).toString();
80225
- let nextthreeResid = atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) + 3).toString();
80226
-
80227
- // add one more residue if only one residue is available
80228
- if(pnts.length == 1 && ic.residues.hasOwnProperty(nextoneResid)) {
80229
- let nextAtom = ic.firstAtomObjCls.getAtomFromResi(nextoneResid, atomName);
80230
-
80231
- if(nextAtom) {
80232
- pnts.push(nextAtom.coord);
80233
- colors.push(nextAtom.color);
80234
-
80235
- let radiusFinal = this.getRadius(radius, atom);
80236
- radii.push(radiusFinal);
80237
-
80238
- nextoneResid = nexttwoResid;
80239
- nexttwoResid = nextthreeResid;
80025
+ if(tubePosArray) {
80026
+ if(prevAtom) {
80027
+ let bMissingEnd = ic.missingResEnd[prevAtom.structure + '_' + prevAtom.chain + '_' + prevAtom.resi];
80028
+ if(bMissingEnd) {
80029
+ pnts.splice(-half);
80030
+ colors.splice(-half);
80031
+ radii.splice(-half);
80240
80032
  }
80241
- }
80242
80033
 
80243
- let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
80244
- if(nextoneCoord !== undefined) {
80245
- nexttwo.push(nextoneCoord);
80246
- }
80034
+ let result = this.closeSegment(firstAtom, firstPos, prevAtom, prevPos, pnts, colors, radii, pntsCAAllSub);
80247
80035
 
80248
- let nexttwoCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nexttwoResid, atomName);
80249
- if(nexttwoCoord !== undefined) {
80250
- nexttwo.push(nexttwoCoord);
80036
+ pnts_colors_radii.push(result);
80251
80037
  }
80252
80038
  }
80253
-
80254
- pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
80039
+ else {
80040
+ pnts_colors_radii.push({'pnts':pnts, 'colors':colors, 'radii':radii});
80041
+ }
80255
80042
  }
80256
80043
 
80257
- for(let i = 0, il = pnts_colors_radii_prevone_nexttwo.length; i < il; ++i) {
80258
- let pnts = pnts_colors_radii_prevone_nexttwo[i].pnts;
80259
- let colors = pnts_colors_radii_prevone_nexttwo[i].colors;
80260
- let radii = pnts_colors_radii_prevone_nexttwo[i].radii;
80261
- let prevone = pnts_colors_radii_prevone_nexttwo[i].prevone;
80262
- let nexttwo = pnts_colors_radii_prevone_nexttwo[i].nexttwo;
80044
+ for(let i = 0, il = pnts_colors_radii.length; i < il; ++i) {
80045
+ let pnts = pnts_colors_radii[i].pnts;
80046
+ let colors = pnts_colors_radii[i].colors;
80047
+ let radii = pnts_colors_radii[i].radii;
80263
80048
 
80264
- this.createTubeSub(pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil);
80049
+ this.createTubeSub(pnts, colors, radii, bHighlight, bNonCoil);
80265
80050
  }
80266
80051
 
80267
- pnts_colors_radii_prevone_nexttwo = [];
80052
+ pnts_colors_radii = [];
80268
80053
  }
80269
80054
 
80270
- /*
80271
- createTube(atoms, atomName, radius, bHighlight, bCustom, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
80272
- if(me.bNode) return;
80273
-
80274
- let pnts = [], colors = [], radii = [], prevone = [], nexttwo = [];
80275
- let currentChain, currentResi;
80276
- let index = 0;
80277
- let maxDist = 6.0;
80278
- let maxDist2 = 3.0; // avoid tube between the residues in 3 residue helix
80279
-
80280
- let pnts_colors_radii_prevone_nexttwo = [];
80281
- let firstAtom, atom, prevAtom;
80282
-
80283
- for (let i in atoms) {
80284
- atom = atoms[i];
80285
- if ((atom.name === atomName) && !atom.het) {
80286
- if(index == 0) {
80287
- firstAtom = atom;
80288
- }
80289
-
80290
- 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
80291
- || (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))
80292
- ) ) {
80293
- if(bHighlight !== 2) {
80294
- if(!isNaN(firstAtom.resi) && !isNaN(prevAtom.resi)) {
80295
- let prevoneResid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
80296
- let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
80297
- prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
80298
-
80299
- let nextoneResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 1).toString();
80300
-
80301
- // add one more residue if only one residue is available
80302
- if(pnts.length == 1 && ic.residues.hasOwnProperty(nextoneResid)) {
80303
- let nextAtom = ic.firstAtomObjCls.getAtomFromResi(nextoneResid, atomName);
80304
-
80305
- if(nextAtom) {
80306
- pnts.push(nextAtom.coord);
80307
- colors.push(nextAtom.color);
80308
-
80309
- let radiusFinal = this.getRadius(radius, atom);
80310
- radii.push(radiusFinal);
80311
- }
80312
- }
80313
-
80314
- }
80315
-
80316
- pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
80317
- }
80318
- pnts = []; colors = []; radii = []; prevone = []; nexttwo = [];
80319
- firstAtom = atom;
80320
- index = 0;
80321
- }
80322
-
80323
- pnts.push(atom.coord);
80324
-
80325
- let radiusFinal;
80326
- if(bCustom) {
80327
- radiusFinal = this.getCustomtubesize(atom.structure + '_' + atom.chain + '_' + atom.resi);
80328
- }
80329
- else {
80330
- radiusFinal = this.getRadius(radius, atom);
80331
- }
80055
+ closeSegment(firstAtom, firstPos, prevAtom, prevPos, pnts, colors, radii, pntsCAAllSub) { let ic = this.icn3d; ic.icn3dui;
80056
+ if (pnts.length === 0) return {'pnts': [], 'colors': [], 'radii': []};
80332
80057
 
80333
- // draw all atoms in tubes and assign zero radius when the residue is not coil
80334
- if(!bNonCoil && atom.ss != 'coil' && !atom.ssbegin && !atom.ssend ) radiusFinal = 0;
80058
+ let extra = 1; // extend the tube by 5 sub-points into a preceding/following helix/sheet
80335
80059
 
80336
- //radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
80337
- radii.push(radiusFinal);
80060
+ // extend backward by one sub-point into a preceding helix/sheet
80061
+ if (!isNaN(firstAtom.resi)) {
80062
+ if(firstAtom.style == 'strand') extra = 0;
80338
80063
 
80339
- colors.push(atom.color);
80340
- // the starting residue of a coil uses the color from the next residue to avoid using the color of the last helix/sheet residue
80341
- if(index === 1) colors[colors.length - 2] = atom.color;
80064
+ let resid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1);
80065
+ let before = ic.residues.hasOwnProperty(resid) ? ic.firstAtomObjCls.getAtomFromResi(resid, 'CA') : undefined;
80342
80066
 
80343
- currentChain = atom.chain;
80344
- currentResi = atom.resi;
80345
-
80346
- let scale = 1.2;
80347
- if(bHighlight === 2 && !atom.ssbegin) {
80348
- ic.boxCls.createBox(atom, undefined, undefined, scale, undefined, bHighlight);
80067
+ for(let i = 1, il = extra + 1; i < il; ++i) {
80068
+ let idx = ic.strandCls.pos2IndexArray(firstPos, pntsCAAllSub)[0] - i;
80069
+ if (before && (before.ssbegin || before.ssend) && idx >= 0) {
80070
+ pnts.unshift(pntsCAAllSub[idx]);
80071
+ colors.unshift(colors[0]); // keep the coil color
80072
+ radii.unshift(radii[0]);
80349
80073
  }
80350
-
80351
- ++index;
80352
-
80353
- prevAtom = atom;
80354
80074
  }
80355
80075
  }
80356
80076
 
80357
- if(bHighlight !== 2) {
80358
- pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
80359
- }
80360
-
80361
- for(let i = 0, il = pnts_colors_radii_prevone_nexttwo.length; i < il; ++i) {
80362
- let pnts = pnts_colors_radii_prevone_nexttwo[i].pnts;
80363
- let colors = pnts_colors_radii_prevone_nexttwo[i].colors;
80364
- let radii = pnts_colors_radii_prevone_nexttwo[i].radii;
80365
- let prevone = []; // = pnts_colors_radii_prevone_nexttwo[i].prevone;
80366
- let nexttwo = []; // = pnts_colors_radii_prevone_nexttwo[i].nexttwo;
80077
+ // extend forward by one sub-point into a following helix/sheet
80078
+ if (!isNaN(prevAtom.resi)) {
80079
+ if(prevAtom.style == 'strand') extra = 0;
80367
80080
 
80368
- this.createTubeSub(pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil);
80081
+ let resid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 1);
80082
+ let after = ic.residues.hasOwnProperty(resid) ? ic.firstAtomObjCls.getAtomFromResi(resid, 'CA') : undefined;
80083
+ let arr = ic.strandCls.pos2IndexArray(prevPos, pntsCAAllSub);
80084
+ for(let i = 1, il = extra + 1; i < il; ++i) {
80085
+ let idx = arr[arr.length - 1] + i;
80086
+ if (after && (after.ssbegin || after.ssend) && idx < pntsCAAllSub.length) {
80087
+ pnts.push(pntsCAAllSub[idx]);
80088
+ colors.push(colors[colors.length - 1]);
80089
+ radii.push(radii[radii.length - 1]);
80090
+ }
80091
+ }
80369
80092
  }
80370
80093
 
80371
- pnts_colors_radii_prevone_nexttwo = [];
80094
+ return {'pnts': pnts, 'colors': colors, 'radii': radii};
80372
80095
  }
80373
- */
80374
80096
 
80375
80097
  getCustomtubesize(resid) { let ic = this.icn3d; ic.icn3dui;
80376
80098
  let pos = resid.lastIndexOf('_');
@@ -80383,11 +80105,11 @@ class Tube {
80383
80105
  };
80384
80106
 
80385
80107
  // modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
80386
- createTubeSub(_pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
80108
+ createTubeSub(_pnts, colors, radii, bHighlight, bNonCoil) { let ic = this.icn3d, me = ic.icn3dui;
80387
80109
  if(me.bNode) return;
80388
80110
 
80389
80111
  if (_pnts.length < 2) return;
80390
-
80112
+
80391
80113
  let circleDiv = ic.tubeDIV, axisDiv = ic.axisDIV;
80392
80114
  let circleDivInv = 1 / circleDiv, axisDivInv = 1 / axisDiv;
80393
80115
  //var geo = new THREE.Geometry();
@@ -80395,10 +80117,19 @@ class Tube {
80395
80117
  let verticeArray = [], colorArray = [],indexArray = [], color;
80396
80118
  let offset = 0, offset2 = 0, offset3 = 0;
80397
80119
 
80398
- let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv, undefined, undefined, prevone, nexttwo);
80120
+ let pnts;
80121
+ /*
80122
+ if(!bSubdivided) {
80123
+ let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv);
80399
80124
 
80400
- let pnts = pnts_clrs[0];
80401
- colors = pnts_clrs[2];
80125
+ pnts = pnts_clrs[0];
80126
+ colors = pnts_clrs[2];
80127
+ }
80128
+ else {
80129
+ pnts = _pnts;
80130
+ }
80131
+ */
80132
+ pnts = _pnts;
80402
80133
 
80403
80134
  let constRadiius;
80404
80135
  // a threshold to stop drawing the tube if it's less than this ratio of radius
@@ -80436,6 +80167,7 @@ class Tube {
80436
80167
  }
80437
80168
  }
80438
80169
  }
80170
+
80439
80171
  let delta, axis1, axis2;
80440
80172
  if (i < lim - 1) {
80441
80173
  delta = pnts[i].clone().sub(pnts[i + 1]);
@@ -80615,29 +80347,31 @@ class Strand {
80615
80347
  coilWidth = coilWidth || ic.coilWidth;
80616
80348
  doNotSmoothen = doNotSmoothen || false;
80617
80349
  helixSheetWidth = helixSheetWidth || ic.helixSheetWidth;
80618
- let pnts = {}; for (let k = 0; k < num; ++k) pnts[k] = [];
80619
- let pntsCA = [];
80620
- let prevCOArray = [];
80621
- let bShowArray = [];
80622
- let calphaIdArray = []; // used to store one of the final positions drawn in 3D
80623
- let colors = [];
80624
- let currentChain, currentStyle, currentCA = null, currentO = null, currentColor = null, prevCoorCA = null, prevCoorO = null, prevColor = null;
80625
- let prevCO = null, ss = null, ssend = false, atomid = null, prevAtomid = null, prevResi = null, calphaid = null, prevCalphaid = null;
80626
- let strandWidth, bSheetSegment = false, bHelixSegment = false;
80627
- let atom, tubeAtoms = {};
80628
80350
 
80629
80351
  // test the first 30 atoms to see whether only C-alpha is available
80630
80352
  ic.bCalphaOnly = me.utilsCls.isCalphaPhosOnly(atomsAdjust); //, 'CA');
80631
80353
 
80632
- // when highlight, draw whole beta sheet and use bShowArray to show the highlight part
80633
- let residueHash = {};
80354
+ // get chains
80355
+ let chainidHash = {};
80634
80356
  for(let i in atomsAdjust) {
80635
- let atom = atomsAdjust[i];
80636
-
80637
- let residueid = atom.structure + '_' + atom.chain + '_' + atom.resi;
80638
- residueHash[residueid] = 1;
80357
+ let atom = ic.atoms[i];
80358
+ let chainid = atom.structure + '_' + atom.chain;
80359
+ chainidHash[chainid] = 1;
80639
80360
  }
80640
- let totalResidueCount = Object.keys(residueHash).length;
80361
+
80362
+ for(let chainid in chainidHash) {
80363
+ let pntsAll = {}; for (let k = 0; k < num; ++k) pntsAll[k] = [];
80364
+ let pntsAllSub = {}; for (let k = 0; k < num; ++k) pntsAllSub[k] = [];
80365
+ let pntsCAAll = [], posArray = [], tubePosArray = [], missingResArray = [];
80366
+ let prevCOArrayAll = [];
80367
+ let colorsAll = [];
80368
+
80369
+ let pntsCAAllSub = [], prevCOArrayAllSub = [], positionsSub = [], colorsAllSub = [];
80370
+
80371
+ let currentChain, currentStyle, currentCA = null, currentColor = null, prevCoorCA = null, prevCoorO = null, prevColor = null;
80372
+ let prevCO = null, ss = null, ssend = false, ssJoint = false, prevResi = null, prevResid = null;
80373
+ let strandWidth, bSheetSegment = false, bHelixSegment = false;
80374
+ let atom, tubeAtoms = [];
80641
80375
 
80642
80376
  let drawnResidueCount = 0;
80643
80377
 
@@ -80645,64 +80379,56 @@ class Strand {
80645
80379
 
80646
80380
  let caArray = []; // record all C-alpha atoms to predict the helix
80647
80381
 
80648
- for (let i in atomsAdjust) {
80649
- atom = atomsAdjust[i];
80650
- if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
80651
- // "CA" has to appear before "O"
80382
+ let chainAtoms = me.hashUtilsCls.intHash(ic.chains[chainid], atomsAdjust);
80652
80383
 
80653
- if (atom.name === 'CA') {
80654
- if ( atoms.hasOwnProperty(i) && ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) ) {
80655
- tubeAtoms[i] = atom;
80656
- }
80384
+ let residueArray = ic.resid2specCls.atoms2residues(Object.keys(chainAtoms));
80385
+ let totalResidueCount = residueArray.length;
80386
+
80387
+ let index = 0;
80388
+
80389
+ // get pntsAll, pntsCAAll, prevCOArrayAll, colorsAll
80390
+ // get the subdivided points for all atoms
80391
+ let resi2pos = {};
80392
+ for (let i in ic.chains[chainid]) {
80393
+ atom = ic.atoms[i];
80657
80394
 
80395
+ if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
80396
+ if (atom.name === 'CA') {
80658
80397
  currentCA = atom.coord;
80659
80398
  currentColor = atom.color;
80660
- calphaid = atom.serial;
80661
-
80662
80399
  caArray.push(atom.serial);
80663
80400
  }
80664
80401
 
80665
80402
  if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA')) {
80403
+ ++index;
80404
+
80666
80405
  if(currentCA === null || currentCA === undefined) {
80667
80406
  currentCA = atom.coord;
80668
80407
  currentColor = atom.color;
80669
- calphaid = atom.serial;
80670
- }
80671
-
80672
- if(atom.name === 'O') {
80673
- currentO = atom.coord;
80674
- }
80675
- // smoothen each coil, helix and sheet separately. The joint residue has to be included both in the previous and next segment
80676
- let bSameChain = true;
80677
-
80678
- if (currentChain !== atom.chain) {
80679
- bSameChain = false;
80680
- }
80681
-
80682
- if((atom.ssend || currentStyle != atom.style)&& atom.ss === 'sheet') {
80683
- bSheetSegment = true;
80684
- }
80685
- else if((atom.ssend || currentStyle != atom.style) && atom.ss === 'helix') {
80686
- bHelixSegment = true;
80687
80408
  }
80688
80409
 
80689
80410
  // assign the previous residue
80690
80411
  if(prevCoorO) {
80691
- if(bHighlight === 1 || bHighlight === 2) {
80692
- colors.push(ic.hColor);
80412
+ // posArray.push(index - 1 - 1);
80413
+ resi2pos[prevResi] = index - 1 - 1;
80414
+
80415
+ /*
80416
+ strandWidth = (ss === 'coil') ? coilWidth : helixSheetWidth;
80417
+
80418
+ if(ss == 'sheet' && atom.ss == 'sheet' && atom.ssend) { // a transition between two sheets
80419
+ strandWidth = 1.8 * helixSheetWidth;
80693
80420
  }
80694
- else {
80695
- colors.push(prevColor);
80421
+ else if(ss == 'sheet' && ssend && atom.ss == 'coil') { // a transition between two ss
80422
+ strandWidth = 0;
80696
80423
  }
80424
+ */
80425
+ strandWidth = helixSheetWidth;
80697
80426
 
80698
- if(ss !== 'coil' && atom.ss === 'coil') {
80699
- strandWidth = coilWidth;
80700
- }
80701
- else if(ssend && atom.ssbegin) { // a transition between two ss
80702
- strandWidth = coilWidth;
80427
+ if(bHighlight === 1 || bHighlight === 2) {
80428
+ colorsAll.push(ic.hColor);
80703
80429
  }
80704
80430
  else {
80705
- strandWidth = (ss === 'coil') ? coilWidth : helixSheetWidth;
80431
+ colorsAll.push(prevColor);
80706
80432
  }
80707
80433
 
80708
80434
  let O, oldCA, resSpan = 4;
@@ -80744,239 +80470,161 @@ class Strand {
80744
80470
  for (let j = 0, numM1Inv2 = 2 / (num - 1); j < num; ++j) {
80745
80471
  let delta = -1 + numM1Inv2 * j;
80746
80472
  let v = new Vector3$1(prevCoorCA.x + prevCO.x * delta, prevCoorCA.y + prevCO.y * delta, prevCoorCA.z + prevCO.z * delta);
80747
- if (!doNotSmoothen && ss === 'sheet') v.smoothen = true;
80748
- pnts[j].push(v);
80473
+ // no smoothen for the last two residues in sheet
80474
+ if (!doNotSmoothen && ss === 'sheet' && !ssJoint && !(atom.ssend)) v.smoothen = true;
80475
+ pntsAll[j].push(v);
80749
80476
  }
80750
80477
 
80751
- pntsCA.push(prevCoorCA);
80752
- prevCOArray.push(prevCO);
80478
+ pntsCAAll.push(prevCoorCA);
80479
+ prevCOArrayAll.push(prevCO);
80480
+ }
80753
80481
 
80754
- if(atoms.hasOwnProperty(prevAtomid)) {
80755
- bShowArray.push(prevResi);
80756
- calphaIdArray.push(prevCalphaid);
80757
- }
80758
- else {
80759
- bShowArray.push(0);
80760
- calphaIdArray.push(0);
80761
- }
80482
+ // only update when atom.name === 'O'
80483
+ prevResi = atom.resi;
80762
80484
 
80763
- ++drawnResidueCount;
80764
- }
80485
+ prevCoorCA = currentCA;
80486
+ prevCoorO = atom.coord;
80487
+ prevColor = currentColor;
80765
80488
 
80766
- let maxDist = 6.0;
80767
- 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);
80768
- // The following code didn't work to select one residue
80769
- // 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);
80489
+ ss = atom.ss;
80490
+ ssend = atom.ssend;
80491
+ ssJoint = atom.ssbegin || atom.ssend;
80492
+ } // end if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA') ) {
80493
+ } // end if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
80494
+ } // end for
80770
80495
 
80771
- // if(bBrokenSs && atom.ss === 'sheet') {
80772
- // bSheetSegment = true;
80773
- // }
80774
- // else if(bBrokenSs && atom.ss === 'helix') {
80775
- // bHelixSegment = true;
80776
- // }
80496
+ // add the last residue
80497
+ // posArray.push(index - 1);
80498
+ resi2pos[prevResi] = index - 1;
80777
80499
 
80778
- if ((atom.ssbegin || atom.ssend || (drawnResidueCount === totalResidueCount - 1) || bBrokenSs || currentStyle != atom.style) && pnts[0].length > 0 && bSameChain) {
80779
- let atomName = 'CA';
80500
+ colorsAll.push(prevColor);
80501
+ for (let j = 0, numM1Inv2 = 2 / (num - 1); j < num; ++j) {
80502
+ let delta = -1 + numM1Inv2 * j;
80503
+ let v = new Vector3$1(prevCoorCA.x + prevCO.x * delta, prevCoorCA.y + prevCO.y * delta, prevCoorCA.z + prevCO.z * delta);
80504
+ // no smoothen for the last two residues in sheet
80505
+ if (!doNotSmoothen && ss === 'sheet' && !ssJoint && !(ssend)) v.smoothen = true;
80506
+ pntsAll[j].push(v);
80507
+ }
80508
+ pntsCAAll.push(prevCoorCA);
80509
+ prevCOArrayAll.push(prevCO);
80780
80510
 
80781
- let prevone = [], nexttwo = [];
80511
+ // each point except the last one are divided into div segments. The last point is not divided.
80512
+ let pnts_clrs;
80513
+ for(let i = 0; i < num; ++i) {
80514
+ pnts_clrs = me.subdivideCls.subdivide(pntsAll[i], colorsAll, div);
80515
+ pntsAllSub[i] = pnts_clrs[0];
80516
+ }
80782
80517
 
80783
- if(isNaN(ic.atoms[prevAtomid].resi)) {
80784
- prevone = [];
80785
- }
80786
- else {
80787
- let prevoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) - 1).toString();
80788
- let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
80789
- prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
80790
- }
80518
+ pnts_clrs = me.subdivideCls.subdivide(pntsCAAll, colorsAll, div);
80519
+ pntsCAAllSub = pnts_clrs[0];
80520
+ colorsAllSub = pnts_clrs[2];
80521
+
80522
+ pnts_clrs = me.subdivideCls.subdivide(prevCOArrayAll, colorsAll, div);
80523
+ prevCOArrayAllSub = pnts_clrs[0];
80524
+ positionsSub = pnts_clrs[1];
80791
80525
 
80792
- if(!isNaN(ic.atoms[prevAtomid].resi)) {
80793
- let nextoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) + 1).toString();
80794
- let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
80795
- if(nextoneCoord !== undefined) {
80796
- nexttwo.push(nextoneCoord);
80797
- }
80526
+ posArray = [];
80527
+ prevCoorO = null;
80528
+ prevCoorCA = null;
80529
+ ss = null;
80530
+ ssend = false;
80531
+ ssJoint = false;
80798
80532
 
80799
- let nexttwoResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) + 2).toString();
80800
- let nexttwoCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nexttwoResid, atomName);
80801
- if(nexttwoCoord !== undefined) {
80802
- nexttwo.push(nexttwoCoord);
80803
- }
80804
- }
80533
+ index = 0;
80534
+ let bLastResDrawn = false;
80805
80535
 
80806
- if(!bBrokenSs) { // include the current residue
80807
- // assign the current joint residue to the previous segment
80808
- if(bHighlight === 1 || bHighlight === 2) {
80809
- colors.push(ic.hColor);
80810
- }
80811
- else {
80812
- //colors.push(atom.color);
80813
- colors.push(prevColor);
80814
- }
80536
+ // draw only for the selected atoms
80537
+ for (let i in chainAtoms) {
80538
+ atom = ic.atoms[i];
80539
+ if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
80540
+ // "CA" has to appear before "O"
80815
80541
 
80816
- if(atom.ssend && atom.ss === 'sheet') { // current residue is the end of ss and is the end of arrow
80817
- strandWidth = 0; // make the arrow end sharp
80818
- }
80819
- else if(ss === 'coil' && atom.ssbegin) {
80820
- strandWidth = coilWidth;
80821
- }
80822
- else if(ssend && atom.ssbegin) { // current residue is the start of ss and the previous residue is the end of ss, then use coil
80823
- strandWidth = coilWidth;
80824
- }
80825
- else { // use the ss from the previous residue
80826
- strandWidth = (atom.ss === 'coil') ? coilWidth : helixSheetWidth;
80827
- }
80542
+ if (atom.name === 'CA') {
80543
+ // if ( atoms.hasOwnProperty(i) && ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) ) {
80544
+ if ( atoms.hasOwnProperty(i) && ((atom.ss !== 'helix' && atom.ss !== 'sheet') ) ) {
80545
+ tubeAtoms.push(atom);
80546
+ let pos = resi2pos[atom.resi];
80547
+ tubePosArray.push(pos);
80828
80548
 
80829
- let O, oldCA, resSpan = 4;
80830
- if(atom.name === 'O') {
80831
- O = currentO.clone();
80832
- O.sub(currentCA);
80833
- }
80834
- else if(ic.bCalphaOnly && atom.name === 'CA') {
80835
- if(caArray.length > resSpan) { // use the calpha and the previous 4th c-alpha to calculate the helix direction
80836
- O = currentCA.clone();
80837
- oldCA = ic.atoms[caArray[caArray.length - 1 - resSpan]].coord.clone();
80838
- //O.sub(oldCA);
80839
- oldCA.sub(O);
80840
- }
80841
- else {
80842
- O = new Vector3$1(Math.random(),Math.random(),Math.random());
80843
- }
80844
- }
80549
+ continue;
80550
+ }
80551
+ }
80845
80552
 
80846
- O.normalize(); // can be omitted for performance
80847
- O.multiplyScalar(strandWidth);
80848
- if (prevCO !== null && O.dot(prevCO) < 0) O.negate();
80849
- prevCO = O;
80553
+ if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA')) {
80554
+ ++index;
80850
80555
 
80851
- for (let j = 0, numM1Inv2 = 2 / (num - 1); j < num; ++j) {
80852
- let delta = -1 + numM1Inv2 * j;
80853
- let v = new Vector3$1(currentCA.x + prevCO.x * delta, currentCA.y + prevCO.y * delta, currentCA.z + prevCO.z * delta);
80854
- if (!doNotSmoothen && ss === 'sheet') v.smoothen = true;
80855
- pnts[j].push(v);
80856
- }
80556
+ currentCA = atom.coord;
80857
80557
 
80858
- atomid = atom.serial;
80558
+ // smoothen each coil, helix and sheet separately. The joint residue has to be included both in the previous and next segment
80559
+ // if((atom.ssend || currentStyle != atom.style)&& atom.ss === 'sheet') {
80560
+ // bSheetSegment = true;
80561
+ // }
80562
+ // else if((atom.ssend || currentStyle != atom.style) && atom.ss === 'helix') {
80563
+ // bHelixSegment = true;
80564
+ // }
80565
+ if(atom.ss === 'sheet') {
80566
+ bSheetSegment = true;
80567
+ bHelixSegment = false;
80568
+ }
80569
+ else if(atom.ss === 'helix') {
80570
+ bSheetSegment = false;
80571
+ bHelixSegment = true;
80572
+ }
80573
+ else {
80574
+ bSheetSegment = false;
80575
+ bHelixSegment = false;
80576
+ }
80859
80577
 
80860
- pntsCA.push(currentCA);
80861
- prevCOArray.push(prevCO);
80578
+ // assign the previous residue
80579
+ if(prevCoorO) {
80580
+ //pntsCA.push(prevCoorCA);
80581
+ //prevCOArray.push(prevCO);
80582
+ let pos = resi2pos[prevResi];
80583
+ // posArray.push(index - 1 - 1);
80584
+ posArray.push(pos);
80862
80585
 
80863
- // 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.
80864
- //if(atoms.hasOwnProperty(atomid) && (bHighlight === 1 && !atom.notshow) ) {
80865
- if(atoms.hasOwnProperty(atomid)) {
80866
- bShowArray.push(atom.resi);
80867
- calphaIdArray.push(calphaid);
80868
- }
80869
- else {
80870
- bShowArray.push(0);
80871
- calphaIdArray.push(0);
80872
- }
80873
- }
80586
+ let bMissingStart = ic.missingResStart[prevResid];
80587
+ let bMissingEnd = ic.missingResEnd[prevResid];
80588
+ let missingResType = bMissingStart ? 1 : (bMissingEnd ? 2 : 0);
80589
+ missingResArray.push(missingResType);
80874
80590
 
80875
- // draw the current segment
80876
- for (let j = 0; !fill && j < num; ++j) {
80877
- if(bSheetSegment) {
80878
- ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
80879
- }
80880
- else if(bHelixSegment) {
80881
- if(bFullAtom) {
80882
- ic.curveCls.createCurveSub(pnts[j], 1, colors, div, bHighlight, bRibbon, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo);
80883
- }
80884
- else {
80885
- ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
80886
- }
80887
- }
80888
- }
80889
- if (fill) {
80890
- if(bSheetSegment) {
80891
- let start = 0, end = num - 1;
80892
- ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
80893
- }
80894
- else if(bHelixSegment) {
80895
- if(bFullAtom) {
80896
- ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
80897
- }
80898
- else {
80899
- let start = 0, end = num - 1;
80900
- ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
80901
- }
80902
- }
80903
- else {
80904
- if(bHighlight === 2) { // draw coils only when highlighted. if not highlighted, coils will be drawn as tubes separately
80905
- ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
80906
- }
80907
- }
80908
- }
80909
- for (let k = 0; k < num; ++k) pnts[k] = [];
80591
+ ++drawnResidueCount;
80592
+ }
80910
80593
 
80911
- colors = [];
80912
- pntsCA = [];
80913
- prevCOArray = [];
80914
- bShowArray = [];
80915
- calphaIdArray = [];
80916
- bSheetSegment = false;
80917
- bHelixSegment = false;
80918
- } // end if (atom.ssbegin || atom.ssend)
80594
+ let maxDist = 6.0;
80595
+ 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);
80919
80596
 
80920
- // end of a chain
80921
- if ((currentChain !== atom.chain || currentStyle != atom.style) && pnts[0].length > 0) {
80922
- let atomName = 'CA';
80597
+ // check for the last atom
80598
+ if ((atom.ssbegin || atom.ssend || bBrokenSs || currentStyle != atom.style || currentChain !== atom.chain) ) {
80599
+ // && posArray.length > 0) {
80600
+ if(!bBrokenSs) { // include the current residue
80601
+ if(drawnResidueCount === totalResidueCount - 1) bLastResDrawn = true;
80923
80602
 
80924
- let prevone = [], nexttwo = [];
80925
- if(isNaN(ic.atoms[prevAtomid].resi)) {
80926
- prevone = [];
80927
- }
80928
- else {
80929
- let prevoneResid = ic.atoms[prevAtomid].structure + '_' + ic.atoms[prevAtomid].chain + '_' + (parseInt(ic.atoms[prevAtomid].resi) - 1).toString();
80930
- ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
80931
- }
80603
+ let pos = resi2pos[atom.resi];
80604
+ // posArray.push(index - 1);
80605
+ posArray.push(pos);
80932
80606
 
80933
- for (let j = 0; !fill && j < num; ++j) {
80934
- if(bSheetSegment) {
80935
- ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
80936
- }
80937
- else if(bHelixSegment) {
80938
- if(bFullAtom) {
80939
- ic.curveCls.createCurveSub(pnts[j], 1, colors, div, bHighlight, bRibbon, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo);
80940
- }
80941
- else {
80942
- ic.curveStripArrowCls.createCurveSubArrow(pnts[j], 1, colors, div, bHighlight, bRibbon, num, j, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
80943
- }
80944
- }
80945
- }
80946
- if (fill) {
80947
- if(bSheetSegment) {
80948
- let start = 0, end = num - 1;
80949
- ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, true, prevone, nexttwo);
80950
- }
80951
- else if(bHelixSegment) {
80952
- if(bFullAtom) {
80953
- ic.stripCls.createStrip(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, false, bShowArray, calphaIdArray, undefined, prevone, nexttwo, pntsCA, prevCOArray);
80954
- }
80955
- else {
80956
- let start = 0, end = num - 1;
80957
- ic.curveStripArrowCls.createStripArrow(pnts[0], pnts[num - 1], colors, div, thickness, bHighlight, num, start, end, pntsCA, prevCOArray, bShowArray, calphaIdArray, false, prevone, nexttwo);
80958
- }
80959
- }
80607
+ let bMissingStart = ic.missingResStart[atom.structure + '_' + atom.chain + '_' + atom.resi];
80608
+ let bMissingEnd = ic.missingResEnd[atom.structure + '_' + atom.chain + '_' + atom.resi];
80609
+ let missingResType = bMissingStart ? 1 : (bMissingEnd ? 2 : 0);
80610
+ missingResArray.push(missingResType);
80960
80611
  }
80961
80612
 
80962
- for (let k = 0; k < num; ++k) pnts[k] = [];
80963
- colors = [];
80964
- pntsCA = [];
80965
- prevCOArray = [];
80966
- bShowArray = [];
80967
- calphaIdArray = [];
80968
- bSheetSegment = false;
80969
- bHelixSegment = false;
80970
- }
80613
+ bSheetSegment = prevCoorO ? (ss === 'sheet') : (atom.ss === 'sheet');
80614
+ bHelixSegment = prevCoorO ? (ss === 'helix') : (atom.ss === 'helix');
80615
+ this.createStrand_base(posArray, pntsAllSub, pntsCAAllSub, prevCOArrayAllSub, colorsAllSub, positionsSub, missingResArray, fill, bHighlight, bRibbon, num, bSheetSegment, bHelixSegment, bFullAtom, thickness);
80616
+ posArray = [];
80617
+ missingResArray = [];
80618
+ } // end if (atom.ssbegin || atom.ssend)
80971
80619
 
80972
80620
  currentChain = atom.chain;
80973
80621
  currentStyle = atom.style;
80974
80622
  ss = atom.ss;
80975
80623
  ssend = atom.ssend;
80976
- prevAtomid = atom.serial;
80624
+ atom.serial;
80977
80625
  prevResi = atom.resi;
80978
80626
 
80979
- prevCalphaid = calphaid;
80627
+ prevResid = atom.structure + '_' + atom.chain + '_' + atom.resi;
80980
80628
 
80981
80629
  // only update when atom.name === 'O'
80982
80630
  prevCoorCA = currentCA;
@@ -80986,12 +80634,95 @@ class Strand {
80986
80634
  } // end if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
80987
80635
  } // end for
80988
80636
 
80637
+ // draw the last residue
80638
+ if(!bLastResDrawn && drawnResidueCount === totalResidueCount - 1) {
80639
+ let pos = resi2pos[prevResi];
80640
+ // posArray.push(index - 1);
80641
+ posArray.push(pos);
80642
+
80643
+ let bMissingStart = ic.missingResStart[prevResid];
80644
+ let bMissingEnd = ic.missingResEnd[prevResid];
80645
+ let missingResType = bMissingStart ? 1 : (bMissingEnd ? 2 : 0);
80646
+ missingResArray.push(missingResType);
80647
+
80648
+ bSheetSegment = prevCoorO ? (ss === 'sheet') : (atom.ss === 'sheet');
80649
+ bHelixSegment = prevCoorO ? (ss === 'helix') : (atom.ss === 'helix');
80650
+ this.createStrand_base(posArray, pntsAllSub, pntsCAAllSub, prevCOArrayAllSub, colorsAllSub, positionsSub, missingResArray, fill, bHighlight, bRibbon, num, bSheetSegment, bHelixSegment, bFullAtom, thickness);
80651
+ } // end if (atom.ssbegin || atom.ssend)
80652
+
80653
+ ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight, undefined, undefined, tubePosArray, pntsCAAllSub, colorsAllSub);
80654
+
80989
80655
  caArray = [];
80656
+ tubeAtoms = [];
80657
+ posArray = [];
80658
+ missingResArray = [];
80659
+ tubePosArray = [];
80660
+ pntsAll = {}, pntsCAAll = [], prevCOArrayAll = [], colorsAll = [];
80661
+ } // end for chainid in ic.chains
80662
+ }
80990
80663
 
80991
- ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight);
80664
+ createStrand_base(posArray, pntsAllSub, pntsCAAllSub, prevCOArrayAllSub, colorsAllSub, positionsSub, missingResArray, fill, bHighlight, bRibbon, num, bSheetSegment, bHelixSegment, bFullAtom, thickness) { let ic = this.icn3d; ic.icn3dui;
80665
+ let pntsCATmp = [], prevCOArrayTmp = [], colorsTmp = [], positionsTmp = [];
80666
+ let pntsTmp = {}; for (let k = 0; k < num; ++k) pntsTmp[k] = [];
80667
+ let half = Math.floor(ic.axisDIV / 2) - 1;
80992
80668
 
80993
- tubeAtoms = {};
80994
- pnts = {};
80669
+ for(let j = 0, jl = posArray.length; j < jl; ++j) {
80670
+ let pos = posArray[j];
80671
+ let missingResType = missingResArray[j];
80672
+
80673
+ let offsetStart = (missingResType == 1) ? half : 0;
80674
+ let offsetEnd = (missingResType == 2) ? half : 0;
80675
+
80676
+ let indexArray = this.pos2IndexArray(pos, pntsCAAllSub);
80677
+
80678
+ for(let k = offsetEnd, kl = indexArray.length - offsetStart; k < kl; ++k) {
80679
+ pntsCATmp.push(pntsCAAllSub[indexArray[k]]);
80680
+ prevCOArrayTmp.push(prevCOArrayAllSub[indexArray[k]]);
80681
+ colorsTmp.push(colorsAllSub[indexArray[k]]);
80682
+ positionsTmp.push(positionsSub[indexArray[k]]);
80683
+ }
80684
+
80685
+ for(let k = 0; k < num; ++k) {
80686
+ for(let l = 0, ll = indexArray.length; l < ll; ++l) {
80687
+ pntsTmp[k].push(pntsAllSub[k][indexArray[l]]);
80688
+ }
80689
+ }
80690
+ }
80691
+
80692
+ // draw the current segment
80693
+ for (let j = 0; !fill && j < num; ++j) {
80694
+ if(bSheetSegment) {
80695
+ ic.curveStripArrowCls.createCurveSubArrow(pntsTmp[j], 1, colorsTmp, 1, bHighlight, bRibbon, num, j, pntsCATmp, prevCOArrayTmp, positionsTmp, true);
80696
+ }
80697
+ else if(bHelixSegment) {
80698
+ if(bFullAtom) {
80699
+ ic.curveCls.createCurveSub(pntsTmp[j], 1, colorsTmp, 1, bHighlight, bRibbon, false, undefined);
80700
+ }
80701
+ else {
80702
+ ic.curveStripArrowCls.createCurveSubArrow(pntsTmp[j], 1, colorsTmp, 1, bHighlight, bRibbon, num, j, pntsCATmp, prevCOArrayTmp, positionsTmp, false);
80703
+ }
80704
+ }
80705
+ }
80706
+ if (fill) {
80707
+ if(bSheetSegment) {
80708
+ let start = 0, end = num - 1;
80709
+ ic.curveStripArrowCls.createStripArrow(pntsTmp[0], pntsTmp[num - 1], colorsTmp, 1, thickness, bHighlight, num, start, end, pntsCATmp, prevCOArrayTmp, positionsTmp, true);
80710
+ }
80711
+ else if(bHelixSegment) {
80712
+ if(bFullAtom) {
80713
+ ic.stripCls.createStrip(pntsTmp[0], pntsTmp[num - 1], colorsTmp, 1, thickness, bHighlight, false, undefined, pntsCATmp, prevCOArrayTmp);
80714
+ }
80715
+ else {
80716
+ let start = 0, end = num - 1;
80717
+ ic.curveStripArrowCls.createStripArrow(pntsTmp[0], pntsTmp[num - 1], colorsTmp, 1, thickness, bHighlight, num, start, end, pntsCATmp, prevCOArrayTmp, positionsTmp, false);
80718
+ }
80719
+ }
80720
+ else {
80721
+ if(bHighlight === 2) { // draw coils only when highlighted. if not highlighted, coils will be drawn as tubes separately
80722
+ ic.stripCls.createStrip(pntsTmp[0], pntsTmp[num - 1], colorsTmp, 1, thickness, bHighlight, false, undefined, pntsCATmp, prevCOArrayTmp);
80723
+ }
80724
+ }
80725
+ }
80995
80726
  }
80996
80727
 
80997
80728
  getSSExpandedAtoms(atoms, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
@@ -81016,7 +80747,7 @@ class Strand {
81016
80747
  else if(index === length - 1) {
81017
80748
  lastAtom = currAtom;
81018
80749
  }
81019
-
80750
+ /*
81020
80751
  // fill the beginning
81021
80752
  let beginResi = firstAtom.resi;
81022
80753
  if(!isNaN(firstAtom.resi) && firstAtom.ss !== 'coil' && !(firstAtom.ssbegin) ) {
@@ -81038,7 +80769,7 @@ class Strand {
81038
80769
  ic.atoms));
81039
80770
  }
81040
80771
  }
81041
-
80772
+ */
81042
80773
  // add one extra residue for coils between strands/helix if the style is NOT stick, ball and stick, lines, sphere, and dot
81043
80774
  // if(!isNaN(firstAtom.resi) && ic.pk === 3 && bHighlight === 1 && firstAtom.ss === 'coil') {
81044
80775
  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') {
@@ -81049,7 +80780,7 @@ class Strand {
81049
80780
  atoms = me.hashUtilsCls.unionHash(atoms, me.hashUtilsCls.hash2Atoms(ic.residues[residueid], ic.atoms));
81050
80781
  }
81051
80782
  }
81052
-
80783
+ /*
81053
80784
  // fill the end
81054
80785
  let endResi = lastAtom.resi;
81055
80786
  // 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.
@@ -81075,7 +80806,7 @@ class Strand {
81075
80806
  ic.atoms));
81076
80807
  }
81077
80808
  }
81078
-
80809
+ */
81079
80810
  // add one extra residue for coils between strands/helix if the style is NOT stick, ball and stick, lines, sphere, and dot
81080
80811
  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') {
81081
80812
  let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + (parseInt(lastAtom.resi) + 1).toString();
@@ -81101,6 +80832,32 @@ class Strand {
81101
80832
 
81102
80833
  return atomsAdjust;
81103
80834
  }
80835
+
80836
+ pos2IndexArray(pos, pntsCAAllSub) { let ic = this.icn3d; ic.icn3dui;
80837
+ let indexArray = [];
80838
+
80839
+ let offset = Math.floor(ic.axisDIV / 2) + 1; // first residue has floor(DIV/2)+1 points (8 when axisDIV = 15)
80840
+
80841
+ //subdivide() gives the first residue only floor(DIV/2)+1 points (8 when axisDIV = 15) and each later residue 15.
80842
+ if(pos == 0) {
80843
+ for(let j = 0; j < offset; ++j) {
80844
+ indexArray.push(j);
80845
+ }
80846
+ }
80847
+ else {
80848
+ for(let j = 0; j < ic.axisDIV; ++j) {
80849
+ let index = offset + (pos - 1) * ic.axisDIV + j;
80850
+ if(index >= pntsCAAllSub.length) {
80851
+ indexArray.push(pntsCAAllSub.length - 1);
80852
+ break;
80853
+ } else {
80854
+ indexArray.push(index);
80855
+ }
80856
+ }
80857
+ }
80858
+
80859
+ return indexArray;
80860
+ }
81104
80861
  }
81105
80862
 
81106
80863
  /**
@@ -85224,6 +84981,9 @@ class ApplyMissingRes {
85224
84981
  }
85225
84982
  }
85226
84983
 
84984
+ if(ic.missingResStart === undefined) ic.missingResStart = {};
84985
+ if(ic.missingResEnd === undefined) ic.missingResEnd = {};
84986
+
85227
84987
  for(let i = 0, il = misingResArray.length; i < il; i += 2) {
85228
84988
  let resid0 = misingResArray[i];
85229
84989
  let resid1 = misingResArray[i + 1];
@@ -85240,6 +85000,10 @@ class ApplyMissingRes {
85240
85000
  ic.missingResPnts[structure].push(resid0);
85241
85001
  ic.missingResPnts[structure].push(resid1);
85242
85002
 
85003
+ ic.missingResStart[resid0] = 1;
85004
+ ic.missingResEnd[resid1] = 1;
85005
+
85006
+
85243
85007
  ic.missingResResid2serial[resid0 + ',' + resid1] = atom0.serial;
85244
85008
  ic.missingResResid2serial[resid1 + ',' + resid0] = atom1.serial;
85245
85009
  }
@@ -85519,10 +85283,20 @@ class ApplyDisplay {
85519
85283
  ic.cylinderCls.createCylinderCurve(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), ['CA'], ic.traceRadius, false, bHighlight);
85520
85284
  }
85521
85285
  else if(style === 'b factor tube') {
85522
- ic.tubeCls.createTube(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), 'CA', null, bHighlight, false, true);
85286
+ let atomArray = [];
85287
+ for(let i in atomHash) {
85288
+ let atom = ic.atoms[i];
85289
+ atomArray.push(atom);
85290
+ }
85291
+ ic.tubeCls.createTube(atomArray, 'CA', null, bHighlight, false, true);
85523
85292
  }
85524
85293
  else if(style === 'custom tube') {
85525
- ic.tubeCls.createTube(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), 'CA', null, bHighlight, true, true);
85294
+ let atomArray = [];
85295
+ for(let i in atomHash) {
85296
+ let atom = ic.atoms[i];
85297
+ atomArray.push(atom);
85298
+ }
85299
+ ic.tubeCls.createTube(atomArray, 'CA', null, bHighlight, true, true);
85526
85300
  }
85527
85301
  else if(style === 'lines' || style === 'lines2') {
85528
85302
  if(bHighlight === 1) {
@@ -85833,7 +85607,7 @@ class ApplyOther {
85833
85607
  break;
85834
85608
  }
85835
85609
  else if(atom.name === 'CA' && (atom.ss == 'helix' || atom.ss == 'sheet')) { // protein secondary: CA
85836
- pos = (ic.atoms[i].coord2 !== undefined) ? ic.atoms[i].coord2 : ic.atoms[i].coord;
85610
+ pos = ic.atoms[i].coord;
85837
85611
  break;
85838
85612
  }
85839
85613
  }
@@ -105158,7 +104932,6 @@ class WebGLPathTracer {
105158
104932
  }
105159
104933
  else {
105160
104934
  if(bPathTracer) {
105161
- console.log("###pathTracer");
105162
104935
  ic.bImpo = false; // disable impostor for path tracing
105163
104936
  const pathTracer = new WebGLPathTracer(ic.renderer);
105164
104937
  pathTracer.setScene(ic.scene, cam);
@@ -131562,6 +131335,59 @@ class SetSeqAlign {
131562
131335
  ic.nconsHash2 = {};
131563
131336
  ic.nalignHash2 = {};
131564
131337
 
131338
+ let msaSameColor = [];
131339
+ // assume all aligned seq are the same. If any aligned res is different,set it to false (0)
131340
+ for(let i = 0, il = seqalign[0].length; i < il; ++i) {
131341
+ msaSameColor.push(1);
131342
+ }
131343
+
131344
+ for(let i = 0, il = seqalign.length; i < il; ++i) {
131345
+ // first sequence
131346
+ let alignData = seqalign[i][0];
131347
+ let molid1 = alignData.moleculeId;
131348
+
131349
+ let chain1 = ic.pdbid_molid2chain[mmdbid1 + '_' + molid1];
131350
+ chainid1 = mmdbid1 + '_' + chain1;
131351
+
131352
+ let id2aligninfo = {};
131353
+ let start = alignData.sequence.length, end = -1;
131354
+ let bStart = false;
131355
+ for(let j = 0, jl = alignData.sequence.length; j < jl; ++j) {
131356
+ // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
131357
+ let resi =(ic.bUsePdbNum) ? ic.ParserUtilsCls.getResi(chainid1, alignData.sequence[j][0] - 1) : alignData.sequence[j][0];
131358
+ let resn =(alignData.sequence[j][2] === '~') ? '-' : alignData.sequence[j][2];
131359
+ resn =(resn === ' ' || resn === '') ? 'X' : resn;
131360
+
131361
+ let aligned =(alignData.sequence[j][3]) ? 1 : 0;
131362
+
131363
+ if(aligned == 1) {
131364
+ if(j < start && !bStart) {
131365
+ start = j;
131366
+ bStart = true; // set start just once
131367
+ }
131368
+ if(j > end) end = j;
131369
+ }
131370
+
131371
+ id2aligninfo[j] = {"resi": resi, "resn": resn, "aligned": aligned};
131372
+ }
131373
+
131374
+ // second sequence
131375
+ alignData = seqalign[i][1];
131376
+
131377
+ for(let j = start; j <= end; ++j) {
131378
+ // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
131379
+ let alignedTmp =(alignData.sequence[j][3]) ? 1 : 0;
131380
+
131381
+ let aligned = id2aligninfo[j].aligned + alignedTmp; // 0 or 2
131382
+
131383
+ if(aligned === 2) { // aligned
131384
+ if(id2aligninfo[j].resn != resn) {
131385
+ msaSameColor[j] = 0;
131386
+ }
131387
+ }
131388
+ }
131389
+ }
131390
+
131565
131391
  for(let i = 0, il = seqalign.length; i < il; ++i) {
131566
131392
  // first sequence
131567
131393
  let alignData = seqalign[i][0];
@@ -131658,6 +131484,8 @@ class SetSeqAlign {
131658
131484
  ic.nconsHash2[chainid2 + '_' + resi] = 1;
131659
131485
  }
131660
131486
 
131487
+ color = (msaSameColor[j] == 0) ? '#0000FF' : '#FF0000';
131488
+
131661
131489
  // mapping, use the firstsequence as the reference structure
131662
131490
  ic.chainsMapping[chainid1][chainid1 + '_' + id2aligninfo[j].resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
131663
131491
  ic.chainsMapping[chainid2][chainid2 + '_' + resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
@@ -131674,6 +131502,8 @@ class SetSeqAlign {
131674
131502
 
131675
131503
  ic.nalignHash1[chainid1 + '_' + id2aligninfo[j].resi] = 1;
131676
131504
  ic.nalignHash2[chainid2 + '_' + resi] = 1;
131505
+
131506
+ msaSameColor[j] = 2; // not aligned
131677
131507
  }
131678
131508
 
131679
131509
  // chain1
@@ -132771,8 +132601,10 @@ class SetSeqAlign {
132771
132601
  ic.msaSeq[chainid2] += '-';
132772
132602
  }
132773
132603
  }
132774
-
132604
+ /*
132775
132605
  setSeqAlignForRealign(chainid_t, chainid, chainIndex) { let ic = this.icn3d, me = ic.icn3dui;
132606
+ //loadSeqAlignment
132607
+ let alignedAtoms = {};
132776
132608
  //var chainid_t = ic.chainidArray[0];
132777
132609
 
132778
132610
  // let structureArray = Object.keys(ic.structures);
@@ -132794,7 +132626,7 @@ class SetSeqAlign {
132794
132626
  ic.alnChains = {};
132795
132627
 
132796
132628
  ic.alnChainsSeq[chainid_t] = [];
132797
- ic.alnChains[chainid_t] = {};
132629
+ ic.alnChains[chainid_t] = {}
132798
132630
  ic.alnChainsAnno[chainid_t] = [];
132799
132631
  ic.alnChainsAnTtl[chainid_t] = [];
132800
132632
 
@@ -132872,8 +132704,8 @@ class SetSeqAlign {
132872
132704
  ic.alnChainsSeq[chainid1].push(resObject1);
132873
132705
  ic.alnChainsSeq[chainid2].push(resObject2);
132874
132706
 
132875
- if(ic.alnChains[chainid1] === undefined) ic.alnChains[chainid1] = {};
132876
- if(ic.alnChains[chainid2] === undefined) ic.alnChains[chainid2] = {};
132707
+ if(ic.alnChains[chainid1] === undefined) ic.alnChains[chainid1] = {}
132708
+ if(ic.alnChains[chainid2] === undefined) ic.alnChains[chainid2] = {}
132877
132709
  $.extend(ic.alnChains[chainid1], ic.residues[chainid1 + '_' + resObject1.resi] );
132878
132710
  $.extend(ic.alnChains[chainid2], ic.residues[chainid2 + '_' + resObject2.resi] );
132879
132711
 
@@ -132903,6 +132735,7 @@ class SetSeqAlign {
132903
132735
  let select = "select " + ic.resid2specCls.residueids2spec(Object.keys(residuesHash));
132904
132736
  ic.selectionCls.addCustomSelection(Object.keys(residuesHash), commandname, commanddescr, select, true);
132905
132737
  }
132738
+ */
132906
132739
 
132907
132740
  setSeqPerResi(chainid, chainid1, chainid2, resi, resn, bAligned, color, color2, classname, bFirstChain, bFirstResi, alignIndex) { let ic = this.icn3d, me = ic.icn3dui;
132908
132741
  if(ic.alnChainsSeq[chainid] === undefined) ic.alnChainsSeq[chainid] = [];
@@ -137220,16 +137053,6 @@ class ApplyCommand {
137220
137053
  let color = command.substr(command.lastIndexOf(' ') + 1);
137221
137054
  me.htmlCls.setMenuCls.setTheme(color);
137222
137055
  }
137223
- else if(command.indexOf('set double color') == 0) {
137224
- let value = command.substr(command.lastIndexOf(' ') + 1);
137225
- if(value == 'on') {
137226
- ic.bDoublecolor = true;
137227
- ic.setOptionCls.setStyle('proteins', 'ribbon');
137228
- }
137229
- else if(value == 'off') {
137230
- ic.bDoublecolor = false;
137231
- }
137232
- }
137233
137056
  else if(command.indexOf('adjust dialog') == 0) {
137234
137057
  let id = command.substr(command.lastIndexOf(' ') + 1);
137235
137058
  ic.scapCls.adjust2DWidth(id);
@@ -137696,7 +137519,6 @@ class ApplyCommand {
137696
137519
  else if(cmd.indexOf('replay on') !== -1) return 'File > Replay Each Step > On';
137697
137520
  else if(cmd.indexOf('replay off') !== -1) return 'File > Replay Each Step > Off';
137698
137521
  else if(cmd.indexOf('set theme') !== -1) return 'Style > Theme Color';
137699
- else if(cmd.indexOf('set double color') !== -1) return 'Style > Two-color Helix';
137700
137522
  else return '';
137701
137523
  }
137702
137524
  }
@@ -138814,6 +138636,17 @@ class LoadScript {
138814
138636
  nameArray = paraArray[1].split(',');
138815
138637
  ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(nameArray);
138816
138638
  }
138639
+ else {
138640
+ let structureHash = {};
138641
+
138642
+ for(let chainid in ic.chains) {
138643
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chainid]);
138644
+ if(!structureHash.hasOwnProperty(atom.structure) && (ic.proteins.hasOwnProperty(atom.serial) || ic.nucleotides.hasOwnProperty(atom.serial))) {
138645
+ nameArray.push(chainid);
138646
+ structureHash[atom.structure] = 1;
138647
+ }
138648
+ }
138649
+ }
138817
138650
 
138818
138651
  return nameArray;
138819
138652
  }
@@ -148927,24 +148760,31 @@ class Transform {
148927
148760
  }
148928
148761
  else { // |||pos:a,b,c|dir:a,b,c|up:a,b,c|fov:a
148929
148762
  let bcfArray = commandTransformation[1].split('|');
148763
+ // let dirVec;
148930
148764
  bcfArray.forEach(item => {
148931
148765
  let itemArray = item.split(':');
148932
148766
  if(itemArray[0] == 'fov') {
148933
148767
  ic.cam.fov = parseFloat(itemArray[1]);
148934
148768
  }
148935
148769
  else {
148936
- let abc = itemArray[1].split(',');
148770
+ let abc = itemArray[1].split(',').map(parseFloat);
148937
148771
  if(itemArray[0] == 'pos') {
148938
- ic.cam.position.set(parseFloat(abc[0]), parseFloat(abc[1]), parseFloat(abc[2]));
148772
+ ic.cam.position.set(abc[0], abc[1], abc[2]);
148939
148773
  }
148940
148774
  else if(itemArray[0] == 'dir') {
148941
- ic.cam.quaternion.setFromUnitVectors(new Vector3$1(0, 0, -1), new Vector3$1(parseFloat(abc[0]), parseFloat(abc[1]), parseFloat(abc[2])));
148775
+ ic.cam.quaternion.setFromUnitVectors(new Vector3$1(0, 0, -1), new Vector3$1(abc[0], abc[1], abc[2]));
148776
+ // dirVec = new THREE.Vector3(abc[0], abc[1], abc[2]);
148942
148777
  }
148943
148778
  else if(itemArray[0] == 'up') {
148944
- ic.cam.up.set(parseFloat(abc[0]), parseFloat(abc[1]), parseFloat(abc[2]));
148779
+ ic.cam.up.set(abc[0], abc[1], abc[2]);
148945
148780
  }
148946
148781
  }
148947
148782
  });
148783
+ // apply after pos and up are known, so the roll follows "up"
148784
+ // if(dirVec) {
148785
+ // ic.cam.lookAt(ic.cam.position.clone().add(dirVec));
148786
+ // ic.cam.updateMatrixWorld(true);
148787
+ // }
148948
148788
 
148949
148789
  // set the aspect ratio
148950
148790
  if(!ic.container.whratio) {
@@ -149285,17 +149125,30 @@ class SaveFile {
149285
149125
  let height = $("#" + ic.pre + "canvas").height();
149286
149126
  ic.applyCenterCls.setWidthHeight(width, height);
149287
149127
 
149128
+ let bPathTracer = (ic.scaleFactor == 1) ? false : true;
149129
+ /*
149288
149130
  // disable path tracing for large structures
149289
- let bPathTracer = (Object.keys(ic.atoms).length > ic.maxatomcnt) ? false : true;
149131
+ let bPathTracer = (Object.keys(ic.atoms).length > ic.maxatomcnt || ic.scaleFactor == 1) ? false : true;
149290
149132
 
149291
149133
  if(ic.biomtMatrices !== undefined && ic.biomtMatrices.length > 1 && ic.bAssembly
149292
149134
  && Object.keys(ic.atoms).length * ic.biomtMatrices.length > ic.maxatomcnt) {
149293
149135
  bPathTracer = false; // disable path tracing for large assemblies
149294
149136
  }
149137
+ */
149295
149138
 
149296
- //if(ic.bRender) ic.drawCls.render(undefined, bPathTracer);
149297
- if(ic.bRender) ic.drawCls.draw(undefined, bPathTracer);
149139
+ if(bPathTracer) {
149140
+ if(ic.bRender) ic.drawCls.draw(undefined, bPathTracer);
149298
149141
 
149142
+ /*
149143
+ let commandTransformation = ic.commands[ic.commands.length-1].split('|||');
149144
+ ic.transformCls.resetOrientation_base(commandTransformation);
149145
+ if(ic.bRender) ic.drawCls.render(undefined, bPathTracer);
149146
+ */
149147
+ }
149148
+ else {
149149
+ if(ic.bRender) ic.drawCls.render(undefined, bPathTracer);
149150
+ }
149151
+
149299
149152
  // reset impostor and instancing
149300
149153
  ic.bImpo = true; // enable impostor
149301
149154
  ic.bInstanced = true; // enable instancing
@@ -152980,8 +152833,6 @@ class iCn3D {
152980
152833
 
152981
152834
  this.bInitial = true; // first 3d display
152982
152835
 
152983
- this.bDoublecolor = false;
152984
-
152985
152836
  this.originSize = 1; // radius
152986
152837
 
152987
152838
  this.ALTERNATE_STRUCTURE = -1;
@@ -153058,7 +152909,7 @@ class iCn3D {
153058
152909
  //This is the line radius for stabilizers, hydrogen bonds, and distance lines. It's 0.1 by default.
153059
152910
  this.lineRadius = 0.1; // hbonds, distance lines
153060
152911
  //This is the coil radius for coils. It's 0.3 by default.
153061
- this.coilWidth = 0.3; //0.4; // style cartoon-coil
152912
+ this.coilWidth = 0.12; //0.3; // style cartoon-coil
153062
152913
  //This is the stick radius. It's 0.4 by default.
153063
152914
  this.cylinderRadius = 0.4; // style stick
153064
152915
  //This is the cross-linkage radius. It's 0.4 by default.
@@ -153073,7 +152924,7 @@ class iCn3D {
153073
152924
  this.cylinderHelixRadius = 1.6; // style cylinder and plate
153074
152925
 
153075
152926
  //This is the ribbon thickness for helix and sheet ribbons, and nucleotide ribbons. It's 0.4 by default.
153076
- this.ribbonthickness = 0.2; // 0.4; // style ribbon, nucleotide cartoon, stand thickness
152927
+ this.ribbonthickness = 0.35; // 0.2; // style ribbon, nucleotide cartoon, stand thickness
153077
152928
  //This is the width of protein ribbons. It's 1.3 by default.
153078
152929
  this.helixSheetWidth = 1.3; // style ribbon, nucleotide cartoon, stand thickness
153079
152930
  //This is the width of nucleotide ribbons. It's 0.8 by default.
@@ -153691,7 +153542,7 @@ class iCn3DUI {
153691
153542
  //even when multiple iCn3D viewers are shown together.
153692
153543
  this.pre = this.cfg.divid + "_";
153693
153544
 
153694
- this.REVISION = '3.53.0';
153545
+ this.REVISION = '3.54.0';
153695
153546
 
153696
153547
  // In nodejs, iCn3D defines "window = {navigator: {}}", and added window = {navigator: {}, "__THREE__":"177"}
153697
153548
  this.bNode = (Object.keys(window).length < 3) ? true : false;