icn3d 3.5.0 → 3.8.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 +971 -316
  2. package/package.json +1 -1
package/icn3d.js CHANGED
@@ -2462,7 +2462,10 @@ THREE.TrackballControls = function ( object, domElement, icn3d ) {
2462
2462
 
2463
2463
  _eye.multiplyScalar( factor );
2464
2464
 
2465
- if(icn3d !== undefined && icn3d._zoomFactor !== undefined && (bUpdate === undefined || bUpdate === true)) icn3d._zoomFactor *= factor;
2465
+ if(icn3d !== undefined && icn3d._zoomFactor !== undefined && (bUpdate === undefined || bUpdate === true)) {
2466
+ icn3d._zoomFactor *= factor;
2467
+ icn3d.fogCls.setFog();
2468
+ }
2466
2469
 
2467
2470
  } else {
2468
2471
 
@@ -2475,7 +2478,10 @@ THREE.TrackballControls = function ( object, domElement, icn3d ) {
2475
2478
  factor = 1.0 + ( _this._zoomEnd.y - _this._zoomStart.y ) * _this.zoomSpeed;
2476
2479
  }
2477
2480
 
2478
- if(icn3d !== undefined && icn3d._zoomFactor !== undefined && (bUpdate === undefined || bUpdate === true)) icn3d._zoomFactor *= factor;
2481
+ if(icn3d !== undefined && icn3d._zoomFactor !== undefined && (bUpdate === undefined || bUpdate === true)) {
2482
+ icn3d._zoomFactor *= factor;
2483
+ icn3d.fogCls.setFog();
2484
+ }
2479
2485
 
2480
2486
  //if ( factor !== 1.0 && factor > 0.0 ) {
2481
2487
  if ( factor !== 1.0 ) {
@@ -3952,7 +3958,7 @@ class ParasCls {
3952
3958
  black: this.thr(0x000000),
3953
3959
  grey: this.thr(0xCCCCCC),
3954
3960
  white: this.thr(0xFFFFFF),
3955
- transparent: this.thr(0x000000)
3961
+ transparent: this.thr(0xFFFFFF) //this.thr(0x000000)
3956
3962
  };
3957
3963
 
3958
3964
  this.residueColors = {
@@ -4484,6 +4490,16 @@ class UtilsCls {
4484
4490
  if(viewer_width && me.htmlCls.WIDTH > viewer_width) me.htmlCls.WIDTH = viewer_width;
4485
4491
  if(viewer_height && me.htmlCls.HEIGHT > viewer_height) me.htmlCls.HEIGHT = viewer_height;
4486
4492
  }
4493
+
4494
+ sumArray(numArray) {
4495
+ let sum = 0;
4496
+
4497
+ for(let i = 0, il = numArray.length; i < il; ++i) {
4498
+ sum += numArray[i];
4499
+ }
4500
+
4501
+ return sum;
4502
+ }
4487
4503
  }
4488
4504
 
4489
4505
  /**
@@ -5844,7 +5860,8 @@ class Fog {
5844
5860
  if(bZoomin) {
5845
5861
  let centerAtomsResults = ic.applyCenterCls.centerAtoms(ic.hAtoms);
5846
5862
  ic.maxD = centerAtomsResults.maxD;
5847
- if (ic.maxD < 5) ic.maxD = 5;
5863
+ //if (ic.maxD < 5) ic.maxD = 5;
5864
+ if (ic.maxD < 25) ic.maxD = 25;
5848
5865
  }
5849
5866
 
5850
5867
  let bInstance = (ic.biomtMatrices !== undefined && ic.biomtMatrices.length * ic.cnt > ic.maxatomcnt) ? true : false;
@@ -5861,7 +5878,9 @@ class Fog {
5861
5878
  ic.bSetFog = false;
5862
5879
  }
5863
5880
  else {
5864
- ic.scene.fog = new THREE.Fog(background, 2.5*ic.maxD, 4*ic.maxD);
5881
+ // adjust
5882
+ let zoomFactor = (ic._zoomFactor > 1) ? ic._zoomFactor * 1.0 : ic._zoomFactor;
5883
+ ic.scene.fog = new THREE.Fog(background, 2.5 * ic.maxD * zoomFactor, 4 * ic.maxD * zoomFactor);
5865
5884
  ic.bSetFog = true;
5866
5885
  ic.camMaxDFactorFog = 3;
5867
5886
  }
@@ -5880,9 +5899,9 @@ class Fog {
5880
5899
  ic.bSetFog = false;
5881
5900
  }
5882
5901
 
5883
- if(bZoomin && !bInstance) {
5884
- ic.transformCls.zoominSelection();
5885
- }
5902
+ //if(bZoomin && !bInstance) {
5903
+ // ic.transformCls.zoominSelection();
5904
+ //}
5886
5905
  }
5887
5906
  }
5888
5907
 
@@ -11887,7 +11906,8 @@ class ShareLink {
11887
11906
 
11888
11907
  if(ic.commands.length > start) {
11889
11908
  let command_tf = ic.commands[start].split('|||');
11890
- prevCommandStr = command_tf[0].trim();
11909
+ let command_tf2 = command_tf[0].split('&command=');
11910
+ prevCommandStr = command_tf2[0].trim();
11891
11911
 
11892
11912
  //statefile += ic.commands[start] + "\n";
11893
11913
 
@@ -11898,7 +11918,8 @@ class ShareLink {
11898
11918
  let tmpUrl = '';
11899
11919
  for(let il = ic.commands.length; i < il; ++i) {
11900
11920
  let command_tf = ic.commands[i].split('|||');
11901
- let commandStr = command_tf[0].trim();
11921
+ let command_tf2 = command_tf[0].split('&command=');
11922
+ let commandStr = command_tf2[0].trim();
11902
11923
 
11903
11924
  //statefile += ic.commands[i] + "\n";
11904
11925
 
@@ -15147,24 +15168,7 @@ class Saltbridge {
15147
15168
  || (atom.het && me.parasCls.cationsTrimArray.indexOf(atom.elem) !== -1)
15148
15169
  || (atom.het && atom.elem === "N" && atom.bonds.length == 1);
15149
15170
 
15150
- // For ligand, "O" in carboxy group may be negatively charged. => to be improved
15151
- let bLigNeg = undefined;
15152
- if(atom.het && atom.elem === "O" && atom.bonds.length == 1) {
15153
- let cAtom = ic.atoms[atom.bonds[0]];
15154
- for(let j = 0; j < cAtom.bonds.length; ++j) {
15155
- let serial = cAtom.bonds[j];
15156
- if(ic.atoms[serial].elem == "O" && serial != atom.serial) {
15157
- bLigNeg = true;
15158
- break;
15159
- }
15160
- }
15161
- }
15162
-
15163
- let bAtomCondAnion = ( atom.resn === 'GLU' && (atom.name === "OE1" || atom.name === "OE2") )
15164
- || ( atom.resn === 'ASP' && (atom.name === "OD1" || atom.name === "OD2") )
15165
- || ( ic.nucleotides.hasOwnProperty(atom.serial) && (atom.name === "OP1" || atom.name === "OP2" || atom.name === "O1P" || atom.name === "O2P"))
15166
- || (atom.het && me.parasCls.anionsTrimArray.indexOf(atom.elem) !== -1)
15167
- || bLigNeg;
15171
+ let bAtomCondAnion = this.isAnion(atom);
15168
15172
 
15169
15173
  bAtomCondCation = (ic.bOpm) ? bAtomCondCation && atom.resn !== 'DUM' : bAtomCondCation;
15170
15174
  bAtomCondAnion = (ic.bOpm) ? bAtomCondAnion && atom.resn !== 'DUM' : bAtomCondAnion;
@@ -15195,10 +15199,7 @@ class Saltbridge {
15195
15199
  || ( atom.resn === 'ARG' && (atom.name === "NH1" || atom.name === "NH2"))
15196
15200
  || (atom.het && me.parasCls.cationsTrimArray.indexOf(atom.elem) !== -1);
15197
15201
 
15198
- let bAtomCondAnion = ( atom.resn === 'GLU' && (atom.name === "OE1" || atom.name === "OE2") )
15199
- || ( atom.resn === 'ASP' && (atom.name === "OD1" || atom.name === "OD2") )
15200
- || ( ic.nucleotides.hasOwnProperty(atom.serial) && (atom.name === "OP1" || atom.name === "OP2" || atom.name === "O1P" || atom.name === "O2P"))
15201
- || (atom.het && me.parasCls.anionsTrimArray.indexOf(atom.elem) !== -1);
15202
+ let bAtomCondAnion = this.isAnion(atom);
15202
15203
 
15203
15204
  bAtomCondCation = (ic.bOpm) ? bAtomCondCation && atom.resn !== 'DUM' : bAtomCondCation;
15204
15205
  bAtomCondAnion = (ic.bOpm) ? bAtomCondAnion && atom.resn !== 'DUM' : bAtomCondAnion;
@@ -15309,6 +15310,35 @@ class Saltbridge {
15309
15310
  return hbondsAtoms;
15310
15311
  }
15311
15312
 
15313
+ isAnion(atom) { let ic = this.icn3d, me = ic.icn3dui;
15314
+ // For ligand, "O" in carboxy group may be negatively charged. => to be improved
15315
+ let bLigNeg = undefined;
15316
+ if(atom.het && atom.elem === "O" && atom.bonds.length == 1) {
15317
+ let cAtom = ic.atoms[atom.bonds[0]];
15318
+ for(let j = 0; j < cAtom.bonds.length; ++j) {
15319
+ let serial = cAtom.bonds[j];
15320
+ if(ic.atoms[serial].elem == "O" && serial != atom.serial) {
15321
+ bLigNeg = true;
15322
+ break;
15323
+ }
15324
+ }
15325
+ }
15326
+
15327
+ // "O" in phosphae or sulfate group is neagatively charged
15328
+ if(atom.elem === "O" && atom.bonds.length == 1) {
15329
+ let pAtom = ic.atoms[atom.bonds[0]];
15330
+ if(pAtom.elem == "P" || pAtom.elem == "S") bLigNeg = true;
15331
+ }
15332
+
15333
+ let bAtomCondAnion = ( atom.resn === 'GLU' && (atom.name === "OE1" || atom.name === "OE2") )
15334
+ || ( atom.resn === 'ASP' && (atom.name === "OD1" || atom.name === "OD2") )
15335
+ || ( ic.nucleotides.hasOwnProperty(atom.serial) && (atom.name === "OP1" || atom.name === "OP2" || atom.name === "O1P" || atom.name === "O2P"))
15336
+ || (atom.het && me.parasCls.anionsTrimArray.indexOf(atom.elem) !== -1)
15337
+ || bLigNeg;
15338
+
15339
+ return bAtomCondAnion;
15340
+ }
15341
+
15312
15342
  hideSaltbridge() { let ic = this.icn3d; ic.icn3dui;
15313
15343
  ic.opts["saltbridge"] = "no";
15314
15344
  if(ic.lines === undefined) ic.lines = { };
@@ -15456,7 +15486,7 @@ class GetGraph {
15456
15486
  return resStr;
15457
15487
  }
15458
15488
 
15459
- drawResNode(node, i, r, gap, margin, y, setName, bVertical, bContactMap) { let ic = this.icn3d; ic.icn3dui;
15489
+ drawResNode(node, i, r, gap, margin, y, setName, bVertical, bContactMap, bAfMap) { let ic = this.icn3d; ic.icn3dui;
15460
15490
  let x, resid = node.r.substr(4);
15461
15491
  if(bVertical) {
15462
15492
  x = margin - i *(r + gap);
@@ -15482,7 +15512,7 @@ class GetGraph {
15482
15512
  let strokewidth = '1';
15483
15513
  let textcolor = '#000';
15484
15514
  let fontsize = '6px'; // '6';
15485
- let html = "<g class='icn3d-node' resid='" + resid + "' >";
15515
+ let html = (bAfMap) ? "<g>" : "<g class='icn3d-node' resid='" + resid + "' >";
15486
15516
  html += "<title>" + node.id + "</title>";
15487
15517
  if(bVertical) {
15488
15518
  html += "<circle cx='" + y + "' cy='" + x + "' r='" + r + "' fill='" + color + "' stroke-width='" + strokewidth + "' stroke='" + strokecolor + "' resid='" + resid + "' />";
@@ -15495,23 +15525,40 @@ class GetGraph {
15495
15525
  html += "</g>";
15496
15526
  return html;
15497
15527
  }
15498
- getNodeTopBottom(nameHash, name2node, bReverseNode) { let ic = this.icn3d; ic.icn3dui;
15528
+ getNodeTopBottom(nameHash, name2node, bReverseNode, bCommonDiff, nameHashCommon) { let ic = this.icn3d, me = ic.icn3dui;
15499
15529
  let thisClass = this;
15500
- let nodeArray1 = [], nodeArray2 = [];
15530
+ let nodeArray1 = [], nodeArray2 = [], name2nodeCommon = {};
15531
+
15532
+ let separatorCommon = "=>", separatorDiff = "==>", postCommon = "-", postDiff = "--";
15501
15533
  for(let name in nameHash) {
15502
15534
  let node = name2node[name];
15503
15535
  if(!node) continue;
15504
15536
 
15537
+ if(bCommonDiff == 1 || bCommonDiff == 2) {
15538
+ node = me.hashUtilsCls.cloneHash(node);
15539
+
15540
+ if(bCommonDiff == 1) {
15541
+ let mapping = (nameHashCommon[name]) ? nameHashCommon[name] : postCommon;
15542
+ node.id += separatorCommon + mapping;
15543
+ }
15544
+ else {
15545
+ let mapping = (nameHashCommon[name]) ? nameHashCommon[name] : postDiff;
15546
+ node.id += separatorDiff + mapping;
15547
+ }
15548
+
15549
+ name2nodeCommon[node.id] = node;
15550
+ }
15551
+
15505
15552
  if(node.s == 'a') {
15506
15553
  nodeArray1.push(node);
15507
15554
  }
15508
15555
  else if(node.s == 'b') {
15509
15556
  nodeArray2.push(node);
15510
15557
  }
15511
- else if(node.s == 'ab') {
15512
- nodeArray1.push(node);
15513
- nodeArray2.push(node);
15514
- }
15558
+ //else if(node.s == 'ab') {
15559
+ // nodeArray1.push(node);
15560
+ // nodeArray2.push(node);
15561
+ //}
15515
15562
  }
15516
15563
  // sort array
15517
15564
  nodeArray1.sort(function(a,b) {
@@ -15520,7 +15567,7 @@ class GetGraph {
15520
15567
  nodeArray2.sort(function(a,b) {
15521
15568
  return thisClass.compNode(a, b, bReverseNode);
15522
15569
  });
15523
- return {"nodeArray1": nodeArray1, "nodeArray2": nodeArray2}
15570
+ return {"nodeArray1": nodeArray1, "nodeArray2": nodeArray2, "name2node": name2nodeCommon};
15524
15571
  }
15525
15572
  updateGraphJson(struc, index, nodeArray1, nodeArray2, linkArray) { let ic = this.icn3d, me = ic.icn3dui;
15526
15573
  let lineGraphStr = '';
@@ -15843,22 +15890,37 @@ class LineGraph {
15843
15890
  let structureArray = ic.resid2specCls.atoms2structureArray(ic.hAtoms);
15844
15891
  //if(Object.keys(ic.structures).length > 1) {
15845
15892
  if(structureArray.length > 1) {
15846
- let nodeArray1a = [],
15847
- nodeArray1b = [],
15848
- nodeArray2a = [],
15849
- nodeArray2b = [],
15850
- nodeArray3a = [],
15851
- nodeArray3b = [];
15852
- //let struc1 = Object.keys(ic.structures)[0],
15853
- // struc2 = Object.keys(ic.structures)[1];
15854
- let struc1 = structureArray[0],
15855
- struc2 = structureArray[1];
15856
- let linkArrayA = [],
15857
- linkArrayB = [],
15858
- linkArrayAB = [];
15859
- let nameHashA = {},
15860
- nameHashB = {},
15861
- nameHashAB = {};
15893
+
15894
+ let struc2index= {};
15895
+ let nodeArray1Split = [], nodeArray2Split = [], linkArraySplit = [], nameHashSplit = [];
15896
+
15897
+ // show common interactions: nodes will be the same. The links/interactins are different.
15898
+ // The mapped residue name and number are attached to "id".
15899
+ // Original node: {id : "Q24.A.2AJF", r : "1_1_2AJF_A_24", s: "a", ...}
15900
+ // Node for common interaction: {id : "Q24.A.2AJF|Q24", r : "1_1_2AJF_A_24", s: "a", ...}
15901
+ let nodeArray1SplitCommon = [], nodeArray2SplitCommon = [], linkArraySplitCommon = [], nameHashSplitCommon = [];
15902
+ let nodeArray1SplitDiff = [], nodeArray2SplitDiff = [], linkArraySplitDiff = [], nameHashSplitDiff = [];
15903
+ let linkedNodeCnt = {};
15904
+
15905
+ for(let i = 0, il = structureArray.length; i < il; ++i) {
15906
+ nodeArray1Split[i] = [];
15907
+ nodeArray2Split[i] = [];
15908
+ linkArraySplit[i] = [];
15909
+ nameHashSplit[i] = {};
15910
+
15911
+ nodeArray1SplitCommon[i] = [];
15912
+ nodeArray2SplitCommon[i] = [];
15913
+ linkArraySplitCommon[i] = [];
15914
+ nameHashSplitCommon[i] = {};
15915
+
15916
+ nodeArray1SplitDiff[i] = [];
15917
+ nodeArray2SplitDiff[i] = [];
15918
+ linkArraySplitDiff[i] = [];
15919
+ nameHashSplitDiff[i] = {};
15920
+
15921
+ struc2index[structureArray[i]] = i;
15922
+ }
15923
+
15862
15924
  for(let i = 0, il = linkArray.length; i < il; ++i) {
15863
15925
  let link = linkArray[i];
15864
15926
  let nodeA = name2node[link.source];
@@ -15868,119 +15930,188 @@ class LineGraph {
15868
15930
  continue;
15869
15931
  }
15870
15932
 
15871
- //var idArrayA = nodeA.r.split('_'); // 1_1_1KQ2_A_1
15872
- let idArrayA = [];
15873
- idArrayA.push('');
15874
- idArrayA.push('');
15933
+ let idArrayA = this.getIdArrayFromNode(nodeA);
15934
+ let idArrayB = this.getIdArrayFromNode(nodeB);
15875
15935
 
15876
- let tmpStr = nodeA.r.substr(4);
15877
- idArrayA = idArrayA.concat(me.utilsCls.getIdArray(tmpStr));
15936
+ let index = struc2index[idArrayA[2]];
15878
15937
 
15879
- //var idArrayB = nodeB.r.split('_'); // 1_1_1KQ2_A_1
15880
- let idArrayB = [];
15881
- idArrayB.push('');
15882
- idArrayB.push('');
15938
+ if(idArrayA[2] == structureArray[index] && idArrayB[2] == structureArray[index]) {
15939
+ linkArraySplit[index].push(link);
15940
+ nameHashSplit[index][link.source] = 1;
15941
+ nameHashSplit[index][link.target] = 1;
15883
15942
 
15884
- tmpStr = nodeB.r.substr(4);
15885
- idArrayB = idArrayB.concat(me.utilsCls.getIdArray(tmpStr));
15943
+ let chainid1 = idArrayA[2] + '_' + idArrayA[3];
15944
+ let chainid2 = idArrayB[2] + '_' + idArrayB[3];
15945
+ let resid1 = chainid1 + '_' + idArrayA[4];
15946
+ let resid2 = chainid2 + '_' + idArrayB[4];
15886
15947
 
15887
- if(idArrayA[2] == struc1 && idArrayB[2] == struc1) {
15888
- linkArrayA.push(link);
15889
- nameHashA[link.source] = 1;
15890
- nameHashA[link.target] = 1;
15891
- } else if(idArrayA[2] == struc2 && idArrayB[2] == struc2) {
15892
- linkArrayB.push(link);
15893
- nameHashB[link.source] = 1;
15894
- nameHashB[link.target] = 1;
15895
- } else {
15896
- linkArrayAB.push(link);
15897
- nameHashAB[link.source] = 1;
15898
- nameHashAB[link.target] = 1;
15899
- }
15900
- }
15901
- let nodeArraysA = ic.getGraphCls.getNodeTopBottom(nameHashA, name2node);
15902
- nodeArray1a = nodeArraysA.nodeArray1;
15903
- nodeArray1b = nodeArraysA.nodeArray2;
15904
- let nodeArraysB = ic.getGraphCls.getNodeTopBottom(nameHashB, name2node);
15905
- nodeArray2a = nodeArraysB.nodeArray1;
15906
- nodeArray2b = nodeArraysB.nodeArray2;
15907
- let nodeArraysAB = ic.getGraphCls.getNodeTopBottom(nameHashAB, name2node, true);
15908
- nodeArray3a = nodeArraysAB.nodeArray1;
15909
- nodeArray3b = nodeArraysAB.nodeArray2;
15910
- let len1a = nodeArray1a.length,
15911
- len1b = nodeArray1b.length;
15912
- let len2a = nodeArray2a.length,
15913
- len2b = nodeArray2b.length;
15914
- let len3a = nodeArray3a.length,
15915
- len3b = nodeArray3b.length;
15916
- let maxLen = Math.max(len1a, len1b, len2a, len2b, len3a, len3b);
15948
+ let mapping1, mapping2;
15949
+
15950
+ if(ic.chainsMapping[chainid1] && ic.chainsMapping[chainid1][resid1]
15951
+ && ic.chainsMapping[chainid2] && ic.chainsMapping[chainid2][resid2]) {
15952
+ mapping1 = (nodeA.s == "a") ? ic.chainsMapping[chainid1][resid1] : ic.chainsMapping[chainid2][resid2];
15953
+ mapping2 = (nodeA.s == "a") ? ic.chainsMapping[chainid2][resid2] : ic.chainsMapping[chainid1][resid1];
15954
+
15955
+ let mappingid = mapping1 + '_' + mapping2 + '_' + link.c; // link.c determines the interaction type
15956
+ if(!linkedNodeCnt.hasOwnProperty(mappingid)) {
15957
+ linkedNodeCnt[mappingid] = 1;
15958
+ }
15959
+ else {
15960
+ ++linkedNodeCnt[mappingid];
15961
+ }
15962
+ }
15963
+ }
15964
+ }
15965
+
15966
+ // set linkArraySplitCommon and nameHashSplitCommon
15967
+ // set linkArraySplitDiff and nameHashSplitDiff
15968
+ let separatorCommon = "=>", separatorDiff = "==>", postCommon = "-", postDiff = "--";
15969
+ for(let i = 0, il = linkArray.length; i < il; ++i) {
15970
+ let link = linkArray[i];
15971
+ let nodeA = name2node[link.source];
15972
+ let nodeB = name2node[link.target];
15973
+
15974
+ if(!nodeA || !nodeB || !nodeA.r || !nodeB.r) {
15975
+ continue;
15976
+ }
15977
+
15978
+ let idArrayA = this.getIdArrayFromNode(nodeA);
15979
+ let idArrayB = this.getIdArrayFromNode(nodeB);
15980
+
15981
+ let index = struc2index[idArrayA[2]];
15982
+
15983
+ if(idArrayA[2] == structureArray[index] && idArrayB[2] == structureArray[index]) {
15984
+ let chainid1 = idArrayA[2] + '_' + idArrayA[3];
15985
+ let chainid2 = idArrayB[2] + '_' + idArrayB[3];
15986
+ let resid1 = chainid1 + '_' + idArrayA[4];
15987
+ let resid2 = chainid2 + '_' + idArrayB[4];
15988
+
15989
+ let mapping1, mapping2;
15990
+
15991
+ if(ic.chainsMapping[chainid1] && ic.chainsMapping[chainid1][resid1]
15992
+ && ic.chainsMapping[chainid2] && ic.chainsMapping[chainid2][resid2]) {
15993
+ mapping1 = (nodeA.s == "a") ? ic.chainsMapping[chainid1][resid1] : ic.chainsMapping[chainid2][resid2];
15994
+ mapping2 = (nodeA.s == "a") ? ic.chainsMapping[chainid2][resid2] : ic.chainsMapping[chainid1][resid1];
15995
+
15996
+ let mappingid = mapping1 + '_' + mapping2 + '_' + link.c; // link.c determines the interaction type
15997
+
15998
+ let linkCommon = me.hashUtilsCls.cloneHash(link);
15999
+ linkCommon.source += (ic.chainsMapping[chainid1][resid1]) ? separatorCommon + ic.chainsMapping[chainid1][resid1] : separatorCommon + postCommon;
16000
+ linkCommon.target += (ic.chainsMapping[chainid2][resid2]) ? separatorCommon + ic.chainsMapping[chainid2][resid2] : separatorCommon + postCommon;
16001
+
16002
+ let linkDiff = me.hashUtilsCls.cloneHash(link);
16003
+ linkDiff.source += (ic.chainsMapping[chainid1][resid1]) ? separatorDiff + ic.chainsMapping[chainid1][resid1] : separatorDiff + postDiff;
16004
+ linkDiff.target += (ic.chainsMapping[chainid2][resid2]) ? separatorDiff + ic.chainsMapping[chainid2][resid2] : separatorDiff + postDiff;
16005
+
16006
+ if(linkedNodeCnt[mappingid] == structureArray.length) {
16007
+ linkArraySplitCommon[index].push(linkCommon);
16008
+ }
16009
+ else {
16010
+ linkArraySplitDiff[index].push(linkDiff);
16011
+ }
16012
+
16013
+ // use the original node names and thus use the original link
16014
+ nameHashSplitCommon[index][link.source] = ic.chainsMapping[chainid1][resid1];
16015
+ nameHashSplitCommon[index][link.target] = ic.chainsMapping[chainid2][resid2];
16016
+
16017
+ nameHashSplitDiff[index][link.source] = ic.chainsMapping[chainid1][resid1];
16018
+ nameHashSplitDiff[index][link.target] = ic.chainsMapping[chainid2][resid2];
16019
+ }
16020
+ }
16021
+ }
16022
+
16023
+ let len1Split = [], len2Split = [], maxWidth = 0;
15917
16024
  let strucArray = [];
15918
- if(linkArrayA.length > 0) strucArray.push(struc1);
15919
- if(linkArrayB.length > 0) strucArray.push(struc2);
15920
- if(linkArrayAB.length > 0) strucArray.push(struc1 + '_' + struc2);
16025
+ let bCommonDiff = 1;
16026
+ for(let i = 0, il = structureArray.length; i < il; ++i) {
16027
+ let nodeArraysTmp = ic.getGraphCls.getNodeTopBottom(nameHashSplit[i], name2node);
16028
+ nodeArray1Split[i] = nodeArraysTmp.nodeArray1;
16029
+ nodeArray2Split[i] = nodeArraysTmp.nodeArray2;
16030
+
16031
+ // common interactions
16032
+ bCommonDiff = 1;
16033
+ nodeArraysTmp = ic.getGraphCls.getNodeTopBottom(nameHashSplit[i], name2node, undefined, bCommonDiff, nameHashSplitCommon[i]);
16034
+ nodeArray1SplitCommon[i] = nodeArraysTmp.nodeArray1;
16035
+ nodeArray2SplitCommon[i] = nodeArraysTmp.nodeArray2;
16036
+ name2node = me.hashUtilsCls.unionHash(name2node, nodeArraysTmp.name2node);
16037
+
16038
+ // different interactions
16039
+ bCommonDiff = 2;
16040
+ nodeArraysTmp = ic.getGraphCls.getNodeTopBottom(nameHashSplit[i], name2node, undefined, bCommonDiff, nameHashSplitDiff[i]);
16041
+ nodeArray1SplitDiff[i] = nodeArraysTmp.nodeArray1;
16042
+ nodeArray2SplitDiff[i] = nodeArraysTmp.nodeArray2;
16043
+ name2node = me.hashUtilsCls.unionHash(name2node, nodeArraysTmp.name2node);
16044
+
16045
+ len1Split[i] = nodeArray1Split[i].length;
16046
+ len2Split[i] = nodeArray2Split[i].length;
16047
+
16048
+ maxWidth = Math.max(maxWidth, len2Split[i]);
16049
+
16050
+ //if(linkArraySplit[i].length > 0) strucArray.push(structureArray[i]);
16051
+ strucArray.push(structureArray[i]);
16052
+ }
16053
+
15921
16054
  let factor = 1;
15922
16055
  let r = 3 * factor;
15923
16056
  let gap = 7 * factor;
15924
16057
  let height, width, heightAll;
15925
16058
  let marginX = 10,
15926
16059
  marginY = 10,
15927
- legendWidth = 30;
16060
+ legendWidth = 30,
16061
+ textHeight = 20;
16062
+
15928
16063
  if(bScatterplot) {
15929
- heightAll =(len1a + 2 + len2a + 2) *(r + gap) + 4 * marginY + 2 * legendWidth;
15930
- width =(Math.max(len1b, len2b) + 2) *(r + gap) + 2 * marginX + legendWidth;
16064
+ //heightAll =(len1a + 2 + len2a + 2) *(r + gap) + 4 * marginY + 2 * legendWidth;
16065
+ //width =(Math.max(len1b, len2b) + 2) *(r + gap) + 2 * marginX + legendWidth;
16066
+ heightAll =(me.utilsCls.sumArray(len1Split) + 2*strucArray.length) *(r + gap) + 4 * marginY
16067
+ + 2 * legendWidth + textHeight*strucArray.length;
16068
+ // show common and diff interaction as well
16069
+ heightAll *= 3;
16070
+
16071
+ width = (maxWidth + 2) * (r + gap) + 2 * marginX + legendWidth;
16072
+
15931
16073
  } else {
15932
- height = 110;
16074
+ height = 110 + textHeight;
15933
16075
  heightAll = height * strucArray.length;
15934
- width = maxLen *(r + gap) + 2 * marginX;
16076
+ // show common and diff interaction as well
16077
+ heightAll *= 3;
16078
+
16079
+ width = (maxWidth + 2) * (r + gap) + 2 * marginX;
15935
16080
  }
15936
- let id, graphWidth;
16081
+ let id;
15937
16082
  if(bScatterplot) {
15938
16083
  ic.scatterplotWidth = 2 * width;
15939
- graphWidth = ic.scatterplotWidth;
16084
+ ic.scatterplotWidth;
15940
16085
  id = me.scatterplotid;
15941
16086
  } else {
15942
16087
  ic.linegraphWidth = 2 * width;
15943
- graphWidth = ic.linegraphWidth;
16088
+ ic.linegraphWidth;
15944
16089
  id = me.linegraphid;
15945
16090
  }
15946
16091
  html =(strucArray.length == 0) ? "No interactions found for each structure<br><br>" :
15947
- "2D integration graph for structure(s) <b>" + strucArray + "</b><br><br>";
15948
- html += "<svg id='" + id + "' viewBox='0,0," + width + "," + heightAll + "' width='" + graphWidth + "px'>";
15949
- let heightFinal = 0;
15950
- if(linkArrayA.length > 0) {
15951
- if(bScatterplot) {
15952
- heightFinal -= 15;
15953
- html += this.drawScatterplot_base(nodeArray1a, nodeArray1b, linkArrayA, name2node, heightFinal);
15954
- heightFinal = 15;
15955
- height =(len1a + 1) *(r + gap) + 2 * marginY;
15956
- } else {
15957
- html += this.drawLineGraph_base(nodeArray1a, nodeArray1b, linkArrayA, name2node, heightFinal);
15958
- }
15959
- heightFinal += height;
15960
- ic.lineGraphStr += ic.getGraphCls.updateGraphJson(struc1, 1, nodeArray1a, nodeArray1b, linkArrayA);
15961
- }
15962
- if(linkArrayB.length > 0) {
15963
- if(bScatterplot) {
15964
- html += this.drawScatterplot_base(nodeArray2a, nodeArray2b, linkArrayB, name2node, heightFinal);
15965
- height =(len2a + 1) *(r + gap) + 2 * marginY;
15966
- } else {
15967
- html += this.drawLineGraph_base(nodeArray2a, nodeArray2b, linkArrayB, name2node, heightFinal);
15968
- }
15969
- heightFinal += height;
15970
- if(linkArrayA.length > 0) ic.lineGraphStr += ', \n';
15971
- ic.lineGraphStr += ic.getGraphCls.updateGraphJson(struc2, 2, nodeArray2a, nodeArray2b, linkArrayB);
15972
- }
15973
- if(linkArrayAB.length > 0 && !bScatterplot) {
15974
- html += this.drawLineGraph_base(nodeArray3a, nodeArray3b, linkArrayAB, name2node, heightFinal);
15975
- if(linkArrayA.length > 0 || linkArrayB.length > 0) ic.lineGraphStr += ', \n';
15976
- ic.lineGraphStr += '"structure1_2": {"id1": "' + struc1 + '", "id2": "' + struc2 + '", "nodes1":[';
15977
- ic.lineGraphStr += me.utilsCls.getJSONFromArray(nodeArray3a);
15978
- ic.lineGraphStr += '], \n"nodes2":[';
15979
- ic.lineGraphStr += me.utilsCls.getJSONFromArray(nodeArray3b);
15980
- ic.lineGraphStr += '], \n"links":[';
15981
- ic.lineGraphStr += me.utilsCls.getJSONFromArray(linkArrayAB);
15982
- ic.lineGraphStr += ']}';
15983
- }
16092
+ "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>";
16093
+ html += "<svg id='" + id + "' viewBox='0,0," + width + "," + heightAll + "'>";
16094
+
16095
+ let result, heightFinal = 0;
16096
+
16097
+ bCommonDiff = 0; // 0: all interactions, 1: common interactions, 2: different interactions
16098
+ result = this.drawGraphPerType(bCommonDiff, structureArray, bScatterplot, nodeArray1Split, nodeArray2Split, linkArraySplit, name2node, heightFinal, height, textHeight, len1Split, r, gap, marginY);
16099
+
16100
+ heightFinal = result.heightFinal;
16101
+ html += result.html;
16102
+
16103
+ bCommonDiff = 1;
16104
+ result = this.drawGraphPerType(bCommonDiff, structureArray, bScatterplot, nodeArray1SplitCommon, nodeArray2SplitCommon, linkArraySplitCommon, name2node, heightFinal, height, textHeight, len1Split, r, gap, marginY);
16105
+
16106
+ heightFinal = result.heightFinal;
16107
+ html += result.html;
16108
+
16109
+ bCommonDiff = 2;
16110
+ result = this.drawGraphPerType(bCommonDiff, structureArray, bScatterplot, nodeArray1SplitDiff, nodeArray2SplitDiff, linkArraySplitDiff, name2node, heightFinal, height, textHeight, len1Split, r, gap, marginY);
16111
+
16112
+ heightFinal = result.heightFinal;
16113
+ html += result.html;
16114
+
15984
16115
  html += "</svg>";
15985
16116
  } else {
15986
16117
  if(!bScatterplot) {
@@ -16038,7 +16169,57 @@ class LineGraph {
16038
16169
  return html;
16039
16170
  }
16040
16171
 
16041
- drawLineGraph_base(nodeArray1, nodeArray2, linkArray, name2node, height) { let ic = this.icn3d, me = ic.icn3dui;
16172
+ drawGraphPerType(bCommonDiff, structureArray, bScatterplot, nodeArray1, nodeArray2, linkArray, name2node, heightFinal, height, textHeight, len1Split, r, gap, marginY) { let ic = this.icn3d; ic.icn3dui;
16173
+ let html = "";
16174
+
16175
+ // draw common interaction
16176
+ let label, postfix;
16177
+ if(bCommonDiff == 0) {
16178
+ label = "Interactions in structure ";
16179
+ postfix = "";
16180
+ }
16181
+ else if(bCommonDiff == 1) {
16182
+ label = "Common interactions in structure ";
16183
+ postfix = "_common";
16184
+ }
16185
+ else if(bCommonDiff == 2) {
16186
+ label = "Different interactions in structure ";
16187
+ postfix = "_diff";
16188
+ }
16189
+
16190
+ for(let i = 0, il = structureArray.length; i < il; ++i) {
16191
+ if(bScatterplot) {
16192
+ html += this.drawScatterplot_base(nodeArray1[i], nodeArray2[i], linkArray[i], name2node, heightFinal, undefined, label + structureArray[i], textHeight);
16193
+ height =(len1Split[i] + 1) *(r + gap) + 2 * marginY + textHeight;
16194
+ } else {
16195
+ html += this.drawLineGraph_base(nodeArray1[i], nodeArray2[i], linkArray[i], name2node, heightFinal, label + structureArray[i], textHeight);
16196
+ }
16197
+ heightFinal += height;
16198
+
16199
+ if(bCommonDiff) { // very beginning
16200
+ if(i > 0) ic.lineGraphStr += ', \n';
16201
+ }
16202
+ else {
16203
+ ic.lineGraphStr += ', \n';
16204
+ }
16205
+ ic.lineGraphStr += ic.getGraphCls.updateGraphJson(structureArray[i], i + postfix, nodeArray1[i], nodeArray2[i], linkArray[i]);
16206
+ }
16207
+
16208
+ return {"heightFinal": heightFinal, "html": html};
16209
+ }
16210
+
16211
+ getIdArrayFromNode(node) { let ic = this.icn3d, me = ic.icn3dui;
16212
+ let idArray = []; // 1_1_1KQ2_A_1
16213
+ idArray.push('');
16214
+ idArray.push('');
16215
+
16216
+ let tmpStr = node.r.substr(4);
16217
+ idArray = idArray.concat(me.utilsCls.getIdArray(tmpStr));
16218
+
16219
+ return idArray;
16220
+ }
16221
+
16222
+ drawLineGraph_base(nodeArray1, nodeArray2, linkArray, name2node, height, label, textHeight) { let ic = this.icn3d, me = ic.icn3dui;
16042
16223
  let html = '';
16043
16224
  let len1 = nodeArray1.length,
16044
16225
  len2 = nodeArray2.length;
@@ -16055,6 +16236,13 @@ class LineGraph {
16055
16236
  margin2 = margin;
16056
16237
  margin1 = Math.abs(len1 - len2) *(r + gap) * 0.5 + margin;
16057
16238
  }
16239
+
16240
+ // draw label
16241
+ if(label) {
16242
+ height += textHeight;
16243
+ html += "<text x='" + margin1 + "' y='" + height + "' style='font-size:8px; font-weight:bold'>" + label + "</text>";
16244
+ }
16245
+
16058
16246
  let h1 = 30 + height,
16059
16247
  h2 = 80 + height;
16060
16248
  let nodeHtml = '';
@@ -16110,7 +16298,7 @@ class LineGraph {
16110
16298
  return html;
16111
16299
  }
16112
16300
 
16113
- drawScatterplot_base(nodeArray1, nodeArray2, linkArray, name2node, height, bContactMap) { let ic = this.icn3d; ic.icn3dui;
16301
+ drawScatterplot_base(nodeArray1, nodeArray2, linkArray, name2node, height, bContactMap, label, textHeight, bAfMap) { let ic = this.icn3d; ic.icn3dui;
16114
16302
  let html = '';
16115
16303
  let len1 = nodeArray1.length,
16116
16304
  len2 = nodeArray2.length;
@@ -16121,19 +16309,27 @@ class LineGraph {
16121
16309
  let marginX = 10,
16122
16310
  marginY = 20;
16123
16311
  let heightTotal =(len1 + 1) *(r + gap) + legendWidth + 2 * marginY;
16312
+
16313
+ // draw label
16314
+ if(label) {
16315
+ height += textHeight;
16316
+ html += "<text x='" + marginX + "' y='" + (height + 15).toString() + "' style='font-size:8px; font-weight:bold'>" + label + "</text>";
16317
+ }
16318
+
16124
16319
  let margin1 = height + heightTotal -(legendWidth + marginY +(r + gap)); // y-axis
16125
16320
  let margin2 = legendWidth + marginX +(r + gap); // x-axis
16126
- let x = legendWidth + marginX;
16321
+
16127
16322
  let nodeHtml = '';
16128
16323
  let node2posSet1 = {},
16129
16324
  node2posSet2 = {};
16325
+ let x = legendWidth + marginX;
16130
16326
  for(let i = 0; i < len1; ++i) {
16131
- nodeHtml += ic.getGraphCls.drawResNode(nodeArray1[i], i, r, gap, margin1, x, 'a', true);
16327
+ nodeHtml += ic.getGraphCls.drawResNode(nodeArray1[i], i, r, gap, margin1, x, 'a', true, undefined, bAfMap);
16132
16328
  node2posSet1[nodeArray1[i].id] = { x: x, y: margin1 - i *(r + gap) };
16133
16329
  }
16134
16330
  let y = height + heightTotal -(legendWidth + marginY);
16135
16331
  for(let i = 0; i < len2; ++i) {
16136
- nodeHtml += ic.getGraphCls.drawResNode(nodeArray2[i], i, r, gap, margin2, y, 'b', false, bContactMap);
16332
+ nodeHtml += ic.getGraphCls.drawResNode(nodeArray2[i], i, r, gap, margin2, y, 'b', false, bContactMap, bAfMap);
16137
16333
  node2posSet2[nodeArray2[i].id] = { x: margin2 + i *(r + gap), y: y };
16138
16334
  }
16139
16335
  for(let i = 0, il = linkArray.length; i < il; ++i) {
@@ -16143,10 +16339,10 @@ class LineGraph {
16143
16339
 
16144
16340
  if(!node1 || !node2) continue;
16145
16341
 
16146
- html += this.drawOnePairNode(link, node1, node2, node2posSet1, node2posSet2, bContactMap);
16342
+ html += this.drawOnePairNode(link, node1, node2, node2posSet1, node2posSet2, bContactMap, bAfMap);
16147
16343
 
16148
- if(bContactMap) { // draw symmetric contact map
16149
- html += this.drawOnePairNode(link, node2, node1, node2posSet1, node2posSet2, bContactMap);
16344
+ if(bContactMap && !bAfMap) { // draw symmetric contact map, bAfmap just need to draw once
16345
+ html += this.drawOnePairNode(link, node2, node1, node2posSet1, node2posSet2, bContactMap, bAfMap);
16150
16346
  }
16151
16347
  }
16152
16348
  // show nodes later
@@ -16154,7 +16350,7 @@ class LineGraph {
16154
16350
  return html;
16155
16351
  }
16156
16352
 
16157
- drawOnePairNode(link, node1, node2, node2posSet1, node2posSet2, bContactMap) { let ic = this.icn3d, me = ic.icn3dui;
16353
+ drawOnePairNode(link, node1, node2, node2posSet1, node2posSet2, bContactMap, bAfMap) { let ic = this.icn3d, me = ic.icn3dui;
16158
16354
  let html = '';
16159
16355
 
16160
16356
  let factor = 1;
@@ -16184,21 +16380,31 @@ class LineGraph {
16184
16380
  strokecolor = "#" + me.htmlCls.contactColor;
16185
16381
  }
16186
16382
 
16383
+ if(bContactMap) strokecolor = "#" + link.c;
16384
+
16187
16385
  let linestrokewidth;
16188
16386
  if(link.v == me.htmlCls.contactValue) {
16189
16387
  linestrokewidth = 1;
16190
16388
  } else {
16191
16389
  linestrokewidth = 2;
16192
16390
  }
16193
- html += "<g class='icn3d-interaction' resid1='" + resid1 + "' resid2='" + resid2 + "' >";
16194
- html += "<title>Interaction of residue " + node1.id + " with residue " + node2.id + "</title>";
16195
- if(bContactMap) {
16196
- html += "<rect x='" +(pos2.x - halfSize).toString() + "' y='" +(pos1.y - halfSize).toString() + "' width='" + rectSize + "' height='" + rectSize + "' fill='" + strokecolor + "' stroke-width='" + linestrokewidth + "' stroke='" + strokecolor + "' />";
16391
+
16392
+ if(bAfMap && ic.hex2skip[link.c]) ;
16393
+ else if(bAfMap && ic.hex2id[link.c]) {
16394
+ let id = ic.hex2id[link.c];
16395
+ html += "<use href='#" + id + "' x='" +(pos2.x - halfSize).toString() + "' y='" +(pos1.y - halfSize).toString() + "' />";
16197
16396
  }
16198
16397
  else {
16199
- html += "<rect x='" +(pos2.x - halfSize).toString() + "' y='" +(pos1.y - halfSize).toString() + "' width='" + rectSize + "' height='" + rectSize + "' fill='" + strokecolor + "' fill-opacity='0.6' stroke-width='" + linestrokewidth + "' stroke='" + strokecolor + "' />";
16398
+ html += "<g class='icn3d-interaction' resid1='" + resid1 + "' resid2='" + resid2 + "' >";
16399
+ html += "<title>Interaction of residue " + node1.id + " with residue " + node2.id + "</title>";
16400
+ if(bContactMap) {
16401
+ html += "<rect x='" +(pos2.x - halfSize).toString() + "' y='" +(pos1.y - halfSize).toString() + "' width='" + rectSize + "' height='" + rectSize + "' fill='" + strokecolor + "' stroke-width='" + linestrokewidth + "' stroke='" + strokecolor + "' />";
16402
+ }
16403
+ else {
16404
+ html += "<rect x='" +(pos2.x - halfSize).toString() + "' y='" +(pos1.y - halfSize).toString() + "' width='" + rectSize + "' height='" + rectSize + "' fill='" + strokecolor + "' fill-opacity='0.6' stroke-width='" + linestrokewidth + "' stroke='" + strokecolor + "' />";
16405
+ }
16406
+ html += "</g>";
16200
16407
  }
16201
- html += "</g>";
16202
16408
 
16203
16409
  return html;
16204
16410
  }
@@ -16498,8 +16704,9 @@ class ViewInterPairs {
16498
16704
  tmpText = 'Set 2';
16499
16705
  }
16500
16706
  html += '<div style="text-align:center"><br><b>Interactions Sorted on ' + tmpText + '</b>: <button class="' + ic.pre + 'showintercntonly" style="margin-left:20px">Show Count Only</button><button class="' + ic.pre + 'showinterdetails" style="margin-left:20px">Show Details</button></div>';
16501
- html += this.getAllInteractionTable(type).html;
16502
- bondCnt = this.getAllInteractionTable(type).bondCnt;
16707
+ let result = this.getAllInteractionTable(type);
16708
+ html += result.html;
16709
+ bondCnt = result.bondCnt;
16503
16710
 
16504
16711
  $("#" + ic.pre + "dl_interactionsorted").html(html);
16505
16712
  me.htmlCls.dialogCls.openDlg('dl_interactionsorted', 'Show sorted interactions');
@@ -18412,8 +18619,15 @@ class ResidueLabels {
18412
18619
  label.factor = 0.3;
18413
18620
 
18414
18621
  let atomColorStr = atom.color.getHexString().toUpperCase();
18415
- label.color = (ic.opts.background == 'white' || ic.opts.background == 'gray') ? ic.colorWhitebkgd : ic.colorBlackbkgd; //(atomColorStr === "CCCCCC" || atomColorStr === "C8C8C8") ? "#888888" : "#" + atomColorStr;
18416
- if(bSchematic) label.color = (atomColorStr === "CCCCCC" || atomColorStr === "C8C8C8") ? "#888888" : "#" + atomColorStr;
18622
+ //label.color = (ic.opts.background != 'black') ? ic.colorWhitebkgd : ic.colorBlackbkgd; //(atomColorStr === "CCCCCC" || atomColorStr === "C8C8C8") ? "#888888" : "#" + atomColorStr;
18623
+ //if(bSchematic) label.color = (atomColorStr === "CCCCCC" || atomColorStr === "C8C8C8") ? "#888888" : "#" + atomColorStr;
18624
+ // don't change residue labels
18625
+ if(bNumber) {
18626
+ label.color = (ic.opts.background != 'black') ? ic.colorWhitebkgd : ic.colorBlackbkgd;
18627
+ }
18628
+ else {
18629
+ label.color = (atomColorStr === "CCCCCC" || atomColorStr === "C8C8C8") ? "#888888" : "#" + atomColorStr;
18630
+ }
18417
18631
  label.background = background;
18418
18632
  //label.alpha = alpha; // ic.labelCls.hideLabels() didn't work. Remove this line for now
18419
18633
 
@@ -18457,7 +18671,7 @@ class ResidueLabels {
18457
18671
  label.text = atom.elem;
18458
18672
  label.size = size;
18459
18673
 
18460
- label.color = (ic.opts.background == 'white' || ic.opts.background == 'gray') ? ic.colorWhitebkgd : atom.color.getHexString();
18674
+ label.color = (ic.opts.background != 'black') ? ic.colorWhitebkgd : atom.color.getHexString();
18461
18675
  label.background = background;
18462
18676
 
18463
18677
  ic.labels['schematic'].push(label);
@@ -18495,7 +18709,7 @@ class ResidueLabels {
18495
18709
  }
18496
18710
 
18497
18711
  let atomColorStr = atom.color.getHexString().toUpperCase();
18498
- label.color = (ic.opts.background == 'white' || ic.opts.background == 'gray') ? ic.colorWhitebkgd : ic.colorBlackbkgd; //(atomColorStr === "CCCCCC" || atomColorStr === "C8C8C8") ? "#888888" : "#" + atomColorStr;
18712
+ label.color = (ic.opts.background != 'black') ? ic.colorWhitebkgd : ic.colorBlackbkgd; //(atomColorStr === "CCCCCC" || atomColorStr === "C8C8C8") ? "#888888" : "#" + atomColorStr;
18499
18713
  if(bElement) label.color = (atomColorStr === "CCCCCC" || atomColorStr === "C8C8C8") ? "#888888" : "#" + atomColorStr;
18500
18714
  label.background = background;
18501
18715
 
@@ -19275,7 +19489,8 @@ class Scap {
19275
19489
  if(!ic.alertAlt) {
19276
19490
  ic.alertAlt = true;
19277
19491
 
19278
- if(ic.bRender) var aaa = 1; //alert('Please press the letter "a" to alternate between wild type and mutant.');
19492
+ //if(ic.bRender) var aaa = 1; //alert('Please press the letter "a" to alternate between wild type and mutant.');
19493
+ var aaa = 1; //alert('Please press the letter "a" to alternate between wild type and mutant.');
19279
19494
  }
19280
19495
  }
19281
19496
 
@@ -19923,7 +20138,7 @@ class LoadPDB {
19923
20138
  // modified from iview (http://istar.cse.cuhk.edu.hk/iview/)
19924
20139
  //This PDB parser feeds the viewer with the content of a PDB file, pdbData.
19925
20140
  loadPDB(src, pdbid, bOpm, bVector, bMutation, bAppend) { let ic = this.icn3d, me = ic.icn3dui;
19926
- //ic.atoms = {}
20141
+ let bNMR = false;
19927
20142
  let lines = src.split('\n');
19928
20143
 
19929
20144
  let chainsTmp = {}; // serial -> atom
@@ -20108,6 +20323,11 @@ class LoadPDB {
20108
20323
  if(line.indexOf('1/2 of bilayer thickness:') !== -1) { // OPM transmembrane protein
20109
20324
  ic.halfBilayerSize = parseFloat(line.substr(line.indexOf(':') + 1).trim());
20110
20325
  }
20326
+ else if (type == 210) {
20327
+ if((line.substr(11, 32).trim() == 'EXPERIMENT TYPE') && line.substr(45).trim() == 'NMR') {
20328
+ bNMR = true;
20329
+ }
20330
+ }
20111
20331
  else if (type == 350 && line.substr(13, 5) == 'BIOMT') {
20112
20332
  let n = parseInt(line[18]) - 1;
20113
20333
  //var m = parseInt(line.substr(21, 2));
@@ -20165,12 +20385,14 @@ class LoadPDB {
20165
20385
 
20166
20386
  //helices = [];
20167
20387
  //sheets = [];
20168
- sheetArray = [];
20169
- sheetStart = [];
20170
- sheetEnd = [];
20171
- helixArray = [];
20172
- helixStart = [];
20173
- helixEnd = [];
20388
+ if(!bNMR) {
20389
+ sheetArray = [];
20390
+ sheetStart = [];
20391
+ sheetEnd = [];
20392
+ helixArray = [];
20393
+ helixStart = [];
20394
+ helixEnd = [];
20395
+ }
20174
20396
  } else if (record === 'JRNL ') {
20175
20397
  if(line.substr(12, 4) === 'PMID') {
20176
20398
  ic.pmid = line.substr(19).trim();
@@ -20268,27 +20490,26 @@ class LoadPDB {
20268
20490
 
20269
20491
  // Assign secondary structures from the input
20270
20492
  // if a residue is assigned both sheet and helix, it is assigned as sheet
20271
- if($.inArray(residueNum, sheetArray) !== -1) {
20493
+ if(this.isSecondary(residueNum, sheetArray, bNMR)) {
20272
20494
  ic.atoms[serial].ss = 'sheet';
20273
-
20274
- if($.inArray(residueNum, sheetStart) !== -1) {
20495
+ if(this.isSecondary(residueNum, sheetStart, bNMR)) {
20275
20496
  ic.atoms[serial].ssbegin = true;
20276
20497
  }
20277
20498
 
20278
20499
  // do not use else if. Some residues are both start and end of secondary structure
20279
- if($.inArray(residueNum, sheetEnd) !== -1) {
20500
+ if(this.isSecondary(residueNum, sheetEnd, bNMR)) {
20280
20501
  ic.atoms[serial].ssend = true;
20281
20502
  }
20282
20503
  }
20283
- else if($.inArray(residueNum, helixArray) !== -1) {
20504
+ else if(this.isSecondary(residueNum, helixArray, bNMR)) {
20284
20505
  ic.atoms[serial].ss = 'helix';
20285
20506
 
20286
- if($.inArray(residueNum, helixStart) !== -1) {
20507
+ if(this.isSecondary(residueNum, helixStart, bNMR)) {
20287
20508
  ic.atoms[serial].ssbegin = true;
20288
20509
  }
20289
20510
 
20290
20511
  // do not use else if. Some residues are both start and end of secondary structure
20291
- if($.inArray(residueNum, helixEnd) !== -1) {
20512
+ if(this.isSecondary(residueNum, helixEnd, bNMR)) {
20292
20513
  ic.atoms[serial].ssend = true;
20293
20514
  }
20294
20515
  }
@@ -20729,6 +20950,24 @@ class LoadPDB {
20729
20950
  return {'chainresiCalphaHash': chainCalphaHash, 'center': ic.center.clone()}
20730
20951
  }
20731
20952
 
20953
+ isSecondary(resid, residArray, bNMR) { let ic = this.icn3d; ic.icn3dui;
20954
+ if(!bNMR) {
20955
+ return $.inArray(resid, residArray) != -1;
20956
+ }
20957
+ else {
20958
+ let chain_resi = resid.substr(resid.indexOf('_') + 1);
20959
+
20960
+ let bFound = false;
20961
+ for(let i = 0, il = residArray.length; i < il; ++i) {
20962
+ if(chain_resi == residArray[i].substr(residArray[i].indexOf('_') + 1)) {
20963
+ bFound = true;
20964
+ break;
20965
+ }
20966
+ }
20967
+
20968
+ return bFound;
20969
+ }
20970
+ }
20732
20971
  }
20733
20972
 
20734
20973
  /**
@@ -20776,6 +21015,7 @@ class LoadAtomData {
20776
21015
  let refinedStr =(me.cfg.inpara && me.cfg.inpara.indexOf('atype=1') !== -1) ? 'Invariant Core ' : '';
20777
21016
  ic.molTitle = refinedStr + 'Structure Alignment of ';
20778
21017
 
21018
+ let bTitle = false;
20779
21019
  for(let i = 0, il = data.alignedStructures[0].length; i < il; ++i) {
20780
21020
  let structure = data.alignedStructures[0][i];
20781
21021
 
@@ -20813,10 +21053,13 @@ class LoadAtomData {
20813
21053
  ic.molTitle += " and ";
20814
21054
  if(structure.descr !== undefined) ic.pmid += "_";
20815
21055
  }
21056
+
21057
+ bTitle = true;
20816
21058
  }
20817
21059
 
20818
21060
  ic.molTitle += ' from VAST+';
20819
21061
 
21062
+ if(!bTitle) ic.molTitle = '';
20820
21063
  }
20821
21064
  else { // mmdbid or mmcifid
20822
21065
  if(data.descr !== undefined) ic.molTitle += data.descr.name;
@@ -22316,7 +22559,7 @@ class PdbParser {
22316
22559
  let url, dataType;
22317
22560
 
22318
22561
  if(bAf) {
22319
- url = "https://alphafold.ebi.ac.uk/files/AF-" + pdbid + "-F1-model_v1.pdb";
22562
+ url = "https://alphafold.ebi.ac.uk/files/AF-" + pdbid + "-F1-model_v2.pdb";
22320
22563
  ic.ParserUtilsCls.setYourNote(pdbid.toUpperCase() + '(AlphaFold) in iCn3D');
22321
22564
  }
22322
22565
  else {
@@ -23121,11 +23364,11 @@ class AlignParser {
23121
23364
  ic.alignmolid2color.push(tmpHash);
23122
23365
  }
23123
23366
 
23124
- //var url3 = me.htmlCls.baseUrl + 'mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&atomonly=1&uid=' + ic.mmdbidArray[0];
23125
- //var url4 = me.htmlCls.baseUrl + 'mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&atomonly=1&uid=' + ic.mmdbidArray[1];
23367
+ //var url3 = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&bu=" + me.cfg.bu + "&atomonly=1&uid=" + ic.mmdbidArray[0];
23368
+ //var url4 = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&bu=" + me.cfg.bu + "&atomonly=1&uid=" + ic.mmdbidArray[1];
23126
23369
  // need the parameter moleculeInfor
23127
- let url3 = me.htmlCls.baseUrl + 'mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&uid=' + ic.mmdbidArray[0];
23128
- let url4 = me.htmlCls.baseUrl + 'mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&uid=' + ic.mmdbidArray[1];
23370
+ let url3 = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&bu=" + me.cfg.bu + "&uid=" + ic.mmdbidArray[0];
23371
+ let url4 = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&bu=" + me.cfg.bu + "&uid=" + ic.mmdbidArray[1];
23129
23372
 
23130
23373
  let d3 = $.ajax({
23131
23374
  url: url3,
@@ -23660,14 +23903,14 @@ class MmdbParser {
23660
23903
  // b: b-factor, s: water, ft: pdbsite
23661
23904
  //&ft=1
23662
23905
  if(bGi) {
23663
- url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&simple=1&gi=" + mmdbid;
23906
+ url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&bu=" + me.cfg.bu + "&simple=1&gi=" + mmdbid;
23664
23907
  }
23665
23908
  else {
23666
- url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&simple=1&uid=" + mmdbid;
23667
- }
23909
+ url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&bu=" + me.cfg.bu + "&simple=1&uid=" + mmdbid;
23910
+ }
23668
23911
 
23669
- // use asymmetric unit for BLAST search, e.g., https://www.ncbi.nlm.nih.gov/Structure/icn3d/full.html?from=blast&blast_rep_id=5XZC_B&query_id=1TUP_A&command=view+annotations;set+annotation+cdd;set+annotation+site;set+view+detailed+view;select+chain+5XZC_B;show+selection&log$=align&blast_rank=1&RID=EPUCYNVV014&buidx=0
23670
- if(me.cfg.blast_rep_id !== undefined) url += '&buidx=0';
23912
+ // use asymmetric unit for BLAST search, e.g., https://www.ncbi.nlm.nih.gov/Structure/icn3d/full.html?from=blast&blast_rep_id=5XZC_B&query_id=1TUP_A&command=view+annotations;set+annotation+cdd;set+annotation+site;set+view+detailed+view;select+chain+5XZC_B;show+selection&log$=align&blast_rank=1&RID=EPUCYNVV014&bu=0
23913
+ if(me.cfg.blast_rep_id !== undefined) url += '&bu=0';
23671
23914
 
23672
23915
  ic.bCid = undefined;
23673
23916
 
@@ -23923,7 +24166,7 @@ class MmdbParser {
23923
24166
  } // for each domainArray
23924
24167
  } // for each molid
23925
24168
 
23926
- // "asuAtomCount" is defined when: 1) atom count is over the threshold 2) buidx=1 3) asu atom count is smaller than biological unit atom count
24169
+ // "asuAtomCount" is defined when: 1) atom count is over the threshold 2) bu=1 3) asu atom count is smaller than biological unit atom count
23927
24170
  ic.bAssemblyUseAsu =(data.asuAtomCount !== undefined) ? true : false;
23928
24171
  if(type !== undefined) {
23929
24172
  ic.bAssemblyUseAsu = false;
@@ -24549,7 +24792,7 @@ class ChainalignParser {
24549
24792
  let pos1 = alignArray[0].indexOf('_');
24550
24793
  ic.mmdbid_t = alignArray[0].substr(0, pos1).toUpperCase();
24551
24794
  ic.chain_t = alignArray[0].substr(pos1+1);
24552
- let url_t = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&uid=" + ic.mmdbid_t;
24795
+ let url_t = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&bu=" + me.cfg.bu + "&uid=" + ic.mmdbid_t;
24553
24796
  if(me.cfg.inpara !== undefined) url_t += me.cfg.inpara;
24554
24797
 
24555
24798
  let ajaxArray = [];
@@ -24575,7 +24818,7 @@ class ChainalignParser {
24575
24818
  let chainalignFinal = ic.mmdbid_q + "_" + ic.chain_q + "," + ic.mmdbid_t + "_" + ic.chain_t;
24576
24819
 
24577
24820
  let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi?chainpairs=" + chainalignFinal;
24578
- let url_q = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&uid=" + ic.mmdbid_q;
24821
+ let url_q = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&bu=" + me.cfg.bu + "&uid=" + ic.mmdbid_q;
24579
24822
 
24580
24823
  if(me.cfg.inpara !== undefined) url_q += me.cfg.inpara;
24581
24824
 
@@ -26452,6 +26695,19 @@ class LoadScript {
26452
26695
 
26453
26696
  return;
26454
26697
  }
26698
+ else if(ic.commands[i].trim().indexOf('set af align error map') == 0) {
26699
+ let strArray = ic.commands[i].split("|||");
26700
+ let command = strArray[0].trim();
26701
+
26702
+ $.when(thisClass.applyCommandAfmap(command)).then(function() {
26703
+ //if(!me.cfg.notebook && dialog && dialog.hasClass("ui-dialog-content")) dialog.dialog( "close" );
26704
+
26705
+ //ic.drawCls.draw();
26706
+ thisClass.execCommandsBase(i + 1, end, steps);
26707
+ });
26708
+
26709
+ return;
26710
+ }
26455
26711
  else {
26456
26712
  ic.applyCommandCls.applyCommand(ic.commands[i]);
26457
26713
  }
@@ -26644,11 +26900,18 @@ class LoadScript {
26644
26900
  me.cfg.mmcifid = id;
26645
26901
  ic.mmcifParserCls.downloadMmcif(id);
26646
26902
  }
26647
- else if(command.indexOf('load mmdb') !== -1) {
26903
+ else if(command.indexOf('load mmdb') !== -1 || command.indexOf('load mmdb1') !== -1) {
26648
26904
  me.cfg.mmdbid = id;
26905
+ me.cfg.bu = 1;
26649
26906
 
26650
26907
  ic.mmdbParserCls.downloadMmdb(id);
26651
26908
  }
26909
+ else if(command.indexOf('load mmdb0') !== -1) {
26910
+ me.cfg.mmdbid = id;
26911
+ me.cfg.bu = 0;
26912
+
26913
+ ic.mmdbParserCls.downloadMmdb(id);
26914
+ }
26652
26915
  else if(command.indexOf('load gi') !== -1) {
26653
26916
  me.cfg.gi = id;
26654
26917
  ic.mmdbParserCls.downloadGi(id);
@@ -26778,6 +27041,23 @@ class LoadScript {
26778
27041
  return ic.deferredRealign.promise();
26779
27042
  }
26780
27043
 
27044
+ applyCommandAfmapBase(command) { let ic = this.icn3d; ic.icn3dui;
27045
+ let afid = command.substr(command.lastIndexOf(' ') + 1);
27046
+
27047
+ ic.contactMapCls.afErrorMap(afid);
27048
+ }
27049
+
27050
+ applyCommandAfmap(command) { let ic = this.icn3d; ic.icn3dui;
27051
+ let thisClass = this;
27052
+
27053
+ // chain functions together
27054
+ ic.deferredAfmap = new $.Deferred(function() {
27055
+ thisClass.applyCommandAfmapBase(command);
27056
+ }); // end of me.deferred = $.Deferred(function() {
27057
+
27058
+ return ic.deferredAfmap.promise();
27059
+ }
27060
+
26781
27061
  applyCommandGraphinteractionBase(command) { let ic = this.icn3d; ic.icn3dui;
26782
27062
  let paraArray = command.split(' | ');
26783
27063
  if(paraArray.length >= 3) {
@@ -28925,7 +29205,7 @@ class Analysis {
28925
29205
  label.text = 'Chain ' + chainName + ': ' + proteinName;
28926
29206
  label.size = size;
28927
29207
  ic.firstAtomObjCls.getFirstCalphaAtomObj(ic.chains[chainid]).color.getHexString().toUpperCase();
28928
- label.color = (ic.opts.background == 'white' || ic.opts.background == 'gray') ? ic.colorWhitebkgd : ic.colorBlackbkgd; //(atomColorStr === "CCCCCC" || atomColorStr === "C8C8C8") ? "#888888" : "#" + atomColorStr;
29208
+ label.color = (ic.opts.background != 'black') ? ic.colorWhitebkgd : ic.colorBlackbkgd; //(atomColorStr === "CCCCCC" || atomColorStr === "C8C8C8") ? "#888888" : "#" + atomColorStr;
28929
29209
  label.background = background;
28930
29210
  ic.labels['chain'].push(label);
28931
29211
  }
@@ -28959,10 +29239,10 @@ class Analysis {
28959
29239
  }
28960
29240
  labelN.size = size;
28961
29241
  labelC.size = size;
28962
- let atomNColorStr = firstAtom.color.getHexString().toUpperCase();
28963
- let atomCColorStr = lastAtom.color.getHexString().toUpperCase();
28964
- labelN.color = (ic.opts.background == 'white' || ic.opts.background == 'gray') ? ic.colorWhitebkgd : (atomNColorStr === "CCCCCC" || atomNColorStr === "C8C8C8") ? "#888888" : "#" + atomNColorStr;
28965
- labelC.color = (ic.opts.background == 'white' || ic.opts.background == 'gray') ? ic.colorWhitebkgd : (atomCColorStr === "CCCCCC" || atomCColorStr === "C8C8C8") ? "#888888" : "#" + atomCColorStr;
29242
+ firstAtom.color.getHexString().toUpperCase();
29243
+ lastAtom.color.getHexString().toUpperCase();
29244
+ labelN.color = (ic.opts.background != 'black') ? ic.colorWhitebkgd : ic.colorBlackbkgd; //(atomNColorStr === "CCCCCC" || atomNColorStr === "C8C8C8") ? "#888888" : "#" + atomNColorStr;
29245
+ labelC.color = (ic.opts.background != 'black') ? ic.colorWhitebkgd : ic.colorBlackbkgd; //(atomCColorStr === "CCCCCC" || atomCColorStr === "C8C8C8") ? "#888888" : "#" + atomCColorStr;
28966
29246
  labelN.background = background;
28967
29247
  labelC.background = background;
28968
29248
  ic.labels['chain'].push(labelN);
@@ -29551,7 +29831,7 @@ class Picking {
29551
29831
  let text =(ic.pk == 1) ? atom.resn + atom.resi + '@' + atom.name : atom.resn + atom.resi;
29552
29832
  if(ic.structures !== undefined && Object.keys(ic.structures).length > 1) {
29553
29833
  text = atom.structure + '_' + atom.chain + ' ' + text;
29554
- $("#" + ic.pre + "popup").css("width", "140px");
29834
+ $("#" + ic.pre + "popup").css("width", "160px");
29555
29835
  }
29556
29836
  else {
29557
29837
  $("#" + ic.pre + "popup").css("width", "80px");
@@ -29779,8 +30059,9 @@ class ApplyCommand {
29779
30059
  ic.bAddCommands = false;
29780
30060
 
29781
30061
  let commandTransformation = commandStr.split('|||');
30062
+ let commandTransformation2 = commandTransformation[0].split('%7C%7C%7C'); // sometimes encoded transformation is also included
29782
30063
 
29783
- let commandOri = commandTransformation[0].replace(/\s+/g, ' ').trim();
30064
+ let commandOri = commandTransformation2[0].replace(/\s+/g, ' ').trim();
29784
30065
  let command = commandOri.toLowerCase();
29785
30066
 
29786
30067
  // exact match =============
@@ -30376,15 +30657,18 @@ class ApplyCommand {
30376
30657
  let value = command.substr(command.lastIndexOf(' ') + 1);
30377
30658
  ic.opts['background'] = value;
30378
30659
 
30379
- if(value == 'white' || value == 'grey') {
30380
- $("#" + ic.pre + "title").css("color", "black");
30381
- $("#" + ic.pre + "titlelink").css("color", "black");
30660
+ if(value == 'black') {
30661
+ $("#" + ic.pre + "title").css("color", me.htmlCls.GREYD);
30662
+ $("#" + ic.pre + "titlelink").css("color", me.htmlCls.GREYD);
30382
30663
  }
30383
30664
  else {
30384
- $("#" + ic.pre + "title").css("color", me.htmlCls.GREYD);
30385
- $("#" + ic.pre + "titlelink").css("color", me.htmlCls.GREYD);
30665
+ $("#" + ic.pre + "title").css("color", "black");
30666
+ $("#" + ic.pre + "titlelink").css("color", "black");
30386
30667
  }
30387
30668
  }
30669
+ else if(command.indexOf('set label color') == 0) {
30670
+ ic.labelcolor = command.substr(command.lastIndexOf(' ') + 1);
30671
+ }
30388
30672
  else if(commandOri.indexOf('set thickness') == 0) {
30389
30673
  let paraArray = command.split(' | ');
30390
30674
 
@@ -30769,6 +31053,14 @@ class ApplyCommand {
30769
31053
 
30770
31054
  $("#" + me.contactmapid).attr("width",(ic.contactmapWidth * parseFloat(scale)).toString() + "px");
30771
31055
  }
31056
+ else if(command.indexOf('alignerrormap scale') == 0) {
31057
+ let pos = command.lastIndexOf(' ');
31058
+ let scale = command.substr(pos + 1);
31059
+
31060
+ $("#" + me.alignerrormapid + "_scale").val(scale);
31061
+
31062
+ $("#" + me.alignerrormapid).attr("width",(ic.alignerrormapWidth * parseFloat(scale)).toString() + "px");
31063
+ }
30772
31064
  else if(command.indexOf('graph force') == 0) {
30773
31065
  let pos = command.lastIndexOf(' ');
30774
31066
  me.htmlCls.force = parseInt(command.substr(pos + 1));
@@ -32216,6 +32508,8 @@ class SetSeqAlign {
32216
32508
  ic.alnChainsAnTtl[chainid1][6].push("");
32217
32509
 
32218
32510
  let alignIndex = 1;
32511
+ if(!ic.chainsMapping[chainid1]) ic.chainsMapping[chainid1] = {};
32512
+ if(!ic.chainsMapping[chainid2]) ic.chainsMapping[chainid2] = {};
32219
32513
  //for(let j = 0, jl = alignData.sseq.length; j < jl; ++j) {
32220
32514
  for(let j = start; j <= end; ++j) {
32221
32515
  // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
@@ -32247,6 +32541,10 @@ class SetSeqAlign {
32247
32541
  ic.nconsHash2[chainid2 + '_' + resi] = 1;
32248
32542
  }
32249
32543
 
32544
+ // mapping, use the firstsequence as the reference structure
32545
+ ic.chainsMapping[chainid1][chainid1 + '_' + id2aligninfo[j].resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
32546
+ ic.chainsMapping[chainid2][chainid2 + '_' + resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
32547
+
32250
32548
  color2 = '#' + ic.showAnnoCls.getColorhexFromBlosum62(id2aligninfo[j].resn, resn);
32251
32549
 
32252
32550
  // expensive and thus remove
@@ -32431,6 +32729,8 @@ class SetSeqAlign {
32431
32729
  if(ic.qt_start_end[chainIndex] === undefined) return;
32432
32730
 
32433
32731
  let alignIndex = 1;
32732
+ if(!ic.chainsMapping[chainid1]) ic.chainsMapping[chainid1] = {};
32733
+ if(!ic.chainsMapping[chainid2]) ic.chainsMapping[chainid2] = {};
32434
32734
  for(let i = 0, il = ic.qt_start_end[chainIndex].length; i < il; ++i) {
32435
32735
  //var start1 = ic.qt_start_end[chainIndex][i].q_start - 1;
32436
32736
  //var start2 = ic.qt_start_end[chainIndex][i].t_start - 1;
@@ -32524,6 +32824,10 @@ class SetSeqAlign {
32524
32824
  ic.nconsHash2[chainid2 + '_' + resi2] = 1;
32525
32825
  }
32526
32826
 
32827
+ // mapping, use the firstsequence as the reference structure
32828
+ ic.chainsMapping[chainid1][chainid1 + '_' + resi1] = resn1 + resi1;
32829
+ ic.chainsMapping[chainid2][chainid2 + '_' + resi2] = resn1 + resi1;
32830
+
32527
32831
  color2 = '#' + ic.showAnnoCls.getColorhexFromBlosum62(resn1, resn2);
32528
32832
 
32529
32833
  let bFirstResi =(i === 0 && j === 0) ? true : false;
@@ -32573,6 +32877,8 @@ class SetSeqAlign {
32573
32877
  // let prevChainid1 = '', prevChainid2 = '', cnt1 = 0, cnt2 = 0;
32574
32878
 
32575
32879
  let residuesHash = {};
32880
+ if(!ic.chainsMapping[chainid_t]) ic.chainsMapping[chainid_t] = {};
32881
+ if(!ic.chainsMapping[chainid]) ic.chainsMapping[chainid] = {};
32576
32882
 
32577
32883
  for(let i = 0, il = ic.realignResid[structure1].length; i < il; ++i) {
32578
32884
  let resObject1 = ic.realignResid[structure1][i];
@@ -32599,6 +32905,11 @@ class SetSeqAlign {
32599
32905
  else {
32600
32906
  color = "#0000FF";
32601
32907
  }
32908
+
32909
+ // mapping, use the firstsequence as the reference structure
32910
+ ic.chainsMapping[chainid_t][chainid_t + '_' + resObject1.resi] = resObject1.resn + resObject1.resi;
32911
+ ic.chainsMapping[chainid][chainid + '_' + resObject2.resi] = resObject1.resn + resObject1.resi;
32912
+
32602
32913
  let color2 = '#' + ic.showAnnoCls.getColorhexFromBlosum62(resObject1.resn, resObject2.resn);
32603
32914
 
32604
32915
  resObject1.color = color;
@@ -34178,7 +34489,7 @@ class HlSeq {
34178
34489
 
34179
34490
  //var size = parseInt(ic.LABELSIZE * 10 / commandname.length);
34180
34491
  let size = ic.LABELSIZE;
34181
- let color = (ic.opts.background == 'white' || ic.opts.background == 'gray') ? ic.colorWhitebkgd : ic.colorBlackbkgd; //"FFFF00";
34492
+ let color = (ic.opts.background != 'black') ? ic.colorWhitebkgd : ic.colorBlackbkgd; //"FFFF00";
34182
34493
  if(position !== undefined) ic.analysisCls.addLabel(commanddescr, position.center.x, position.center.y, position.center.z, size, color, undefined, 'custom');
34183
34494
 
34184
34495
  ic.drawCls.draw();
@@ -34582,7 +34893,7 @@ class ShowAnno {
34582
34893
  $.ajax(this);
34583
34894
  return;
34584
34895
  }
34585
- this.enableHlSeq();
34896
+ thisClass.enableHlSeq();
34586
34897
  console.log( "No data were found for the protein " + chnidBaseArray + "..." );
34587
34898
  for(let chnid in ic.protein_chainid) {
34588
34899
  let chnidBase = ic.protein_chainid[chnid];
@@ -35272,7 +35583,7 @@ class AnnoDomain {
35272
35583
  }
35273
35584
  ic.showAnnoCls.enableHlSeq();
35274
35585
  ic.bAjax3ddomain = true;
35275
- bAjaxDone1 = true;
35586
+ //bAjaxDone1 = true;
35276
35587
  if(ic.deferred3ddomain !== undefined) {
35277
35588
  if(me.cfg.align === undefined || me.cfg.chainalign === undefined) {
35278
35589
  ic.deferred3ddomain.resolve();
@@ -35485,7 +35796,7 @@ class AnnoSnpClinVar {
35485
35796
  ic.labels['clinvar'] = [];
35486
35797
  //var size = Math.round(ic.LABELSIZE * 10 / label.length);
35487
35798
  let size = ic.LABELSIZE;
35488
- let color = (ic.opts.background == 'white' || ic.opts.background == 'gray') ? ic.colorWhitebkgd : ic.colorBlackbkgd; //"#FFFF00";
35799
+ let color = (ic.opts.background != 'black') ? ic.colorWhitebkgd : ic.colorBlackbkgd; //"#FFFF00";
35489
35800
  ic.analysisCls.addLabel(label, position.center.x + 1, position.center.y + 1, position.center.z + 1, size, color, undefined, 'clinvar');
35490
35801
  ic.hAtoms = {};
35491
35802
  for(let j in ic.residues[residueid]) {
@@ -38387,9 +38698,12 @@ class Selection {
38387
38698
  ic.graphStr = this.getGraphDataForDisplayed();
38388
38699
  }
38389
38700
 
38701
+ // don not redraw graphs after the selection changes
38702
+ /*
38390
38703
  if(ic.bGraph) ic.drawGraphCls.drawGraph(ic.graphStr, ic.pre + 'dl_graph');
38391
38704
  if(ic.bLinegraph) ic.lineGraphCls.drawLineGraph(ic.graphStr);
38392
38705
  if(ic.bScatterplot) ic.lineGraphCls.drawLineGraph(ic.graphStr, true);
38706
+ */
38393
38707
  }
38394
38708
 
38395
38709
  hideSelection() { let ic = this.icn3d, me = ic.icn3dui;
@@ -38597,7 +38911,7 @@ class Selection {
38597
38911
  }
38598
38912
 
38599
38913
  toggleMembrane(bShowMembrane) {var ic = this.icn3d, me = ic.icn3dui;
38600
- let structureArray = Object.keys(ic.structures);
38914
+ let structureArray = (ic.structures) ? Object.keys(ic.structures) : [];
38601
38915
 
38602
38916
  for(let i = 0, il = structureArray.length; i < il; ++i) {
38603
38917
  let structure = structureArray[i];
@@ -38918,7 +39232,8 @@ class SetStyle {
38918
39232
  setBackground(color) {var ic = this.icn3d, me = ic.icn3dui;
38919
39233
  ic.setOptionCls.setOption('background', color);
38920
39234
  me.htmlCls.clickMenuCls.setLogCmd('set background ' + color, true);
38921
- let titleColor =(color == 'black' || color == 'transparent') ? me.htmlCls.GREYD : 'black';
39235
+ //let titleColor =(color == 'black' || color == 'transparent') ? me.htmlCls.GREYD : 'black';
39236
+ let titleColor = (color == 'black') ? me.htmlCls.GREYD : 'black';
38922
39237
  $("#" + ic.pre + "title").css("color", titleColor);
38923
39238
  $("#" + ic.pre + "titlelink").css("color", titleColor);
38924
39239
  }
@@ -39468,7 +39783,7 @@ class TextSprite {
39468
39783
  // default yellow
39469
39784
  //let textColor = parameters.hasOwnProperty("textColor") && parameters["textColor"] !== undefined ? me.utilsCls.hexToRgb(parameters["textColor"], textAlpha) : { r:255, g:255, b:0, a:1.0 };
39470
39785
  // default black or white
39471
- let defaultColor = ( ic.opts.background == 'white' || ic.opts.background == 'gray' ) ? { r:0, g:0, b:0, a:1.0 } : { r:255, g:255, b:0, a:1.0 };
39786
+ let defaultColor = (ic.opts.background != 'black') ? { r:0, g:0, b:0, a:1.0 } : { r:255, g:255, b:0, a:1.0 };
39472
39787
  let textColor = parameters.hasOwnProperty("textColor") && parameters["textColor"] !== undefined ? me.utilsCls.hexToRgb(parameters["textColor"], textAlpha)
39473
39788
  : defaultColor;
39474
39789
  if(!textColor) textColor = defaultColor;
@@ -39608,7 +39923,7 @@ class Label {
39608
39923
 
39609
39924
  for(let name in labels) {
39610
39925
  let labelArray = (labels[name] !== undefined) ? labels[name] : [];
39611
- let defaultColor = (ic.opts.background == 'white' || ic.opts.background == 'gray') ? ic.colorWhitebkgd : ic.colorBlackbkgd;
39926
+ let defaultColor = (ic.opts.background != 'black') ? ic.colorWhitebkgd : ic.colorBlackbkgd;
39612
39927
 
39613
39928
  for (let i = 0, il = labelArray.length; i < il; ++i) {
39614
39929
  let label = labelArray[i];
@@ -39620,6 +39935,8 @@ class Label {
39620
39935
 
39621
39936
  let labelsize = (label.size !== undefined) ? label.size : ic.LABELSIZE;
39622
39937
  let labelcolor = (label.color !== undefined) ? label.color : defaultColor;
39938
+ if(ic.labelcolor) labelcolor = ic.labelcolor;
39939
+
39623
39940
  let labelbackground = (label.background !== undefined) ? label.background : '#cccccc';
39624
39941
  let labelalpha = (label.alpha !== undefined) ? label.alpha : 1.0;
39625
39942
 
@@ -39645,7 +39962,8 @@ class Label {
39645
39962
  }
39646
39963
  }
39647
39964
 
39648
- bb.position.set(label.position.x, label.position.y, label.position.z);
39965
+ let labelOffset = (name == 'schematic' || name == 'residue') ? 0 : ic.coilWidth; // 0.3
39966
+ bb.position.set(label.position.x + labelOffset, label.position.y + labelOffset, label.position.z + labelOffset);
39649
39967
  ic.mdl.add(bb);
39650
39968
  // do not add labels to objects for pk
39651
39969
  }
@@ -39986,10 +40304,10 @@ class ApplyDisplay {
39986
40304
  if(labelArray) {
39987
40305
  for(let i = 0, il = labelArray.length; i < il; ++i) {
39988
40306
  let label = labelArray[i];
39989
- if((ic.opts.background == 'white' || ic.opts.background == 'grey') && label.color == ic.colorBlackbkgd) {
40307
+ if((ic.opts.background != 'black') && label.color == ic.colorBlackbkgd) {
39990
40308
  label.color = ic.colorWhitebkgd;
39991
40309
  }
39992
- else if((ic.opts.background == 'black' || ic.opts.background == 'transparent') && label.color == ic.colorWhitebkgd) {
40310
+ else if((ic.opts.background == 'black') && label.color == ic.colorWhitebkgd) {
39993
40311
  label.color = ic.colorBlackbkgd;
39994
40312
  }
39995
40313
  }
@@ -42476,10 +42794,10 @@ class Transform {
42476
42794
 
42477
42795
  if(ic.bRender) ic.drawCls.render();
42478
42796
  }
42479
-
42797
+ /*
42480
42798
  //Zoom in the structure at certain ratio, e.g., 0.1 is a reasonable value.
42481
42799
  zoomIn(normalizedFactor) { let ic = this.icn3d, me = ic.icn3dui;
42482
- let para = {};
42800
+ let para = {}
42483
42801
  para._zoomFactor = 1 - normalizedFactor;
42484
42802
  para.update = true;
42485
42803
  if(ic.bControlGl && !me.bNode) {
@@ -42489,12 +42807,14 @@ class Transform {
42489
42807
  ic.controls.update(para);
42490
42808
  }
42491
42809
 
42492
- if(ic.bRender) ic.drawCls.render();
42810
+ if(ic.bRender) {
42811
+ ic.drawCls.render();
42812
+ }
42493
42813
  }
42494
42814
 
42495
42815
  //Zoom out the structure at certain ratio, e.g., 0.1 is a reasonable value.
42496
42816
  zoomOut(normalizedFactor) { let ic = this.icn3d, me = ic.icn3dui;
42497
- let para = {};
42817
+ let para = {}
42498
42818
  para._zoomFactor = 1 + normalizedFactor;
42499
42819
  para.update = true;
42500
42820
 
@@ -42504,8 +42824,11 @@ class Transform {
42504
42824
  else {
42505
42825
  ic.controls.update(para);
42506
42826
  }
42507
- if(ic.bRender) ic.drawCls.render();
42827
+ if(ic.bRender) {
42828
+ ic.drawCls.render();
42829
+ }
42508
42830
  }
42831
+ */
42509
42832
 
42510
42833
  //Center on the selected atoms and zoom in.
42511
42834
  zoominSelection(atoms) { let ic = this.icn3d, me = ic.icn3dui;
@@ -42708,20 +43031,29 @@ class SaveFile {
42708
43031
  }
42709
43032
  }
42710
43033
 
42711
- saveSvg(id, filename) { let ic = this.icn3d; ic.icn3dui;
42712
- let svg = this.getSvgXml(id);
43034
+ saveSvg(id, filename, bContactmap) { let ic = this.icn3d, me = ic.icn3dui;
43035
+ if(me.bNode) return '';
43036
+
43037
+ let width = $("#" + id).width();
43038
+ let height = $("#" + id).height();
43039
+
43040
+ if(bContactmap) height = width;
42713
43041
 
42714
- let blob = new Blob([svg], {type: "image/svg+xml"});
43042
+ let svgXml = this.getSvgXml(id, width, height, bContactmap);
43043
+
43044
+ let blob = new Blob([svgXml], {type: "image/svg+xml"});
42715
43045
  saveAs(blob, filename);
42716
43046
  }
42717
43047
 
42718
- getSvgXml(id) { let ic = this.icn3d, me = ic.icn3dui;
43048
+ getSvgXml(id, width, height, bContactmap) { let ic = this.icn3d, me = ic.icn3dui;
42719
43049
  if(me.bNode) return '';
42720
43050
 
42721
43051
  // font is not good
42722
43052
  let svg_data = document.getElementById(id).innerHTML; //put id of your svg element here
42723
43053
 
42724
- let head = "<svg title=\"graph\" version=\"1.1\" xmlns:xl=\"http://www.w3.org/1999/xlink\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">";
43054
+ let viewbox = (width && height) ? "<svg viewBox=\"0 0 " + width + " " + height + "\"" : "<svg";
43055
+ //let head = viewbox + " title=\"graph\" version=\"1.1\" xmlns:xl=\"http://www.w3.org/1999/xlink\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">";
43056
+ let head = viewbox + " title=\"graph\" xmlns:xl=\"http://www.w3.org/1999/xlink\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">";
42725
43057
 
42726
43058
  //if you have some additional styling like graph edges put them inside <style> tag
42727
43059
  let style = "<style>text {font-family: sans-serif; font-weight: bold; font-size: 18px;}</style>";
@@ -42731,9 +43063,14 @@ class SaveFile {
42731
43063
  return full_svg;
42732
43064
  }
42733
43065
 
42734
- savePng(id, filename, width, height) { let ic = this.icn3d, me = ic.icn3dui;
43066
+ savePng(id, filename, bContactmap) { let ic = this.icn3d, me = ic.icn3dui;
42735
43067
  if(me.bNode) return '';
42736
43068
 
43069
+ let width = $("#" + id).width();
43070
+ let height = $("#" + id).height();
43071
+
43072
+ if(bContactmap) height = width;
43073
+
42737
43074
  // https://stackoverflow.com/questions/3975499/convert-svg-to-image-jpeg-png-etc-in-the-browser
42738
43075
  let svg = document.getElementById(id);
42739
43076
  let bbox = svg.getBBox();
@@ -42747,7 +43084,7 @@ class SaveFile {
42747
43084
  let ctx = canvas.getContext("2d");
42748
43085
  ctx.clearRect(0, 0, bbox.width, bbox.height);
42749
43086
 
42750
- let data = this.getSvgXml(id); //(new XMLSerializer()).serializeToString(copy); //ic.saveFileCls.getSvgXml();
43087
+ let data = this.getSvgXml(id, width, height, bContactmap); //(new XMLSerializer()).serializeToString(copy); //ic.saveFileCls.getSvgXml();
42751
43088
  let DOMURL = window.URL || window.webkitURL || window;
42752
43089
  let svgBlob = new Blob([data], {type: "image/svg+xml;charset=utf-8"});
42753
43090
 
@@ -43266,7 +43603,7 @@ class SaveFile {
43266
43603
  if(ic.molTitle !== undefined && ic.molTitle !== '') {
43267
43604
  let title = ic.molTitle;
43268
43605
 
43269
- let titlelinkColor =(ic.opts['background'] == 'white' || ic.opts['background'] == 'grey') ? 'black' : me.htmlCls.GREYD;
43606
+ let titlelinkColor =(ic.opts['background'] == 'black') ? me.htmlCls.GREYD : 'black';
43270
43607
 
43271
43608
  if(ic.inputid === undefined) {
43272
43609
  if(ic.molTitle.length > 40) title = ic.molTitle.substr(0, 40) + "...";
@@ -43459,6 +43796,10 @@ class ClickMenu {
43459
43796
  me.myEventCls.onIds("#" + me.pre + "mn1_xyzfile", "click", function(e) { me.icn3d;
43460
43797
  me.htmlCls.dialogCls.openDlg('dl_xyzfile', 'Please input XYZ File');
43461
43798
  });
43799
+
43800
+ me.myEventCls.onIds("#" + me.pre + "mn1_afmapfile", "click", function(e) { me.icn3d;
43801
+ me.htmlCls.dialogCls.openDlg('dl_afmapfile', 'Please input AlphaFold aligned error File');
43802
+ });
43462
43803
  // },
43463
43804
  // clkMn1_urlfile: function() {
43464
43805
  me.myEventCls.onIds("#" + me.pre + "mn1_urlfile", "click", function(e) { me.icn3d;
@@ -44869,6 +45210,10 @@ class ClickMenu {
44869
45210
  me.myEventCls.onIds("#" + me.pre + "mn6_addlabelSelection", "click", function(e) { me.icn3d;
44870
45211
  me.htmlCls.dialogCls.openDlg('dl_addlabelselection', 'Add custom labels by the selected');
44871
45212
  });
45213
+
45214
+ me.myEventCls.onIds("#" + me.pre + "mn6_labelColor", "click", function(e) { me.icn3d;
45215
+ me.htmlCls.dialogCls.openDlg('dl_labelColor', 'Change color for all labels');
45216
+ });
44872
45217
  // },
44873
45218
  // clkMn2_saveselection: function() {
44874
45219
  me.myEventCls.onIds("#" + me.pre + "mn2_saveselection", "click", function(e) { me.icn3d;
@@ -44877,7 +45222,8 @@ class ClickMenu {
44877
45222
  // },
44878
45223
  // clkMn6_addlabelNo: function() {
44879
45224
  me.myEventCls.onIds(["#" + me.pre + "mn6_addlabelNo", "#" + me.pre + "removeLabels"], "click", function(e) { let ic = me.icn3d;
44880
- ic.pickpair = false;
45225
+ ic.labelcolor = undefined;
45226
+ ic.pickpair = false;
44881
45227
  //ic.labels['residue'] = [];
44882
45228
  //ic.labels['custom'] = [];
44883
45229
  let select = "set labels off";
@@ -45430,6 +45776,8 @@ class SetMenu {
45430
45776
  setTopMenusHtml(id, str1, str2) { let me = this.icn3dui;
45431
45777
  if(me.bNode) return '';
45432
45778
 
45779
+ let titleColor =(me.htmlCls.opts['background'] == 'black') ? me.htmlCls.GREYD : 'black';
45780
+
45433
45781
  let html = "";
45434
45782
 
45435
45783
  html += "<div style='position:relative;'>";
@@ -45473,7 +45821,7 @@ class SetMenu {
45473
45821
  html += this.setTools();
45474
45822
 
45475
45823
  // show title at the top left corner
45476
- html += me.htmlCls.divStr + "title' class='icn3d-commandTitle' style='font-size:1.2em; font-weight:normal; position:absolute; z-index:1; float:left; display:table-row; margin: 85px 0px 0px 5px; color:" + me.htmlCls.GREYD + "; width:" + me.htmlCls.WIDTH + "px'></div>";
45824
+ html += me.htmlCls.divStr + "title' class='icn3d-commandTitle' style='font-size:1.2em; font-weight:normal; position:absolute; z-index:1; float:left; display:table-row; margin: 85px 0px 0px 5px; color:" + titleColor + "; width:" + me.htmlCls.WIDTH + "px'></div>";
45477
45825
 
45478
45826
  html += me.htmlCls.divStr + "viewer' style='position:relative; width:100%; height:100%; background-color: " + me.htmlCls.GREYD + ";'>";
45479
45827
 
@@ -45490,7 +45838,7 @@ class SetMenu {
45490
45838
  let tmpStr = 'top:180px; font-size: 1.8em;';
45491
45839
  html += me.htmlCls.divStr + "wait' style='position:absolute; left:50px; " + tmpStr + " color: #444444;'>Loading data...</div>";
45492
45840
  }
45493
- html += "<canvas id='" + me.pre + "canvas' style='width:100%; height: 100%; background-color: #000;'>Your browser does not support WebGL.</canvas>";
45841
+ html += "<canvas id='" + me.pre + "canvas' style='width:100%; height: 100%; background-color: #FFF;'>Your browser does not support WebGL.</canvas>";
45494
45842
 
45495
45843
  // separate for the log box
45496
45844
  if(me.cfg.showcommand === undefined || me.cfg.showcommand) {
@@ -45526,6 +45874,8 @@ class SetMenu {
45526
45874
  setTopMenusHtmlMobile(id, str1, str2) { let me = this.icn3dui;
45527
45875
  if(me.bNode) return '';
45528
45876
 
45877
+ let titleColor =(me.htmlCls.opts['background'] == 'black') ? me.htmlCls.GREYD : 'black';
45878
+
45529
45879
  let html = "";
45530
45880
 
45531
45881
  html += "<div style='position:relative;'>";
@@ -45595,8 +45945,6 @@ class SetMenu {
45595
45945
  //html += me.htmlCls.setMenuCls.setTools();
45596
45946
 
45597
45947
  // show title at the top left corner
45598
- let titleColor =(me.htmlCls.opts['background'] == 'white' || me.htmlCls.opts['background'] == 'grey') ? 'black' : me.htmlCls.GREYD;
45599
-
45600
45948
  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>";
45601
45949
  html += me.htmlCls.divStr + "viewer' style='position:relative; width:100%; height:100%; background-color: " + me.htmlCls.GREYD + ";'>";
45602
45950
  html += me.htmlCls.divStr + "mnLogSection'>";
@@ -45608,7 +45956,7 @@ class SetMenu {
45608
45956
  let tmpStr = 'top:180px; font-size: 1.8em;';
45609
45957
  html += me.htmlCls.divStr + "wait' style='position:absolute; left:50px; " + tmpStr + " color: #444444;'>Loading data...</div>";
45610
45958
  }
45611
- html += "<canvas id='" + me.pre + "canvas' style='width:100%; height: 100%; background-color: #000;'>Your browser does not support WebGL.</canvas>";
45959
+ html += "<canvas id='" + me.pre + "canvas' style='width:100%; height: 100%; background-color: #FFF;'>Your browser does not support WebGL.</canvas>";
45612
45960
 
45613
45961
  // separate for the log box
45614
45962
  if(me.cfg.showcommand === undefined || me.cfg.showcommand) {
@@ -45800,6 +46148,7 @@ class SetMenu {
45800
46148
  let html = "";
45801
46149
 
45802
46150
  html += "<ul class='icn3d-mn-item'>";
46151
+ html += "<li><a href='https://www.ncbi.nlm.nih.gov/structure' target='_blank'>Search Structure " + me.htmlCls.wifiStr + "</a></li>";
45803
46152
  html += "<li><span>Retrieve by ID</span>";
45804
46153
  html += "<ul>";
45805
46154
  html += me.htmlCls.setHtmlCls.getLink('mn1_mmdbid', 'MMDB ID ' + me.htmlCls.wifiStr);
@@ -45824,6 +46173,7 @@ class SetMenu {
45824
46173
  html += me.htmlCls.setHtmlCls.getLink('mn1_mol2file', 'Mol2 File');
45825
46174
  html += me.htmlCls.setHtmlCls.getLink('mn1_sdffile', 'SDF File');
45826
46175
  html += me.htmlCls.setHtmlCls.getLink('mn1_xyzfile', 'XYZ File');
46176
+ html += me.htmlCls.setHtmlCls.getLink('mn1_afmapfile', 'AlphaFold Aligned Error File');
45827
46177
  if(!me.cfg.simplemenu) html += me.htmlCls.setHtmlCls.getLink('mn1_urlfile', 'URL(Same Host) ' + me.htmlCls.wifiStr);
45828
46178
  html += "<li>-</li>";
45829
46179
  html += me.htmlCls.setHtmlCls.getLink('mn1_pngimage', 'iCn3D PNG Image');
@@ -46392,8 +46742,8 @@ class SetMenu {
46392
46742
 
46393
46743
  html += "<li><span>Background</span>";
46394
46744
  html += "<ul>";
46395
- html += me.htmlCls.setHtmlCls.getRadio('mn6_bkgd', 'mn6_bkgdTransparent', 'Transparent', true);
46396
- html += me.htmlCls.setHtmlCls.getRadio('mn6_bkgd', 'mn6_bkgdBlack', 'Black');
46745
+ html += me.htmlCls.setHtmlCls.getRadio('mn6_bkgd', 'mn6_bkgdTransparent', 'Transparent');
46746
+ html += me.htmlCls.setHtmlCls.getRadio('mn6_bkgd', 'mn6_bkgdBlack', 'Black', true);
46397
46747
  html += me.htmlCls.setHtmlCls.getRadio('mn6_bkgd', 'mn6_bkgdGrey', 'Gray');
46398
46748
  html += me.htmlCls.setHtmlCls.getRadio('mn6_bkgd', 'mn6_bkgdWhite', 'White');
46399
46749
  html += "</ul>";
@@ -46874,6 +47224,8 @@ class SetMenu {
46874
47224
  html += me.htmlCls.setHtmlCls.getRadio('mn6_addlabel', 'mn6_addlabelTermini', 'N- & C-Termini');
46875
47225
  }
46876
47226
 
47227
+ html += "<li>-</li>";
47228
+ html += me.htmlCls.setHtmlCls.getRadio('mn6_addlabel', 'mn6_labelColor', 'Change Label Color', true);
46877
47229
  html += me.htmlCls.setHtmlCls.getRadio('mn6_addlabel', 'mn6_addlabelNo', 'Remove', true);
46878
47230
  html += "</ul>";
46879
47231
  html += "</li>";
@@ -46929,12 +47281,13 @@ class SetMenu {
46929
47281
  }
46930
47282
 
46931
47283
  let bOnePdb = me.cfg.mmtfid !== undefined || me.cfg.pdbid !== undefined || me.cfg.opmid !== undefined || me.cfg.mmcifid !== undefined || me.cfg.mmdbid !== undefined || me.cfg.gi !== undefined || me.cfg.blast_rep_id !== undefined;
47284
+
46932
47285
  if(bOnePdb) {
46933
47286
  html += "<li id='" + me.pre + "assemblyWrapper'><span>Assembly</span>";
46934
47287
  html += "<ul>";
46935
47288
 
46936
- html += me.htmlCls.setHtmlCls.getRadio('mn6_assembly', 'mn6_assemblyYes', 'Biological Assembly', true);
46937
- html += me.htmlCls.setHtmlCls.getRadio('mn6_assembly', 'mn6_assemblyNo', 'Asymmetric Unit');
47289
+ html += me.htmlCls.setHtmlCls.getRadio('mn6_assembly', 'mn6_assemblyYes', 'Biological Assembly');
47290
+ html += me.htmlCls.setHtmlCls.getRadio('mn6_assembly', 'mn6_assemblyNo', 'Asymmetric Unit', true);
46938
47291
 
46939
47292
  html += "</ul>";
46940
47293
  html += "</li>";
@@ -47178,6 +47531,7 @@ class Dialog {
47178
47531
  let bLineGraph = $('#' + me.pre + 'dl_linegraph').hasClass('ui-dialog-content'); // initialized
47179
47532
  let bScatterplot = $('#' + me.pre + 'dl_scatterplot').hasClass('ui-dialog-content'); // initialized
47180
47533
  let bContactmap = $('#' + me.pre + 'dl_contactmap').hasClass('ui-dialog-content'); // initialized
47534
+ let bAlignerrormap = $('#' + me.pre + 'dl_alignerrormap').hasClass('ui-dialog-content'); // initialized
47181
47535
  let bTable = $('#' + me.pre + 'dl_interactionsorted').hasClass('ui-dialog-content'); // initialized
47182
47536
  let bAlignmentInit = $('#' + me.pre + 'dl_alignment').hasClass('ui-dialog-content'); // initialized
47183
47537
  let bTwoddgmInit = $('#' + me.pre + 'dl_2ddgm').hasClass('ui-dialog-content'); // initialized
@@ -47193,6 +47547,7 @@ class Dialog {
47193
47547
  if(bLineGraph) status.bLineGraph2 = $('#' + me.pre + 'dl_linegraph').dialog( 'isOpen' );
47194
47548
  if(bScatterplot) status.bScatterplot2 = $('#' + me.pre + 'dl_scatterplot').dialog( 'isOpen' );
47195
47549
  if(bContactmap) status.bContactmap2 = $('#' + me.pre + 'dl_contactmap').dialog( 'isOpen' );
47550
+ if(bAlignerrormap) status.bAlignerror2 = $('#' + me.pre + 'dl_alignerrormap').dialog( 'isOpen' );
47196
47551
  if(bTable) status.bTable2 = $('#' + me.pre + 'dl_interactionsorted').dialog( 'isOpen' );
47197
47552
  if(bAlignmentInit) status.bAlignmentInit2 = $('#' + me.pre + 'dl_alignment').dialog( 'isOpen' );
47198
47553
  if(bTwoddgmInit) status.bTwoddgmInit2 = $('#' + me.pre + 'dl_2ddgm').dialog( 'isOpen' );
@@ -47237,13 +47592,14 @@ class Dialog {
47237
47592
  close: function(e) {
47238
47593
  let status = thisClass.getDialogStatus();
47239
47594
 
47240
- if((id === me.pre + 'dl_selectannotations' &&(!status.bAlignmentInit2) && !status.bGraph2 && !status.bTable2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bContactmap2)
47241
- ||(id === me.pre + 'dl_graph' &&(!status.bSelectannotationsInit2) &&(!status.bAlignmentInit2) && !status.bTable2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bContactmap2)
47242
- ||(id === me.pre + 'dl_alignment' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bTable2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bContactmap2)
47243
- ||(id === me.pre + 'dl_interactionsorted' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bAlignmentInit2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bContactmap2)
47244
- ||(id === me.pre + 'dl_linegraph' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bAlignmentInit2 && !status.bTable2 && !status.bScatterplot2 && !status.bContactmap2)
47245
- ||(id === me.pre + 'dl_scatterplot' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bAlignmentInit2 && !status.bTable2 && !status.bLineGraph2 && !status.bContactmap2)
47246
- ||(id === me.pre + 'dl_contactmap' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bAlignmentInit2 && !status.bTable2 && !status.bLineGraph2 && !status.bScatterplot2)
47595
+ if((id === me.pre + 'dl_selectannotations' &&(!status.bAlignmentInit2) && !status.bGraph2 && !status.bTable2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bContactmap2 && !status.bAlignerrormap2)
47596
+ ||(id === me.pre + 'dl_graph' &&(!status.bSelectannotationsInit2) &&(!status.bAlignmentInit2) && !status.bTable2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bContactmap2 && !status.bAlignerrormap2)
47597
+ ||(id === me.pre + 'dl_alignment' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bTable2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bContactmap2 && !status.bAlignerrormap2)
47598
+ ||(id === me.pre + 'dl_interactionsorted' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bAlignmentInit2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bContactmap2 && !status.bAlignerrormap2)
47599
+ ||(id === me.pre + 'dl_linegraph' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bAlignmentInit2 && !status.bTable2 && !status.bScatterplot2 && !status.bContactmap2 && !status.bAlignerrormap2)
47600
+ ||(id === me.pre + 'dl_scatterplot' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bAlignmentInit2 && !status.bTable2 && !status.bLineGraph2 && !status.bContactmap2 && !status.bAlignerrormap2)
47601
+ ||(id === me.pre + 'dl_contactmap' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bAlignmentInit2 && !status.bTable2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bAlignerrormap2)
47602
+ ||(id === me.pre + 'dl_alignerrormap' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bAlignmentInit2 && !status.bTable2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bContactmap2)
47247
47603
  ) {
47248
47604
  if(status.bTwoddgmInit2 || status.bTwodctnInit2 || status.bSetsInit2) {
47249
47605
  //ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH - twoddgmWidth, me.htmlCls.HEIGHT - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT, true);
@@ -47270,7 +47626,7 @@ class Dialog {
47270
47626
 
47271
47627
  d3.select("#" + me.svgid).attr("width", width).attr("height", height);
47272
47628
  }
47273
- else if(id == me.pre + 'dl_linegraph' || id == me.pre + 'dl_scatterplot' || id == me.pre + 'dl_contactmap') {
47629
+ else if(id == me.pre + 'dl_linegraph' || id == me.pre + 'dl_scatterplot' || id == me.pre + 'dl_contactmap' || id == me.pre + 'dl_alignerrormap') {
47274
47630
  //var bTwoddgmInit = $('#' + me.pre + 'dl_2ddgm').hasClass('ui-dialog-content'); // initialized
47275
47631
  //var bSetsInit = $('#' + me.pre + 'dl_definedsets').hasClass('ui-dialog-content'); // initialized
47276
47632
 
@@ -47293,6 +47649,10 @@ class Dialog {
47293
47649
  let width = ic.contactmapWidth * ratio;
47294
47650
  $("#" + me.contactmapid).attr("width", width);
47295
47651
  }
47652
+ else if(id == me.pre + 'dl_alignerrormap') {
47653
+ let width = ic.alignerrormapWidth * ratio;
47654
+ $("#" + me.alignerrormapid).attr("width", width);
47655
+ }
47296
47656
  }
47297
47657
  }
47298
47658
  });
@@ -47388,7 +47748,7 @@ class Dialog {
47388
47748
 
47389
47749
  let status = this.getDialogStatus();
47390
47750
 
47391
- if(id === me.pre + 'dl_selectannotations' || id === me.pre + 'dl_graph' || id === me.pre + 'dl_linegraph' || id === me.pre + 'dl_scatterplot' || id === me.pre + 'dl_contactmap' || id === me.pre + 'dl_interactionsorted' || id === me.pre + 'dl_alignment') {
47751
+ if(id === me.pre + 'dl_selectannotations' || id === me.pre + 'dl_graph' || id === me.pre + 'dl_linegraph' || id === me.pre + 'dl_scatterplot' || id === me.pre + 'dl_contactmap' || id === me.pre + 'dl_alignerrormap' || id === me.pre + 'dl_interactionsorted' || id === me.pre + 'dl_alignment') {
47392
47752
  //var dialogWidth = 0.5 *(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH) - twoddgmWidth * 0.5;
47393
47753
  let dialogWidth = 0.5 *(me.htmlCls.WIDTH) - twoddgmWidth * 0.5;
47394
47754
 
@@ -47424,13 +47784,14 @@ class Dialog {
47424
47784
  modal: false,
47425
47785
  position: position,
47426
47786
  close: function(e) {
47427
- if((id === me.pre + 'dl_selectannotations' &&(!status.bAlignmentInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2))
47428
- ||(id === me.pre + 'dl_graph' &&(!status.bSelectannotationsInit2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2))
47429
- ||(id === me.pre + 'dl_alignment' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2))
47430
- ||(id === me.pre + 'dl_interactionsorted' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2))
47431
- ||(id === me.pre + 'dl_linegraph' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bScatterplot2) &&(!status.bContactmap2))
47432
- ||(id === me.pre + 'dl_scatterplot' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bContactmap2))
47433
- ||(id === me.pre + 'dl_contactmap' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2))
47787
+ if((id === me.pre + 'dl_selectannotations' &&(!status.bAlignmentInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
47788
+ ||(id === me.pre + 'dl_graph' &&(!status.bSelectannotationsInit2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
47789
+ ||(id === me.pre + 'dl_alignment' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
47790
+ ||(id === me.pre + 'dl_interactionsorted' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
47791
+ ||(id === me.pre + 'dl_linegraph' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
47792
+ ||(id === me.pre + 'dl_scatterplot' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
47793
+ ||(id === me.pre + 'dl_contactmap' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bAlignerrormap2))
47794
+ ||(id === me.pre + 'dl_alignerrormap' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2))
47434
47795
  ) {
47435
47796
  if(status.bTwoddgmInit2 || status.bTwodctnInit2 || status.bSetsInit2) {
47436
47797
  let canvasWidth = me.utilsCls.isMobile() ? me.htmlCls.WIDTH : me.htmlCls.WIDTH - twoddgmWidth;
@@ -47456,7 +47817,7 @@ class Dialog {
47456
47817
 
47457
47818
  d3.select("#" + me.svgid).attr("width", width).attr("height", height);
47458
47819
  }
47459
- else if(id == me.pre + 'dl_linegraph' || id == me.pre + 'dl_scatterplot' || id == me.pre + 'dl_contactmap') {
47820
+ else if(id == me.pre + 'dl_linegraph' || id == me.pre + 'dl_scatterplot' || id == me.pre + 'dl_contactmap' || id == me.pre + 'dl_alignerrormap') {
47460
47821
  //var bTwoddgmInit = $('#' + me.pre + 'dl_2ddgm').hasClass('ui-dialog-content'); // initialized
47461
47822
  //var bSetsInit = $('#' + me.pre + 'dl_definedsets').hasClass('ui-dialog-content'); // initialized
47462
47823
 
@@ -47479,6 +47840,10 @@ class Dialog {
47479
47840
  let width = ic.contactmapWidth * ratio;
47480
47841
  $("#" + me.contactmapid).attr("width", width);
47481
47842
  }
47843
+ else if(id == me.pre + 'dl_alignerrormap') {
47844
+ let width = ic.alignerrormapWidth * ratio;
47845
+ $("#" + me.alignerrormapid).attr("width", width);
47846
+ }
47482
47847
  }
47483
47848
  }
47484
47849
  });
@@ -47601,7 +47966,7 @@ class Dialog {
47601
47966
  let width = 400, height = 150;
47602
47967
  let twoddgmWidth = me.htmlCls.width2d + 20;
47603
47968
 
47604
- if(id === me.pre + 'dl_selectannotations' || id === me.pre + 'dl_graph' || id === me.pre + 'dl_linegraph' || id === me.pre + 'dl_scatterplot' || id === me.pre + 'dl_contactmap' || id === me.pre + 'dl_interactionsorted' || id === me.pre + 'dl_alignment') {
47969
+ if(id === me.pre + 'dl_selectannotations' || id === me.pre + 'dl_graph' || id === me.pre + 'dl_linegraph' || id === me.pre + 'dl_scatterplot' || id === me.pre + 'dl_contactmap' || id === me.pre + 'dl_alignerrormap' || id === me.pre + 'dl_interactionsorted' || id === me.pre + 'dl_alignment') {
47605
47970
  $( "#" + id ).show();
47606
47971
 
47607
47972
  height =(me.htmlCls.HEIGHT) * 0.5;
@@ -47639,6 +48004,11 @@ class Dialog {
47639
48004
 
47640
48005
  $("#" + me.contactmapid).attr("width", width);
47641
48006
  }
48007
+ else if(id == me.pre + 'dl_alignerrormap') {
48008
+ let width = ic.alignerrormapWidth * ratio;
48009
+
48010
+ $("#" + me.alignerrormapid).attr("width", width);
48011
+ }
47642
48012
  });
47643
48013
  }
47644
48014
  else {
@@ -47772,8 +48142,11 @@ class SetDialog {
47772
48142
  html += "Note: AlphaFold produces a per-residue confidence score (pLDDT) between 0 and 100:<br>";
47773
48143
  html += me.htmlCls.clickMenuCls.setAlphaFoldLegend() + "<br>";
47774
48144
 
47775
- html += "<a href='https://alphafold.ebi.ac.uk/' target='_blank'>AlphaFold Uniprot</a> ID: " + me.htmlCls.inputTextStr + "id='" + me.pre + "afid' value='A0A061AD48' size=10> ";
47776
- html += me.htmlCls.buttonStr + "reload_af'>Load</button>";
48145
+ let afid = (me.cfg.afid) ? me.cfg.afid : 'Q76EI6';
48146
+
48147
+ html += "<a href='https://alphafold.ebi.ac.uk/' target='_blank'>AlphaFold Uniprot</a> ID: " + me.htmlCls.inputTextStr + "id='" + me.pre + "afid' value='" + afid + "' size=10><br><br>";
48148
+ html += me.htmlCls.buttonStr + "reload_af'>Load Structure</button>"
48149
+ + me.htmlCls.buttonStr + "reload_afmap' style='margin-left:30px'>Load Aligned Error Map (slow)</button>";
47777
48150
  html += "</div>";
47778
48151
 
47779
48152
  html += me.htmlCls.divStr + "dl_opmid' class='" + dialogClass + "'>";
@@ -47844,7 +48217,7 @@ class SetDialog {
47844
48217
  html += "<b>Optional 1</b>, full chains are used for structure alignment<br/><br/>";
47845
48218
  html += "<b>Optional 2</b>, sequence alignment (followed by structure alignemnt) based on residue numbers in the First/Master chain: <br>" + me.htmlCls.inputTextStr + "id='" + me.pre + "resalignids' placeholder='1,5,10-50' size=50><br/><br/>";
47846
48219
  html += "<b>Optional 3</b>, predefined alignment with residue numbers in each chain specified (one chain per line): <br><textarea id='" + me.pre + "predefinedres' rows='5' style='width: 100%; height: " +(me.htmlCls.LOG_HEIGHT) + "px; padding: 0px; border: 0px;' placeholder='1,5,10-50\n1,5,10-50\n1,5,10-50'></textarea><br/><br/>";
47847
- html += me.htmlCls.buttonStr + "reload_chainalign'>Align Biological Unit</button>" + me.htmlCls.buttonStr + "reload_chainalign_asym' style='margin-left:30px'>Align Asymmetric Unit</button><br/><br/>";
48220
+ html += me.htmlCls.buttonStr + "reload_chainalign_asym'>Align Asymmetric Unit</button>" + me.htmlCls.buttonStr + "reload_chainalign' style='margin-left:30px'>Align Biological Unit</button><br/><br/>";
47848
48221
  html += "(Note: To align chains in custom PDB files, you could concatenate PDB files in a single PDB file with the separation line \"ENDMDL\". Then load it in \"Open File > PDB File\" in the \"File\" menu and click \"View Sequences & Annotations\" in the \"Window\" menu. Finally select multiple chains in the sequence window and click \"Realign Selection\" in the \"File\" menu.)<br><br>";
47849
48222
  html += "</div></div>";
47850
48223
 
@@ -47869,6 +48242,12 @@ class SetDialog {
47869
48242
  html += "XYZ File: " + me.htmlCls.inputFileStr + "id='" + me.pre + "xyzfile' size=8> ";
47870
48243
  html += me.htmlCls.buttonStr + "reload_xyzfile'>Load</button>";
47871
48244
  html += "</div>";
48245
+
48246
+ html += me.htmlCls.divStr + "dl_afmapfile' class='" + dialogClass + "'>";
48247
+ html += "AlphaFold Aligned Error File: " + me.htmlCls.inputFileStr + "id='" + me.pre + "afmapfile' size=8> ";
48248
+ html += me.htmlCls.buttonStr + "reload_afmapfile'>Load</button>";
48249
+ html += "</div>";
48250
+
47872
48251
  html += me.htmlCls.divStr + "dl_urlfile' class='" + dialogClass + "'>";
47873
48252
  html += "File type: ";
47874
48253
  html += "<select id='" + me.pre + "filetype'>";
@@ -47892,9 +48271,16 @@ class SetDialog {
47892
48271
  html += me.htmlCls.buttonStr + "reload_mmcif'>Load</button>";
47893
48272
  html += "</div>";
47894
48273
 
47895
- html += me.htmlCls.divStr + "dl_mmdbid' class='" + dialogClass + "'>";
47896
- html += "MMDB or PDB ID: " + me.htmlCls.inputTextStr + "id='" + me.pre + "mmdbid' value='1TUP' size=8> ";
47897
- html += me.htmlCls.buttonStr + "reload_mmdb'>Load</button>";
48274
+ html += me.htmlCls.divStr + "dl_mmdbid' class='" + dialogClass + "' style='max-width:500px'>";
48275
+ html += "MMDB or PDB ID: " + me.htmlCls.inputTextStr + "id='" + me.pre + "mmdbid' value='1TUP' size=8> <br><br>";
48276
+ html += me.htmlCls.buttonStr + "reload_mmdb_asym'>Load Asymmetric Unit (All Chains)</button>" + me.htmlCls.buttonStr + "reload_mmdb' style='margin-left:30px'>Load Biological Unit</button><br/><br/><br>";
48277
+ html += '<b>Note</b>: The "<b>biological unit</b>" is the <b>biochemically active form of a biomolecule</b>, <div style="width:20px; margin:6px 0 0 20px; display:inline-block;"><span id="'
48278
+ + me.pre + 'asu_bu_expand" class="ui-icon ui-icon-plus icn3d-expand icn3d-link" style="width:15px;" title="Expand"></span><span id="'
48279
+ + me.pre + 'asu_bu_shrink" class="ui-icon ui-icon-minus icn3d-shrink icn3d-link" style="display:none; width:15px;" title="Shrink"></span></div>';
48280
+
48281
+ html += me.htmlCls.divStr + "asu_bu' style='display:none;'>";
48282
+ html += 'which can range from a monomer (single protein molecule) to an oligomer of 100+ protein molecules.<br><br>The "<b>asymmetric unit</b>" is the raw 3D structure data resolved by X-ray crystallography, NMR, or Cryo-electron microscopy. The asymmetric unit is equivalent to the biological unit in approximately 60% of structure records. In the remaining 40% of the records, the asymmetric unit represents a portion of the biological unit that can be reconstructed using crystallographic symmetry, or it represents multiple copies of the biological unit.</div>';
48283
+
47898
48284
  html += "</div>";
47899
48285
 
47900
48286
  html += me.htmlCls.divStr + "dl_blast_rep_id' style='max-width:500px;' class='" + dialogClass + "'>";
@@ -48230,6 +48616,33 @@ class SetDialog {
48230
48616
 
48231
48617
  html += "</div>";
48232
48618
 
48619
+ html += me.htmlCls.divStr + "dl_alignerrormap' style='background-color:white' class='" + dialogClass + "'>";
48620
+
48621
+ //html += me.htmlCls.divNowrapStr + "Hold Ctrl key to select multiple nodes." + me.htmlCls.space3 + "</div>";
48622
+
48623
+ me.alignerrormapid = me.pre + 'alignerrormap';
48624
+ html += me.htmlCls.divNowrapStr + buttonStrTmp + me.alignerrormapid + '_svg">SVG</button>' + me.htmlCls.space2;
48625
+ html += buttonStrTmp + me.alignerrormapid + '_png">PNG (slow)</button>' + me.htmlCls.space2;
48626
+ html += buttonStrTmp + me.alignerrormapid + '_json">JSON</button>' + me.htmlCls.space4;
48627
+ html += "<b>Scale</b>: <select id='" + me.alignerrormapid + "_scale'>";
48628
+
48629
+ //let optArray5 = ['0.01', '0.02', '0.04', '0.06', '0.08', '0.1', '0.2', '0.4', '0.6', '0.8', '1'];
48630
+ html += me.htmlCls.setHtmlCls.getOptionHtml(optArray5, 2);
48631
+
48632
+ html += "</select></div><br>";
48633
+
48634
+ //min: 004d00, max: FFFFFF
48635
+ let startColorStr = '#004d00';
48636
+ let endColorStr = '#FFFFFF';
48637
+ let rangeStr = startColorStr + ' 0%, ' + endColorStr + ' 100%';
48638
+
48639
+ html += "<div style='width:200px'><div style='height: 12px; border: 1px solid #000; background: linear-gradient(to right, " + rangeStr + ");'></div>";
48640
+ html += "<table width='100%' border='0' cellspacing='0' cellpadding='0'><tr><td width='15%'>0</td><td width='15%'>5</td><td width='15%'>10</td><td width='15%'>15</td><td width='15%'>20</td><td width='15%'>25</td><td>30</td></tr><tr><td colspan='7' align='center'>Expected position error (Angstroms)</td></tr></table></div><br>";
48641
+
48642
+ html += '<div id="' + me.pre + 'alignerrormapDiv"></div>';
48643
+
48644
+ html += "</div>";
48645
+
48233
48646
  html += me.htmlCls.divStr + "dl_elecmap2fofc' class='" + dialogClass + "'>";
48234
48647
  html += "<span style='white-space:nowrap;font-weight:bold;'>Contour at: <select id='" + me.pre + "sigma2fofc'>";
48235
48648
 
@@ -48286,22 +48699,27 @@ class SetDialog {
48286
48699
  html += "1. Text: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labeltext' value='Text' size=4><br/>";
48287
48700
  html += "2. Size: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labelsize' value='18' size=4 maxlength=2><br/>";
48288
48701
  html += "3. Color: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labelcolor' value='" + defaultColor + "' size=4><br/>";
48289
- html += "4. Background: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labelbkgd' value='' size=4><br/>";
48702
+ //html += "4. Background: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labelbkgd' value='' size=4><br/>";
48290
48703
  if(me.utilsCls.isMobile()) {
48291
- html += me.htmlCls.spanNowrapStr + "5. Touch TWO atoms</span><br/>";
48704
+ html += me.htmlCls.spanNowrapStr + "4. Touch TWO atoms</span><br/>";
48292
48705
  }
48293
48706
  else {
48294
- html += me.htmlCls.spanNowrapStr + "5. Pick TWO atoms while holding \"Alt\" key</span><br/>";
48707
+ html += me.htmlCls.spanNowrapStr + "4. Pick TWO atoms while holding \"Alt\" key</span><br/>";
48295
48708
  }
48296
- html += me.htmlCls.spanNowrapStr + "6. " + me.htmlCls.buttonStr + "applypick_labels'>Display</button></span>";
48709
+ html += me.htmlCls.spanNowrapStr + "5. " + me.htmlCls.buttonStr + "applypick_labels'>Display</button></span>";
48297
48710
  html += "</div>";
48298
48711
 
48299
48712
  html += me.htmlCls.divStr + "dl_addlabelselection' class='" + dialogClass + "'>";
48300
48713
  html += "1. Text: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labeltext2' value='Text' size=4><br/>";
48301
48714
  html += "2. Size: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labelsize2' value='18' size=4 maxlength=2><br/>";
48302
48715
  html += "3. Color: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labelcolor2' value='" + defaultColor + "' size=4><br/>";
48303
- html += "4. Background: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labelbkgd2' value='' size=4><br/>";
48304
- html += me.htmlCls.spanNowrapStr + "5. " + me.htmlCls.buttonStr + "applyselection_labels'>Display</button></span>";
48716
+ //html += "4. Background: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labelbkgd2' value='' size=4><br/>";
48717
+ html += me.htmlCls.spanNowrapStr + "4. " + me.htmlCls.buttonStr + "applyselection_labels'>Display</button></span>";
48718
+ html += "</div>";
48719
+
48720
+ html += me.htmlCls.divStr + "dl_labelColor' class='" + dialogClass + "'>";
48721
+ html += "Color for all labels: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labelcolorall' value='" + defaultColor + "' size=4><br/><br/>";
48722
+ html += me.htmlCls.spanNowrapStr + me.htmlCls.buttonStr + "applylabelcolor'>Display</button></span>";
48305
48723
  html += "</div>";
48306
48724
 
48307
48725
  html += me.htmlCls.divStr + "dl_distance' class='" + dialogClass + "'>";
@@ -48959,6 +49377,16 @@ class Events {
48959
49377
  window.open(hostUrl + '?afid=' + $("#" + me.pre + "afid").val(), '_blank');
48960
49378
  });
48961
49379
 
49380
+ me.myEventCls.onIds("#" + me.pre + "reload_afmap", "click", function(e) { let ic = me.icn3d;
49381
+ e.preventDefault();
49382
+ if(!me.cfg.notebook) dialog.dialog( "close" );
49383
+ let afid = me.cfg.afid ? me.cfg.afid : $("#" + me.pre + "afid").val();
49384
+
49385
+ me.htmlCls.clickMenuCls.setLogCmd("set af align error map " + afid, true);
49386
+
49387
+ ic.contactMapCls.afErrorMap(afid);
49388
+ });
49389
+
48962
49390
  me.myEventCls.onIds("#" + me.pre + "afid", "keyup", function(e) { me.icn3d;
48963
49391
  if (e.keyCode === 13) {
48964
49392
  e.preventDefault();
@@ -49042,8 +49470,8 @@ class Events {
49042
49470
  }
49043
49471
 
49044
49472
  me.htmlCls.clickMenuCls.setLogCmd("load chains " + alignment + " on asymmetric unit | residues " + resalign + " | resdef " + predefinedres, false);
49045
- //window.open(me.htmlCls.baseUrl + 'icn3d/full.html?chainalign=' + alignment + '&resnum=' + resalign + '&resdef=' + predefinedres + '&showalignseq=1&buidx=0', '_blank');
49046
- window.open(hostUrl + '?chainalign=' + alignment + '&resnum=' + resalign + '&resdef=' + predefinedres + '&showalignseq=1&buidx=0', '_blank');
49473
+ //window.open(me.htmlCls.baseUrl + 'icn3d/full.html?chainalign=' + alignment + '&resnum=' + resalign + '&resdef=' + predefinedres + '&showalignseq=1&bu=0', '_blank');
49474
+ window.open(hostUrl + '?chainalign=' + alignment + '&resnum=' + resalign + '&resdef=' + predefinedres + '&showalignseq=1&bu=0', '_blank');
49047
49475
  });
49048
49476
 
49049
49477
  me.myEventCls.onIds("#" + me.pre + "reload_mutation_3d", "click", function(e) { me.icn3d;
@@ -49118,21 +49546,25 @@ class Events {
49118
49546
  // clickReload_mmdb: function() {
49119
49547
  me.myEventCls.onIds("#" + me.pre + "reload_mmdb", "click", function(e) { me.icn3d;
49120
49548
  e.preventDefault();
49121
- if(!me.cfg.notebook) dialog.dialog( "close" );
49122
- me.htmlCls.clickMenuCls.setLogCmd("load mmdb " + $("#" + me.pre + "mmdbid").val(), false);
49123
- //ic.mmdbParserCls.downloadMmdb($("#" + me.pre + "mmdbid").val());
49124
- //window.open(me.htmlCls.baseUrl + 'icn3d/full.html?mmdbid=' + $("#" + me.pre + "mmdbid").val(), '_blank');
49125
- window.open(hostUrl + '?mmdbid=' + $("#" + me.pre + "mmdbid").val(), '_blank');
49549
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
49550
+ me.htmlCls.clickMenuCls.setLogCmd("load mmdb1 " + $("#" + me.pre + "mmdbid").val(), false);
49551
+ window.open(hostUrl + '?mmdbid=' + $("#" + me.pre + "mmdbid").val() + '&bu=1', '_blank');
49126
49552
  });
49127
49553
 
49554
+ me.myEventCls.onIds("#" + me.pre + "reload_mmdb_asym", "click", function(e) { me.icn3d;
49555
+ e.preventDefault();
49556
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
49557
+ me.htmlCls.clickMenuCls.setLogCmd("load mmdb0 " + $("#" + me.pre + "mmdbid").val(), false);
49558
+ window.open(hostUrl + '?mmdbid=' + $("#" + me.pre + "mmdbid").val() + '&bu=0', '_blank');
49559
+ });
49560
+
49128
49561
  me.myEventCls.onIds("#" + me.pre + "mmdbid", "keyup", function(e) { me.icn3d;
49129
49562
  if (e.keyCode === 13) {
49130
49563
  e.preventDefault();
49131
- if(!me.cfg.notebook) dialog.dialog( "close" );
49132
- me.htmlCls.clickMenuCls.setLogCmd("load mmdb " + $("#" + me.pre + "mmdbid").val(), false);
49133
- //window.open(me.htmlCls.baseUrl + 'icn3d/full.html?mmdbid=' + $("#" + me.pre + "mmdbid").val(), '_blank');
49134
- window.open(hostUrl + '?mmdbid=' + $("#" + me.pre + "mmdbid").val(), '_blank');
49135
- }
49564
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
49565
+ me.htmlCls.clickMenuCls.setLogCmd("load mmdb0 " + $("#" + me.pre + "mmdbid").val(), false);
49566
+ window.open(hostUrl + '?mmdbid=' + $("#" + me.pre + "mmdbid").val() + '&bu=0', '_blank');
49567
+ }
49136
49568
  });
49137
49569
 
49138
49570
  // },
@@ -49517,6 +49949,35 @@ class Events {
49517
49949
  reader.readAsText(file);
49518
49950
  }
49519
49951
  });
49952
+
49953
+ me.myEventCls.onIds("#" + me.pre + "reload_afmapfile", "click", function(e) { let ic = me.icn3d;
49954
+ e.preventDefault();
49955
+ ic.bInitial = true;
49956
+ if(!me.cfg.notebook) dialog.dialog( "close" );
49957
+ //close all dialog
49958
+ if(!me.cfg.notebook) {
49959
+ $(".ui-dialog-content").dialog("close");
49960
+ }
49961
+ else {
49962
+ ic.resizeCanvasCls.closeDialogs();
49963
+ }
49964
+ let file = $("#" + me.pre + "afmapfile")[0].files[0];
49965
+ if(!file) {
49966
+ var aaa = 1; //alert("Please select a file before clicking 'Load'");
49967
+ }
49968
+ else {
49969
+ me.htmlCls.setHtmlCls.fileSupport();
49970
+ let reader = new FileReader();
49971
+ reader.onload = function(e) {
49972
+ let dataStr = e.target.result; // or = reader.result;
49973
+ me.htmlCls.clickMenuCls.setLogCmd('load AlphaFold aligned error file ' + $("#" + me.pre + "afmapfile").val(), false);
49974
+
49975
+ me.htmlCls.dialogCls.openDlg('dl_alignerrormap', 'Show predicted aligned error map');
49976
+ ic.contactMapCls.processAfErrorMap(JSON.parse(dataStr));
49977
+ };
49978
+ reader.readAsText(file);
49979
+ }
49980
+ });
49520
49981
  // },
49521
49982
  // clickReload_urlfile: function() {
49522
49983
  me.myEventCls.onIds("#" + me.pre + "reload_urlfile", "click", function(e) { let ic = me.icn3d;
@@ -49769,9 +50230,7 @@ class Events {
49769
50230
  me.myEventCls.onIds("#" + me.svgid + "_png", "click", function(e) { let ic = me.icn3d;
49770
50231
  e.preventDefault();
49771
50232
  //if(!me.cfg.notebook) dialog.dialog( "close" );
49772
- let width = $("#" + me.pre + "dl_graph").width();
49773
- let height = $("#" + me.pre + "dl_graph").height();
49774
- ic.saveFileCls.savePng(me.svgid, ic.inputid + "_force_directed_graph.png", width, height);
50233
+ ic.saveFileCls.savePng(me.svgid, ic.inputid + "_force_directed_graph.png");
49775
50234
  });
49776
50235
  me.myEventCls.onIds("#" + me.svgid + "_json", "click", function(e) { let ic = me.icn3d;
49777
50236
  e.preventDefault();
@@ -49790,9 +50249,7 @@ class Events {
49790
50249
  $(document).on("click", "#" + me.svgid_ct + "_png", function(e) { let ic = me.icn3d;
49791
50250
  e.preventDefault();
49792
50251
  //if(!me.cfg.notebook) dialog.dialog( "close" );
49793
- let width = $("#" + me.pre + "dl_2dctn").width();
49794
- let height = $("#" + me.pre + "dl_2dctn").height();
49795
- ic.saveFileCls.savePng(me.svgid_ct, ic.inputid + "_cartoon.png", width, height);
50252
+ ic.saveFileCls.savePng(me.svgid_ct, ic.inputid + "_cartoon.png");
49796
50253
  });
49797
50254
  $(document).on("click", "#" + me.svgid_ct + "_json", function(e) { let ic = me.icn3d;
49798
50255
  e.preventDefault();
@@ -49818,9 +50275,7 @@ class Events {
49818
50275
  me.myEventCls.onIds("#" + me.linegraphid + "_png", "click", function(e) { let ic = me.icn3d;
49819
50276
  e.preventDefault();
49820
50277
  //if(!me.cfg.notebook) dialog.dialog( "close" );
49821
- let width = $("#" + me.pre + "dl_linegraph").width();
49822
- let height = $("#" + me.pre + "dl_linegraph").height();
49823
- ic.saveFileCls.savePng(me.linegraphid, ic.inputid + "_line_graph.png", width, height);
50278
+ ic.saveFileCls.savePng(me.linegraphid, ic.inputid + "_line_graph.png");
49824
50279
  });
49825
50280
  me.myEventCls.onIds("#" + me.linegraphid + "_json", "click", function(e) { let ic = me.icn3d;
49826
50281
  e.preventDefault();
@@ -49846,9 +50301,7 @@ class Events {
49846
50301
  me.myEventCls.onIds("#" + me.scatterplotid + "_png", "click", function(e) { let ic = me.icn3d;
49847
50302
  e.preventDefault();
49848
50303
  //if(!me.cfg.notebook) dialog.dialog( "close" );
49849
- let width = $("#" + me.pre + "dl_scatterplot").width();
49850
- let height = $("#" + me.pre + "dl_scatterplot").height();
49851
- ic.saveFileCls.savePng(me.scatterplotid, ic.inputid + "_scatterplot.png", width, height);
50304
+ ic.saveFileCls.savePng(me.scatterplotid, ic.inputid + "_scatterplot.png");
49852
50305
  });
49853
50306
  me.myEventCls.onIds("#" + me.scatterplotid + "_json", "click", function(e) { let ic = me.icn3d;
49854
50307
  e.preventDefault();
@@ -49870,14 +50323,12 @@ class Events {
49870
50323
  me.myEventCls.onIds("#" + me.contactmapid + "_svg", "click", function(e) { let ic = me.icn3d;
49871
50324
  e.preventDefault();
49872
50325
  //if(!me.cfg.notebook) dialog.dialog( "close" );
49873
- ic.saveFileCls.saveSvg(me.contactmapid, ic.inputid + "_contactmap.svg");
50326
+ ic.saveFileCls.saveSvg(me.contactmapid, ic.inputid + "_contactmap.svg", true);
49874
50327
  });
49875
50328
  me.myEventCls.onIds("#" + me.contactmapid + "_png", "click", function(e) { let ic = me.icn3d;
49876
50329
  e.preventDefault();
49877
50330
  //if(!me.cfg.notebook) dialog.dialog( "close" );
49878
- let width = $("#" + me.pre + "dl_contactmap").width();
49879
- let height = $("#" + me.pre + "dl_contactmap").height();
49880
- ic.saveFileCls.savePng(me.contactmapid, ic.inputid + "_contactmap.png", width, height);
50331
+ ic.saveFileCls.savePng(me.contactmapid, ic.inputid + "_contactmap.png", true);
49881
50332
  });
49882
50333
  me.myEventCls.onIds("#" + me.contactmapid + "_json", "click", function(e) { let ic = me.icn3d;
49883
50334
  e.preventDefault();
@@ -49889,11 +50340,39 @@ class Events {
49889
50340
  ic.saveFileCls.saveFile(ic.inputid + "_contactmap.json", "text", [graphStr2]);
49890
50341
  });
49891
50342
  me.myEventCls.onIds("#" + me.contactmapid + "_scale", "change", function(e) { let ic = me.icn3d;
50343
+ e.preventDefault();
50344
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
50345
+ let scale = $("#" + me.contactmapid + "_scale").val();
50346
+ $("#" + me.contactmapid).attr("width",(ic.contactmapWidth * parseFloat(scale)).toString() + "px");
50347
+ me.htmlCls.clickMenuCls.setLogCmd("contactmap scale " + scale, true);
50348
+ });
50349
+
50350
+ me.myEventCls.onIds("#" + me.alignerrormapid + "_svg", "click", function(e) { let ic = me.icn3d;
50351
+ e.preventDefault();
50352
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
50353
+ ic.saveFileCls.saveSvg(me.alignerrormapid, ic.inputid + "_alignerrormap.svg", true);
50354
+ });
50355
+ me.myEventCls.onIds("#" + me.alignerrormapid + "_png", "click", function(e) { let ic = me.icn3d;
50356
+ e.preventDefault();
50357
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
50358
+ ic.saveFileCls.savePng(me.alignerrormapid, ic.inputid + "_alignerrormap.png", true);
50359
+ });
50360
+ me.myEventCls.onIds("#" + me.alignerrormapid + "_json", "click", function(e) { let ic = me.icn3d;
50361
+ e.preventDefault();
50362
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
50363
+ let graphStr2 = ic.alignerrormapStr.substr(0, ic.alignerrormapStr.lastIndexOf('}'));
50364
+
50365
+ graphStr2 += me.htmlCls.setHtmlCls.getLinkColor();
50366
+
50367
+ ic.saveFileCls.saveFile(ic.inputid + "_alignerrormap.json", "text", [graphStr2]);
50368
+ });
50369
+
50370
+ me.myEventCls.onIds("#" + me.alignerrormapid + "_scale", "change", function(e) { let ic = me.icn3d;
49892
50371
  e.preventDefault();
49893
50372
  //if(!me.cfg.notebook) dialog.dialog( "close" );
49894
- let scale = $("#" + me.contactmapid + "_scale").val();
49895
- $("#" + me.contactmapid).attr("width",(ic.contactmapWidth * parseFloat(scale)).toString() + "px");
49896
- me.htmlCls.clickMenuCls.setLogCmd("contactmap scale " + scale, true);
50373
+ let scale = $("#" + me.alignerrormapid + "_scale").val();
50374
+ $("#" + me.alignerrormapid).attr("width",(ic.alignerrormapWidth * parseFloat(scale)).toString() + "px");
50375
+ me.htmlCls.clickMenuCls.setLogCmd("alignerrormap scale " + scale, true);
49897
50376
  });
49898
50377
 
49899
50378
  me.myEventCls.onIds("#" + me.svgid + "_label", "change", function(e) { me.icn3d;
@@ -49993,6 +50472,15 @@ class Events {
49993
50472
  me.htmlCls.clickMenuCls.setLogCmd('add label ' + text + ' | x ' + x.toPrecision(4) + ' y ' + y.toPrecision(4) + ' z ' + z.toPrecision(4) + sizeStr + colorStr + backgroundStr + ' | type custom', true);
49994
50473
  ic.drawCls.draw();
49995
50474
  });
50475
+
50476
+ me.myEventCls.onIds("#" + me.pre + "applylabelcolor", "click", function(e) { let ic = me.icn3d;
50477
+ e.preventDefault();
50478
+ if(!me.cfg.notebook) dialog.dialog( "close" );
50479
+ ic.labelcolor = $("#" + me.pre + "labelcolorall" ).val();
50480
+
50481
+ me.htmlCls.clickMenuCls.setLogCmd('set label color ' + ic.labelcolor, true);
50482
+ ic.drawCls.draw();
50483
+ });
49996
50484
  // },
49997
50485
  // clickApplypick_stabilizer: function() {
49998
50486
  me.myEventCls.onIds("#" + me.pre + "applypick_stabilizer", "click", function(e) { let ic = me.icn3d;
@@ -51617,7 +52105,7 @@ class Html {
51617
52105
  this.cfg = this.icn3dui.cfg;
51618
52106
 
51619
52107
  this.opts = {};
51620
- this.opts['background'] = 'transparent'; //transparent, black, grey, white
52108
+ this.opts['background'] = 'black'; //transparent, black, grey, white
51621
52109
 
51622
52110
  this.WIDTH = 400; // total width of view area
51623
52111
  this.HEIGHT = 400; // total height of view area
@@ -52301,7 +52789,115 @@ class ContactMap {
52301
52789
  }
52302
52790
  }
52303
52791
 
52304
- drawContactMap(lineGraphStr) { let ic = this.icn3d, me = ic.icn3dui;
52792
+ afErrorMap(afid) { let ic = this.icn3d, me = ic.icn3dui;
52793
+ let thisClass = this;
52794
+
52795
+ me.htmlCls.dialogCls.openDlg('dl_alignerrormap', 'Show predicted aligned error map');
52796
+
52797
+ let url, dataType;
52798
+
52799
+ url = "https://alphafold.ebi.ac.uk/files/AF-" + afid + "-F1-predicted_aligned_error_v2.json";
52800
+
52801
+ dataType = "json";
52802
+
52803
+ $.ajax({
52804
+ url: url,
52805
+ dataType: dataType,
52806
+ cache: true,
52807
+ tryCount : 0,
52808
+ retryLimit : 1,
52809
+ success: function(data) {
52810
+ thisClass.processAfErrorMap(data);
52811
+ },
52812
+ error : function(xhr, textStatus, errorThrown ) {
52813
+ this.tryCount++;
52814
+ if(this.tryCount <= this.retryLimit) {
52815
+ //try again
52816
+ $.ajax(this);
52817
+ return;
52818
+ }
52819
+ var aaa = 1; //alert("There are some problems in loading the predicted aligned error file...");
52820
+ return;
52821
+ }
52822
+ });
52823
+ }
52824
+
52825
+ processAfErrorMap(dataJson) { let ic = this.icn3d, me = ic.icn3dui;
52826
+ // json format: [{"residue1": [1, ..., 1, ..., n, ..., n], "residue2": [1, 2, ..., n, ..., 1, 2, ..., n],
52827
+ // "distance": [n*n matrix],"max_predicted_aligned_error":31.75}]
52828
+ let distMatrix = dataJson[0].distance;
52829
+ let max = dataJson[0].max_predicted_aligned_error;
52830
+ if(!distMatrix || !max) {
52831
+ var aaa = 1; //alert("The predicted aligned error file didn't have the right format...");
52832
+ return;
52833
+ }
52834
+
52835
+ // generate lineGraphStr
52836
+ // e.g., {"nodes": [{"id":"A1.A","r":"1_1_1TOP_A_1","s":"ab","x":1,"y":21,"c":"FF00FF"}, ...],
52837
+ // "links": [{"source": "A1.A", "target": "S2.A", "v": 3, "c": "FF00FF"}, ...]}
52838
+ let nodeStr = '"nodes": [', linkStr = '"links": [';
52839
+ let bNode = false, bLink = false;
52840
+ let postA = '', postB = '.';
52841
+
52842
+ // initialize some parameters if no structure wasloaded yet
52843
+ if(!ic.chains) ic.init_base();
52844
+
52845
+ let chainidArray = Object.keys(ic.chains);
52846
+ let chainid = (chainidArray.length == 1) ? chainidArray[0] : 'stru_A';
52847
+
52848
+ let dim = parseInt(Math.sqrt(distMatrix.length));
52849
+
52850
+ //for(let chainid in ic.chains) {
52851
+ //for(let i = 0, il = ic.chainsSeq[chainid].length; i < il; ++i) {
52852
+ for(let i = 0; i < dim; ++i) {
52853
+ let resi = (ic.chainsSeq[chainid]) ? ic.chainsSeq[chainid][i].resi : i + 1;
52854
+ let resn = (ic.chainsSeq[chainid]) ? ic.chainsSeq[chainid][i].name : '*';
52855
+ let resid = chainid + '_' + resi;
52856
+ let atom = (ic.residues[resid]) ? ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid])
52857
+ : {color: me.parasCls.thr(0x888888)};
52858
+ let chain = chainid.substr(chainid.indexOf('_') + 1);
52859
+ let color = atom.color.getHexString();
52860
+
52861
+ if(bNode) nodeStr += ', ';
52862
+ let idStr = resn + resi + '.' + chain;
52863
+ nodeStr += '{"id":"' + idStr + postA + '","r":"1_1_' + resid + '","s":"a","c":"' + color + '"}\n';
52864
+ nodeStr += ', {"id":"' + idStr + postB + '","r":"1_1_' + resid + '","s":"b","c":"' + color + '"}';
52865
+ bNode = true;
52866
+
52867
+ //for(let j = 0, jl = ic.chainsSeq[chainid].length; j < jl; ++j) {
52868
+ //for(let j = 0; j < dim; ++j) {
52869
+ for(let j = i; j < dim; ++j) { // half map
52870
+ let resi2 = (ic.chainsSeq[chainid]) ? ic.chainsSeq[chainid][j].resi : j + 1;
52871
+ let resn2 = (ic.chainsSeq[chainid]) ? ic.chainsSeq[chainid][j].name : '*';
52872
+ let idStr2 = resn2 + resi2 + '.' + chain;
52873
+ let index = i * dim + j;
52874
+ // max dark green color 004d00, 0x4d = 77, 77/255 = 0.302
52875
+ // 0: 004d00, max: FFFFFF
52876
+ let ratio = (distMatrix[index]) ? distMatrix[index] / max : 0;
52877
+ let r = parseInt(ratio*255).toString(16);
52878
+ let g = parseInt(((1.0 - 0.302)*ratio + 0.302) * 255).toString(16);
52879
+ let rHex = (r.length == 1) ? '0' + r : r;
52880
+ let gHex = (g.length == 1) ? '0' + g : g;
52881
+ let bHex = rHex;
52882
+ let color2 = rHex + gHex + bHex;
52883
+
52884
+ if(bLink) linkStr += ', ';
52885
+ linkStr += '{"source": "' + idStr + postA + '", "target": "' + idStr2 + postB + '", "v": 11, "c": "' + color2 + '"}\n';
52886
+ bLink = true;
52887
+ }
52888
+ }
52889
+ //}
52890
+
52891
+ dataJson = {};
52892
+
52893
+ let lineGraphStr = '{' + nodeStr + '], ' + linkStr + ']}';
52894
+ let bAfMap = true;
52895
+ this.drawContactMap(lineGraphStr, bAfMap, max);
52896
+
52897
+ if(ic.deferredAfmap !== undefined) ic.deferredAfmap.resolve();
52898
+ }
52899
+
52900
+ drawContactMap(lineGraphStr, bAfMap, max) { let ic = this.icn3d, me = ic.icn3dui;
52305
52901
  let html, graph = JSON.parse(lineGraphStr);
52306
52902
  let linkArray = graph.links;
52307
52903
 
@@ -52335,7 +52931,7 @@ class ContactMap {
52335
52931
 
52336
52932
  let graphStr = '{\n';
52337
52933
 
52338
- let struc1 = Object.keys(ic.structures)[0];
52934
+ let struc1 = (ic.structures.length > 0) ? ic.structures[0] : 'stru';
52339
52935
  let len1 = nodeArray1.length,
52340
52936
  len2 = nodeArray2.length;
52341
52937
  let factor = 1;
@@ -52349,20 +52945,76 @@ class ContactMap {
52349
52945
  width =(len2 + 2) *(r + gap) + 2 * marginX + legendWidth;
52350
52946
 
52351
52947
  let id, graphWidth;
52352
- ic.contactmapWidth = 2 * width;
52353
- graphWidth = ic.contactmapWidth;
52354
- id = me.contactmapid;
52948
+ if(bAfMap) {
52949
+ ic.alignerrormapWidth = 2 * width;
52950
+ graphWidth = ic.alignerrormapWidth;
52951
+ id = me.alignerrormapid;
52952
+ }
52953
+ else {
52954
+ ic.contactmapWidth = 2 * width;
52955
+ graphWidth = ic.contactmapWidth;
52956
+ id = me.contactmapid;
52957
+ }
52958
+
52355
52959
  html =(linkArray.length > 0) ? "" : "No interactions found for these two sets<br><br>";
52356
- html += "<svg id='" + id + "' viewBox='0,0," + width + "," + heightAll + "' width='" + graphWidth + "px'>";
52960
+ html += "<svg xmlns='http://www.w3.org/2000/svg' id='" + id + "' viewBox='0,0," + width + "," + heightAll + "' width='" + graphWidth + "px'>";
52357
52961
  let bContactMap = true;
52358
- html += ic.lineGraphCls.drawScatterplot_base(nodeArray1, nodeArray2, linkArray, name2node, 0, bContactMap);
52962
+
52963
+ if(bAfMap) { // cleaned the code by using "use" in SVG, but didn't improve rendering
52964
+ let factor = 1;
52965
+ let r = 3 * factor;
52966
+ let rectSize = 2 * r;
52967
+
52968
+ ic.hex2id = {};
52969
+ let threshold = 29.0 / max;
52970
+ ic.hex2skip = {}; // do not display any error larger than 29 angstrom
52971
+
52972
+ html += "<defs>";
52973
+
52974
+ let linestrokewidth = 1;
52975
+ let nRef = 1000;
52976
+ for(let i = 0; i < nRef; ++i) {
52977
+ let ratio = 1.0 * i / nRef;
52978
+ let r = parseInt(ratio*255).toString(16);
52979
+ let g = parseInt(((1.0 - 0.302)*ratio + 0.302) * 255).toString(16);
52980
+ let rHex = (r.length == 1) ? '0' + r : r;
52981
+ let gHex = (g.length == 1) ? '0' + g : g;
52982
+ let bHex = rHex;
52983
+ let color = rHex + gHex + bHex;
52984
+ let strokecolor = "#" + color;
52985
+
52986
+ let idRect = me.pre + "afmap_" + i;
52987
+
52988
+ ic.hex2id[color] = idRect;
52989
+ if(ratio > threshold) {
52990
+ ic.hex2skip[color] = idRect;
52991
+ }
52992
+
52993
+ //html += "<g id='" + id + "'>";
52994
+ html += "<rect id='" + idRect + "' x='0' y='0' width='" + rectSize + "' height='" + rectSize + "' fill='"
52995
+ + strokecolor + "' stroke-width='" + linestrokewidth + "' stroke='" + strokecolor + "' />";
52996
+ //html += "</g>"
52997
+ }
52998
+ html += "</defs>";
52999
+ }
53000
+
53001
+ html += ic.lineGraphCls.drawScatterplot_base(nodeArray1, nodeArray2, linkArray, name2node, 0, bContactMap, undefined, undefined, bAfMap);
52359
53002
  graphStr += ic.getGraphCls.updateGraphJson(struc1, 1, nodeArray1, nodeArray2, linkArray);
52360
53003
  html += "</svg>";
52361
53004
 
52362
53005
  graphStr += '}\n';
52363
- ic.contactmapStr = graphStr;
53006
+ if(bAfMap) {
53007
+ ic.alignerrormapStr = graphStr;
53008
+ $("#" + ic.pre + "alignerrormapDiv").html(html);
53009
+
53010
+ let scale = $("#" + me.alignerrormapid + "_scale").val();
53011
+ $("#" + me.alignerrormapid).attr("width",(ic.alignerrormapWidth * parseFloat(scale)).toString() + "px");
53012
+ }
53013
+ else {
53014
+ ic.contactmapStr = graphStr;
53015
+ $("#" + ic.pre + "contactmapDiv").html(html);
53016
+ }
52364
53017
 
52365
- $("#" + ic.pre + "contactmapDiv").html(html);
52366
53018
  return html;
52367
53019
  }
52368
53020
  }
@@ -54390,6 +55042,7 @@ class iCn3D {
54390
55042
  this.bInstanced = true;
54391
55043
 
54392
55044
  this.chainMissingResidueArray = {};
55045
+ this._zoomFactor = 1.0;
54393
55046
 
54394
55047
  if(!this.icn3dui.bNode) {
54395
55048
  this.bExtFragDepth = this.renderer.extensions.get( "EXT_frag_depth" );
@@ -54518,7 +55171,7 @@ class iCn3D {
54518
55171
  //The default display options
54519
55172
  this.optsOri = {};
54520
55173
  this.optsOri['camera'] = 'perspective'; //perspective, orthographic
54521
- this.optsOri['background'] = 'transparent'; //transparent, black, grey, white
55174
+ this.optsOri['background'] = 'black'; //transparent, black, grey, white
54522
55175
  this.optsOri['color'] = 'chain'; //spectrum, secondary structure, charge, hydrophobic, conserved, chain, residue, atom, b factor, red, green, blue, magenta, yellow, cyan, white, grey, custom
54523
55176
  this.optsOri['proteins'] = 'ribbon'; //ribbon, strand, cylinder and plate, schematic, c alpha trace, backbone, b factor tube, lines, stick, ball and stick, sphere, nothing
54524
55177
  this.optsOri['sidec'] = 'nothing'; //lines, stick, ball and stick, sphere, nothing
@@ -54767,6 +55420,8 @@ iCn3D.prototype.init_base = function (bKeepCmd) {
54767
55420
  this.chainsAn = {}; // structure_chain name -> array of annotations, such as residue number
54768
55421
  this.chainsAnTitle = {}; // structure_chain name -> array of annotation title
54769
55422
 
55423
+ this.chainsMapping = {}; // structure_chain name -> residue id hash such as {'structure_chain_resi1': 'reference residue such as K10', ...}
55424
+
54770
55425
  this.alnChainsSeq = {}; // structure_chain name -> array of residue object: {mmdbid, chain, resi, resn, aligned}
54771
55426
  this.alnChainsAnno = {}; // structure_chain name -> array of annotations, such as residue number
54772
55427
  this.alnChainsAnTtl = {}; // structure_chain name -> array of annotation title
@@ -54916,7 +55571,7 @@ class iCn3DUI {
54916
55571
  //even when multiple iCn3D viewers are shown together.
54917
55572
  this.pre = this.cfg.divid + "_";
54918
55573
 
54919
- this.REVISION = '3.5.0';
55574
+ this.REVISION = '3.8.0';
54920
55575
 
54921
55576
  // In nodejs, iCn3D defines "window = {navigator: {}}"
54922
55577
  this.bNode = (Object.keys(window).length < 2) ? true : false;