icn3d 3.53.0 → 3.54.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/icn3d.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] = [];
78228
+ for(let i = 0, il = linePos.length; i < il; ++i) pnts[i] = [];
78294
78229
 
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];
78299
-
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,55 @@ 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
+ if(!pntsCA[i] || !prevCOArray[i]) continue;
78282
+
78283
+ let v = new Vector3$1(pntsCA[i].x + prevCOArray[i].x * delta,
78284
+ pntsCA[i].y + prevCOArray[i].y * delta,
78285
+ pntsCA[i].z + prevCOArray[i].z * delta);
78286
+ //v.smoothen = true;
78287
+ pnts[index].push(v);
78288
+ colorsTmp.push(colors[i]);
78289
+ if(index === 0) posIndex.push(pos);
78388
78290
  }
78389
-
78291
+
78390
78292
  // last residue
78391
78293
  // 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
- }
78294
+ let lastCAIndex = pntsCA.length - 1;
78295
+ let delta = -1 + numM1Inv2 * linePos[index];
78296
+ let scale = 1.8; // scale of the arrow width
78297
+ delta = delta * scale / ic.axisDIV;
78406
78298
 
78407
- pntsCASmooth = [];
78299
+ let v = new Vector3$1(pntsCA[lastCAIndex].x + prevCOArray[lastCAIndex].x * delta,
78300
+ pntsCA[lastCAIndex].y + prevCOArray[lastCAIndex].y * delta,
78301
+ pntsCA[lastCAIndex].z + prevCOArray[lastCAIndex].z * delta);
78408
78302
 
78409
- //colorsTmp.push(colors[colors.length - 2]);
78410
- //colorsTmp.push(colors[colors.length - 1]);
78303
+ pnts[index].push(v);
78304
+ colorsTmp.push(colors[lastCAIndex]);
78305
+ if(index === 0) posIndex.push(positions[lastCAIndex]);
78306
+ }
78411
78307
 
78412
78308
  if(bStrip) {
78413
78309
  ic.stripCls.createStrip(pnts[0], pnts[1], colorsTmp, div, thickness, bHighlight, true,
78414
- undefined, undefined, posIndex, prevone, nexttwo);
78310
+ undefined, undefined, posIndex);
78415
78311
  }
78416
78312
  else {
78417
78313
  ic.curveCls.createCurveSub(pnts[0], width, colorsTmp, div, bHighlight, bRibbon, true,
78418
- undefined, undefined, posIndex, prevone, nexttwo);
78314
+ undefined, undefined, posIndex);
78419
78315
  }
78420
78316
  }
78421
78317
 
78318
+ //pntsCA = [];
78319
+
78422
78320
  for(let i in pnts) {
78423
78321
  for(let j = 0, jl = pnts[i].length; j < jl; ++j) {
78424
78322
  pnts[i][j] = null;
@@ -78427,7 +78325,7 @@ class CurveStripArrow {
78427
78325
  }
78428
78326
 
78429
78327
  pnts = {};
78430
- }
78328
+ }
78431
78329
  }
78432
78330
 
