icn3d 3.8.1 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/icn3d.js +1337 -122
  2. package/package.json +2 -1
package/icn3d.js CHANGED
@@ -6862,10 +6862,11 @@ class Tube {
6862
6862
  firstAtom = atom;
6863
6863
  }
6864
6864
 
6865
- //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
6866
- // || (currentResi + 1 !== 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) )
6865
+ atom.structure + '_' + atom.chain + '_' + (parseInt(atom.resi) - 1).toString();
6866
+
6867
6867
  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
6868
- || (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) )
6868
+ // || (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')
6869
+ || (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))
6869
6870
  ) ) {
6870
6871
  if(bHighlight !== 2) {
6871
6872
  if(!isNaN(firstAtom.resi) && !isNaN(prevAtom.resi)) {
@@ -7459,7 +7460,15 @@ class Strand {
7459
7460
  }
7460
7461
 
7461
7462
  let maxDist = 6.0;
7462
- 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);
7463
+ //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);
7464
+ 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);
7465
+
7466
+ if(bBrokenSs && atom.ss === 'sheet') {
7467
+ bSheetSegment = true;
7468
+ }
7469
+ else if(bBrokenSs && atom.ss === 'helix') {
7470
+ bHelixSegment = true;
7471
+ }
7463
7472
 
7464
7473
  if ((atom.ssbegin || atom.ssend || (drawnResidueCount === totalResidueCount - 1) || bBrokenSs) && pnts[0].length > 0 && bSameChain) {
7465
7474
  let atomName = 'CA';
@@ -11460,17 +11469,32 @@ class Surface {
11460
11469
  //vertexColors.push(ic.atoms[verts[vb].atomid].color);
11461
11470
  //vertexColors.push(ic.atoms[verts[vc].atomid].color);
11462
11471
 
11463
- colorArray[offset2++] = ic.atoms[verts[va].atomid].color.r;
11464
- colorArray[offset2++] = ic.atoms[verts[va].atomid].color.g;
11465
- colorArray[offset2++] = ic.atoms[verts[va].atomid].color.b;
11472
+ if(type == 21 || type == 22 || type == 23) { // potential on surface
11473
+ colorArray[offset2++] = verts[va].color.r;
11474
+ colorArray[offset2++] = verts[va].color.g;
11475
+ colorArray[offset2++] = verts[va].color.b;
11466
11476
 
11467
- colorArray[offset2++] = ic.atoms[verts[vb].atomid].color.r;
11468
- colorArray[offset2++] = ic.atoms[verts[vb].atomid].color.g;
11469
- colorArray[offset2++] = ic.atoms[verts[vb].atomid].color.b;
11477
+ colorArray[offset2++] = verts[vb].color.r;
11478
+ colorArray[offset2++] = verts[vb].color.g;
11479
+ colorArray[offset2++] = verts[vb].color.b;
11470
11480
 
11471
- colorArray[offset2++] = ic.atoms[verts[vc].atomid].color.r;
11472
- colorArray[offset2++] = ic.atoms[verts[vc].atomid].color.g;
11473
- colorArray[offset2++] = ic.atoms[verts[vc].atomid].color.b;
11481
+ colorArray[offset2++] = verts[vc].color.r;
11482
+ colorArray[offset2++] = verts[vc].color.g;
11483
+ colorArray[offset2++] = verts[vc].color.b;
11484
+ }
11485
+ else {
11486
+ colorArray[offset2++] = ic.atoms[verts[va].atomid].color.r;
11487
+ colorArray[offset2++] = ic.atoms[verts[va].atomid].color.g;
11488
+ colorArray[offset2++] = ic.atoms[verts[va].atomid].color.b;
11489
+
11490
+ colorArray[offset2++] = ic.atoms[verts[vb].atomid].color.r;
11491
+ colorArray[offset2++] = ic.atoms[verts[vb].atomid].color.g;
11492
+ colorArray[offset2++] = ic.atoms[verts[vb].atomid].color.b;
11493
+
11494
+ colorArray[offset2++] = ic.atoms[verts[vc].atomid].color.r;
11495
+ colorArray[offset2++] = ic.atoms[verts[vc].atomid].color.g;
11496
+ colorArray[offset2++] = ic.atoms[verts[vc].atomid].color.b;
11497
+ }
11474
11498
 
11475
11499
  //var normals = [];
11476
11500
  //normals.push(normalArrayIn[va]);
@@ -11722,7 +11746,7 @@ class ShareLink {
11722
11746
 
11723
11747
  if(!bPngHtml) {
11724
11748
  if(ic.bInputfile && !ic.bInputUrlfile) {
11725
- var aaa = 1; //alert("Share Link does NOT work when the data is from custom files. Please save 'iCn3D PNG Image' in the File menu and open it in iCn3D.");
11749
+ var aaa = 1; //alert("Share Link does NOT work when the data are from custom files. Please save 'iCn3D PNG Image' in the File menu and open it in iCn3D.");
11726
11750
  return;
11727
11751
  }
11728
11752
  if(bTooLong) {
@@ -14360,9 +14384,7 @@ class HBond {
14360
14384
  }
14361
14385
 
14362
14386
  //if(result > kMaxHBondEnergy) {
14363
- if(atom.ss == 'helix' && atomHbond[j].ss == 'helix' && result > kMaxHBondEnergy) {
14364
- continue;
14365
- }
14387
+ if(atom.ss == 'helix' && atomHbond[j].ss == 'helix' && result > kMaxHBondEnergy) ;
14366
14388
  }
14367
14389
  }
14368
14390
  else {
@@ -15511,7 +15533,8 @@ class GetGraph {
15511
15533
  let strokewidth = '1';
15512
15534
  let textcolor = '#000';
15513
15535
  let fontsize = '6px'; // '6';
15514
- let html = (bAfMap) ? "<g>" : "<g class='icn3d-node' resid='" + resid + "' >";
15536
+ //let html = (bAfMap) ? "<g>" : "<g class='icn3d-node' resid='" + resid + "' >";
15537
+ let html = "<g class='icn3d-node' resid='" + resid + "' >";
15515
15538
  html += "<title>" + node.id + "</title>";
15516
15539
  if(bVertical) {
15517
15540
  html += "<circle cx='" + y + "' cy='" + x + "' r='" + r + "' fill='" + color + "' stroke-width='" + strokewidth + "' stroke='" + strokecolor + "' resid='" + resid + "' />";
@@ -15554,10 +15577,10 @@ class GetGraph {
15554
15577
  else if(node.s == 'b') {
15555
15578
  nodeArray2.push(node);
15556
15579
  }
15557
- //else if(node.s == 'ab') {
15558
- // nodeArray1.push(node);
15559
- // nodeArray2.push(node);
15560
- //}
15580
+ else if(node.s == 'ab') {
15581
+ nodeArray1.push(node);
15582
+ nodeArray2.push(node);
15583
+ }
15561
15584
  }
15562
15585
  // sort array
15563
15586
  nodeArray1.sort(function(a,b) {
@@ -15589,6 +15612,7 @@ class GetGraph {
15589
15612
  let atom = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]);
15590
15613
  resid2color[resid] = atom.color.getHexString().toUpperCase();
15591
15614
  }
15615
+
15592
15616
  let target2resid = {};
15593
15617
  for(let i = 0, il = graphJson.nodes.length; i < il; ++i) {
15594
15618
  let node = graphJson.nodes[i];
@@ -15614,6 +15638,7 @@ class GetGraph {
15614
15638
  }
15615
15639
  ic.graphStr = JSON.stringify(graphJson);
15616
15640
  }
15641
+
15617
15642
  if(ic.bGraph) ic.drawGraphCls.drawGraph(ic.graphStr, ic.pre + 'dl_graph');
15618
15643
  if(ic.bLinegraph) ic.lineGraphCls.drawLineGraph(ic.graphStr);
15619
15644
  if(ic.bScatterplot) ic.lineGraphCls.drawLineGraph(ic.graphStr, true);
@@ -15945,7 +15970,7 @@ class LineGraph {
15945
15970
  let resid2 = chainid2 + '_' + idArrayB[4];
15946
15971
 
15947
15972
  let mapping1, mapping2;
15948
-
15973
+
15949
15974
  if(ic.chainsMapping[chainid1] && ic.chainsMapping[chainid1][resid1]
15950
15975
  && ic.chainsMapping[chainid2] && ic.chainsMapping[chainid2][resid2]) {
15951
15976
  mapping1 = (nodeA.s == "a") ? ic.chainsMapping[chainid1][resid1] : ic.chainsMapping[chainid2][resid2];
@@ -15961,7 +15986,7 @@ class LineGraph {
15961
15986
  }
15962
15987
  }
15963
15988
  }
15964
-
15989
+
15965
15990
  // set linkArraySplitCommon and nameHashSplitCommon
15966
15991
  // set linkArraySplitDiff and nameHashSplitDiff
15967
15992
  let separatorCommon = "=>", separatorDiff = "==>", postCommon = "-", postDiff = "--";
@@ -16077,17 +16102,19 @@ class LineGraph {
16077
16102
 
16078
16103
  width = (maxWidth + 2) * (r + gap) + 2 * marginX;
16079
16104
  }
16080
- let id;
16105
+ let id, graphWidth;
16081
16106
  if(bScatterplot) {
16082
16107
  ic.scatterplotWidth = 2 * width;
16108
+ graphWidth = ic.scatterplotWidth;
16083
16109
  id = me.scatterplotid;
16084
16110
  } else {
16085
16111
  ic.linegraphWidth = 2 * width;
16112
+ graphWidth = ic.linegraphWidth;
16086
16113
  id = me.linegraphid;
16087
16114
  }
16088
16115
  html =(strucArray.length == 0) ? "No interactions found for each structure<br><br>" :
16089
16116
  "2D integration graph for " + strucArray.length + " structure(s) <b>" + strucArray + "</b>. There are three sections: \"Interactions\", \"Common interactions\", and \"Different interactions\". Each section has " + strucArray.length + " graphs.<br><br>";
16090
- html += "<svg id='" + id + "' viewBox='0,0," + width + "," + heightAll + "'>";
16117
+ html += "<svg id='" + id + "' viewBox='0,0," + width + "," + heightAll + "' width='" + graphWidth + "px'>";
16091
16118
 
16092
16119
  let result, heightFinal = 0;
16093
16120
 
@@ -16172,15 +16199,15 @@ class LineGraph {
16172
16199
  // draw common interaction
16173
16200
  let label, postfix;
16174
16201
  if(bCommonDiff == 0) {
16175
- label = "Interactions in structure ";
16202
+ label = "Interactions in ";
16176
16203
  postfix = "";
16177
16204
  }
16178
16205
  else if(bCommonDiff == 1) {
16179
- label = "Common interactions in structure ";
16206
+ label = "Common interactions in ";
16180
16207
  postfix = "_common";
16181
16208
  }
16182
16209
  else if(bCommonDiff == 2) {
16183
- label = "Different interactions in structure ";
16210
+ label = "Different interactions in ";
16184
16211
  postfix = "_diff";
16185
16212
  }
16186
16213
 
@@ -16237,7 +16264,7 @@ class LineGraph {
16237
16264
  // draw label
16238
16265
  if(label) {
16239
16266
  height += textHeight;
16240
- html += "<text x='" + margin1 + "' y='" + height + "' style='font-size:8px; font-weight:bold'>" + label + "</text>";
16267
+ html += "<text x='" + margin + "' y='" + height + "' style='font-size:8px; font-weight:bold'>" + label + "</text>";
16241
16268
  }
16242
16269
 
16243
16270
  let h1 = 30 + height,
@@ -16388,8 +16415,13 @@ class LineGraph {
16388
16415
 
16389
16416
  if(bAfMap && ic.hex2skip[link.c]) ;
16390
16417
  else if(bAfMap && ic.hex2id[link.c]) {
16391
- let id = ic.hex2id[link.c];
16392
- html += "<use href='#" + id + "' x='" +(pos2.x - halfSize).toString() + "' y='" +(pos1.y - halfSize).toString() + "' />";
16418
+ ic.hex2id[link.c];
16419
+ // html += "<use href='#" + id + "' x='" +(pos2.x - halfSize).toString() + "' y='" +(pos1.y - halfSize).toString() + "' />";
16420
+
16421
+ //html += "<g class='icn3d-interaction' resid1='" + resid1 + "' resid2='" + resid2 + "' >";
16422
+ //html += "<title>Interaction of residue " + node1.id + " with residue " + node2.id + "</title>";
16423
+ html += "<rect class='icn3d-interaction' resid1='" + resid1 + "' resid2='" + resid2 + "' x='" +(pos2.x - halfSize).toString() + "' y='" +(pos1.y - halfSize).toString() + "' width='" + rectSize + "' height='" + rectSize + "' fill='" + strokecolor + "' stroke-width='" + linestrokewidth + "' stroke='" + strokecolor + "' />";
16424
+ //html += "</g>";
16393
16425
  }
16394
16426
  else {
16395
16427
  html += "<g class='icn3d-interaction' resid1='" + resid1 + "' resid2='" + resid2 + "' >";
@@ -19353,19 +19385,19 @@ class Scap {
19353
19385
  //snp: 6M0J_E_484_K,6M0J_E_501_Y,6M0J_E_417_N
19354
19386
  let snpStr = '';
19355
19387
  let snpArray = snp.split(','); //stru_chain_resi_snp
19356
- let atomHash = {}, residArray = [];
19388
+ let atomHash = {}, snpResidArray = [];
19357
19389
  for(let i = 0, il = snpArray.length; i < il; ++i) {
19358
19390
  let idArray = snpArray[i].split('_'); //stru_chain_resi_snp
19359
19391
 
19360
19392
  let resid = idArray[0] + '_' + idArray[1] + '_' + idArray[2];
19361
19393
  atomHash = me.hashUtilsCls.unionHash(atomHash, ic.residues[resid]);
19362
- residArray.push(resid);
19394
+ snpResidArray.push(resid);
19363
19395
 
19364
19396
  snpStr += idArray[1] + '_' + idArray[2] + '_' + idArray[3];
19365
19397
  if(i != il -1) snpStr += ',';
19366
19398
  }
19367
19399
 
19368
- let selectSpec = ic.resid2specCls.residueids2spec(residArray);
19400
+ let selectSpec = ic.resid2specCls.residueids2spec(snpResidArray);
19369
19401
  let select = "select " + selectSpec;
19370
19402
 
19371
19403
  let bGetPairs = false;
@@ -19374,7 +19406,7 @@ class Scap {
19374
19406
  let result = ic.showInterCls.pickCustomSphere_base(radius, atomHash, ic.atoms, false, false, undefined, select, bGetPairs);
19375
19407
 
19376
19408
 
19377
- residArray = Object.keys(result.residues);
19409
+ let residArray = Object.keys(result.residues);
19378
19410
  ic.hAtoms = {};
19379
19411
  for(let index = 0, indexl = residArray.length; index < indexl; ++index) {
19380
19412
  let residueid = residArray[index];
@@ -19421,6 +19453,18 @@ class Scap {
19421
19453
  let bAddition = true;
19422
19454
  let hAtom1 = me.hashUtilsCls.cloneHash(ic.hAtoms);
19423
19455
 
19456
+ // the wild type is the reference
19457
+ for(let serial in hAtom1) {
19458
+ let atom = ic.atoms[serial];
19459
+ let chainid = atom.structure + '_' + atom.chain;
19460
+ let resid = chainid + '_' + atom.resi;
19461
+
19462
+ if(!ic.chainsMapping.hasOwnProperty(chainid)) {
19463
+ ic.chainsMapping[chainid] = {};
19464
+ }
19465
+ ic.chainsMapping[chainid][resid] = me.utilsCls.residueName2Abbr(atom.resn) + atom.resi;
19466
+ }
19467
+
19424
19468
  ic.hAtoms = {};
19425
19469
  ic.loadPDBCls.loadPDB(pdbData, pdbid, false, false, bAddition);
19426
19470
  let hAtom2 = me.hashUtilsCls.cloneHash(ic.hAtoms);
@@ -19433,17 +19477,31 @@ class Scap {
19433
19477
 
19434
19478
  ic.opts['color'] = 'chain';
19435
19479
  ic.setColorCls.setColorByOptions(ic.opts, ic.dAtoms);
19436
-
19437
19480
  for(let serial in hAtom2) {
19438
19481
  let atom = ic.atoms[serial];
19439
19482
  if(!atom.het) {
19440
19483
  // use the same color as the wild type
19441
- let resid = atom.structure.substr(0, 4) + '_' + atom.chain + '_' + atom.resi;
19484
+ let resid = atom.structure.substr(0, atom.structure.length - 1) + '_' + atom.chain + '_' + atom.resi;
19442
19485
 
19443
19486
  let atomWT = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid]);
19444
19487
  ic.atoms[serial].color = atomWT.color;
19445
19488
  ic.atomPrevColors[serial] = atomWT.color;
19446
19489
  }
19490
+
19491
+ let chainid = atom.structure + '_' + atom.chain;
19492
+ let resid = chainid + '_' + atom.resi;
19493
+ let residWT = atom.structure.substr(0, atom.structure.length - 1) + '_' + atom.chain + '_' + atom.resi;
19494
+
19495
+ if(!ic.chainsMapping.hasOwnProperty(chainid)) {
19496
+ ic.chainsMapping[chainid] = {};
19497
+ }
19498
+ ic.chainsMapping[chainid][resid] = me.utilsCls.residueName2Abbr(atom.resn) + atom.resi;
19499
+ // use the wild type as reference
19500
+
19501
+ if(snpResidArray.indexOf(residWT) != -1) {
19502
+ let atomWT = ic.firstAtomObjCls.getFirstAtomObj(ic.residues[residWT]);
19503
+ ic.chainsMapping[chainid][resid] = me.utilsCls.residueName2Abbr(atomWT.resn) + atomWT.resi;
19504
+ }
19447
19505
  }
19448
19506
 
19449
19507
  if(bPdb) {
@@ -26455,9 +26513,10 @@ class LoadScript {
26455
26513
  let strArray = ic.commands[i].split("|||");
26456
26514
 
26457
26515
  if(Object.keys(ic.proteins).length > 0 && ic.mmdb_data === undefined &&(ic.bAjax3ddomain === undefined || !ic.bAjax3ddomain)) {
26458
- $.when(thisClass.applyCommand3ddomain(strArray[0].trim())).then(function() {
26459
- thisClass.execCommandsBase(i + 1, end, steps);
26460
- });
26516
+ //$.when(thisClass.applyCommand3ddomain(strArray[0].trim())).then(function() {
26517
+ thisClass.applyCommand3ddomain(strArray[0].trim());
26518
+ thisClass.execCommandsBase(i + 1, end, steps);
26519
+ //});
26461
26520
  }
26462
26521
  else {
26463
26522
  if(Object.keys(ic.proteins).length > 0) {
@@ -26479,8 +26538,9 @@ class LoadScript {
26479
26538
  &&(ic.bAjax3ddomain === undefined || !ic.bAjax3ddomain || ic.mmdb_data === undefined) ) {
26480
26539
  $.when(thisClass.applyCommandClinvar(strArray[0].trim()))
26481
26540
  .then(thisClass.applyCommandSnp(strArray[0].trim()))
26482
- .then(thisClass.applyCommand3ddomain(strArray[0].trim()))
26541
+ //.then(thisClass.applyCommand3ddomain(strArray[0].trim()))
26483
26542
  .then(function() {
26543
+ thisClass.applyCommand3ddomain(strArray[0].trim());
26484
26544
  ic.annotationCls.setAnnoTabAll();
26485
26545
 
26486
26546
  thisClass.execCommandsBase(i + 1, end, steps);
@@ -26499,8 +26559,9 @@ class LoadScript {
26499
26559
  else if(Object.keys(ic.proteins).length > 0 &&(ic.bAjaxClinvar === undefined || !ic.bAjaxClinvar)
26500
26560
  &&(ic.bAjax3ddomain === undefined || !ic.bAjax3ddomain || ic.mmdb_data === undefined)) {
26501
26561
  $.when(thisClass.applyCommandClinvar(strArray[0].trim()))
26502
- .then(thisClass.applyCommand3ddomain(strArray[0].trim()))
26562
+ //.then(thisClass.applyCommand3ddomain(strArray[0].trim()))
26503
26563
  .then(function() {
26564
+ thisClass.applyCommand3ddomain(strArray[0].trim());
26504
26565
  ic.annotationCls.setAnnoTabAll();
26505
26566
 
26506
26567
  thisClass.execCommandsBase(i + 1, end, steps);
@@ -26508,10 +26569,11 @@ class LoadScript {
26508
26569
  }
26509
26570
  else if(Object.keys(ic.proteins).length > 0 &&(ic.bAjax3ddomain === undefined || !ic.bAjax3ddomain || ic.mmdb_data === undefined)
26510
26571
  &&(ic.bAjaxSnp === undefined || !ic.bAjaxSnp)) {
26511
- $.when(thisClass.applyCommand3ddomain(strArray[0].trim()))
26512
- .then(thisClass.applyCommandSnp(strArray[0].trim()))
26572
+ //$.when(thisClass.applyCommand3ddomain(strArray[0].trim()))
26573
+ $.when(thisClass.applyCommandSnp(strArray[0].trim()))
26513
26574
  .then(function() {
26514
- ic.annotationCls.setAnnoTabAll();
26575
+ thisClass.applyCommand3ddomain(strArray[0].trim());
26576
+ ic.annotationCls.setAnnoTabAll();
26515
26577
 
26516
26578
  thisClass.execCommandsBase(i + 1, end, steps);
26517
26579
  });
@@ -26533,12 +26595,14 @@ class LoadScript {
26533
26595
  });
26534
26596
  }
26535
26597
  else if(Object.keys(ic.proteins).length > 0 &&(ic.bAjax3ddomain === undefined || !ic.bAjax3ddomain || ic.mmdb_data === undefined) ) {
26536
- $.when(thisClass.applyCommand3ddomain(strArray[0].trim()))
26537
- .then(function() {
26598
+ //$.when(thisClass.applyCommand3ddomain(strArray[0].trim()))
26599
+ // .then(function() {
26600
+ thisClass.applyCommand3ddomain(strArray[0].trim());
26601
+
26538
26602
  ic.annotationCls.setAnnoTabAll();
26539
26603
 
26540
26604
  thisClass.execCommandsBase(i + 1, end, steps);
26541
- });
26605
+ //});
26542
26606
  }
26543
26607
  else {
26544
26608
  if(Object.keys(ic.proteins).length > 0) {
@@ -26805,12 +26869,13 @@ class LoadScript {
26805
26869
  thisClass.applyCommand3ddomain(lastCommand);
26806
26870
  }
26807
26871
  else if(lastCommand.indexOf('set annotation all') == 0) {
26808
- //$.when(thisClass.applyCommandAnnotationsAndCddSite(lastCommand))
26809
- // .then(thisClass.applyCommandSnpClinvar(lastCommand))
26810
26872
  $.when(thisClass.applyCommandClinvar(lastCommand))
26811
26873
  .then(thisClass.applyCommandSnp(lastCommand))
26812
- .then(thisClass.applyCommand3ddomain(lastCommand));
26813
- ic.annotationCls.setAnnoTabAll();
26874
+ //.then(thisClass.applyCommand3ddomain(lastCommand));
26875
+ .then(function() {
26876
+ thisClass.applyCommand3ddomain(lastCommand);
26877
+ ic.annotationCls.setAnnoTabAll();
26878
+ });
26814
26879
  }
26815
26880
  else if(lastCommand.indexOf('view interactions') == 0 && me.cfg.align !== undefined) {
26816
26881
  thisClass.applyCommandViewinteraction(lastCommand);
@@ -27202,11 +27267,11 @@ class LoadScript {
27202
27267
  let thisClass = this;
27203
27268
 
27204
27269
  // chain functions together
27205
- ic.deferred3ddomain = $.Deferred(function() {
27270
+ //ic.deferred3ddomain = $.Deferred(function() {
27206
27271
  thisClass.applyCommand3ddomainBase(command);
27207
- }); // end of me.deferred = $.Deferred(function() {
27272
+ //}); // end of me.deferred = $.Deferred(function() {
27208
27273
 
27209
- return ic.deferred3ddomain.promise();
27274
+ //return ic.deferred3ddomain.promise();
27210
27275
  }
27211
27276
 
27212
27277
  applyCommandViewinteractionBase(command) { let ic = this.icn3d, me = ic.icn3dui;
@@ -27545,6 +27610,1037 @@ class ResizeCanvas {
27545
27610
  }
27546
27611
  }
27547
27612
 
27613
+ /*
27614
+ * @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
27615
+ * Modified from Tom Madej's C++ code
27616
+ */
27617
+
27618
+ //import * as THREE from 'three';
27619
+
27620
+ class Domain3d {
27621
+ constructor(icn3d) {
27622
+ this.icn3d = icn3d;
27623
+
27624
+ this.dcut = 8; // threshold for C-alpha interactions
27625
+
27626
+ this.MAX_SSE = 512;
27627
+
27628
+ //let this.ctc_cnt[this.MAX_SSE][this.MAX_SSE]; // contact count matrix
27629
+ this.ctc_cnt = [];
27630
+ for(let i = 0; i < this.MAX_SSE; ++i) {
27631
+ this.ctc_cnt[i] = [];
27632
+ }
27633
+
27634
+ //let this.elt_size[this.MAX_SSE]; // element sizes in residues
27635
+ this.elt_size = [];
27636
+ this.elt_size.length = this.MAX_SSE;
27637
+
27638
+ //let this.group_num[this.MAX_SSE]; // indicates required element groupings
27639
+ this.group_num = [];
27640
+ this.group_num.length = this.MAX_SSE;
27641
+
27642
+ this.split_ratio = 0.0; //let // splitting ratio
27643
+ this.min_size = 0; // min required size of a domain
27644
+ this.min_sse = 0; // min number of SSEs required in a domain
27645
+ this.max_csz = 0; // max size of a cut, i.e. number of points
27646
+ this.mean_cts = 0.0; // mean number of contacts in a domain
27647
+ this.c_delta = 0; // cut set parameter
27648
+ this.nc_fact = 0.0; // size factor for internal contacts
27649
+ //let this.elements[2*this.MAX_SSE]; // sets of this.elements to be split
27650
+ this.elements = [];
27651
+ this.elements.length = 2*this.MAX_SSE;
27652
+
27653
+ //let this.stack[this.MAX_SSE]; // this.stack of sets (subdomains) to split
27654
+ this.stack = [];
27655
+ this.stack.length = this.MAX_SSE;
27656
+
27657
+ this.top = 0; // this.top of this.stack
27658
+ //let this.curr_prt0[this.MAX_SSE]; // current part 0 this.elements
27659
+ this.curr_prt0 = [];
27660
+ this.curr_prt0.length = this.MAX_SSE;
27661
+
27662
+ //let this.curr_prt1[this.MAX_SSE]; // current part 1 this.elements
27663
+ this.curr_prt1 = [];
27664
+ this.curr_prt1.length = this.MAX_SSE;
27665
+
27666
+ this.curr_ne0 = 0; // no. of this.elements in current part 0
27667
+ this.curr_ne1 = 0; // no. of this.elements in current part 1
27668
+ this.curr_ratio = 0.0; // current splitting ratio
27669
+ this.curr_msize = 0; // min of current part sizes
27670
+ //let this.parts[2*this.MAX_SSE]; // final partition into domains
27671
+ this.parts = [];
27672
+ this.parts.length = 2*this.MAX_SSE;
27673
+
27674
+ this.np = 0; // next free location in this.parts[]
27675
+ this.n_doms = 0; // number of domains
27676
+ //let this.save_ratios[this.MAX_SSE]; // this.saved splitting ratios
27677
+ this.save_ratios = [];
27678
+ this.save_ratios.length = this.MAX_SSE;
27679
+
27680
+ this.saved = 0; // number of this.saved ratios
27681
+ }
27682
+
27683
+ // Partition the set of this.elements on this.top of the this.stack based on the input cut.
27684
+ // If the partition is valid and the ratio is smaller than the current one, then
27685
+ // save it as the best partition so far encountered. Various criteria are
27686
+ // employed for valid partitions, as described below.
27687
+ //
27688
+
27689
+ //update_partition(int* cut, let k, let n) { let ic = this.icn3d, me = ic.icn3dui;
27690
+ update_partition(cut, k, n) { let ic = this.icn3d; ic.icn3dui;
27691
+ let i, il, j, t, nc0, nc1, ncx, ne, ne0, ne1, elts = [], prt = []; //int
27692
+ let size0, size1, prt0 = [], prt1 = []; // int
27693
+ prt0.length = this.MAX_SSE;
27694
+ prt1.length = this.MAX_SSE;
27695
+ let f, r0; //let
27696
+
27697
+ // this.elements from the this.top of the this.stack
27698
+ //elts = &this.elements[this.stack[this.top - 1]];
27699
+ for(i = this.stack[this.top - 1], il = this.elements.length; i < il; ++i) {
27700
+ elts.push(this.elements[i]);
27701
+ }
27702
+
27703
+ // generate the partition based on the cut //
27704
+ for (i = ne = ne0 = ne1 = 0, prt = prt0, t = -1; i < k; i++) {
27705
+ // write the this.elements into prt //
27706
+ for (j = t + 1; j <= cut[i]; j++)
27707
+ prt[ne++] = elts[j];
27708
+
27709
+ t = cut[i];
27710
+
27711
+ // switch the partition //
27712
+ if (prt == prt0) {
27713
+ ne0 = ne;
27714
+ prt = prt1;
27715
+ ne = ne1;
27716
+ }
27717
+ else {
27718
+ ne1 = ne;
27719
+ prt = prt0;
27720
+ ne = ne0;
27721
+ }
27722
+ }
27723
+
27724
+ // finish with the last part //
27725
+ for (j = t + 1; j < n; j++)
27726
+ prt[ne++] = elts[j];
27727
+
27728
+ if (prt == prt0)
27729
+ ne0 = ne;
27730
+ else
27731
+ ne1 = ne;
27732
+
27733
+ // don't split into two teeny this.parts! //
27734
+ if ((ne0 < this.min_sse) && (ne1 < this.min_sse))
27735
+ return cut;
27736
+
27737
+ // check to see if the partition splits any required groups //
27738
+ for (i = 0; i < ne0; i++) {
27739
+ t = this.group_num[prt0[i]];
27740
+
27741
+ for (j = 0; j < ne1; j++) {
27742
+ if (t == this.group_num[prt1[j]])
27743
+ return cut;
27744
+ }
27745
+ }
27746
+
27747
+ // compute the sizes of the this.parts //
27748
+ for (i = size0 = 0; i < ne0; i++)
27749
+ size0 += this.elt_size[prt0[i]];
27750
+
27751
+ for (i = size1 = 0; i < ne1; i++)
27752
+ size1 += this.elt_size[prt1[i]];
27753
+
27754
+ // count internal contacts for part 0 //
27755
+ for (i = nc0 = 0; i < ne0; i++) {
27756
+ for (j = i; j < ne0; j++)
27757
+ nc0 += this.ctc_cnt[prt0[i]][prt0[j]];
27758
+ }
27759
+
27760
+ // count internal contacts for part 1 //
27761
+ for (i = nc1 = 0; i < ne1; i++) {
27762
+ for (j = i; j < ne1; j++)
27763
+ nc1 += this.ctc_cnt[prt1[i]][prt1[j]];
27764
+ }
27765
+
27766
+ // check globularity condition //
27767
+ if ((1.0 * nc0 / size0 < this.mean_cts) ||
27768
+ (1.0 * nc1 / size1 < this.mean_cts))
27769
+ return cut;
27770
+
27771
+ // to handle non-globular pieces make sure nc0, nc1, are large enough //
27772
+ nc0 = Math.max(nc0, this.nc_fact*size0);
27773
+ nc1 = Math.max(nc1, this.nc_fact*size1);
27774
+
27775
+ // count inter-part contacts //
27776
+ for (i = ncx = 0; i < ne0; i++) {
27777
+ t = prt0[i];
27778
+
27779
+ for (j = 0; j < ne1; j++)
27780
+ ncx += this.ctc_cnt[t][prt1[j]];
27781
+ }
27782
+
27783
+ // compute the splitting ratio //
27784
+ f = Math.min(nc0, nc1);
27785
+ r0 = 1.0 * ncx / (f + 1.0);
27786
+
27787
+ if ((r0 >= this.curr_ratio + 0.01) || (r0 > this.split_ratio))
27788
+ return cut;
27789
+
27790
+ // If the difference in the ratios is insignificant then take the split
27791
+ // that most evenly partitions the domain.
27792
+
27793
+ if ((r0 > this.curr_ratio - 0.01) && (Math.min(size0, size1) < this.curr_msize))
27794
+ return cut;
27795
+
27796
+ // if we get to here then keep this split //
27797
+ for (i = 0; i < ne0; i++)
27798
+ this.curr_prt0[i] = prt0[i];
27799
+
27800
+ for (i = 0; i < ne1; i++)
27801
+ this.curr_prt1[i] = prt1[i];
27802
+
27803
+ this.curr_ne0 = ne0;
27804
+ this.curr_ne1 = ne1;
27805
+ this.curr_ratio = r0;
27806
+ this.curr_msize = Math.min(size0, size1);
27807
+
27808
+ return cut;
27809
+
27810
+ } // end update_partition //
27811
+
27812
+
27813
+
27814
+ // // Run through the possible cuts of size k for a set of this.elements of size n.
27815
+ // *
27816
+ // * To avoid small protrusions, no blocks of consecutive this.elements of length <= this.c_delta
27817
+ // * are allowed. An example where this is desirable is as follows. Let's say you
27818
+ // * have a protein with 2 subdomains, one of them an alpha-beta-alpha sandwich. It
27819
+ // * could then happen that one of the helices in the sandwich domain might make more
27820
+ // * contacts with the other subdomain than with the sandwich. The correct thing to
27821
+ // * do is to keep the helix with the rest of the sandwich, and the "this.c_delta rule"
27822
+ // * enforces this.
27823
+ // //
27824
+
27825
+ cut_size(k, n) { let ic = this.icn3d; ic.icn3dui;
27826
+ let i, j, cok, cut0 = []; //int
27827
+ cut0.length = this.MAX_SSE;
27828
+
27829
+ for (i = 0; i < k; i++)
27830
+ cut0[i] = i;
27831
+
27832
+ // enumerate cuts of length k //
27833
+ while (1) {
27834
+ // check block sizes in the cut //
27835
+ for (i = cok = 1; i < k; i++) {
27836
+ if (cut0[i] - cut0[i - 1] <= this.c_delta) {
27837
+ cok = 0;
27838
+ break;
27839
+ }
27840
+ }
27841
+ if (cok && (cut0[k - 1] < n - 1))
27842
+ cut0 = this.update_partition(cut0, k, n);
27843
+
27844
+ // generate the next k-tuple of positions //
27845
+ for (j = k - 1; (j >= 0) && (cut0[j] == n - k + j); j--);
27846
+
27847
+ if (j < 0) break;
27848
+
27849
+ cut0[j]++;
27850
+
27851
+ for (i = j + 1; i < k; i++)
27852
+ cut0[i] = cut0[i - 1] + 1;
27853
+ }
27854
+
27855
+ } // end cut_size //
27856
+
27857
+
27858
+
27859
+ // // Process the set of this.elements on this.top of the this.stack. We generate cut sets in
27860
+ // * a limited size range, generally from 1 to 5. For each cut the induced
27861
+ // * partition is considered and its splitting parameters computed. The cut
27862
+ // * that yields the smallest splitting ratio is chosen as the correct one, if
27863
+ // * the ratio is low enough. The subdomains are then placed on the this.stack for
27864
+ // * further consideration.
27865
+ // *
27866
+ // * Subdomains with < this.min_sse SSEs are not allowed to split further, however,
27867
+ // * it is possible to trim fewer than this.min_sse SSEs from a larger domain. E.g.
27868
+ // * a chain with 7 SSEs can be split into a subdomain with 5 SSEs and another
27869
+ // * with 2 SSEs, but the one with 2 SSEs cannot be split further.
27870
+ // *
27871
+ // * Note that the invariant is, that this.stack[top] always points to the next free
27872
+ // * location in this.elements[].
27873
+ // //
27874
+
27875
+ process_set() { let ic = this.icn3d; ic.icn3dui;
27876
+ let i, il, k, n, t, k0, elts = []; //int
27877
+
27878
+ // count the this.elements //
27879
+ //elts = &this.elements[this.stack[this.top - 1]];
27880
+ for(i = this.stack[this.top - 1], il = this.elements.length; i < il; ++i) {
27881
+ elts.push(this.elements[i]);
27882
+ }
27883
+
27884
+ //for (n = 0; *elts > -1; n++, elts++);
27885
+ for (n = 0; n < elts.length && elts[n] > -1; n++);
27886
+
27887
+ // try various cut sizes //
27888
+ k0 = Math.min(n - 1, this.max_csz);
27889
+ this.curr_ne0 = this.curr_ne1 = 0;
27890
+ this.curr_ratio = 100.0;
27891
+
27892
+ for (k = 1; k <= k0; k++)
27893
+ this.cut_size(k, n);
27894
+
27895
+ // pop this.stack //
27896
+ this.top--;
27897
+
27898
+ if (this.curr_ne0 == 0) {
27899
+ // no split took place, save part //
27900
+ t = this.stack[this.top];
27901
+
27902
+ //for (elts = &this.elements[t]; *elts > -1; elts++)
27903
+ // parts[np++] = *elts;
27904
+
27905
+ for (i = t; i < this.elements.length && this.elements[i] > -1; i++)
27906
+ this.parts[this.np++] = this.elements[i];
27907
+
27908
+ this.parts[this.np++] = -1;
27909
+ this.n_doms++;
27910
+ }
27911
+ else {
27912
+ this.save_ratios[this.saved++] = this.curr_ratio;
27913
+
27914
+ if (this.curr_ne0 > this.min_sse) {
27915
+ // push on part 0 //
27916
+ t = this.stack[this.top];
27917
+
27918
+ for (i = 0; i < this.curr_ne0; i++)
27919
+ this.elements[t++] = this.curr_prt0[i];
27920
+
27921
+ this.elements[t++] = -1;
27922
+ this.stack[++this.top] = t;
27923
+ }
27924
+ else {
27925
+ // save part 0 //
27926
+ for (i = 0; i < this.curr_ne0; i++)
27927
+ this.parts[this.np++] = this.curr_prt0[i];
27928
+
27929
+ this.parts[this.np++] = -1;
27930
+ this.n_doms++;
27931
+ }
27932
+
27933
+ if (this.curr_ne1 > this.min_sse) {
27934
+ // push on part 1 //
27935
+ t = this.stack[this.top];
27936
+
27937
+ for (i = 0; i < this.curr_ne1; i++)
27938
+ this.elements[t++] = this.curr_prt1[i];
27939
+
27940
+ this.elements[t++] = -1;
27941
+ this.stack[++this.top] = t;
27942
+ }
27943
+ else {
27944
+ // save part 1 //
27945
+ for (i = 0; i < this.curr_ne1; i++)
27946
+ this.parts[this.np++] = this.curr_prt1[i];
27947
+
27948
+ this.parts[this.np++] = -1;
27949
+ this.n_doms++;
27950
+ }
27951
+ }
27952
+ } // end process_set //
27953
+
27954
+
27955
+
27956
+ // Main driver for chain splitting. //
27957
+ //process_all(let n) { let ic = this.icn3d, me = ic.icn3dui;
27958
+ process_all(n) { let ic = this.icn3d; ic.icn3dui;
27959
+ let i; //int
27960
+
27961
+ // initialize the this.stack //
27962
+ this.top = 1;
27963
+ this.stack[0] = this.np = this.n_doms = 0;
27964
+ this.saved = 0;
27965
+
27966
+ for (i = 0; i < n; i++)
27967
+ this.elements[i] = i;
27968
+
27969
+ this.elements[n] = -1;
27970
+
27971
+ // recursively split the chain into domains //
27972
+ while (this.top > 0) {
27973
+ this.process_set();
27974
+ }
27975
+ } // end process_all //
27976
+
27977
+ // Output the domains. For S we number the this.elements 1, 2, ..., n. //
27978
+ //output(let n, int* prts) { let ic = this.icn3d, me = ic.icn3dui;
27979
+ output(n) { let ic = this.icn3d; ic.icn3dui;
27980
+ let i, k; //int
27981
+
27982
+ let prts = [];
27983
+
27984
+ // zap the output array //
27985
+ for (i = 0; i < 2*n; i++)
27986
+ prts.push(0);
27987
+
27988
+ // now write out the subdomains //
27989
+ for (i = k = 0; k < this.n_doms; i++) {
27990
+ prts[i] = this.parts[i] + 1;
27991
+
27992
+ if (this.parts[i] < 0)
27993
+ k++;
27994
+ }
27995
+
27996
+ return prts;
27997
+ } // end output //
27998
+
27999
+
28000
+
28001
+ // // S-interface to the chain-splitting program.
28002
+ // *
28003
+ // * Explanation of parameters:
28004
+ // *
28005
+ // * ne - number of secondary structure this.elements (SSEs)
28006
+ // * cts - contact count matrix
28007
+ // * elt_sz - sizes of SSEs
28008
+ // * grps - element group indicators
28009
+ // * sratio - splitting ratio
28010
+ // * msize - min size of a split domain
28011
+ // * m_sse - min number of SSEs required in a split part
28012
+ // * mcsz - max cut size, i.e. max number of split points
28013
+ // * avg_cts - mean number of internal contacts for a domain
28014
+ // * c_delt - cut set parameter
28015
+ // * ncf0 - size factor for number of internal contacts
28016
+ // * prts - output listing of domains
28017
+ // * n_saved - number of this.saved splitting ratios
28018
+ // * ratios - splitting ratios
28019
+ // * ret - success/failure indicator
28020
+ // * verb - flag to turn off/on splitting information
28021
+ // //
28022
+
28023
+ //new_split_chain(let ne, let sratio, let msize, let m_sse, let mcsz, let avg_cts,
28024
+ // let c_delt, let ncf0, int* prts, int* n_saved, let* ratios) { let ic = this.icn3d, me = ic.icn3dui;
28025
+ new_split_chain(ne, sratio, msize, m_sse, mcsz, avg_cts,
28026
+ c_delt, ncf0, prts, n_saved, ratios) { let ic = this.icn3d; ic.icn3dui;
28027
+ let i; //int
28028
+
28029
+ this.split_ratio = sratio;
28030
+ this.min_size = msize;
28031
+ this.min_sse = m_sse;
28032
+ this.max_csz = mcsz;
28033
+ this.mean_cts = avg_cts;
28034
+ this.c_delta = c_delt;
28035
+ this.nc_fact = ncf0;
28036
+
28037
+ this.process_all(ne);
28038
+ //this.output(ne, prts);
28039
+ this.parts = this.output(ne);
28040
+ n_saved = this.saved;
28041
+ for (i = 0; i < this.saved; i++)
28042
+ ratios[i] = this.save_ratios[i];
28043
+
28044
+ return n_saved;
28045
+
28046
+ } // end new_split_chain //
28047
+
28048
+ //
28049
+ // Actually, here is a better method that is also simple!
28050
+ //
28051
+ // If there are N atoms (residues) this algorithm should usually run in
28052
+ // time O(N^4/3), and usually even much faster! In very unusual cases
28053
+ // it could take quadratic time. The key idea is that atoms are not
28054
+ // infinitely compressible, i.e. only a fixed number will fit in a given
28055
+ // region of space. So if the protein is roughly spherical, there will
28056
+ // only be O(N^1/3) atoms close to any given diameter. Therefore, a
28057
+ // bound on the number of iterations of the inner loop is O(N^1/3).
28058
+ //
28059
+ // For an elongated protein that happens to have the x-axis normal to
28060
+ // the long axis, then it is possible for the inner loop to take time
28061
+ // O(N), in which case the whole takes O(N^2). But this should rarely,
28062
+ // if ever, occur in practice. It would also be possible beforehand to
28063
+ // choose the axis with the largest variance.
28064
+ //
28065
+
28066
+ // typedef struct res_struct {
28067
+ // let rnum;
28068
+ // let x, y, z;
28069
+ // } ResRec;
28070
+
28071
+ //list< pair< pair< int, let >, let > >
28072
+ //c2b_AlphaContacts(let n0, let* x0, let* y0, let* z0,
28073
+ // const let incr = 4, const let dcut = 8.0) { let ic = this.icn3d, me = ic.icn3dui;
28074
+ c2b_AlphaContacts(n0, x0, y0, z0, dcut) { let ic = this.icn3d; ic.icn3dui;
28075
+ //if(!incr) incr = 4;
28076
+ if(!dcut) dcut = this.dcut;
28077
+
28078
+ let list_cts = [], list_rr = [];
28079
+
28080
+ for (let i = 0; i < n0; i++) {
28081
+ // don't include residues with missing coordinates
28082
+ //if ((x0[i] == MissingCoord) || (y0[i] == MissingCoord) || (z0[i] == MissingCoord))
28083
+ if (!x0[i]|| !y0[i] || !z0[i])
28084
+ continue;
28085
+
28086
+ //ResRec rr0;
28087
+ let rr0 = {};
28088
+ rr0.rnum = i + 1;
28089
+ rr0.x = x0[i];
28090
+ rr0.y = y0[i];
28091
+ rr0.z = z0[i];
28092
+ list_rr.push(rr0);
28093
+ }
28094
+
28095
+ list_rr.sort(function(rr1, rr2) {
28096
+ return rr1.x - rr2.x;
28097
+ });
28098
+
28099
+ //let rrit1, rrit2, rrbeg;
28100
+ let i, j, len = list_rr.length;
28101
+
28102
+ //for (rrit1 = list_rr.begin(); rrit1 != list_rr.end(); rrit1++) {
28103
+ for (i = 0; i < len; ++i) {
28104
+ //ResRec rr1 = *rrit1;
28105
+ let rr1 = list_rr[i];
28106
+ let x1 = rr1.x;
28107
+ let y1 = rr1.y;
28108
+ let z1 = rr1.z;
28109
+ //rrbeg = rrit1;
28110
+ //rrbeg++;
28111
+
28112
+ //for (rrit2 = rrbeg; rrit2 != list_rr.end(); rrit2++) {
28113
+ for (j = i + 1; j < len; ++j) {
28114
+ //ResRec rr2 = *rrit2;
28115
+ let rr2 = list_rr[j];
28116
+ if ((rr1.rnum - rr2.rnum <= 3) && (rr2.rnum - rr1.rnum <= 3)) continue;
28117
+ let x2 = rr2.x;
28118
+ let y2 = rr2.y;
28119
+ let z2 = rr2.z;
28120
+
28121
+ if (x2 > x1 + dcut)
28122
+ break;
28123
+
28124
+ // x1 <= x2 <= x1 + dcut so compare
28125
+ let sum = (x1 - x2)*(x1 - x2);
28126
+ sum += (y1 - y2)*(y1 - y2);
28127
+ sum += (z1 - z2)*(z1 - z2);
28128
+ let d0 = Math.sqrt(sum);
28129
+ if (d0 > dcut) continue;
28130
+ //pair< pair< int, let >, let > lpair;
28131
+ //pair< int, let > rpair;
28132
+ let lpair = {}, rpair = {};
28133
+
28134
+ if (rr1.rnum < rr2.rnum) {
28135
+ rpair.first = rr1.rnum;
28136
+ rpair.second = rr2.rnum;
28137
+ }
28138
+ else {
28139
+ rpair.first = rr2.rnum;
28140
+ rpair.second = rr1.rnum;
28141
+ }
28142
+
28143
+ lpair.first = rpair;
28144
+ lpair.second = d0;
28145
+ list_cts.push(lpair);
28146
+ }
28147
+ }
28148
+
28149
+ return list_cts;
28150
+
28151
+ } // end c2b_AlphaContacts
28152
+
28153
+
28154
+
28155
+ //
28156
+ // Creates a table, actually a graph, of the contacts between SSEs.
28157
+ //
28158
+
28159
+ //static map< pair< int, let >, let >
28160
+ //c2b_ContactTable(vector<int>& v1, vector<int>& v2) { let ic = this.icn3d, me = ic.icn3dui;
28161
+ c2b_ContactTable(v1, v2) { let ic = this.icn3d; ic.icn3dui;
28162
+ let cmap = {};
28163
+ let n0 = v1.length; //unsigned int
28164
+
28165
+ if (n0 != v2.length) {
28166
+ // problem!
28167
+
28168
+ return cmap;
28169
+ }
28170
+
28171
+ for (let i = 0; i < n0; i++) {
28172
+ let e1 = v1[i];
28173
+ let e2 = v2[i];
28174
+ //pair<int, int> epr;
28175
+ //let epr = {};
28176
+ //epr.first = e1;
28177
+ //epr.second = e2;
28178
+ let epr = e1 + '_' + e2;
28179
+
28180
+ //if (cmap.count(epr) == 0) {
28181
+ if (!cmap[epr]) {
28182
+ cmap[epr] = 1;
28183
+ }
28184
+ else
28185
+ cmap[epr]++;
28186
+ }
28187
+
28188
+ return cmap;
28189
+
28190
+ } // end c2b_ContactTable
28191
+
28192
+
28193
+ //https://www.geeksforgeeks.org/number-groups-formed-graph-friends/
28194
+ countUtil(ss1, sheetNeighbor, existing_groups) {
28195
+ this.visited[ss1] = true;
28196
+ if(!this.groupnum2sheet[existing_groups]) this.groupnum2sheet[existing_groups] = [];
28197
+ this.groupnum2sheet[existing_groups].push(parseInt(ss1));
28198
+
28199
+ for(let ss2 in sheetNeighbor[ss1]) {
28200
+ if (!this.visited[ss2]) {
28201
+ this.countUtil(ss2, sheetNeighbor, existing_groups);
28202
+ }
28203
+ }
28204
+ }
28205
+
28206
+ //
28207
+ // Residue ranges of the Vast domains, per protein chain.
28208
+ //
28209
+
28210
+ //
28211
+ // Subdomain definition rules are as follows; let m0 = minSSE:
28212
+ //
28213
+ // 1. A subdomain with <= m0 SSEs cannot be split.
28214
+ //
28215
+ // 2. A subdomain cannot be split into two this.parts, both with < m0 SSEs.
28216
+ //
28217
+ // 3. However, a subdomain can be trimmed, i.e. split into two this.parts,
28218
+ // one with < m0 SSEs.
28219
+ //
28220
+ //c2b_NewSplitChain(string asymId, let seqLen, let* x0, let* y0, let* z0) { let ic = this.icn3d, me = ic.icn3dui;
28221
+ // x0, y0, z0: array of x,y,z coordinates of C-alpha atoms
28222
+ c2b_NewSplitChain(chnid, dcut) { let ic = this.icn3d; ic.icn3dui;
28223
+ let x0 = [], y0 = [], z0 = [];
28224
+
28225
+ //substruct: array of secondary structures, each of which has the keys: From (1-based), To (1-based), Sheet (0 or 1)
28226
+ let substruct = [];
28227
+ // sheets: array of sheets, each of which has the key: sheet_num (beta sandwich has two sheets, e.g., 0 and 1), adj_strand1 (not used), adj_strand2
28228
+ let sheets = [];
28229
+
28230
+ let substructItem = {};
28231
+ let resiOffset = 0;
28232
+ for(let i = 0; i < ic.chainsSeq[chnid].length; ++i) {
28233
+ let resi = ic.chainsSeq[chnid][i].resi;
28234
+ if(i == 0) {
28235
+ resiOffset = resi - 1;
28236
+
28237
+ for(let j = 0; j < resiOffset; ++j) {
28238
+ x0.push(undefined);
28239
+ y0.push(undefined);
28240
+ z0.push(undefined);
28241
+ }
28242
+ }
28243
+
28244
+ let resid = chnid + "_" + resi;
28245
+ let atom = ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.residues[resid]);
28246
+
28247
+ if(atom) {
28248
+ x0.push(atom.coord.x);
28249
+ y0.push(atom.coord.y);
28250
+ z0.push(atom.coord.z);
28251
+ }
28252
+ else {
28253
+ x0.push(undefined);
28254
+ y0.push(undefined);
28255
+ z0.push(undefined);
28256
+ }
28257
+
28258
+ if(!atom) continue;
28259
+
28260
+ if(atom.ssend) {
28261
+ substructItem.To = parseInt(resi);
28262
+ substructItem.Sheet = (atom.ss == 'sheet') ? true : false;
28263
+ substruct.push(substructItem);
28264
+ substructItem = {};
28265
+ }
28266
+
28267
+ // a residue could be both start and end. check ssend first, then check ssbegin
28268
+ if(atom.ssbegin) {
28269
+ substructItem.From = parseInt(resi);
28270
+ }
28271
+ }
28272
+
28273
+ let nsse = substruct.length;
28274
+
28275
+ if (nsse <= 3)
28276
+ // too small, can't split or trim
28277
+ return;
28278
+
28279
+ if (nsse > this.MAX_SSE) {
28280
+ // we have a problem...
28281
+
28282
+ return;
28283
+ }
28284
+
28285
+ let seqLen = ic.chainsSeq[chnid].length + resiOffset;
28286
+
28287
+ // get a list of Calpha-Calpha contacts
28288
+ ///list< pair< pair< int, let >, let > >
28289
+ let cts = this.c2b_AlphaContacts(seqLen, x0, y0, z0, dcut);
28290
+
28291
+ //
28292
+ // Produce a "map" of the SSEs, i.e. vec_sse[i] = 0 means residue i + 1
28293
+ // is in a loop, and vec_sse[i] = k means residue i + 1 belongs to SSE
28294
+ // number k.
28295
+ //
28296
+ let vec_sse = []; //vector<int>
28297
+
28298
+ for (let i = 0; i < seqLen; i++)
28299
+ vec_sse.push(0);
28300
+
28301
+ let hasSheets = false;
28302
+
28303
+ //substruct: array of secondary structures, each of which has the keys: From, To, Sheet (0, 1)
28304
+ for (let i = 0; i < substruct.length; i++) {
28305
+ //SSE_Rec sserec = substruct[i];
28306
+ let sserec = substruct[i];
28307
+ let From = sserec.From;
28308
+ let To = sserec.To;
28309
+ this.elt_size[i] = To - From + 1;
28310
+
28311
+ // double-check indexing OK???
28312
+ for (let j = From; j <= To; j++)
28313
+ vec_sse[j - 1] = i + 1;
28314
+
28315
+ //if (sserec.Sheet > 0)
28316
+ if (sserec.Sheet)
28317
+ hasSheets = true;
28318
+ }
28319
+
28320
+ // produce the SSE contact lists
28321
+ let vec_cts1 = [], vec_cts2 = [], vec_cts1a = [], vec_cts2a = [];
28322
+
28323
+ //for (ctsit = cts.begin(); ctsit != cts.end(); ctsit++) {
28324
+ for (let i = 0, il = cts.length; i < il; ++i) {
28325
+ //pair< pair< int, let >, let > epr = *ctsit;
28326
+ //pair< int, let > respair = epr.first;
28327
+ let epr = cts[i];
28328
+ let respair = epr.first;
28329
+ let sse1 = vec_sse[respair.first - 1];
28330
+ let sse2 = vec_sse[respair.second - 1];
28331
+ // could be 0 or null
28332
+ if ((sse1 <= 0) || (sse2 <= 0) || !sse1 || !sse2) continue;
28333
+ vec_cts1.push(sse1);
28334
+ vec_cts2.push(sse2);
28335
+ if (sse1 == sse2) continue;
28336
+ vec_cts1a.push(sse1);
28337
+ vec_cts2a.push(sse2);
28338
+ }
28339
+
28340
+ // this symmetrizes the contact data
28341
+ for (let i = 0; i < vec_cts1a.length; i++) {
28342
+ vec_cts1.push(vec_cts2a[i]);
28343
+ vec_cts2.push(vec_cts1a[i]);
28344
+ }
28345
+
28346
+ // add dummy contacts
28347
+ for (let i = 0; i < nsse; i++) {
28348
+ vec_cts1.push(i + 1);
28349
+ vec_cts2.push(i + 1);
28350
+ }
28351
+
28352
+ // create contact counts from the contacts/interactions
28353
+ //map< pair< int, let >, let > ctable = this.c2b_ContactTable(vec_cts1, vec_cts2);
28354
+ let ctable = this.c2b_ContactTable(vec_cts1, vec_cts2);
28355
+
28356
+ // neighbor list of each sheet
28357
+ let sheetNeighbor = {};
28358
+ for(let pair in ctable) {
28359
+ let ssPair = pair.split('_'); // 1-based
28360
+ let ss1 = parseInt(ssPair[0]);
28361
+ let ss2 = parseInt(ssPair[1]);
28362
+
28363
+ // both are sheets
28364
+ if(substruct[ss1 - 1].Sheet && substruct[ss2 - 1].Sheet) {
28365
+ if(!sheetNeighbor[ss1]) sheetNeighbor[ss1] = {};
28366
+ if(!sheetNeighbor[ss2]) sheetNeighbor[ss2] = {};
28367
+
28368
+ sheetNeighbor[ss1][ss2] = 1;
28369
+ sheetNeighbor[ss2][ss1] = 1;
28370
+ }
28371
+ }
28372
+
28373
+ //https://www.geeksforgeeks.org/number-groups-formed-graph-friends/
28374
+ let existing_groups = 0;
28375
+ let sheet2sheetnum = {};
28376
+ this.groupnum2sheet = {};
28377
+ this.visited = {};
28378
+ for (let ss1 in sheetNeighbor) {
28379
+ this.visited[ss1] = false;
28380
+ }
28381
+
28382
+ // get this.groupnum2sheet
28383
+ for (let ss1 in sheetNeighbor) {
28384
+ // If not in any group.
28385
+ if (this.visited[ss1] == false) {
28386
+ existing_groups++;
28387
+
28388
+ this.countUtil(ss1, sheetNeighbor, existing_groups);
28389
+ }
28390
+ }
28391
+
28392
+ // get sheet2sheetnum
28393
+ // each neighboring sheet willbe represented by the sheet with the smallest sse
28394
+ for(let groupnum in this.groupnum2sheet) {
28395
+ let ssArray = this.groupnum2sheet[groupnum].sort();
28396
+ for(let i = 0, il = ssArray.length; i < il; ++i) {
28397
+ sheet2sheetnum[ssArray[i]] = ssArray[0];
28398
+ }
28399
+ }
28400
+
28401
+ for (let i = 0; i < nsse; i++) {
28402
+ if(substruct[i].Sheet) {
28403
+ let sheetsItem = {};
28404
+ if(sheet2sheetnum[i+1]) {
28405
+ sheetsItem.sheet_num = sheet2sheetnum[i+1];
28406
+ sheetsItem.adj_strand2 = 1;
28407
+ sheetsItem.sse = i + 1;
28408
+ }
28409
+ else {
28410
+ sheetsItem.sheet_num = 0;
28411
+ sheetsItem.adj_strand2 = 0;
28412
+ sheetsItem.sse = i + 1;
28413
+ }
28414
+
28415
+ sheets.push(sheetsItem);
28416
+ }
28417
+ }
28418
+
28419
+ //
28420
+ // Correct for dummy contacts; they're present to ensure that the
28421
+ // table gives the right result in the possible case there is an
28422
+ // element with no contacts.
28423
+ //
28424
+ for (let i = 0; i < nsse; i++) {
28425
+ for (let j = 0; j < nsse; j++) {
28426
+ //pair<int, int> epr;
28427
+ //let epr = {};
28428
+ //epr.first = i + 1;
28429
+ //epr.second = j + 1;
28430
+ let epr = (i+1).toString() + '_' + (j+1).toString();
28431
+
28432
+ //if (ctable.count(epr) == 0)
28433
+ if (!ctable[epr])
28434
+ this.ctc_cnt[i][j] = 0;
28435
+ else {
28436
+ let cnt = ctable[epr];
28437
+ if (i == j) cnt--; // subtract dummy contact
28438
+ this.ctc_cnt[i][j] = cnt;
28439
+ this.ctc_cnt[j][i] = cnt;
28440
+ }
28441
+ }
28442
+ }
28443
+
28444
+ let minStrand = 6;
28445
+
28446
+ if (hasSheets) {
28447
+ //sheets: array of sheets, each of which has the key: sheet_num (number of strands), adj_strand1, adj_strand2
28448
+
28449
+ let cnt = 0;
28450
+
28451
+ for (let i = 0; i < sheets.length; i++) {
28452
+ //BetaSheet_Rec bsrec = sheets[i];
28453
+ let bsrec = sheets[i];
28454
+
28455
+ //if ((bsrec.sheet_num > 0) && (this.elt_size[i] >= minStrand) && (bsrec.adj_strand2 != 0))
28456
+ if ((bsrec.sheet_num > 0) && (this.elt_size[bsrec.sse - 1] >= minStrand) && (bsrec.adj_strand2 != 0))
28457
+ cnt++;
28458
+ }
28459
+
28460
+ for (let i = 0; i < nsse; i++) {
28461
+ //this.group_num[i] = (cnt == 0) ? i + 1 : 0;
28462
+ this.group_num[i] = i + 1;
28463
+ }
28464
+
28465
+ if (cnt> 0) {
28466
+ for (let i = 0; i < sheets.length; i++) {
28467
+ let bsrec = sheets[i];
28468
+ this.group_num[bsrec.sse - 1] = bsrec.sheet_num;
28469
+ }
28470
+ }
28471
+ }
28472
+ else {
28473
+ for (let i = 0; i < nsse; i++)
28474
+ this.group_num[i] = i + 1;
28475
+ }
28476
+
28477
+ let sratio = 0.25;
28478
+ let minSize = 25;
28479
+ let maxCsz = 4;
28480
+ let avgCts = 0.0;
28481
+ let ncFact = 0.0;
28482
+ let cDelta = 3;
28483
+ let minSSE = 3;
28484
+
28485
+ // call the domain splitter
28486
+ this.parts = [];
28487
+ this.parts.length = 2*this.MAX_SSE;
28488
+ let ratios = [];
28489
+ ratios.length = this.MAX_SSE;
28490
+ let n_saved = 0;
28491
+
28492
+ for (let i = 0; i < nsse; i++) {
28493
+ this.parts[2*i] = this.parts[2*i + 1] = 0;
28494
+ ratios[i] = 0.0;
28495
+ }
28496
+
28497
+ n_saved = this.new_split_chain(nsse, sratio, minSize, minSSE, maxCsz, avgCts, cDelta, ncFact, this.parts, n_saved, ratios);
28498
+
28499
+ // save domain data
28500
+ //list< vector< let > > list_parts;
28501
+ let list_parts = [];
28502
+
28503
+ if (n_saved > 0) {
28504
+ // splits occurred...
28505
+ let j = 0;
28506
+
28507
+ for (let i = 0; i <= n_saved; i++) {
28508
+ //vector<int> sselst;
28509
+ let sselst = [];
28510
+ //sselst.clear();
28511
+
28512
+ while (j < 2*nsse) {
28513
+ let sse0 = this.parts[j++];
28514
+
28515
+ if (sse0 == 0) {
28516
+ list_parts.push(sselst);
28517
+ break;
28518
+ }
28519
+ else
28520
+ sselst.push(sse0);
28521
+ }
28522
+ }
28523
+ }
28524
+
28525
+ list_parts.sort(function(v1, v2) {
28526
+ return v1[0] - v2[0];
28527
+ });
28528
+
28529
+ // determine residue ranges for each subdomain
28530
+ let subdomains = [];
28531
+
28532
+ //for (lplet = list_parts.begin(); lplet != list_parts.end(); lpint++) {
28533
+ for (let index = 0, indexl = list_parts.length; index < indexl; ++index) {
28534
+ //vector<int> prts = *lpint;
28535
+ let prts = list_parts[index];
28536
+ //vector<int> resflags;
28537
+ //resflags.clear();
28538
+ let resflags = [];
28539
+
28540
+ // a domain must have at least 3 SSEs...
28541
+ if (prts.length <= 2) continue;
28542
+
28543
+ for (let i = 0; i < seqLen; i++)
28544
+ resflags.push(0);
28545
+
28546
+ for (let i = 0; i < prts.length; i++) {
28547
+ let k = prts[i] - 1;
28548
+
28549
+ if ((k < 0) || (k >= substruct.length)) {
28550
+ return;
28551
+ }
28552
+
28553
+ //SSE_Rec sserec = substruct[k];
28554
+ let sserec = substruct[k];
28555
+ let From = sserec.From;
28556
+ let To = sserec.To;
28557
+
28558
+ for (let j = From; j <= To; j++)
28559
+ resflags[j - 1] = 1;
28560
+
28561
+ if ((k == 0) && (From > 1)) {
28562
+ // residues with negative residue numbers will not be included
28563
+ for (let j = 1; j < From; j++)
28564
+ resflags[j - 1] = 1;
28565
+ }
28566
+
28567
+ if ((k == substruct.length - 1) && (To < seqLen)) {
28568
+ for (let j = To + 1; j <= seqLen; j++)
28569
+ resflags[j - 1] = 1;
28570
+ }
28571
+
28572
+ // left side
28573
+ if (k > 0) {
28574
+ //SSE_Rec sserec1 = substruct[k - 1];
28575
+ let sserec1 = substruct[k - 1];
28576
+ let To1 = sserec1.To;
28577
+ //let ll = (int) floor(0.5*((let) (From - To1 - 1)));
28578
+ let ll = parseInt(0.5 * (From - To1 - 1));
28579
+
28580
+ if (ll > 0) {
28581
+ for (let j = From - ll; j <= From - 1; j++)
28582
+ resflags[j - 1] = 1;
28583
+ }
28584
+ }
28585
+
28586
+ // right side
28587
+ if (k < substruct.length - 1) {
28588
+ //SSE_Rec sserec1 = substruct[k + 1];
28589
+ let sserec1 = substruct[k + 1];
28590
+ let From1 = sserec1.From;
28591
+ //let ll = (int) ceil(0.5*((let) (From1 - To - 1)));
28592
+ // let ft = From1 - To - 1;
28593
+ // let ll = parseInt(ft/2);
28594
+ // if (ft % 2 == 1) ll++;
28595
+ let ll = parseInt(0.5 * (From1 - To - 1) + 0.5);
28596
+
28597
+ if (ll > 0) {
28598
+ for (let j = To + 1; j <= To + ll; j++)
28599
+ resflags[j - 1] = 1;
28600
+ }
28601
+ }
28602
+ }
28603
+
28604
+ // extract the continguous segments
28605
+ let inseg = false;
28606
+ let startseg;
28607
+ //vector<int> segments;
28608
+ //segments.clear();
28609
+ let segments = [];
28610
+
28611
+ for (let i = 0; i < seqLen; i++) {
28612
+ let rf = resflags[i];
28613
+
28614
+ if (!inseg && (rf == 1)) {
28615
+ // new segment starts here
28616
+ startseg = i + 1;
28617
+ inseg = true;
28618
+ continue;
28619
+ }
28620
+
28621
+ if (inseg && (rf == 0)) {
28622
+ // segment ends
28623
+ segments.push(startseg);
28624
+ segments.push(i);
28625
+ inseg = false;
28626
+ }
28627
+ }
28628
+
28629
+ // check for the last segment
28630
+ if (inseg) {
28631
+ segments.push(startseg);
28632
+ segments.push(seqLen);
28633
+ }
28634
+
28635
+ subdomains.push(segments);
28636
+ }
28637
+
28638
+ //console.log("subdomains: " + JSON.stringify(subdomains));
28639
+
28640
+ return subdomains;
28641
+ } // end c2b_NewSplitChain
28642
+ }
28643
+
27548
28644
  /**
27549
28645
  * @author Jiyao Wang <wangjiy@ncbi.nlm.nih.gov> / https://github.com/ncbi/icn3d
27550
28646
  */
@@ -29866,6 +30962,8 @@ class Picking {
29866
30962
  transformation.quaternion._y = parseFloat(ic.quaternion._y).toPrecision(5);
29867
30963
  transformation.quaternion._z = parseFloat(ic.quaternion._z).toPrecision(5);
29868
30964
  transformation.quaternion._w = parseFloat(ic.quaternion._w).toPrecision(5);
30965
+
30966
+ /*
29869
30967
  if(ic.bAddCommands) {
29870
30968
  ic.commands.push('pickatom ' + atom.serial + '|||' + ic.transformCls.getTransformationStr(transformation));
29871
30969
  ic.optsHistory.push(me.hashUtilsCls.cloneHash(ic.opts));
@@ -29877,6 +30975,9 @@ class Picking {
29877
30975
  if( $( "#" + ic.pre + "logtext" ).length ) {
29878
30976
  $("#" + ic.pre + "logtext").val("> " + ic.logs.join("\n> ") + "\n> ").scrollTop($("#" + ic.pre + "logtext")[0].scrollHeight);
29879
30977
  }
30978
+ */
30979
+ me.htmlCls.clickMenuCls.setLogCmd('pickatom ' + atom.serial, true);
30980
+
29880
30981
  // update the interaction flag
29881
30982
  ic.bSphereCalc = false;
29882
30983
  //me.htmlCls.clickMenuCls.setLogCmd('set calculate sphere false', true);
@@ -31253,11 +32354,16 @@ class ApplyCommand {
31253
32354
  ic.bGlycansCartoon = false;
31254
32355
  }
31255
32356
  }
32357
+ else if(command.indexOf('save html') == 0) {
32358
+ let id = command.substr(command.lastIndexOf(' ') + 1);
32359
+ me.htmlCls.eventsCls.saveHtml(id);
32360
+ }
31256
32361
 
31257
32362
  // special, select ==========
31258
32363
 
31259
32364
  else if(command.indexOf('select displayed set') !== -1) {
31260
- ic.hAtoms = me.hashUtilsCls.cloneHash(ic.dAtoms);
32365
+ //ic.hAtoms = me.hashUtilsCls.cloneHash(ic.dAtoms);
32366
+ ic.hAtoms = me.hashUtilsCls.cloneHash(ic.viewSelectionAtoms);
31261
32367
  ic.hlUpdateCls.updateHlAll();
31262
32368
  }
31263
32369
  else if(command.indexOf('select prop') !== -1) {
@@ -32104,11 +33210,12 @@ class Resid2spec {
32104
33210
 
32105
33211
  atoms2spec(atomHash) {var ic = this.icn3d; ic.icn3dui;
32106
33212
  let spec = "";
32107
-
32108
33213
  let i = 0;
32109
33214
  let structureHash = {}, chainHash = {}, resiHash = {};
33215
+
33216
+ let atom;
32110
33217
  for(let serial in atomHash) {
32111
- let atom = ic.atoms[serial];
33218
+ atom = ic.atoms[serial];
32112
33219
  if(i > 0) {
32113
33220
  spec += ' or ';
32114
33221
  }
@@ -34015,7 +35122,7 @@ class MmcifParser {
34015
35122
 
34016
35123
  // not all listed residues are considered missing, e.g., PDB ID 4OR2, only the firts four residues are considered missing
34017
35124
  if(!isNaN(resi) &&(prevMissingChain == '' ||(chain != prevMissingChain) ||(chain == prevMissingChain && resi > maxMissingResi)) ) {
34018
- chainMissingResidueArray[chainNum].push(resObject);
35125
+ ic.chainMissingResidueArray[chainNum].push(resObject);
34019
35126
 
34020
35127
  maxMissingResi = resi;
34021
35128
  prevMissingChain = chain;
@@ -35167,7 +36274,7 @@ class ShowAnno {
35167
36274
  // the missing residues at the end of the seq will be filled up in the API showNewTrack()
35168
36275
  let nGap = 0;
35169
36276
  ic.alnChainsSeq[chnid] = [];
35170
- let offset =(ic.chainid2offset[chnid]) ? ic.chainid2offset[chnid] : 0;
36277
+ let offset =(ic.chainid2offset[chnid]) ? ic.chainid2offset[chnid] : 0;
35171
36278
  for(let i = 0, il = targetSeq.length; i < il; ++i) {
35172
36279
  //text += ic.showSeqCls.insertGap(chnid, i, '-', true);
35173
36280
  if(ic.targetGapHash.hasOwnProperty(i)) {
@@ -35540,7 +36647,8 @@ class AnnoDomain {
35540
36647
  let pdbArray = Object.keys(ic.structures);
35541
36648
  // show 3D domains
35542
36649
  let pdbid = pdbArray[index];
35543
- let url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&domain&molinfor&uid=" + pdbid;
36650
+ me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&domain&molinfor&uid=" + pdbid;
36651
+
35544
36652
  if(index == 0 && ic.mmdb_data !== undefined) {
35545
36653
  for(let chnid in ic.protein_chainid) {
35546
36654
  if(chnid.indexOf(pdbid) !== -1) {
@@ -35556,6 +36664,43 @@ class AnnoDomain {
35556
36664
  }
35557
36665
  }
35558
36666
  else {
36667
+ // calculate 3D domains on-the-fly
36668
+ //ic.protein_chainid[chainArray[i]]
36669
+ let data = {};
36670
+ data.domains = {};
36671
+ for(let chainid in ic.chains) {
36672
+ let structure = chainid.substr(0, chainid.indexOf('_'));
36673
+ if(pdbid == structure && ic.protein_chainid.hasOwnProperty(chainid)) {
36674
+ data.domains[chainid] = {};
36675
+ data.domains[chainid].domains = [];
36676
+
36677
+ let subdomains = ic.domain3dCls.c2b_NewSplitChain(chainid);
36678
+ for(let i = 0, il = subdomains.length; i < il; ++i) {
36679
+ // domain item: {"sdid":1722375,"intervals":[[1,104],[269,323]]}
36680
+ let domain = {};
36681
+ domain.intervals = [];
36682
+
36683
+ for(let j = 0, jl = subdomains[i].length; j < jl; j += 2) {
36684
+ domain.intervals.push([subdomains[i][j], subdomains[i][j+1]]);
36685
+ }
36686
+
36687
+ data.domains[chainid].domains.push(domain);
36688
+ }
36689
+ }
36690
+ }
36691
+
36692
+ ic.mmdb_dataArray[index] = data;
36693
+ let bCalcDirect = true;
36694
+ for(let chnid in ic.protein_chainid) {
36695
+ if(chnid.indexOf(pdbid) !== -1) {
36696
+ thisClass.showDomainWithData(chnid, ic.mmdb_dataArray[index], bCalcDirect);
36697
+ }
36698
+ }
36699
+
36700
+ ic.bAjax3ddomain = true;
36701
+ ic.bAjaxDoneArray[index] = true;
36702
+
36703
+ /*
35559
36704
  $.ajax({
35560
36705
  url: url,
35561
36706
  dataType: 'json',
@@ -35619,6 +36764,7 @@ class AnnoDomain {
35619
36764
  return;
35620
36765
  }
35621
36766
  });
36767
+ */
35622
36768
  }
35623
36769
  }
35624
36770
 
@@ -35637,28 +36783,36 @@ class AnnoDomain {
35637
36783
  this.showDomainPerStructure(i);
35638
36784
  }
35639
36785
  }
35640
- showDomainWithData(chnid, data) { let ic = this.icn3d, me = ic.icn3dui;
36786
+ showDomainWithData(chnid, data, bCalcDirect) { let ic = this.icn3d, me = ic.icn3dui;
35641
36787
  let html = '<div id="' + ic.pre + chnid + '_domainseq_sequence" class="icn3d-dl_sequence">';
35642
36788
  let html2 = html;
35643
36789
  let html3 = html;
35644
36790
  let domainArray, proteinname;
35645
36791
  let pos = chnid.indexOf('_');
35646
36792
  let chain = chnid.substr(pos + 1);
35647
- let molinfo = data.moleculeInfor;
35648
- let currMolid;
35649
- for(let molid in molinfo) {
35650
- if(molinfo[molid].chain === chain) {
35651
- currMolid = molid;
35652
- proteinname = molinfo[molid].name;
35653
- break;
35654
- }
35655
- }
35656
- if(currMolid !== undefined && data.domains[currMolid] !== undefined) {
35657
- domainArray = data.domains[currMolid].domains;
36793
+
36794
+ if(bCalcDirect) {
36795
+ proteinname = chnid;
36796
+ domainArray = data.domains[chnid].domains;
35658
36797
  }
35659
- if(domainArray === undefined) {
35660
- domainArray = [];
36798
+ else {
36799
+ let molinfo = data.moleculeInfor;
36800
+ let currMolid;
36801
+ for(let molid in molinfo) {
36802
+ if(molinfo[molid].chain === chain) {
36803
+ currMolid = molid;
36804
+ proteinname = molinfo[molid].name;
36805
+ break;
36806
+ }
36807
+ }
36808
+ if(currMolid !== undefined && data.domains[currMolid] !== undefined) {
36809
+ domainArray = data.domains[currMolid].domains;
36810
+ }
36811
+ if(domainArray === undefined) {
36812
+ domainArray = [];
36813
+ }
35661
36814
  }
36815
+
35662
36816
  for(let index = 0, indexl = domainArray.length; index < indexl; ++index) {
35663
36817
  //var fulltitle = '3D domain ' +(index+1).toString() + ' of ' + proteinname + '(PDB ID: ' + data.pdbId + ')';
35664
36818
  let fulltitle = '3D domain ' +(index+1).toString() + ' of ' + proteinname;
@@ -35681,7 +36835,7 @@ class AnnoDomain {
35681
36835
  }
35682
36836
 
35683
36837
  // use the NCBI residue number, and convert to PDB residue number during selection
35684
- if(ic.bNCBI) {
36838
+ if(ic.bNCBI || bCalcDirect) {
35685
36839
  fromArray.push(domainFrom);
35686
36840
  toArray.push(domainTo);
35687
36841
  }
@@ -37780,6 +38934,18 @@ class Diagram2d {
37780
38934
  ic.bSelectResidue = false;
37781
38935
  */
37782
38936
  });
38937
+
38938
+ $(document).on("click", "#" + ic.pre + "dl_alignerrormap .icn3d-interaction", function(e) { thisClass.icn3d;
38939
+ e.stopImmediatePropagation();
38940
+
38941
+ thisClass.clickInteraction(this);
38942
+ });
38943
+
38944
+ $(document).on("click", "#" + ic.pre + "dl_alignerrormap .icn3d-node", function(e) { thisClass.icn3d;
38945
+ e.stopImmediatePropagation();
38946
+
38947
+ thisClass.clickNode(this);
38948
+ });
37783
38949
  }
37784
38950
 
37785
38951
  clickNode(node) { let ic = this.icn3d, me = ic.icn3dui;
@@ -38459,8 +39625,11 @@ class Selection {
38459
39625
 
38460
39626
  for(let i in ic.chains) {
38461
39627
  ic.hAtoms = me.hashUtilsCls.unionHash(ic.hAtoms, ic.chains[i]);
38462
- ic.dAtoms = me.hashUtilsCls.unionHash(ic.dAtoms, ic.chains[i]);
39628
+ //ic.dAtoms = me.hashUtilsCls.unionHash(ic.dAtoms, ic.chains[i]);
38463
39629
  }
39630
+
39631
+ ic.dAtoms = me.hashUtilsCls.cloneHash(ic.hAtoms);
39632
+ ic.viewSelectionAtoms = me.hashUtilsCls.cloneHash(ic.hAtoms);
38464
39633
  }
38465
39634
 
38466
39635
  //Select a chain with the chain id "chainid" in the sequence dialog and save it as a custom selection with the name "commandname".
@@ -38695,6 +39864,7 @@ class Selection {
38695
39864
  if(Object.keys(ic.hAtoms).length == 0) this.selectAll_base();
38696
39865
 
38697
39866
  ic.dAtoms = me.hashUtilsCls.cloneHash(ic.hAtoms);
39867
+ ic.viewSelectionAtoms = me.hashUtilsCls.cloneHash(ic.hAtoms);
38698
39868
 
38699
39869
  let centerAtomsResults = ic.applyCenterCls.centerAtoms(me.hashUtilsCls.hash2Atoms(ic.dAtoms, ic.atoms));
38700
39870
  ic.maxD = centerAtomsResults.maxD;
@@ -40951,8 +42121,9 @@ class ApplySsbonds {
40951
42121
  let start, end;
40952
42122
 
40953
42123
  if(ic.bAlternate) {
40954
- start = ic.ALTERNATE_STRUCTURE;
40955
- end = ic.ALTERNATE_STRUCTURE + 1;
42124
+ let nStructures = structureArray.length;
42125
+ start = ic.ALTERNATE_STRUCTURE % nStructures;
42126
+ end = ic.ALTERNATE_STRUCTURE % nStructures + 1;
40956
42127
  }
40957
42128
  else {
40958
42129
  start = 0;
@@ -44243,7 +45414,8 @@ class ClickMenu {
44243
45414
  // clkMn2_selectdisplayed: function() {
44244
45415
  me.myEventCls.onIds("#" + me.pre + "mn2_selectdisplayed", "click", function(e) { let ic = me.icn3d;
44245
45416
  thisClass.setLogCmd("select displayed set", true);
44246
- ic.hAtoms = me.hashUtilsCls.cloneHash(ic.dAtoms);
45417
+ //ic.hAtoms = me.hashUtilsCls.cloneHash(ic.dAtoms);
45418
+ ic.hAtoms = me.hashUtilsCls.cloneHash(ic.viewSelectionAtoms);
44247
45419
  ic.hlUpdateCls.updateHlAll();
44248
45420
  //ic.drawCls.draw();
44249
45421
  });
@@ -45364,6 +46536,10 @@ class ClickMenu {
45364
46536
  // },
45365
46537
  // clkMn6_sidebyside: function() {
45366
46538
  me.myEventCls.onIds("#" + me.pre + "mn6_sidebyside", "click", function(e) { let ic = me.icn3d;
46539
+ if(ic.bInputfile) {
46540
+ var aaa = 1; //alert("Side-by-Side does NOT work when the input is from a local file.");
46541
+ return;
46542
+ }
45367
46543
  let url = ic.shareLinkCls.shareLinkUrl(undefined);
45368
46544
  //if(url.indexOf('http') !== 0) {
45369
46545
  // var aaa = 1; //alert("The url is more than 4000 characters and may not work.");
@@ -45971,6 +47147,8 @@ class SetMenu {
45971
47147
  // show title at the top left corner
45972
47148
  html += me.htmlCls.divStr + "title' class='icn3d-commandTitle' style='font-size:1.2em; font-weight:normal; position:absolute; z-index:1; float:left; display:block; margin: 12px 0px 0px 40px; color:" + titleColor + "; width:" +(me.htmlCls.WIDTH - 40).toString() + "px'></div>";
45973
47149
  html += me.htmlCls.divStr + "viewer' style='position:relative; width:100%; height:100%; background-color: " + me.htmlCls.GREYD + ";'>";
47150
+ // don't show legend in mobile
47151
+ //html += me.htmlCls.divStr + "legend' class='icn3d-text icn3d-legend'></div>";
45974
47152
  html += me.htmlCls.divStr + "mnLogSection'>";
45975
47153
  html += "<div style='height: " + me.htmlCls.MENU_HEIGHT + "px;'></div>";
45976
47154
  html += "</div>";
@@ -48257,6 +49435,12 @@ class SetDialog {
48257
49435
  html += "<div style='width:500px'>";
48258
49436
  html += 'Please specify the mutations with a comma separated mutation list. Each mutation can be specified as "[PDB ID]_[Chain ID]_[Residue Number]_[One Letter Mutatnt Residue]". E.g., the mutation of N501Y in the E chain of PDB 6M0J can be specified as "6M0J_E_501_Y". <br/><br/>';
48259
49437
  html += "<div style='display:inline-block; width:110px'>Mutations: </div>" + me.htmlCls.inputTextStr + "id='" + me.pre + "mutationids' value='6M0J_E_484_K,6M0J_E_501_Y,6M0J_E_417_N' size=50><br/><br/>";
49438
+
49439
+ html += "<b>Data Source</b>: <select id='" + me.pre + "idsource'>";
49440
+ html += "<option value='mmdbid' selected>PDB ID</option>";
49441
+ html += "<option value='afid'>AlphaFold UniProt ID</option>";
49442
+ html += "</select><br/><br/>";
49443
+
48260
49444
  html += me.htmlCls.buttonStr + "reload_mutation_3d' title='Show the mutations in 3D using the scap program'>3D with scap</button>";
48261
49445
  html += me.htmlCls.buttonStr + "reload_mutation_inter' style='margin-left:20px' title='Show the mutations in 3D and the change of interactions'>Interactions</button>";
48262
49446
  html += me.htmlCls.buttonStr + "reload_mutation_pdb' style='margin-left:20px' title='Show the mutations in 3D and export the PDB of the mutant within 10 angstrom'>PDB</button>";
@@ -48651,7 +49835,7 @@ class SetDialog {
48651
49835
 
48652
49836
  html += me.htmlCls.divStr + "dl_alignerrormap' style='background-color:white' class='" + dialogClass + "'>";
48653
49837
 
48654
- //html += me.htmlCls.divNowrapStr + "Hold Ctrl key to select multiple nodes." + me.htmlCls.space3 + "</div>";
49838
+ html += me.htmlCls.divNowrapStr + "Hold Ctrl key to select multiple nodes." + me.htmlCls.space3 + "</div>";
48655
49839
 
48656
49840
  me.alignerrormapid = me.pre + 'alignerrormap';
48657
49841
  html += me.htmlCls.divNowrapStr + buttonStrTmp + me.alignerrormapid + '_svg">SVG</button>' + me.htmlCls.space2;
@@ -49122,6 +50306,18 @@ class Events {
49122
50306
  }
49123
50307
  }
49124
50308
 
50309
+ saveHtml(id) { let me = this.icn3dui, ic = me.icn3d;
50310
+ let html = '';
50311
+ html += '<link rel="stylesheet" href="https:///structure.ncbi.nlm.nih.gov/icn3d/lib/jquery-ui-1.12.1.min.css">\n';
50312
+ html += '<link rel="stylesheet" href="https:///structure.ncbi.nlm.nih.gov/icn3d/icn3d_full_ui.css">\n';
50313
+ html += $("#" + id).html();
50314
+ let idArray = id.split('_');
50315
+ let idStr =(idArray.length > 2) ? idArray[2] : id;
50316
+ let structureStr = Object.keys(ic.structures)[0];
50317
+ if(Object.keys(ic.structures).length > 1) structureStr += '-' + Object.keys(ic.structures)[1];
50318
+ ic.saveFileCls.saveFile(structureStr + '-' + idStr + '.html', 'html', encodeURIComponent(html));
50319
+ }
50320
+
49125
50321
  //Hold all functions related to click events.
49126
50322
  allEventFunctions() { let me = this.icn3dui, ic = me.icn3d;
49127
50323
  let thisClass = this;
@@ -49520,26 +50716,29 @@ class Events {
49520
50716
  e.preventDefault();
49521
50717
  if(!me.cfg.notebook) dialog.dialog( "close" );
49522
50718
  let mutationids = $("#" + me.pre + "mutationids").val();
49523
- let mmdbid = mutationids.substr(0, mutationids.indexOf('_'));
50719
+ let idsource = $("#" + me.pre + "idsource").val();
50720
+ let mmdbid = mutationids.substr(0, mutationids.indexOf('_'));
49524
50721
  me.htmlCls.clickMenuCls.setLogCmd("3d of mutation " + mutationids, false);
49525
50722
  //window.open(me.htmlCls.baseUrl + 'icn3d/full.html?mmdbid=' + mmdbid + '&command=scap 3d ' + mutationids + '; select displayed set', '_blank');
49526
- window.open(hostUrl + '?mmdbid=' + mmdbid + '&command=scap 3d ' + mutationids + '; select displayed set', '_blank');
50723
+ window.open(hostUrl + '?' + idsource + '=' + mmdbid + '&command=scap 3d ' + mutationids + '; select displayed set', '_blank');
49527
50724
  });
49528
50725
 
49529
50726
  me.myEventCls.onIds("#" + me.pre + "reload_mutation_pdb", "click", function(e) { me.icn3d;
49530
50727
  e.preventDefault();
49531
50728
  if(!me.cfg.notebook) dialog.dialog( "close" );
49532
50729
  let mutationids = $("#" + me.pre + "mutationids").val();
50730
+ let idsource = $("#" + me.pre + "idsource").val();
49533
50731
  let mmdbid = mutationids.substr(0, mutationids.indexOf('_'));
49534
50732
  me.htmlCls.clickMenuCls.setLogCmd("pdb of mutation " + mutationids, false);
49535
50733
  //window.open(me.htmlCls.baseUrl + 'icn3d/full.html?mmdbid=' + mmdbid + '&command=scap pdb ' + mutationids + '; select displayed set', '_blank');
49536
- window.open(hostUrl + '?mmdbid=' + mmdbid + '&command=scap pdb ' + mutationids + '; select displayed set', '_blank');
50734
+ window.open(hostUrl + '?' + idsource + '=' + mmdbid + '&command=scap pdb ' + mutationids + '; select displayed set', '_blank');
49537
50735
  });
49538
50736
 
49539
50737
  me.myEventCls.onIds("#" + me.pre + "reload_mutation_inter", "click", function(e) { let ic = me.icn3d;
49540
50738
  e.preventDefault();
49541
50739
  if(!me.cfg.notebook) dialog.dialog( "close" );
49542
50740
  let mutationids = $("#" + me.pre + "mutationids").val();
50741
+ let idsource = $("#" + me.pre + "idsource").val();
49543
50742
 
49544
50743
  let mutationArray = mutationids.split(',');
49545
50744
  let residArray = [];
@@ -49561,7 +50760,7 @@ class Events {
49561
50760
  me.htmlCls.clickMenuCls.setLogCmd("interaction change of mutation " + mutationids, false);
49562
50761
  //window.open(me.htmlCls.baseUrl + 'icn3d/full.html?mmdbid=' + mmdbid + '&command=scap interaction ' + mutationids + '; select ' + selectSpec + ' | name test; line graph interaction pairs | selected non-selected | hbonds,salt bridge,interactions,halogen,pi-cation,pi-stacking | false | threshold 3.8 6 4 3.8 6 5.5; adjust dialog dl_linegraph; select displayed set', '_blank');
49563
50762
  //window.open(me.htmlCls.baseUrl + 'icn3d/full.html?mmdbid=' + mmdbid + '&command=scap interaction ' + mutationids, '_blank');
49564
- window.open(hostUrl + '?mmdbid=' + mmdbid + '&command=scap interaction ' + mutationids, '_blank');
50763
+ window.open(hostUrl + '?' + idsource + '=' + mmdbid + '&command=scap interaction ' + mutationids, '_blank');
49565
50764
  });
49566
50765
 
49567
50766
  // },
@@ -50780,18 +51979,12 @@ class Events {
50780
51979
  });
50781
51980
  // },
50782
51981
  // clickSaveDialog: function() {
50783
- $(document).on("click", ".icn3d-saveicon", function(e) { let ic = me.icn3d;
51982
+ $(document).on("click", ".icn3d-saveicon", function(e) { me.icn3d;
50784
51983
  e.stopImmediatePropagation();
50785
51984
  let id = $(this).attr('pid');
50786
- let html = '';
50787
- html += '<link rel="stylesheet" href="https:///structure.ncbi.nlm.nih.gov/icn3d/lib/jquery-ui-1.12.1.min.css">\n';
50788
- html += '<link rel="stylesheet" href="https:///structure.ncbi.nlm.nih.gov/icn3d/icn3d_full_ui.css">\n';
50789
- html += $("#" + id).html();
50790
- let idArray = id.split('_');
50791
- let idStr =(idArray.length > 2) ? idArray[2] : id;
50792
- let structureStr = Object.keys(ic.structures)[0];
50793
- if(Object.keys(ic.structures).length > 1) structureStr += '-' + Object.keys(ic.structures)[1];
50794
- ic.saveFileCls.saveFile(structureStr + '-' + idStr + '.html', 'html', encodeURIComponent(html));
51985
+
51986
+ thisClass.saveHtml(id);
51987
+ me.htmlCls.clickMenuCls.setLogCmd("save html " + id, true);
50795
51988
  });
50796
51989
  // },
50797
51990
  // clickHideDialog: function() {
@@ -52306,38 +53499,66 @@ class Alternate {
52306
53499
  // change the display atom when alternating
52307
53500
  //Show structures one by one.
52308
53501
  alternateStructures() { let ic = this.icn3d, me = ic.icn3dui;
52309
- let hAtomsCount = Object.keys(ic.hAtoms).length;
53502
+ if(!ic.viewSelectionAtoms) {
53503
+ ic.viewSelectionAtoms = me.hashUtilsCls.cloneHash(ic.dAtoms);
53504
+ }
53505
+
53506
+ let viewSelectionAtomsCount = Object.keys(ic.viewSelectionAtoms).length;
52310
53507
  let allAtomsCount = Object.keys(ic.atoms).length;
52311
53508
 
52312
53509
  ic.dAtoms = {};
52313
53510
 
53511
+ // alternate all displayed structures
53512
+ let moleculeArray = Object.keys(ic.structures);
52314
53513
  // only alternate selected structures
52315
- //let moleculeArray = Object.keys(ic.structures);
52316
- let structureHash = {};
52317
- for(let i in ic.hAtoms) {
52318
- let structure = ic.atoms[i].structure;
52319
- structureHash[structure] = 1;
52320
- }
52321
- let moleculeArray = Object.keys(structureHash);
53514
+ // let structureHash = {};
53515
+ // for(let i in ic.hAtoms) {
53516
+ // let structure = ic.atoms[i].structure;
53517
+ // structureHash[structure] = 1;
53518
+ // }
53519
+ // let moleculeArray = Object.keys(structureHash);
52322
53520
 
52323
53521
  for(let i = 0, il = moleculeArray.length; i < il; ++i) {
52324
53522
  let structure = moleculeArray[i];
52325
- if(i > ic.ALTERNATE_STRUCTURE || (ic.ALTERNATE_STRUCTURE === il - 1 && i === 0) ) {
53523
+ //if(i > ic.ALTERNATE_STRUCTURE || (ic.ALTERNATE_STRUCTURE === il - 1 && i === 0) ) {
53524
+ let bChoose;
53525
+ if(ic.bShift) {
53526
+ // default ic.ALTERNATE_STRUCTURE = -1
53527
+ if(ic.ALTERNATE_STRUCTURE < 0) ic.ALTERNATE_STRUCTURE = 1;
53528
+
53529
+ bChoose = (i == ic.ALTERNATE_STRUCTURE % il - 1)
53530
+ || (ic.ALTERNATE_STRUCTURE % il === 0 && i === il - 1);
53531
+ }
53532
+ else {
53533
+ bChoose = (i == ic.ALTERNATE_STRUCTURE % il + 1)
53534
+ || (ic.ALTERNATE_STRUCTURE % il === il - 1 && i === 0);
53535
+ }
53536
+
53537
+ if(bChoose) {
52326
53538
  for(let k in ic.structures[structure]) {
52327
53539
  let chain = ic.structures[structure][k];
52328
53540
  ic.dAtoms = me.hashUtilsCls.unionHash(ic.dAtoms, ic.chains[chain]);
52329
53541
  }
52330
53542
 
52331
- ic.ALTERNATE_STRUCTURE = i;
53543
+ //ic.ALTERNATE_STRUCTURE = i;
53544
+ if(ic.bShift) {
53545
+ --ic.ALTERNATE_STRUCTURE;
53546
+ }
53547
+ else {
53548
+ ++ic.ALTERNATE_STRUCTURE;
53549
+ }
53550
+
53551
+ if(ic.ALTERNATE_STRUCTURE < 0) ic.ALTERNATE_STRUCTURE += il;
52332
53552
 
52333
53553
  $("#" + ic.pre + "title").html(structure);
52334
53554
 
52335
53555
  break;
52336
53556
  }
52337
- }
53557
+ }
52338
53558
 
52339
- if(hAtomsCount < allAtomsCount) {
52340
- ic.dAtoms = me.hashUtilsCls.intHash(ic.dAtoms, ic.hAtoms);
53559
+ if(viewSelectionAtomsCount < allAtomsCount) {
53560
+ //ic.dAtoms = me.hashUtilsCls.intHash(ic.dAtoms, ic.hAtoms);
53561
+ ic.dAtoms = me.hashUtilsCls.intHash(ic.dAtoms, ic.viewSelectionAtoms);
52341
53562
 
52342
53563
  ic.bShowHighlight = false;
52343
53564
  ic.opts['rotationcenter'] = 'highlight center';
@@ -53067,17 +54288,10 @@ class ContactMap {
53067
54288
  let bContactMap = true;
53068
54289
 
53069
54290
  if(bAfMap) { // cleaned the code by using "use" in SVG, but didn't improve rendering
53070
- let factor = 1;
53071
- let r = 3 * factor;
53072
- let rectSize = 2 * r;
53073
54291
 
53074
54292
  ic.hex2id = {};
53075
54293
  let threshold = 29.0 / max;
53076
54294
  ic.hex2skip = {}; // do not display any error larger than 29 angstrom
53077
-
53078
- html += "<defs>";
53079
-
53080
- let linestrokewidth = 1;
53081
54295
  let nRef = 1000;
53082
54296
  for(let i = 0; i < nRef; ++i) {
53083
54297
  let ratio = 1.0 * i / nRef;
@@ -53087,7 +54301,6 @@ class ContactMap {
53087
54301
  let gHex = (g.length == 1) ? '0' + g : g;
53088
54302
  let bHex = rHex;
53089
54303
  let color = rHex + gHex + bHex;
53090
- let strokecolor = "#" + color;
53091
54304
 
53092
54305
  let idRect = me.pre + "afmap_" + i;
53093
54306
 
@@ -53097,11 +54310,11 @@ class ContactMap {
53097
54310
  }
53098
54311
 
53099
54312
  //html += "<g id='" + id + "'>";
53100
- html += "<rect id='" + idRect + "' x='0' y='0' width='" + rectSize + "' height='" + rectSize + "' fill='"
53101
- + strokecolor + "' stroke-width='" + linestrokewidth + "' stroke='" + strokecolor + "' />";
54313
+ // html += "<rect id='" + idRect + "' x='0' y='0' width='" + rectSize + "' height='" + rectSize + "' fill='"
54314
+ // + strokecolor + "' stroke-width='" + linestrokewidth + "' stroke='" + strokecolor + "' />";
53102
54315
  //html += "</g>"
53103
54316
  }
53104
- html += "</defs>";
54317
+ // html += "</defs>";
53105
54318
  }
53106
54319
 
53107
54320
  html += ic.lineGraphCls.drawScatterplot_base(nodeArray1, nodeArray2, linkArray, name2node, 0, bContactMap, undefined, undefined, bAfMap);
@@ -54878,7 +56091,7 @@ class Control {
54878
56091
 
54879
56092
  else if(e.keyCode === 65 ) { // A, alternate
54880
56093
  if(Object.keys(ic.structures).length > 1) {
54881
- ic.alternateCls.alternateWrapper();
56094
+ ic.alternateCls.alternateWrapper();
54882
56095
  }
54883
56096
  }
54884
56097
 
@@ -55425,6 +56638,7 @@ class iCn3D {
55425
56638
  this.annoSnpClinVarCls = new AnnoSnpClinVar(this);
55426
56639
  this.annoSsbondCls = new AnnoSsbond(this);
55427
56640
  this.annoTransMemCls = new AnnoTransMem(this);
56641
+ this.domain3dCls = new Domain3d(this);
55428
56642
 
55429
56643
  this.addTrackCls = new AddTrack(this);
55430
56644
  this.annotationCls = new Annotation(this);
@@ -55677,7 +56891,7 @@ class iCn3DUI {
55677
56891
  //even when multiple iCn3D viewers are shown together.
55678
56892
  this.pre = this.cfg.divid + "_";
55679
56893
 
55680
- this.REVISION = '3.8.1';
56894
+ this.REVISION = '3.9.0';
55681
56895
 
55682
56896
  // In nodejs, iCn3D defines "window = {navigator: {}}"
55683
56897
  this.bNode = (Object.keys(window).length < 2) ? true : false;
@@ -56192,6 +57406,7 @@ exports.Delphi = Delphi;
56192
57406
  exports.DensityCifParser = DensityCifParser;
56193
57407
  exports.Diagram2d = Diagram2d;
56194
57408
  exports.Dialog = Dialog;
57409
+ exports.Domain3d = Domain3d;
56195
57410
  exports.Draw = Draw;
56196
57411
  exports.DrawGraph = DrawGraph;
56197
57412
  exports.Dsn6Parser = Dsn6Parser;