icn3d 3.6.0 → 3.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/icn3d.js +1020 -297
  2. package/package.json +2 -2
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 ) {
@@ -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
 
@@ -7639,7 +7658,6 @@ class Strand {
7639
7658
  }
7640
7659
 
7641
7660
  currentChain = atom.chain;
7642
- atom.resi;
7643
7661
  ss = atom.ss;
7644
7662
  ssend = atom.ssend;
7645
7663
  prevAtomid = atom.serial;
@@ -12026,7 +12044,6 @@ class HlObjects {
12026
12044
 
12027
12045
  //Show the highlight for the selected atoms: hAtoms.
12028
12046
  addHlObjects(color, bRender, atomsHash) { let ic = this.icn3d, me = ic.icn3dui;
12029
- if(color === undefined) color = ic.hColor;
12030
12047
  //if(atomsHash === undefined) atomsHash = ic.hAtoms;
12031
12048
  let atomsHashDisplay = (atomsHash) ? me.hashUtilsCls.intHash(atomsHash, ic.dAtoms) : me.hashUtilsCls.intHash(ic.hAtoms, ic.dAtoms);
12032
12049
 
@@ -13337,13 +13354,14 @@ class DefinedSets {
13337
13354
  dAtoms = me.hashUtilsCls.unionHash(dAtoms, ic.alnChains[alignChain]);
13338
13355
  }
13339
13356
 
13340
- let residuesHash = {};
13357
+ let residuesHash = {}, chains = {};
13341
13358
  for(let i in dAtoms) {
13342
13359
  let atom = ic.atoms[i];
13343
13360
 
13344
13361
  let chainid = atom.structure + '_' + atom.chain;
13345
13362
  let resid = chainid + '_' + atom.resi;
13346
13363
  residuesHash[resid] = 1;
13364
+ chains[chainid] = 1;
13347
13365
  }
13348
13366
 
13349
13367
  let commandname = 'protein_aligned';
@@ -15149,24 +15167,7 @@ class Saltbridge {
15149
15167
  || (atom.het && me.parasCls.cationsTrimArray.indexOf(atom.elem) !== -1)
15150
15168
  || (atom.het && atom.elem === "N" && atom.bonds.length == 1);
15151
15169
 
15152
- // For ligand, "O" in carboxy group may be negatively charged. => to be improved
15153
- let bLigNeg = undefined;
15154
- if(atom.het && atom.elem === "O" && atom.bonds.length == 1) {
15155
- let cAtom = ic.atoms[atom.bonds[0]];
15156
- for(let j = 0; j < cAtom.bonds.length; ++j) {
15157
- let serial = cAtom.bonds[j];
15158
- if(ic.atoms[serial].elem == "O" && serial != atom.serial) {
15159
- bLigNeg = true;
15160
- break;
15161
- }
15162
- }
15163
- }
15164
-
15165
- let bAtomCondAnion = ( atom.resn === 'GLU' && (atom.name === "OE1" || atom.name === "OE2") )
15166
- || ( atom.resn === 'ASP' && (atom.name === "OD1" || atom.name === "OD2") )
15167
- || ( ic.nucleotides.hasOwnProperty(atom.serial) && (atom.name === "OP1" || atom.name === "OP2" || atom.name === "O1P" || atom.name === "O2P"))
15168
- || (atom.het && me.parasCls.anionsTrimArray.indexOf(atom.elem) !== -1)
15169
- || bLigNeg;
15170
+ let bAtomCondAnion = this.isAnion(atom);
15170
15171
 
15171
15172
  bAtomCondCation = (ic.bOpm) ? bAtomCondCation && atom.resn !== 'DUM' : bAtomCondCation;
15172
15173
  bAtomCondAnion = (ic.bOpm) ? bAtomCondAnion && atom.resn !== 'DUM' : bAtomCondAnion;
@@ -15197,10 +15198,7 @@ class Saltbridge {
15197
15198
  || ( atom.resn === 'ARG' && (atom.name === "NH1" || atom.name === "NH2"))
15198
15199
  || (atom.het && me.parasCls.cationsTrimArray.indexOf(atom.elem) !== -1);
15199
15200
 
15200
- let bAtomCondAnion = ( atom.resn === 'GLU' && (atom.name === "OE1" || atom.name === "OE2") )
15201
- || ( atom.resn === 'ASP' && (atom.name === "OD1" || atom.name === "OD2") )
15202
- || ( ic.nucleotides.hasOwnProperty(atom.serial) && (atom.name === "OP1" || atom.name === "OP2" || atom.name === "O1P" || atom.name === "O2P"))
15203
- || (atom.het && me.parasCls.anionsTrimArray.indexOf(atom.elem) !== -1);
15201
+ let bAtomCondAnion = this.isAnion(atom);
15204
15202
 
15205
15203
  bAtomCondCation = (ic.bOpm) ? bAtomCondCation && atom.resn !== 'DUM' : bAtomCondCation;
15206
15204
  bAtomCondAnion = (ic.bOpm) ? bAtomCondAnion && atom.resn !== 'DUM' : bAtomCondAnion;
@@ -15311,6 +15309,35 @@ class Saltbridge {
15311
15309
  return hbondsAtoms;
15312
15310
  }
15313
15311
 
15312
+ isAnion(atom) { let ic = this.icn3d, me = ic.icn3dui;
15313
+ // For ligand, "O" in carboxy group may be negatively charged. => to be improved
15314
+ let bLigNeg = undefined;
15315
+ if(atom.het && atom.elem === "O" && atom.bonds.length == 1) {
15316
+ let cAtom = ic.atoms[atom.bonds[0]];
15317
+ for(let j = 0; j < cAtom.bonds.length; ++j) {
15318
+ let serial = cAtom.bonds[j];
15319
+ if(ic.atoms[serial].elem == "O" && serial != atom.serial) {
15320
+ bLigNeg = true;
15321
+ break;
15322
+ }
15323
+ }
15324
+ }
15325
+
15326
+ // "O" in phosphae or sulfate group is neagatively charged
15327
+ if(atom.elem === "O" && atom.bonds.length == 1) {
15328
+ let pAtom = ic.atoms[atom.bonds[0]];
15329
+ if(pAtom.elem == "P" || pAtom.elem == "S") bLigNeg = true;
15330
+ }
15331
+
15332
+ let bAtomCondAnion = ( atom.resn === 'GLU' && (atom.name === "OE1" || atom.name === "OE2") )
15333
+ || ( atom.resn === 'ASP' && (atom.name === "OD1" || atom.name === "OD2") )
15334
+ || ( ic.nucleotides.hasOwnProperty(atom.serial) && (atom.name === "OP1" || atom.name === "OP2" || atom.name === "O1P" || atom.name === "O2P"))
15335
+ || (atom.het && me.parasCls.anionsTrimArray.indexOf(atom.elem) !== -1)
15336
+ || bLigNeg;
15337
+
15338
+ return bAtomCondAnion;
15339
+ }
15340
+
15314
15341
  hideSaltbridge() { let ic = this.icn3d; ic.icn3dui;
15315
15342
  ic.opts["saltbridge"] = "no";
15316
15343
  if(ic.lines === undefined) ic.lines = { };
@@ -15458,7 +15485,7 @@ class GetGraph {
15458
15485
  return resStr;
15459
15486
  }
15460
15487
 
15461
- drawResNode(node, i, r, gap, margin, y, setName, bVertical, bContactMap) { let ic = this.icn3d; ic.icn3dui;
15488
+ drawResNode(node, i, r, gap, margin, y, setName, bVertical, bContactMap, bAfMap) { let ic = this.icn3d; ic.icn3dui;
15462
15489
  let x, resid = node.r.substr(4);
15463
15490
  if(bVertical) {
15464
15491
  x = margin - i *(r + gap);
@@ -15484,7 +15511,7 @@ class GetGraph {
15484
15511
  let strokewidth = '1';
15485
15512
  let textcolor = '#000';
15486
15513
  let fontsize = '6px'; // '6';
15487
- let html = "<g class='icn3d-node' resid='" + resid + "' >";
15514
+ let html = (bAfMap) ? "<g>" : "<g class='icn3d-node' resid='" + resid + "' >";
15488
15515
  html += "<title>" + node.id + "</title>";
15489
15516
  if(bVertical) {
15490
15517
  html += "<circle cx='" + y + "' cy='" + x + "' r='" + r + "' fill='" + color + "' stroke-width='" + strokewidth + "' stroke='" + strokecolor + "' resid='" + resid + "' />";
@@ -15497,23 +15524,40 @@ class GetGraph {
15497
15524
  html += "</g>";
15498
15525
  return html;
15499
15526
  }
15500
- getNodeTopBottom(nameHash, name2node, bReverseNode) { let ic = this.icn3d; ic.icn3dui;
15527
+ getNodeTopBottom(nameHash, name2node, bReverseNode, bCommonDiff, nameHashCommon) { let ic = this.icn3d, me = ic.icn3dui;
15501
15528
  let thisClass = this;
15502
- let nodeArray1 = [], nodeArray2 = [];
15529
+ let nodeArray1 = [], nodeArray2 = [], name2nodeCommon = {};
15530
+
15531
+ let separatorCommon = "=>", separatorDiff = "==>", postCommon = "-", postDiff = "--";
15503
15532
  for(let name in nameHash) {
15504
15533
  let node = name2node[name];
15505
15534
  if(!node) continue;
15506
15535
 
15536
+ if(bCommonDiff == 1 || bCommonDiff == 2) {
15537
+ node = me.hashUtilsCls.cloneHash(node);
15538
+
15539
+ if(bCommonDiff == 1) {
15540
+ let mapping = (nameHashCommon[name]) ? nameHashCommon[name] : postCommon;
15541
+ node.id += separatorCommon + mapping;
15542
+ }
15543
+ else {
15544
+ let mapping = (nameHashCommon[name]) ? nameHashCommon[name] : postDiff;
15545
+ node.id += separatorDiff + mapping;
15546
+ }
15547
+
15548
+ name2nodeCommon[node.id] = node;
15549
+ }
15550
+
15507
15551
  if(node.s == 'a') {
15508
15552
  nodeArray1.push(node);
15509
15553
  }
15510
15554
  else if(node.s == 'b') {
15511
15555
  nodeArray2.push(node);
15512
15556
  }
15513
- else if(node.s == 'ab') {
15514
- nodeArray1.push(node);
15515
- nodeArray2.push(node);
15516
- }
15557
+ //else if(node.s == 'ab') {
15558
+ // nodeArray1.push(node);
15559
+ // nodeArray2.push(node);
15560
+ //}
15517
15561
  }
15518
15562
  // sort array
15519
15563
  nodeArray1.sort(function(a,b) {
@@ -15522,7 +15566,7 @@ class GetGraph {
15522
15566
  nodeArray2.sort(function(a,b) {
15523
15567
  return thisClass.compNode(a, b, bReverseNode);
15524
15568
  });
15525
- return {"nodeArray1": nodeArray1, "nodeArray2": nodeArray2}
15569
+ return {"nodeArray1": nodeArray1, "nodeArray2": nodeArray2, "name2node": name2nodeCommon};
15526
15570
  }
15527
15571
  updateGraphJson(struc, index, nodeArray1, nodeArray2, linkArray) { let ic = this.icn3d, me = ic.icn3dui;
15528
15572
  let lineGraphStr = '';
@@ -15845,22 +15889,37 @@ class LineGraph {
15845
15889
  let structureArray = ic.resid2specCls.atoms2structureArray(ic.hAtoms);
15846
15890
  //if(Object.keys(ic.structures).length > 1) {
15847
15891
  if(structureArray.length > 1) {
15848
- let nodeArray1a = [],
15849
- nodeArray1b = [],
15850
- nodeArray2a = [],
15851
- nodeArray2b = [],
15852
- nodeArray3a = [],
15853
- nodeArray3b = [];
15854
- //let struc1 = Object.keys(ic.structures)[0],
15855
- // struc2 = Object.keys(ic.structures)[1];
15856
- let struc1 = structureArray[0],
15857
- struc2 = structureArray[1];
15858
- let linkArrayA = [],
15859
- linkArrayB = [],
15860
- linkArrayAB = [];
15861
- let nameHashA = {},
15862
- nameHashB = {},
15863
- nameHashAB = {};
15892
+
15893
+ let struc2index= {};
15894
+ let nodeArray1Split = [], nodeArray2Split = [], linkArraySplit = [], nameHashSplit = [];
15895
+
15896
+ // show common interactions: nodes will be the same. The links/interactins are different.
15897
+ // The mapped residue name and number are attached to "id".
15898
+ // Original node: {id : "Q24.A.2AJF", r : "1_1_2AJF_A_24", s: "a", ...}
15899
+ // Node for common interaction: {id : "Q24.A.2AJF|Q24", r : "1_1_2AJF_A_24", s: "a", ...}
15900
+ let nodeArray1SplitCommon = [], nodeArray2SplitCommon = [], linkArraySplitCommon = [], nameHashSplitCommon = [];
15901
+ let nodeArray1SplitDiff = [], nodeArray2SplitDiff = [], linkArraySplitDiff = [], nameHashSplitDiff = [];
15902
+ let linkedNodeCnt = {};
15903
+
15904
+ for(let i = 0, il = structureArray.length; i < il; ++i) {
15905
+ nodeArray1Split[i] = [];
15906
+ nodeArray2Split[i] = [];
15907
+ linkArraySplit[i] = [];
15908
+ nameHashSplit[i] = {};
15909
+
15910
+ nodeArray1SplitCommon[i] = [];
15911
+ nodeArray2SplitCommon[i] = [];
15912
+ linkArraySplitCommon[i] = [];
15913
+ nameHashSplitCommon[i] = {};
15914
+
15915
+ nodeArray1SplitDiff[i] = [];
15916
+ nodeArray2SplitDiff[i] = [];
15917
+ linkArraySplitDiff[i] = [];
15918
+ nameHashSplitDiff[i] = {};
15919
+
15920
+ struc2index[structureArray[i]] = i;
15921
+ }
15922
+
15864
15923
  for(let i = 0, il = linkArray.length; i < il; ++i) {
15865
15924
  let link = linkArray[i];
15866
15925
  let nodeA = name2node[link.source];
@@ -15870,119 +15929,186 @@ class LineGraph {
15870
15929
  continue;
15871
15930
  }
15872
15931
 
15873
- //var idArrayA = nodeA.r.split('_'); // 1_1_1KQ2_A_1
15874
- let idArrayA = [];
15875
- idArrayA.push('');
15876
- idArrayA.push('');
15932
+ let idArrayA = this.getIdArrayFromNode(nodeA);
15933
+ let idArrayB = this.getIdArrayFromNode(nodeB);
15877
15934
 
15878
- let tmpStr = nodeA.r.substr(4);
15879
- idArrayA = idArrayA.concat(me.utilsCls.getIdArray(tmpStr));
15935
+ let index = struc2index[idArrayA[2]];
15880
15936
 
15881
- //var idArrayB = nodeB.r.split('_'); // 1_1_1KQ2_A_1
15882
- let idArrayB = [];
15883
- idArrayB.push('');
15884
- idArrayB.push('');
15937
+ if(idArrayA[2] == structureArray[index] && idArrayB[2] == structureArray[index]) {
15938
+ linkArraySplit[index].push(link);
15939
+ nameHashSplit[index][link.source] = 1;
15940
+ nameHashSplit[index][link.target] = 1;
15885
15941
 
15886
- tmpStr = nodeB.r.substr(4);
15887
- idArrayB = idArrayB.concat(me.utilsCls.getIdArray(tmpStr));
15942
+ let chainid1 = idArrayA[2] + '_' + idArrayA[3];
15943
+ let chainid2 = idArrayB[2] + '_' + idArrayB[3];
15944
+ let resid1 = chainid1 + '_' + idArrayA[4];
15945
+ let resid2 = chainid2 + '_' + idArrayB[4];
15888
15946
 
15889
- if(idArrayA[2] == struc1 && idArrayB[2] == struc1) {
15890
- linkArrayA.push(link);
15891
- nameHashA[link.source] = 1;
15892
- nameHashA[link.target] = 1;
15893
- } else if(idArrayA[2] == struc2 && idArrayB[2] == struc2) {
15894
- linkArrayB.push(link);
15895
- nameHashB[link.source] = 1;
15896
- nameHashB[link.target] = 1;
15897
- } else {
15898
- linkArrayAB.push(link);
15899
- nameHashAB[link.source] = 1;
15900
- nameHashAB[link.target] = 1;
15901
- }
15902
- }
15903
- let nodeArraysA = ic.getGraphCls.getNodeTopBottom(nameHashA, name2node);
15904
- nodeArray1a = nodeArraysA.nodeArray1;
15905
- nodeArray1b = nodeArraysA.nodeArray2;
15906
- let nodeArraysB = ic.getGraphCls.getNodeTopBottom(nameHashB, name2node);
15907
- nodeArray2a = nodeArraysB.nodeArray1;
15908
- nodeArray2b = nodeArraysB.nodeArray2;
15909
- let nodeArraysAB = ic.getGraphCls.getNodeTopBottom(nameHashAB, name2node, true);
15910
- nodeArray3a = nodeArraysAB.nodeArray1;
15911
- nodeArray3b = nodeArraysAB.nodeArray2;
15912
- let len1a = nodeArray1a.length,
15913
- len1b = nodeArray1b.length;
15914
- let len2a = nodeArray2a.length,
15915
- len2b = nodeArray2b.length;
15916
- let len3a = nodeArray3a.length,
15917
- len3b = nodeArray3b.length;
15918
- let maxLen = Math.max(len1a, len1b, len2a, len2b, len3a, len3b);
15947
+ let mapping1, mapping2;
15948
+
15949
+ if(ic.chainsMapping[chainid1] && ic.chainsMapping[chainid1][resid1]
15950
+ && ic.chainsMapping[chainid2] && ic.chainsMapping[chainid2][resid2]) {
15951
+ mapping1 = (nodeA.s == "a") ? ic.chainsMapping[chainid1][resid1] : ic.chainsMapping[chainid2][resid2];
15952
+ mapping2 = (nodeA.s == "a") ? ic.chainsMapping[chainid2][resid2] : ic.chainsMapping[chainid1][resid1];
15953
+
15954
+ let mappingid = mapping1 + '_' + mapping2 + '_' + link.c; // link.c determines the interaction type
15955
+ if(!linkedNodeCnt.hasOwnProperty(mappingid)) {
15956
+ linkedNodeCnt[mappingid] = 1;
15957
+ }
15958
+ else {
15959
+ ++linkedNodeCnt[mappingid];
15960
+ }
15961
+ }
15962
+ }
15963
+ }
15964
+
15965
+ // set linkArraySplitCommon and nameHashSplitCommon
15966
+ // set linkArraySplitDiff and nameHashSplitDiff
15967
+ let separatorCommon = "=>", separatorDiff = "==>", postCommon = "-", postDiff = "--";
15968
+ for(let i = 0, il = linkArray.length; i < il; ++i) {
15969
+ let link = linkArray[i];
15970
+ let nodeA = name2node[link.source];
15971
+ let nodeB = name2node[link.target];
15972
+
15973
+ if(!nodeA || !nodeB || !nodeA.r || !nodeB.r) {
15974
+ continue;
15975
+ }
15976
+
15977
+ let idArrayA = this.getIdArrayFromNode(nodeA);
15978
+ let idArrayB = this.getIdArrayFromNode(nodeB);
15979
+
15980
+ let index = struc2index[idArrayA[2]];
15981
+
15982
+ if(idArrayA[2] == structureArray[index] && idArrayB[2] == structureArray[index]) {
15983
+ let chainid1 = idArrayA[2] + '_' + idArrayA[3];
15984
+ let chainid2 = idArrayB[2] + '_' + idArrayB[3];
15985
+ let resid1 = chainid1 + '_' + idArrayA[4];
15986
+ let resid2 = chainid2 + '_' + idArrayB[4];
15987
+
15988
+ let mapping1, mapping2;
15989
+
15990
+ if(ic.chainsMapping[chainid1] && ic.chainsMapping[chainid1][resid1]
15991
+ && ic.chainsMapping[chainid2] && ic.chainsMapping[chainid2][resid2]) {
15992
+ mapping1 = (nodeA.s == "a") ? ic.chainsMapping[chainid1][resid1] : ic.chainsMapping[chainid2][resid2];
15993
+ mapping2 = (nodeA.s == "a") ? ic.chainsMapping[chainid2][resid2] : ic.chainsMapping[chainid1][resid1];
15994
+
15995
+ let mappingid = mapping1 + '_' + mapping2 + '_' + link.c; // link.c determines the interaction type
15996
+
15997
+ let linkCommon = me.hashUtilsCls.cloneHash(link);
15998
+ linkCommon.source += (ic.chainsMapping[chainid1][resid1]) ? separatorCommon + ic.chainsMapping[chainid1][resid1] : separatorCommon + postCommon;
15999
+ linkCommon.target += (ic.chainsMapping[chainid2][resid2]) ? separatorCommon + ic.chainsMapping[chainid2][resid2] : separatorCommon + postCommon;
16000
+
16001
+ let linkDiff = me.hashUtilsCls.cloneHash(link);
16002
+ linkDiff.source += (ic.chainsMapping[chainid1][resid1]) ? separatorDiff + ic.chainsMapping[chainid1][resid1] : separatorDiff + postDiff;
16003
+ linkDiff.target += (ic.chainsMapping[chainid2][resid2]) ? separatorDiff + ic.chainsMapping[chainid2][resid2] : separatorDiff + postDiff;
16004
+
16005
+ if(linkedNodeCnt[mappingid] == structureArray.length) {
16006
+ linkArraySplitCommon[index].push(linkCommon);
16007
+ }
16008
+ else {
16009
+ linkArraySplitDiff[index].push(linkDiff);
16010
+ }
16011
+
16012
+ // use the original node names and thus use the original link
16013
+ nameHashSplitCommon[index][link.source] = ic.chainsMapping[chainid1][resid1];
16014
+ nameHashSplitCommon[index][link.target] = ic.chainsMapping[chainid2][resid2];
16015
+
16016
+ nameHashSplitDiff[index][link.source] = ic.chainsMapping[chainid1][resid1];
16017
+ nameHashSplitDiff[index][link.target] = ic.chainsMapping[chainid2][resid2];
16018
+ }
16019
+ }
16020
+ }
16021
+
16022
+ let len1Split = [], len2Split = [], maxWidth = 0;
15919
16023
  let strucArray = [];
15920
- if(linkArrayA.length > 0) strucArray.push(struc1);
15921
- if(linkArrayB.length > 0) strucArray.push(struc2);
15922
- if(linkArrayAB.length > 0) strucArray.push(struc1 + '_' + struc2);
16024
+ let bCommonDiff = 1;
16025
+ for(let i = 0, il = structureArray.length; i < il; ++i) {
16026
+ let nodeArraysTmp = ic.getGraphCls.getNodeTopBottom(nameHashSplit[i], name2node);
16027
+ nodeArray1Split[i] = nodeArraysTmp.nodeArray1;
16028
+ nodeArray2Split[i] = nodeArraysTmp.nodeArray2;
16029
+
16030
+ // common interactions
16031
+ bCommonDiff = 1;
16032
+ nodeArraysTmp = ic.getGraphCls.getNodeTopBottom(nameHashSplit[i], name2node, undefined, bCommonDiff, nameHashSplitCommon[i]);
16033
+ nodeArray1SplitCommon[i] = nodeArraysTmp.nodeArray1;
16034
+ nodeArray2SplitCommon[i] = nodeArraysTmp.nodeArray2;
16035
+ name2node = me.hashUtilsCls.unionHash(name2node, nodeArraysTmp.name2node);
16036
+
16037
+ // different interactions
16038
+ bCommonDiff = 2;
16039
+ nodeArraysTmp = ic.getGraphCls.getNodeTopBottom(nameHashSplit[i], name2node, undefined, bCommonDiff, nameHashSplitDiff[i]);
16040
+ nodeArray1SplitDiff[i] = nodeArraysTmp.nodeArray1;
16041
+ nodeArray2SplitDiff[i] = nodeArraysTmp.nodeArray2;
16042
+ name2node = me.hashUtilsCls.unionHash(name2node, nodeArraysTmp.name2node);
16043
+
16044
+ len1Split[i] = nodeArray1Split[i].length;
16045
+ len2Split[i] = nodeArray2Split[i].length;
16046
+
16047
+ maxWidth = Math.max(maxWidth, len2Split[i]);
16048
+
16049
+ //if(linkArraySplit[i].length > 0) strucArray.push(structureArray[i]);
16050
+ strucArray.push(structureArray[i]);
16051
+ }
16052
+
15923
16053
  let factor = 1;
15924
16054
  let r = 3 * factor;
15925
16055
  let gap = 7 * factor;
15926
16056
  let height, width, heightAll;
15927
16057
  let marginX = 10,
15928
16058
  marginY = 10,
15929
- legendWidth = 30;
16059
+ legendWidth = 30,
16060
+ textHeight = 20;
16061
+
15930
16062
  if(bScatterplot) {
15931
- heightAll =(len1a + 2 + len2a + 2) *(r + gap) + 4 * marginY + 2 * legendWidth;
15932
- width =(Math.max(len1b, len2b) + 2) *(r + gap) + 2 * marginX + legendWidth;
16063
+ //heightAll =(len1a + 2 + len2a + 2) *(r + gap) + 4 * marginY + 2 * legendWidth;
16064
+ //width =(Math.max(len1b, len2b) + 2) *(r + gap) + 2 * marginX + legendWidth;
16065
+ heightAll =(me.utilsCls.sumArray(len1Split) + 2*strucArray.length) *(r + gap) + 4 * marginY
16066
+ + 2 * legendWidth + textHeight*strucArray.length;
16067
+ // show common and diff interaction as well
16068
+ heightAll *= 3;
16069
+
16070
+ width = (maxWidth + 2) * (r + gap) + 2 * marginX + legendWidth;
16071
+
15933
16072
  } else {
15934
- height = 110;
16073
+ height = 110 + textHeight;
15935
16074
  heightAll = height * strucArray.length;
15936
- width = maxLen *(r + gap) + 2 * marginX;
16075
+ // show common and diff interaction as well
16076
+ heightAll *= 3;
16077
+
16078
+ width = (maxWidth + 2) * (r + gap) + 2 * marginX;
15937
16079
  }
15938
- let id, graphWidth;
16080
+ let id;
15939
16081
  if(bScatterplot) {
15940
16082
  ic.scatterplotWidth = 2 * width;
15941
- graphWidth = ic.scatterplotWidth;
15942
16083
  id = me.scatterplotid;
15943
16084
  } else {
15944
16085
  ic.linegraphWidth = 2 * width;
15945
- graphWidth = ic.linegraphWidth;
15946
16086
  id = me.linegraphid;
15947
16087
  }
15948
16088
  html =(strucArray.length == 0) ? "No interactions found for each structure<br><br>" :
15949
- "2D integration graph for structure(s) <b>" + strucArray + "</b><br><br>";
15950
- html += "<svg id='" + id + "' viewBox='0,0," + width + "," + heightAll + "' width='" + graphWidth + "px'>";
15951
- let heightFinal = 0;
15952
- if(linkArrayA.length > 0) {
15953
- if(bScatterplot) {
15954
- heightFinal -= 15;
15955
- html += this.drawScatterplot_base(nodeArray1a, nodeArray1b, linkArrayA, name2node, heightFinal);
15956
- heightFinal = 15;
15957
- height =(len1a + 1) *(r + gap) + 2 * marginY;
15958
- } else {
15959
- html += this.drawLineGraph_base(nodeArray1a, nodeArray1b, linkArrayA, name2node, heightFinal);
15960
- }
15961
- heightFinal += height;
15962
- ic.lineGraphStr += ic.getGraphCls.updateGraphJson(struc1, 1, nodeArray1a, nodeArray1b, linkArrayA);
15963
- }
15964
- if(linkArrayB.length > 0) {
15965
- if(bScatterplot) {
15966
- html += this.drawScatterplot_base(nodeArray2a, nodeArray2b, linkArrayB, name2node, heightFinal);
15967
- height =(len2a + 1) *(r + gap) + 2 * marginY;
15968
- } else {
15969
- html += this.drawLineGraph_base(nodeArray2a, nodeArray2b, linkArrayB, name2node, heightFinal);
15970
- }
15971
- heightFinal += height;
15972
- if(linkArrayA.length > 0) ic.lineGraphStr += ', \n';
15973
- ic.lineGraphStr += ic.getGraphCls.updateGraphJson(struc2, 2, nodeArray2a, nodeArray2b, linkArrayB);
15974
- }
15975
- if(linkArrayAB.length > 0 && !bScatterplot) {
15976
- html += this.drawLineGraph_base(nodeArray3a, nodeArray3b, linkArrayAB, name2node, heightFinal);
15977
- if(linkArrayA.length > 0 || linkArrayB.length > 0) ic.lineGraphStr += ', \n';
15978
- ic.lineGraphStr += '"structure1_2": {"id1": "' + struc1 + '", "id2": "' + struc2 + '", "nodes1":[';
15979
- ic.lineGraphStr += me.utilsCls.getJSONFromArray(nodeArray3a);
15980
- ic.lineGraphStr += '], \n"nodes2":[';
15981
- ic.lineGraphStr += me.utilsCls.getJSONFromArray(nodeArray3b);
15982
- ic.lineGraphStr += '], \n"links":[';
15983
- ic.lineGraphStr += me.utilsCls.getJSONFromArray(linkArrayAB);
15984
- ic.lineGraphStr += ']}';
15985
- }
16089
+ "2D integration graph for " + strucArray.length + " structure(s) <b>" + strucArray + "</b>. There are three sections: \"Interactions\", \"Common interactions\", and \"Different interactions\". Each section has " + strucArray.length + " graphs.<br><br>";
16090
+ html += "<svg id='" + id + "' viewBox='0,0," + width + "," + heightAll + "'>";
16091
+
16092
+ let result, heightFinal = 0;
16093
+
16094
+ bCommonDiff = 0; // 0: all interactions, 1: common interactions, 2: different interactions
16095
+ result = this.drawGraphPerType(bCommonDiff, structureArray, bScatterplot, nodeArray1Split, nodeArray2Split, linkArraySplit, name2node, heightFinal, height, textHeight, len1Split, r, gap, marginY);
16096
+
16097
+ heightFinal = result.heightFinal;
16098
+ html += result.html;
16099
+
16100
+ bCommonDiff = 1;
16101
+ result = this.drawGraphPerType(bCommonDiff, structureArray, bScatterplot, nodeArray1SplitCommon, nodeArray2SplitCommon, linkArraySplitCommon, name2node, heightFinal, height, textHeight, len1Split, r, gap, marginY);
16102
+
16103
+ heightFinal = result.heightFinal;
16104
+ html += result.html;
16105
+
16106
+ bCommonDiff = 2;
16107
+ result = this.drawGraphPerType(bCommonDiff, structureArray, bScatterplot, nodeArray1SplitDiff, nodeArray2SplitDiff, linkArraySplitDiff, name2node, heightFinal, height, textHeight, len1Split, r, gap, marginY);
16108
+
16109
+ heightFinal = result.heightFinal;
16110
+ html += result.html;
16111
+
15986
16112
  html += "</svg>";
15987
16113
  } else {
15988
16114
  if(!bScatterplot) {
@@ -16040,7 +16166,57 @@ class LineGraph {
16040
16166
  return html;
16041
16167
  }
16042
16168
 
16043
- drawLineGraph_base(nodeArray1, nodeArray2, linkArray, name2node, height) { let ic = this.icn3d, me = ic.icn3dui;
16169
+ drawGraphPerType(bCommonDiff, structureArray, bScatterplot, nodeArray1, nodeArray2, linkArray, name2node, heightFinal, height, textHeight, len1Split, r, gap, marginY) { let ic = this.icn3d; ic.icn3dui;
16170
+ let html = "";
16171
+
16172
+ // draw common interaction
16173
+ let label, postfix;
16174
+ if(bCommonDiff == 0) {
16175
+ label = "Interactions in structure ";
16176
+ postfix = "";
16177
+ }
16178
+ else if(bCommonDiff == 1) {
16179
+ label = "Common interactions in structure ";
16180
+ postfix = "_common";
16181
+ }
16182
+ else if(bCommonDiff == 2) {
16183
+ label = "Different interactions in structure ";
16184
+ postfix = "_diff";
16185
+ }
16186
+
16187
+ for(let i = 0, il = structureArray.length; i < il; ++i) {
16188
+ if(bScatterplot) {
16189
+ html += this.drawScatterplot_base(nodeArray1[i], nodeArray2[i], linkArray[i], name2node, heightFinal, undefined, label + structureArray[i], textHeight);
16190
+ height =(len1Split[i] + 1) *(r + gap) + 2 * marginY + textHeight;
16191
+ } else {
16192
+ html += this.drawLineGraph_base(nodeArray1[i], nodeArray2[i], linkArray[i], name2node, heightFinal, label + structureArray[i], textHeight);
16193
+ }
16194
+ heightFinal += height;
16195
+
16196
+ if(bCommonDiff) { // very beginning
16197
+ if(i > 0) ic.lineGraphStr += ', \n';
16198
+ }
16199
+ else {
16200
+ ic.lineGraphStr += ', \n';
16201
+ }
16202
+ ic.lineGraphStr += ic.getGraphCls.updateGraphJson(structureArray[i], i + postfix, nodeArray1[i], nodeArray2[i], linkArray[i]);
16203
+ }
16204
+
16205
+ return {"heightFinal": heightFinal, "html": html};
16206
+ }
16207
+
16208
+ getIdArrayFromNode(node) { let ic = this.icn3d, me = ic.icn3dui;
16209
+ let idArray = []; // 1_1_1KQ2_A_1
16210
+ idArray.push('');
16211
+ idArray.push('');
16212
+
16213
+ let tmpStr = node.r.substr(4);
16214
+ idArray = idArray.concat(me.utilsCls.getIdArray(tmpStr));
16215
+
16216
+ return idArray;
16217
+ }
16218
+
16219
+ drawLineGraph_base(nodeArray1, nodeArray2, linkArray, name2node, height, label, textHeight) { let ic = this.icn3d, me = ic.icn3dui;
16044
16220
  let html = '';
16045
16221
  let len1 = nodeArray1.length,
16046
16222
  len2 = nodeArray2.length;
@@ -16057,6 +16233,13 @@ class LineGraph {
16057
16233
  margin2 = margin;
16058
16234
  margin1 = Math.abs(len1 - len2) *(r + gap) * 0.5 + margin;
16059
16235
  }
16236
+
16237
+ // draw label
16238
+ if(label) {
16239
+ height += textHeight;
16240
+ html += "<text x='" + margin1 + "' y='" + height + "' style='font-size:8px; font-weight:bold'>" + label + "</text>";
16241
+ }
16242
+
16060
16243
  let h1 = 30 + height,
16061
16244
  h2 = 80 + height;
16062
16245
  let nodeHtml = '';
@@ -16112,7 +16295,7 @@ class LineGraph {
16112
16295
  return html;
16113
16296
  }
16114
16297
 
16115
- drawScatterplot_base(nodeArray1, nodeArray2, linkArray, name2node, height, bContactMap) { let ic = this.icn3d; ic.icn3dui;
16298
+ drawScatterplot_base(nodeArray1, nodeArray2, linkArray, name2node, height, bContactMap, label, textHeight, bAfMap) { let ic = this.icn3d; ic.icn3dui;
16116
16299
  let html = '';
16117
16300
  let len1 = nodeArray1.length,
16118
16301
  len2 = nodeArray2.length;
@@ -16123,19 +16306,27 @@ class LineGraph {
16123
16306
  let marginX = 10,
16124
16307
  marginY = 20;
16125
16308
  let heightTotal =(len1 + 1) *(r + gap) + legendWidth + 2 * marginY;
16309
+
16310
+ // draw label
16311
+ if(label) {
16312
+ height += textHeight;
16313
+ html += "<text x='" + marginX + "' y='" + (height + 15).toString() + "' style='font-size:8px; font-weight:bold'>" + label + "</text>";
16314
+ }
16315
+
16126
16316
  let margin1 = height + heightTotal -(legendWidth + marginY +(r + gap)); // y-axis
16127
16317
  let margin2 = legendWidth + marginX +(r + gap); // x-axis
16128
- let x = legendWidth + marginX;
16318
+
16129
16319
  let nodeHtml = '';
16130
16320
  let node2posSet1 = {},
16131
16321
  node2posSet2 = {};
16322
+ let x = legendWidth + marginX;
16132
16323
  for(let i = 0; i < len1; ++i) {
16133
- nodeHtml += ic.getGraphCls.drawResNode(nodeArray1[i], i, r, gap, margin1, x, 'a', true);
16324
+ nodeHtml += ic.getGraphCls.drawResNode(nodeArray1[i], i, r, gap, margin1, x, 'a', true, undefined, bAfMap);
16134
16325
  node2posSet1[nodeArray1[i].id] = { x: x, y: margin1 - i *(r + gap) };
16135
16326
  }
16136
16327
  let y = height + heightTotal -(legendWidth + marginY);
16137
16328
  for(let i = 0; i < len2; ++i) {
16138
- nodeHtml += ic.getGraphCls.drawResNode(nodeArray2[i], i, r, gap, margin2, y, 'b', false, bContactMap);
16329
+ nodeHtml += ic.getGraphCls.drawResNode(nodeArray2[i], i, r, gap, margin2, y, 'b', false, bContactMap, bAfMap);
16139
16330
  node2posSet2[nodeArray2[i].id] = { x: margin2 + i *(r + gap), y: y };
16140
16331
  }
16141
16332
  for(let i = 0, il = linkArray.length; i < il; ++i) {
@@ -16145,10 +16336,10 @@ class LineGraph {
16145
16336
 
16146
16337
  if(!node1 || !node2) continue;
16147
16338
 
16148
- html += this.drawOnePairNode(link, node1, node2, node2posSet1, node2posSet2, bContactMap);
16339
+ html += this.drawOnePairNode(link, node1, node2, node2posSet1, node2posSet2, bContactMap, bAfMap);
16149
16340
 
16150
- if(bContactMap) { // draw symmetric contact map
16151
- html += this.drawOnePairNode(link, node2, node1, node2posSet1, node2posSet2, bContactMap);
16341
+ if(bContactMap && !bAfMap) { // draw symmetric contact map, bAfmap just need to draw once
16342
+ html += this.drawOnePairNode(link, node2, node1, node2posSet1, node2posSet2, bContactMap, bAfMap);
16152
16343
  }
16153
16344
  }
16154
16345
  // show nodes later
@@ -16156,7 +16347,7 @@ class LineGraph {
16156
16347
  return html;
16157
16348
  }
16158
16349
 
16159
- drawOnePairNode(link, node1, node2, node2posSet1, node2posSet2, bContactMap) { let ic = this.icn3d, me = ic.icn3dui;
16350
+ drawOnePairNode(link, node1, node2, node2posSet1, node2posSet2, bContactMap, bAfMap) { let ic = this.icn3d, me = ic.icn3dui;
16160
16351
  let html = '';
16161
16352
 
16162
16353
  let factor = 1;
@@ -16186,21 +16377,31 @@ class LineGraph {
16186
16377
  strokecolor = "#" + me.htmlCls.contactColor;
16187
16378
  }
16188
16379
 
16380
+ if(bContactMap) strokecolor = "#" + link.c;
16381
+
16189
16382
  let linestrokewidth;
16190
16383
  if(link.v == me.htmlCls.contactValue) {
16191
16384
  linestrokewidth = 1;
16192
16385
  } else {
16193
16386
  linestrokewidth = 2;
16194
16387
  }
16195
- html += "<g class='icn3d-interaction' resid1='" + resid1 + "' resid2='" + resid2 + "' >";
16196
- html += "<title>Interaction of residue " + node1.id + " with residue " + node2.id + "</title>";
16197
- if(bContactMap) {
16198
- html += "<rect x='" +(pos2.x - halfSize).toString() + "' y='" +(pos1.y - halfSize).toString() + "' width='" + rectSize + "' height='" + rectSize + "' fill='" + strokecolor + "' stroke-width='" + linestrokewidth + "' stroke='" + strokecolor + "' />";
16388
+
16389
+ if(bAfMap && ic.hex2skip[link.c]) ;
16390
+ else if(bAfMap && ic.hex2id[link.c]) {
16391
+ let id = ic.hex2id[link.c];
16392
+ html += "<use href='#" + id + "' x='" +(pos2.x - halfSize).toString() + "' y='" +(pos1.y - halfSize).toString() + "' />";
16199
16393
  }
16200
16394
  else {
16201
- 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 + "' />";
16395
+ html += "<g class='icn3d-interaction' resid1='" + resid1 + "' resid2='" + resid2 + "' >";
16396
+ html += "<title>Interaction of residue " + node1.id + " with residue " + node2.id + "</title>";
16397
+ if(bContactMap) {
16398
+ html += "<rect x='" +(pos2.x - halfSize).toString() + "' y='" +(pos1.y - halfSize).toString() + "' width='" + rectSize + "' height='" + rectSize + "' fill='" + strokecolor + "' stroke-width='" + linestrokewidth + "' stroke='" + strokecolor + "' />";
16399
+ }
16400
+ else {
16401
+ 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 + "' />";
16402
+ }
16403
+ html += "</g>";
16202
16404
  }
16203
- html += "</g>";
16204
16405
 
16205
16406
  return html;
16206
16407
  }
@@ -16500,8 +16701,9 @@ class ViewInterPairs {
16500
16701
  tmpText = 'Set 2';
16501
16702
  }
16502
16703
  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>';
16503
- html += this.getAllInteractionTable(type).html;
16504
- bondCnt = this.getAllInteractionTable(type).bondCnt;
16704
+ let result = this.getAllInteractionTable(type);
16705
+ html += result.html;
16706
+ bondCnt = result.bondCnt;
16505
16707
 
16506
16708
  $("#" + ic.pre + "dl_interactionsorted").html(html);
16507
16709
  me.htmlCls.dialogCls.openDlg('dl_interactionsorted', 'Show sorted interactions');
@@ -20791,6 +20993,7 @@ class LoadAtomData {
20791
20993
  let serial = serialBase;
20792
20994
 
20793
20995
  let serial2structure = {}; // for "align" only
20996
+ let mmdbid2pdbid = {}; // for "align" only
20794
20997
 
20795
20998
  if(alignType === undefined || alignType === 'target') {
20796
20999
  ic.pmid = data.pubmedId;
@@ -20810,6 +21013,7 @@ class LoadAtomData {
20810
21013
  let refinedStr =(me.cfg.inpara && me.cfg.inpara.indexOf('atype=1') !== -1) ? 'Invariant Core ' : '';
20811
21014
  ic.molTitle = refinedStr + 'Structure Alignment of ';
20812
21015
 
21016
+ let bTitle = false;
20813
21017
  for(let i = 0, il = data.alignedStructures[0].length; i < il; ++i) {
20814
21018
  let structure = data.alignedStructures[0][i];
20815
21019
 
@@ -20818,10 +21022,11 @@ class LoadAtomData {
20818
21022
  }
20819
21023
 
20820
21024
  let pdbidTmp = structure.pdbId;
20821
- structure.mmdbId;
21025
+ let mmdbidTmp = structure.mmdbId;
20822
21026
 
20823
21027
  for(let j = structure.serialInterval[0], jl = structure.serialInterval[1]; j <= jl; ++j) {
20824
21028
  serial2structure[j] = pdbidTmp.toString();
21029
+ mmdbid2pdbid[mmdbidTmp] = pdbidTmp;
20825
21030
  }
20826
21031
 
20827
21032
  for(let j = 0, jl = structure.molecules.length; j < jl; ++j) {
@@ -20847,10 +21052,13 @@ class LoadAtomData {
20847
21052
  ic.molTitle += " and ";
20848
21053
  if(structure.descr !== undefined) ic.pmid += "_";
20849
21054
  }
21055
+
21056
+ bTitle = true;
20850
21057
  }
20851
21058
 
20852
21059
  ic.molTitle += ' from VAST+';
20853
21060
 
21061
+ if(!bTitle) ic.molTitle = '';
20854
21062
  }
20855
21063
  else { // mmdbid or mmcifid
20856
21064
  if(data.descr !== undefined) ic.molTitle += data.descr.name;
@@ -22350,7 +22558,7 @@ class PdbParser {
22350
22558
  let url, dataType;
22351
22559
 
22352
22560
  if(bAf) {
22353
- url = "https://alphafold.ebi.ac.uk/files/AF-" + pdbid + "-F1-model_v1.pdb";
22561
+ url = "https://alphafold.ebi.ac.uk/files/AF-" + pdbid + "-F1-model_v2.pdb";
22354
22562
  ic.ParserUtilsCls.setYourNote(pdbid.toUpperCase() + '(AlphaFold) in iCn3D');
22355
22563
  }
22356
22564
  else {
@@ -23155,11 +23363,11 @@ class AlignParser {
23155
23363
  ic.alignmolid2color.push(tmpHash);
23156
23364
  }
23157
23365
 
23158
- //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];
23159
- //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];
23366
+ //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];
23367
+ //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];
23160
23368
  // need the parameter moleculeInfor
23161
- let url3 = me.htmlCls.baseUrl + 'mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&uid=' + ic.mmdbidArray[0];
23162
- let url4 = me.htmlCls.baseUrl + 'mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&uid=' + ic.mmdbidArray[1];
23369
+ 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];
23370
+ 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];
23163
23371
 
23164
23372
  let d3 = $.ajax({
23165
23373
  url: url3,
@@ -23618,7 +23826,7 @@ class MmdbParser {
23618
23826
  }
23619
23827
 
23620
23828
  let molid2rescount = data.moleculeInfor;
23621
- let molid2chain = {};
23829
+ let molid2color = {}, chain2molid = {}, molid2chain = {};
23622
23830
  let chainNameHash = {};
23623
23831
  for(let i in molid2rescount) {
23624
23832
  if(Object.keys(molid2rescount[i]).length === 0) continue;
@@ -23634,6 +23842,9 @@ class MmdbParser {
23634
23842
 
23635
23843
  let chainNameFinal =(chainNameHash[chainName] === 1) ? chainName : chainName + chainNameHash[chainName].toString();
23636
23844
  let chain = id + '_' + chainNameFinal;
23845
+
23846
+ molid2color[i] = color;
23847
+ chain2molid[chain] = i;
23637
23848
  molid2chain[i] = chain;
23638
23849
 
23639
23850
  ic.chainsColor[chain] =(type !== undefined) ? me.parasCls.thr(me.htmlCls.GREY8) : me.parasCls.thr(color);
@@ -23694,14 +23905,14 @@ class MmdbParser {
23694
23905
  // b: b-factor, s: water, ft: pdbsite
23695
23906
  //&ft=1
23696
23907
  if(bGi) {
23697
- url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&simple=1&gi=" + mmdbid;
23908
+ 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;
23698
23909
  }
23699
23910
  else {
23700
- url = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&simple=1&uid=" + mmdbid;
23701
- }
23911
+ 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;
23912
+ }
23702
23913
 
23703
- // 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
23704
- if(me.cfg.blast_rep_id !== undefined) url += '&buidx=0';
23914
+ // 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
23915
+ if(me.cfg.blast_rep_id !== undefined) url += '&bu=0';
23705
23916
 
23706
23917
  ic.bCid = undefined;
23707
23918
 
@@ -23796,13 +24007,13 @@ class MmdbParser {
23796
24007
  }
23797
24008
 
23798
24009
  downloadMmdbPart2(type) { let ic = this.icn3d, me = ic.icn3dui;
23799
- if(ic.bAssemblyUseAsu) { // set up symmetric matrices
24010
+ if(ic.bAssemblyUseAsu) {
23800
24011
  $("#" + ic.pre + "assemblyWrapper").show();
23801
- ic.bAssembly = true;
24012
+ //ic.bAssembly = true;
23802
24013
  }
23803
24014
  else {
23804
24015
  $("#" + ic.pre + "assemblyWrapper").hide();
23805
- ic.bAssembly = false;
24016
+ //ic.bAssembly = false;
23806
24017
  }
23807
24018
 
23808
24019
  if(ic.emd !== undefined) {
@@ -23957,7 +24168,7 @@ class MmdbParser {
23957
24168
  } // for each domainArray
23958
24169
  } // for each molid
23959
24170
 
23960
- // "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
24171
+ // "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
23961
24172
  ic.bAssemblyUseAsu =(data.asuAtomCount !== undefined) ? true : false;
23962
24173
  if(type !== undefined) {
23963
24174
  ic.bAssemblyUseAsu = false;
@@ -24583,7 +24794,7 @@ class ChainalignParser {
24583
24794
  let pos1 = alignArray[0].indexOf('_');
24584
24795
  ic.mmdbid_t = alignArray[0].substr(0, pos1).toUpperCase();
24585
24796
  ic.chain_t = alignArray[0].substr(pos1+1);
24586
- let url_t = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&uid=" + ic.mmdbid_t;
24797
+ 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;
24587
24798
  if(me.cfg.inpara !== undefined) url_t += me.cfg.inpara;
24588
24799
 
24589
24800
  let ajaxArray = [];
@@ -24609,7 +24820,7 @@ class ChainalignParser {
24609
24820
  let chainalignFinal = ic.mmdbid_q + "_" + ic.chain_q + "," + ic.mmdbid_t + "_" + ic.chain_t;
24610
24821
 
24611
24822
  let urlalign = me.htmlCls.baseUrl + "vastdyn/vastdyn.cgi?chainpairs=" + chainalignFinal;
24612
- let url_q = me.htmlCls.baseUrl + "mmdb/mmdb_strview.cgi?v=2&program=icn3d&b=1&s=1&ft=1&uid=" + ic.mmdbid_q;
24823
+ 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;
24613
24824
 
24614
24825
  if(me.cfg.inpara !== undefined) url_q += me.cfg.inpara;
24615
24826
 
@@ -26486,6 +26697,32 @@ class LoadScript {
26486
26697
 
26487
26698
  return;
26488
26699
  }
26700
+ else if(ic.commands[i].trim().indexOf('set half pae map') == 0) {
26701
+ let strArray = ic.commands[i].split("|||");
26702
+ let command = strArray[0].trim();
26703
+
26704
+ $.when(thisClass.applyCommandAfmap(command)).then(function() {
26705
+ //if(!me.cfg.notebook && dialog && dialog.hasClass("ui-dialog-content")) dialog.dialog( "close" );
26706
+
26707
+ //ic.drawCls.draw();
26708
+ thisClass.execCommandsBase(i + 1, end, steps);
26709
+ });
26710
+
26711
+ return;
26712
+ }
26713
+ else if(ic.commands[i].trim().indexOf('set full pae map') == 0) {
26714
+ let strArray = ic.commands[i].split("|||");
26715
+ let command = strArray[0].trim();
26716
+
26717
+ $.when(thisClass.applyCommandAfmap(command, true)).then(function() {
26718
+ //if(!me.cfg.notebook && dialog && dialog.hasClass("ui-dialog-content")) dialog.dialog( "close" );
26719
+
26720
+ //ic.drawCls.draw();
26721
+ thisClass.execCommandsBase(i + 1, end, steps);
26722
+ });
26723
+
26724
+ return;
26725
+ }
26489
26726
  else {
26490
26727
  ic.applyCommandCls.applyCommand(ic.commands[i]);
26491
26728
  }
@@ -26678,11 +26915,18 @@ class LoadScript {
26678
26915
  me.cfg.mmcifid = id;
26679
26916
  ic.mmcifParserCls.downloadMmcif(id);
26680
26917
  }
26681
- else if(command.indexOf('load mmdb') !== -1) {
26918
+ else if(command.indexOf('load mmdb') !== -1 || command.indexOf('load mmdb1') !== -1) {
26682
26919
  me.cfg.mmdbid = id;
26920
+ me.cfg.bu = 1;
26683
26921
 
26684
26922
  ic.mmdbParserCls.downloadMmdb(id);
26685
26923
  }
26924
+ else if(command.indexOf('load mmdb0') !== -1) {
26925
+ me.cfg.mmdbid = id;
26926
+ me.cfg.bu = 0;
26927
+
26928
+ ic.mmdbParserCls.downloadMmdb(id);
26929
+ }
26686
26930
  else if(command.indexOf('load gi') !== -1) {
26687
26931
  me.cfg.gi = id;
26688
26932
  ic.mmdbParserCls.downloadGi(id);
@@ -26812,6 +27056,23 @@ class LoadScript {
26812
27056
  return ic.deferredRealign.promise();
26813
27057
  }
26814
27058
 
27059
+ applyCommandAfmapBase(command, bFull) { let ic = this.icn3d; ic.icn3dui;
27060
+ let afid = command.substr(command.lastIndexOf(' ') + 1);
27061
+
27062
+ ic.contactMapCls.afErrorMap(afid, bFull);
27063
+ }
27064
+
27065
+ applyCommandAfmap(command, bFull) { let ic = this.icn3d; ic.icn3dui;
27066
+ let thisClass = this;
27067
+
27068
+ // chain functions together
27069
+ ic.deferredAfmap = new $.Deferred(function() {
27070
+ thisClass.applyCommandAfmapBase(command, bFull);
27071
+ }); // end of me.deferred = $.Deferred(function() {
27072
+
27073
+ return ic.deferredAfmap.promise();
27074
+ }
27075
+
26815
27076
  applyCommandGraphinteractionBase(command) { let ic = this.icn3d; ic.icn3dui;
26816
27077
  let paraArray = command.split(' | ');
26817
27078
  if(paraArray.length >= 3) {
@@ -28086,14 +28347,14 @@ class AddTrack {
28086
28347
 
28087
28348
  let strand, itemRgb;
28088
28349
 
28089
- if(fieldArray.length > 4) fieldArray[4];
28350
+ if(fieldArray.length > 4) ;
28090
28351
  if(fieldArray.length > 5) strand = fieldArray[5]; // ., +, or -
28091
- if(fieldArray.length > 6) fieldArray[6];
28092
- if(fieldArray.length > 7) fieldArray[7];
28352
+ if(fieldArray.length > 6) ;
28353
+ if(fieldArray.length > 7) ;
28093
28354
  if(fieldArray.length > 8) itemRgb = fieldArray[8];
28094
- if(fieldArray.length > 9) fieldArray[9];
28095
- if(fieldArray.length > 10) fieldArray[10];
28096
- if(fieldArray.length > 11) fieldArray[11];
28355
+ if(fieldArray.length > 9) ;
28356
+ if(fieldArray.length > 10) ;
28357
+ if(fieldArray.length > 11) ;
28097
28358
 
28098
28359
  let title = trackName;
28099
28360
 
@@ -29585,7 +29846,7 @@ class Picking {
29585
29846
  let text =(ic.pk == 1) ? atom.resn + atom.resi + '@' + atom.name : atom.resn + atom.resi;
29586
29847
  if(ic.structures !== undefined && Object.keys(ic.structures).length > 1) {
29587
29848
  text = atom.structure + '_' + atom.chain + ' ' + text;
29588
- $("#" + ic.pre + "popup").css("width", "140px");
29849
+ $("#" + ic.pre + "popup").css("width", "160px");
29589
29850
  }
29590
29851
  else {
29591
29852
  $("#" + ic.pre + "popup").css("width", "80px");
@@ -30420,6 +30681,9 @@ class ApplyCommand {
30420
30681
  $("#" + ic.pre + "titlelink").css("color", "black");
30421
30682
  }
30422
30683
  }
30684
+ else if(command.indexOf('set label color') == 0) {
30685
+ ic.labelcolor = command.substr(command.lastIndexOf(' ') + 1);
30686
+ }
30423
30687
  else if(commandOri.indexOf('set thickness') == 0) {
30424
30688
  let paraArray = command.split(' | ');
30425
30689
 
@@ -30804,6 +31068,14 @@ class ApplyCommand {
30804
31068
 
30805
31069
  $("#" + me.contactmapid).attr("width",(ic.contactmapWidth * parseFloat(scale)).toString() + "px");
30806
31070
  }
31071
+ else if(command.indexOf('alignerrormap scale') == 0) {
31072
+ let pos = command.lastIndexOf(' ');
31073
+ let scale = command.substr(pos + 1);
31074
+
31075
+ $("#" + me.alignerrormapid + "_scale").val(scale);
31076
+
31077
+ $("#" + me.alignerrormapid).attr("width",(ic.alignerrormapWidth * parseFloat(scale)).toString() + "px");
31078
+ }
30807
31079
  else if(command.indexOf('graph force') == 0) {
30808
31080
  let pos = command.lastIndexOf(' ');
30809
31081
  me.htmlCls.force = parseInt(command.substr(pos + 1));
@@ -32251,6 +32523,8 @@ class SetSeqAlign {
32251
32523
  ic.alnChainsAnTtl[chainid1][6].push("");
32252
32524
 
32253
32525
  let alignIndex = 1;
32526
+ if(!ic.chainsMapping[chainid1]) ic.chainsMapping[chainid1] = {};
32527
+ if(!ic.chainsMapping[chainid2]) ic.chainsMapping[chainid2] = {};
32254
32528
  //for(let j = 0, jl = alignData.sseq.length; j < jl; ++j) {
32255
32529
  for(let j = start; j <= end; ++j) {
32256
32530
  // 0: internal resi id, 1: pdb resi id, 2: resn, 3: aligned or not
@@ -32282,6 +32556,10 @@ class SetSeqAlign {
32282
32556
  ic.nconsHash2[chainid2 + '_' + resi] = 1;
32283
32557
  }
32284
32558
 
32559
+ // mapping, use the firstsequence as the reference structure
32560
+ ic.chainsMapping[chainid1][chainid1 + '_' + id2aligninfo[j].resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
32561
+ ic.chainsMapping[chainid2][chainid2 + '_' + resi] = id2aligninfo[j].resn + id2aligninfo[j].resi;
32562
+
32285
32563
  color2 = '#' + ic.showAnnoCls.getColorhexFromBlosum62(id2aligninfo[j].resn, resn);
32286
32564
 
32287
32565
  // expensive and thus remove
@@ -32466,6 +32744,8 @@ class SetSeqAlign {
32466
32744
  if(ic.qt_start_end[chainIndex] === undefined) return;
32467
32745
 
32468
32746
  let alignIndex = 1;
32747
+ if(!ic.chainsMapping[chainid1]) ic.chainsMapping[chainid1] = {};
32748
+ if(!ic.chainsMapping[chainid2]) ic.chainsMapping[chainid2] = {};
32469
32749
  for(let i = 0, il = ic.qt_start_end[chainIndex].length; i < il; ++i) {
32470
32750
  //var start1 = ic.qt_start_end[chainIndex][i].q_start - 1;
32471
32751
  //var start2 = ic.qt_start_end[chainIndex][i].t_start - 1;
@@ -32559,6 +32839,10 @@ class SetSeqAlign {
32559
32839
  ic.nconsHash2[chainid2 + '_' + resi2] = 1;
32560
32840
  }
32561
32841
 
32842
+ // mapping, use the firstsequence as the reference structure
32843
+ ic.chainsMapping[chainid1][chainid1 + '_' + resi1] = resn1 + resi1;
32844
+ ic.chainsMapping[chainid2][chainid2 + '_' + resi2] = resn1 + resi1;
32845
+
32562
32846
  color2 = '#' + ic.showAnnoCls.getColorhexFromBlosum62(resn1, resn2);
32563
32847
 
32564
32848
  let bFirstResi =(i === 0 && j === 0) ? true : false;
@@ -32608,6 +32892,8 @@ class SetSeqAlign {
32608
32892
  // let prevChainid1 = '', prevChainid2 = '', cnt1 = 0, cnt2 = 0;
32609
32893
 
32610
32894
  let residuesHash = {};
32895
+ if(!ic.chainsMapping[chainid_t]) ic.chainsMapping[chainid_t] = {};
32896
+ if(!ic.chainsMapping[chainid]) ic.chainsMapping[chainid] = {};
32611
32897
 
32612
32898
  for(let i = 0, il = ic.realignResid[structure1].length; i < il; ++i) {
32613
32899
  let resObject1 = ic.realignResid[structure1][i];
@@ -32634,6 +32920,11 @@ class SetSeqAlign {
32634
32920
  else {
32635
32921
  color = "#0000FF";
32636
32922
  }
32923
+
32924
+ // mapping, use the firstsequence as the reference structure
32925
+ ic.chainsMapping[chainid_t][chainid_t + '_' + resObject1.resi] = resObject1.resn + resObject1.resi;
32926
+ ic.chainsMapping[chainid][chainid + '_' + resObject2.resi] = resObject1.resn + resObject1.resi;
32927
+
32637
32928
  let color2 = '#' + ic.showAnnoCls.getColorhexFromBlosum62(resObject1.resn, resObject2.resn);
32638
32929
 
32639
32930
  resObject1.color = color;
@@ -33801,7 +34092,7 @@ class MmcifParser {
33801
34092
  }
33802
34093
  }
33803
34094
 
33804
- loadMmcifSymmetry(assembly) { let ic = this.icn3d; ic.icn3dui;
34095
+ loadMmcifSymmetry(assembly) { let ic = this.icn3d, me = ic.icn3dui;
33805
34096
  // load assembly info
33806
34097
  //var assembly = data.assembly;
33807
34098
  //var pmatrix = data.pmatrix;
@@ -33814,6 +34105,11 @@ class MmcifParser {
33814
34105
  }
33815
34106
 
33816
34107
  ic.asuCnt = ic.biomtMatrices.length;
34108
+
34109
+ // show bioassembly
34110
+ if(me.cfg.bu == 1 && Object.keys(ic.atoms).length * ic.asuCnt > ic.maxatomcnt) {
34111
+ ic.bAssembly = true;
34112
+ }
33817
34113
  }
33818
34114
 
33819
34115
  loadMmcifOpmDataPart2(data, pdbid) { let ic = this.icn3d, me = ic.icn3dui;
@@ -38422,9 +38718,12 @@ class Selection {
38422
38718
  ic.graphStr = this.getGraphDataForDisplayed();
38423
38719
  }
38424
38720
 
38721
+ // don not redraw graphs after the selection changes
38722
+ /*
38425
38723
  if(ic.bGraph) ic.drawGraphCls.drawGraph(ic.graphStr, ic.pre + 'dl_graph');
38426
38724
  if(ic.bLinegraph) ic.lineGraphCls.drawLineGraph(ic.graphStr);
38427
38725
  if(ic.bScatterplot) ic.lineGraphCls.drawLineGraph(ic.graphStr, true);
38726
+ */
38428
38727
  }
38429
38728
 
38430
38729
  hideSelection() { let ic = this.icn3d, me = ic.icn3dui;
@@ -38632,7 +38931,7 @@ class Selection {
38632
38931
  }
38633
38932
 
38634
38933
  toggleMembrane(bShowMembrane) {var ic = this.icn3d, me = ic.icn3dui;
38635
- let structureArray = Object.keys(ic.structures);
38934
+ let structureArray = (ic.structures) ? Object.keys(ic.structures) : [];
38636
38935
 
38637
38936
  for(let i = 0, il = structureArray.length; i < il; ++i) {
38638
38937
  let structure = structureArray[i];
@@ -39656,6 +39955,8 @@ class Label {
39656
39955
 
39657
39956
  let labelsize = (label.size !== undefined) ? label.size : ic.LABELSIZE;
39658
39957
  let labelcolor = (label.color !== undefined) ? label.color : defaultColor;
39958
+ if(ic.labelcolor) labelcolor = ic.labelcolor;
39959
+
39659
39960
  let labelbackground = (label.background !== undefined) ? label.background : '#cccccc';
39660
39961
  let labelalpha = (label.alpha !== undefined) ? label.alpha : 1.0;
39661
39962
 
@@ -39681,7 +39982,8 @@ class Label {
39681
39982
  }
39682
39983
  }
39683
39984
 
39684
- bb.position.set(label.position.x, label.position.y, label.position.z);
39985
+ let labelOffset = (name == 'schematic' || name == 'residue') ? 0 : ic.coilWidth; // 0.3
39986
+ bb.position.set(label.position.x + labelOffset, label.position.y + labelOffset, label.position.z + labelOffset);
39685
39987
  ic.mdl.add(bb);
39686
39988
  // do not add labels to objects for pk
39687
39989
  }
@@ -39713,7 +40015,6 @@ class ApplyDisplay {
39713
40015
 
39714
40016
  //Apply style and label options to a certain set of atoms.
39715
40017
  applyDisplayOptions(options, atoms, bHighlight) { let ic = this.icn3d, me = ic.icn3dui;
39716
- if(options === undefined) options = ic.opts;
39717
40018
 
39718
40019
  // get parameters from cookies
39719
40020
  if(!me.bNode && me.htmlCls.setHtmlCls.getCookie('lineRadius') != '') {
@@ -42215,7 +42516,12 @@ class Draw {
42215
42516
  ic.setColorCls.applyPrevColor();
42216
42517
 
42217
42518
  if(ic.biomtMatrices !== undefined && ic.biomtMatrices.length > 1) {
42218
- if(ic.bAssembly && Object.keys(ic.structures).length == 1) {
42519
+ // show bioassembly in two cases
42520
+ // 1. asymmetric unit: me.cfg.bu == 0
42521
+ // 2. biological unit with less than ic.maxatomcnt atom:
42522
+ // me.cfg.bu == 1 && Object.keys(ic.atoms).length * ic.biomtMatrices.length < ic.maxatomcnt
42523
+ if(ic.bAssembly && Object.keys(ic.structures).length == 1 && (me.cfg.bu == 0
42524
+ || (me.cfg.bu == 1 && Object.keys(ic.atoms).length * ic.biomtMatrices.length > ic.maxatomcnt)) ) {
42219
42525
  ic.instancingCls.drawSymmetryMates();
42220
42526
  }
42221
42527
  else {
@@ -42512,10 +42818,10 @@ class Transform {
42512
42818
 
42513
42819
  if(ic.bRender) ic.drawCls.render();
42514
42820
  }
42515
-
42821
+ /*
42516
42822
  //Zoom in the structure at certain ratio, e.g., 0.1 is a reasonable value.
42517
42823
  zoomIn(normalizedFactor) { let ic = this.icn3d, me = ic.icn3dui;
42518
- let para = {};
42824
+ let para = {}
42519
42825
  para._zoomFactor = 1 - normalizedFactor;
42520
42826
  para.update = true;
42521
42827
  if(ic.bControlGl && !me.bNode) {
@@ -42525,12 +42831,14 @@ class Transform {
42525
42831
  ic.controls.update(para);
42526
42832
  }
42527
42833
 
42528
- if(ic.bRender) ic.drawCls.render();
42834
+ if(ic.bRender) {
42835
+ ic.drawCls.render();
42836
+ }
42529
42837
  }
42530
42838
 
42531
42839
  //Zoom out the structure at certain ratio, e.g., 0.1 is a reasonable value.
42532
42840
  zoomOut(normalizedFactor) { let ic = this.icn3d, me = ic.icn3dui;
42533
- let para = {};
42841
+ let para = {}
42534
42842
  para._zoomFactor = 1 + normalizedFactor;
42535
42843
  para.update = true;
42536
42844
 
@@ -42540,8 +42848,11 @@ class Transform {
42540
42848
  else {
42541
42849
  ic.controls.update(para);
42542
42850
  }
42543
- if(ic.bRender) ic.drawCls.render();
42851
+ if(ic.bRender) {
42852
+ ic.drawCls.render();
42853
+ }
42544
42854
  }
42855
+ */
42545
42856
 
42546
42857
  //Center on the selected atoms and zoom in.
42547
42858
  zoominSelection(atoms) { let ic = this.icn3d, me = ic.icn3dui;
@@ -42744,20 +43055,29 @@ class SaveFile {
42744
43055
  }
42745
43056
  }
42746
43057
 
42747
- saveSvg(id, filename) { let ic = this.icn3d; ic.icn3dui;
42748
- let svg = this.getSvgXml(id);
43058
+ saveSvg(id, filename, bContactmap) { let ic = this.icn3d, me = ic.icn3dui;
43059
+ if(me.bNode) return '';
43060
+
43061
+ let width = $("#" + id).width();
43062
+ let height = $("#" + id).height();
43063
+
43064
+ if(bContactmap) height = width;
42749
43065
 
42750
- let blob = new Blob([svg], {type: "image/svg+xml"});
43066
+ let svgXml = this.getSvgXml(id, width, height, bContactmap);
43067
+
43068
+ let blob = new Blob([svgXml], {type: "image/svg+xml"});
42751
43069
  saveAs(blob, filename);
42752
43070
  }
42753
43071
 
42754
- getSvgXml(id) { let ic = this.icn3d, me = ic.icn3dui;
43072
+ getSvgXml(id, width, height, bContactmap) { let ic = this.icn3d, me = ic.icn3dui;
42755
43073
  if(me.bNode) return '';
42756
43074
 
42757
43075
  // font is not good
42758
43076
  let svg_data = document.getElementById(id).innerHTML; //put id of your svg element here
42759
43077
 
42760
- 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/\">";
43078
+ let viewbox = (width && height) ? "<svg viewBox=\"0 0 " + width + " " + height + "\"" : "<svg";
43079
+ //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/\">";
43080
+ 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/\">";
42761
43081
 
42762
43082
  //if you have some additional styling like graph edges put them inside <style> tag
42763
43083
  let style = "<style>text {font-family: sans-serif; font-weight: bold; font-size: 18px;}</style>";
@@ -42767,9 +43087,14 @@ class SaveFile {
42767
43087
  return full_svg;
42768
43088
  }
42769
43089
 
42770
- savePng(id, filename, width, height) { let ic = this.icn3d, me = ic.icn3dui;
43090
+ savePng(id, filename, bContactmap) { let ic = this.icn3d, me = ic.icn3dui;
42771
43091
  if(me.bNode) return '';
42772
43092
 
43093
+ let width = $("#" + id).width();
43094
+ let height = $("#" + id).height();
43095
+
43096
+ if(bContactmap) height = width;
43097
+
42773
43098
  // https://stackoverflow.com/questions/3975499/convert-svg-to-image-jpeg-png-etc-in-the-browser
42774
43099
  let svg = document.getElementById(id);
42775
43100
  let bbox = svg.getBBox();
@@ -42783,7 +43108,7 @@ class SaveFile {
42783
43108
  let ctx = canvas.getContext("2d");
42784
43109
  ctx.clearRect(0, 0, bbox.width, bbox.height);
42785
43110
 
42786
- let data = this.getSvgXml(id); //(new XMLSerializer()).serializeToString(copy); //ic.saveFileCls.getSvgXml();
43111
+ let data = this.getSvgXml(id, width, height, bContactmap); //(new XMLSerializer()).serializeToString(copy); //ic.saveFileCls.getSvgXml();
42787
43112
  let DOMURL = window.URL || window.webkitURL || window;
42788
43113
  let svgBlob = new Blob([data], {type: "image/svg+xml;charset=utf-8"});
42789
43114
 
@@ -43495,6 +43820,10 @@ class ClickMenu {
43495
43820
  me.myEventCls.onIds("#" + me.pre + "mn1_xyzfile", "click", function(e) { me.icn3d;
43496
43821
  me.htmlCls.dialogCls.openDlg('dl_xyzfile', 'Please input XYZ File');
43497
43822
  });
43823
+
43824
+ me.myEventCls.onIds("#" + me.pre + "mn1_afmapfile", "click", function(e) { me.icn3d;
43825
+ me.htmlCls.dialogCls.openDlg('dl_afmapfile', 'Please input AlphaFold PAE File');
43826
+ });
43498
43827
  // },
43499
43828
  // clkMn1_urlfile: function() {
43500
43829
  me.myEventCls.onIds("#" + me.pre + "mn1_urlfile", "click", function(e) { me.icn3d;
@@ -44905,6 +45234,10 @@ class ClickMenu {
44905
45234
  me.myEventCls.onIds("#" + me.pre + "mn6_addlabelSelection", "click", function(e) { me.icn3d;
44906
45235
  me.htmlCls.dialogCls.openDlg('dl_addlabelselection', 'Add custom labels by the selected');
44907
45236
  });
45237
+
45238
+ me.myEventCls.onIds("#" + me.pre + "mn6_labelColor", "click", function(e) { me.icn3d;
45239
+ me.htmlCls.dialogCls.openDlg('dl_labelColor', 'Change color for all labels');
45240
+ });
44908
45241
  // },
44909
45242
  // clkMn2_saveselection: function() {
44910
45243
  me.myEventCls.onIds("#" + me.pre + "mn2_saveselection", "click", function(e) { me.icn3d;
@@ -44913,7 +45246,8 @@ class ClickMenu {
44913
45246
  // },
44914
45247
  // clkMn6_addlabelNo: function() {
44915
45248
  me.myEventCls.onIds(["#" + me.pre + "mn6_addlabelNo", "#" + me.pre + "removeLabels"], "click", function(e) { let ic = me.icn3d;
44916
- ic.pickpair = false;
45249
+ ic.labelcolor = undefined;
45250
+ ic.pickpair = false;
44917
45251
  //ic.labels['residue'] = [];
44918
45252
  //ic.labels['custom'] = [];
44919
45253
  let select = "set labels off";
@@ -45838,6 +46172,7 @@ class SetMenu {
45838
46172
  let html = "";
45839
46173
 
45840
46174
  html += "<ul class='icn3d-mn-item'>";
46175
+ html += "<li><a href='https://www.ncbi.nlm.nih.gov/structure' target='_blank'>Search Structure " + me.htmlCls.wifiStr + "</a></li>";
45841
46176
  html += "<li><span>Retrieve by ID</span>";
45842
46177
  html += "<ul>";
45843
46178
  html += me.htmlCls.setHtmlCls.getLink('mn1_mmdbid', 'MMDB ID ' + me.htmlCls.wifiStr);
@@ -45862,6 +46197,8 @@ class SetMenu {
45862
46197
  html += me.htmlCls.setHtmlCls.getLink('mn1_mol2file', 'Mol2 File');
45863
46198
  html += me.htmlCls.setHtmlCls.getLink('mn1_sdffile', 'SDF File');
45864
46199
  html += me.htmlCls.setHtmlCls.getLink('mn1_xyzfile', 'XYZ File');
46200
+ html += me.htmlCls.setHtmlCls.getLink('mn1_afmapfile', 'AlphaFold PAE File');
46201
+
45865
46202
  if(!me.cfg.simplemenu) html += me.htmlCls.setHtmlCls.getLink('mn1_urlfile', 'URL(Same Host) ' + me.htmlCls.wifiStr);
45866
46203
  html += "<li>-</li>";
45867
46204
  html += me.htmlCls.setHtmlCls.getLink('mn1_pngimage', 'iCn3D PNG Image');
@@ -46912,6 +47249,8 @@ class SetMenu {
46912
47249
  html += me.htmlCls.setHtmlCls.getRadio('mn6_addlabel', 'mn6_addlabelTermini', 'N- & C-Termini');
46913
47250
  }
46914
47251
 
47252
+ html += "<li>-</li>";
47253
+ html += me.htmlCls.setHtmlCls.getRadio('mn6_addlabel', 'mn6_labelColor', 'Change Label Color', true);
46915
47254
  html += me.htmlCls.setHtmlCls.getRadio('mn6_addlabel', 'mn6_addlabelNo', 'Remove', true);
46916
47255
  html += "</ul>";
46917
47256
  html += "</li>";
@@ -46967,12 +47306,19 @@ class SetMenu {
46967
47306
  }
46968
47307
 
46969
47308
  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;
47309
+
46970
47310
  if(bOnePdb) {
46971
47311
  html += "<li id='" + me.pre + "assemblyWrapper'><span>Assembly</span>";
46972
47312
  html += "<ul>";
46973
47313
 
46974
- html += me.htmlCls.setHtmlCls.getRadio('mn6_assembly', 'mn6_assemblyYes', 'Biological Assembly', true);
46975
- html += me.htmlCls.setHtmlCls.getRadio('mn6_assembly', 'mn6_assemblyNo', 'Asymmetric Unit');
47314
+ if(me.cfg.bu == 0) {
47315
+ html += me.htmlCls.setHtmlCls.getRadio('mn6_assembly', 'mn6_assemblyYes', 'Biological Assembly');
47316
+ html += me.htmlCls.setHtmlCls.getRadio('mn6_assembly', 'mn6_assemblyNo', 'Asymmetric Unit', true);
47317
+ }
47318
+ else {
47319
+ html += me.htmlCls.setHtmlCls.getRadio('mn6_assembly', 'mn6_assemblyYes', 'Biological Assembly', true);
47320
+ html += me.htmlCls.setHtmlCls.getRadio('mn6_assembly', 'mn6_assemblyNo', 'Asymmetric Unit');
47321
+ }
46976
47322
 
46977
47323
  html += "</ul>";
46978
47324
  html += "</li>";
@@ -47216,6 +47562,7 @@ class Dialog {
47216
47562
  let bLineGraph = $('#' + me.pre + 'dl_linegraph').hasClass('ui-dialog-content'); // initialized
47217
47563
  let bScatterplot = $('#' + me.pre + 'dl_scatterplot').hasClass('ui-dialog-content'); // initialized
47218
47564
  let bContactmap = $('#' + me.pre + 'dl_contactmap').hasClass('ui-dialog-content'); // initialized
47565
+ let bAlignerrormap = $('#' + me.pre + 'dl_alignerrormap').hasClass('ui-dialog-content'); // initialized
47219
47566
  let bTable = $('#' + me.pre + 'dl_interactionsorted').hasClass('ui-dialog-content'); // initialized
47220
47567
  let bAlignmentInit = $('#' + me.pre + 'dl_alignment').hasClass('ui-dialog-content'); // initialized
47221
47568
  let bTwoddgmInit = $('#' + me.pre + 'dl_2ddgm').hasClass('ui-dialog-content'); // initialized
@@ -47231,6 +47578,7 @@ class Dialog {
47231
47578
  if(bLineGraph) status.bLineGraph2 = $('#' + me.pre + 'dl_linegraph').dialog( 'isOpen' );
47232
47579
  if(bScatterplot) status.bScatterplot2 = $('#' + me.pre + 'dl_scatterplot').dialog( 'isOpen' );
47233
47580
  if(bContactmap) status.bContactmap2 = $('#' + me.pre + 'dl_contactmap').dialog( 'isOpen' );
47581
+ if(bAlignerrormap) status.bAlignerror2 = $('#' + me.pre + 'dl_alignerrormap').dialog( 'isOpen' );
47234
47582
  if(bTable) status.bTable2 = $('#' + me.pre + 'dl_interactionsorted').dialog( 'isOpen' );
47235
47583
  if(bAlignmentInit) status.bAlignmentInit2 = $('#' + me.pre + 'dl_alignment').dialog( 'isOpen' );
47236
47584
  if(bTwoddgmInit) status.bTwoddgmInit2 = $('#' + me.pre + 'dl_2ddgm').dialog( 'isOpen' );
@@ -47275,13 +47623,14 @@ class Dialog {
47275
47623
  close: function(e) {
47276
47624
  let status = thisClass.getDialogStatus();
47277
47625
 
47278
- if((id === me.pre + 'dl_selectannotations' &&(!status.bAlignmentInit2) && !status.bGraph2 && !status.bTable2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bContactmap2)
47279
- ||(id === me.pre + 'dl_graph' &&(!status.bSelectannotationsInit2) &&(!status.bAlignmentInit2) && !status.bTable2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bContactmap2)
47280
- ||(id === me.pre + 'dl_alignment' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bTable2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bContactmap2)
47281
- ||(id === me.pre + 'dl_interactionsorted' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bAlignmentInit2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bContactmap2)
47282
- ||(id === me.pre + 'dl_linegraph' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bAlignmentInit2 && !status.bTable2 && !status.bScatterplot2 && !status.bContactmap2)
47283
- ||(id === me.pre + 'dl_scatterplot' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bAlignmentInit2 && !status.bTable2 && !status.bLineGraph2 && !status.bContactmap2)
47284
- ||(id === me.pre + 'dl_contactmap' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bAlignmentInit2 && !status.bTable2 && !status.bLineGraph2 && !status.bScatterplot2)
47626
+ if((id === me.pre + 'dl_selectannotations' &&(!status.bAlignmentInit2) && !status.bGraph2 && !status.bTable2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bContactmap2 && !status.bAlignerrormap2)
47627
+ ||(id === me.pre + 'dl_graph' &&(!status.bSelectannotationsInit2) &&(!status.bAlignmentInit2) && !status.bTable2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bContactmap2 && !status.bAlignerrormap2)
47628
+ ||(id === me.pre + 'dl_alignment' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bTable2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bContactmap2 && !status.bAlignerrormap2)
47629
+ ||(id === me.pre + 'dl_interactionsorted' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bAlignmentInit2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bContactmap2 && !status.bAlignerrormap2)
47630
+ ||(id === me.pre + 'dl_linegraph' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bAlignmentInit2 && !status.bTable2 && !status.bScatterplot2 && !status.bContactmap2 && !status.bAlignerrormap2)
47631
+ ||(id === me.pre + 'dl_scatterplot' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bAlignmentInit2 && !status.bTable2 && !status.bLineGraph2 && !status.bContactmap2 && !status.bAlignerrormap2)
47632
+ ||(id === me.pre + 'dl_contactmap' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bAlignmentInit2 && !status.bTable2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bAlignerrormap2)
47633
+ ||(id === me.pre + 'dl_alignerrormap' &&(!status.bSelectannotationsInit2) && !status.bGraph2 && !status.bAlignmentInit2 && !status.bTable2 && !status.bLineGraph2 && !status.bScatterplot2 && !status.bContactmap2)
47285
47634
  ) {
47286
47635
  if(status.bTwoddgmInit2 || status.bTwodctnInit2 || status.bSetsInit2) {
47287
47636
  //ic.resizeCanvasCls.resizeCanvas(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH - twoddgmWidth, me.htmlCls.HEIGHT - me.htmlCls.LESSHEIGHT - me.htmlCls.EXTRAHEIGHT, true);
@@ -47308,7 +47657,7 @@ class Dialog {
47308
47657
 
47309
47658
  d3.select("#" + me.svgid).attr("width", width).attr("height", height);
47310
47659
  }
47311
- else if(id == me.pre + 'dl_linegraph' || id == me.pre + 'dl_scatterplot' || id == me.pre + 'dl_contactmap') {
47660
+ else if(id == me.pre + 'dl_linegraph' || id == me.pre + 'dl_scatterplot' || id == me.pre + 'dl_contactmap' || id == me.pre + 'dl_alignerrormap') {
47312
47661
  //var bTwoddgmInit = $('#' + me.pre + 'dl_2ddgm').hasClass('ui-dialog-content'); // initialized
47313
47662
  //var bSetsInit = $('#' + me.pre + 'dl_definedsets').hasClass('ui-dialog-content'); // initialized
47314
47663
 
@@ -47331,6 +47680,10 @@ class Dialog {
47331
47680
  let width = ic.contactmapWidth * ratio;
47332
47681
  $("#" + me.contactmapid).attr("width", width);
47333
47682
  }
47683
+ else if(id == me.pre + 'dl_alignerrormap') {
47684
+ let width = ic.alignerrormapWidth * ratio;
47685
+ $("#" + me.alignerrormapid).attr("width", width);
47686
+ }
47334
47687
  }
47335
47688
  }
47336
47689
  });
@@ -47426,7 +47779,7 @@ class Dialog {
47426
47779
 
47427
47780
  let status = this.getDialogStatus();
47428
47781
 
47429
- 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') {
47782
+ 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') {
47430
47783
  //var dialogWidth = 0.5 *(me.htmlCls.WIDTH - me.htmlCls.LESSWIDTH) - twoddgmWidth * 0.5;
47431
47784
  let dialogWidth = 0.5 *(me.htmlCls.WIDTH) - twoddgmWidth * 0.5;
47432
47785
 
@@ -47462,13 +47815,14 @@ class Dialog {
47462
47815
  modal: false,
47463
47816
  position: position,
47464
47817
  close: function(e) {
47465
- if((id === me.pre + 'dl_selectannotations' &&(!status.bAlignmentInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2))
47466
- ||(id === me.pre + 'dl_graph' &&(!status.bSelectannotationsInit2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2))
47467
- ||(id === me.pre + 'dl_alignment' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2))
47468
- ||(id === me.pre + 'dl_interactionsorted' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2))
47469
- ||(id === me.pre + 'dl_linegraph' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bScatterplot2) &&(!status.bContactmap2))
47470
- ||(id === me.pre + 'dl_scatterplot' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bContactmap2))
47471
- ||(id === me.pre + 'dl_contactmap' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2))
47818
+ if((id === me.pre + 'dl_selectannotations' &&(!status.bAlignmentInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
47819
+ ||(id === me.pre + 'dl_graph' &&(!status.bSelectannotationsInit2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
47820
+ ||(id === me.pre + 'dl_alignment' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
47821
+ ||(id === me.pre + 'dl_interactionsorted' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
47822
+ ||(id === me.pre + 'dl_linegraph' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bScatterplot2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
47823
+ ||(id === me.pre + 'dl_scatterplot' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bContactmap2) &&(!status.bAlignerrormap2))
47824
+ ||(id === me.pre + 'dl_contactmap' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bAlignerrormap2))
47825
+ ||(id === me.pre + 'dl_alignerrormap' &&(!status.bSelectannotationsInit2) &&(!status.bGraph2) &&(!status.bAlignmentInit2) &&(!status.bTable2) &&(!status.bLineGraph2) &&(!status.bScatterplot2) &&(!status.bContactmap2))
47472
47826
  ) {
47473
47827
  if(status.bTwoddgmInit2 || status.bTwodctnInit2 || status.bSetsInit2) {
47474
47828
  let canvasWidth = me.utilsCls.isMobile() ? me.htmlCls.WIDTH : me.htmlCls.WIDTH - twoddgmWidth;
@@ -47494,7 +47848,7 @@ class Dialog {
47494
47848
 
47495
47849
  d3.select("#" + me.svgid).attr("width", width).attr("height", height);
47496
47850
  }
47497
- else if(id == me.pre + 'dl_linegraph' || id == me.pre + 'dl_scatterplot' || id == me.pre + 'dl_contactmap') {
47851
+ else if(id == me.pre + 'dl_linegraph' || id == me.pre + 'dl_scatterplot' || id == me.pre + 'dl_contactmap' || id == me.pre + 'dl_alignerrormap') {
47498
47852
  //var bTwoddgmInit = $('#' + me.pre + 'dl_2ddgm').hasClass('ui-dialog-content'); // initialized
47499
47853
  //var bSetsInit = $('#' + me.pre + 'dl_definedsets').hasClass('ui-dialog-content'); // initialized
47500
47854
 
@@ -47517,6 +47871,10 @@ class Dialog {
47517
47871
  let width = ic.contactmapWidth * ratio;
47518
47872
  $("#" + me.contactmapid).attr("width", width);
47519
47873
  }
47874
+ else if(id == me.pre + 'dl_alignerrormap') {
47875
+ let width = ic.alignerrormapWidth * ratio;
47876
+ $("#" + me.alignerrormapid).attr("width", width);
47877
+ }
47520
47878
  }
47521
47879
  }
47522
47880
  });
@@ -47639,7 +47997,7 @@ class Dialog {
47639
47997
  let width = 400, height = 150;
47640
47998
  let twoddgmWidth = me.htmlCls.width2d + 20;
47641
47999
 
47642
- 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') {
48000
+ 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') {
47643
48001
  $( "#" + id ).show();
47644
48002
 
47645
48003
  height =(me.htmlCls.HEIGHT) * 0.5;
@@ -47677,6 +48035,11 @@ class Dialog {
47677
48035
 
47678
48036
  $("#" + me.contactmapid).attr("width", width);
47679
48037
  }
48038
+ else if(id == me.pre + 'dl_alignerrormap') {
48039
+ let width = ic.alignerrormapWidth * ratio;
48040
+
48041
+ $("#" + me.alignerrormapid).attr("width", width);
48042
+ }
47680
48043
  });
47681
48044
  }
47682
48045
  else {
@@ -47810,8 +48173,12 @@ class SetDialog {
47810
48173
  html += "Note: AlphaFold produces a per-residue confidence score (pLDDT) between 0 and 100:<br>";
47811
48174
  html += me.htmlCls.clickMenuCls.setAlphaFoldLegend() + "<br>";
47812
48175
 
47813
- 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> ";
47814
- html += me.htmlCls.buttonStr + "reload_af'>Load</button>";
48176
+ let afid = (me.cfg.afid) ? me.cfg.afid : 'Q76EI6';
48177
+
48178
+ 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>";
48179
+ html += me.htmlCls.buttonStr + "reload_af'>Load Structure</button>"
48180
+ + me.htmlCls.buttonStr + "reload_afmap' style='margin-left:30px'>Load Half PAE Map</button>"
48181
+ + me.htmlCls.buttonStr + "reload_afmapfull' style='margin-left:30px'>Load Full PAE Map (slow)</button>";
47815
48182
  html += "</div>";
47816
48183
 
47817
48184
  html += me.htmlCls.divStr + "dl_opmid' class='" + dialogClass + "'>";
@@ -47882,7 +48249,7 @@ class SetDialog {
47882
48249
  html += "<b>Optional 1</b>, full chains are used for structure alignment<br/><br/>";
47883
48250
  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/>";
47884
48251
  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/>";
47885
- 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/>";
48252
+ 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/>";
47886
48253
  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>";
47887
48254
  html += "</div></div>";
47888
48255
 
@@ -47907,6 +48274,13 @@ class SetDialog {
47907
48274
  html += "XYZ File: " + me.htmlCls.inputFileStr + "id='" + me.pre + "xyzfile' size=8> ";
47908
48275
  html += me.htmlCls.buttonStr + "reload_xyzfile'>Load</button>";
47909
48276
  html += "</div>";
48277
+
48278
+ html += me.htmlCls.divStr + "dl_afmapfile' class='" + dialogClass + "'>";
48279
+ html += "AlphaFold PAE File: " + me.htmlCls.inputFileStr + "id='" + me.pre + "afmapfile' size=8> <br><br>";
48280
+ html += me.htmlCls.buttonStr + "reload_afmapfile'>Load Half PAE Map</button>"
48281
+ + me.htmlCls.buttonStr + "reload_afmapfilefull' style='margin-left:30px'>Load Full PAE Map (slow)</button>";
48282
+ html += "</div>";
48283
+
47910
48284
  html += me.htmlCls.divStr + "dl_urlfile' class='" + dialogClass + "'>";
47911
48285
  html += "File type: ";
47912
48286
  html += "<select id='" + me.pre + "filetype'>";
@@ -47930,9 +48304,16 @@ class SetDialog {
47930
48304
  html += me.htmlCls.buttonStr + "reload_mmcif'>Load</button>";
47931
48305
  html += "</div>";
47932
48306
 
47933
- html += me.htmlCls.divStr + "dl_mmdbid' class='" + dialogClass + "'>";
47934
- html += "MMDB or PDB ID: " + me.htmlCls.inputTextStr + "id='" + me.pre + "mmdbid' value='1TUP' size=8> ";
47935
- html += me.htmlCls.buttonStr + "reload_mmdb'>Load</button>";
48307
+ html += me.htmlCls.divStr + "dl_mmdbid' class='" + dialogClass + "' style='max-width:500px'>";
48308
+ html += "MMDB or PDB ID: " + me.htmlCls.inputTextStr + "id='" + me.pre + "mmdbid' value='1TUP' size=8> <br><br>";
48309
+ 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>";
48310
+ 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="'
48311
+ + me.pre + 'asu_bu_expand" class="ui-icon ui-icon-plus icn3d-expand icn3d-link" style="width:15px;" title="Expand"></span><span id="'
48312
+ + me.pre + 'asu_bu_shrink" class="ui-icon ui-icon-minus icn3d-shrink icn3d-link" style="display:none; width:15px;" title="Shrink"></span></div>';
48313
+
48314
+ html += me.htmlCls.divStr + "asu_bu' style='display:none;'>";
48315
+ 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>';
48316
+
47936
48317
  html += "</div>";
47937
48318
 
47938
48319
  html += me.htmlCls.divStr + "dl_blast_rep_id' style='max-width:500px;' class='" + dialogClass + "'>";
@@ -48268,6 +48649,33 @@ class SetDialog {
48268
48649
 
48269
48650
  html += "</div>";
48270
48651
 
48652
+ html += me.htmlCls.divStr + "dl_alignerrormap' style='background-color:white' class='" + dialogClass + "'>";
48653
+
48654
+ //html += me.htmlCls.divNowrapStr + "Hold Ctrl key to select multiple nodes." + me.htmlCls.space3 + "</div>";
48655
+
48656
+ me.alignerrormapid = me.pre + 'alignerrormap';
48657
+ html += me.htmlCls.divNowrapStr + buttonStrTmp + me.alignerrormapid + '_svg">SVG</button>' + me.htmlCls.space2;
48658
+ html += buttonStrTmp + me.alignerrormapid + '_png">PNG (slow)</button>' + me.htmlCls.space2;
48659
+ html += buttonStrTmp + me.alignerrormapid + '_json">JSON</button>' + me.htmlCls.space4;
48660
+ html += '<b>Scale</b>: <select id="' + me.alignerrormapid + '_scale">';
48661
+
48662
+ //let optArray5 = ['0.01', '0.02', '0.04', '0.06', '0.08', '0.1', '0.2', '0.4', '0.6', '0.8', '1'];
48663
+ html += me.htmlCls.setHtmlCls.getOptionHtml(optArray5, 2);
48664
+
48665
+ html += "</select></div><br>";
48666
+
48667
+ //min: 004d00, max: FFFFFF
48668
+ let startColorStr = '#004d00';
48669
+ let endColorStr = '#FFFFFF';
48670
+ let rangeStr = startColorStr + ' 0%, ' + endColorStr + ' 100%';
48671
+
48672
+ html += "<div style='width:200px'><div style='height: 12px; border: 1px solid #000; background: linear-gradient(to right, " + rangeStr + ");'></div>";
48673
+ 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>";
48674
+
48675
+ html += '<div id="' + me.pre + 'alignerrormapDiv"></div>';
48676
+
48677
+ html += "</div>";
48678
+
48271
48679
  html += me.htmlCls.divStr + "dl_elecmap2fofc' class='" + dialogClass + "'>";
48272
48680
  html += "<span style='white-space:nowrap;font-weight:bold;'>Contour at: <select id='" + me.pre + "sigma2fofc'>";
48273
48681
 
@@ -48323,23 +48731,28 @@ class SetDialog {
48323
48731
  html += me.htmlCls.divStr + "dl_addlabel' class='" + dialogClass + "'>";
48324
48732
  html += "1. Text: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labeltext' value='Text' size=4><br/>";
48325
48733
  html += "2. Size: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labelsize' value='18' size=4 maxlength=2><br/>";
48326
- //html += "3. Color: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labelcolor' value='" + defaultColor + "' size=4><br/>";
48734
+ html += "3. Color: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labelcolor' value='" + defaultColor + "' size=4><br/>";
48327
48735
  //html += "4. Background: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labelbkgd' value='' size=4><br/>";
48328
48736
  if(me.utilsCls.isMobile()) {
48329
- html += me.htmlCls.spanNowrapStr + "3. Touch TWO atoms</span><br/>";
48737
+ html += me.htmlCls.spanNowrapStr + "4. Touch TWO atoms</span><br/>";
48330
48738
  }
48331
48739
  else {
48332
- html += me.htmlCls.spanNowrapStr + "3. Pick TWO atoms while holding \"Alt\" key</span><br/>";
48740
+ html += me.htmlCls.spanNowrapStr + "4. Pick TWO atoms while holding \"Alt\" key</span><br/>";
48333
48741
  }
48334
- html += me.htmlCls.spanNowrapStr + "4. " + me.htmlCls.buttonStr + "applypick_labels'>Display</button></span>";
48742
+ html += me.htmlCls.spanNowrapStr + "5. " + me.htmlCls.buttonStr + "applypick_labels'>Display</button></span>";
48335
48743
  html += "</div>";
48336
48744
 
48337
48745
  html += me.htmlCls.divStr + "dl_addlabelselection' class='" + dialogClass + "'>";
48338
48746
  html += "1. Text: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labeltext2' value='Text' size=4><br/>";
48339
48747
  html += "2. Size: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labelsize2' value='18' size=4 maxlength=2><br/>";
48340
- //html += "3. Color: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labelcolor2' value='" + defaultColor + "' size=4><br/>";
48748
+ html += "3. Color: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labelcolor2' value='" + defaultColor + "' size=4><br/>";
48341
48749
  //html += "4. Background: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labelbkgd2' value='' size=4><br/>";
48342
- html += me.htmlCls.spanNowrapStr + "3. " + me.htmlCls.buttonStr + "applyselection_labels'>Display</button></span>";
48750
+ html += me.htmlCls.spanNowrapStr + "4. " + me.htmlCls.buttonStr + "applyselection_labels'>Display</button></span>";
48751
+ html += "</div>";
48752
+
48753
+ html += me.htmlCls.divStr + "dl_labelColor' class='" + dialogClass + "'>";
48754
+ html += "Color for all labels: " + me.htmlCls.inputTextStr + "id='" + me.pre + "labelcolorall' value='" + defaultColor + "' size=4><br/><br/>";
48755
+ html += me.htmlCls.spanNowrapStr + me.htmlCls.buttonStr + "applylabelcolor'>Display</button></span>";
48343
48756
  html += "</div>";
48344
48757
 
48345
48758
  html += me.htmlCls.divStr + "dl_distance' class='" + dialogClass + "'>";
@@ -48997,6 +49410,25 @@ class Events {
48997
49410
  window.open(hostUrl + '?afid=' + $("#" + me.pre + "afid").val(), '_blank');
48998
49411
  });
48999
49412
 
49413
+ me.myEventCls.onIds("#" + me.pre + "reload_afmap", "click", function(e) { let ic = me.icn3d;
49414
+ e.preventDefault();
49415
+ if(!me.cfg.notebook) dialog.dialog( "close" );
49416
+ let afid = me.cfg.afid ? me.cfg.afid : $("#" + me.pre + "afid").val();
49417
+
49418
+ me.htmlCls.clickMenuCls.setLogCmd("set half pae map " + afid, true);
49419
+
49420
+ ic.contactMapCls.afErrorMap(afid);
49421
+ });
49422
+ me.myEventCls.onIds("#" + me.pre + "reload_afmapfull", "click", function(e) { let ic = me.icn3d;
49423
+ e.preventDefault();
49424
+ if(!me.cfg.notebook) dialog.dialog( "close" );
49425
+ let afid = me.cfg.afid ? me.cfg.afid : $("#" + me.pre + "afid").val();
49426
+
49427
+ me.htmlCls.clickMenuCls.setLogCmd("set full pae map " + afid, true);
49428
+
49429
+ ic.contactMapCls.afErrorMap(afid, true);
49430
+ });
49431
+
49000
49432
  me.myEventCls.onIds("#" + me.pre + "afid", "keyup", function(e) { me.icn3d;
49001
49433
  if (e.keyCode === 13) {
49002
49434
  e.preventDefault();
@@ -49030,23 +49462,23 @@ class Events {
49030
49462
  // },
49031
49463
  // clickReload_align_refined: function() {
49032
49464
  me.myEventCls.onIds("#" + me.pre + "reload_align_refined", "click", function(e) { me.icn3d;
49033
- e.preventDefault();
49034
- if(!me.cfg.notebook) dialog.dialog( "close" );
49035
- let alignment = $("#" + me.pre + "alignid1").val() + "," + $("#" + me.pre + "alignid2").val();
49036
- me.htmlCls.clickMenuCls.setLogCmd("load alignment " + alignment + ' | parameters &atype=1', false);
49037
- //window.open(me.htmlCls.baseUrl + 'icn3d/full.html?align=' + alignment + '&showalignseq=1&atype=1', '_blank');
49038
- window.open(hostUrl + '?align=' + alignment + '&showalignseq=1&atype=1', '_blank');
49039
- });
49465
+ e.preventDefault();
49466
+ if(!me.cfg.notebook) dialog.dialog( "close" );
49467
+ let alignment = $("#" + me.pre + "alignid1").val() + "," + $("#" + me.pre + "alignid2").val();
49468
+ me.htmlCls.clickMenuCls.setLogCmd("load alignment " + alignment + ' | parameters &atype=1&bu=1', false);
49469
+ //window.open(me.htmlCls.baseUrl + 'icn3d/full.html?align=' + alignment + '&showalignseq=1&atype=1', '_blank');
49470
+ window.open(hostUrl + '?align=' + alignment + '&showalignseq=1&atype=1&bu=1', '_blank');
49471
+ });
49040
49472
  // },
49041
49473
  // clickReload_align_ori: function() {
49042
49474
  me.myEventCls.onIds("#" + me.pre + "reload_align_ori", "click", function(e) { me.icn3d;
49043
- e.preventDefault();
49044
- if(!me.cfg.notebook) dialog.dialog( "close" );
49045
- let alignment = $("#" + me.pre + "alignid1").val() + "," + $("#" + me.pre + "alignid2").val();
49046
- me.htmlCls.clickMenuCls.setLogCmd("load alignment " + alignment + ' | parameters &atype=0', false);
49047
- //window.open( me.htmlCls.baseUrl + 'icn3d/full.html?align=' + alignment + '&showalignseq=1&atype=0', '_blank');
49048
- window.open(hostUrl + '?align=' + alignment + '&showalignseq=1&atype=0', '_blank');
49049
- });
49475
+ e.preventDefault();
49476
+ if(!me.cfg.notebook) dialog.dialog( "close" );
49477
+ let alignment = $("#" + me.pre + "alignid1").val() + "," + $("#" + me.pre + "alignid2").val();
49478
+ me.htmlCls.clickMenuCls.setLogCmd("load alignment " + alignment + ' | parameters &atype=0&bu=1', false);
49479
+ //window.open( me.htmlCls.baseUrl + 'icn3d/full.html?align=' + alignment + '&showalignseq=1&atype=0', '_blank');
49480
+ window.open(hostUrl + '?align=' + alignment + '&showalignseq=1&atype=0&bu=1', '_blank');
49481
+ });
49050
49482
  // },
49051
49483
  // clickReload_chainalign: function() {
49052
49484
  me.myEventCls.onIds("#" + me.pre + "reload_chainalign", "click", function(e) { me.icn3d;
@@ -49080,8 +49512,8 @@ class Events {
49080
49512
  }
49081
49513
 
49082
49514
  me.htmlCls.clickMenuCls.setLogCmd("load chains " + alignment + " on asymmetric unit | residues " + resalign + " | resdef " + predefinedres, false);
49083
- //window.open(me.htmlCls.baseUrl + 'icn3d/full.html?chainalign=' + alignment + '&resnum=' + resalign + '&resdef=' + predefinedres + '&showalignseq=1&buidx=0', '_blank');
49084
- window.open(hostUrl + '?chainalign=' + alignment + '&resnum=' + resalign + '&resdef=' + predefinedres + '&showalignseq=1&buidx=0', '_blank');
49515
+ //window.open(me.htmlCls.baseUrl + 'icn3d/full.html?chainalign=' + alignment + '&resnum=' + resalign + '&resdef=' + predefinedres + '&showalignseq=1&bu=0', '_blank');
49516
+ window.open(hostUrl + '?chainalign=' + alignment + '&resnum=' + resalign + '&resdef=' + predefinedres + '&showalignseq=1&bu=0', '_blank');
49085
49517
  });
49086
49518
 
49087
49519
  me.myEventCls.onIds("#" + me.pre + "reload_mutation_3d", "click", function(e) { me.icn3d;
@@ -49156,21 +49588,25 @@ class Events {
49156
49588
  // clickReload_mmdb: function() {
49157
49589
  me.myEventCls.onIds("#" + me.pre + "reload_mmdb", "click", function(e) { me.icn3d;
49158
49590
  e.preventDefault();
49159
- if(!me.cfg.notebook) dialog.dialog( "close" );
49160
- me.htmlCls.clickMenuCls.setLogCmd("load mmdb " + $("#" + me.pre + "mmdbid").val(), false);
49161
- //ic.mmdbParserCls.downloadMmdb($("#" + me.pre + "mmdbid").val());
49162
- //window.open(me.htmlCls.baseUrl + 'icn3d/full.html?mmdbid=' + $("#" + me.pre + "mmdbid").val(), '_blank');
49163
- window.open(hostUrl + '?mmdbid=' + $("#" + me.pre + "mmdbid").val(), '_blank');
49591
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
49592
+ me.htmlCls.clickMenuCls.setLogCmd("load mmdb1 " + $("#" + me.pre + "mmdbid").val(), false);
49593
+ window.open(hostUrl + '?mmdbid=' + $("#" + me.pre + "mmdbid").val() + '&bu=1', '_blank');
49164
49594
  });
49165
49595
 
49596
+ me.myEventCls.onIds("#" + me.pre + "reload_mmdb_asym", "click", function(e) { me.icn3d;
49597
+ e.preventDefault();
49598
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
49599
+ me.htmlCls.clickMenuCls.setLogCmd("load mmdb0 " + $("#" + me.pre + "mmdbid").val(), false);
49600
+ window.open(hostUrl + '?mmdbid=' + $("#" + me.pre + "mmdbid").val() + '&bu=0', '_blank');
49601
+ });
49602
+
49166
49603
  me.myEventCls.onIds("#" + me.pre + "mmdbid", "keyup", function(e) { me.icn3d;
49167
49604
  if (e.keyCode === 13) {
49168
49605
  e.preventDefault();
49169
- if(!me.cfg.notebook) dialog.dialog( "close" );
49170
- me.htmlCls.clickMenuCls.setLogCmd("load mmdb " + $("#" + me.pre + "mmdbid").val(), false);
49171
- //window.open(me.htmlCls.baseUrl + 'icn3d/full.html?mmdbid=' + $("#" + me.pre + "mmdbid").val(), '_blank');
49172
- window.open(hostUrl + '?mmdbid=' + $("#" + me.pre + "mmdbid").val(), '_blank');
49173
- }
49606
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
49607
+ me.htmlCls.clickMenuCls.setLogCmd("load mmdb0 " + $("#" + me.pre + "mmdbid").val(), false);
49608
+ window.open(hostUrl + '?mmdbid=' + $("#" + me.pre + "mmdbid").val() + '&bu=0', '_blank');
49609
+ }
49174
49610
  });
49175
49611
 
49176
49612
  // },
@@ -49555,6 +49991,64 @@ class Events {
49555
49991
  reader.readAsText(file);
49556
49992
  }
49557
49993
  });
49994
+
49995
+ me.myEventCls.onIds("#" + me.pre + "reload_afmapfile", "click", function(e) { let ic = me.icn3d;
49996
+ e.preventDefault();
49997
+ ic.bInitial = true;
49998
+ if(!me.cfg.notebook) dialog.dialog( "close" );
49999
+ //close all dialog
50000
+ if(!me.cfg.notebook) {
50001
+ $(".ui-dialog-content").dialog("close");
50002
+ }
50003
+ else {
50004
+ ic.resizeCanvasCls.closeDialogs();
50005
+ }
50006
+ let file = $("#" + me.pre + "afmapfile")[0].files[0];
50007
+ if(!file) {
50008
+ var aaa = 1; //alert("Please select a file before clicking 'Load'");
50009
+ }
50010
+ else {
50011
+ me.htmlCls.setHtmlCls.fileSupport();
50012
+ let reader = new FileReader();
50013
+ reader.onload = function(e) {
50014
+ let dataStr = e.target.result; // or = reader.result;
50015
+ me.htmlCls.clickMenuCls.setLogCmd('load AlphaFold PAE file ' + $("#" + me.pre + "afmapfile").val(), false);
50016
+
50017
+ me.htmlCls.dialogCls.openDlg('dl_alignerrormap', 'Show Predicted Aligned Error (PAE) map');
50018
+ ic.contactMapCls.processAfErrorMap(JSON.parse(dataStr));
50019
+ };
50020
+ reader.readAsText(file);
50021
+ }
50022
+ });
50023
+
50024
+ me.myEventCls.onIds("#" + me.pre + "reload_afmapfilefull", "click", function(e) { let ic = me.icn3d;
50025
+ e.preventDefault();
50026
+ ic.bInitial = true;
50027
+ if(!me.cfg.notebook) dialog.dialog( "close" );
50028
+ //close all dialog
50029
+ if(!me.cfg.notebook) {
50030
+ $(".ui-dialog-content").dialog("close");
50031
+ }
50032
+ else {
50033
+ ic.resizeCanvasCls.closeDialogs();
50034
+ }
50035
+ let file = $("#" + me.pre + "afmapfile")[0].files[0];
50036
+ if(!file) {
50037
+ var aaa = 1; //alert("Please select a file before clicking 'Load'");
50038
+ }
50039
+ else {
50040
+ me.htmlCls.setHtmlCls.fileSupport();
50041
+ let reader = new FileReader();
50042
+ reader.onload = function(e) {
50043
+ let dataStr = e.target.result; // or = reader.result;
50044
+ me.htmlCls.clickMenuCls.setLogCmd('load AlphaFold PAE file ' + $("#" + me.pre + "afmapfile").val(), false);
50045
+
50046
+ me.htmlCls.dialogCls.openDlg('dl_alignerrormap', 'Show Predicted Aligned Error (PAE) map');
50047
+ ic.contactMapCls.processAfErrorMap(JSON.parse(dataStr), true);
50048
+ };
50049
+ reader.readAsText(file);
50050
+ }
50051
+ });
49558
50052
  // },
49559
50053
  // clickReload_urlfile: function() {
49560
50054
  me.myEventCls.onIds("#" + me.pre + "reload_urlfile", "click", function(e) { let ic = me.icn3d;
@@ -49807,9 +50301,7 @@ class Events {
49807
50301
  me.myEventCls.onIds("#" + me.svgid + "_png", "click", function(e) { let ic = me.icn3d;
49808
50302
  e.preventDefault();
49809
50303
  //if(!me.cfg.notebook) dialog.dialog( "close" );
49810
- let width = $("#" + me.pre + "dl_graph").width();
49811
- let height = $("#" + me.pre + "dl_graph").height();
49812
- ic.saveFileCls.savePng(me.svgid, ic.inputid + "_force_directed_graph.png", width, height);
50304
+ ic.saveFileCls.savePng(me.svgid, ic.inputid + "_force_directed_graph.png");
49813
50305
  });
49814
50306
  me.myEventCls.onIds("#" + me.svgid + "_json", "click", function(e) { let ic = me.icn3d;
49815
50307
  e.preventDefault();
@@ -49828,9 +50320,7 @@ class Events {
49828
50320
  $(document).on("click", "#" + me.svgid_ct + "_png", function(e) { let ic = me.icn3d;
49829
50321
  e.preventDefault();
49830
50322
  //if(!me.cfg.notebook) dialog.dialog( "close" );
49831
- let width = $("#" + me.pre + "dl_2dctn").width();
49832
- let height = $("#" + me.pre + "dl_2dctn").height();
49833
- ic.saveFileCls.savePng(me.svgid_ct, ic.inputid + "_cartoon.png", width, height);
50323
+ ic.saveFileCls.savePng(me.svgid_ct, ic.inputid + "_cartoon.png");
49834
50324
  });
49835
50325
  $(document).on("click", "#" + me.svgid_ct + "_json", function(e) { let ic = me.icn3d;
49836
50326
  e.preventDefault();
@@ -49856,9 +50346,7 @@ class Events {
49856
50346
  me.myEventCls.onIds("#" + me.linegraphid + "_png", "click", function(e) { let ic = me.icn3d;
49857
50347
  e.preventDefault();
49858
50348
  //if(!me.cfg.notebook) dialog.dialog( "close" );
49859
- let width = $("#" + me.pre + "dl_linegraph").width();
49860
- let height = $("#" + me.pre + "dl_linegraph").height();
49861
- ic.saveFileCls.savePng(me.linegraphid, ic.inputid + "_line_graph.png", width, height);
50349
+ ic.saveFileCls.savePng(me.linegraphid, ic.inputid + "_line_graph.png");
49862
50350
  });
49863
50351
  me.myEventCls.onIds("#" + me.linegraphid + "_json", "click", function(e) { let ic = me.icn3d;
49864
50352
  e.preventDefault();
@@ -49884,9 +50372,7 @@ class Events {
49884
50372
  me.myEventCls.onIds("#" + me.scatterplotid + "_png", "click", function(e) { let ic = me.icn3d;
49885
50373
  e.preventDefault();
49886
50374
  //if(!me.cfg.notebook) dialog.dialog( "close" );
49887
- let width = $("#" + me.pre + "dl_scatterplot").width();
49888
- let height = $("#" + me.pre + "dl_scatterplot").height();
49889
- ic.saveFileCls.savePng(me.scatterplotid, ic.inputid + "_scatterplot.png", width, height);
50375
+ ic.saveFileCls.savePng(me.scatterplotid, ic.inputid + "_scatterplot.png");
49890
50376
  });
49891
50377
  me.myEventCls.onIds("#" + me.scatterplotid + "_json", "click", function(e) { let ic = me.icn3d;
49892
50378
  e.preventDefault();
@@ -49908,14 +50394,12 @@ class Events {
49908
50394
  me.myEventCls.onIds("#" + me.contactmapid + "_svg", "click", function(e) { let ic = me.icn3d;
49909
50395
  e.preventDefault();
49910
50396
  //if(!me.cfg.notebook) dialog.dialog( "close" );
49911
- ic.saveFileCls.saveSvg(me.contactmapid, ic.inputid + "_contactmap.svg");
50397
+ ic.saveFileCls.saveSvg(me.contactmapid, ic.inputid + "_contactmap.svg", true);
49912
50398
  });
49913
50399
  me.myEventCls.onIds("#" + me.contactmapid + "_png", "click", function(e) { let ic = me.icn3d;
49914
50400
  e.preventDefault();
49915
50401
  //if(!me.cfg.notebook) dialog.dialog( "close" );
49916
- let width = $("#" + me.pre + "dl_contactmap").width();
49917
- let height = $("#" + me.pre + "dl_contactmap").height();
49918
- ic.saveFileCls.savePng(me.contactmapid, ic.inputid + "_contactmap.png", width, height);
50402
+ ic.saveFileCls.savePng(me.contactmapid, ic.inputid + "_contactmap.png", true);
49919
50403
  });
49920
50404
  me.myEventCls.onIds("#" + me.contactmapid + "_json", "click", function(e) { let ic = me.icn3d;
49921
50405
  e.preventDefault();
@@ -49927,11 +50411,47 @@ class Events {
49927
50411
  ic.saveFileCls.saveFile(ic.inputid + "_contactmap.json", "text", [graphStr2]);
49928
50412
  });
49929
50413
  me.myEventCls.onIds("#" + me.contactmapid + "_scale", "change", function(e) { let ic = me.icn3d;
50414
+ e.preventDefault();
50415
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
50416
+ let scale = $("#" + me.contactmapid + "_scale").val();
50417
+ $("#" + me.contactmapid).attr("width",(ic.contactmapWidth * parseFloat(scale)).toString() + "px");
50418
+ me.htmlCls.clickMenuCls.setLogCmd("contactmap scale " + scale, true);
50419
+ });
50420
+
50421
+ me.myEventCls.onIds("#" + me.alignerrormapid + "_svg", "click", function(e) { let ic = me.icn3d;
50422
+ e.preventDefault();
50423
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
50424
+ ic.saveFileCls.saveSvg(me.alignerrormapid, ic.inputid + "_alignerrormap.svg", true);
50425
+ });
50426
+ me.myEventCls.onIds("#" + me.alignerrormapid + "_png", "click", function(e) { let ic = me.icn3d;
50427
+ e.preventDefault();
50428
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
50429
+ ic.saveFileCls.savePng(me.alignerrormapid, ic.inputid + "_alignerrormap.png", true);
50430
+ });
50431
+ me.myEventCls.onIds("#" + me.alignerrormapid + "_full", "click", function(e) { let ic = me.icn3d;
50432
+ e.preventDefault();
50433
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
50434
+ ic.contactMapCls.afErrorMap(afid, true);
50435
+
50436
+
50437
+ });
50438
+ me.myEventCls.onIds("#" + me.alignerrormapid + "_json", "click", function(e) { let ic = me.icn3d;
50439
+ e.preventDefault();
50440
+
50441
+ //if(!me.cfg.notebook) dialog.dialog( "close" );
50442
+ let graphStr2 = ic.alignerrormapStr.substr(0, ic.alignerrormapStr.lastIndexOf('}'));
50443
+
50444
+ graphStr2 += me.htmlCls.setHtmlCls.getLinkColor();
50445
+
50446
+ ic.saveFileCls.saveFile(ic.inputid + "_alignerrormap.json", "text", [graphStr2]);
50447
+ });
50448
+
50449
+ me.myEventCls.onIds("#" + me.alignerrormapid + "_scale", "change", function(e) { let ic = me.icn3d;
49930
50450
  e.preventDefault();
49931
50451
  //if(!me.cfg.notebook) dialog.dialog( "close" );
49932
- let scale = $("#" + me.contactmapid + "_scale").val();
49933
- $("#" + me.contactmapid).attr("width",(ic.contactmapWidth * parseFloat(scale)).toString() + "px");
49934
- me.htmlCls.clickMenuCls.setLogCmd("contactmap scale " + scale, true);
50452
+ let scale = $("#" + me.alignerrormapid + "_scale").val();
50453
+ $("#" + me.alignerrormapid).attr("width",(ic.alignerrormapWidth * parseFloat(scale)).toString() + "px");
50454
+ me.htmlCls.clickMenuCls.setLogCmd("alignerrormap scale " + scale, true);
49935
50455
  });
49936
50456
 
49937
50457
  me.myEventCls.onIds("#" + me.svgid + "_label", "change", function(e) { me.icn3d;
@@ -50031,6 +50551,15 @@ class Events {
50031
50551
  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);
50032
50552
  ic.drawCls.draw();
50033
50553
  });
50554
+
50555
+ me.myEventCls.onIds("#" + me.pre + "applylabelcolor", "click", function(e) { let ic = me.icn3d;
50556
+ e.preventDefault();
50557
+ if(!me.cfg.notebook) dialog.dialog( "close" );
50558
+ ic.labelcolor = $("#" + me.pre + "labelcolorall" ).val();
50559
+
50560
+ me.htmlCls.clickMenuCls.setLogCmd('set label color ' + ic.labelcolor, true);
50561
+ ic.drawCls.draw();
50562
+ });
50034
50563
  // },
50035
50564
  // clickApplypick_stabilizer: function() {
50036
50565
  me.myEventCls.onIds("#" + me.pre + "applypick_stabilizer", "click", function(e) { let ic = me.icn3d;
@@ -52339,7 +52868,142 @@ class ContactMap {
52339
52868
  }
52340
52869
  }
52341
52870
 
52342
- drawContactMap(lineGraphStr) { let ic = this.icn3d, me = ic.icn3dui;
52871
+ afErrorMap(afid, bFull) { let ic = this.icn3d, me = ic.icn3dui;
52872
+ let thisClass = this;
52873
+
52874
+ me.htmlCls.dialogCls.openDlg('dl_alignerrormap', 'Show Predicted Aligned Error (PAE) map');
52875
+
52876
+ let url, dataType;
52877
+
52878
+ url = "https://alphafold.ebi.ac.uk/files/AF-" + afid + "-F1-predicted_aligned_error_v2.json";
52879
+
52880
+ dataType = "json";
52881
+
52882
+ $.ajax({
52883
+ url: url,
52884
+ dataType: dataType,
52885
+ cache: true,
52886
+ tryCount : 0,
52887
+ retryLimit : 1,
52888
+ success: function(data) {
52889
+ thisClass.processAfErrorMap(data, bFull);
52890
+ },
52891
+ error : function(xhr, textStatus, errorThrown ) {
52892
+ this.tryCount++;
52893
+ if(this.tryCount <= this.retryLimit) {
52894
+ //try again
52895
+ $.ajax(this);
52896
+ return;
52897
+ }
52898
+ var aaa = 1; //alert("There are some problems in loading the PAE file...");
52899
+ return;
52900
+ }
52901
+ });
52902
+ }
52903
+
52904
+ processAfErrorMap(dataJson, bFull) { let ic = this.icn3d, me = ic.icn3dui;
52905
+ // json format: [{"residue1": [1, ..., 1, ..., n, ..., n], "residue2": [1, 2, ..., n, ..., 1, 2, ..., n],
52906
+ // "distance": [n*n matrix],"max_predicted_aligned_error":31.75}]
52907
+ let distMatrix = dataJson[0].distance;
52908
+ let max = dataJson[0].max_predicted_aligned_error;
52909
+ if(!distMatrix || !max) {
52910
+ var aaa = 1; //alert("The PAE file didn't have the right format...");
52911
+ return;
52912
+ }
52913
+
52914
+ // generate lineGraphStr
52915
+ // e.g., {"nodes": [{"id":"A1.A","r":"1_1_1TOP_A_1","s":"ab","x":1,"y":21,"c":"FF00FF"}, ...],
52916
+ // "links": [{"source": "A1.A", "target": "S2.A", "v": 3, "c": "FF00FF"}, ...]}
52917
+ let nodeStr = '"nodes": [', linkStr = '"links": [';
52918
+ let bNode = false, bLink = false;
52919
+ let postA = '', postB = '.';
52920
+
52921
+ // initialize some parameters if no structure wasloaded yet
52922
+ let bStruData;
52923
+ if(!ic.chains || Object.keys(ic.chains).length == 0) {
52924
+ bStruData = false;
52925
+ ic.init_base();
52926
+ }
52927
+ else {
52928
+ bStruData = true;
52929
+ }
52930
+
52931
+ //let chainidArray = Object.keys(ic.chains);
52932
+ //let chainid = (chainidArray.length == 1) ? chainidArray[0] : 'stru_A';
52933
+
52934
+ let dim = parseInt(Math.sqrt(distMatrix.length));
52935
+
52936
+ // map index with residue number when the structure has multiple chains
52937
+ let index = 0;
52938
+ let index2resObj = {};
52939
+ for(let chainid in ic.chains) {
52940
+ for(let j = 0, jl = ic.chainsSeq[chainid].length; j < jl; ++j) {
52941
+ index2resObj[index] = ic.chainsSeq[chainid][j];
52942
+ index2resObj[index].chainid = chainid;
52943
+ ++index;
52944
+ }
52945
+ }
52946
+
52947
+ //for(let chainid in ic.chains) {
52948
+ //for(let i = 0, il = ic.chainsSeq[chainid].length; i < il; ++i) {
52949
+ index = 0;
52950
+ for(let i = 0; i < dim; ++i) {
52951
+ let resi = (bStruData) ? index2resObj[i].resi : i + 1;
52952
+ let resn = (bStruData) ? index2resObj[i].name : '*';
52953
+ let chainid = (bStruData) ? index2resObj[i].chainid : 'stru_A';
52954
+
52955
+ let resid = chainid + '_' + resi;
52956
+ let atom = (ic.residues[resid]) ? ic.firstAtomObjCls.getFirstAtomObj(ic.residues[resid])
52957
+ : {color: me.parasCls.thr(0x888888)};
52958
+ let chain = chainid.substr(chainid.indexOf('_') + 1);
52959
+ let color = atom.color.getHexString();
52960
+
52961
+ if(bNode) nodeStr += ', ';
52962
+ let idStr = resn + resi + '.' + chain;
52963
+ nodeStr += '{"id":"' + idStr + postA + '","r":"1_1_' + resid + '","s":"a","c":"' + color + '"}\n';
52964
+ nodeStr += ', {"id":"' + idStr + postB + '","r":"1_1_' + resid + '","s":"b","c":"' + color + '"}';
52965
+ bNode = true;
52966
+
52967
+ let start = (bFull) ? 0 : i; // full map, or half map
52968
+
52969
+ //for(let j = 0, jl = ic.chainsSeq[chainid].length; j < jl; ++j) {
52970
+ //for(let j = 0; j < dim; ++j) {
52971
+ for(let j = start; j < dim; ++j) {
52972
+ index = i * dim + j;
52973
+ let resi2 = (bStruData) ? index2resObj[j].resi : j + 1;
52974
+ let resn2 = (bStruData) ? index2resObj[j].name : '*';
52975
+ let chainid2 = (bStruData) ? index2resObj[j].chainid : 'stru_A';
52976
+ let chain2 = chainid2.substr(chainid2.indexOf('_') + 1);
52977
+
52978
+ let idStr2 = resn2 + resi2 + '.' + chain2;
52979
+
52980
+ // max dark green color 004d00, 0x4d = 77, 77/255 = 0.302
52981
+ // 0: 004d00, max: FFFFFF
52982
+ let ratio = (distMatrix[index]) ? distMatrix[index] / max : 0;
52983
+ let r = parseInt(ratio*255).toString(16);
52984
+ let g = parseInt(((1.0 - 0.302)*ratio + 0.302) * 255).toString(16);
52985
+ let rHex = (r.length == 1) ? '0' + r : r;
52986
+ let gHex = (g.length == 1) ? '0' + g : g;
52987
+ let bHex = rHex;
52988
+ let color2 = rHex + gHex + bHex;
52989
+
52990
+ if(bLink) linkStr += ', ';
52991
+ linkStr += '{"source": "' + idStr + postA + '", "target": "' + idStr2 + postB + '", "v": 11, "c": "' + color2 + '"}\n';
52992
+ bLink = true;
52993
+ }
52994
+ }
52995
+ //}
52996
+
52997
+ dataJson = {};
52998
+
52999
+ let lineGraphStr = '{' + nodeStr + '], ' + linkStr + ']}';
53000
+ let bAfMap = true;
53001
+ this.drawContactMap(lineGraphStr, bAfMap, max);
53002
+
53003
+ if(ic.deferredAfmap !== undefined) ic.deferredAfmap.resolve();
53004
+ }
53005
+
53006
+ drawContactMap(lineGraphStr, bAfMap, max) { let ic = this.icn3d, me = ic.icn3dui;
52343
53007
  let html, graph = JSON.parse(lineGraphStr);
52344
53008
  let linkArray = graph.links;
52345
53009
 
@@ -52373,7 +53037,7 @@ class ContactMap {
52373
53037
 
52374
53038
  let graphStr = '{\n';
52375
53039
 
52376
- let struc1 = Object.keys(ic.structures)[0];
53040
+ let struc1 = (ic.structures.length > 0) ? ic.structures[0] : 'stru';
52377
53041
  let len1 = nodeArray1.length,
52378
53042
  len2 = nodeArray2.length;
52379
53043
  let factor = 1;
@@ -52387,20 +53051,76 @@ class ContactMap {
52387
53051
  width =(len2 + 2) *(r + gap) + 2 * marginX + legendWidth;
52388
53052
 
52389
53053
  let id, graphWidth;
52390
- ic.contactmapWidth = 2 * width;
52391
- graphWidth = ic.contactmapWidth;
52392
- id = me.contactmapid;
53054
+ if(bAfMap) {
53055
+ ic.alignerrormapWidth = 2 * width;
53056
+ graphWidth = ic.alignerrormapWidth;
53057
+ id = me.alignerrormapid;
53058
+ }
53059
+ else {
53060
+ ic.contactmapWidth = 2 * width;
53061
+ graphWidth = ic.contactmapWidth;
53062
+ id = me.contactmapid;
53063
+ }
53064
+
52393
53065
  html =(linkArray.length > 0) ? "" : "No interactions found for these two sets<br><br>";
52394
- html += "<svg id='" + id + "' viewBox='0,0," + width + "," + heightAll + "' width='" + graphWidth + "px'>";
53066
+ html += "<svg xmlns='http://www.w3.org/2000/svg' id='" + id + "' viewBox='0,0," + width + "," + heightAll + "' width='" + graphWidth + "px'>";
52395
53067
  let bContactMap = true;
52396
- html += ic.lineGraphCls.drawScatterplot_base(nodeArray1, nodeArray2, linkArray, name2node, 0, bContactMap);
53068
+
53069
+ if(bAfMap) { // cleaned the code by using "use" in SVG, but didn't improve rendering
53070
+ let factor = 1;
53071
+ let r = 3 * factor;
53072
+ let rectSize = 2 * r;
53073
+
53074
+ ic.hex2id = {};
53075
+ let threshold = 29.0 / max;
53076
+ ic.hex2skip = {}; // do not display any error larger than 29 angstrom
53077
+
53078
+ html += "<defs>";
53079
+
53080
+ let linestrokewidth = 1;
53081
+ let nRef = 1000;
53082
+ for(let i = 0; i < nRef; ++i) {
53083
+ let ratio = 1.0 * i / nRef;
53084
+ let r = parseInt(ratio*255).toString(16);
53085
+ let g = parseInt(((1.0 - 0.302)*ratio + 0.302) * 255).toString(16);
53086
+ let rHex = (r.length == 1) ? '0' + r : r;
53087
+ let gHex = (g.length == 1) ? '0' + g : g;
53088
+ let bHex = rHex;
53089
+ let color = rHex + gHex + bHex;
53090
+ let strokecolor = "#" + color;
53091
+
53092
+ let idRect = me.pre + "afmap_" + i;
53093
+
53094
+ ic.hex2id[color] = idRect;
53095
+ if(ratio > threshold) {
53096
+ ic.hex2skip[color] = idRect;
53097
+ }
53098
+
53099
+ //html += "<g id='" + id + "'>";
53100
+ html += "<rect id='" + idRect + "' x='0' y='0' width='" + rectSize + "' height='" + rectSize + "' fill='"
53101
+ + strokecolor + "' stroke-width='" + linestrokewidth + "' stroke='" + strokecolor + "' />";
53102
+ //html += "</g>"
53103
+ }
53104
+ html += "</defs>";
53105
+ }
53106
+
53107
+ html += ic.lineGraphCls.drawScatterplot_base(nodeArray1, nodeArray2, linkArray, name2node, 0, bContactMap, undefined, undefined, bAfMap);
52397
53108
  graphStr += ic.getGraphCls.updateGraphJson(struc1, 1, nodeArray1, nodeArray2, linkArray);
52398
53109
  html += "</svg>";
52399
53110
 
52400
53111
  graphStr += '}\n';
52401
- ic.contactmapStr = graphStr;
53112
+ if(bAfMap) {
53113
+ ic.alignerrormapStr = graphStr;
53114
+ $("#" + ic.pre + "alignerrormapDiv").html(html);
53115
+
53116
+ let scale = $("#" + me.alignerrormapid + "_scale").val();
53117
+ $("#" + me.alignerrormapid).attr("width",(ic.alignerrormapWidth * parseFloat(scale)).toString() + "px");
53118
+ }
53119
+ else {
53120
+ ic.contactmapStr = graphStr;
53121
+ $("#" + ic.pre + "contactmapDiv").html(html);
53122
+ }
52402
53123
 
52403
- $("#" + ic.pre + "contactmapDiv").html(html);
52404
53124
  return html;
52405
53125
  }
52406
53126
  }
@@ -54428,6 +55148,7 @@ class iCn3D {
54428
55148
  this.bInstanced = true;
54429
55149
 
54430
55150
  this.chainMissingResidueArray = {};
55151
+ this._zoomFactor = 1.0;
54431
55152
 
54432
55153
  if(!this.icn3dui.bNode) {
54433
55154
  this.bExtFragDepth = this.renderer.extensions.get( "EXT_frag_depth" );
@@ -54779,7 +55500,7 @@ iCn3D.prototype.init = function (bKeepCmd) {
54779
55500
  //this.inputid = {"idtype": undefined, "id":undefined}; // support pdbid, mmdbid
54780
55501
 
54781
55502
  this.biomtMatrices = [];
54782
- this.bAssembly = true;
55503
+ this.bAssembly = false; //true;
54783
55504
 
54784
55505
  this.bDrawn = false;
54785
55506
  this.bSecondaryStructure = false;
@@ -54805,6 +55526,8 @@ iCn3D.prototype.init_base = function (bKeepCmd) {
54805
55526
  this.chainsAn = {}; // structure_chain name -> array of annotations, such as residue number
54806
55527
  this.chainsAnTitle = {}; // structure_chain name -> array of annotation title
54807
55528
 
55529
+ this.chainsMapping = {}; // structure_chain name -> residue id hash such as {'structure_chain_resi1': 'reference residue such as K10', ...}
55530
+
54808
55531
  this.alnChainsSeq = {}; // structure_chain name -> array of residue object: {mmdbid, chain, resi, resn, aligned}
54809
55532
  this.alnChainsAnno = {}; // structure_chain name -> array of annotations, such as residue number
54810
55533
  this.alnChainsAnTtl = {}; // structure_chain name -> array of annotation title
@@ -54915,7 +55638,7 @@ iCn3D.prototype.reinitAfterLoad = function () { let ic = this, me = ic.icn3dui;
54915
55638
  ic.lines = {}; // hash of name -> a list of solid or dashed lines. Each line contains 'position1', 'position2', 'color', and a boolean of 'dashed'
54916
55639
  // line name could be custom, hbond, ssbond, distance
54917
55640
 
54918
- ic.bAssembly = true;
55641
+ ic.bAssembly = false; //true;
54919
55642
  };
54920
55643
 
54921
55644
  iCn3D.prototype.resetConfig = function () { let ic = this, me = ic.icn3dui;
@@ -54954,7 +55677,7 @@ class iCn3DUI {
54954
55677
  //even when multiple iCn3D viewers are shown together.
54955
55678
  this.pre = this.cfg.divid + "_";
54956
55679
 
54957
- this.REVISION = '3.6.0';
55680
+ this.REVISION = '3.8.1';
54958
55681
 
54959
55682
  // In nodejs, iCn3D defines "window = {navigator: {}}"
54960
55683
  this.bNode = (Object.keys(window).length < 2) ? true : false;