78433
78331
  /**
@@ -78440,15 +78338,14 @@ class Curve {
78440
78338
  }
78441
78339
 
78442
78340
  // 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;
78341
+ createCurveSub(_pnts, width, colors, div, bHighlight, bRibbon, bNoSmoothen, positions) { let ic = this.icn3d, me = ic.icn3dui;
78444
78342
  if(me.bNode) return;
78445
78343
 
78446
78344
  if (_pnts.length === 0) return;
78447
78345
  div = div || 5;
78448
78346
  let pnts;
78449
- if(!bNoSmoothen) {
78450
- let bExtendLastRes = true;
78451
- let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, div, bShowArray, bHighlight, prevone, nexttwo, bExtendLastRes);
78347
+ if(div != 1 && !bNoSmoothen) {
78348
+ let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, div);
78452
78349
  pnts = pnts_clrs[0];
78453
78350
  colors = pnts_clrs[2];
78454
78351
  }
@@ -78457,8 +78354,6 @@ class Curve {
78457
78354
  }
78458
78355
  if (pnts.length === 0) return;
78459
78356
 
78460
- ic.stripCls.setCalphaDrawnCoord(pnts, div, calphaIdArray);
78461
-
78462
78357
  if(bHighlight === 1) {
78463
78358
  let radius = ic.coilWidth / 2;
78464
78359
  //var radiusSegments = 8;
@@ -78585,7 +78480,7 @@ class Curve {
78585
78480
  }
78586
78481
 
78587
78482
  pnts = null;
78588
- }
78483
+ }
78589
78484
  }
78590
78485
 
78591
78486
  /**
@@ -78755,12 +78650,12 @@ class Cylinder {
78755
78650
 
78756
78651
  let start = null;
78757
78652
  let currentChain, currentResi;
78758
- let others = {}, beta = {};
78653
+ let others = [], beta = {};
78759
78654
  let i;
78760
78655
  for (i in atoms) {
78761
78656
  let atom = atoms[i];
78762
78657
  if (atom.het) continue;
78763
- if ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) others[atom.serial] = atom;
78658
+ if ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) others.push(atom);
78764
78659
  if (atom.ss === 'sheet') beta[atom.serial] = atom;
78765
78660
  if (atom.name !== 'CA') continue;
78766
78661
  if (atom.ss === 'helix' && atom.ssend) {
@@ -79736,45 +79631,22 @@ class Strip {
79736
79631
  }
79737
79632
 
79738
79633
  // 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;
79634
+ createStrip(p0, p1, colors, div, thickness, bHighlight, bNoSmoothen,
79635
+ positions, pntsCA, prevCOArray) { let ic = this.icn3d, me = ic.icn3dui;
79741
79636
  if(me.bNode) return;
79742
79637
 
79743
79638
  if (p0.length < 2) return;
79744
79639
  div = div || ic.axisDIV;
79745
79640
 
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
-
79641
+ if(div != 1) { // not subdivided yet
79766
79642
  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);
79643
+ let pnts_clrs0 = me.subdivideCls.subdivide(p0, colors, div);
79644
+ let pnts_clrs1 = me.subdivideCls.subdivide(p1, colors, div);
79771
79645
  p0 = pnts_clrs0[0];
79772
79646
  p1 = pnts_clrs1[0];
79773
79647
  colors = pnts_clrs0[2];
79774
79648
  }
79775
79649
  if (p0.length < 2) return;
79776
-
79777
- this.setCalphaDrawnCoord(p0, div, calphaIdArray);
79778
79650
  }
79779
79651
 
79780
79652
  if(bHighlight === 1) {
@@ -79801,7 +79673,7 @@ class Strip {
79801
79673
  radiusSegments,
79802
79674
  closed
79803
79675
  );
79804
-
79676
+
79805
79677
  let mesh = new Mesh$1(geometry0, ic.matShader);
79806
79678
  mesh.renderOrder = ic.renderOrderPicking;
79807
79679
  //ic.mdlPicking.add(mesh);
@@ -79896,33 +79768,29 @@ class Strip {
79896
79768
 
79897
79769
  if(!p0v || !p1v) continue;
79898
79770
 
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
79771
+ // compute the thickness direction first
79772
+ if (i < lim - 1 && p0[i + 1]) {
79773
+ axis = p1[i].clone().sub(p0[i]).cross(p0[i + 1].clone().sub(p0[i])).normalize().multiplyScalar(thickness);
79774
+ }
79775
+ let half = axis.clone().multiplyScalar(0.5);
79903
79776
 
79777
+ // bottom face: half a thickness below the edge plane
79778
+ let b0v = p0v.clone().sub(half);
79779
+ let b1v = p1v.clone().sub(half);
79904
79780
  for(let j = 0; j < 2; ++j) {
79905
- vs[offset++] = p0v.x;
79906
- vs[offset++] = p0v.y;
79907
- vs[offset++] = p0v.z;
79781
+ vs[offset++] = b0v.x;
79782
+ vs[offset++] = b0v.y;
79783
+ vs[offset++] = b0v.z;
79908
79784
  }
79909
79785
  for(let j = 0; j < 2; ++j) {
79910
- vs[offset++] = p1v.x;
79911
- vs[offset++] = p1v.y;
79912
- vs[offset++] = p1v.z;
79786
+ vs[offset++] = b1v.x;
79787
+ vs[offset++] = b1v.y;
79788
+ vs[offset++] = b1v.z;
79913
79789
  }
79914
79790
 
79915
- if (i < lim - 1) {
79916
- axis = p1[i].clone().sub(p0[i]).cross(p0[i + 1].clone().sub(p0[i])).normalize().multiplyScalar(thickness);
79917
- }
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
-
79791
+ // top face: half a thickness above the edge plane
79792
+ a0v = p0v.clone().add(half);
79793
+ a1v = p1v.clone().add(half);
79926
79794
  for(let j = 0; j < 2; ++j) {
79927
79795
  vs[offset++] = a0v.x;
79928
79796
  vs[offset++] = a0v.y;
@@ -80041,22 +79909,6 @@ class Strip {
80041
79909
  p0 = null;
80042
79910
  p1 = null;
80043
79911
  }
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
79912
  }
80061
79913
 
80062
79914
  /**
@@ -80072,129 +79924,161 @@ class Tube {
80072
79924
  //Create tubes for "atoms" with certain "atomName". "radius" is the radius of the tubes.
80073
79925
  //"bHighlight" is an option to draw the highlight for these atoms. The highlight could be
80074
79926
  //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;
79927
+ createTube(atoms, atomName, radius, bHighlight, bCustom, bNonCoil, tubePosArray, pntsCAAllSub, colorsAllSub) { let ic = this.icn3d, me = ic.icn3dui;
80076
79928
  if(me.bNode) return;
80077
79929
 
80078
- let pnts = [], colors = [], radii = [], prevone = [], nexttwo = [];
79930
+ let pnts = [], colors = [], radii = [];
80079
79931
  let currentChain, currentResi;
80080
79932
  let index = 0;
80081
79933
  let maxDist = 6.0;
80082
79934
  let maxDist2 = 3.0; // avoid tube between the residues in 3 residue helix
80083
79935
 
80084
- let pnts_colors_radii_prevone_nexttwo = [];
80085
- let firstAtom, atom, prevAtom;
79936
+ let pnts_colors_radii = [];
79937
+ let firstAtom, firstPos, atom, prevAtom, prevPos;
79938
+ let half = Math.floor(ic.axisDIV / 2) - 1;
79939
+
79940
+ for (let i = 0, il = atoms.length; i < il; ++i) {
79941
+ let pos = (tubePosArray) ? tubePosArray[i] : undefined;
80086
79942
 
80087
- for (let i in atoms) {
80088
79943
  atom = atoms[i];
80089
79944
  if ((atom.name === atomName) && !atom.het) {
80090
79945
  if(index == 0) {
80091
79946
  firstAtom = atom;
79947
+ firstPos = pos;
80092
79948
  }
80093
79949
 
80094
79950
  atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) - 1).toString();
80095
79951
 
80096
79952
  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
79953
  || (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
79954
  || (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
79955
  ) ) {
80101
79956
  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));
79957
+ if(tubePosArray) {
79958
+ let bMissingEnd = ic.missingResEnd[prevAtom.structure + '_' + prevAtom.chain + '_' + prevAtom.resi];
79959
+ // remove half of the points when missign residues
79960
+ if(bMissingEnd) {
79961
+ pnts.splice(-half);
79962
+ colors.splice(-half);
79963
+ radii.splice(-half);
79964
+ }
79965
+
79966
+ let result = this.closeSegment(firstAtom, firstPos, prevAtom, prevPos, pnts, colors, radii, pntsCAAllSub);
79967
+
79968
+ pnts_colors_radii.push(result);
79969
+ }
79970
+ else {
79971
+ /*
79972
+ if(!isNaN(firstAtom.resi) && !isNaN(prevAtom.resi)) {
79973
+ let prevoneResid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
79974
+ let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
79975
+ prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
79976
+
79977
+ let nextoneResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 1).toString();
79978
+ let nexttwoResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 2).toString();
79979
+ let nextthreeResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 3).toString();
79980
+
79981
+ if(ic.residues.hasOwnProperty(nextoneResid)) {
79982
+ let nextAtom = ic.firstAtomObjCls.getAtomFromResi(nextoneResid, atomName);
79983
+ if(nextAtom !== undefined && nextAtom.ssbegin) { // include the residue
79984
+ nextoneResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 2).toString();
79985
+ nexttwoResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 3).toString();
79986
+
79987
+ pnts.push(nextAtom.coord);
79988
+ if(bCustom) {
79989
+ radii.push(this.getCustomtubesize(nextoneResid));
79990
+ }
79991
+ else {
79992
+ radii.push(this.getRadius(radius, nextAtom));
79993
+ }
79994
+ colors.push(nextAtom.color);
80123
79995
  }
80124
- colors.push(nextAtom.color);
80125
79996
  }
80126
- }
80127
79997
 
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);
79998
+ // add one more residue if only one residue is available and it's not part of helix/sheet
79999
+ if(pnts.length == 1 && ic.residues.hasOwnProperty(nextoneResid) && atom.ss == 'coil') {
80000
+ let nextAtom = ic.firstAtomObjCls.getAtomFromResi(nextoneResid, atomName);
80131
80001
 
80132
- if(nextAtom) {
80133
- pnts.push(nextAtom.coord);
80134
- colors.push(nextAtom.color);
80002
+ if(nextAtom) {
80003
+ pnts.push(nextAtom.coord);
80004
+ colors.push(nextAtom.color);
80135
80005
 
80136
- let radiusFinal = this.getRadius(radius, atom);
80137
- radii.push(radiusFinal);
80006
+ let radiusFinal = this.getRadius(radius, atom);
80007
+ radii.push(radiusFinal);
80138
80008
 
80139
- nextoneResid = nexttwoResid;
80140
- nexttwoResid = nextthreeResid;
80009
+ nextoneResid = nexttwoResid;
80010
+ nexttwoResid = nextthreeResid;
80011
+ }
80141
80012
  }
80142
- }
80143
80013
 
80144
- let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
80145
- if(nextoneCoord !== undefined) {
80146
- nexttwo.push(nextoneCoord);
80147
- }
80014
+ let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
80015
+ if(nextoneCoord !== undefined) {
80016
+ nexttwo.push(nextoneCoord);
80017
+ }
80148
80018
 
80149
- let nexttwoCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nexttwoResid, atomName);
80150
- if(nexttwoCoord !== undefined) {
80151
- nexttwo.push(nexttwoCoord);
80019
+ let nexttwoCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nexttwoResid, atomName);
80020
+ if(nexttwoCoord !== undefined) {
80021
+ nexttwo.push(nexttwoCoord);
80022
+ }
80152
80023
  }
80024
+ */
80025
+ pnts_colors_radii.push({'pnts':pnts, 'colors':colors, 'radii':radii});
80153
80026
  }
80154
-
80155
- pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
80156
80027
  }
80157
- pnts = []; colors = []; radii = []; prevone = []; nexttwo = [];
80158
- firstAtom = atom;
80028
+ pnts = []; colors = []; radii = []; firstAtom = atom;
80029
+ firstPos = pos;
80159
80030
  index = 0;
80160
80031
  }
80161
80032
 
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));
80033
+ if(tubePosArray) { // coil
80034
+ let bMissingStart = ic.missingResStart[atom.structure + '_' + atom.chain + '_' + atom.resi];
80035
+ let bMissingEnd = ic.missingResEnd[atom.structure + '_' + atom.chain + '_' + atom.resi];
80036
+
80037
+ let offsetStart = (bMissingStart) ? half : 0;
80038
+ let offsetEnd = (bMissingEnd) ? half : 0;
80039
+
80040
+ let indexArray = ic.strandCls.pos2IndexArray(pos, pntsCAAllSub);
80041
+ for(let j = offsetEnd, jl = indexArray.length - offsetStart; j < jl; ++j) {
80042
+ pnts.push(pntsCAAllSub[indexArray[j]]);
80043
+ colors.push(colorsAllSub[indexArray[j]]);
80044
+ radii.push(ic.coilWidth);
80045
+ }
80046
+ }
80047
+ else { // b factor, etc
80048
+ /*
80049
+ if(pnts.length == 0 && !isNaN(atom.resi)) {
80050
+ let prevoneResid = atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) - 1).toString();
80051
+ if(ic.residues.hasOwnProperty(prevoneResid)) {
80052
+ prevAtom = ic.firstAtomObjCls.getAtomFromResi(prevoneResid, atomName);
80053
+ if(prevAtom !== undefined && prevAtom.ssend) { // include the residue
80054
+ pnts.push(prevAtom.coord);
80055
+ if(bCustom) {
80056
+ radii.push(this.getCustomtubesize(prevoneResid));
80057
+ }
80058
+ else {
80059
+ radii.push(this.getRadius(radius, prevAtom));
80060
+ }
80061
+ colors.push(prevAtom.color);
80173
80062
  }
80174
- colors.push(prevAtom.color);
80175
80063
  }
80176
80064
  }
80177
- }
80065
+ */
80066
+ pnts.push(atom.coord);
80178
80067
 
80179
- pnts.push(atom.coord);
80068
+ let radiusFinal;
80069
+ if(bCustom) {
80070
+ radiusFinal = this.getCustomtubesize(atom.structure + '_' + atom.chain + '_' + atom.resi);
80071
+ }
80072
+ else {
80073
+ radiusFinal = this.getRadius(radius, atom);
80074
+ }
80075
+
80076
+ radii.push(radiusFinal);
80180
80077
 
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);
80078
+ colors.push(atom.color);
80079
+ // the starting residue of a coil uses the color from the next residue to avoid using the color of the last helix/sheet residue
80080
+ if(index === 1) colors[colors.length - 2] = atom.color;
80187
80081
  }
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;
80191
-
80192
- //radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
80193
- radii.push(radiusFinal);
80194
-
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;
80198
80082
 
80199
80083
  currentChain = atom.chain;
80200
80084
  currentResi = atom.resi;
@@ -80207,170 +80091,128 @@ class Tube {
80207
80091
  ++index;
80208
80092
 
80209
80093
  prevAtom = atom;
80094
+ prevPos = pos;
80210
80095
  }
80211
80096
  }
80212
80097
 
80213
80098
  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;
80099
+ if(tubePosArray) {
80100
+ if(prevAtom) {
80101
+ let bMissingEnd = ic.missingResEnd[prevAtom.structure + '_' + prevAtom.chain + '_' + prevAtom.resi];
80102
+ if(bMissingEnd) {
80103
+ pnts.splice(-half);
80104
+ colors.splice(-half);
80105
+ radii.splice(-half);
80240
80106
  }
80241
- }
80242
80107
 
80243
- let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
80244
- if(nextoneCoord !== undefined) {
80245
- nexttwo.push(nextoneCoord);
80246
- }
80108
+ let result = this.closeSegment(firstAtom, firstPos, prevAtom, prevPos, pnts, colors, radii, pntsCAAllSub);
80247
80109
 
80248
- let nexttwoCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nexttwoResid, atomName);
80249
- if(nexttwoCoord !== undefined) {
80250
- nexttwo.push(nexttwoCoord);
80110
+ pnts_colors_radii.push(result);
80251
80111
  }
80252
80112
  }
80253
-
80254
- pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
80255
- }
80256
-
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;
80263
-
80264
- this.createTubeSub(pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil);
80265
- }
80266
-
80267
- pnts_colors_radii_prevone_nexttwo = [];
80268
- }
80269
-
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;
80113
+ else {
80114
+ /*
80115
+ prevone = [];
80116
+ if(firstAtom !== undefined && !isNaN(firstAtom.resi)) {
80117
+ let prevoneResid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1).toString();
80118
+ let prevoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(prevoneResid, atomName);
80119
+ prevone = (prevoneCoord !== undefined) ? [prevoneCoord] : [];
80288
80120
  }
80289
80121
 
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] : [];
80122
+ nexttwo = [];
80123
+ if(atom !== undefined && !isNaN(atom.resi)) {
80124
+ let nextoneResid = atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) + 1).toString();
80125
+ let nexttwoResid = atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) + 2).toString();
80126
+ let nextthreeResid = atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) + 3).toString();
80298
80127
 
80299
- let nextoneResid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 1).toString();
80128
+ // add one more residue if only one residue is available
80129
+ if(pnts.length == 1 && ic.residues.hasOwnProperty(nextoneResid)) {
80130
+ let nextAtom = ic.firstAtomObjCls.getAtomFromResi(nextoneResid, atomName);
80300
80131
 
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);
80132
+ if(nextAtom) {
80133
+ pnts.push(nextAtom.coord);
80134
+ colors.push(nextAtom.color);
80304
80135
 
80305
- if(nextAtom) {
80306
- pnts.push(nextAtom.coord);
80307
- colors.push(nextAtom.color);
80136
+ let radiusFinal = this.getRadius(radius, atom);
80137
+ radii.push(radiusFinal);
80308
80138
 
80309
- let radiusFinal = this.getRadius(radius, atom);
80310
- radii.push(radiusFinal);
80311
- }
80312
- }
80313
-
80139
+ nextoneResid = nexttwoResid;
80140
+ nexttwoResid = nextthreeResid;
80314
80141
  }
80315
-
80316
- pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
80317
80142
  }
80318
- pnts = []; colors = []; radii = []; prevone = []; nexttwo = [];
80319
- firstAtom = atom;
80320
- index = 0;
80321
- }
80322
80143
 
80323
- pnts.push(atom.coord);
80144
+ let nextoneCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nextoneResid, atomName);
80145
+ if(nextoneCoord !== undefined) {
80146
+ nexttwo.push(nextoneCoord);
80147
+ }
80324
80148
 
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);
80149
+ let nexttwoCoord = ic.firstAtomObjCls.getAtomCoordFromResi(nexttwoResid, atomName);
80150
+ if(nexttwoCoord !== undefined) {
80151
+ nexttwo.push(nexttwoCoord);
80152
+ }
80331
80153
  }
80154
+ */
80155
+ pnts_colors_radii.push({'pnts':pnts, 'colors':colors, 'radii':radii});
80156
+ }
80157
+ }
80332
80158
 
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;
80159
+ for(let i = 0, il = pnts_colors_radii.length; i < il; ++i) {
80160
+ let pnts = pnts_colors_radii[i].pnts;
80161
+ let colors = pnts_colors_radii[i].colors;
80162
+ let radii = pnts_colors_radii[i].radii;
80335
80163
 
80336
- //radii.push(radius || (atom.b > 0 ? atom.b * 0.01 : ic.coilWidth));
80337
- radii.push(radiusFinal);
80164
+ if(tubePosArray) {
80165
+ this.createTubeSub(pnts, colors, radii, bHighlight, bNonCoil);
80166
+ }
80167
+ else {
80168
+ this.createTubeSub(pnts, colors, radii, bHighlight, bNonCoil, true);
80169
+ }
80170
+ }
80338
80171
 
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;
80172
+ pnts_colors_radii = [];
80173
+ }
80342
80174
 
80343
- currentChain = atom.chain;
80344
- currentResi = atom.resi;
80175
+ closeSegment(firstAtom, firstPos, prevAtom, prevPos, pnts, colors, radii, pntsCAAllSub) { let ic = this.icn3d; ic.icn3dui;
80176
+ if (pnts.length === 0) return {'pnts': [], 'colors': [], 'radii': []};
80345
80177
 
80346
- let scale = 1.2;
80347
- if(bHighlight === 2 && !atom.ssbegin) {
80348
- ic.boxCls.createBox(atom, undefined, undefined, scale, undefined, bHighlight);
80349
- }
80178
+ let extra = 1; // extend the tube by 5 sub-points into a preceding/following helix/sheet
80350
80179
 
80351
- ++index;
80180
+ // extend backward by one sub-point into a preceding helix/sheet
80181
+ if (!isNaN(firstAtom.resi)) {
80182
+ if(firstAtom.style == 'strand') extra = 0;
80352
80183
 
80353
- prevAtom = atom;
80354
- }
80355
- }
80184
+ let resid = firstAtom.structure + '_' + firstAtom.chain + '_' + (parseInt(firstAtom.resi) - 1);
80185
+ let before = ic.residues.hasOwnProperty(resid) ? ic.firstAtomObjCls.getAtomFromResi(resid, 'CA') : undefined;
80356
80186
 
80357
- if(bHighlight !== 2) {
80358
- pnts_colors_radii_prevone_nexttwo.push({'pnts':pnts, 'colors':colors, 'radii':radii, 'prevone':prevone, 'nexttwo':nexttwo});
80187
+ for(let i = 1, il = extra + 1; i < il; ++i) {
80188
+ let idx = ic.strandCls.pos2IndexArray(firstPos, pntsCAAllSub)[0] - i;
80189
+ if (before && (before.ssbegin || before.ssend) && idx >= 0) {
80190
+ pnts.unshift(pntsCAAllSub[idx]);
80191
+ colors.unshift(colors[0]); // keep the coil color
80192
+ radii.unshift(radii[0]);
80193
+ }
80194
+ }
80359
80195
  }
80360
80196
 
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;
80197
+ // extend forward by one sub-point into a following helix/sheet
80198
+ if (!isNaN(prevAtom.resi)) {
80199
+ if(prevAtom.style == 'strand') extra = 0;
80367
80200
 
80368
- this.createTubeSub(pnts, colors, radii, bHighlight, prevone, nexttwo, bNonCoil);
80201
+ let resid = prevAtom.structure + '_' + prevAtom.chain + '_' + (parseInt(prevAtom.resi) + 1);
80202
+ let after = ic.residues.hasOwnProperty(resid) ? ic.firstAtomObjCls.getAtomFromResi(resid, 'CA') : undefined;
80203
+ let arr = ic.strandCls.pos2IndexArray(prevPos, pntsCAAllSub);
80204
+ for(let i = 1, il = extra + 1; i < il; ++i) {
80205
+ let idx = arr[arr.length - 1] + i;
80206
+ if (after && (after.ssbegin || after.ssend) && idx < pntsCAAllSub.length) {
80207
+ pnts.push(pntsCAAllSub[idx]);
80208
+ colors.push(colors[colors.length - 1]);
80209
+ radii.push(radii[radii.length - 1]);
80210
+ }
80211
+ }
80369
80212
  }
80370
80213
 
80371
- pnts_colors_radii_prevone_nexttwo = [];
80214
+ return {'pnts': pnts, 'colors': colors, 'radii': radii};
80372
80215
  }
80373
- */
80374
80216
 
80375
80217
  getCustomtubesize(resid) { let ic = this.icn3d; ic.icn3dui;
80376
80218
  let pos = resid.lastIndexOf('_');
@@ -80383,11 +80225,11 @@ class Tube {
80383
80225
  };
80384
80226
 
80385
80227
  // 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;
80228
+ createTubeSub(_pnts, colors, radii, bHighlight, bNonCoil, bSubdivide) { let ic = this.icn3d, me = ic.icn3dui;
80387
80229
  if(me.bNode) return;
80388
80230
 
80389
80231
  if (_pnts.length < 2) return;
80390
-
80232
+
80391
80233
  let circleDiv = ic.tubeDIV, axisDiv = ic.axisDIV;
80392
80234
  let circleDivInv = 1 / circleDiv, axisDivInv = 1 / axisDiv;
80393
80235
  //var geo = new THREE.Geometry();
@@ -80395,10 +80237,17 @@ class Tube {
80395
80237
  let verticeArray = [], colorArray = [],indexArray = [], color;
80396
80238
  let offset = 0, offset2 = 0, offset3 = 0;
80397
80239
 
80398
- let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv, undefined, undefined, prevone, nexttwo);
80240
+ let pnts;
80241
+
80242
+ if(bSubdivide) {
80243
+ let pnts_clrs = me.subdivideCls.subdivide(_pnts, colors, axisDiv);
80399
80244
 
80400
- let pnts = pnts_clrs[0];
80401
- colors = pnts_clrs[2];
80245
+ pnts = pnts_clrs[0];
80246
+ colors = pnts_clrs[2];
80247
+ }
80248
+ else {
80249
+ pnts = _pnts;
80250
+ }
80402
80251
 
80403
80252
  let constRadiius;
80404
80253
  // a threshold to stop drawing the tube if it's less than this ratio of radius
@@ -80436,6 +80285,7 @@ class Tube {
80436
80285
  }
80437
80286
  }
80438
80287
  }
80288
+
80439
80289
  let delta, axis1, axis2;
80440
80290
  if (i < lim - 1) {
80441
80291
  delta = pnts[i].clone().sub(pnts[i + 1]);
@@ -80615,29 +80465,31 @@ class Strand {
80615
80465
  coilWidth = coilWidth || ic.coilWidth;
80616
80466
  doNotSmoothen = doNotSmoothen || false;
80617
80467
  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
80468
 
80629
80469
  // test the first 30 atoms to see whether only C-alpha is available
80630
80470
  ic.bCalphaOnly = me.utilsCls.isCalphaPhosOnly(atomsAdjust); //, 'CA');
80631
80471
 
80632
- // when highlight, draw whole beta sheet and use bShowArray to show the highlight part
80633
- let residueHash = {};
80472
+ // get chains
80473
+ let chainidHash = {};
80634
80474
  for(let i in atomsAdjust) {
80635
- let atom = atomsAdjust[i];
80636
-
80637
- let residueid = atom.structure + '_' + atom.chain + '_' + atom.resi;
80638
- residueHash[residueid] = 1;
80475
+ let atom = ic.atoms[i];
80476
+ let chainid = atom.structure + '_' + atom.chain;
80477
+ chainidHash[chainid] = 1;
80639
80478
  }
80640
- let totalResidueCount = Object.keys(residueHash).length;
80479
+
80480
+ for(let chainid in chainidHash) {
80481
+ let pntsAll = {}; for (let k = 0; k < num; ++k) pntsAll[k] = [];
80482
+ let pntsAllSub = {}; for (let k = 0; k < num; ++k) pntsAllSub[k] = [];
80483
+ let pntsCAAll = [], posArray = [], tubePosArray = [], missingResArray = [];
80484
+ let prevCOArrayAll = [];
80485
+ let colorsAll = [];
80486
+
80487
+ let pntsCAAllSub = [], prevCOArrayAllSub = [], positionsSub = [], colorsAllSub = [];
80488
+
80489
+ let currentChain, currentStyle, currentCA = null, currentColor = null, prevCoorCA = null, prevCoorO = null, prevColor = null;
80490
+ let prevCO = null, ss = null, ssend = false, ssJoint = false, prevResi = null, prevResid = null;
80491
+ let strandWidth, bSheetSegment = false, bHelixSegment = false;
80492
+ let atom, tubeAtoms = [];
80641
80493
 
80642
80494
  let drawnResidueCount = 0;
80643
80495
 
@@ -80645,64 +80497,56 @@ class Strand {
80645
80497
 
80646
80498
  let caArray = []; // record all C-alpha atoms to predict the helix
80647
80499
 
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"
80500
+ let chainAtoms = me.hashUtilsCls.intHash(ic.chains[chainid], atomsAdjust);
80652
80501
 
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
- }
80502
+ let residueArray = ic.resid2specCls.atoms2residues(Object.keys(chainAtoms));
80503
+ let totalResidueCount = residueArray.length;
80504
+
80505
+ let index = 0;
80506
+
80507
+ // get pntsAll, pntsCAAll, prevCOArrayAll, colorsAll
80508
+ // get the subdivided points for all atoms
80509
+ let resi2pos = {};
80510
+ for (let i in ic.chains[chainid]) {
80511
+ atom = ic.atoms[i];
80657
80512
 
80513
+ if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
80514
+ if (atom.name === 'CA') {
80658
80515
  currentCA = atom.coord;
80659
80516
  currentColor = atom.color;
80660
- calphaid = atom.serial;
80661
-
80662
80517
  caArray.push(atom.serial);
80663
80518
  }
80664
80519
 
80665
80520
  if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA')) {
80521
+ ++index;
80522
+
80666
80523
  if(currentCA === null || currentCA === undefined) {
80667
80524
  currentCA = atom.coord;
80668
80525
  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
80526
  }
80688
80527
 
80689
80528
  // assign the previous residue
80690
80529
  if(prevCoorO) {
80691
- if(bHighlight === 1 || bHighlight === 2) {
80692
- colors.push(ic.hColor);
80530
+ // posArray.push(index - 1 - 1);
80531
+ resi2pos[prevResi] = index - 1 - 1;
80532
+
80533
+ /*
80534
+ strandWidth = (ss === 'coil') ? coilWidth : helixSheetWidth;
80535
+
80536
+ if(ss == 'sheet' && atom.ss == 'sheet' && atom.ssend) { // a transition between two sheets
80537
+ strandWidth = 1.8 * helixSheetWidth;
80693
80538
  }
80694
- else {
80695
- colors.push(prevColor);
80539
+ else if(ss == 'sheet' && ssend && atom.ss == 'coil') { // a transition between two ss
80540
+ strandWidth = 0;
80696
80541
  }
80542
+ */
80543
+ strandWidth = helixSheetWidth;
80697
80544
 
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;
80545
+ if(bHighlight === 1 || bHighlight === 2) {
80546
+ colorsAll.push(ic.hColor);
80703
80547
  }
80704
80548
  else {
80705
- strandWidth = (ss === 'coil') ? coilWidth : helixSheetWidth;
80549
+ colorsAll.push(prevColor);
80706
80550
  }
80707
80551
 
80708
80552
  let O, oldCA, resSpan = 4;
@@ -80744,239 +80588,164 @@ class Strand {
80744
80588
  for (let j = 0, numM1Inv2 = 2 / (num - 1); j < num; ++j) {
80745
80589
  let delta = -1 + numM1Inv2 * j;
80746
80590
  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);
80591
+ // no smoothen for the last two residues in sheet
80592
+ if (!doNotSmoothen && ss === 'sheet' && !ssJoint && !(atom.ssend)) v.smoothen = true;
80593
+ pntsAll[j].push(v);
80749
80594
  }
80750
80595
 
80751
- pntsCA.push(prevCoorCA);
80752
- prevCOArray.push(prevCO);
80596
+ pntsCAAll.push(prevCoorCA);
80597
+ prevCOArrayAll.push(prevCO);
80598
+ }
80753
80599
 
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
- }
80600
+ // only update when atom.name === 'O'
80601
+ prevResi = atom.resi;
80762
80602
 
80763
- ++drawnResidueCount;
80764
- }
80603
+ prevCoorCA = currentCA;
80604
+ prevCoorO = atom.coord;
80605
+ prevColor = currentColor;
80765
80606
 
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);
80607
+ ss = atom.ss;
80608
+ ssend = atom.ssend;
80609
+ ssJoint = atom.ssbegin || atom.ssend;
80610
+ } // end if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA') ) {
80611
+ } // end if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
80612
+ } // end for
80770
80613
 
80771
- // if(bBrokenSs && atom.ss === 'sheet') {
80772
- // bSheetSegment = true;
80773
- // }
80774
- // else if(bBrokenSs && atom.ss === 'helix') {
80775
- // bHelixSegment = true;
80776
- // }
80614
+ // add the last residue
80615
+ // posArray.push(index - 1);
80616
+ resi2pos[prevResi] = index - 1;
80777
80617
 
80778
- if ((atom.ssbegin || atom.ssend || (drawnResidueCount === totalResidueCount - 1) || bBrokenSs || currentStyle != atom.style) && pnts[0].length > 0 && bSameChain) {
80779
- let atomName = 'CA';
80618
+ colorsAll.push(prevColor);
80619
+ for (let j = 0, numM1Inv2 = 2 / (num - 1); j < num; ++j) {
80620
+ let delta = -1 + numM1Inv2 * j;
80621
+ let v = new Vector3$1(prevCoorCA.x + prevCO.x * delta, prevCoorCA.y + prevCO.y * delta, prevCoorCA.z + prevCO.z * delta);
80622
+ // no smoothen for the last two residues in sheet
80623
+ if (!doNotSmoothen && ss === 'sheet' && !ssJoint && !(ssend)) v.smoothen = true;
80624
+ pntsAll[j].push(v);
80625
+ }
80626
+ pntsCAAll.push(prevCoorCA);
80627
+ prevCOArrayAll.push(prevCO);
80780
80628
 
80781
- let prevone = [], nexttwo = [];
80629
+ // each point except the last one are divided into div segments. The last point is not divided.
80630
+ let pnts_clrs;
80631
+ for(let i = 0; i < num; ++i) {
80632
+ pnts_clrs = me.subdivideCls.subdivide(pntsAll[i], colorsAll, div);
80633
+ pntsAllSub[i] = pnts_clrs[0];
80634
+ }
80782
80635
 
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
- }
80636
+ pnts_clrs = me.subdivideCls.subdivide(pntsCAAll, colorsAll, div);
80637
+ pntsCAAllSub = pnts_clrs[0];
80638
+ colorsAllSub = pnts_clrs[2];
80639
+
80640
+ pnts_clrs = me.subdivideCls.subdivide(prevCOArrayAll, colorsAll, div);
80641
+ prevCOArrayAllSub = pnts_clrs[0];
80642
+ positionsSub = pnts_clrs[1];
80791
80643
 
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
- }
80644
+ posArray = [];
80645
+ prevCoorO = null;
80646
+ prevCoorCA = null;
80647
+ ss = null;
80648
+ ssend = false;
80649
+ ssJoint = false;
80798
80650
 
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
- }
80651
+ index = 0;
80652
+ let bLastResDrawn = false;
80805
80653
 
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
- }
80654
+ // draw only for the selected atoms
80655
+ for (let i in chainAtoms) {
80656
+ atom = ic.atoms[i];
80657
+ if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
80658
+ // "CA" has to appear before "O"
80815
80659
 
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
- }
80660
+ if (atom.name === 'CA') {
80661
+ // if ( atoms.hasOwnProperty(i) && ((atom.ss !== 'helix' && atom.ss !== 'sheet') || atom.ssend || atom.ssbegin) ) {
80662
+ if ( atoms.hasOwnProperty(i) && ((atom.ss !== 'helix' && atom.ss !== 'sheet') ) ) {
80663
+ tubeAtoms.push(atom);
80664
+ let pos = resi2pos[atom.resi];
80665
+ tubePosArray.push(pos);
80828
80666
 
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
- }
80667
+ continue;
80668
+ }
80669
+ }
80845
80670
 
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;
80671
+ if (atom.name === 'O' || (ic.bCalphaOnly && atom.name === 'CA')) {
80672
+ ++index;
80850
80673
 
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
- }
80674
+ currentCA = atom.coord;
80857
80675
 
80858
- atomid = atom.serial;
80676
+ // smoothen each coil, helix and sheet separately. The joint residue has to be included both in the previous and next segment
80677
+ // if((atom.ssend || currentStyle != atom.style)&& atom.ss === 'sheet') {
80678
+ // bSheetSegment = true;
80679
+ // }
80680
+ // else if((atom.ssend || currentStyle != atom.style) && atom.ss === 'helix') {
80681
+ // bHelixSegment = true;
80682
+ // }
80683
+ if(atom.ss === 'sheet') {
80684
+ bSheetSegment = true;
80685
+ bHelixSegment = false;
80686
+ }
80687
+ else if(atom.ss === 'helix') {
80688
+ bSheetSegment = false;
80689
+ bHelixSegment = true;
80690
+ }
80691
+ else {
80692
+ bSheetSegment = false;
80693
+ bHelixSegment = false;
80694
+ }
80859
80695
 
80860
- pntsCA.push(currentCA);
80861
- prevCOArray.push(prevCO);
80696
+ // assign the previous residue
80697
+ if(prevCoorO) {
80698
+ //pntsCA.push(prevCoorCA);
80699
+ //prevCOArray.push(prevCO);
80700
+ let pos = resi2pos[prevResi];
80701
+ // posArray.push(index - 1 - 1);
80702
+ posArray.push(pos);
80862
80703
 
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
- }
80704
+ let bMissingStart = ic.missingResStart[prevResid];
80705
+ let bMissingEnd = ic.missingResEnd[prevResid];
80706
+ let missingResType = bMissingStart ? 1 : (bMissingEnd ? 2 : 0);
80707
+ missingResArray.push(missingResType);
80874
80708
 
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] = [];
80709
+ ++drawnResidueCount;
80710
+ }
80910
80711
 
80911
- colors = [];
80912
- pntsCA = [];
80913
- prevCOArray = [];
80914
- bShowArray = [];
80915
- calphaIdArray = [];
80916
- bSheetSegment = false;
80917
- bHelixSegment = false;
80918
- } // end if (atom.ssbegin || atom.ssend)
80712
+ let maxDist = 6.0;
80713
+ 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
80714
 
80920
- // end of a chain
80921
- if ((currentChain !== atom.chain || currentStyle != atom.style) && pnts[0].length > 0) {
80922
- let atomName = 'CA';
80715
+ // check for the last atom
80716
+ if ((atom.ssbegin || atom.ssend || bBrokenSs || currentStyle != atom.style || currentChain !== atom.chain) ) {
80717
+ // && posArray.length > 0) {
80718
+ if(!bBrokenSs) { // include the current residue
80719
+ if(drawnResidueCount === totalResidueCount - 1) bLastResDrawn = true;
80923
80720
 
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
- }
80721
+ let pos = resi2pos[atom.resi];
80722
+ // posArray.push(index - 1);
80723
+ posArray.push(pos);
80932
80724
 
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
- }
80725
+ let bMissingStart = ic.missingResStart[atom.structure + '_' + atom.chain + '_' + atom.resi];
80726
+ let bMissingEnd = ic.missingResEnd[atom.structure + '_' + atom.chain + '_' + atom.resi];
80727
+ let missingResType = bMissingStart ? 1 : (bMissingEnd ? 2 : 0);
80728
+ missingResArray.push(missingResType);
80960
80729
  }
80961
80730
 
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
- }
80731
+ bSheetSegment = prevCoorO ? (ss === 'sheet') : (atom.ss === 'sheet');
80732
+ bHelixSegment = prevCoorO ? (ss === 'helix') : (atom.ss === 'helix');
80733
+ // skip the 2-residue joint between two adjacent SS (sheet end -> helix begin)
80734
+ if(!(ssend && atom.ssbegin)) {
80735
+ this.createStrand_base(posArray, pntsAllSub, pntsCAAllSub, prevCOArrayAllSub, colorsAllSub, positionsSub, missingResArray, fill, bHighlight, bRibbon, num, bSheetSegment, bHelixSegment, bFullAtom, thickness);
80736
+ }
80737
+ posArray = [];
80738
+ missingResArray = [];
80739
+ } // end if (atom.ssbegin || atom.ssend)
80971
80740
 
80972
80741
  currentChain = atom.chain;
80973
80742
  currentStyle = atom.style;
80974
80743
  ss = atom.ss;
80975
80744
  ssend = atom.ssend;
80976
- prevAtomid = atom.serial;
80745
+ atom.serial;
80977
80746
  prevResi = atom.resi;
80978
80747
 
80979
- prevCalphaid = calphaid;
80748
+ prevResid = atom.structure + '_' + atom.chain + '_' + atom.resi;
80980
80749
 
80981
80750
  // only update when atom.name === 'O'
80982
80751
  prevCoorCA = currentCA;
@@ -80986,12 +80755,95 @@ class Strand {
80986
80755
  } // end if ((atom.name === 'O' || atom.name === 'CA') && !atom.het) {
80987
80756
  } // end for
80988
80757
 
80758
+ // draw the last residue
80759
+ if(!bLastResDrawn && drawnResidueCount === totalResidueCount - 1) {
80760
+ let pos = resi2pos[prevResi];
80761
+ // posArray.push(index - 1);
80762
+ posArray.push(pos);
80763
+
80764
+ let bMissingStart = ic.missingResStart[prevResid];
80765
+ let bMissingEnd = ic.missingResEnd[prevResid];
80766
+ let missingResType = bMissingStart ? 1 : (bMissingEnd ? 2 : 0);
80767
+ missingResArray.push(missingResType);
80768
+
80769
+ bSheetSegment = prevCoorO ? (ss === 'sheet') : (atom.ss === 'sheet');
80770
+ bHelixSegment = prevCoorO ? (ss === 'helix') : (atom.ss === 'helix');
80771
+ this.createStrand_base(posArray, pntsAllSub, pntsCAAllSub, prevCOArrayAllSub, colorsAllSub, positionsSub, missingResArray, fill, bHighlight, bRibbon, num, bSheetSegment, bHelixSegment, bFullAtom, thickness);
80772
+ } // end if (atom.ssbegin || atom.ssend)
80773
+
80774
+ ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight, undefined, undefined, tubePosArray, pntsCAAllSub, colorsAllSub);
80775
+
80989
80776
  caArray = [];
80777
+ tubeAtoms = [];
80778
+ posArray = [];
80779
+ missingResArray = [];
80780
+ tubePosArray = [];
80781
+ pntsAll = {}, pntsCAAll = [], prevCOArrayAll = [], colorsAll = [];
80782
+ } // end for chainid in ic.chains
80783
+ }
80990
80784
 
80991
- ic.tubeCls.createTube(tubeAtoms, 'CA', coilWidth, bHighlight);
80785
+ createStrand_base(posArray, pntsAllSub, pntsCAAllSub, prevCOArrayAllSub, colorsAllSub, positionsSub, missingResArray, fill, bHighlight, bRibbon, num, bSheetSegment, bHelixSegment, bFullAtom, thickness) { let ic = this.icn3d; ic.icn3dui;
80786
+ let pntsCATmp = [], prevCOArrayTmp = [], colorsTmp = [], positionsTmp = [];
80787
+ let pntsTmp = {}; for (let k = 0; k < num; ++k) pntsTmp[k] = [];
80788
+ let half = Math.floor(ic.axisDIV / 2) - 1;
80992
80789
 
80993
- tubeAtoms = {};
80994
- pnts = {};
80790
+ for(let j = 0, jl = posArray.length; j < jl; ++j) {
80791
+ let pos = posArray[j];
80792
+ let missingResType = missingResArray[j];
80793
+
80794
+ let offsetStart = (missingResType == 1) ? half : 0;
80795
+ let offsetEnd = (missingResType == 2) ? half : 0;
80796
+
80797
+ let indexArray = this.pos2IndexArray(pos, pntsCAAllSub);
80798
+
80799
+ for(let k = offsetEnd, kl = indexArray.length - offsetStart; k < kl; ++k) {
80800
+ pntsCATmp.push(pntsCAAllSub[indexArray[k]]);
80801
+ prevCOArrayTmp.push(prevCOArrayAllSub[indexArray[k]]);
80802
+ colorsTmp.push(colorsAllSub[indexArray[k]]);
80803
+ positionsTmp.push(positionsSub[indexArray[k]]);
80804
+ }
80805
+
80806
+ for(let k = 0; k < num; ++k) {
80807
+ for(let l = 0, ll = indexArray.length; l < ll; ++l) {
80808
+ pntsTmp[k].push(pntsAllSub[k][indexArray[l]]);
80809
+ }
80810
+ }
80811
+ }
80812
+
80813
+ // draw the current segment
80814
+ for (let j = 0; !fill && j < num; ++j) {
80815
+ if(bSheetSegment) {
80816
+ ic.curveStripArrowCls.createCurveSubArrow(pntsTmp[j], 1, colorsTmp, 1, bHighlight, bRibbon, num, j, pntsCATmp, prevCOArrayTmp, positionsTmp, true);
80817
+ }
80818
+ else if(bHelixSegment) {
80819
+ if(bFullAtom) {
80820
+ ic.curveCls.createCurveSub(pntsTmp[j], 1, colorsTmp, 1, bHighlight, bRibbon, false, undefined);
80821
+ }
80822
+ else {
80823
+ ic.curveStripArrowCls.createCurveSubArrow(pntsTmp[j], 1, colorsTmp, 1, bHighlight, bRibbon, num, j, pntsCATmp, prevCOArrayTmp, positionsTmp, false);
80824
+ }
80825
+ }
80826
+ }
80827
+ if (fill) {
80828
+ if(bSheetSegment) {
80829
+ let start = 0, end = num - 1;
80830
+ ic.curveStripArrowCls.createStripArrow(pntsTmp[0], pntsTmp[num - 1], colorsTmp, 1, thickness, bHighlight, num, start, end, pntsCATmp, prevCOArrayTmp, positionsTmp, true);
80831
+ }
80832
+ else if(bHelixSegment) {
80833
+ if(bFullAtom) {
80834
+ ic.stripCls.createStrip(pntsTmp[0], pntsTmp[num - 1], colorsTmp, 1, thickness, bHighlight, false, undefined, pntsCATmp, prevCOArrayTmp);
80835
+ }
80836
+ else {
80837
+ let start = 0, end = num - 1;
80838
+ ic.curveStripArrowCls.createStripArrow(pntsTmp[0], pntsTmp[num - 1], colorsTmp, 1, thickness, bHighlight, num, start, end, pntsCATmp, prevCOArrayTmp, positionsTmp, false);
80839
+ }
80840
+ }
80841
+ else {
80842
+ if(bHighlight === 2) { // draw coils only when highlighted. if not highlighted, coils will be drawn as tubes separately
80843
+ ic.stripCls.createStrip(pntsTmp[0], pntsTmp[num - 1], colorsTmp, 1, thickness, bHighlight, false, undefined, pntsCATmp, prevCOArrayTmp);
80844
+ }
80845
+ }
80846
+ }
80995
80847
  }
80996
80848
 
80997
80849
  getSSExpandedAtoms(atoms, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
@@ -81016,7 +80868,7 @@ class Strand {
81016
80868
  else if(index === length - 1) {
81017
80869
  lastAtom = currAtom;
81018
80870
  }
81019
-
80871
+ /*
81020
80872
  // fill the beginning
81021
80873
  let beginResi = firstAtom.resi;
81022
80874
  if(!isNaN(firstAtom.resi) && firstAtom.ss !== 'coil' && !(firstAtom.ssbegin) ) {
@@ -81038,7 +80890,7 @@ class Strand {
81038
80890
  ic.atoms));
81039
80891
  }
81040
80892
  }
81041
-
80893
+ */
81042
80894
  // add one extra residue for coils between strands/helix if the style is NOT stick, ball and stick, lines, sphere, and dot
81043
80895
  // if(!isNaN(firstAtom.resi) && ic.pk === 3 && bHighlight === 1 && firstAtom.ss === 'coil') {
81044
80896
  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 +80901,7 @@ class Strand {
81049
80901
  atoms = me.hashUtilsCls.unionHash(atoms, me.hashUtilsCls.hash2Atoms(ic.residues[residueid], ic.atoms));
81050
80902
  }
81051
80903
  }
81052
-
80904
+ /*
81053
80905
  // fill the end
81054
80906
  let endResi = lastAtom.resi;
81055
80907
  // 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 +80927,7 @@ class Strand {
81075
80927
  ic.atoms));
81076
80928
  }
81077
80929
  }
81078
-
80930
+ */
81079
80931
  // add one extra residue for coils between strands/helix if the style is NOT stick, ball and stick, lines, sphere, and dot
81080
80932
  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
80933
  let residueid = lastAtom.structure + '_' + lastAtom.chain + '_' + (parseInt(lastAtom.resi) + 1).toString();
@@ -81101,6 +80953,32 @@ class Strand {
81101
80953
 
81102
80954
  return atomsAdjust;
81103
80955
  }
80956
+
80957
+ pos2IndexArray(pos, pntsCAAllSub) { let ic = this.icn3d; ic.icn3dui;
80958
+ let indexArray = [];
80959
+
80960
+ let offset = Math.floor(ic.axisDIV / 2) + 1; // first residue has floor(DIV/2)+1 points (8 when axisDIV = 15)
80961
+
80962
+ //subdivide() gives the first residue only floor(DIV/2)+1 points (8 when axisDIV = 15) and each later residue 15.
80963
+ if(pos == 0) {
80964
+ for(let j = 0; j < offset; ++j) {
80965
+ indexArray.push(j);
80966
+ }
80967
+ }
80968
+ else {
80969
+ for(let j = 0; j < ic.axisDIV; ++j) {
80970
+ let index = offset + (pos - 1) * ic.axisDIV + j;
80971
+ if(index >= pntsCAAllSub.length) {
80972
+ indexArray.push(pntsCAAllSub.length - 1);
80973
+ break;
80974
+ } else {
80975
+ indexArray.push(index);
80976
+ }
80977
+ }
80978
+ }
80979
+
80980
+ return indexArray;
80981
+ }
81104
80982
  }
81105
80983
 
81106
80984
  /**
@@ -85224,6 +85102,9 @@ class ApplyMissingRes {
85224
85102
  }
85225
85103
  }
85226
85104
 
85105
+ if(ic.missingResStart === undefined) ic.missingResStart = {};
85106
+ if(ic.missingResEnd === undefined) ic.missingResEnd = {};
85107
+
85227
85108
  for(let i = 0, il = misingResArray.length; i < il; i += 2) {
85228
85109
  let resid0 = misingResArray[i];
85229
85110
  let resid1 = misingResArray[i + 1];
@@ -85240,6 +85121,10 @@ class ApplyMissingRes {
85240
85121
  ic.missingResPnts[structure].push(resid0);
85241
85122
  ic.missingResPnts[structure].push(resid1);
85242
85123
 
85124
+ ic.missingResStart[resid0] = 1;
85125
+ ic.missingResEnd[resid1] = 1;
85126
+
85127
+
85243
85128
  ic.missingResResid2serial[resid0 + ',' + resid1] = atom0.serial;
85244
85129
  ic.missingResResid2serial[resid1 + ',' + resid0] = atom1.serial;
85245
85130
  }
@@ -85519,10 +85404,20 @@ class ApplyDisplay {
85519
85404
  ic.cylinderCls.createCylinderCurve(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), ['CA'], ic.traceRadius, false, bHighlight);
85520
85405
  }
85521
85406
  else if(style === 'b factor tube') {
85522
- ic.tubeCls.createTube(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), 'CA', null, bHighlight, false, true);
85407
+ let atomArray = [];
85408
+ for(let i in atomHash) {
85409
+ let atom = ic.atoms[i];
85410
+ atomArray.push(atom);
85411
+ }
85412
+ ic.tubeCls.createTube(atomArray, 'CA', null, bHighlight, false, true);
85523
85413
  }
85524
85414
  else if(style === 'custom tube') {
85525
- ic.tubeCls.createTube(me.hashUtilsCls.hash2Atoms(atomHash, ic.atoms), 'CA', null, bHighlight, true, true);
85415
+ let atomArray = [];
85416
+ for(let i in atomHash) {
85417
+ let atom = ic.atoms[i];
85418
+ atomArray.push(atom);
85419
+ }
85420
+ ic.tubeCls.createTube(atomArray, 'CA', null, bHighlight, true, true);
85526
85421
  }
85527
85422
  else if(style === 'lines' || style === 'lines2') {
85528
85423
  if(bHighlight === 1) {
@@ -85833,7 +85728,7 @@ class ApplyOther {
85833
85728
  break;
85834
85729
  }
85835
85730
  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;
85731
+ pos = ic.atoms[i].coord;
85837
85732
  break;
85838
85733
  }
85839
85734
  }
@@ -105158,7 +105053,6 @@ class WebGLPathTracer {
105158
105053
  }
105159
105054
  else {
105160
105055
  if(bPathTracer) {
105161
- console.log("###pathTracer");
105162
105056
  ic.bImpo = false; // disable impostor for path tracing
105163
105057
  const pathTracer = new WebGLPathTracer(ic.renderer);
105164
105058
  pathTracer.setScene(ic.scene, cam);
@@ -131562,6 +131456,59 @@ class SetSeqAlign {
131562
131456
  ic.nconsHash2 = {};
131563
131457
  ic.nalignHash2 = {};
131564
131458
 
131459
+ let msaSameColor = [];
131460
+ // assume all aligned seq are the same. If any aligned res is different,set it to false (0)
131461
+ for(let i = 0, il = seqalign[0].length; i < il; ++i) {
131462
+ msaSameColor.push(1);
131463
+ }
131464
+
131465
+ for(let i = 0, il = seqalign.length; i < il; ++i) {
131466
+ // first sequence
131467
+ let alignData = seqalign[i][0];
131468
+ let molid1 = alignData.moleculeId;
131469
+
131470
+ let chain1 = ic.pdbid_molid2chain[mmdbid1 + '_' + molid1];
131471
+ chainid1 = mmdbid1 + '_' + chain1;
131472
+
131473
+ let id2aligninfo = {};
131474
+ let start = alignData.sequence.length, end = -1;
131475
+ let bStart = false;
131476
+ for(let j = 0, jl = alignData.sequence.length; j < jl; ++j) {
131477
+ // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
131478
+ let resi =(ic.bUsePdbNum) ? ic.ParserUtilsCls.getResi(chainid1, alignData.sequence[j][0] - 1) : alignData.sequence[j][0];
131479
+ let resn =(alignData.sequence[j][2] === '~') ? '-' : alignData.sequence[j][2];
131480
+ resn =(resn === ' ' || resn === '') ? 'X' : resn;
131481
+
131482
+ let aligned =(alignData.sequence[j][3]) ? 1 : 0;
131483
+
131484
+ if(aligned == 1) {
131485
+ if(j < start && !bStart) {
131486
+ start = j;
131487
+ bStart = true; // set start just once
131488
+ }
131489
+ if(j > end) end = j;
131490
+ }
131491
+
131492
+ id2aligninfo[j] = {"resi": resi, "resn": resn, "aligned": aligned};
131493
+ }
131494
+
131495
+ // second sequence
131496
+ alignData = seqalign[i][1];
131497
+
131498
+ for(let j = start; j <= end; ++j) {
131499
+ // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
131500
+ let alignedTmp =(alignData.sequence[j][3]) ? 1 : 0;
131501
+
131502
+ let aligned = id2aligninfo[j].aligned + alignedTmp; // 0 or 2
131503
+
131504
+ if(aligned === 2) { // aligned
131505
+ if(id2aligninfo[j].resn != resn) {
131506
+ msaSameColor[j] = 0;
131507
+ }
131508
+ }
131509
+ }
131510
+ }
131511
+
131565
131512
  for(let i = 0, il = seqalign.length; i < il; ++i) {
131566
131513
  // first sequence
131567
131514
  let alignData = seqalign[i][0];
@@ -131658,6 +131605,8 @@ class SetSeqAlign {
131658
131605
  ic.nconsHash2[chainid2 + '_' + resi] = 1;
131659
131606
  }
131660
131607
 
131608
+ color = (msaSameColor[j] == 0) ? '#0000FF' : '#FF0000';
131609
+
131661
131610
  // mapping, use the firstsequence as the reference structure
131662
131611
  ic.chainsMapping[chainid1][chainid1 + '_' + id2aligninfo[j].resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
131663
131612
  ic.chainsMapping[chainid2][chainid2 + '_' + resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
@@ -131674,6 +131623,8 @@ class SetSeqAlign {
131674
131623
 
131675
131624
  ic.nalignHash1[chainid1 + '_' + id2aligninfo[j].resi] = 1;
131676
131625
  ic.nalignHash2[chainid2 + '_' + resi] = 1;
131626
+
131627
+ msaSameColor[j] = 2; // not aligned
131677
131628
  }
131678
131629
 
131679
131630
  // chain1
@@ -132771,8 +132722,10 @@ class SetSeqAlign {
132771
132722
  ic.msaSeq[chainid2] += '-';
132772
132723
  }
132773
132724
  }
132774
-
132725
+ /*
132775
132726
  setSeqAlignForRealign(chainid_t, chainid, chainIndex) { let ic = this.icn3d, me = ic.icn3dui;
132727
+ //loadSeqAlignment
132728
+ let alignedAtoms = {};
132776
132729
  //var chainid_t = ic.chainidArray[0];
132777
132730
 
132778
132731
  // let structureArray = Object.keys(ic.structures);
@@ -132794,7 +132747,7 @@ class SetSeqAlign {
132794
132747
  ic.alnChains = {};
132795
132748
 
132796
132749
  ic.alnChainsSeq[chainid_t] = [];
132797
- ic.alnChains[chainid_t] = {};
132750
+ ic.alnChains[chainid_t] = {}
132798
132751
  ic.alnChainsAnno[chainid_t] = [];
132799
132752
  ic.alnChainsAnTtl[chainid_t] = [];
132800
132753
 
@@ -132872,8 +132825,8 @@ class SetSeqAlign {
132872
132825
  ic.alnChainsSeq[chainid1].push(resObject1);
132873
132826
  ic.alnChainsSeq[chainid2].push(resObject2);
132874
132827
 
132875
- if(ic.alnChains[chainid1] === undefined) ic.alnChains[chainid1] = {};
132876
- if(ic.alnChains[chainid2] === undefined) ic.alnChains[chainid2] = {};
132828
+ if(ic.alnChains[chainid1] === undefined) ic.alnChains[chainid1] = {}
132829
+ if(ic.alnChains[chainid2] === undefined) ic.alnChains[chainid2] = {}
132877
132830
  $.extend(ic.alnChains[chainid1], ic.residues[chainid1 + '_' + resObject1.resi] );
132878
132831
  $.extend(ic.alnChains[chainid2], ic.residues[chainid2 + '_' + resObject2.resi] );
132879
132832
 
@@ -132903,6 +132856,7 @@ class SetSeqAlign {
132903
132856
  let select = "select " + ic.resid2specCls.residueids2spec(Object.keys(residuesHash));
132904
132857
  ic.selectionCls.addCustomSelection(Object.keys(residuesHash), commandname, commanddescr, select, true);
132905
132858
  }
132859
+ */
132906
132860
 
132907
132861
  setSeqPerResi(chainid, chainid1, chainid2, resi, resn, bAligned, color, color2, classname, bFirstChain, bFirstResi, alignIndex) { let ic = this.icn3d, me = ic.icn3dui;
132908
132862
  if(ic.alnChainsSeq[chainid] === undefined) ic.alnChainsSeq[chainid] = [];
@@ -137220,16 +137174,6 @@ class ApplyCommand {
137220
137174
  let color = command.substr(command.lastIndexOf(' ') + 1);
137221
137175
  me.htmlCls.setMenuCls.setTheme(color);
137222
137176
  }
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
137177
  else if(command.indexOf('adjust dialog') == 0) {
137234
137178
  let id = command.substr(command.lastIndexOf(' ') + 1);
137235
137179
  ic.scapCls.adjust2DWidth(id);
@@ -137696,7 +137640,6 @@ class ApplyCommand {
137696
137640
  else if(cmd.indexOf('replay on') !== -1) return 'File > Replay Each Step > On';
137697
137641
  else if(cmd.indexOf('replay off') !== -1) return 'File > Replay Each Step > Off';
137698
137642
  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
137643
  else return '';
137701
137644
  }
137702
137645
  }
@@ -138814,6 +138757,17 @@ class LoadScript {
138814
138757
  nameArray = paraArray[1].split(',');
138815
138758
  ic.hAtoms = ic.definedSetsCls.getAtomsFromNameArray(nameArray);
138816
138759
  }
138760
+ else {
138761
+ let structureHash = {};
138762
+
138763
+ for(let chainid in ic.chains) {
138764
+ let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.chains[chainid]);
138765
+ if(!structureHash.hasOwnProperty(atom.structure) && (ic.proteins.hasOwnProperty(atom.serial) || ic.nucleotides.hasOwnProperty(atom.serial))) {
138766
+ nameArray.push(chainid);
138767
+ structureHash[atom.structure] = 1;
138768
+ }
138769
+ }
138770
+ }
138817
138771
 
138818
138772
  return nameArray;
138819
138773
  }
@@ -148927,24 +148881,31 @@ class Transform {
148927
148881
  }
148928
148882
  else { // |||pos:a,b,c|dir:a,b,c|up:a,b,c|fov:a
148929
148883
  let bcfArray = commandTransformation[1].split('|');
148884
+ // let dirVec;
148930
148885
  bcfArray.forEach(item => {
148931
148886
  let itemArray = item.split(':');
148932
148887
  if(itemArray[0] == 'fov') {
148933
148888
  ic.cam.fov = parseFloat(itemArray[1]);
148934
148889
  }
148935
148890
  else {
148936
- let abc = itemArray[1].split(',');
148891
+ let abc = itemArray[1].split(',').map(parseFloat);
148937
148892
  if(itemArray[0] == 'pos') {
148938
- ic.cam.position.set(parseFloat(abc[0]), parseFloat(abc[1]), parseFloat(abc[2]));
148893
+ ic.cam.position.set(abc[0], abc[1], abc[2]);
148939
148894
  }
148940
148895
  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])));
148896
+ ic.cam.quaternion.setFromUnitVectors(new Vector3$1(0, 0, -1), new Vector3$1(abc[0], abc[1], abc[2]));
148897
+ // dirVec = new THREE.Vector3(abc[0], abc[1], abc[2]);
148942
148898
  }
148943
148899
  else if(itemArray[0] == 'up') {
148944
- ic.cam.up.set(parseFloat(abc[0]), parseFloat(abc[1]), parseFloat(abc[2]));
148900
+ ic.cam.up.set(abc[0], abc[1], abc[2]);
148945
148901
  }
148946
148902
  }
148947
148903
  });
148904
+ // apply after pos and up are known, so the roll follows "up"
148905
+ // if(dirVec) {
148906
+ // ic.cam.lookAt(ic.cam.position.clone().add(dirVec));
148907
+ // ic.cam.updateMatrixWorld(true);
148908
+ // }
148948
148909
 
148949
148910
  // set the aspect ratio
148950
148911
  if(!ic.container.whratio) {
@@ -149285,17 +149246,30 @@ class SaveFile {
149285
149246
  let height = $("#" + ic.pre + "canvas").height();
149286
149247
  ic.applyCenterCls.setWidthHeight(width, height);
149287
149248
 
149249
+ let bPathTracer = (ic.scaleFactor == 1) ? false : true;
149250
+ /*
149288
149251
  // disable path tracing for large structures
149289
- let bPathTracer = (Object.keys(ic.atoms).length > ic.maxatomcnt) ? false : true;
149252
+ let bPathTracer = (Object.keys(ic.atoms).length > ic.maxatomcnt || ic.scaleFactor == 1) ? false : true;
149290
149253
 
149291
149254
  if(ic.biomtMatrices !== undefined && ic.biomtMatrices.length > 1 && ic.bAssembly
149292
149255
  && Object.keys(ic.atoms).length * ic.biomtMatrices.length > ic.maxatomcnt) {
149293
149256
  bPathTracer = false; // disable path tracing for large assemblies
149294
149257
  }
149258
+ */
149295
149259
 
149296
- //if(ic.bRender) ic.drawCls.render(undefined, bPathTracer);
149297
- if(ic.bRender) ic.drawCls.draw(undefined, bPathTracer);
149260
+ if(bPathTracer) {
149261
+ if(ic.bRender) ic.drawCls.draw(undefined, bPathTracer);
149298
149262
 
149263
+ /*
149264
+ let commandTransformation = ic.commands[ic.commands.length-1].split('|||');
149265
+ ic.transformCls.resetOrientation_base(commandTransformation);
149266
+ if(ic.bRender) ic.drawCls.render(undefined, bPathTracer);
149267
+ */
149268
+ }
149269
+ else {
149270
+ if(ic.bRender) ic.drawCls.render(undefined, bPathTracer);
149271
+ }
149272
+
149299
149273
  // reset impostor and instancing
149300
149274
  ic.bImpo = true; // enable impostor
149301
149275
  ic.bInstanced = true; // enable instancing
@@ -152980,8 +152954,6 @@ class iCn3D {
152980
152954
 
152981
152955
  this.bInitial = true; // first 3d display
152982
152956
 
152983
- this.bDoublecolor = false;
152984
-
152985
152957
  this.originSize = 1; // radius
152986
152958
 
152987
152959
  this.ALTERNATE_STRUCTURE = -1;
@@ -153058,7 +153030,7 @@ class iCn3D {
153058
153030
  //This is the line radius for stabilizers, hydrogen bonds, and distance lines. It's 0.1 by default.
153059
153031
  this.lineRadius = 0.1; // hbonds, distance lines
153060
153032
  //This is the coil radius for coils. It's 0.3 by default.
153061
- this.coilWidth = 0.3; //0.4; // style cartoon-coil
153033
+ this.coilWidth = 0.12; //0.3; // style cartoon-coil
153062
153034
  //This is the stick radius. It's 0.4 by default.
153063
153035
  this.cylinderRadius = 0.4; // style stick
153064
153036
  //This is the cross-linkage radius. It's 0.4 by default.
@@ -153073,7 +153045,7 @@ class iCn3D {
153073
153045
  this.cylinderHelixRadius = 1.6; // style cylinder and plate
153074
153046
 
153075
153047
  //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
153048
+ this.ribbonthickness = 0.35; // 0.2; // style ribbon, nucleotide cartoon, stand thickness
153077
153049
  //This is the width of protein ribbons. It's 1.3 by default.
153078
153050
  this.helixSheetWidth = 1.3; // style ribbon, nucleotide cartoon, stand thickness
153079
153051
  //This is the width of nucleotide ribbons. It's 0.8 by default.
@@ -153691,7 +153663,7 @@ class iCn3DUI {
153691
153663
  //even when multiple iCn3D viewers are shown together.
153692
153664
  this.pre = this.cfg.divid + "_";
153693
153665
 
153694
- this.REVISION = '3.53.0';
153666
+ this.REVISION = '3.54.0';
153695
153667
 
153696
153668
  // In nodejs, iCn3D defines "window = {navigator: {}}", and added window = {navigator: {}, "__THREE__":"177"}
153697
153669
  this.bNode = (Object.keys(window).length < 3) ? true : false;